diff --git a/Directory.Build.props b/Directory.Build.props index 3de84a18463..1c94b5e5e2a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -24,8 +24,9 @@ true opencover [System.Windows.*]* - - + + [Microsoft.DotNet.XUnitExtensions]*,[xunit*]* + Obsolete,ExcludeFromCodeCoverage @@ -39,4 +40,9 @@ true + + + $(MicrosoftNETCoreAppPackageVersion) + + diff --git a/Directory.Build.targets b/Directory.Build.targets index ebfe8c81517..e94b652da15 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -22,4 +22,18 @@ - \ No newline at end of file + + + + $(MicrosoftNETCoreAppPackageVersion) + + + + + + + + + + diff --git a/Documentation/building.md b/Documentation/building.md index 1b5e8212a1f..e9ca49a8252 100644 --- a/Documentation/building.md +++ b/Documentation/building.md @@ -40,6 +40,8 @@ Note that this does **not** build using your machine-wide installed version of t * Other error may be from MSBuild tasks. You need to examine the build logs to investigate. * The logs are generated at `artifacts\log\Debug\Build.binlog` * The file format is an MSBuild Binary Log. Install the [MSBuild Structured Log Viewer][msbuild-log-viewer] to view them. +* WinForms uses Visual Studio MSBuild but sometimes with a preview .NET Core SDK; so if you have a non-preview version of [Visual Studio][VS-download] (i.e. a release version), then you may need to enable `use preview` for .NET Core SDKs in VS. + * you can do this in VS at Tools :arrow_right: options :arrow_right: Projects and Solutions :arrow_right: .net core :arrow_right: use previews ## Creating a package @@ -49,4 +51,5 @@ To create the Microsoft.Private.Winforms package, run `.\build -pack` [corefx-windows-instructions]: https://github.com/dotnet/corefx/blob/master/Documentation/building/windows-instructions.md [latest-core-build]: https://github.com/dotnet/core/blob/master/daily-builds.md -[msbuild-log-viewer]: http://msbuildlog.com/ \ No newline at end of file +[msbuild-log-viewer]: http://msbuildlog.com/ +[VS-download]: https://visualstudio.microsoft.com/downloads/ diff --git a/Documentation/developer-guide.md b/Documentation/developer-guide.md index 77bc6b05948..03e23b3e38c 100644 --- a/Documentation/developer-guide.md +++ b/Documentation/developer-guide.md @@ -6,7 +6,7 @@ The [Issue Guide](issue-guide.md) describes our approach to using GitHub issues. ## Machine Setup -Follow the [Building CoreFX on Windows][corefx-windows-instructions] instructions. However, we recommend Visual Studio 2019 Preview 1. +Follow the [Building CoreFX on Windows][corefx-windows-instructions] instructions. In particular, [Visual Studio 2019 Preview][vs-preview] is required to develop on .NET Core. Windows Forms requires the following workloads and components be selected when installing Visual Studio: @@ -39,6 +39,7 @@ You first need to [Fork][fork] and [Clone][clone] this WinForms repository. This [comment]: <> (URI Links) [corefx-windows-instructions]: https://github.com/dotnet/corefx/blob/master/Documentation/building/windows-instructions.md +[vs-preview]: https://visualstudio.microsoft.com/vs/preview/ [fork]: https://github.com/dotnet/corefx/wiki/Checking-out-the-code-repository#fork-the-repository [clone]: https://github.com/dotnet/corefx/wiki/Checking-out-the-code-repository#clone-the-repository [git-commands]: https://github.com/dotnet/corefx/wiki/git-reference diff --git a/Documentation/getting-started.md b/Documentation/getting-started.md index 94d4a978b36..16140c1261b 100644 --- a/Documentation/getting-started.md +++ b/Documentation/getting-started.md @@ -6,7 +6,7 @@ This document describes the experience of using WinForms on .NET Core. The [Deve Choose one of these options: -1. [.NET Core 3.0 SDK Preview 1 (recommended)][.net-core-3.0-sdk-preview-1] +1. [.NET Core 3.0 SDK Preview 1 (recommended)][.net-core-3.0-sdk-preview] 1. [.NET Core 3.0 daily build (latest changes, but less stable)][.net-core-3.0-daily] @@ -34,6 +34,6 @@ To port your existing WinForms application from .NET Framework to .NET Core 3.0, [comment]: <> (URI Links) -[.net-core-3.0-sdk-preview-1]: https://www.microsoft.com/net/download +[.net-core-3.0-sdk-preview]: https://dotnet.microsoft.com/download/dotnet-core/3.0 [.net-core-3.0-daily]: https://github.com/dotnet/core/blob/master/daily-builds.md -[.net-core-3.0-samples]: https://github.com/dotnet/samples/tree/master/windowsforms \ No newline at end of file +[.net-core-3.0-samples]: https://github.com/dotnet/samples/tree/master/windowsforms diff --git a/Documentation/porting-guidelines.md b/Documentation/porting-guidelines.md index 55c9eabeb14..cbeafa15de3 100644 --- a/Documentation/porting-guidelines.md +++ b/Documentation/porting-guidelines.md @@ -85,6 +85,10 @@ For additional information and assistance, we recommend checking out [this artic ## Migration tips +### Include the System.Windows.Forms.Datavisualization Pack + +If you wish to use types previously associated with the [Charting control in the .NET Framework][framework-charting], you should add a package reference to the [NuGet package of Data Visualization][nuget-dataviz] ported to .NET Core. For more information about Data Visualization and the Charting control in .NET Core, including a sample application demonstrating its use, see the [winforms-datavisualization repository][dataviz] + ### Include the Windows.Compatibility Pack Windows applications like Windows Forms and WPF often use APIs that aren't referenced by default in .NET Core. The reason is that .NET Core tries to reduce the risk that new applications accidentally depend on legacy technologies or on APIs that are Windows-only. However, when porting existing Windows applications, neither of these two aspects is a concern. To simplify your porting efforts, you can simply reference the [Windows Compatibility Pack][compat-pack], which will give @@ -115,5 +119,8 @@ System.PlatformNotSupportedException: 'Configuration files are not supported.' [api-port]: https://blogs.msdn.microsoft.com/dotnet/2018/08/08/are-your-windows-forms-and-wpf-applications-ready-for-net-core-3-0/ [pkg-config]: https://docs.microsoft.com/en-us/nuget/reference/migrate-packages-config-to-package-reference [sdk-tool]:https://github.com/hvanbakel/CsprojToVs2017 +[framework-charting]: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datavisualization.charting +[nuget-dataviz]: https://www.nuget.org/packages/System.windows.forms.datavisualization +[dataviz]: https://github.com/dotnet/winforms-datavisualization [compat-pack]: https://docs.microsoft.com/en-us/dotnet/core/porting/windows-compat-pack -[wcf-supported]: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.1.0.md \ No newline at end of file +[wcf-supported]: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.1.0.md diff --git a/Winforms.sln b/Winforms.sln index 360bde95e34..5d702209575 100644 --- a/Winforms.sln +++ b/Winforms.sln @@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Tests", "src\System.Windows.Forms\tests\UnitTests\System.Windows.Forms.Tests.csproj", "{AB38E262-F206-4820-8F29-23C5F72A4A16}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Private.Winforms", "pkg\Microsoft.Private.Winforms.csproj", "{F133342A-3040-4005-A2F0-7685AA7CB82D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Design.Editors", "src\System.Windows.Forms.Design.Editors\src\System.Windows.Forms.Design.Editors.csproj", "{B50AC96F-2655-4687-A404-16DF51882CBC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Design.Editors.Tests", "src\System.Windows.Forms.Design.Editors\tests\UnitTests\System.Windows.Forms.Design.Editors.Tests.csproj", "{27F24D0C-5F0A-472E-AE12-98B386A13D50}" @@ -23,6 +21,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Drawing.Design.Facad EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Design.Facade", "src\System.Design\src\System.Design.Facade.csproj", "{9BEC2806-D8E0-443B-8B58-9D344E0C2D24}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Private.Winforms", "pkg\Microsoft.Private.Winforms\Microsoft.Private.Winforms.csproj", "{F133342A-3040-4005-A2F0-7685AA7CB82D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Dotnet.Winforms.ProjectTemplates", "pkg\Microsoft.Dotnet.WinForms.ProjectTemplates\Microsoft.Dotnet.Winforms.ProjectTemplates.csproj", "{36A5139E-3E9C-42BD-95EE-818153A487DB}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pkg", "pkg", "{989F376E-AE19-43B0-A3E6-96A7E22B4E80}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{77FEDB47-F7F6-490D-AF7C-ABB4A9E0B9D7}" @@ -116,6 +118,10 @@ Global {6103E743-057D-41C6-946C-23A751A08748}.Debug|Any CPU.Build.0 = Debug|Any CPU {6103E743-057D-41C6-946C-23A751A08748}.Release|Any CPU.ActiveCfg = Release|Any CPU {6103E743-057D-41C6-946C-23A751A08748}.Release|Any CPU.Build.0 = Release|Any CPU + {36A5139E-3E9C-42BD-95EE-818153A487DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36A5139E-3E9C-42BD-95EE-818153A487DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36A5139E-3E9C-42BD-95EE-818153A487DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36A5139E-3E9C-42BD-95EE-818153A487DB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -139,6 +145,7 @@ Global {351D8601-6E21-45E8-B3B9-847C4540BD4E} = {088DD24C-DF6B-45F3-A8BC-592580A4B2A9} {6103E743-057D-41C6-946C-23A751A08748} = {088DD24C-DF6B-45F3-A8BC-592580A4B2A9} {088DD24C-DF6B-45F3-A8BC-592580A4B2A9} = {77FEDB47-F7F6-490D-AF7C-ABB4A9E0B9D7} + {36A5139E-3E9C-42BD-95EE-818153A487DB} = {989F376E-AE19-43B0-A3E6-96A7E22B4E80} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7B1B0433-F612-4E5A-BE7E-FCF5B9F6E136} diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1e492df7685..c631379ca9a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,7 +5,8 @@ # so they can be used to control yaml flow. variables: - + _PublishUsingPipelines: true + _DotNetArtifactsCategory: WINDOWSDESKTOP # clean the local repo on the build agents Build.Repository.Clean: true diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d2a895b395d..dbaa4b8edbc 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -7,73 +7,77 @@ Note: if the Uri is a new place, you will need to add a subscription from that p --> - - https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + + + + + https://github.com/dotnet/core-setup + a2ccf1ad6ed1735ed1b1631661710c755356db00 - + + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - - https://github.com/dotnet/core-setup - 4ea0233e38681384ee91d7a72c011db9c02e35ff + + https://github.com/dotnet/corefx + bdd2014f2d1863a296f76b5c90152ae016854afc - - - + https://github.com/dotnet/corefx - 2c1cf10610d8102e080b203ff396707eeced15bd + bdd2014f2d1863a296f76b5c90152ae016854afc - - https://github.com/dotnet/arcade - 505e38906e1ee2d032c41bb297de0958307db946 + + + https://github.com/dotnet/coreclr + 8808f4eab10d1760182590cad4964f566b9c88ca + 5596 - - https://github.com/dotnet/arcade - 505e38906e1ee2d032c41bb297de0958307db946 + + https://github.com/dotnet/coreclr + 8808f4eab10d1760182590cad4964f566b9c88ca + 5596 - + + https://github.com/dotnet/arcade - 505e38906e1ee2d032c41bb297de0958307db946 + e02c88fca482f1141a9bb310c97be20b0ebd0465 - + https://github.com/dotnet/arcade - 505e38906e1ee2d032c41bb297de0958307db946 + e02c88fca482f1141a9bb310c97be20b0ebd0465 - - https://github.com/dotnet/coreclr - 2520798548b0c414f513aaaf708399f8ef5a4f6c - 5596 + + https://github.com/dotnet/arcade + e02c88fca482f1141a9bb310c97be20b0ebd0465 - - https://github.com/dotnet/coreclr - 2520798548b0c414f513aaaf708399f8ef5a4f6c - 5596 + + https://github.com/dotnet/arcade + e02c88fca482f1141a9bb310c97be20b0ebd0465 diff --git a/eng/Versions.props b/eng/Versions.props index 407d263b9c3..bcb91b47b1b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -3,7 +3,7 @@ 4.8.0 - preview4 + preview6 false @@ -12,28 +12,35 @@ https://dotnetfeed.blob.core.windows.net/dotnet-coreclr/index.json - + + - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 4.6.0-preview4.19181.2 - 3.0.0-preview4.19181.2 + 3.0.0-preview6-27625-10 - + - 3.0.0-preview4-27525-72 + 3.0.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 + 4.6.0-preview6.19225.3 - + - 1.0.0-beta.19201.12 - 2.4.0-beta.19201.12 + 3.0.0-preview5-27616-73 + 3.0.0-preview6-27624-71 - + + + 1.0.0-beta.19224.9 + 2.4.0-beta.19224.9 + + + 2.4.1-pre.build.4059 $(XUnitVersion) diff --git a/eng/ci.yml b/eng/ci.yml index 0c669dcf2c7..011a835469c 100644 --- a/eng/ci.yml +++ b/eng/ci.yml @@ -14,8 +14,9 @@ jobs: enablePublishBuildArtifacts: true enablePublishTestResults: true enablePublishBuildAssets: true + enablePublishUsingPipelines: $(_PublishUsingPipelines) enableTelemetry: true - helixRepo: $(repoName) + helixRepo: ${{ parameters.repoName }} jobs: - job: Windows_NT @@ -47,13 +48,7 @@ jobs: # needed for helix jobs - name: _TestHelixAgentPool - value: 'Windows.10.Amd64.Open' - - name: _WinformsControlsTestBinDir - value: $(BUILD.SOURCESDIRECTORY)\artifacts\bin\WinformsControlsTest\$(_BuildConfig)\netcoreapp3.0 - - name: _WinformsFuncTestBinDir - value: $(BUILD.SOURCESDIRECTORY)\artifacts\bin\System.Windows.Forms.Func.Tests\$(_BuildConfig)\netcoreapp3.0 - - name: _HelixStagingDir - value: $(BUILD.STAGINGDIRECTORY)\helix\functests + value: 'Windows.10.Amd64.ClientRS5.Open' - name: _HelixSource value: ${{ parameters.repoName }}/$(Build.SourceBranch) - name: _HelixToken @@ -89,6 +84,8 @@ jobs: value: /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) /p:DotNetPublishBlobFeedUrl=$(_PublishBlobFeedUrl) /p:DotNetPublishToBlobFeed=$(_DotNetPublishToBlobFeed) + /p:DotNetPublishUsingPipelines=$(_PublishUsingPipelines) + /p:DotNetArtifactsCategory=$(_DotNetArtifactsCategory) /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - name: _OfficialBuildIdArgs @@ -96,7 +93,7 @@ jobs: # Windows.81.Amd64 will fail on Debug.Assert in TryGetSystemMetricsForDpi in UnsafeNativeMethods - name: _TestHelixAgentPool - value: 'Windows.10.Amd64' + value: 'Windows.10.Amd64.ClientRS5' - name: _HelixSource value: official/${{ parameters.repoName }}/$(Build.SourceBranch) - name: _HelixToken @@ -218,13 +215,13 @@ jobs: # Publish the nuget package as a build artifact (only for release, ensuring package contents are real-signed) - task: PublishPipelineArtifact@0 inputs: - artifactName: 'Package' + artifactName: 'Packages' targetPath: '$(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping' - displayName: Publish package to build artifacts + displayName: Publish transport NuGet package & templates package to build artifacts continueOnError: true condition: and(succeeded(), eq(variables['_BuildConfig'], 'Release')) # Run component governance detection (only for release; only for internal) - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: Component Governance Detection - condition: and(succeeded(), eq(variables['_BuildConfig'], 'Release')) \ No newline at end of file + condition: and(succeeded(), eq(variables['_BuildConfig'], 'Release')) diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1 new file mode 100644 index 00000000000..b8d84607b89 --- /dev/null +++ b/eng/common/CheckSymbols.ps1 @@ -0,0 +1,158 @@ +param( + [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where NuGet packages to be checked are stored + [Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation + [Parameter(Mandatory=$true)][string] $SymbolToolPath # Full path to directory where dotnet symbol-tool was installed +) + +Add-Type -AssemblyName System.IO.Compression.FileSystem + +function FirstMatchingSymbolDescriptionOrDefault { + param( + [string] $FullPath, # Full path to the module that has to be checked + [string] $TargetServerParam, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols + [string] $SymbolsPath + ) + + $FileName = [System.IO.Path]::GetFileName($FullPath) + $Extension = [System.IO.Path]::GetExtension($FullPath) + + # Those below are potential symbol files that the `dotnet symbol` might + # return. Which one will be returned depend on the type of file we are + # checking and which type of file was uploaded. + + # The file itself is returned + $SymbolPath = $SymbolsPath + "\" + $FileName + + # PDB file for the module + $PdbPath = $SymbolPath.Replace($Extension, ".pdb") + + # PDB file for R2R module (created by crossgen) + $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb") + + # DBG file for a .so library + $SODbg = $SymbolPath.Replace($Extension, ".so.dbg") + + # DWARF file for a .dylib + $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf") + + .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParam $FullPath -o $SymbolsPath | Out-Null + + if (Test-Path $PdbPath) { + return "PDB" + } + elseif (Test-Path $NGenPdb) { + return "NGen PDB" + } + elseif (Test-Path $SODbg) { + return "DBG for SO" + } + elseif (Test-Path $DylibDwarf) { + return "Dwarf for Dylib" + } + elseif (Test-Path $SymbolPath) { + return "Module" + } + else { + return $null + } +} + +function CountMissingSymbols { + param( + [string] $PackagePath # Path to a NuGet package + ) + + # Ensure input file exist + if (!(Test-Path $PackagePath)) { + throw "Input file does not exist: $PackagePath" + } + + # Extensions for which we'll look for symbols + $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib") + + # How many files are missing symbol information + $MissingSymbols = 0 + + $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) + $PackageGuid = New-Guid + $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid + $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath "Symbols" + + [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) + + # Makes easier to reference `symbol tool` + Push-Location $SymbolToolPath + + Get-ChildItem -Recurse $ExtractPath | + Where-Object {$RelevantExtensions -contains $_.Extension} | + ForEach-Object { + if ($_.FullName -Match "\\ref\\") { + Write-Host "`t Ignoring reference assembly file" $_.FullName + return + } + + $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" $SymbolsPath + $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" $SymbolsPath + + Write-Host -NoNewLine "`t Checking file" $_.FullName "... " + + if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) { + Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")" + } + else { + $MissingSymbols++ + + if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) { + Write-Host "No symbols found on MSDL or SymWeb!" + } + else { + if ($SymbolsOnMSDL -eq $null) { + Write-Host "No symbols found on MSDL!" + } + else { + Write-Host "No symbols found on SymWeb!" + } + } + } + } + + Pop-Location + + return $MissingSymbols +} + +function CheckSymbolsAvailable { + if (Test-Path $ExtractPath) { + Remove-Item $ExtractPath -Force -Recurse -ErrorAction SilentlyContinue + } + + Get-ChildItem "$InputPath\*.nupkg" | + ForEach-Object { + $FileName = $_.Name + + # These packages from Arcade-Services include some native libraries that + # our current symbol uploader can't handle. Below is a workaround until + # we get issue: https://github.com/dotnet/arcade/issues/2457 sorted. + if ($FileName -Match "Microsoft\.DotNet\.Darc\.") { + Write-Host "Ignoring Arcade-services file: $FileName" + Write-Host + return + } + elseif ($FileName -Match "Microsoft\.DotNet\.Maestro\.Tasks\.") { + Write-Host "Ignoring Arcade-services file: $FileName" + Write-Host + return + } + + Write-Host "Validating $FileName " + $Status = CountMissingSymbols "$InputPath\$FileName" + + if ($Status -ne 0) { + Write-Error "Missing symbols for $Status modules in the package $FileName" + } + + Write-Host + } +} + +CheckSymbolsAvailable diff --git a/eng/common/PublishToPackageFeed.proj b/eng/common/PublishToPackageFeed.proj index ccb81e8c355..e17f72644e3 100644 --- a/eng/common/PublishToPackageFeed.proj +++ b/eng/common/PublishToPackageFeed.proj @@ -1,11 +1,13 @@ - + + + netcoreapp2.1 @@ -41,6 +43,16 @@ https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json https://dotnetfeed.blob.core.windows.net/arcade-validation/index.json + https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json + https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json + https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json + https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json + https://dotnetfeed.blob.core.windows.net/dotnet-coreclr/index.json + https://dotnetfeed.blob.core.windows.net/dotnet-sdk/index.json + https://dotnetfeed.blob.core.windows.net/dotnet-tools-internal/index.json + https://dotnetfeed.blob.core.windows.net/dotnet-toolset/index.json + https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json + https://dotnetfeed.blob.core.windows.net/nuget-nugetclient/index.json + + + + + netcoreapp2.1 + + + + + + + + + + + + + + + + 3650 + true + false + + + + + + + + + + + + + + + + + diff --git a/eng/common/SigningValidation.proj b/eng/common/SigningValidation.proj index 17e40d12877..7045fb6fb9d 100644 --- a/eng/common/SigningValidation.proj +++ b/eng/common/SigningValidation.proj @@ -1,18 +1,20 @@ - + + - + - PackageBasePath : Directory containing all files that need to be validated. + - SignCheckVersion : Version of SignCheck package to be used. + - SignValidationExclusionList : ItemGroup containing exclusion list to be forwarded to SignCheck. + - EnableJarSigningCheck : Whether .jar files should be validated. + - EnableStrongNameCheck : Whether strong name check should be performed. + --> + netcoreapp2.1 diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1 index 29c443212b4..81ffd16779c 100644 --- a/eng/common/darc-init.ps1 +++ b/eng/common/darc-init.ps1 @@ -19,7 +19,7 @@ function InstallDarcCli ($darcVersion) { # Until we can anonymously query the BAR API for the latest arcade-services # build applied to the PROD channel, this is hardcoded. if (-not $darcVersion) { - $darcVersion = '1.1.0-beta.19175.6' + $darcVersion = '1.1.0-beta.19205.4' } $arcadeServicesSource = 'https://dotnetfeed.blob.core.windows.net/dotnet-arcade/index.json' diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh old mode 100644 new mode 100755 index cab6cd5bf9f..bd7eb463986 --- a/eng/common/darc-init.sh +++ b/eng/common/darc-init.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash source="${BASH_SOURCE[0]}" -darcVersion="1.1.0-beta.19175.6" +darcVersion="1.1.0-beta.19205.4" while [[ $# > 0 ]]; do opt="$(echo "$1" | awk '{print tolower($0)}')" diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj index 1a81ff906f6..1a39a7ef3f6 100644 --- a/eng/common/internal/Tools.csproj +++ b/eng/common/internal/Tools.csproj @@ -12,8 +12,12 @@ - - https://devdiv.pkgs.visualstudio.com/_packaging/8f470c7e-ac49-4afe-a6ee-cf784e438b93/nuget/v3/index.json; + + + https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json; + + + $(RestoreSources); https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json; diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 74dd81fdc0a..7839b70bb70 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -43,9 +43,12 @@ parameters: # Optional: enable sending telemetry enableTelemetry: false - # Optional: define the helix repo for telemeetry (example: 'dotnet/arcade') + # Optional: define the helix repo for telemetry (example: 'dotnet/arcade') helixRepo: '' + # Optional: define the helix type for telemetry (example: 'build/product/') + helixType: '' + # Required: name of the job name: '' @@ -122,6 +125,8 @@ jobs: displayName: 'Send Helix Start Telemetry' inputs: helixRepo: ${{ parameters.helixRepo }} + ${{ if ne(parameters.helixType, '') }}: + helixType: ${{ parameters.helixType }} buildConfig: $(_BuildConfig) runAsPublic: ${{ parameters.runAsPublic }} continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/templates/phases/publish-build-assets.yml b/eng/common/templates/phases/publish-build-assets.yml index 211967debab..a0a8074282a 100644 --- a/eng/common/templates/phases/publish-build-assets.yml +++ b/eng/common/templates/phases/publish-build-assets.yml @@ -5,6 +5,7 @@ parameters: condition: succeeded() continueOnError: false runAsPublic: false + publishUsingPipelines: false phases: - phase: Asset_Registry_Publish displayName: Publish to Build Asset Registry @@ -36,6 +37,7 @@ phases: /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' /p:BuildAssetRegistryToken=$(MaestroAccessToken) /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} /p:Configuration=$(_BuildConfig) condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/templates/steps/helix-publish.yml b/eng/common/templates/steps/helix-publish.yml deleted file mode 100644 index 470ab65da0c..00000000000 --- a/eng/common/templates/steps/helix-publish.yml +++ /dev/null @@ -1,51 +0,0 @@ -parameters: - HelixSource: 'pr/dotnet-github-anon-kaonashi-bot' - HelixType: ̓'tests/default' - HelixBuild: $(Build.BuildNumber) - HelixTargetQueues: '' - HelixAccessToken: '' - HelixPreCommands: '' - HelixPostCommands: '' - WorkItemDirectory: '' - WorkItemCommand: '' - CorrelationPayloadDirectory: '' - XUnitProjects: '' - XUnitTargetFramework: '' - XUnitRunnerVersion: '' - IncludeDotNetCli: false - DotNetCliPackageType: '' - DotNetCliVersion: '' - EnableXUnitReporter: false - WaitForWorkItemCompletion: true - condition: succeeded() - continueOnError: false - -steps: - - task: DotNetCoreCLI@2 - inputs: - command: custom - projects: eng/common/helixpublish.proj - custom: msbuild - arguments: '/bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog' - displayName: Send job to Helix - env: - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 7c185e94147..d1ce577db5b 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -23,7 +23,7 @@ parameters: WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Send job to Helix' # optional -- rename the beginning of the displayName of the steps in AzDO + DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false diff --git a/global.json b/global.json index 7bff5a4fe96..0ce915fd3f7 100644 --- a/global.json +++ b/global.json @@ -1,17 +1,17 @@ { "tools": { - "dotnet": "3.0.100-preview4-010924", + "dotnet": "3.0.100-preview5-011162", "vs": { "version": "16.0" }, "xcopy-msbuild": "16.0.0-rc1-alpha" }, "sdk": { - "version": "3.0.100-preview4-010924" + "version": "3.0.100-preview5-011162" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19201.12", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19201.12", - "Microsoft.NET.Sdk.IL": "3.0.0-preview4-27525-72" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19224.9", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19224.9", + "Microsoft.NET.Sdk.IL": "3.0.0-preview6-27624-71" } } diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/Microsoft.Dotnet.Winforms.ProjectTemplates.csproj b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/Microsoft.Dotnet.Winforms.ProjectTemplates.csproj new file mode 100644 index 00000000000..9c3f4ceed31 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/Microsoft.Dotnet.Winforms.ProjectTemplates.csproj @@ -0,0 +1,79 @@ + + + + netcoreapp + 3.0 + $(TargetFrameworkName)$(TargetFrameworkVersion) + false + false + + + + + true + + + + false + false + false + + + + + false + + + + + Microsoft.Dotnet.WinForms.ProjectTemplates + Project templates for .NET Core Windows Forms projects + Microsoft + https://github.com/dotnet/winforms + Windows Forms WinForms Project Templates .NET Core + + + + + .\ + + + + + + + .\ + true + + + + + + + + + + + + + + + + + + + + + BuildOnlySettings; + PrepareForBuild; + PreBuildEvent; + ResolveReferences; + GetTargetPath; + PrepareForRun; + IncrementalClean; + PostBuildEvent + + + diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/.template.config/dotnetcli.host.json b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/.template.config/dotnetcli.host.json new file mode 100644 index 00000000000..22ab4a3929f --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/.template.config/dotnetcli.host.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json.schemastore.org/dotnetcli.host", + "symbolInfo": { + "TargetFrameworkOverride": { + "isHidden": "true", + "longName": "target-framework-override", + "shortName": "" + }, + "Framework": { + "longName": "framework" + }, + "skipRestore": { + "longName": "no-restore", + "shortName": "" + }, + "langVersion": { + "longName": "langVersion", + "shortName": "" + } + }, + "usageExamples": [ + "" + ] +} diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/.template.config/template.json b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/.template.config/template.json new file mode 100644 index 00000000000..e9226dbf010 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/.template.config/template.json @@ -0,0 +1,86 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": ["Common", "WinForms"], + "name": "Windows Forms (WinForms) Application", + "generatorVersions": "[1.0.0.0-*)", + "description": "A project for creating a .NET Core Windows Forms (WinForms) Application", + "groupIdentity": "Microsoft.Common.WinForms", + "precedence": "3000", + "identity": "Microsoft.Common.WinForms", + "shortName": "winforms", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "Company.WinFormsApplication1", + "preferNameDirectory": true, + "symbols": { + "TargetFrameworkOverride": { + "type": "parameter", + "description": "Overrides the target framework", + "replaces": "TargetFrameworkOverride", + "datatype": "string", + "defaultValue": "" + }, + "Framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "netcoreapp3.0", + "description": "Target netcoreapp3.0" + } + ], + "replaces": "netcoreapp3.0", + "defaultValue": "netcoreapp3.0" + }, + "langVersion": { + "type": "parameter", + "datatype": "text", + "description": "Sets langVersion in the created project file", + "defaultValue": "", + "replaces": "$(ProjectLanguageVersion)" + }, + "HostIdentifier": { + "type": "bind", + "binding": "HostIdentifier" + }, + "skipRestore": { + "type": "parameter", + "datatype": "bool", + "description": "If specified, skips the automatic restore of the project on create.", + "defaultValue": "false" + } + }, + "primaryOutputs": [ + { "path": "Company.WinFormsApplication1.csproj" }, + { + "condition": "(HostIdentifier != \"dotnetcli\" && HostIdentifier != \"dotnetcli-preview\")", + "path": "Form1.cs" + } + ], + "defaultName": "WinFormsApp1", + "postActions": [ + { + "condition": "(!skipRestore)", + "description": "Restore NuGet packages required by this project.", + "manualInstructions": [ + { "text": "Run 'dotnet restore'" } + ], + "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", + "continueOnError": true + }, + { + "condition": "(HostIdentifier != \"dotnetcli\" && HostIdentifier != \"dotnetcli-preview\")", + "description": "Opens Form1.cs in the editor", + "manualInstructions": [ ], + "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6", + "args": { + "files": "1" + }, + "continueOnError": true + } + ] +} diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Company.WinFormsApplication1.csproj b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Company.WinFormsApplication1.csproj new file mode 100644 index 00000000000..9dd6eb88bed --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Company.WinFormsApplication1.csproj @@ -0,0 +1,12 @@ + + + + WinExe + netcoreapp3.0 + TargetFrameworkOverride + Company.WinFormsApplication1 + $(ProjectLanguageVersion) + true + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.Designer.cs b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.Designer.cs new file mode 100644 index 00000000000..5ee8d7b46e1 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.Designer.cs @@ -0,0 +1,40 @@ +namespace Company.WinFormsApplication1 +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Text = "Form1"; + } + + #endregion + } +} + diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.cs b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.cs new file mode 100644 index 00000000000..0ac1f900f5d --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Company.WinFormsApplication1 +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + } +} diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.resx b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.resx new file mode 100644 index 00000000000..1af7de150c9 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Program.cs b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Program.cs new file mode 100644 index 00000000000..0b950cc7851 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Company.WinFormsApplication1 +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.cs.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.cs.xlf new file mode 100644 index 00000000000..aa40faef86f --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.cs.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.de.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.de.xlf new file mode 100644 index 00000000000..caab0ce76f7 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.de.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.es.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.es.xlf new file mode 100644 index 00000000000..37761f811ce --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.es.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.fr.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.fr.xlf new file mode 100644 index 00000000000..366eb9d5436 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.fr.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.it.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.it.xlf new file mode 100644 index 00000000000..e68d3fe2676 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.it.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ja.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ja.xlf new file mode 100644 index 00000000000..2943ecce294 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ja.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ko.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ko.xlf new file mode 100644 index 00000000000..83cb763b8f6 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ko.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.pl.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.pl.xlf new file mode 100644 index 00000000000..58b6edd6da0 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.pl.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.pt-BR.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.pt-BR.xlf new file mode 100644 index 00000000000..073f6c00557 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.pt-BR.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ru.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ru.xlf new file mode 100644 index 00000000000..5d784e2bc56 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.ru.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.tr.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.tr.xlf new file mode 100644 index 00000000000..9ae0ede5336 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.tr.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.zh-Hans.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.zh-Hans.xlf new file mode 100644 index 00000000000..2dbdc8d0ce3 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.zh-Hans.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.zh-Hant.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.zh-Hant.xlf new file mode 100644 index 00000000000..8782e525d98 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-CSharp/xlf/Form1.zh-Hant.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/.template.config/dotnetcli.host.json b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/.template.config/dotnetcli.host.json new file mode 100644 index 00000000000..22ab4a3929f --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/.template.config/dotnetcli.host.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json.schemastore.org/dotnetcli.host", + "symbolInfo": { + "TargetFrameworkOverride": { + "isHidden": "true", + "longName": "target-framework-override", + "shortName": "" + }, + "Framework": { + "longName": "framework" + }, + "skipRestore": { + "longName": "no-restore", + "shortName": "" + }, + "langVersion": { + "longName": "langVersion", + "shortName": "" + } + }, + "usageExamples": [ + "" + ] +} diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/.template.config/template.json b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/.template.config/template.json new file mode 100644 index 00000000000..f30b7c910b8 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/.template.config/template.json @@ -0,0 +1,86 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": ["Common", "WinForms"], + "name": "Windows Forms (WinForms) Application", + "generatorVersions": "[1.0.0.0-*)", + "description": "A project for creating a .NET Core Windows Forms (WinForms) Application", + "groupIdentity": "Microsoft.Common.WinForms", + "precedence": "3000", + "identity": "Microsoft.Common.WinForms.VisualBasic.3.0", + "shortName": "winforms", + "tags": { + "language": "VB", + "type": "project" + }, + "sourceName": "Company.WinFormsApplication1", + "preferNameDirectory": true, + "symbols": { + "TargetFrameworkOverride": { + "type": "parameter", + "description": "Overrides the target framework", + "replaces": "TargetFrameworkOverride", + "datatype": "string", + "defaultValue": "" + }, + "Framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "netcoreapp3.0", + "description": "Target netcoreapp3.0" + } + ], + "replaces": "netcoreapp3.0", + "defaultValue": "netcoreapp3.0" + }, + "langVersion": { + "type": "parameter", + "datatype": "text", + "description": "Sets langVersion in the created project file", + "defaultValue": "", + "replaces": "$(ProjectLanguageVersion)" + }, + "HostIdentifier": { + "type": "bind", + "binding": "HostIdentifier" + }, + "skipRestore": { + "type": "parameter", + "datatype": "bool", + "description": "If specified, skips the automatic restore of the project on create.", + "defaultValue": "false" + } + }, + "primaryOutputs": [ + { "path": "Company.WinFormsApplication1.vbproj" }, + { + "condition": "(HostIdentifier != \"dotnetcli\" && HostIdentifier != \"dotnetcli-preview\")", + "path": "Form1.vb" + } + ], + "defaultName": "WinFormsApp1", + "postActions": [ + { + "condition": "(!skipRestore)", + "description": "Restore NuGet packages required by this project.", + "manualInstructions": [ + { "text": "Run 'dotnet restore'" } + ], + "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", + "continueOnError": true + }, + { + "condition": "(HostIdentifier != \"dotnetcli\" && HostIdentifier != \"dotnetcli-preview\")", + "description": "Opens Form1.vb in the editor", + "manualInstructions": [ ], + "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6", + "args": { + "files": "1" + }, + "continueOnError": true + } + ] +} diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Company.WinFormsApplication1.vbproj b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Company.WinFormsApplication1.vbproj new file mode 100644 index 00000000000..4c54d1a376e --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Company.WinFormsApplication1.vbproj @@ -0,0 +1,19 @@ + + + + WinExe + netcoreapp3.0 + TargetFrameworkOverride + Company.WinFormsApplication1 + Company.WinFormsApplication1.Form1 + $(ProjectLanguageVersion) + true + + + + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.Designer.vb b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.Designer.vb new file mode 100644 index 00000000000..a418df0ea8d --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.Designer.vb @@ -0,0 +1,31 @@ + _ +Partial Class Form1 + Inherits System.Windows.Forms.Form + + 'Form overrides dispose to clean up the component list. + _ + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Required by the Windows Form Designer + Private components As System.ComponentModel.IContainer + + 'NOTE: The following procedure is required by the Windows Form Designer + 'It can be modified using the Windows Form Designer. + 'Do not modify it using the code editor. + _ + Private Sub InitializeComponent() + components = New System.ComponentModel.Container() + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(800, 450) + Me.Text = "Form1" + End Sub + +End Class diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.resx b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.resx new file mode 100644 index 00000000000..1af7de150c9 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.vb b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.vb new file mode 100644 index 00000000000..17d659563f3 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/Form1.vb @@ -0,0 +1,3 @@ +Public Class Form1 + +End Class diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.cs.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.cs.xlf new file mode 100644 index 00000000000..aa40faef86f --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.cs.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.de.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.de.xlf new file mode 100644 index 00000000000..caab0ce76f7 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.de.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.es.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.es.xlf new file mode 100644 index 00000000000..37761f811ce --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.es.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.fr.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.fr.xlf new file mode 100644 index 00000000000..366eb9d5436 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.fr.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.it.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.it.xlf new file mode 100644 index 00000000000..e68d3fe2676 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.it.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ja.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ja.xlf new file mode 100644 index 00000000000..2943ecce294 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ja.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ko.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ko.xlf new file mode 100644 index 00000000000..83cb763b8f6 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ko.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.pl.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.pl.xlf new file mode 100644 index 00000000000..58b6edd6da0 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.pl.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.pt-BR.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.pt-BR.xlf new file mode 100644 index 00000000000..073f6c00557 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.pt-BR.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ru.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ru.xlf new file mode 100644 index 00000000000..5d784e2bc56 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.ru.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.tr.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.tr.xlf new file mode 100644 index 00000000000..9ae0ede5336 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.tr.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.zh-Hans.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.zh-Hans.xlf new file mode 100644 index 00000000000..2dbdc8d0ce3 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.zh-Hans.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.zh-Hant.xlf b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.zh-Hant.xlf new file mode 100644 index 00000000000..8782e525d98 --- /dev/null +++ b/pkg/Microsoft.Dotnet.WinForms.ProjectTemplates/content/WinFormsApplication-VisualBasic/xlf/Form1.zh-Hant.xlf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pkg/Microsoft.Private.Winforms.csproj b/pkg/Microsoft.Private.Winforms/Microsoft.Private.Winforms.csproj similarity index 74% rename from pkg/Microsoft.Private.Winforms.csproj rename to pkg/Microsoft.Private.Winforms/Microsoft.Private.Winforms.csproj index aa41a551f85..47b1e68d3a4 100644 --- a/pkg/Microsoft.Private.Winforms.csproj +++ b/pkg/Microsoft.Private.Winforms/Microsoft.Private.Winforms.csproj @@ -14,18 +14,26 @@ --> + netcoreapp + 3.0 + $(TargetFrameworkName)$(TargetFrameworkVersion) + + + + + true + + false false false + - netcoreapp3.0 - true - + false - @@ -45,24 +53,25 @@ - + - + - + - + - + - + + + - diff --git a/src/Common/src/ClientUtils.cs b/src/Common/src/ClientUtils.cs index 246116a1c8f..0f1072e6bbc 100644 --- a/src/Common/src/ClientUtils.cs +++ b/src/Common/src/ClientUtils.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms #elif DRAWING_NAMESPACE namespace System.Drawing @@ -270,7 +270,7 @@ private static void Debug_NonSequentialEnumIsDefinedCheck(System.Enum value, int /// ----------------------------------------------------------------- /// /// -#if WINFORMS_NAMESPACE || WINFORMS_PUBLIC_GRAPHICS_LIBRARY || DRAWING_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE || WINFORMS_PUBLIC_GRAPHICS_LIBRARY || DRAWING_NAMESPACE internal class WeakRefCollection : IList { private int refCheckThreshold = int.MaxValue; // this means this is disabled by default. private ArrayList _innerList; diff --git a/src/Common/src/CompModSwitches.cs b/src/Common/src/CompModSwitches.cs index ae6bdd9c862..a02feae0396 100644 --- a/src/Common/src/CompModSwitches.cs +++ b/src/Common/src/CompModSwitches.cs @@ -6,15 +6,10 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.ComponentModel.CompModSwitches.get_LayoutPerformance():System.Diagnostics.TraceSwitch")] namespace System.ComponentModel { - using System.Diagnostics; + using System.Diagnostics; - /// - // Shared between dlls - internal static class CompModSwitches { -#if WINDOWS_FORMS_SWITCHES - private static TraceSwitch activeX; private static TraceSwitch flowLayout; private static TraceSwitch dataCursor; @@ -23,17 +18,17 @@ internal static class CompModSwitches { private static TraceSwitch dataGridKeys; private static TraceSwitch dataGridLayout; private static TraceSwitch dataGridPainting; - private static TraceSwitch dataGridParents; + private static TraceSwitch dataGridParents; private static TraceSwitch dataGridScrolling; - private static TraceSwitch dataGridSelection; - private static TraceSwitch dataObject; + private static TraceSwitch dataGridSelection; + private static TraceSwitch dataObject; private static TraceSwitch dataView; private static TraceSwitch debugGridView; - private static TraceSwitch dgCaptionPaint; - private static TraceSwitch dgEditColumnEditing; + private static TraceSwitch dgCaptionPaint; + private static TraceSwitch dgEditColumnEditing; private static TraceSwitch dgRelationShpRowLayout; private static TraceSwitch dgRelationShpRowPaint; - private static TraceSwitch dgRowPaint; + private static TraceSwitch dgRowPaint; private static TraceSwitch dragDrop; private static TraceSwitch imeMode; private static TraceSwitch msaa; @@ -44,7 +39,11 @@ internal static class CompModSwitches { private static TraceSwitch setBounds; private static BooleanSwitch lifetimeTracing; - + + private static TraceSwitch s_handleLeak; + private static BooleanSwitch s_traceCollect; + private static BooleanSwitch s_commonDesignerServices; + public static TraceSwitch ActiveX { get { if (activeX == null) { @@ -52,7 +51,7 @@ public static TraceSwitch ActiveX { } return activeX; } - } + } public static TraceSwitch DataCursor { get { @@ -89,7 +88,7 @@ public static TraceSwitch DataGridKeys { return dataGridKeys; } } - + public static TraceSwitch DataGridLayout { get { if (dataGridLayout == null) { @@ -107,7 +106,7 @@ public static TraceSwitch DataGridPainting { return dataGridPainting; } } - + public static TraceSwitch DataGridParents { get { if (dataGridParents == null) { @@ -134,7 +133,7 @@ public static TraceSwitch DataGridSelection { return dataGridSelection; } } - + public static TraceSwitch DataObject { get { if (dataObject == null) { @@ -151,7 +150,7 @@ public static TraceSwitch DataView { } return dataView; } - } + } public static TraceSwitch DebugGridView { get { @@ -160,8 +159,8 @@ public static TraceSwitch DebugGridView { } return debugGridView; } - } - + } + public static TraceSwitch DGCaptionPaint { get { if (dgCaptionPaint == null) { @@ -170,7 +169,7 @@ public static TraceSwitch DGCaptionPaint { return dgCaptionPaint; } } - + public static TraceSwitch DGEditColumnEditing { get { if (dgEditColumnEditing == null) { @@ -179,7 +178,7 @@ public static TraceSwitch DGEditColumnEditing { return dgEditColumnEditing; } } - + public static TraceSwitch DGRelationShpRowLayout { get { if (dgRelationShpRowLayout == null) { @@ -188,7 +187,7 @@ public static TraceSwitch DGRelationShpRowLayout { return dgRelationShpRowLayout; } } - + public static TraceSwitch DGRelationShpRowPaint { get { if (dgRelationShpRowPaint == null) { @@ -196,8 +195,8 @@ public static TraceSwitch DGRelationShpRowPaint { } return dgRelationShpRowPaint; } - } - + } + public static TraceSwitch DGRowPaint { get { if (dgRowPaint == null) { @@ -223,8 +222,8 @@ public static TraceSwitch FlowLayout { } return flowLayout; } - } - + } + public static TraceSwitch ImeMode { get { if (imeMode == null) { @@ -242,7 +241,7 @@ public static TraceSwitch LayoutPerformance { return layoutPerformance; } } - + public static TraceSwitch LayoutSuspendResume { get { if (layoutSuspendResume == null) { @@ -260,7 +259,7 @@ public static BooleanSwitch LifetimeTracing { return lifetimeTracing; } } - + public static TraceSwitch MSAA { get { if (msaa == null) { @@ -269,7 +268,7 @@ public static TraceSwitch MSAA { return msaa; } } - + public static TraceSwitch MSOComponentManager { get { if (msoComponentManager == null) { @@ -278,7 +277,7 @@ public static TraceSwitch MSOComponentManager { return msoComponentManager; } } - + public static TraceSwitch RichLayout { get { if (richLayout == null) { @@ -286,8 +285,7 @@ public static TraceSwitch RichLayout { } return richLayout; } - } - + } public static TraceSwitch SetBounds { get { @@ -296,32 +294,36 @@ public static TraceSwitch SetBounds { } return setBounds; } - } - - #endif - - - - private static TraceSwitch handleLeak; + } public static TraceSwitch HandleLeak { get { - if (handleLeak == null) { - handleLeak = new TraceSwitch("HANDLELEAK", "HandleCollector: Track Win32 Handle Leaks"); + if (s_handleLeak == null) { + s_handleLeak = new TraceSwitch("HANDLELEAK", "HandleCollector: Track Win32 Handle Leaks"); } - return handleLeak; + return s_handleLeak; } } - private static BooleanSwitch traceCollect; public static BooleanSwitch TraceCollect { get { - if (traceCollect == null) { - traceCollect = new BooleanSwitch("TRACECOLLECT", "HandleCollector: Trace HandleCollector operations"); + if (s_traceCollect == null) { + s_traceCollect = new BooleanSwitch("TRACECOLLECT", "HandleCollector: Trace HandleCollector operations"); } - return traceCollect; + return s_traceCollect; } } + public static BooleanSwitch CommonDesignerServices + { + get + { + if (s_commonDesignerServices == null) + { + s_commonDesignerServices = new BooleanSwitch("CommonDesignerServices", "Assert if any common designer service is not found."); + } + return s_commonDesignerServices; + } + } } } diff --git a/src/Common/src/DpiHelper.cs b/src/Common/src/DpiHelper.cs index 013636236d7..ca30e7a25e2 100644 --- a/src/Common/src/DpiHelper.cs +++ b/src/Common/src/DpiHelper.cs @@ -6,15 +6,10 @@ using System.Drawing.Drawing2D; using System.Runtime.InteropServices; -#if WINFORMS_NAMESPACE -using CAPS = System.Windows.Forms.NativeMethods; -#elif WINFORMS_DESIGN_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE using CAPS = System.Windows.Forms.NativeMethods; #elif DRAWING_NAMESPACE using CAPS = System.Drawing.SafeNativeMethods; -#elif DRAWINGDESIGN_NAMESPACE -using System.Drawing.Design; -using CAPS = System.Drawing.Design.NativeMethods; #else using CAPS = System.Experimental.Gdi; #endif @@ -292,6 +287,17 @@ public static Bitmap CreateResizedBitmap(Bitmap logicalImage, Size targetImageSi return ScaleBitmapToSize(logicalImage, targetImageSize); } + /// + /// Creating bitmap from Icon resource + /// + public static Bitmap GetBitmapFromIcon(Type t, string name) + { + Icon b = new Icon(t, name); + Bitmap bitmap = b.ToBitmap(); + b.Dispose(); + return bitmap; + } + /// /// Create a new bitmap scaled for the device units. /// When displayed on the device, the scaled image will have same size as the original image would have when displayed at 96dpi. @@ -314,7 +320,7 @@ public static void ScaleBitmapLogicalToDevice(ref Bitmap logicalBitmap, int devi // This method is used only in System.Design, thus excluding the rest. // This is particularly important for System.Drawing, which should not depend // on System.Windows.Forms assembly, where "Button" type is defined. -#if (!DRAWING_NAMESPACE && !DRAWINGDESIGN_NAMESPACE && !WINFORMS_NAMESPACE) +#if (!DRAWING_NAMESPACE && !DRAWING_DESIGN_NAMESPACE) /// /// Create a new button bitmap scaled for the device units. /// Note: original image might be disposed. diff --git a/src/Common/src/Interop/Interop.EditMessages.cs b/src/Common/src/Interop/Interop.EditMessages.cs new file mode 100644 index 00000000000..cc696a39c72 --- /dev/null +++ b/src/Common/src/Interop/Interop.EditMessages.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + public static class EditMessages + { + public const int EM_GETSEL = 0x00B0; + public const int EM_SETSEL = 0x00B1; + public const int EM_SCROLL = 0x00B5; + public const int EM_GETMODIFY = 0x00B8; + public const int EM_SETMODIFY = 0x00B9; + public const int EM_GETLINECOUNT = 0x00BA; + public const int EM_REPLACESEL = 0x00C2; + public const int EM_GETLINE = 0x00C4; + public const int EM_LIMITTEXT = 0x00C5; + public const int EM_CANUNDO = 0x00C6; + public const int EM_UNDO = 0x00C7; + public const int EM_SETPASSWORDCHAR = 0x00CC; + public const int EM_GETPASSWORDCHAR = 0x00D2; + public const int EM_EMPTYUNDOBUFFER = 0x00CD; + public const int EM_SETREADONLY = 0x00CF; + public const int EM_SETMARGINS = 0x00D3; + public const int EM_LINEFROMCHAR = 0x00C9; + public const int EM_GETFIRSTVISIBLELINE = 0x00CE; + public const int EM_LINEINDEX = 0x00BB; + + public const int EM_GETLIMITTEXT = (WindowMessages.WM_USER + 37); + + public const int EM_POSFROMCHAR = (WindowMessages.WM_USER + 38); + public const int EM_CHARFROMPOS = (WindowMessages.WM_USER + 39); + + public const int EM_SCROLLCARET = (WindowMessages.WM_USER + 49); + public const int EM_CANPASTE = (WindowMessages.WM_USER + 50); + public const int EM_DISPLAYBAND = (WindowMessages.WM_USER + 51); + public const int EM_EXGETSEL = (WindowMessages.WM_USER + 52); + public const int EM_EXLIMITTEXT = (WindowMessages.WM_USER + 53); + public const int EM_EXLINEFROMCHAR = (WindowMessages.WM_USER + 54); + public const int EM_EXSETSEL = (WindowMessages.WM_USER + 55); + public const int EM_FINDTEXT = (WindowMessages.WM_USER + 56); + public const int EM_FORMATRANGE = (WindowMessages.WM_USER + 57); + public const int EM_GETCHARFORMAT = (WindowMessages.WM_USER + 58); + public const int EM_GETEVENTMASK = (WindowMessages.WM_USER + 59); + public const int EM_GETOLEINTERFACE = (WindowMessages.WM_USER + 60); + public const int EM_GETPARAFORMAT = (WindowMessages.WM_USER + 61); + public const int EM_GETSELTEXT = (WindowMessages.WM_USER + 62); + public const int EM_HIDESELECTION = (WindowMessages.WM_USER + 63); + public const int EM_PASTESPECIAL = (WindowMessages.WM_USER + 64); + public const int EM_REQUESTRESIZE = (WindowMessages.WM_USER + 65); + public const int EM_SELECTIONTYPE = (WindowMessages.WM_USER + 66); + public const int EM_SETBKGNDCOLOR = (WindowMessages.WM_USER + 67); + public const int EM_SETCHARFORMAT = (WindowMessages.WM_USER + 68); + public const int EM_SETEVENTMASK = (WindowMessages.WM_USER + 69); + public const int EM_SETOLECALLBACK = (WindowMessages.WM_USER + 70); + public const int EM_SETPARAFORMAT = (WindowMessages.WM_USER + 71); + public const int EM_SETTARGETDEVICE = (WindowMessages.WM_USER + 72); + public const int EM_STREAMIN = (WindowMessages.WM_USER + 73); + public const int EM_STREAMOUT = (WindowMessages.WM_USER + 74); + public const int EM_GETTEXTRANGE = (WindowMessages.WM_USER + 75); + public const int EM_FINDWORDBREAK = (WindowMessages.WM_USER + 76); + public const int EM_SETOPTIONS = (WindowMessages.WM_USER + 77); + public const int EM_GETOPTIONS = (WindowMessages.WM_USER + 78); + public const int EM_FINDTEXTEX = (WindowMessages.WM_USER + 79); + public const int EM_GETWORDBREAKPROCEX = (WindowMessages.WM_USER + 80); + public const int EM_SETWORDBREAKPROCEX = (WindowMessages.WM_USER + 81); + + // Richedit v2.0 messages + public const int EM_SETUNDOLIMIT = (WindowMessages.WM_USER + 82); + public const int EM_REDO = (WindowMessages.WM_USER + 84); + public const int EM_CANREDO = (WindowMessages.WM_USER + 85); + public const int EM_GETUNDONAME = (WindowMessages.WM_USER + 86); + public const int EM_GETREDONAME = (WindowMessages.WM_USER + 87); + public const int EM_STOPGROUPTYPING = (WindowMessages.WM_USER + 88); + + public const int EM_SETTEXTMODE = (WindowMessages.WM_USER + 89); + public const int EM_GETTEXTMODE = (WindowMessages.WM_USER + 90); + + public const int EM_AUTOURLDETECT = (WindowMessages.WM_USER + 91); + public const int EM_GETAUTOURLDETECT = (WindowMessages.WM_USER + 92); + public const int EM_SETPALETTE = (WindowMessages.WM_USER + 93); + public const int EM_GETTEXTEX = (WindowMessages.WM_USER + 94); + public const int EM_GETTEXTLENGTHEX = (WindowMessages.WM_USER + 95); + + // Asia specific messages + public const int EM_SETPUNCTUATION = (WindowMessages.WM_USER + 100); + public const int EM_GETPUNCTUATION = (WindowMessages.WM_USER + 101); + public const int EM_SETWORDWRAPMODE = (WindowMessages.WM_USER + 102); + public const int EM_GETWORDWRAPMODE = (WindowMessages.WM_USER + 103); + public const int EM_SETIMECOLOR = (WindowMessages.WM_USER + 104); + public const int EM_GETIMECOLOR = (WindowMessages.WM_USER + 105); + public const int EM_SETIMEOPTIONS = (WindowMessages.WM_USER + 106); + public const int EM_GETIMEOPTIONS = (WindowMessages.WM_USER + 107); + public const int EM_CONVPOSITION = (WindowMessages.WM_USER + 108); + + public const int EM_SETLANGOPTIONS = (WindowMessages.WM_USER + 120); + public const int EM_GETLANGOPTIONS = (WindowMessages.WM_USER + 121); + public const int EM_GETIMECOMPMODE = (WindowMessages.WM_USER + 122); + + public const int EM_FINDTEXTW = (WindowMessages.WM_USER + 123); + public const int EM_FINDTEXTEXW = (WindowMessages.WM_USER + 124); + + // Rich TextBox 3.0 Asia msgs + public const int EM_RECONVERSION = (WindowMessages.WM_USER + 125); + public const int EM_SETIMEMODEBIAS = (WindowMessages.WM_USER + 126); + public const int EM_GETIMEMODEBIAS = (WindowMessages.WM_USER + 127); + + // BiDi Specific messages + public const int EM_SETBIDIOPTIONS = (WindowMessages.WM_USER + 200); + public const int EM_GETBIDIOPTIONS = (WindowMessages.WM_USER + 201); + + public const int EM_SETTYPOGRAPHYOPTIONS = (WindowMessages.WM_USER + 202); + public const int EM_GETTYPOGRAPHYOPTIONS = (WindowMessages.WM_USER + 203); + + // Extended TextBox style specific messages + public const int EM_SETEDITSTYLE = (WindowMessages.WM_USER + 204); + public const int EM_GETEDITSTYLE = (WindowMessages.WM_USER + 205); + + // Ole Objects Disabling message + public const int EM_SETQUERYRTFOBJ = (WindowMessages.WM_USER + 270); + + // Pegasus outline mode messages (RE 3.0) + // Outline mode message + internal const int EM_OUTLINE = Interop.WindowMessages.WM_USER + 220; + + // Message for getting and restoring scroll pos + internal const int EM_GETSCROLLPOS = Interop.WindowMessages.WM_USER + 221; + internal const int EM_SETSCROLLPOS = Interop.WindowMessages.WM_USER + 222; + + // Change fontsize in current selection by wparam + internal const int EM_SETFONTSIZE = Interop.WindowMessages.WM_USER + 223; + internal const int EM_GETZOOM = Interop.WindowMessages.WM_USER + 224; + internal const int EM_SETZOOM = Interop.WindowMessages.WM_USER + 225; + } +} \ No newline at end of file diff --git a/src/Common/src/Interop/Interop.HRESULT.cs b/src/Common/src/Interop/Interop.HRESULT.cs new file mode 100644 index 00000000000..addf249e199 --- /dev/null +++ b/src/Common/src/Interop/Interop.HRESULT.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + public static class HRESULT + { + public const int S_OK = 0; + } +} diff --git a/src/Common/src/Interop/Interop.Libraries.cs b/src/Common/src/Interop/Interop.Libraries.cs new file mode 100644 index 00000000000..bb9384e9a4b --- /dev/null +++ b/src/Common/src/Interop/Interop.Libraries.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + public static partial class Libraries + { + internal const string Kernel32 = "kernel32.dll"; + internal const string Gdi32 = "gdi32.dll"; + internal const string User32 = "user32.dll"; + internal const string Shell32 = "shell32.dll"; + } +} diff --git a/src/Common/src/Interop/Interop.WindowMessages.cs b/src/Common/src/Interop/Interop.WindowMessages.cs new file mode 100644 index 00000000000..c65205b6454 --- /dev/null +++ b/src/Common/src/Interop/Interop.WindowMessages.cs @@ -0,0 +1,225 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + public static class WindowMessages + { + public const int WM_NULL = 0x0000; + public const int WM_CREATE = 0x0001; + public const int WM_DELETEITEM = 0x002D; + public const int WM_DESTROY = 0x0002; + public const int WM_MOVE = 0x0003; + public const int WM_SIZE = 0x0005; + public const int WM_ACTIVATE = 0x0006; + public const int WM_SETFOCUS = 0x0007; + public const int WM_KILLFOCUS = 0x0008; + public const int WM_ENABLE = 0x000A; + public const int WM_SETREDRAW = 0x000B; + public const int WM_SETTEXT = 0x000C; + public const int WM_GETTEXT = 0x000D; + public const int WM_GETTEXTLENGTH = 0x000E; + public const int WM_PAINT = 0x000F; + public const int WM_CLOSE = 0x0010; + public const int WM_QUERYENDSESSION = 0x0011; + public const int WM_QUIT = 0x0012; + public const int WM_QUERYOPEN = 0x0013; + public const int WM_ERASEBKGND = 0x0014; + public const int WM_SYSCOLORCHANGE = 0x0015; + public const int WM_ENDSESSION = 0x0016; + public const int WM_SHOWWINDOW = 0x0018; + public const int WM_WININICHANGE = 0x001A; + public const int WM_SETTINGCHANGE = 0x001A; + public const int WM_DEVMODECHANGE = 0x001B; + public const int WM_ACTIVATEAPP = 0x001C; + public const int WM_FONTCHANGE = 0x001D; + public const int WM_TIMECHANGE = 0x001E; + public const int WM_CANCELMODE = 0x001F; + public const int WM_SETCURSOR = 0x0020; + public const int WM_MOUSEACTIVATE = 0x0021; + public const int WM_CHILDACTIVATE = 0x0022; + public const int WM_QUEUESYNC = 0x0023; + public const int WM_GETMINMAXINFO = 0x0024; + public const int WM_PAINTICON = 0x0026; + public const int WM_ICONERASEBKGND = 0x0027; + public const int WM_NEXTDLGCTL = 0x0028; + public const int WM_SPOOLERSTATUS = 0x002A; + public const int WM_DRAWITEM = 0x002B; + public const int WM_MEASUREITEM = 0x002C; + public const int WM_VKEYTOITEM = 0x002E; + public const int WM_CHARTOITEM = 0x002F; + public const int WM_SETFONT = 0x0030; + public const int WM_GETFONT = 0x0031; + public const int WM_SETHOTKEY = 0x0032; + public const int WM_GETHOTKEY = 0x0033; + public const int WM_QUERYDRAGICON = 0x0037; + public const int WM_COMPAREITEM = 0x0039; + public const int WM_GETOBJECT = 0x003D; + public const int WM_COMPACTING = 0x0041; + public const int WM_COMMNOTIFY = 0x0044; + public const int WM_WINDOWPOSCHANGING = 0x0046; + public const int WM_WINDOWPOSCHANGED = 0x0047; + public const int WM_POWER = 0x0048; + public const int WM_COPYDATA = 0x004A; + public const int WM_CANCELJOURNAL = 0x004B; + public const int WM_NOTIFY = 0x004E; + public const int WM_INPUTLANGCHANGEREQUEST = 0x0050; + public const int WM_INPUTLANGCHANGE = 0x0051; + public const int WM_TCARD = 0x0052; + public const int WM_HELP = 0x0053; + public const int WM_USERCHANGED = 0x0054; + public const int WM_NOTIFYFORMAT = 0x0055; + public const int WM_CONTEXTMENU = 0x007B; + public const int WM_STYLECHANGING = 0x007C; + public const int WM_STYLECHANGED = 0x007D; + public const int WM_DISPLAYCHANGE = 0x007E; + public const int WM_GETICON = 0x007F; + public const int WM_SETICON = 0x0080; + public const int WM_NCCREATE = 0x0081; + public const int WM_NCDESTROY = 0x0082; + public const int WM_NCCALCSIZE = 0x0083; + public const int WM_NCHITTEST = 0x0084; + public const int WM_NCPAINT = 0x0085; + public const int WM_NCACTIVATE = 0x0086; + public const int WM_GETDLGCODE = 0x0087; + public const int WM_NCMOUSEMOVE = 0x00A0; + public const int WM_NCMOUSELEAVE = 0x02A2; + public const int WM_NCLBUTTONDOWN = 0x00A1; + public const int WM_NCLBUTTONUP = 0x00A2; + public const int WM_NCLBUTTONDBLCLK = 0x00A3; + public const int WM_NCRBUTTONDOWN = 0x00A4; + public const int WM_NCRBUTTONUP = 0x00A5; + public const int WM_NCRBUTTONDBLCLK = 0x00A6; + public const int WM_NCMBUTTONDOWN = 0x00A7; + public const int WM_NCMBUTTONUP = 0x00A8; + public const int WM_NCMBUTTONDBLCLK = 0x00A9; + public const int WM_NCXBUTTONDOWN = 0x00AB; + public const int WM_NCXBUTTONUP = 0x00AC; + public const int WM_NCXBUTTONDBLCLK = 0x00AD; + public const int WM_KEYFIRST = 0x0100; + public const int WM_KEYDOWN = 0x0100; + public const int WM_KEYUP = 0x0101; + public const int WM_CHAR = 0x0102; + public const int WM_DEADCHAR = 0x0103; + public const int WM_CTLCOLOR = 0x0019; + public const int WM_SYSKEYDOWN = 0x0104; + public const int WM_SYSKEYUP = 0x0105; + public const int WM_SYSCHAR = 0x0106; + public const int WM_SYSDEADCHAR = 0x0107; + public const int WM_KEYLAST = 0x0108; + public const int WM_IME_STARTCOMPOSITION = 0x010D; + public const int WM_IME_ENDCOMPOSITION = 0x010E; + public const int WM_IME_COMPOSITION = 0x010F; + public const int WM_IME_KEYLAST = 0x010F; + public const int WM_INITDIALOG = 0x0110; + public const int WM_COMMAND = 0x0111; + public const int WM_SYSCOMMAND = 0x0112; + public const int WM_TIMER = 0x0113; + public const int WM_HSCROLL = 0x0114; + public const int WM_VSCROLL = 0x0115; + public const int WM_INITMENU = 0x0116; + public const int WM_INITMENUPOPUP = 0x0117; + public const int WM_MENUSELECT = 0x011F; + public const int WM_MENUCHAR = 0x0120; + public const int WM_ENTERIDLE = 0x0121; + public const int WM_UNINITMENUPOPUP = 0x0125; + public const int WM_CHANGEUISTATE = 0x0127; + public const int WM_UPDATEUISTATE = 0x0128; + public const int WM_QUERYUISTATE = 0x0129; + public const int WM_CTLCOLORMSGBOX = 0x0132; + public const int WM_CTLCOLOREDIT = 0x0133; + public const int WM_CTLCOLORLISTBOX = 0x0134; + public const int WM_CTLCOLORBTN = 0x0135; + public const int WM_CTLCOLORDLG = 0x0136; + public const int WM_CTLCOLORSCROLLBAR = 0x0137; + public const int WM_CTLCOLORSTATIC = 0x0138; + public const int WM_MOUSEFIRST = 0x0200; + public const int WM_MOUSEMOVE = 0x0200; + public const int WM_LBUTTONDOWN = 0x0201; + public const int WM_LBUTTONUP = 0x0202; + public const int WM_LBUTTONDBLCLK = 0x0203; + public const int WM_RBUTTONDOWN = 0x0204; + public const int WM_RBUTTONUP = 0x0205; + public const int WM_RBUTTONDBLCLK = 0x0206; + public const int WM_MBUTTONDOWN = 0x0207; + public const int WM_MBUTTONUP = 0x0208; + public const int WM_MBUTTONDBLCLK = 0x0209; + public const int WM_NCMOUSEHOVER = 0x02A0; + public const int WM_XBUTTONDOWN = 0x020B; + public const int WM_XBUTTONUP = 0x020C; + public const int WM_XBUTTONDBLCLK = 0x020D; + public const int WM_MOUSEWHEEL = 0x020A; + public const int WM_MOUSELAST = 0x020A; + public const int WM_PARENTNOTIFY = 0x0210; + public const int WM_ENTERMENULOOP = 0x0211; + public const int WM_EXITMENULOOP = 0x0212; + public const int WM_NEXTMENU = 0x0213; + public const int WM_SIZING = 0x0214; + public const int WM_CAPTURECHANGED = 0x0215; + public const int WM_MOVING = 0x0216; + public const int WM_POWERBROADCAST = 0x0218; + public const int WM_DEVICECHANGE = 0x0219; + public const int WM_IME_SETCONTEXT = 0x0281; + public const int WM_IME_NOTIFY = 0x0282; + public const int WM_IME_CONTROL = 0x0283; + public const int WM_IME_COMPOSITIONFULL = 0x0284; + public const int WM_IME_SELECT = 0x0285; + public const int WM_IME_CHAR = 0x0286; + public const int WM_IME_KEYDOWN = 0x0290; + public const int WM_IME_KEYUP = 0x0291; + public const int WM_MDICREATE = 0x0220; + public const int WM_MDIDESTROY = 0x0221; + public const int WM_MDIACTIVATE = 0x0222; + public const int WM_MDIRESTORE = 0x0223; + public const int WM_MDINEXT = 0x0224; + public const int WM_MDIMAXIMIZE = 0x0225; + public const int WM_MDITILE = 0x0226; + public const int WM_MDICASCADE = 0x0227; + public const int WM_MDIICONARRANGE = 0x0228; + public const int WM_MDIGETACTIVE = 0x0229; + public const int WM_MDISETMENU = 0x0230; + public const int WM_ENTERSIZEMOVE = 0x0231; + public const int WM_EXITSIZEMOVE = 0x0232; + public const int WM_DROPFILES = 0x0233; + public const int WM_MDIREFRESHMENU = 0x0234; + public const int WM_MOUSEHOVER = 0x02A1; + public const int WM_MOUSELEAVE = 0x02A3; + public const int WM_DPICHANGED = 0x02E0; + public const int WM_GETDPISCALEDSIZE = 0x02E1; + public const int WM_DPICHANGED_BEFOREPARENT = 0x02E2; + public const int WM_DPICHANGED_AFTERPARENT = 0x02E3; + public const int WM_CUT = 0x0300; + public const int WM_COPY = 0x0301; + public const int WM_PASTE = 0x0302; + public const int WM_CLEAR = 0x0303; + public const int WM_UNDO = 0x0304; + public const int WM_RENDERFORMAT = 0x0305; + public const int WM_RENDERALLFORMATS = 0x0306; + public const int WM_DESTROYCLIPBOARD = 0x0307; + public const int WM_DRAWCLIPBOARD = 0x0308; + public const int WM_PAINTCLIPBOARD = 0x0309; + public const int WM_VSCROLLCLIPBOARD = 0x030A; + public const int WM_SIZECLIPBOARD = 0x030B; + public const int WM_ASKCBFORMATNAME = 0x030C; + public const int WM_CHANGECBCHAIN = 0x030D; + public const int WM_HSCROLLCLIPBOARD = 0x030E; + public const int WM_QUERYNEWPALETTE = 0x030F; + public const int WM_PALETTEISCHANGING = 0x0310; + public const int WM_PALETTECHANGED = 0x0311; + public const int WM_HOTKEY = 0x0312; + public const int WM_PRINT = 0x0317; + public const int WM_PRINTCLIENT = 0x0318; + public const int WM_THEMECHANGED = 0x031A; + public const int WM_HANDHELDFIRST = 0x0358; + public const int WM_HANDHELDLAST = 0x035F; + public const int WM_AFXFIRST = 0x0360; + public const int WM_AFXLAST = 0x037F; + public const int WM_PENWINFIRST = 0x0380; + public const int WM_PENWINLAST = 0x038F; + public const int WM_APP = unchecked((int)0x8000); + public const int WM_USER = 0x0400; + public const int WM_REFLECT = WM_USER + 0x1C00; + public const int WM_CHOOSEFONT_GETLOGFONT = (0x0400+1); + } +} \ No newline at end of file diff --git a/src/Common/src/Interop/Kernel32/Interop.MAX_PATH.cs b/src/Common/src/Interop/Kernel32/Interop.MAX_PATH.cs new file mode 100644 index 00000000000..f7fa32669ba --- /dev/null +++ b/src/Common/src/Interop/Kernel32/Interop.MAX_PATH.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class Kernel32 + { + internal const int MAX_PATH = 260; + } +} diff --git a/src/Common/src/Interop/Kernel32/Interop.MAX_UNICODESTRING_LEN.cs b/src/Common/src/Interop/Kernel32/Interop.MAX_UNICODESTRING_LEN.cs new file mode 100644 index 00000000000..f79886c337d --- /dev/null +++ b/src/Common/src/Interop/Kernel32/Interop.MAX_UNICODESTRING_LEN.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class Kernel32 + { + internal const int MAX_UNICODESTRING_LEN = short.MaxValue; + } +} diff --git a/src/Common/src/Interop/Shell32/Interop.SHBrowseForFolder.cs b/src/Common/src/Interop/Shell32/Interop.SHBrowseForFolder.cs new file mode 100644 index 00000000000..19af10c12b0 --- /dev/null +++ b/src/Common/src/Interop/Shell32/Interop.SHBrowseForFolder.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + public static partial class Shell32 + { + [DllImport(Libraries.Shell32)] + public static extern CoTaskMemSafeHandle SHBrowseForFolderW(ref BROWSEINFO lpbi); + + public delegate int BrowseCallbackProc(IntPtr hwnd, int msg, IntPtr lParam, IntPtr lpData); + + public static class BrowseInfoFlags + { + public const uint BIF_RETURNONLYFSDIRS = 0x00000001; + public const uint BIF_DONTGOBELOWDOMAIN = 0x00000002; + public const uint BIF_RETURNFSANCESTORS = 0x00000008; + public const uint BIF_EDITBOX = 0x00000010; + public const uint BIF_NEWDIALOGSTYLE = 0x00000040; + public const uint BIF_NONEWFOLDERBUTTON = 0x00000200; + + public const uint BIF_BROWSEFORCOMPUTER = 0x00001000; + public const uint BIF_BROWSEFORPRINTER = 0x00002000; + public const uint BIF_BROWSEFOREVERYTHING = 0x00004000; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public unsafe struct BROWSEINFO + { + public IntPtr hwndOwner; + + public CoTaskMemSafeHandle pidlRoot; + + public char *pszDisplayName; + + public string lpszTitle; + + public uint ulFlags; + + public BrowseCallbackProc lpfn; + + public IntPtr lParam; + + public int iImage; + } + } +} diff --git a/src/Common/src/Interop/Shell32/Interop.SHGetKnownFolderPath.cs b/src/Common/src/Interop/Shell32/Interop.SHGetKnownFolderPath.cs new file mode 100644 index 00000000000..0947eb7fc54 --- /dev/null +++ b/src/Common/src/Interop/Shell32/Interop.SHGetKnownFolderPath.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + public static partial class Shell32 + { + [DllImport(Libraries.Shell32, CharSet = CharSet.Unicode, SetLastError = false, BestFitMapping = false, ExactSpelling = true)] + public static extern int SHGetKnownFolderPath(ref Guid rfid, uint dwFlags, IntPtr hToken, out string pszPath); + } +} diff --git a/src/Common/src/Interop/Shell32/Interop.SHGetPathFromIDListLongPath.cs b/src/Common/src/Interop/Shell32/Interop.SHGetPathFromIDListLongPath.cs new file mode 100644 index 00000000000..f3d91119478 --- /dev/null +++ b/src/Common/src/Interop/Shell32/Interop.SHGetPathFromIDListLongPath.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + public static partial class Shell32 + { + [DllImport(ExternDll.Shell32, EntryPoint = "SHGetPathFromIDListEx", ExactSpelling = true)] + private static extern bool SHGetPathFromIDListEx(IntPtr pidl, IntPtr pszPath, int cchPath, int flags); + + public static bool SHGetPathFromIDListLongPath(IntPtr pidl, out string path) + { + IntPtr pszPath = Marshal.AllocHGlobal((Interop.Kernel32.MAX_PATH + 1) * sizeof(char)); + int length = Interop.Kernel32.MAX_PATH; + try + { + if (!SHGetPathFromIDListLongPath(pidl, ref pszPath, length)) + { + path = null; + return false; + } + + path = Marshal.PtrToStringAuto(pszPath); + return true; + } + finally + { + Marshal.FreeHGlobal(pszPath); + } + } + + public unsafe static bool SHGetPathFromIDListLongPath(IntPtr pidl, ref IntPtr pszPath, int length) + { + // SHGetPathFromIDListEx is basically a helper to get IShellFolder.DisplayNameOf() with some + // extra functionally built in if the various flags are set. + + // SHGetPathFromIDListEx copies into the ouput buffer using StringCchCopyW, which truncates + // when there isn't enough space (with a terminating null) and fails. Long paths can be + // extracted by simply increasing the buffer size whenever the buffer is full. + + // To get the equivalent functionality we could call SHBindToParent on the PIDL to get IShellFolder + // and then invoke IShellFolder.DisplayNameOf directly. This would avoid long path contortions as + // we could directly convert from STRRET, calling CoTaskMemFree manually. (Presuming the type is + // STRRET_WSTR, of course. Otherwise we can just fall back to StrRetToBufW and give up for > MAX_PATH. + // Presumption is that we shouldn't be getting back ANSI results, and if we are they are likely + // some very old component that won't have a > MAX_PATH string.) + + // While we could avoid contortions and avoid intermediate buffers by invoking IShellFolder directly, + // it isn't without cost as we'd be initializing a COM wrapper (RCW) for IShellFolder. Presumably + // this is much less overhead then looping and copying to intermediate buffers before creating a string. + // Additionally, implementing this would allow us to short circuit the one caller (FolderBrowserDialog) + // who doesn't care about the path, but just wants to know that we have an IShellFolder. + while (SHGetPathFromIDListEx(pidl, pszPath, length, 0) == false) + { + if (length >= Kernel32.MAX_UNICODESTRING_LEN + || *(char*)pszPath.ToPointer() == '\0') + { + // Already at the maximum size string, or no data was copied in. Fail. + return false; + } + + // Try giving the API a larger buffer + length = length * 2; + if (length > Kernel32.MAX_UNICODESTRING_LEN) + length = Kernel32.MAX_UNICODESTRING_LEN; + + pszPath = Marshal.ReAllocHGlobal(pszPath, (IntPtr)(length * sizeof(char))); + } + + return true; + } + } +} diff --git a/src/Common/src/Interop/Shell32/Interop.SHGetSpecialFolderLocation.cs b/src/Common/src/Interop/Shell32/Interop.SHGetSpecialFolderLocation.cs new file mode 100644 index 00000000000..f79c1bbe073 --- /dev/null +++ b/src/Common/src/Interop/Shell32/Interop.SHGetSpecialFolderLocation.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + public static partial class Shell32 + { + [DllImport(Libraries.Shell32, EntryPoint = "SHGetSpecialFolderLocation", ExactSpelling = true)] + public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, out CoTaskMemSafeHandle ppidl); + } +} diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/CoTaskMemSafeHandle.cs b/src/Common/src/Microsoft/Win32/SafeHandles/CoTaskMemSafeHandle.cs new file mode 100644 index 00000000000..1f7ac1d4019 --- /dev/null +++ b/src/Common/src/Microsoft/Win32/SafeHandles/CoTaskMemSafeHandle.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Win32.SafeHandles +{ + internal sealed class CoTaskMemSafeHandle : SafeHandle + { + internal CoTaskMemSafeHandle() : base(IntPtr.Zero, true) + { + } + + public override bool IsInvalid => IsClosed || handle == IntPtr.Zero; + + protected override bool ReleaseHandle() + { + Marshal.FreeCoTaskMem(handle); + handle = IntPtr.Zero; + return true; + } + } +} diff --git a/src/Common/src/NativeMethods.cs b/src/Common/src/NativeMethods.cs index 10eb0da4654..1c01ae0a4ab 100644 --- a/src/Common/src/NativeMethods.cs +++ b/src/Common/src/NativeMethods.cs @@ -46,7 +46,6 @@ namespace System.Windows.Forms { using Accessibility; using System.Runtime.InteropServices; using System; - using System.Security.Permissions; using System.Collections; using System.Diagnostics; using System.IO; @@ -55,7 +54,8 @@ namespace System.Windows.Forms { using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.Versioning; - + using static System.Windows.Forms.NativeMethods; + /// internal static class NativeMethods { @@ -360,27 +360,7 @@ public const int CONNECT_E_NOCONNECTION = unchecked((int)0x80040200), CONNECT_E_CANNOTCONNECT = unchecked((int)0x80040202), CTRLINFO_EATS_RETURN = 1, - CTRLINFO_EATS_ESCAPE = 2, - CSIDL_DESKTOP = 0x0000, // - CSIDL_INTERNET = 0x0001, // Internet Explorer (icon on desktop) - CSIDL_PROGRAMS = 0x0002, // Start Menu\Programs - CSIDL_PERSONAL = 0x0005, // My Documents - CSIDL_FAVORITES = 0x0006, // \Favorites - CSIDL_STARTUP = 0x0007, // Start Menu\Programs\Startup - CSIDL_RECENT = 0x0008, // \Recent - CSIDL_SENDTO = 0x0009, // \SendTo - CSIDL_STARTMENU = 0x000b, // \Start Menu - CSIDL_DESKTOPDIRECTORY = 0x0010, // \Desktop - CSIDL_TEMPLATES = 0x0015, - CSIDL_APPDATA = 0x001a, // \Application Data - CSIDL_LOCAL_APPDATA = 0x001c, // \Local Settings\Applicaiton Data (non roaming) - CSIDL_INTERNET_CACHE = 0x0020, - CSIDL_COOKIES = 0x0021, - CSIDL_HISTORY = 0x0022, - CSIDL_COMMON_APPDATA = 0x0023, // All Users\Application Data - CSIDL_SYSTEM = 0x0025, // GetSystemDirectory() - CSIDL_PROGRAM_FILES = 0x0026, // C:\Program Files - CSIDL_PROGRAM_FILES_COMMON = 0x002b; // C:\Program Files\Common + CTRLINFO_EATS_ESCAPE = 2; public const int DUPLICATE = 0x06, DISPID_UNKNOWN = (-1), @@ -490,29 +470,7 @@ public const int EN_ALIGN_LTR_EC = 0x0700, EN_ALIGN_RTL_EC = 0x0701, EC_LEFTMARGIN = 0x0001, - EC_RIGHTMARGIN = 0x0002, - EM_GETSEL = 0x00B0, - EM_SETSEL = 0x00B1, - EM_SCROLL = 0x00B5, - EM_SCROLLCARET = 0x00B7, - EM_GETMODIFY = 0x00B8, - EM_SETMODIFY = 0x00B9, - EM_GETLINECOUNT = 0x00BA, - EM_REPLACESEL = 0x00C2, - EM_GETLINE = 0x00C4, - EM_LIMITTEXT = 0x00C5, - EM_CANUNDO = 0x00C6, - EM_UNDO = 0x00C7, - EM_SETPASSWORDCHAR = 0x00CC, - EM_GETPASSWORDCHAR = 0x00D2, - EM_EMPTYUNDOBUFFER = 0x00CD, - EM_SETREADONLY = 0x00CF, - EM_SETMARGINS = 0x00D3, - EM_POSFROMCHAR = 0x00D6, - EM_CHARFROMPOS = 0x00D7, - EM_LINEFROMCHAR = 0x00C9, - EM_GETFIRSTVISIBLELINE = 0x00CE, - EM_LINEINDEX = 0x00BB; + EC_RIGHTMARGIN = 0x0002; public const int ERROR_INVALID_HANDLE = 6; public const int ERROR_CLASS_ALREADY_EXISTS = 1410; @@ -975,6 +933,12 @@ public const int public const int LOCALE_IMEASURE = 0x0000000D; // 0 = metric, 1 = US + public const int TVM_SETEXTENDEDSTYLE = TV_FIRST + 44; + public const int TVM_GETEXTENDEDSTYLE = TV_FIRST + 45; + + public const int TVS_EX_FADEINOUTEXPANDOS = 0x0040; + public const int TVS_EX_DOUBLEBUFFER = 0x0004; + public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); @@ -1000,8 +964,6 @@ public static int MAKELCID(int lgid, int sort) { public const int MEMBERID_NIL = (-1), - MAX_PATH = 260, - MAX_UNICODESTRING_LEN = short.MaxValue, // maximum unicode string length ERROR_INSUFFICIENT_BUFFER = 122, //https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx MA_ACTIVATE = 0x0001, MA_ACTIVATEANDEAT = 0x0002, @@ -1094,10 +1056,10 @@ public static int MAKELCID(int lgid, int sort) { NIIF_INFO = 0x00000001, NIIF_WARNING = 0x00000002, NIIF_ERROR = 0x00000003, - NIN_BALLOONSHOW = (WM_USER + 2), - NIN_BALLOONHIDE = (WM_USER + 3), - NIN_BALLOONTIMEOUT = (WM_USER + 4), - NIN_BALLOONUSERCLICK = (WM_USER + 5), + NIN_BALLOONSHOW = (Interop.WindowMessages.WM_USER + 2), + NIN_BALLOONHIDE = (Interop.WindowMessages.WM_USER + 3), + NIN_BALLOONTIMEOUT = (Interop.WindowMessages.WM_USER + 4), + NIN_BALLOONUSERCLICK = (Interop.WindowMessages.WM_USER + 5), NFR_ANSI = 1, NFR_UNICODE = 2, NM_CLICK = ((0-0)-2), @@ -1605,7 +1567,7 @@ public static bool Failed(int hr) { TTM_POP = (0x0400 + 28), TTM_ADJUSTRECT = (0x400 + 31), TTM_SETDELAYTIME = (0x0400 + 3), - TTM_SETTITLE = (WM_USER + 33), // wParam = TTI_*, lParam = wchar* szTitle + TTM_SETTITLE = (Interop.WindowMessages.WM_USER + 33), // wParam = TTI_*, lParam = wchar* szTitle TTM_ADDTOOL = (0x0400 + 50), TTM_DELTOOL = (0x0400 + 51), TTM_NEWTOOLRECT = (0x0400 + 52), @@ -1809,265 +1771,53 @@ public static bool Failed(int hr) { VK_INSERT = 0x002D, VK_DELETE = 0x002E; - public const int WH_JOURNALPLAYBACK = 1, - WH_GETMESSAGE = 3, - WH_MOUSE = 7, - WSF_VISIBLE = 0x0001, - WM_NULL = 0x0000, - WM_CREATE = 0x0001, - WM_DELETEITEM = 0x002D, - WM_DESTROY = 0x0002, - WM_MOVE = 0x0003, - WM_SIZE = 0x0005, - WM_ACTIVATE = 0x0006, - WA_INACTIVE = 0, - WA_ACTIVE = 1, - WA_CLICKACTIVE = 2, - WM_SETFOCUS = 0x0007, - WM_KILLFOCUS = 0x0008, - WM_ENABLE = 0x000A, - WM_SETREDRAW = 0x000B, - WM_SETTEXT = 0x000C, - WM_GETTEXT = 0x000D, - WM_GETTEXTLENGTH = 0x000E, - WM_PAINT = 0x000F, - WM_CLOSE = 0x0010, - WM_QUERYENDSESSION = 0x0011, - WM_QUIT = 0x0012, - WM_QUERYOPEN = 0x0013, - WM_ERASEBKGND = 0x0014, - WM_SYSCOLORCHANGE = 0x0015, - WM_ENDSESSION = 0x0016, - WM_SHOWWINDOW = 0x0018, - WM_WININICHANGE = 0x001A, - WM_SETTINGCHANGE = 0x001A, - WM_DEVMODECHANGE = 0x001B, - WM_ACTIVATEAPP = 0x001C, - WM_FONTCHANGE = 0x001D, - WM_TIMECHANGE = 0x001E, - WM_CANCELMODE = 0x001F, - WM_SETCURSOR = 0x0020, - WM_MOUSEACTIVATE = 0x0021, - WM_CHILDACTIVATE = 0x0022, - WM_QUEUESYNC = 0x0023, - WM_GETMINMAXINFO = 0x0024, - WM_PAINTICON = 0x0026, - WM_ICONERASEBKGND = 0x0027, - WM_NEXTDLGCTL = 0x0028, - WM_SPOOLERSTATUS = 0x002A, - WM_DRAWITEM = 0x002B, - WM_MEASUREITEM = 0x002C, - WM_VKEYTOITEM = 0x002E, - WM_CHARTOITEM = 0x002F, - WM_SETFONT = 0x0030, - WM_GETFONT = 0x0031, - WM_SETHOTKEY = 0x0032, - WM_GETHOTKEY = 0x0033, - WM_QUERYDRAGICON = 0x0037, - WM_COMPAREITEM = 0x0039, - WM_GETOBJECT = 0x003D, - WM_COMPACTING = 0x0041, - WM_COMMNOTIFY = 0x0044, - WM_WINDOWPOSCHANGING = 0x0046, - WM_WINDOWPOSCHANGED = 0x0047, - WM_POWER = 0x0048, - WM_COPYDATA = 0x004A, - WM_CANCELJOURNAL = 0x004B, - WM_NOTIFY = 0x004E, - WM_INPUTLANGCHANGEREQUEST = 0x0050, - WM_INPUTLANGCHANGE = 0x0051, - WM_TCARD = 0x0052, - WM_HELP = 0x0053, - WM_USERCHANGED = 0x0054, - WM_NOTIFYFORMAT = 0x0055, - WM_CONTEXTMENU = 0x007B, - WM_STYLECHANGING = 0x007C, - WM_STYLECHANGED = 0x007D, - WM_DISPLAYCHANGE = 0x007E, - WM_GETICON = 0x007F, - WM_SETICON = 0x0080, - WM_NCCREATE = 0x0081, - WM_NCDESTROY = 0x0082, - WM_NCCALCSIZE = 0x0083, - WM_NCHITTEST = 0x0084, - WM_NCPAINT = 0x0085, - WM_NCACTIVATE = 0x0086, - WM_GETDLGCODE = 0x0087, - WM_NCMOUSEMOVE = 0x00A0, - WM_NCMOUSELEAVE = 0x02A2, - WM_NCLBUTTONDOWN = 0x00A1, - WM_NCLBUTTONUP = 0x00A2, - WM_NCLBUTTONDBLCLK = 0x00A3, - WM_NCRBUTTONDOWN = 0x00A4, - WM_NCRBUTTONUP = 0x00A5, - WM_NCRBUTTONDBLCLK = 0x00A6, - WM_NCMBUTTONDOWN = 0x00A7, - WM_NCMBUTTONUP = 0x00A8, - WM_NCMBUTTONDBLCLK = 0x00A9, - WM_NCXBUTTONDOWN = 0x00AB, - WM_NCXBUTTONUP = 0x00AC, - WM_NCXBUTTONDBLCLK = 0x00AD, - WM_KEYFIRST = 0x0100, - WM_KEYDOWN = 0x0100, - WM_KEYUP = 0x0101, - WM_CHAR = 0x0102, - WM_DEADCHAR = 0x0103, - WM_CTLCOLOR = 0x0019, - WM_SYSKEYDOWN = 0x0104, - WM_SYSKEYUP = 0x0105, - WM_SYSCHAR = 0x0106, - WM_SYSDEADCHAR = 0x0107, - WM_KEYLAST = 0x0108, - WM_IME_STARTCOMPOSITION = 0x010D, - WM_IME_ENDCOMPOSITION = 0x010E, - WM_IME_COMPOSITION = 0x010F, - WM_IME_KEYLAST = 0x010F, - WM_INITDIALOG = 0x0110, - WM_COMMAND = 0x0111, - WM_SYSCOMMAND = 0x0112, - WM_TIMER = 0x0113, - WM_HSCROLL = 0x0114, - WM_VSCROLL = 0x0115, - WM_INITMENU = 0x0116, - WM_INITMENUPOPUP = 0x0117, - WM_MENUSELECT = 0x011F, - WM_MENUCHAR = 0x0120, - WM_ENTERIDLE = 0x0121, - WM_UNINITMENUPOPUP = 0x0125, - WM_CHANGEUISTATE = 0x0127, - WM_UPDATEUISTATE = 0x0128, - WM_QUERYUISTATE = 0x0129, - WM_CTLCOLORMSGBOX = 0x0132, - WM_CTLCOLOREDIT = 0x0133, - WM_CTLCOLORLISTBOX = 0x0134, - WM_CTLCOLORBTN = 0x0135, - WM_CTLCOLORDLG = 0x0136, - WM_CTLCOLORSCROLLBAR = 0x0137, - WM_CTLCOLORSTATIC = 0x0138, - WM_MOUSEFIRST = 0x0200, - WM_MOUSEMOVE = 0x0200, - WM_LBUTTONDOWN = 0x0201, - WM_LBUTTONUP = 0x0202, - WM_LBUTTONDBLCLK = 0x0203, - WM_RBUTTONDOWN = 0x0204, - WM_RBUTTONUP = 0x0205, - WM_RBUTTONDBLCLK = 0x0206, - WM_MBUTTONDOWN = 0x0207, - WM_MBUTTONUP = 0x0208, - WM_MBUTTONDBLCLK = 0x0209, - WM_XBUTTONDOWN = 0x020B, - WM_XBUTTONUP = 0x020C, - WM_XBUTTONDBLCLK = 0x020D, - WM_MOUSEWHEEL = 0x020A, - WM_MOUSELAST = 0x020A; - - public const int WHEEL_DELTA = 120, - WM_PARENTNOTIFY = 0x0210, - WM_ENTERMENULOOP = 0x0211, - WM_EXITMENULOOP = 0x0212, - WM_NEXTMENU = 0x0213, - WM_SIZING = 0x0214, - WM_CAPTURECHANGED = 0x0215, - WM_MOVING = 0x0216, - WM_POWERBROADCAST = 0x0218, - WM_DEVICECHANGE = 0x0219, - WM_IME_SETCONTEXT = 0x0281, - WM_IME_NOTIFY = 0x0282, - WM_IME_CONTROL = 0x0283, - WM_IME_COMPOSITIONFULL = 0x0284, - WM_IME_SELECT = 0x0285, - WM_IME_CHAR = 0x0286, - WM_IME_KEYDOWN = 0x0290, - WM_IME_KEYUP = 0x0291, - WM_MDICREATE = 0x0220, - WM_MDIDESTROY = 0x0221, - WM_MDIACTIVATE = 0x0222, - WM_MDIRESTORE = 0x0223, - WM_MDINEXT = 0x0224, - WM_MDIMAXIMIZE = 0x0225, - WM_MDITILE = 0x0226, - WM_MDICASCADE = 0x0227, - WM_MDIICONARRANGE = 0x0228, - WM_MDIGETACTIVE = 0x0229, - WM_MDISETMENU = 0x0230, - WM_ENTERSIZEMOVE = 0x0231, - WM_EXITSIZEMOVE = 0x0232, - WM_DROPFILES = 0x0233, - WM_MDIREFRESHMENU = 0x0234, - WM_MOUSEHOVER = 0x02A1, - WM_MOUSELEAVE = 0x02A3, - WM_DPICHANGED = 0x02E0, - WM_GETDPISCALEDSIZE = 0x02e1, - WM_DPICHANGED_BEFOREPARENT = 0x02E2, - WM_DPICHANGED_AFTERPARENT = 0x02E3, - WM_CUT = 0x0300, - WM_COPY = 0x0301, - WM_PASTE = 0x0302, - WM_CLEAR = 0x0303, - WM_UNDO = 0x0304, - WM_RENDERFORMAT = 0x0305, - WM_RENDERALLFORMATS = 0x0306, - WM_DESTROYCLIPBOARD = 0x0307, - WM_DRAWCLIPBOARD = 0x0308, - WM_PAINTCLIPBOARD = 0x0309, - WM_VSCROLLCLIPBOARD = 0x030A, - WM_SIZECLIPBOARD = 0x030B, - WM_ASKCBFORMATNAME = 0x030C, - WM_CHANGECBCHAIN = 0x030D, - WM_HSCROLLCLIPBOARD = 0x030E, - WM_QUERYNEWPALETTE = 0x030F, - WM_PALETTEISCHANGING = 0x0310, - WM_PALETTECHANGED = 0x0311, - WM_HOTKEY = 0x0312, - WM_PRINT = 0x0317, - WM_PRINTCLIENT = 0x0318, - WM_THEMECHANGED = 0x031A, - WM_HANDHELDFIRST = 0x0358, - WM_HANDHELDLAST = 0x035F, - WM_AFXFIRST = 0x0360, - WM_AFXLAST = 0x037F, - WM_PENWINFIRST = 0x0380, - WM_PENWINLAST = 0x038F, - WM_APP = unchecked((int)0x8000), - WM_USER = 0x0400, - WM_REFLECT = NativeMethods.WM_USER + 0x1C00, - WS_OVERLAPPED = 0x00000000, - WS_POPUP = unchecked((int)0x80000000), - WS_CHILD = 0x40000000, - WS_MINIMIZE = 0x20000000, - WS_VISIBLE = 0x10000000, - WS_DISABLED = 0x08000000, - WS_CLIPSIBLINGS = 0x04000000, - WS_CLIPCHILDREN = 0x02000000, - WS_MAXIMIZE = 0x01000000, - WS_CAPTION = 0x00C00000, - WS_BORDER = 0x00800000, - WS_DLGFRAME = 0x00400000, - WS_VSCROLL = 0x00200000, - WS_HSCROLL = 0x00100000, - WS_SYSMENU = 0x00080000, - WS_THICKFRAME = 0x00040000, - WS_TABSTOP = 0x00010000, - WS_MINIMIZEBOX = 0x00020000, - WS_MAXIMIZEBOX = 0x00010000, - WS_EX_DLGMODALFRAME = 0x00000001, - WS_EX_MDICHILD = 0x00000040, - WS_EX_TOOLWINDOW = 0x00000080, - WS_EX_CLIENTEDGE = 0x00000200, - WS_EX_CONTEXTHELP = 0x00000400, - WS_EX_RIGHT = 0x00001000, - WS_EX_LEFT = 0x00000000, - WS_EX_RTLREADING = 0x00002000, - WS_EX_LEFTSCROLLBAR = 0x00004000, - WS_EX_CONTROLPARENT = 0x00010000, - WS_EX_STATICEDGE = 0x00020000, - WS_EX_APPWINDOW = 0x00040000, - WS_EX_LAYERED = 0x00080000, - WS_EX_TOPMOST = 0x00000008, - WS_EX_LAYOUTRTL = 0x00400000, - WS_EX_NOINHERITLAYOUT = 0x00100000, - WPF_SETMINPOSITION = 0x0001, - WM_CHOOSEFONT_GETLOGFONT = (0x0400+1); + public const int WH_JOURNALPLAYBACK = 1; + public const int WH_GETMESSAGE = 3; + public const int WH_MOUSE = 7; + public const int WSF_VISIBLE = 0x0001; + + public const int WA_INACTIVE = 0; + public const int WA_ACTIVE = 1; + public const int WA_CLICKACTIVE = 2; + + public const int WS_OVERLAPPED = 0x00000000; + public const int WS_POPUP = unchecked((int)0x80000000); + public const int WS_CHILD = 0x40000000; + public const int WS_MINIMIZE = 0x20000000; + public const int WS_VISIBLE = 0x10000000; + public const int WS_DISABLED = 0x08000000; + public const int WS_CLIPSIBLINGS = 0x04000000; + public const int WS_CLIPCHILDREN = 0x02000000; + public const int WS_MAXIMIZE = 0x01000000; + public const int WS_CAPTION = 0x00C00000; + public const int WS_BORDER = 0x00800000; + public const int WS_DLGFRAME = 0x00400000; + public const int WS_VSCROLL = 0x00200000; + public const int WS_HSCROLL = 0x00100000; + public const int WS_SYSMENU = 0x00080000; + public const int WS_THICKFRAME = 0x00040000; + public const int WS_TABSTOP = 0x00010000; + public const int WS_MINIMIZEBOX = 0x00020000; + public const int WS_MAXIMIZEBOX = 0x00010000; + public const int WS_EX_DLGMODALFRAME = 0x00000001; + public const int WS_EX_MDICHILD = 0x00000040; + public const int WS_EX_TOOLWINDOW = 0x00000080; + public const int WS_EX_CLIENTEDGE = 0x00000200; + public const int WS_EX_CONTEXTHELP = 0x00000400; + public const int WS_EX_RIGHT = 0x00001000; + public const int WS_EX_LEFT = 0x00000000; + public const int WS_EX_RTLREADING = 0x00002000; + public const int WS_EX_LEFTSCROLLBAR = 0x00004000; + public const int WS_EX_CONTROLPARENT = 0x00010000; + public const int WS_EX_STATICEDGE = 0x00020000; + public const int WS_EX_APPWINDOW = 0x00040000; + public const int WS_EX_LAYERED = 0x00080000; + public const int WS_EX_TOPMOST = 0x00000008; + public const int WS_EX_LAYOUTRTL = 0x00400000; + public const int WS_EX_NOINHERITLAYOUT = 0x00100000; + public const int WPF_SETMINPOSITION = 0x0001; + + public const int WHEEL_DELTA = 120; // wParam of report message WM_IME_NOTIFY (public\sdk\imm.h) public const int @@ -2188,7 +1938,7 @@ int Exec( [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] public class FONTDESC { - public int cbSizeOfStruct = Marshal.SizeOf(typeof(FONTDESC)); + public int cbSizeOfStruct = Marshal.SizeOf(); public string lpstrName; public long cySize; public short sWeight; @@ -2203,7 +1953,7 @@ public class FONTDESC { /// [StructLayout(LayoutKind.Sequential)] public class PICTDESCbmp { - internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESCbmp)); + internal int cbSizeOfStruct = Marshal.SizeOf(); internal int picType = Ole.PICTYPE_BITMAP; internal IntPtr hbitmap = IntPtr.Zero; internal IntPtr hpalette = IntPtr.Zero; @@ -2220,7 +1970,7 @@ public PICTDESCbmp(System.Drawing.Bitmap bitmap) { /// [StructLayout(LayoutKind.Sequential)] public class PICTDESCicon { - internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESCicon)); + internal int cbSizeOfStruct = Marshal.SizeOf(); internal int picType = Ole.PICTYPE_ICON; internal IntPtr hicon = IntPtr.Zero; internal int unused1 = 0; @@ -2236,7 +1986,7 @@ public PICTDESCicon(System.Drawing.Icon icon) { /// [StructLayout(LayoutKind.Sequential)] public class PICTDESCemf { - internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESCemf)); + internal int cbSizeOfStruct = Marshal.SizeOf(); internal int picType = Ole.PICTYPE_ENHMETAFILE; internal IntPtr hemf = IntPtr.Zero; internal int unused1 = 0; @@ -2278,7 +2028,7 @@ internal class SYSTEMTIMEARRAY { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class HH_AKLINK { - internal int cbStruct=Marshal.SizeOf(typeof(HH_AKLINK)); + internal int cbStruct=Marshal.SizeOf(); internal bool fReserved = false; internal string pszKeywords = null; internal string pszUrl = null; @@ -2290,7 +2040,7 @@ public class HH_AKLINK { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class HH_POPUP { - internal int cbStruct=Marshal.SizeOf(typeof(HH_POPUP)); + internal int cbStruct=Marshal.SizeOf(); internal IntPtr hinst = IntPtr.Zero; internal int idString = 0; internal IntPtr pszText; @@ -2306,7 +2056,7 @@ public class HH_POPUP { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class HH_FTS_QUERY { - internal int cbStruct = Marshal.SizeOf(typeof(HH_FTS_QUERY)); + internal int cbStruct = Marshal.SizeOf(); internal bool fUniCodeStrings = false; [MarshalAs(UnmanagedType.LPStr)] internal string pszSearchQuery = null; @@ -2320,7 +2070,7 @@ public class HH_FTS_QUERY { [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto, Pack=4)] public class MONITORINFOEX { - internal int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX)); + internal int cbSize = Marshal.SizeOf(); internal RECT rcMonitor = new RECT(); internal RECT rcWork = new RECT(); internal int dwFlags = 0; @@ -2330,7 +2080,7 @@ public class MONITORINFOEX { [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto, Pack=4)] public class MONITORINFO { - internal int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); + internal int cbSize = Marshal.SizeOf(); internal RECT rcMonitor = new RECT(); internal RECT rcWork = new RECT(); internal int dwFlags = 0; @@ -2511,7 +2261,7 @@ public class INITCOMMONCONTROLSEX { [StructLayout(LayoutKind.Sequential)] public class IMAGELISTDRAWPARAMS { - public int cbSize = Marshal.SizeOf(typeof(IMAGELISTDRAWPARAMS)); + public int cbSize = Marshal.SizeOf(); public IntPtr himl = IntPtr.Zero; public int i = 0; public IntPtr hdcDst = IntPtr.Zero; @@ -2545,7 +2295,7 @@ public class IMAGEINFO { [StructLayout(LayoutKind.Sequential)] public class TRACKMOUSEEVENT { - public int cbSize = Marshal.SizeOf(typeof(TRACKMOUSEEVENT)); + public int cbSize = Marshal.SizeOf(); public int dwFlags; public IntPtr hwndTrack; public int dwHoverTime = 100; // Never set this to field ZERO, or to HOVER_DEFAULT, ever! @@ -2645,7 +2395,7 @@ public class WNDCLASS_I { [StructLayout(LayoutKind.Sequential)] public class NONCLIENTMETRICS { - public int cbSize = Marshal.SizeOf(typeof(NONCLIENTMETRICS)); + public int cbSize = Marshal.SizeOf(); public int iBorderWidth = 0; public int iScrollWidth = 0; public int iScrollHeight = 0; @@ -2703,7 +2453,7 @@ public struct PAINTSTRUCT { [StructLayout(LayoutKind.Sequential)] public class SCROLLINFO { - public int cbSize = Marshal.SizeOf(typeof(SCROLLINFO)); + public int cbSize = Marshal.SizeOf(); public int fMask; public int nMin; public int nMax; @@ -2717,7 +2467,7 @@ public SCROLLINFO() { [StructLayout(LayoutKind.Sequential)] public class TPMPARAMS { - public int cbSize = Marshal.SizeOf(typeof(TPMPARAMS)); + public int cbSize = Marshal.SizeOf(); // rcExclude was a by-value RECT structure public int rcExclude_left; public int rcExclude_top; @@ -3035,7 +2785,7 @@ public static PICTDESC CreateIconPICTDESC(IntPtr hicon) { [StructLayout(LayoutKind.Sequential)] public sealed class tagFONTDESC { - public int cbSizeofstruct = Marshal.SizeOf(typeof(tagFONTDESC)); + public int cbSizeofstruct = Marshal.SizeOf(); [MarshalAs(UnmanagedType.LPWStr)] public string lpstrName; @@ -3061,7 +2811,7 @@ public sealed class tagFONTDESC { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class CHOOSECOLOR { - public int lStructSize = Marshal.SizeOf(typeof(CHOOSECOLOR)); //ndirect.DllLib.sizeOf(this); + public int lStructSize = Marshal.SizeOf(); //ndirect.DllLib.sizeOf(this); public IntPtr hwndOwner; public IntPtr hInstance; public int rgbResult; @@ -3181,7 +2931,7 @@ public struct TEXTMETRIC [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class NOTIFYICONDATA { - public int cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA)); + public int cbSize = Marshal.SizeOf(); public IntPtr hWnd; public int uID; public int uFlags; @@ -3202,7 +2952,7 @@ public class NOTIFYICONDATA { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class MENUITEMINFO_T { - public int cbSize = Marshal.SizeOf(typeof(MENUITEMINFO_T)); + public int cbSize = Marshal.SizeOf(); public int fMask; public int fType; public int fState; @@ -3221,7 +2971,7 @@ public class MENUITEMINFO_T [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class MENUITEMINFO_T_RW { - public int cbSize = Marshal.SizeOf(typeof(MENUITEMINFO_T_RW)); + public int cbSize = Marshal.SizeOf(); public int fMask = 0; public int fType = 0; public int fState = 0; @@ -3254,7 +3004,7 @@ public MSAAMENUINFO(string text) { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class OPENFILENAME_I { - public int lStructSize = Marshal.SizeOf(typeof(OPENFILENAME_I)); //ndirect.DllLib.sizeOf(this); + public int lStructSize = Marshal.SizeOf(); //ndirect.DllLib.sizeOf(this); public IntPtr hwndOwner; public IntPtr hInstance; public string lpstrFilter; // use embedded nulls to separate filters @@ -3262,9 +3012,9 @@ public class OPENFILENAME_I public int nMaxCustFilter = 0; public int nFilterIndex; public IntPtr lpstrFile; - public int nMaxFile = NativeMethods.MAX_PATH; + public int nMaxFile = Interop.Kernel32.MAX_PATH; public IntPtr lpstrFileTitle = IntPtr.Zero; - public int nMaxFileTitle = NativeMethods.MAX_PATH; + public int nMaxFileTitle = Interop.Kernel32.MAX_PATH; public string lpstrInitialDir; public string lpstrTitle; public int Flags; @@ -3281,7 +3031,7 @@ public class OPENFILENAME_I [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class CHOOSEFONT { - public int lStructSize = Marshal.SizeOf(typeof(CHOOSEFONT)); // ndirect.DllLib.sizeOf(this); + public int lStructSize = Marshal.SizeOf(); // ndirect.DllLib.sizeOf(this); public IntPtr hwndOwner; public IntPtr hDC; public IntPtr lpLogFont; @@ -3480,7 +3230,7 @@ public sealed class tagOleMenuGroupWidths { [StructLayout(LayoutKind.Sequential)] [Serializable] public class MSOCRINFOSTRUCT { - public int cbSize = Marshal.SizeOf(typeof(MSOCRINFOSTRUCT)); // size of MSOCRINFO structure in bytes. + public int cbSize = Marshal.SizeOf(); // size of MSOCRINFO structure in bytes. public int uIdleTimeInterval; // If olecrfNeedPeriodicIdleTime is registered // in grfcrf, component needs to perform // periodic idle time tasks during an idle phase @@ -3640,7 +3390,7 @@ public sealed class tagLOGPALETTE public sealed class tagCONTROLINFO { [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cb)*/] - public int cb = Marshal.SizeOf(typeof(tagCONTROLINFO)); + public int cb = Marshal.SizeOf(); public IntPtr hAccel; @@ -3819,11 +3569,11 @@ public object ToObject() { return (val != IntPtr.Zero); case (int)tagVT.VT_VARIANT: - VARIANT varStruct = (VARIANT)UnsafeNativeMethods.PtrToStructure(val, typeof(VARIANT)); + VARIANT varStruct = Marshal.PtrToStructure(val); return varStruct.ToObject(); + case (int)tagVT.VT_CLSID: - //Debug.Fail("PtrToStructure will not work with System.Guid..."); - Guid guid =(Guid)UnsafeNativeMethods.PtrToStructure(val, typeof(Guid)); + Guid guid = Marshal.PtrToStructure(val); return guid; case (int)tagVT.VT_FILETIME: @@ -3834,9 +3584,6 @@ public object ToObject() { throw new ArgumentException(string.Format(SR.COM2UnhandledVT, "VT_USERDEFINED")); case (int)tagVT.VT_ARRAY: - //gSAFEARRAY sa = (tagSAFEARRAY)Marshal.PtrToStructure(val), typeof(tagSAFEARRAY)); - //return GetArrayFromSafeArray(sa); - case (int)tagVT.VT_VOID: case (int)tagVT.VT_PTR: case (int)tagVT.VT_SAFEARRAY: @@ -3853,7 +3600,6 @@ public object ToObject() { case (int)tagVT.VT_BSTR_BLOB: case (int)tagVT.VT_VECTOR: case (int)tagVT.VT_BYREF: - //case (int)tagVT.VT_RESERVED: default: int iVt = this.vt; throw new ArgumentException(string.Format(SR.COM2UnhandledVT, iVt.ToString(CultureInfo.InvariantCulture))); @@ -3869,7 +3615,7 @@ private static IntPtr GetRefInt(IntPtr value) { public sealed class tagLICINFO { [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cb)*/] - public int cbLicInfo = Marshal.SizeOf(typeof(tagLICINFO)); + public int cbLicInfo = Marshal.SizeOf(); public int fRuntimeAvailable = 0; public int fLicVerified = 0; @@ -4065,7 +3811,7 @@ One can query the reg info of the active (or tracking) component at any [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class TOOLINFO_T { - public int cbSize = Marshal.SizeOf(typeof(TOOLINFO_T)); + public int cbSize = Marshal.SizeOf(); public int uFlags; public IntPtr hwnd; public IntPtr uId; @@ -4078,7 +3824,7 @@ public class TOOLINFO_T [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class TOOLINFO_TOOLTIP { - public int cbSize = Marshal.SizeOf(typeof(TOOLINFO_TOOLTIP)); + public int cbSize = Marshal.SizeOf(); public int uFlags; public IntPtr hwnd; public IntPtr uId; @@ -4341,7 +4087,7 @@ public class MEASUREITEMSTRUCT { [StructLayout(LayoutKind.Sequential)] public class HELPINFO { - public int cbSize = Marshal.SizeOf(typeof(HELPINFO)); + public int cbSize = Marshal.SizeOf(); public int iContextType = 0; public int iCtrlId = 0; public IntPtr hItemHandle = IntPtr.Zero; @@ -4504,7 +4250,7 @@ public struct NMCUSTOMDRAW { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class MCHITTESTINFO { - public int cbSize = Marshal.SizeOf(typeof(MCHITTESTINFO)); + public int cbSize = Marshal.SizeOf(); public int pt_x = 0; public int pt_y = 0; public int uHit = 0; @@ -4695,7 +4441,7 @@ public class LVCOLUMN { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] public class LVGROUP { - public uint cbSize = (uint)Marshal.SizeOf(typeof(LVGROUP)); + public uint cbSize = (uint)Marshal.SizeOf(); public uint mask; public IntPtr pszHeader; public int cchHeader; @@ -4713,7 +4459,7 @@ public override string ToString() { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class LVINSERTMARK { - public uint cbSize = (uint)Marshal.SizeOf(typeof(LVINSERTMARK)); + public uint cbSize = (uint)Marshal.SizeOf(); public int dwFlags; public int iItem; public int dwReserved = 0; @@ -4721,7 +4467,7 @@ public class LVINSERTMARK { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] public class LVTILEVIEWINFO { - public uint cbSize = (uint)Marshal.SizeOf(typeof(LVTILEVIEWINFO)); + public uint cbSize = (uint)Marshal.SizeOf(); public int dwMask; public int dwFlags; public SIZE sizeTile; @@ -4793,7 +4539,8 @@ public class NMHEADER { public int iButton = 0; public IntPtr pItem = IntPtr.Zero; // HDITEM* } - + + [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] [StructLayout(LayoutKind.Sequential)] public class MOUSEHOOKSTRUCT { // pt was a by-value POINT structure @@ -4867,7 +4614,7 @@ public class CHARRANGE [StructLayout(LayoutKind.Sequential, Pack=4)] public class CHARFORMATW { - public int cbSize = Marshal.SizeOf(typeof(CHARFORMATW)); + public int cbSize = Marshal.SizeOf(); public int dwMask; public int dwEffects; public int yHeight; @@ -4882,7 +4629,7 @@ public class CHARFORMATW [StructLayout(LayoutKind.Sequential, Pack=4)] public class CHARFORMATA { - public int cbSize = Marshal.SizeOf(typeof(CHARFORMATA)); + public int cbSize = Marshal.SizeOf(); public int dwMask; public int dwEffects; public int yHeight; @@ -4897,7 +4644,7 @@ public class CHARFORMATA [StructLayout(LayoutKind.Sequential, Pack=4)] public class CHARFORMAT2A { - public int cbSize = Marshal.SizeOf(typeof(CHARFORMAT2A)); + public int cbSize = Marshal.SizeOf(); public int dwMask = 0; public int dwEffects = 0; public int yHeight = 0; @@ -4943,7 +4690,7 @@ public class SELCHANGE { [StructLayout(LayoutKind.Sequential)] public class PARAFORMAT { - public int cbSize = Marshal.SizeOf(typeof(PARAFORMAT)); + public int cbSize = Marshal.SizeOf(); public int dwMask; public short wNumbering; public short wReserved = 0; @@ -5003,7 +4750,7 @@ public struct RGNDATAHEADER [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public class OCPFIPARAMS { - public int cbSizeOfStruct = Marshal.SizeOf(typeof(OCPFIPARAMS)); + public int cbSizeOfStruct = Marshal.SizeOf(); public IntPtr hwndOwner; public int x = 0; public int y = 0; @@ -5020,7 +4767,7 @@ public class OCPFIPARAMS public class DOCHOSTUIINFO { [MarshalAs(UnmanagedType.U4)] - public int cbSize = Marshal.SizeOf(typeof(DOCHOSTUIINFO)); + public int cbSize = Marshal.SizeOf(); [MarshalAs(UnmanagedType.I4)] public int dwFlags; [MarshalAs(UnmanagedType.I4)] @@ -5604,7 +5351,7 @@ public struct PALETTEENTRY { [StructLayout(LayoutKind.Sequential)] public struct BITMAPINFO_FLAT { - public int bmiHeader_biSize;// = Marshal.SizeOf(typeof(BITMAPINFOHEADER)); + public int bmiHeader_biSize;// = Marshal.SizeOf(); public int bmiHeader_biWidth; public int bmiHeader_biHeight; public short bmiHeader_biPlanes; @@ -5693,6 +5440,8 @@ public enum MONTCALENDAR_VIEW_MODE public const int PS_GEOMETRIC = 0x00010000; public const int PS_ENDCAP_SQUARE = 0x00000100; + public const int WS_EX_TRANSPARENT = 0x00000020; + public const int NULL_BRUSH = 5; public const int MM_HIMETRIC = 3; @@ -6009,6 +5758,76 @@ public UiaRect(System.Drawing.Rectangle r) { // This value requires KB2533623 to be installed. // Windows Server 2003 and Windows XP: This value is not supported. internal const int LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800; + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref RECT rect, int cPoints); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] POINT pt, int cPoints); + + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr WindowFromPoint(int x, int y); + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam); + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, string lParam); + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public extern static IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, [In, Out] TV_HITTESTINFO lParam); + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern short GetKeyState(int keyCode); + [DllImport(ExternDll.Gdi32, ExactSpelling = true, EntryPoint = "DeleteObject", CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + private static extern bool IntDeleteObject(IntPtr hObject); + public static bool DeleteObject(IntPtr hObject) + { + System.Internal.HandleCollector.Remove(hObject, CommonHandles.GDI); + return IntDeleteObject(hObject); + } + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern bool GetUpdateRect(IntPtr hwnd, [In, Out] ref RECT rc, bool fErase); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern bool GetUpdateRgn(IntPtr hwnd, IntPtr hrgn, bool fErase); + + [DllImport(ExternDll.Gdi32, ExactSpelling = true, EntryPoint = "CreateRectRgn", CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.Process)] + private static extern IntPtr IntCreateRectRgn(int x1, int y1, int x2, int y2); + [ResourceExposure(ResourceScope.Process)] + [ResourceConsumption(ResourceScope.Process)] + public static IntPtr CreateRectRgn(int x1, int y1, int x2, int y2) + { + return System.Internal.HandleCollector.Add(IntCreateRectRgn(x1, y1, x2, y2), CommonHandles.GDI); + } + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr GetCursor(); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern bool GetCursorPos([In, Out] POINT pt); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent); } } diff --git a/src/Common/src/SafeNativeMethods.cs b/src/Common/src/SafeNativeMethods.cs index a1e3abda3eb..58f709262a5 100644 --- a/src/Common/src/SafeNativeMethods.cs +++ b/src/Common/src/SafeNativeMethods.cs @@ -62,20 +62,20 @@ public static IntPtr CreateCompatibleBitmap(HandleRef hDC, int width, int height return System.Internal.HandleCollector.Add(IntCreateCompatibleBitmap(hDC, width, height), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool GetScrollInfo(HandleRef hWnd, int fnBar, [In, Out] NativeMethods.SCROLLINFO si); - [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool IsAccelerator(HandleRef hAccel, int cAccelEntries, [In] ref NativeMethods.MSG lpMsg, short[] lpwCmd); - [DllImport(ExternDll.Comdlg32, SetLastError=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Comdlg32, SetLastError=true, CharSet=CharSet.Auto)] public static extern bool ChooseFont([In, Out] NativeMethods.CHOOSEFONT cf); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetBitmapBits(HandleRef hbmp, int cbBuffer, byte[] lpvBits); - [DllImport(ExternDll.Comdlg32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Comdlg32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int CommDlgExtendedError(); [DllImport(ExternDll.Oleaut32, ExactSpelling=true, CharSet=CharSet.Unicode)] @@ -130,33 +130,33 @@ public static extern bool Rectangle( public static extern bool PatBlt(HandleRef hdc, int left, int top, int width, int height, int rop); - [DllImport(ExternDll.Kernel32, EntryPoint="GetThreadLocale", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, EntryPoint="GetThreadLocale", CharSet=CharSet.Auto)] public static extern int GetThreadLCID(); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetMessagePos(); - [DllImport(ExternDll.User32, SetLastError=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] public static extern int RegisterClipboardFormat(string format); - [DllImport(ExternDll.User32, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern int GetClipboardFormatName(int format, StringBuilder lpString, int cchMax); - [DllImport(ExternDll.Comdlg32, SetLastError=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Comdlg32, SetLastError=true, CharSet=CharSet.Auto)] public static extern bool ChooseColor([In, Out] NativeMethods.CHOOSECOLOR cc); - [DllImport(ExternDll.User32, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern int RegisterWindowMessage(string msg); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="DeleteObject", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="DeleteObject", CharSet=CharSet.Auto)] public static extern bool ExternalDeleteObject(HandleRef hObject); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="DeleteObject", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="DeleteObject", CharSet=CharSet.Auto)] internal static extern bool IntDeleteObject(HandleRef hObject); public static bool DeleteObject(HandleRef hObject) { @@ -168,7 +168,7 @@ public static bool DeleteObject(HandleRef hObject) { public static extern SafeNativeMethods.IFontDisp OleCreateIFontDispIndirect(NativeMethods.FONTDESC fd, ref Guid iid); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateSolidBrush", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateSolidBrush", CharSet=CharSet.Auto)] private static extern IntPtr IntCreateSolidBrush(int crColor); @@ -176,11 +176,11 @@ public static bool DeleteObject(HandleRef hObject) { public static IntPtr CreateSolidBrush(int crColor) { return System.Internal.HandleCollector.Add(IntCreateSolidBrush(crColor), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool SetWindowExtEx(HandleRef hDC, int x, int y, [In, Out] NativeMethods.SIZE size); - [DllImport(ExternDll.Kernel32, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, CharSet=CharSet.Auto)] public static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, HandleRef arguments); @@ -308,7 +308,7 @@ public static IntPtr ImageList_Read(UnsafeNativeMethods.IStream pstm) { [DllImport(ExternDll.Comctl32)] public static extern int ImageList_WriteEx(HandleRef himl, int dwFlags, UnsafeNativeMethods.IStream pstm); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool TrackPopupMenuEx(HandleRef hmenu, int fuFlags, int x, int y, HandleRef hwnd, NativeMethods.TPMPARAMS tpm); [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] @@ -341,20 +341,20 @@ public static IntPtr ImageList_Read(UnsafeNativeMethods.IStream pstm) { [DllImport(ExternDll.User32, ExactSpelling = true)] public static extern bool EnumDisplayMonitors(HandleRef hdc, NativeMethods.COMRECT rcClip, NativeMethods.MonitorEnumProc lpfnEnum, IntPtr dwData); - [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "CreateHalftonePalette", CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "CreateHalftonePalette", CharSet = CharSet.Auto)] private static extern IntPtr /*HPALETTE*/ IntCreateHalftonePalette(HandleRef hdc); public static IntPtr /*HPALETTE*/ CreateHalftonePalette(HandleRef hdc) { return System.Internal.HandleCollector.Add(IntCreateHalftonePalette(hdc), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetPaletteEntries(HandleRef hpal, int iStartIndex, int nEntries, int[] lppe); [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern int GetTextMetricsW(HandleRef hDC, ref NativeMethods.TEXTMETRIC lptm); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateDIBSection", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateDIBSection", CharSet=CharSet.Auto)] private static extern IntPtr IntCreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, byte[] ppvBits, IntPtr hSection, int dwOffset); @@ -363,7 +363,7 @@ public static IntPtr CreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, return System.Internal.HandleCollector.Add(IntCreateDIBSection(hdc, pbmi, iUsage, ppvBits, hSection, dwOffset), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBitmap", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBitmap", CharSet=CharSet.Auto)] private static extern IntPtr /*HBITMAP*/ IntCreateBitmap(int nWidth, int nHeight, int nPlanes, int nBitsPerPixel, IntPtr lpvBits); @@ -372,7 +372,7 @@ public static IntPtr CreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, return System.Internal.HandleCollector.Add(IntCreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpvBits), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBitmap", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBitmap", CharSet=CharSet.Auto)] private static extern IntPtr /*HBITMAP*/ IntCreateBitmapShort(int nWidth, int nHeight, int nPlanes, int nBitsPerPixel, short[] lpvBits); @@ -381,7 +381,7 @@ public static IntPtr CreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, return System.Internal.HandleCollector.Add(IntCreateBitmapShort(nWidth, nHeight, nPlanes, nBitsPerPixel, lpvBits), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBitmap", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBitmap", CharSet=CharSet.Auto)] private static extern IntPtr /*HBITMAP*/ IntCreateBitmapByte(int nWidth, int nHeight, int nPlanes, int nBitsPerPixel, byte[] lpvBits); @@ -389,7 +389,7 @@ public static IntPtr CreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, public static IntPtr /*HBITMAP*/ CreateBitmap(int nWidth, int nHeight, int nPlanes, int nBitsPerPixel, byte[] lpvBits) { return System.Internal.HandleCollector.Add(IntCreateBitmapByte(nWidth, nHeight, nPlanes, nBitsPerPixel, lpvBits), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreatePatternBrush", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreatePatternBrush", CharSet=CharSet.Auto)] private static extern IntPtr /*HBRUSH*/ IntCreatePatternBrush(HandleRef hbmp); @@ -397,7 +397,7 @@ public static IntPtr CreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, public static IntPtr /*HBRUSH*/ CreatePatternBrush(HandleRef hbmp) { return System.Internal.HandleCollector.Add(IntCreatePatternBrush(hbmp), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBrushIndirect", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateBrushIndirect", CharSet=CharSet.Auto)] private static extern IntPtr IntCreateBrushIndirect(NativeMethods.LOGBRUSH lb); @@ -405,7 +405,7 @@ public static IntPtr CreateDIBSection(HandleRef hdc, HandleRef pbmi, int iUsage, public static IntPtr CreateBrushIndirect(NativeMethods.LOGBRUSH lb) { return System.Internal.HandleCollector.Add(IntCreateBrushIndirect(lb), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreatePen", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreatePen", CharSet=CharSet.Auto)] private static extern IntPtr IntCreatePen(int nStyle, int nWidth, int crColor); @@ -415,26 +415,26 @@ public static IntPtr CreatePen(int nStyle, int nWidth, int crColor) { } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool SetViewportExtEx(HandleRef hDC, int x, int y, NativeMethods.SIZE size); - [DllImport(ExternDll.User32, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern IntPtr LoadCursor(HandleRef hInst, int iconId); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public extern static bool GetClipCursor([In, Out] ref NativeMethods.RECT lpRect); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr GetCursor(); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool GetIconInfo(HandleRef hIcon, [In, Out] NativeMethods.ICONINFO info); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int IntersectClipRect(HandleRef hDC, int x1, int y1, int x2, int y2); - [DllImport(ExternDll.User32, ExactSpelling=true, EntryPoint="CopyImage", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, EntryPoint="CopyImage", CharSet=CharSet.Auto)] private static extern IntPtr IntCopyImage(HandleRef hImage, int uType, int cxDesired, int cyDesired, int fuFlags); public static IntPtr CopyImage(HandleRef hImage, int uType, int cxDesired, int cyDesired, int fuFlags) { @@ -445,7 +445,7 @@ public static IntPtr CopyImageAsCursor(HandleRef hImage, int uType, int cxDesire } - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool AdjustWindowRectEx(ref NativeMethods.RECT lpRect, int dwStyle, bool bMenu, int dwExStyle); @@ -454,28 +454,33 @@ public static IntPtr CopyImageAsCursor(HandleRef hImage, int uType, int cxDesire public static extern bool AdjustWindowRectExForDpi(ref NativeMethods.RECT lpRect, int dwStyle, bool bMenu, int dwExStyle, uint dpi); - [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int DoDragDrop(IComDataObject dataObject, UnsafeNativeMethods.IOleDropSource dropSource, int allowedEffects, int[] finalEffect); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr GetSysColorBrush(int nIndex); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool EnableWindow(HandleRef hWnd, bool enable); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool GetClientRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect); [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetDoubleClickTime(); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetUpdateRgn(HandleRef hwnd, HandleRef hrgn, bool fErase); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool ValidateRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern bool ValidateRect(IntPtr hwnd, IntPtr prect); + // // WARNING: Don't uncomment this code unless you absolutelly need it. Use instead Marshal.GetLastWin32Error // and mark your PInvoke [DllImport(..., SetLastError=true)] @@ -486,36 +491,36 @@ public static IntPtr CopyImageAsCursor(HandleRef hImage, int uType, int cxDesire // definition for GetLastError and calling it. The common language runtime can make internal calls to APIs that // overwrite the operating system maintained GetLastError. // - //[DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + //[DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] //public extern static int GetLastError(); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int FillRect(HandleRef hdc, [In] ref NativeMethods.RECT rect, HandleRef hbrush); - [DllImport(ExternDll.Gdi32,ExactSpelling=true,CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32,ExactSpelling=true,CharSet=CharSet.Auto)] public static extern int /*COLORREF*/ GetTextColor(HandleRef hDC); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = CharSet.Auto)] public static extern int GetBkColor(HandleRef hDC); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int /*COLORREF*/ SetTextColor(HandleRef hDC, int crColor); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int SetBkColor(HandleRef hDC, int clr); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr /* HPALETTE */SelectPalette(HandleRef hdc, HandleRef hpal, int bForceBackground); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool SetViewportOrgEx(HandleRef hDC, int x, int y, [In, Out] NativeMethods.POINT point); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateRectRgn", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="CreateRectRgn", CharSet=CharSet.Auto)] private static extern IntPtr IntCreateRectRgn(int x1, int y1, int x2, int y2); @@ -523,60 +528,64 @@ public static IntPtr CopyImageAsCursor(HandleRef hImage, int uType, int cxDesire public static IntPtr CreateRectRgn(int x1, int y1, int x2, int y2) { return System.Internal.HandleCollector.Add(IntCreateRectRgn(x1, y1, x2, y2), NativeMethods.CommonHandles.GDI); } - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int CombineRgn(HandleRef hRgn, HandleRef hRgn1, HandleRef hRgn2, int nCombineMode); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int RealizePalette(HandleRef hDC); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool LPtoDP(HandleRef hDC, [In, Out] ref NativeMethods.RECT lpRect, int nCount); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool SetWindowOrgEx(HandleRef hDC, int x, int y, [In, Out] NativeMethods.POINT point); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool GetViewportOrgEx(HandleRef hDC, [In, Out] NativeMethods.POINT point); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int SetMapMode(HandleRef hDC, int nMapMode); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool IsWindowEnabled(HandleRef hWnd); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool IsWindowVisible(HandleRef hWnd); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool ReleaseCapture(); - [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetCurrentThreadId(); - [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)] public static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData); internal delegate bool EnumThreadWindowsCallback(IntPtr hWnd, IntPtr lParam); - [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] public static extern int GetWindowThreadProcessId(HandleRef hWnd, out int lpdwProcessId); [return:MarshalAs(UnmanagedType.Bool)] - [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto)] public static extern bool GetExitCodeThread(HandleRef hWnd, out int lpdwExitCode); - [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] public static extern bool ShowWindow(HandleRef hWnd, int nCmdShow); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy, int flags); - [DllImport(ExternDll.User32, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, + int x, int y, int cx, int cy, int flags); + + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern int GetWindowTextLength(HandleRef hWnd); // this is a wrapper that comctl exposes for the NT function since it doesn't exist natively on 95. @@ -587,114 +596,121 @@ public static bool TrackMouseEvent(NativeMethods.TRACKMOUSEEVENT tme) { // only on NT - not on 95 - comctl32 has a wrapper for 95 and NT. return _TrackMouseEvent(tme); } - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool RedrawWindow(HandleRef hwnd, ref NativeMethods.RECT rcUpdate, HandleRef hrgnUpdate, int flags); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool RedrawWindow(HandleRef hwnd, NativeMethods.COMRECT rcUpdate, HandleRef hrgnUpdate, int flags); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern bool RedrawWindow(IntPtr hwnd, NativeMethods.COMRECT rcUpdate, IntPtr hrgnUpdate, int flags); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool InvalidateRect(HandleRef hWnd, ref NativeMethods.RECT rect, bool erase); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool InvalidateRect(HandleRef hWnd, NativeMethods.COMRECT rect, bool erase); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool InvalidateRgn(HandleRef hWnd, HandleRef hrgn, bool erase); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool UpdateWindow(HandleRef hWnd); - [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetCurrentProcessId(); - [DllImport(ExternDll.User32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int ScrollWindowEx(HandleRef hWnd, int nXAmount, int nYAmount, NativeMethods.COMRECT rectScrollRegion, ref NativeMethods.RECT rectClip, HandleRef hrgnUpdate, ref NativeMethods.RECT prcUpdate, int flags); - [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetThreadLocale(); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool MessageBeep(int type); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool DrawMenuBar(HandleRef hWnd); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public extern static bool IsChild(HandleRef parent, HandleRef child); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr SetTimer(HandleRef hWnd, int nIDEvent, int uElapse, IntPtr lpTimerFunc); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool KillTimer(HandleRef hwnd, int idEvent); - [DllImport(ExternDll.User32, CharSet=System.Runtime.InteropServices.CharSet.Auto), + [DllImport(ExternDll.User32, CharSet=CharSet.Auto), SuppressMessage("Microsoft.Usage", "CA2205:UseManagedEquivalentsOfWin32Api")] public static extern int MessageBox(HandleRef hWnd, string text, string caption, int type); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr SelectObject(HandleRef hDC, HandleRef hObject); - [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetTickCount(); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool ScrollWindow(HandleRef hWnd, int nXAmount, int nYAmount, ref NativeMethods.RECT rectScrollRegion, ref NativeMethods.RECT rectClip); - [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr GetCurrentProcess(); - [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr GetCurrentThread(); [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto)] public extern static bool SetThreadLocale(int Locale); - [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] public static extern bool IsWindowUnicode(HandleRef hWnd); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool DrawEdge(HandleRef hDC, ref NativeMethods.RECT rect, int edge, int flags); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool DrawFrameControl(HandleRef hDC, ref NativeMethods.RECT rect, int type, int state); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetClipRgn(HandleRef hDC, HandleRef hRgn); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetRgnBox(HandleRef hRegion, ref NativeMethods.RECT clipRect); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int SelectClipRgn(HandleRef hDC, HandleRef hRgn); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int SetROP2(HandleRef hDC, int nDrawMode); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool DrawIcon(HandleRef hDC, int x, int y, HandleRef hIcon); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool DrawIconEx(HandleRef hDC, int x, int y, HandleRef hIcon, int width, int height, int iStepIfAniCursor, HandleRef hBrushFlickerFree, int diFlags); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int SetBkMode(HandleRef hDC, int nBkMode); - [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nHeight, HandleRef hSrcDC, int xSrc, int ySrc, int dwRop); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.Gdi32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern bool BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool ShowCaret(HandleRef hWnd); - [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern bool HideCaret(HandleRef hWnd); [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] @@ -775,11 +791,22 @@ public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nH [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] public static extern int GetThemeString(HandleRef hTheme, int iPartId, int iStateId, int iPropId, StringBuilder pszBuff, int cchMaxBuffChars); + [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] - public static extern int GetThemeDocumentationProperty([MarshalAs(UnmanagedType.LPWStr)] string pszThemeName, [MarshalAs(UnmanagedType.LPWStr)] string pszPropertyName, StringBuilder pszValueBuff, int cchMaxValChars); - [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] - + + public static class VisualStyleDocProperty + { + public const string DisplayName = "DisplayName"; + public const string Company = "Company"; + public const string Author = "Author"; + public const string Copyright = "Copyright"; + public const string Url = "Url"; + public const string Version = "Version"; + public const string Description = "Description"; + } + + [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] public static extern int GetThemeTextExtent(HandleRef hTheme, HandleRef hdc, int iPartId, int iStateId, [MarshalAs(UnmanagedType.LPWStr)] string pszText, int iCharCount, int dwTextFlags, [In] NativeMethods.COMRECT pBoundingRect, [Out] NativeMethods.COMRECT pExtentRect); [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] @@ -790,13 +817,19 @@ public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nH [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] public static extern bool IsThemeBackgroundPartiallyTransparent(HandleRef hTheme, int iPartId, int iStateId); + [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] - public static extern bool GetThemeSysBool(HandleRef hTheme, int iBoolId); - [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] - + + [DllImport(ExternDll.Uxtheme, CharSet=CharSet.Auto)] public static extern int GetThemeSysInt(HandleRef hTheme, int iIntId, ref int piValue); + public static class VisualStyleSystemProperty + { + public const int SupportsFlatMenus = 1001; + public const int MinimumColorDepth = 1301; + } + [DllImportAttribute(ExternDll.User32)] public static extern IntPtr OpenInputDesktop(int dwFlags, [MarshalAs(UnmanagedType.Bool)] bool fInherit, int dwDesiredAccess); @@ -853,6 +886,12 @@ public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nH [DllImport(ExternDll.Kernel32, SetLastError = true)] public static extern IntPtr OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); + [DllImport(ExternDll.Gdi32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern bool RoundRect(HandleRef hDC, int left, int top, int right, int bottom, int width, int height); + + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Auto)] + public extern static int SetWindowTheme(IntPtr hWnd, string subAppName, string subIdList); + internal const int PROCESS_QUERY_INFORMATION = 0x0400; internal const int PROCESS_VM_READ = 0x0010; @@ -880,7 +919,7 @@ public static int ColorToCOLORREF(Color color) { return (int)color.R | ((int)color.G << 8) | ((int)color.B << 16); } - [ComImport(), Guid("BEF6E003-A874-101A-8BBA-00AA00300CAB"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)] + [ComImport(), Guid("BEF6E003-A874-101A-8BBA-00AA00300CAB"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] public interface IFontDisp { string Name {get; set;} diff --git a/src/Common/src/UnsafeNativeMethods.cs b/src/Common/src/UnsafeNativeMethods.cs index 47d82801884..a0e9df13134 100644 --- a/src/Common/src/UnsafeNativeMethods.cs +++ b/src/Common/src/UnsafeNativeMethods.cs @@ -92,8 +92,8 @@ internal static class UnsafeNativeMethods { public static extern int ReadClassStg(HandleRef pStg, [In, Out] ref Guid pclsid); - [DllImport(ExternDll.Ole32, SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true)] - internal extern static void CoTaskMemFree(IntPtr pv); + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int GetMessageTime(); [DllImport(ExternDll.User32)] @@ -194,19 +194,9 @@ internal static bool IsVista public static extern int OleSaveToStream(IPersistStream pPersistStream, IStream pStream); - [DllImport(ExternDll.Ole32)] - - public static extern int CoGetMalloc(int dwReserved, out IMalloc pMalloc); - - /* Commenting this out until someone actually needs to use it again... - [DllImport(ExternDll.Ole32)] - public static extern int OleSetMenuDescriptor(IntPtr hOleMenu, IntPtr hWndFrame, IntPtr hWndActiveObject, IOleInPlaceFrame frame, IOleInPlaceActiveObject activeObject); - */ - - /* Commenting this out until someone actually needs to use it again... - [DllImport(ExternDll.Kernel32)] - public static extern bool IsBadReadPtr(HandleRef ptr, int size); - */ + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [ResourceExposure(ResourceScope.Process)] + public static extern int GetWindowThreadProcessId(HandleRef hWnd, out int lpdwProcessId); [DllImport(ExternDll.Comdlg32, SetLastError=true, CharSet=CharSet.Auto)] @@ -288,7 +278,7 @@ public static int DragQueryFileLongPath(HandleRef hDrop, int iFile, StringBuilde // passing null for buffer will return actual number of charectors in the file name. // So, one extra call would be suffice to avoid while loop in case of long path. int capacity = DragQueryFile(hDrop, iFile, null, 0); - if (capacity < NativeMethods.MAX_UNICODESTRING_LEN) + if (capacity < Interop.Kernel32.MAX_UNICODESTRING_LEN) { lpszFile.EnsureCapacity(capacity); resultValue = DragQueryFile(hDrop, iFile, lpszFile, capacity); @@ -435,17 +425,17 @@ public static IntPtr DuplicateHandle(HandleRef processSource, HandleRef handleSo public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length); public static StringBuilder GetModuleFileNameLongPath(HandleRef hModule) { - StringBuilder buffer = new StringBuilder(NativeMethods.MAX_PATH); + StringBuilder buffer = new StringBuilder(Interop.Kernel32.MAX_PATH); int noOfTimes = 1; int length = 0; // Iterating by allocating chunk of memory each time we find the length is not sufficient. // Performance should not be an issue for current MAX_PATH length due to this change. while (((length = GetModuleFileName(hModule, buffer, buffer.Capacity)) == buffer.Capacity) && Marshal.GetLastWin32Error() == NativeMethods.ERROR_INSUFFICIENT_BUFFER - && buffer.Capacity < NativeMethods.MAX_UNICODESTRING_LEN) + && buffer.Capacity < Interop.Kernel32.MAX_UNICODESTRING_LEN) { noOfTimes += 2; // Increasing buffer size by 520 in each iteration. - int capacity = noOfTimes * NativeMethods.MAX_PATH < NativeMethods.MAX_UNICODESTRING_LEN ? noOfTimes * NativeMethods.MAX_PATH : NativeMethods.MAX_UNICODESTRING_LEN; + int capacity = noOfTimes * Interop.Kernel32.MAX_PATH < Interop.Kernel32.MAX_UNICODESTRING_LEN ? noOfTimes * Interop.Kernel32.MAX_PATH : Interop.Kernel32.MAX_UNICODESTRING_LEN; buffer.EnsureCapacity(capacity); } buffer.Length = length; @@ -581,21 +571,21 @@ public static IntPtr GetDCEx(HandleRef hWnd, HandleRef hrgnClip, int flags) { public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] NativeMethods.LOGPEN lp); public static int GetObject(HandleRef hObject, NativeMethods.LOGPEN lp) { - return GetObject(hObject, Marshal.SizeOf(typeof(NativeMethods.LOGPEN)), lp); + return GetObject(hObject, Marshal.SizeOf(), lp); } [DllImport(ExternDll.Gdi32, SetLastError=true, CharSet=CharSet.Auto)] public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] NativeMethods.LOGBRUSH lb); public static int GetObject(HandleRef hObject, NativeMethods.LOGBRUSH lb) { - return GetObject(hObject, Marshal.SizeOf(typeof(NativeMethods.LOGBRUSH)), lb); + return GetObject(hObject, Marshal.SizeOf(), lb); } [DllImport(ExternDll.Gdi32, SetLastError=true, CharSet=CharSet.Auto)] public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] NativeMethods.LOGFONT lf); public static int GetObject(HandleRef hObject, NativeMethods.LOGFONT lp) { - return GetObject(hObject, Marshal.SizeOf(typeof(NativeMethods.LOGFONT)), lp); + return GetObject(hObject, Marshal.SizeOf(), lp); } //HPALETTE @@ -828,7 +818,12 @@ public static int SetWindowRgn(HandleRef hwnd, HandleRef hrgn, bool fRedraw) { [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, NativeMethods.LVBKIMAGE lParam); - + + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr SendMessage(IntPtr hwnd, int msg, bool wparam, int lparam); + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern int SendMessage(HandleRef hWnd, int msg, int wParam, ref NativeMethods.LVHITTESTINFO lParam); @@ -993,7 +988,11 @@ public static int SetWindowRgn(HandleRef hwnd, HandleRef hrgn, bool fRedraw) { public static extern IntPtr GetWindow(HandleRef hWnd, int uCmd); [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] - + + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd); + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr GetDlgItem(HandleRef hWnd, int nIDDlgItem); [DllImport(ExternDll.Kernel32, CharSet=CharSet.Auto)] @@ -1008,17 +1007,7 @@ public static int SetWindowRgn(HandleRef hwnd, HandleRef hrgn, bool fRedraw) { public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); - -/* - [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] - public static extern IntPtr GetProp(HandleRef hWnd, int atom); - [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] - public static extern IntPtr GetProp(HandleRef hWnd, string name); - [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] - public static extern IntPtr RemoveProp(HandleRef hWnd, short atom); - [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] - public static extern IntPtr RemoveProp(HandleRef hWnd, string propName); - */ + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern short GlobalDeleteAtom(short atom); @@ -1033,10 +1022,7 @@ public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern bool GetClassInfo(HandleRef hInst, string lpszClass, IntPtr h); -/* - [DllImport(ExternDll.Shell32, CharSet=CharSet.Auto)] - public static extern int SHGetFolderPath(HandleRef hwndOwner, int nFolder, HandleRef hToken, int dwFlags, StringBuilder lpszPath); -*/ + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int GetSystemMetrics(int nIndex); @@ -1046,6 +1032,9 @@ public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, public static extern int GetSystemMetricsForDpi(int nIndex, uint dpi); + [DllImport(ExternDll.Gdi32, CharSet = CharSet.Auto)] + public static extern bool GetTextMetrics(HandleRef hdc, NativeMethods.TEXTMETRIC tm); + /// /// Tries to get system metrics for the dpi. dpi is ignored if "GetSystemMetricsForDpi" is not available on the OS that this application is running. /// @@ -1135,6 +1124,10 @@ public static bool TrySystemParametersInfoForDpi(int nAction, int nParam, [In, O [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int RevokeDragDrop(HandleRef hwnd); + + [DllImport(ExternDll.Ole32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern int RevokeDragDrop(IntPtr hwnd); [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] public static extern bool PeekMessage([In, Out] ref NativeMethods.MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove); @@ -1161,6 +1154,11 @@ public static bool TrySystemParametersInfoForDpi(int nAction, int nParam, [In, O [DllImport(ExternDll.Oleacc, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr LresultFromObject(ref Guid refiid, IntPtr wParam, HandleRef pAcc); + + [DllImport(ExternDll.Oleacc, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.Process)] + public static extern IntPtr LresultFromObject(ref Guid refiid, IntPtr wParam, IntPtr pAcc); + [DllImport(ExternDll.Oleacc, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] public static extern int CreateStdAccessibleObject(HandleRef hWnd, int objID, ref Guid refiid, [In, Out, MarshalAs(UnmanagedType.Interface)] ref object pAcc); @@ -1185,7 +1183,11 @@ public static bool TrySystemParametersInfoForDpi(int nAction, int nParam, [In, O public static IntPtr BeginPaint(HandleRef hWnd, [In, Out, MarshalAs(UnmanagedType.LPStruct)] ref NativeMethods.PAINTSTRUCT lpPaint) { return System.Internal.HandleCollector.Add(IntBeginPaint(hWnd, ref lpPaint), NativeMethods.CommonHandles.HDC); } - + + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "BeginPaint", CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern IntPtr BeginPaint(IntPtr hWnd, [In, Out] ref NativeMethods.PAINTSTRUCT lpPaint); + [DllImport(ExternDll.User32, ExactSpelling=true, EntryPoint="EndPaint", CharSet=CharSet.Auto)] private static extern bool IntEndPaint(HandleRef hWnd, ref NativeMethods.PAINTSTRUCT lpPaint); @@ -1194,6 +1196,10 @@ public static bool EndPaint(HandleRef hWnd, [In, MarshalAs(UnmanagedType.LPStruc return IntEndPaint(hWnd, ref lpPaint); } + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "EndPaint", CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern bool EndPaint(IntPtr hWnd, ref NativeMethods.PAINTSTRUCT lpPaint); + [DllImport(ExternDll.User32, ExactSpelling=true, EntryPoint="GetDC", CharSet=CharSet.Auto)] private static extern IntPtr IntGetDC(HandleRef hWnd); @@ -1582,13 +1588,13 @@ public unsafe static NativeMethods.RECT[] GetRectsFromRegion(IntPtr hRgn) { regionRects = new NativeMethods.RECT[pRgnDataHeader->nCount]; Debug.Assert(regionDataSize == pRgnDataHeader->cbSizeOfStruct + pRgnDataHeader->nCount * pRgnDataHeader->nRgnSize); - Debug.Assert(Marshal.SizeOf(typeof(NativeMethods.RECT)) == pRgnDataHeader->nRgnSize || pRgnDataHeader->nRgnSize == 0); + Debug.Assert(Marshal.SizeOf() == pRgnDataHeader->nRgnSize || pRgnDataHeader->nRgnSize == 0); // use the header size as the offset, and cast each rect in. int rectStart = pRgnDataHeader->cbSizeOfStruct; for (int i = 0; i < pRgnDataHeader->nCount; i++) { // use some fancy pointer math to just copy the rect bits directly into the array. - regionRects[i] = *((NativeMethods.RECT*)((byte*)pBytes + rectStart + (Marshal.SizeOf(typeof(NativeMethods.RECT)) * i))); + regionRects[i] = *((NativeMethods.RECT*)((byte*)pBytes + rectStart + (Marshal.SizeOf() * i))); } } } @@ -7177,7 +7183,7 @@ int GetHelpContext( public sealed class tagQACONTAINER { [MarshalAs(UnmanagedType.U4)] - public int cbSize = Marshal.SizeOf(typeof(tagQACONTAINER)); + public int cbSize = Marshal.SizeOf(); public UnsafeNativeMethods.IOleClientSite pClientSite; @@ -7229,7 +7235,7 @@ public sealed class tagQACONTAINER public sealed class tagQACONTROL { [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cbSize)*/] - public int cbSize = Marshal.SizeOf(typeof(tagQACONTROL)); + public int cbSize = Marshal.SizeOf(); [MarshalAs(UnmanagedType.U4)/*leftover(offset=4, dwMiscStatus)*/] public int dwMiscStatus = 0; @@ -7284,272 +7290,69 @@ public interface ILegacyIAccessibleProvider { string DefaultAction { get; } } - [ComImport(), Guid("0000000A-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface ILockBytes { - - - void ReadAt( - [In, MarshalAs(UnmanagedType.U8)] - long ulOffset, - [Out] - IntPtr pv, - [In, MarshalAs(UnmanagedType.U4)] - int cb, - [Out, MarshalAs(UnmanagedType.LPArray)] - int[] pcbRead); - - - void WriteAt( - [In, MarshalAs(UnmanagedType.U8)] - long ulOffset, - - IntPtr pv, - [In, MarshalAs(UnmanagedType.U4)] - int cb, - [Out, MarshalAs(UnmanagedType.LPArray)] - int[] pcbWritten); - - - void Flush(); - - - void SetSize( - [In, MarshalAs(UnmanagedType.U8)] - long cb); - - - void LockRegion( - [In, MarshalAs(UnmanagedType.U8)] - long libOffset, - [In, MarshalAs(UnmanagedType.U8)] - long cb, - [In, MarshalAs(UnmanagedType.U4)] - int dwLockType); - - - void UnlockRegion( - [In, MarshalAs(UnmanagedType.U8)] - long libOffset, - [In, MarshalAs(UnmanagedType.U8)] - long cb, - [In, MarshalAs(UnmanagedType.U4)] - int dwLockType); - - - void Stat( - [Out] - NativeMethods.STATSTG pstatstg, - [In, MarshalAs(UnmanagedType.U4)] - int grfStatFlag); - - } - - [StructLayout(LayoutKind.Sequential)] - public class OFNOTIFY - { - // hdr was a by-value NMHDR structure - public IntPtr hdr_hwndFrom = IntPtr.Zero; - public IntPtr hdr_idFrom = IntPtr.Zero; - public int hdr_code = 0; - - public IntPtr lpOFN = IntPtr.Zero; - public IntPtr pszFile = IntPtr.Zero; - } - - internal static bool IsComObject(object o) - { - return Marshal.IsComObject(o); - } - - internal static int ReleaseComObject(object objToRelease) - { - return Marshal.ReleaseComObject(objToRelease); - } - - public static object PtrToStructure(IntPtr lparam, Type cls) { - return Marshal.PtrToStructure(lparam, cls); - } - - public static void PtrToStructure(IntPtr lparam, object data) { - Marshal.PtrToStructure(lparam, data); - } - - internal static int SizeOf(Type t) - { - return Marshal.SizeOf(t); - } - - internal static void ThrowExceptionForHR(int errorCode) + [ComImport] + [Guid("0000000A-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface ILockBytes { - Marshal.ThrowExceptionForHR(errorCode); + void ReadAt( + [In, MarshalAs(UnmanagedType.U8)] long ulOffset, + [Out] IntPtr pv, + [In, MarshalAs(UnmanagedType.U4)] int cb, + [Out, MarshalAs(UnmanagedType.LPArray)] int[] pcbRead + ); + + void WriteAt( + [In, MarshalAs(UnmanagedType.U8)] long ulOffset, + IntPtr pv, + [In, MarshalAs(UnmanagedType.U4)] int cb, + [Out, MarshalAs(UnmanagedType.LPArray)] int[] pcbWritten + ); + + void Flush(); + + void SetSize([In, MarshalAs(UnmanagedType.U8)] long cb); + + void LockRegion( + [In, MarshalAs(UnmanagedType.U8)] long libOffset, + [In, MarshalAs(UnmanagedType.U8)] long cb, + [In, MarshalAs(UnmanagedType.U4)] int dwLockType + ); + + void UnlockRegion( + [In, MarshalAs(UnmanagedType.U8)] long libOffset, + [In, MarshalAs(UnmanagedType.U8)] long cb, + [In, MarshalAs(UnmanagedType.U4)] int dwLockType + ); + + void Stat( + [Out] NativeMethods.STATSTG pstatstg, + [In, MarshalAs(UnmanagedType.U4)] int grfStatFlag + ); } - - public delegate int BrowseCallbackProc( - IntPtr hwnd, - int msg, - IntPtr lParam, - IntPtr lpData); - - [Flags] - public enum BrowseInfos + [StructLayout(LayoutKind.Sequential)] + public class OFNOTIFY { - NewDialogStyle = 0x0040, // Use the new dialog layout with the ability to resize - HideNewFolderButton = 0x0200 // Don't display the 'New Folder' button - } + // hdr was a by-value NMHDR structure + public IntPtr hdr_hwndFrom = IntPtr.Zero; + public IntPtr hdr_idFrom = IntPtr.Zero; + public int hdr_code = 0; - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - public class BROWSEINFO - { - [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - public IntPtr hwndOwner; //HWND hwndOwner; // HWND of the owner for the dialog - [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - public IntPtr pidlRoot; //LPCITEMIDLIST pidlRoot; // Root ITEMIDLIST - - // For interop purposes, send over a buffer of MAX_PATH size. - [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - public IntPtr pszDisplayName; //LPWSTR pszDisplayName; // Return display name of item selected. - - public string lpszTitle; //LPCWSTR lpszTitle; // text to go in the banner over the tree. - public int ulFlags; //UINT ulFlags; // Flags that control the return stuff - public BrowseCallbackProc lpfn; //BFFCALLBACK lpfn; // Call back pointer - [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - public IntPtr lParam; //LPARAM lParam; // extra info that's passed back in callbacks - public int iImage; //int iImage; // output var: where to return the Image index. + public IntPtr lpOFN = IntPtr.Zero; + public IntPtr pszFile = IntPtr.Zero; } [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] internal class Shell32 { - [DllImport(ExternDll.Shell32)] - - public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, ref IntPtr ppidl); - //SHSTDAPI SHGetSpecialFolderLocation(HWND hwnd, int csidl, LPITEMIDLIST *ppidl); - - [DllImport(ExternDll.Shell32, CharSet = CharSet.Auto)] - - private static extern bool SHGetPathFromIDListEx(IntPtr pidl, IntPtr pszPath, int cchPath, int flags); - //SHSTDAPI_(BOOL) SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath); - - public static bool SHGetPathFromIDListLongPath(IntPtr pidl, ref IntPtr pszPath) - { - int noOfTimes = 1; - int length = NativeMethods.MAX_PATH; - bool result = false; - - // SHGetPathFromIDListEx returns false in case of insufficient buffer. - // This method does not distinguish between insufficient memory and an error. Until we get a proper solution, - // this logic would work. In the worst case scenario, loop exits when length reaches unicode string length. - while ((result = SHGetPathFromIDListEx(pidl, pszPath, length, 0)) == false - && length < NativeMethods.MAX_UNICODESTRING_LEN) - { - string path = Marshal.PtrToStringAuto(pszPath); - - if (path.Length != 0 && path.Length < length) - break; - - noOfTimes += 2; //520 chars capacity increase in each iteration. - length = noOfTimes * length >= NativeMethods.MAX_UNICODESTRING_LEN - ? NativeMethods.MAX_UNICODESTRING_LEN : noOfTimes * length; - pszPath = Marshal.ReAllocHGlobal(pszPath, (IntPtr)((length + 1) * sizeof(char))); - } - - return result; - } - - [DllImport(ExternDll.Shell32, CharSet=CharSet.Auto)] - - public static extern IntPtr SHBrowseForFolder([In] BROWSEINFO lpbi); - //SHSTDAPI_(LPITEMIDLIST) SHBrowseForFolderW(LPBROWSEINFOW lpbi); - - [DllImport(ExternDll.Shell32)] - - public static extern int SHGetMalloc([Out, MarshalAs(UnmanagedType.LPArray)] UnsafeNativeMethods.IMalloc[] ppMalloc); - //SHSTDAPI SHGetMalloc(LPMALLOC * ppMalloc); - - [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] - [DllImport(ExternDll.Shell32, PreserveSig = true)] - - private static extern int SHGetKnownFolderPath(ref Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath); - - public static int SHGetFolderPathEx(ref Guid rfid, uint dwFlags, IntPtr hToken, StringBuilder pszPath) - { - if (IsVista) - { - IntPtr path = IntPtr.Zero; - int result = -1; - if ((result = SHGetKnownFolderPath(ref rfid, dwFlags, hToken, out path)) == NativeMethods.S_OK) - { - pszPath.Append(Marshal.PtrToStringAuto(path)); - CoTaskMemFree(path); - } - return result; - } - throw new NotSupportedException(); - } - [DllImport(ExternDll.Shell32, PreserveSig = true)] - public static extern int SHCreateShellItem(IntPtr pidlParent, IntPtr psfParent, IntPtr pidl, out FileDialogNative.IShellItem ppsi); [DllImport(ExternDll.Shell32, PreserveSig = true)] - public static extern int SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut); } - [ - ComImport(), - Guid("00000002-0000-0000-c000-000000000046"), - System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)] - public interface IMalloc - { - [PreserveSig] - IntPtr Alloc(int cb); - - [PreserveSig] - IntPtr Realloc(IntPtr pv, int cb); - - [PreserveSig] - void Free(IntPtr pv); - - [PreserveSig] - int GetSize(IntPtr pv); - - [PreserveSig] - int DidAlloc(IntPtr pv); - - [PreserveSig] - void HeapMinimize(); - } - - [ - ComImport, - Guid("00000126-0000-0000-C000-000000000046"), - InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown) - ] - public interface IRunnableObject - { - void GetRunningClass(out Guid guid); - - [PreserveSig] - int Run(IntPtr lpBindContext); - bool IsRunning(); - void LockRunning(bool fLock, bool fLastUnlockCloses); - void SetContainedObject(bool fContained); - } - - [ComVisible(true), ComImport(), Guid("B722BCC7-4E68-101B-A2BC-00AA00404770"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOleDocumentSite - { - - [return: MarshalAs(UnmanagedType.I4)] - [PreserveSig] - int ActivateMe( - [In, MarshalAs(UnmanagedType.Interface)] - IOleDocumentView pViewToActivate); - - } - [ComVisible(true), Guid("B722BCC6-4E68-101B-A2BC-00AA00404770"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IOleDocumentView { @@ -8039,7 +7842,7 @@ public static bool CreateActivationContext(string dllPath, int nativeResourceMan enableThemingActivationContext = new ACTCTX(); - enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX)); + enableThemingActivationContext.cbSize = Marshal.SizeOf(); enableThemingActivationContext.lpSource = dllPath; enableThemingActivationContext.lpResourceName = (IntPtr)nativeResourceManifestID; enableThemingActivationContext.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; @@ -8325,16 +8128,10 @@ public interface IRawElementProviderHwndOverride : IRawElementProviderSimple { IRawElementProviderSimple GetOverrideProviderForHwnd(IntPtr hwnd); } - /// - /// Critical:Elevates to Unmanaged code permission - /// [ComImport()] [Guid("6D5140C1-7436-11CE-8034-00AA006009FA")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] internal interface IServiceProvider { - /// - /// Critical elevates via a SUC. - /// [PreserveSig] int QueryService(ref Guid service, ref Guid riid, out IntPtr ppvObj); } diff --git a/src/Common/tests/CommonTestHelper.cs b/src/Common/tests/CommonTestHelper.cs index d864defb9d4..869e3106b53 100644 --- a/src/Common/tests/CommonTestHelper.cs +++ b/src/Common/tests/CommonTestHelper.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Design.Serialization; using System.Drawing; +using System.Drawing.Text; using System.Linq; using System.Windows.Forms; using Xunit; @@ -166,6 +168,14 @@ public static TheoryData GetNullOrEmptyStringTheoryData() return data; } + public static TheoryData GetCharTheoryData() + { + var data = new TheoryData(); + data.Add('\0'); + data.Add('a'); + return data; + } + public static TheoryData GetIntPtrTheoryData() { var data = new TheoryData(); @@ -192,6 +202,22 @@ public static TheoryData GetColorWithEmptyTheoryData() return data; } + public static TheoryData GetImageTheoryData() + { + var data = new TheoryData(); + data.Add(new Bitmap(10, 10)); + data.Add(null); + return data; + } + + public static TheoryData GetFontTheoryData() + { + var data = new TheoryData(); + data.Add(SystemFonts.MenuFont); + data.Add(null); + return data; + } + public static TheoryData GetTypeWithNullTheoryData() { var data = new TheoryData(); @@ -209,12 +235,49 @@ public static TheoryData GetRightToLeftTheoryData() return data; } - public static TheoryData GetSizeTheoryData() + public static TheoryData GetPointTheoryData() => GetPointTheoryData(TestIncludeType.All); + + public static TheoryData GetPointTheoryData(TestIncludeType includeType) + { + var data = new TheoryData(); + if (!includeType.HasFlag(TestIncludeType.NoPositives)) + { + data.Add(new Point()); + data.Add(new Point(10)); + data.Add(new Point(1, 2)); + } + if (!includeType.HasFlag(TestIncludeType.NoNegatives)) + { + data.Add(new Point(int.MaxValue, int.MinValue)); + data.Add(new Point(-1, -2)); + } + return data; + } + + public static TheoryData GetSizeTheoryData() => GetSizeTheoryData(TestIncludeType.All); + + public static TheoryData GetSizeTheoryData(TestIncludeType includeType) + { + var data = new TheoryData(); + if (!includeType.HasFlag(TestIncludeType.NoPositives)) + { + data.Add(new Size()); + data.Add(new Size(new Point(1,1))); + data.Add(new Size(1, 2)); + } + if (!includeType.HasFlag(TestIncludeType.NoNegatives)) + { + data.Add(new Size(-1, 1)); + data.Add(new Size(1, -1)); + } + return data; + } + + public static TheoryData GetPositiveSizeTheoryData() { var data = new TheoryData(); data.Add(new Size()); data.Add(new Size(1, 2)); - data.Add(new Size(-1, -2)); return data; } @@ -251,13 +314,29 @@ public static TheoryData GetConvertFromTheoryData() { var data = new TheoryData(); data.Add(typeof(bool), false); - data.Add(typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor), true); + data.Add(typeof(InstanceDescriptor), true); data.Add(typeof(int), false); data.Add(typeof(double), false); data.Add(null, false); return data; } + public static TheoryData GetCursorTheoryData() + { + var data = new TheoryData(); + data.Add(null); + data.Add(new Cursor((IntPtr)1)); + return data; + } + #endregion } + + [Flags] + public enum TestIncludeType + { + All, + NoPositives, + NoNegatives + } } diff --git a/src/System.Windows.Forms.Design.Editors/src/Misc/DpiHelper.cs b/src/System.Windows.Forms.Design.Editors/src/Misc/DpiHelper.cs index cbbf420dae9..8b16375a57c 100644 --- a/src/System.Windows.Forms.Design.Editors/src/Misc/DpiHelper.cs +++ b/src/System.Windows.Forms.Design.Editors/src/Misc/DpiHelper.cs @@ -7,14 +7,11 @@ using System.Drawing.Drawing2D; using System.Runtime.InteropServices; -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE using System.Windows.Forms.Internal; using CAPS = System.Windows.Forms.NativeMethods; #elif DRAWING_NAMESPACE using CAPS = System.Drawing.SafeNativeMethods; -#elif DRAWINGDESIGN_NAMESPACE -using System.Drawing.Design; -using CAPS = System.Drawing.Design.NativeMethods; #else using System.Windows.Forms.Design; using CAPS = System.Windows.Forms.Design.NativeMethods; @@ -85,7 +82,7 @@ private static void Initialize() if (enableHighDpi) { -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE try { if (!DpiHelper.SetWinformsApplicationDpiAwareness()) @@ -557,7 +554,7 @@ public static void ScaleBitmapLogicalToDevice(ref Bitmap logicalBitmap, int devi // This method is used only in System.Design, thus excluding the rest. // This is particularly important for System.Drawing, which should not depend // on System.Windows.Forms assembly, where "Button" type is defined. -#if (!DRAWING_NAMESPACE && !DRAWINGDESIGN_NAMESPACE && !WINFORMS_NAMESPACE) +#if (!DRAWING_NAMESPACE && !DRAWING_DESIGN_NAMESPACE) /// /// Create a new button bitmap scaled for the device units. /// Note: original image might be disposed. diff --git a/src/System.Windows.Forms.Design.Editors/src/Misc/NativeMethods.cs b/src/System.Windows.Forms.Design.Editors/src/Misc/NativeMethods.cs index 8546f505ae5..960058d95e3 100644 --- a/src/System.Windows.Forms.Design.Editors/src/Misc/NativeMethods.cs +++ b/src/System.Windows.Forms.Design.Editors/src/Misc/NativeMethods.cs @@ -47,36 +47,27 @@ public class TEXTMETRIC // Investigate removing this if the duplicate code in OleDragDropHandler.cs is removed public const int HOLLOW_BRUSH = 5; - public const int WM_USER = 0x0400, - WM_CLOSE = 0x0010, - WM_GETDLGCODE = 0x0087, - WM_MOUSEMOVE = 0x0200, - WM_NOTIFY = 0x004E, - DLGC_WANTALLKEYS = 0x0004, - NM_CLICK = 0 - 0 - 2, - WM_REFLECT = WM_USER + 0x1C00, - BM_SETIMAGE = 0x00F7, - IMAGE_ICON = 1, - WM_DESTROY = 0x0002, - BS_ICON = 0x00000040, - EM_SETMARGINS = 0x00D3, - EC_LEFTMARGIN = 0x0001, - EC_RIGHTMARGIN = 0x0002, - IDOK = 1, - WM_INITDIALOG = 0x0110; + public const int DLGC_WANTALLKEYS = 0x0004; + public const int NM_CLICK = 0 - 0 - 2; + public const int BM_SETIMAGE = 0x00F7; + public const int IMAGE_ICON = 1; + public const int BS_ICON = 0x00000040; + public const int EC_LEFTMARGIN = 0x0001; + public const int EC_RIGHTMARGIN = 0x0002; + public const int IDOK = 1; + public const int VK_PROCESSKEY = 0xE5; - public const int STGM_READ = 0x00000000, - STGM_WRITE = 0x00000001, - STGM_READWRITE = 0x00000002, - STGM_SHARE_EXCLUSIVE = 0x00000010, - STGM_CREATE = 0x00001000, - STGM_TRANSACTED = 0x00010000, - STGM_CONVERT = 0x00020000, - WM_COMMAND = 0x0111, - CC_FULLOPEN = 0x00000002, - CC_ENABLETEMPLATEHANDLE = 0x00000040, - STGM_DELETEONRELEASE = 0x04000000; + public const int STGM_READ = 0x00000000; + public const int STGM_WRITE = 0x00000001; + public const int STGM_READWRITE = 0x00000002; + public const int STGM_SHARE_EXCLUSIVE = 0x00000010; + public const int STGM_CREATE = 0x00001000; + public const int STGM_TRANSACTED = 0x00010000; + public const int STGM_CONVERT = 0x00020000; + public const int CC_FULLOPEN = 0x00000002; + public const int CC_ENABLETEMPLATEHANDLE = 0x00000040; + public const int STGM_DELETEONRELEASE = 0x04000000; public const int RECO_PASTE = 0x00000000; // paste from clipboard public const int RECO_DROP = 0x00000001; // drop @@ -208,7 +199,7 @@ public enum TabControlHitTest [StructLayout(LayoutKind.Sequential)] public class TRACKMOUSEEVENT { - public readonly int cbSize = Marshal.SizeOf(typeof(TRACKMOUSEEVENT)); + public readonly int cbSize = Marshal.SizeOf(); public readonly int dwFlags; public readonly int dwHoverTime = 0; public readonly IntPtr hwndTrack; @@ -253,9 +244,6 @@ public const int PM_NOREMOVE = 0x0000, PM_REMOVE = 0x0001; - public const int - WM_CHAR = 0x0102; - [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] [StructLayout(LayoutKind.Sequential)] public struct MOUSEHOOKSTRUCT @@ -764,19 +752,6 @@ void OnShowWindow( void RequestNewObjectLayout(); } - [ComVisible(true)] - [ComImport] - [Guid("B722BCC7-4E68-101B-A2BC-00AA00404770")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOleDocumentSite - { - [return: MarshalAs(UnmanagedType.I4)] - [PreserveSig] - int ActivateMe( - [In] [MarshalAs(UnmanagedType.Interface)] - IOleDocumentView pViewToActivate); - } - [ComVisible(true)] [ComImport] [Guid("B722BCC6-4E68-101B-A2BC-00AA00404770")] @@ -3608,294 +3583,223 @@ void SetNodeValue( public static readonly int WM_MOUSEENTER = Util.RegisterWindowMessage("WinFormsMouseEnter"); public static readonly int HDN_ENDTRACK = HDN_ENDTRACKW; - public const int - DT_CALCRECT = 0x00000400, - WM_CAPTURECHANGED = 0x0215, - WM_PARENTNOTIFY = 0x0210, - WM_CREATE = 0x0001, - WM_SETREDRAW = 0x000B, - WM_NCACTIVATE = 0x0086, - WM_HSCROLL = 0x0114, - WM_VSCROLL = 0x0115, - WM_SHOWWINDOW = 0x0018, - WM_WINDOWPOSCHANGING = 0x0046, - WM_WINDOWPOSCHANGED = 0x0047, - WS_DISABLED = 0x08000000, - WS_CLIPSIBLINGS = 0x04000000, - WS_CLIPCHILDREN = 0x02000000, - WS_EX_TOOLWINDOW = 0x00000080, - WS_POPUP = unchecked((int)0x80000000), - WS_BORDER = 0x00800000, - CS_DROPSHADOW = 0x00020000, - CS_DBLCLKS = 0x0008, - NOTSRCCOPY = 0x00330008, - SRCCOPY = 0x00CC0020, - LVM_SETCOLUMNWIDTH = 0x1000 + 30, - LVM_GETHEADER = 0x1000 + 31, - LVM_CREATEDRAGIMAGE = 0x1000 + 33, - LVM_GETVIEWRECT = 0x1000 + 34, - LVM_GETTEXTCOLOR = 0x1000 + 35, - LVM_SETTEXTCOLOR = 0x1000 + 36, - LVM_GETTEXTBKCOLOR = 0x1000 + 37, - LVM_SETTEXTBKCOLOR = 0x1000 + 38, - LVM_GETTOPINDEX = 0x1000 + 39, - LVM_GETCOUNTPERPAGE = 0x1000 + 40, - LVM_GETORIGIN = 0x1000 + 41, - LVM_UPDATE = 0x1000 + 42, - LVM_SETITEMSTATE = 0x1000 + 43, - LVM_GETITEMSTATE = 0x1000 + 44, - LVM_GETITEMTEXTA = 0x1000 + 45, - LVM_GETITEMTEXTW = 0x1000 + 115, - LVM_SETITEMTEXTA = 0x1000 + 46, - LVM_SETITEMTEXTW = 0x1000 + 116, - LVSICF_NOINVALIDATEALL = 0x00000001, - LVSICF_NOSCROLL = 0x00000002, - LVM_SETITEMCOUNT = 0x1000 + 47, - LVM_SORTITEMS = 0x1000 + 48, - LVM_SETITEMPOSITION32 = 0x1000 + 49, - LVM_GETSELECTEDCOUNT = 0x1000 + 50, - LVM_GETITEMSPACING = 0x1000 + 51, - LVM_GETISEARCHSTRINGA = 0x1000 + 52, - LVM_GETISEARCHSTRINGW = 0x1000 + 117, - LVM_SETICONSPACING = 0x1000 + 53, - LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1000 + 54, - LVM_GETEXTENDEDLISTVIEWSTYLE = 0x1000 + 55, - LVS_EX_GRIDLINES = 0x00000001, - HDM_HITTEST = 0x1200 + 6, - HDM_GETITEMRECT = 0x1200 + 7, - HDM_SETIMAGELIST = 0x1200 + 8, - HDM_GETIMAGELIST = 0x1200 + 9, - HDM_ORDERTOINDEX = 0x1200 + 15, - HDM_CREATEDRAGIMAGE = 0x1200 + 16, - HDM_GETORDERARRAY = 0x1200 + 17, - HDM_SETORDERARRAY = 0x1200 + 18, - HDM_SETHOTDIVIDER = 0x1200 + 19, - HDN_ITEMCHANGINGA = 0 - 300 - 0, - HDN_ITEMCHANGINGW = 0 - 300 - 20, - HDN_ITEMCHANGEDA = 0 - 300 - 1, - HDN_ITEMCHANGEDW = 0 - 300 - 21, - HDN_ITEMCLICKA = 0 - 300 - 2, - HDN_ITEMCLICKW = 0 - 300 - 22, - HDN_ITEMDBLCLICKA = 0 - 300 - 3, - HDN_ITEMDBLCLICKW = 0 - 300 - 23, - HDN_DIVIDERDBLCLICKA = 0 - 300 - 5, - HDN_DIVIDERDBLCLICKW = 0 - 300 - 25, - HDN_BEGINTRACKA = 0 - 300 - 6, - HDN_BEGINTRACKW = 0 - 300 - 26, - HDN_ENDTRACKA = 0 - 300 - 7, - HDN_ENDTRACKW = 0 - 300 - 27, - HDN_TRACKA = 0 - 300 - 8, - HDN_TRACKW = 0 - 300 - 28, - HDN_GETDISPINFOA = 0 - 300 - 9, - HDN_GETDISPINFOW = 0 - 300 - 29, - HDN_BEGINDRAG = 0 - 300 - 10, - HDN_ENDDRAG = 0 - 300 - 11, - HC_ACTION = 0, - HIST_BACK = 0, - HHT_ONHEADER = 0x0002, - HHT_ONDIVIDER = 0x0004, - HHT_ONDIVOPEN = 0x0008, - HHT_ABOVE = 0x0100, - HHT_BELOW = 0x0200, - HHT_TORIGHT = 0x0400, - HHT_TOLEFT = 0x0800, - HWND_TOP = 0, - HWND_BOTTOM = 1, - HWND_TOPMOST = -1, - HWND_NOTOPMOST = -2, - CWP_SKIPINVISIBLE = 0x0001, - RDW_FRAME = 0x0400, - WM_KILLFOCUS = 0x0008, - WM_STYLECHANGED = 0x007D, - TVM_GETITEMRECT = 0x1100 + 4, - TVM_GETCOUNT = 0x1100 + 5, - TVM_GETINDENT = 0x1100 + 6, - TVM_SETINDENT = 0x1100 + 7, - TVM_GETIMAGELIST = 0x1100 + 8, - TVSIL_NORMAL = 0, - TVSIL_STATE = 2, - TVM_SETIMAGELIST = 0x1100 + 9, - TVM_GETNEXTITEM = 0x1100 + 10, - TVGN_ROOT = 0x0000, - TV_FIRST = 0x1100, - TVM_SETEXTENDEDSTYLE = TV_FIRST + 44, - TVM_GETEXTENDEDSTYLE = TV_FIRST + 45, - TVS_EX_FADEINOUTEXPANDOS = 0x0040, - TVS_EX_DOUBLEBUFFER = 0x0004, - LVS_EX_DOUBLEBUFFER = 0x00010000, - TVHT_ONITEMICON = 0x0002, - TVHT_ONITEMLABEL = 0x0004, - TVHT_ONITEMINDENT = 0x0008, - TVHT_ONITEMBUTTON = 0x0010, - TVHT_ONITEMRIGHT = 0x0020, - TVHT_ONITEMSTATEICON = 0x0040, - TVHT_ABOVE = 0x0100, - TVHT_BELOW = 0x0200, - TVHT_TORIGHT = 0x0400, - TVHT_TOLEFT = 0x0800, - GW_HWNDFIRST = 0, - GW_HWNDLAST = 1, - GW_HWNDNEXT = 2, - GW_HWNDPREV = 3, - GW_OWNER = 4, - GW_CHILD = 5, - GW_MAX = 5, - GWL_HWNDPARENT = -8, - SB_HORZ = 0, - SB_VERT = 1, - SB_CTL = 2, - SB_BOTH = 3, - SB_LINEUP = 0, - SB_LINELEFT = 0, - SB_LINEDOWN = 1, - SB_LINERIGHT = 1, - SB_PAGEUP = 2, - SB_PAGELEFT = 2, - SB_PAGEDOWN = 3, - SB_PAGERIGHT = 3, - SB_THUMBPOSITION = 4, - SB_THUMBTRACK = 5, - SB_TOP = 6, - SB_LEFT = 6, - SB_BOTTOM = 7, - SB_RIGHT = 7, - SB_ENDSCROLL = 8, - MK_LBUTTON = 0x0001, - TVM_HITTEST = 0x1100 + 17, - MK_RBUTTON = 0x0002, - MK_SHIFT = 0x0004, - MK_CONTROL = 0x0008, - MK_MBUTTON = 0x0010, - MK_XBUTTON1 = 0x0020, - MK_XBUTTON2 = 0x0040, - LB_ADDSTRING = 0x0180, - LB_INSERTSTRING = 0x0181, - LB_DELETESTRING = 0x0182, - LB_SELITEMRANGEEX = 0x0183, - LB_RESETCONTENT = 0x0184, - LB_SETSEL = 0x0185, - LB_SETCURSEL = 0x0186, - LB_GETSEL = 0x0187, - LB_GETCURSEL = 0x0188, - LB_GETTEXT = 0x0189, - LB_GETTEXTLEN = 0x018A, - LB_GETCOUNT = 0x018B, - LB_SELECTSTRING = 0x018C, - LB_DIR = 0x018D, - LB_GETTOPINDEX = 0x018E, - LB_FINDSTRING = 0x018F, - LB_GETSELCOUNT = 0x0190, - LB_GETSELITEMS = 0x0191, - LB_SETTABSTOPS = 0x0192, - LB_GETHORIZONTALEXTENT = 0x0193, - LB_SETHORIZONTALEXTENT = 0x0194, - LB_SETCOLUMNWIDTH = 0x0195, - LB_ADDFILE = 0x0196, - LB_SETTOPINDEX = 0x0197, - LB_GETITEMRECT = 0x0198, - LB_GETITEMDATA = 0x0199, - LB_SETITEMDATA = 0x019A, - LB_SELITEMRANGE = 0x019B, - LB_SETANCHORINDEX = 0x019C, - LB_GETANCHORINDEX = 0x019D, - LB_SETCARETINDEX = 0x019E, - LB_GETCARETINDEX = 0x019F, - LB_SETITEMHEIGHT = 0x01A0, - LB_GETITEMHEIGHT = 0x01A1, - LB_FINDSTRINGEXACT = 0x01A2, - LB_SETLOCALE = 0x01A5, - LB_GETLOCALE = 0x01A6, - LB_SETCOUNT = 0x01A7, - LB_INITSTORAGE = 0x01A8, - LB_ITEMFROMPOINT = 0x01A9, - LB_MSGMAX = 0x01B0, - HTHSCROLL = 6, - HTVSCROLL = 7, - HTERROR = -2, - HTTRANSPARENT = -1, - HTNOWHERE = 0, - HTCLIENT = 1, - HTCAPTION = 2, - HTSYSMENU = 3, - HTGROWBOX = 4, - HTSIZE = 4, - PRF_NONCLIENT = 0x00000002, - PRF_CLIENT = 0x00000004, - PRF_ERASEBKGND = 0x00000008, - PRF_CHILDREN = 0x00000010, - SWP_NOSIZE = 0x0001, - SWP_NOMOVE = 0x0002, - SWP_NOZORDER = 0x0004, - SWP_NOREDRAW = 0x0008, - SWP_NOACTIVATE = 0x0010, - SWP_FRAMECHANGED = 0x0020, - SWP_SHOWWINDOW = 0x0040, - SWP_HIDEWINDOW = 0x0080, - SWP_NOCOPYBITS = 0x0100, - SWP_NOOWNERZORDER = 0x0200, - SWP_NOSENDCHANGING = 0x0400, - SWP_DRAWFRAME = 0x0020, - SWP_NOREPOSITION = 0x0200, - SWP_DEFERERASE = 0x2000, - SWP_ASYNCWINDOWPOS = 0x4000, - WA_INACTIVE = 0, - WA_ACTIVE = 1, - WH_MOUSE = 7, - WM_IME_STARTCOMPOSITION = 0x010D, - WM_IME_ENDCOMPOSITION = 0x10E, - WM_IME_COMPOSITION = 0x010F, - WM_ACTIVATE = 0x0006, - WM_NCMOUSEMOVE = 0x00A0, - WM_NCLBUTTONDOWN = 0x00A1, - WM_NCLBUTTONUP = 0x00A2, - WM_NCLBUTTONDBLCLK = 0x00A3, - WM_NCRBUTTONDOWN = 0x00A4, - WM_NCRBUTTONUP = 0x00A5, - WM_NCRBUTTONDBLCLK = 0x00A6, - WM_NCMBUTTONDOWN = 0x00A7, - WM_NCMBUTTONUP = 0x00A8, - WM_NCMBUTTONDBLCLK = 0x00A9, - WM_NCXBUTTONDOWN = 0x00AB, - WM_NCXBUTTONUP = 0x00AC, - WM_NCXBUTTONDBLCLK = 0x00AD, - WM_MOUSEHOVER = 0x02A1, - WM_MOUSELEAVE = 0x02A3, - WM_MOUSEFIRST = 0x0200, - WM_MOUSEACTIVATE = 0x0021, - WM_LBUTTONDOWN = 0x0201, - WM_LBUTTONUP = 0x0202, - WM_LBUTTONDBLCLK = 0x0203, - WM_RBUTTONDOWN = 0x0204, - WM_RBUTTONUP = 0x0205, - WM_RBUTTONDBLCLK = 0x0206, - WM_MBUTTONDOWN = 0x0207, - WM_MBUTTONUP = 0x0208, - WM_MBUTTONDBLCLK = 0x0209, - WM_NCMOUSEHOVER = 0x02A0, - WM_NCMOUSELEAVE = 0x02A2, - WM_MOUSEWHEEL = 0x020A, - WM_MOUSELAST = 0x020A, - WM_NCHITTEST = 0x0084, - WM_SETCURSOR = 0x0020, - WM_GETOBJECT = 0x003D, - WM_CANCELMODE = 0x001F, - WM_SETFOCUS = 0x0007, - WM_KEYFIRST = 0x0100, - WM_KEYDOWN = 0x0100, - WM_KEYUP = 0x0101, - WM_DEADCHAR = 0x0103, - WM_SYSKEYDOWN = 0x0104, - WM_SYSKEYUP = 0x0105, - WM_SYSCHAR = 0x0106, - WM_SYSDEADCHAR = 0x0107, - WM_KEYLAST = 0x0108, - WM_CONTEXTMENU = 0x007B, - WM_PAINT = 0x000F, - WM_PRINTCLIENT = 0x0318, - WM_NCPAINT = 0x0085, - WM_SIZE = 0x0005, - WM_TIMER = 0x0113, - WM_PRINT = 0x0317; + public const int DT_CALCRECT = 0x00000400; + public const int WS_DISABLED = 0x08000000; + public const int WS_CLIPSIBLINGS = 0x04000000; + public const int WS_CLIPCHILDREN = 0x02000000; + public const int WS_EX_TOOLWINDOW = 0x00000080; + public const int WS_POPUP = unchecked((int)0x80000000); + public const int WS_BORDER = 0x00800000; + public const int CS_DROPSHADOW = 0x00020000; + public const int CS_DBLCLKS = 0x0008; + public const int NOTSRCCOPY = 0x00330008; + public const int SRCCOPY = 0x00CC0020; + public const int LVM_SETCOLUMNWIDTH = 0x1000 + 30; + public const int LVM_GETHEADER = 0x1000 + 31; + public const int LVM_CREATEDRAGIMAGE = 0x1000 + 33; + public const int LVM_GETVIEWRECT = 0x1000 + 34; + public const int LVM_GETTEXTCOLOR = 0x1000 + 35; + public const int LVM_SETTEXTCOLOR = 0x1000 + 36; + public const int LVM_GETTEXTBKCOLOR = 0x1000 + 37; + public const int LVM_SETTEXTBKCOLOR = 0x1000 + 38; + public const int LVM_GETTOPINDEX = 0x1000 + 39; + public const int LVM_GETCOUNTPERPAGE = 0x1000 + 40; + public const int LVM_GETORIGIN = 0x1000 + 41; + public const int LVM_UPDATE = 0x1000 + 42; + public const int LVM_SETITEMSTATE = 0x1000 + 43; + public const int LVM_GETITEMSTATE = 0x1000 + 44; + public const int LVM_GETITEMTEXTA = 0x1000 + 45; + public const int LVM_GETITEMTEXTW = 0x1000 + 115; + public const int LVM_SETITEMTEXTA = 0x1000 + 46; + public const int LVM_SETITEMTEXTW = 0x1000 + 116; + public const int LVSICF_NOINVALIDATEALL = 0x00000001; + public const int LVSICF_NOSCROLL = 0x00000002; + public const int LVM_SETITEMCOUNT = 0x1000 + 47; + public const int LVM_SORTITEMS = 0x1000 + 48; + public const int LVM_SETITEMPOSITION32 = 0x1000 + 49; + public const int LVM_GETSELECTEDCOUNT = 0x1000 + 50; + public const int LVM_GETITEMSPACING = 0x1000 + 51; + public const int LVM_GETISEARCHSTRINGA = 0x1000 + 52; + public const int LVM_GETISEARCHSTRINGW = 0x1000 + 117; + public const int LVM_SETICONSPACING = 0x1000 + 53; + public const int LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1000 + 54; + public const int LVM_GETEXTENDEDLISTVIEWSTYLE = 0x1000 + 55; + public const int LVS_EX_GRIDLINES = 0x00000001; + public const int HDM_HITTEST = 0x1200 + 6; + public const int HDM_GETITEMRECT = 0x1200 + 7; + public const int HDM_SETIMAGELIST = 0x1200 + 8; + public const int HDM_GETIMAGELIST = 0x1200 + 9; + public const int HDM_ORDERTOINDEX = 0x1200 + 15; + public const int HDM_CREATEDRAGIMAGE = 0x1200 + 16; + public const int HDM_GETORDERARRAY = 0x1200 + 17; + public const int HDM_SETORDERARRAY = 0x1200 + 18; + public const int HDM_SETHOTDIVIDER = 0x1200 + 19; + public const int HDN_ITEMCHANGINGA = 0 - 300 - 0; + public const int HDN_ITEMCHANGINGW = 0 - 300 - 20; + public const int HDN_ITEMCHANGEDA = 0 - 300 - 1; + public const int HDN_ITEMCHANGEDW = 0 - 300 - 21; + public const int HDN_ITEMCLICKA = 0 - 300 - 2; + public const int HDN_ITEMCLICKW = 0 - 300 - 22; + public const int HDN_ITEMDBLCLICKA = 0 - 300 - 3; + public const int HDN_ITEMDBLCLICKW = 0 - 300 - 23; + public const int HDN_DIVIDERDBLCLICKA = 0 - 300 - 5; + public const int HDN_DIVIDERDBLCLICKW = 0 - 300 - 25; + public const int HDN_BEGINTRACKA = 0 - 300 - 6; + public const int HDN_BEGINTRACKW = 0 - 300 - 26; + public const int HDN_ENDTRACKA = 0 - 300 - 7; + public const int HDN_ENDTRACKW = 0 - 300 - 27; + public const int HDN_TRACKA = 0 - 300 - 8; + public const int HDN_TRACKW = 0 - 300 - 28; + public const int HDN_GETDISPINFOA = 0 - 300 - 9; + public const int HDN_GETDISPINFOW = 0 - 300 - 29; + public const int HDN_BEGINDRAG = 0 - 300 - 10; + public const int HDN_ENDDRAG = 0 - 300 - 11; + public const int HC_ACTION = 0; + public const int HIST_BACK = 0; + public const int HHT_ONHEADER = 0x0002; + public const int HHT_ONDIVIDER = 0x0004; + public const int HHT_ONDIVOPEN = 0x0008; + public const int HHT_ABOVE = 0x0100; + public const int HHT_BELOW = 0x0200; + public const int HHT_TORIGHT = 0x0400; + public const int HHT_TOLEFT = 0x0800; + public const int HWND_TOP = 0; + public const int HWND_BOTTOM = 1; + public const int HWND_TOPMOST = -1; + public const int HWND_NOTOPMOST = -2; + public const int CWP_SKIPINVISIBLE = 0x0001; + public const int RDW_FRAME = 0x0400; + public const int TVM_GETITEMRECT = 0x1100 + 4; + public const int TVM_GETCOUNT = 0x1100 + 5; + public const int TVM_GETINDENT = 0x1100 + 6; + public const int TVM_SETINDENT = 0x1100 + 7; + public const int TVM_GETIMAGELIST = 0x1100 + 8; + public const int TVSIL_NORMAL = 0; + public const int TVSIL_STATE = 2; + public const int TVM_SETIMAGELIST = 0x1100 + 9; + public const int TVM_GETNEXTITEM = 0x1100 + 10; + public const int TVGN_ROOT = 0x0000; + public const int TV_FIRST = 0x1100; + public const int TVM_SETEXTENDEDSTYLE = TV_FIRST + 44; + public const int TVM_GETEXTENDEDSTYLE = TV_FIRST + 45; + public const int TVS_EX_FADEINOUTEXPANDOS = 0x0040; + public const int TVS_EX_DOUBLEBUFFER = 0x0004; + public const int LVS_EX_DOUBLEBUFFER = 0x00010000; + public const int TVHT_ONITEMICON = 0x0002; + public const int TVHT_ONITEMLABEL = 0x0004; + public const int TVHT_ONITEMINDENT = 0x0008; + public const int TVHT_ONITEMBUTTON = 0x0010; + public const int TVHT_ONITEMRIGHT = 0x0020; + public const int TVHT_ONITEMSTATEICON = 0x0040; + public const int TVHT_ABOVE = 0x0100; + public const int TVHT_BELOW = 0x0200; + public const int TVHT_TORIGHT = 0x0400; + public const int TVHT_TOLEFT = 0x0800; + public const int GW_HWNDFIRST = 0; + public const int GW_HWNDLAST = 1; + public const int GW_HWNDNEXT = 2; + public const int GW_HWNDPREV = 3; + public const int GW_OWNER = 4; + public const int GW_CHILD = 5; + public const int GW_MAX = 5; + public const int GWL_HWNDPARENT = -8; + public const int SB_HORZ = 0; + public const int SB_VERT = 1; + public const int SB_CTL = 2; + public const int SB_BOTH = 3; + public const int SB_LINEUP = 0; + public const int SB_LINELEFT = 0; + public const int SB_LINEDOWN = 1; + public const int SB_LINERIGHT = 1; + public const int SB_PAGEUP = 2; + public const int SB_PAGELEFT = 2; + public const int SB_PAGEDOWN = 3; + public const int SB_PAGERIGHT = 3; + public const int SB_THUMBPOSITION = 4; + public const int SB_THUMBTRACK = 5; + public const int SB_TOP = 6; + public const int SB_LEFT = 6; + public const int SB_BOTTOM = 7; + public const int SB_RIGHT = 7; + public const int SB_ENDSCROLL = 8; + public const int MK_LBUTTON = 0x0001; + public const int TVM_HITTEST = 0x1100 + 17; + public const int MK_RBUTTON = 0x0002; + public const int MK_SHIFT = 0x0004; + public const int MK_CONTROL = 0x0008; + public const int MK_MBUTTON = 0x0010; + public const int MK_XBUTTON1 = 0x0020; + public const int MK_XBUTTON2 = 0x0040; + public const int LB_ADDSTRING = 0x0180; + public const int LB_INSERTSTRING = 0x0181; + public const int LB_DELETESTRING = 0x0182; + public const int LB_SELITEMRANGEEX = 0x0183; + public const int LB_RESETCONTENT = 0x0184; + public const int LB_SETSEL = 0x0185; + public const int LB_SETCURSEL = 0x0186; + public const int LB_GETSEL = 0x0187; + public const int LB_GETCURSEL = 0x0188; + public const int LB_GETTEXT = 0x0189; + public const int LB_GETTEXTLEN = 0x018A; + public const int LB_GETCOUNT = 0x018B; + public const int LB_SELECTSTRING = 0x018C; + public const int LB_DIR = 0x018D; + public const int LB_GETTOPINDEX = 0x018E; + public const int LB_FINDSTRING = 0x018F; + public const int LB_GETSELCOUNT = 0x0190; + public const int LB_GETSELITEMS = 0x0191; + public const int LB_SETTABSTOPS = 0x0192; + public const int LB_GETHORIZONTALEXTENT = 0x0193; + public const int LB_SETHORIZONTALEXTENT = 0x0194; + public const int LB_SETCOLUMNWIDTH = 0x0195; + public const int LB_ADDFILE = 0x0196; + public const int LB_SETTOPINDEX = 0x0197; + public const int LB_GETITEMRECT = 0x0198; + public const int LB_GETITEMDATA = 0x0199; + public const int LB_SETITEMDATA = 0x019A; + public const int LB_SELITEMRANGE = 0x019B; + public const int LB_SETANCHORINDEX = 0x019C; + public const int LB_GETANCHORINDEX = 0x019D; + public const int LB_SETCARETINDEX = 0x019E; + public const int LB_GETCARETINDEX = 0x019F; + public const int LB_SETITEMHEIGHT = 0x01A0; + public const int LB_GETITEMHEIGHT = 0x01A1; + public const int LB_FINDSTRINGEXACT = 0x01A2; + public const int LB_SETLOCALE = 0x01A5; + public const int LB_GETLOCALE = 0x01A6; + public const int LB_SETCOUNT = 0x01A7; + public const int LB_INITSTORAGE = 0x01A8; + public const int LB_ITEMFROMPOINT = 0x01A9; + public const int LB_MSGMAX = 0x01B0; + public const int HTHSCROLL = 6; + public const int HTVSCROLL = 7; + public const int HTERROR = -2; + public const int HTTRANSPARENT = -1; + public const int HTNOWHERE = 0; + public const int HTCLIENT = 1; + public const int HTCAPTION = 2; + public const int HTSYSMENU = 3; + public const int HTGROWBOX = 4; + public const int HTSIZE = 4; + public const int PRF_NONCLIENT = 0x00000002; + public const int PRF_CLIENT = 0x00000004; + public const int PRF_ERASEBKGND = 0x00000008; + public const int PRF_CHILDREN = 0x00000010; + public const int SWP_NOSIZE = 0x0001; + public const int SWP_NOMOVE = 0x0002; + public const int SWP_NOZORDER = 0x0004; + public const int SWP_NOREDRAW = 0x0008; + public const int SWP_NOACTIVATE = 0x0010; + public const int SWP_FRAMECHANGED = 0x0020; + public const int SWP_SHOWWINDOW = 0x0040; + public const int SWP_HIDEWINDOW = 0x0080; + public const int SWP_NOCOPYBITS = 0x0100; + public const int SWP_NOOWNERZORDER = 0x0200; + public const int SWP_NOSENDCHANGING = 0x0400; + public const int SWP_DRAWFRAME = 0x0020; + public const int SWP_NOREPOSITION = 0x0200; + public const int SWP_DEFERERASE = 0x2000; + public const int SWP_ASYNCWINDOWPOS = 0x4000; [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] public static extern IntPtr GetCursor(); @@ -4404,8 +4308,7 @@ public static extern string QueryPathOfRegTypeLib(ref Guid guid, short majorVers public const int MWMO_INPUTAVAILABLE = 0x0004; // don't use MWMO_WAITALL, see ddb#176342 public const int GWL_EXSTYLE = -20, - GWL_STYLE = -16, - WS_EX_LAYOUTRTL = 0x00400000; + GWL_STYLE = -16; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class LOGFONT @@ -4537,7 +4440,7 @@ public sealed class CommonHandles [StructLayout(LayoutKind.Sequential)] public class NONCLIENTMETRICS { - public int cbSize = Marshal.SizeOf(typeof(NONCLIENTMETRICS)); + public int cbSize = Marshal.SizeOf(); public int iBorderWidth = 0; public int iScrollWidth = 0; public int iScrollHeight = 0; @@ -4567,5 +4470,7 @@ public class NONCLIENTMETRICS //SendMessage(IntPtr, int, bool, IntPtr), SendMessage(IntPtr, int, IntPtr, ListViewCompareCallback), //SendMessageW, SendMessageA, ValidateRect(IntPtr, ref RECT), ValidateRgn(IntPtr, IntPtr) //COMRECT.FromXYWH, RECT.FromXYWH + + public const int MAX_PATH = 260; } } diff --git a/src/System.Windows.Forms.Design.Editors/src/Misc/UnsafeNativeMethods.cs b/src/System.Windows.Forms.Design.Editors/src/Misc/UnsafeNativeMethods.cs index 35be9d218dc..6a460e95af4 100644 --- a/src/System.Windows.Forms.Design.Editors/src/Misc/UnsafeNativeMethods.cs +++ b/src/System.Windows.Forms.Design.Editors/src/Misc/UnsafeNativeMethods.cs @@ -158,102 +158,6 @@ public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLo [DllImport(ExternDll.Ole32, PreserveSig = false)] public static extern IStorage StgCreateDocfileOnILockBytes(ILockBytes iLockBytes, int grfMode, int reserved); - [Flags] - public enum BrowseInfos - { - // Browsing for directory. - ReturnOnlyFSDirs = 0x0001, // For finding a folder to start document searching - DontGoBelowDomain = 0x0002, // For starting the Find Computer - StatusText = 0x0004, // Top of the dialog has 2 lines of text for BROWSEINFO.lpszTitle and one line if - - // this flag is set. Passing the message BFFM_SETSTATUSTEXTA to the hwnd can set the - // rest of the text. This is not used with USENEWUI and BROWSEINFO.lpszTitle gets - // all three lines of text. - ReturnFSAncestors = 0x0008, - EditBox = 0x0010, // Add an editbox to the dialog - Validate = 0x0020, // insist on valid result (or CANCEL) - - NewDialogStyle = 0x0040, // Use the new dialog layout with the ability to resize - // Caller needs to call OleInitialize() before using this API - - UseNewUI = NewDialogStyle | EditBox, - - AllowUrls = 0x0080, // Allow URLs to be displayed or entered. (Requires USENEWUI) - - BrowseForComputer = 0x1000, // Browsing for Computers. - BrowseForPrinter = 0x2000, // Browsing for Printers - BrowseForEverything = 0x4000, // Browsing for Everything - ShowShares = 0x8000 // sharable resources displayed (remote shares, requires USENEWUI) - } - - [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] - [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public class BROWSEINFO - { - public IntPtr hwndOwner; //HWND hwndOwner; // HWND of the owner for the dialog - - public int - iImage; //int iImage; // output var: where to return the Image index. - - public IntPtr - lParam; //LPARAM lParam; // extra info that's passed back in callbacks - - public IntPtr lpfn; //BFFCALLBACK lpfn; // Call back pointer - - public string lpszTitle; //LPCWSTR lpszTitle; // text to go in the banner over the tree. - public IntPtr pidlRoot; //LPCITEMIDLIST pidlRoot; // Root ITEMIDLIST - - // For interop purposes, send over a buffer of MAX_PATH size. - public IntPtr pszDisplayName; //LPWSTR pszDisplayName; // Return display name of item selected. - public int ulFlags; //UINT ulFlags; // Flags that control the return stuff - } - - public class Shell32 - { - [DllImport(ExternDll.Shell32)] - public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, ref IntPtr ppidl); - //SHSTDAPI SHGetSpecialFolderLocation(HWND hwnd, int csidl, LPITEMIDLIST *ppidl); - - [DllImport(ExternDll.Shell32, CharSet = CharSet.Auto)] - public static extern bool SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath); - //SHSTDAPI_(BOOL) SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath); - - [DllImport(ExternDll.Shell32, CharSet = CharSet.Auto)] - public static extern IntPtr SHBrowseForFolder([In] BROWSEINFO lpbi); - //SHSTDAPI_(LPITEMIDLIST) SHBrowseForFolderW(LPBROWSEINFOW lpbi); - - [DllImport(ExternDll.Shell32)] - public static extern int SHGetMalloc([Out] [MarshalAs(UnmanagedType.LPArray)] - IMalloc[] ppMalloc); - - //SHSTDAPI SHGetMalloc(LPMALLOC * ppMalloc); - } - - [ComImport] - [Guid("00000002-0000-0000-c000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IMalloc - { - [PreserveSig] - IntPtr Alloc(int cb); - - [PreserveSig] - IntPtr Realloc(IntPtr pv, int cb); - - [PreserveSig] - void Free(IntPtr pv); - - [PreserveSig] - int GetSize(IntPtr pv); - - [PreserveSig] - int DidAlloc(IntPtr pv); - - [PreserveSig] - void HeapMinimize(); - } - [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] [StructLayout(LayoutKind.Sequential)] public struct PAINTSTRUCT diff --git a/src/System.Windows.Forms.Design.Editors/src/System.Windows.Forms.Design.Editors.csproj b/src/System.Windows.Forms.Design.Editors/src/System.Windows.Forms.Design.Editors.csproj index b88f35ba5d7..faf835a797f 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System.Windows.Forms.Design.Editors.csproj +++ b/src/System.Windows.Forms.Design.Editors/src/System.Windows.Forms.Design.Editors.csproj @@ -6,6 +6,7 @@ true true true + true @@ -29,6 +30,16 @@ + + + + + + + + + + diff --git a/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/CollectionEditor.cs b/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/CollectionEditor.cs index 223e5692663..33ded7c7d34 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/CollectionEditor.cs +++ b/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/CollectionEditor.cs @@ -2310,7 +2310,7 @@ protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_KEYDOWN: + case Interop.WindowMessages.WM_KEYDOWN: _lastKeyDown = m; // the first thing the ime does on a key it cares about is send a VK_PROCESSKEY, so we use that to sling focus to the grid. @@ -2330,12 +2330,12 @@ protected override void WndProc(ref Message m) if (PropertyGrid.Focused || PropertyGrid.ContainsFocus) { // recreate the keystroke to the newly activated window - NativeMethods.SendMessage(UnsafeNativeMethods.GetFocus(), NativeMethods.WM_KEYDOWN, _lastKeyDown.WParam, _lastKeyDown.LParam); + NativeMethods.SendMessage(UnsafeNativeMethods.GetFocus(), Interop.WindowMessages.WM_KEYDOWN, _lastKeyDown.WParam, _lastKeyDown.LParam); } } break; - case NativeMethods.WM_CHAR: + case Interop.WindowMessages.WM_CHAR: if ((Control.ModifierKeys & (Keys.Control | Keys.Alt)) != 0) { @@ -2357,8 +2357,8 @@ protected override void WndProc(ref Message m) if (PropertyGrid.Focused || PropertyGrid.ContainsFocus) { IntPtr hWnd = UnsafeNativeMethods.GetFocus(); - NativeMethods.SendMessage(hWnd, NativeMethods.WM_KEYDOWN, _lastKeyDown.WParam, _lastKeyDown.LParam); - NativeMethods.SendMessage(hWnd, NativeMethods.WM_CHAR, m.WParam, m.LParam); + NativeMethods.SendMessage(hWnd, Interop.WindowMessages.WM_KEYDOWN, _lastKeyDown.WParam, _lastKeyDown.LParam); + NativeMethods.SendMessage(hWnd, Interop.WindowMessages.WM_CHAR, m.WParam, m.LParam); return; } break; diff --git a/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/ObjectSelectorEditor.cs b/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/ObjectSelectorEditor.cs index 1f16aa9beb9..d2809cb5cfd 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/ObjectSelectorEditor.cs +++ b/src/System.Windows.Forms.Design.Editors/src/System/ComponentModel/Design/ObjectSelectorEditor.cs @@ -79,7 +79,7 @@ public static void ApplyTreeViewThemeStyles(TreeView treeView) { if (treeView == null) { - throw new ArgumentNullException("treeView"); + throw new ArgumentNullException(nameof(treeView)); } treeView.HotTracking = true; @@ -314,17 +314,17 @@ protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: m.Result = (IntPtr)((long)m.Result | NativeMethods.DLGC_WANTALLKEYS); return; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: if (clickSeen) { clickSeen = false; } break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: - NativeMethods.NMTREEVIEW nmtv = (NativeMethods.NMTREEVIEW)Marshal.PtrToStructure(m.LParam, typeof(NativeMethods.NMTREEVIEW)); + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: + NativeMethods.NMTREEVIEW nmtv = Marshal.PtrToStructure(m.LParam); if (nmtv.nmhdr.code == NativeMethods.NM_CLICK) { clickSeen = true; diff --git a/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/ColorEditor.cs b/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/ColorEditor.cs index 669e7d7cdf9..da63b372f60 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/ColorEditor.cs +++ b/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/ColorEditor.cs @@ -1113,13 +1113,13 @@ protected override IntPtr HookProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr l { switch (msg) { - case NativeMethods.WM_INITDIALOG: - NativeMethods.SendDlgItemMessage(hwnd, COLOR_HUE, NativeMethods.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); - NativeMethods.SendDlgItemMessage(hwnd, COLOR_SAT, NativeMethods.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); - NativeMethods.SendDlgItemMessage(hwnd, COLOR_LUM, NativeMethods.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); - NativeMethods.SendDlgItemMessage(hwnd, COLOR_RED, NativeMethods.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); - NativeMethods.SendDlgItemMessage(hwnd, COLOR_GREEN, NativeMethods.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); - NativeMethods.SendDlgItemMessage(hwnd, COLOR_BLUE, NativeMethods.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); + case Interop.WindowMessages.WM_INITDIALOG: + NativeMethods.SendDlgItemMessage(hwnd, COLOR_HUE, Interop.EditMessages.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); + NativeMethods.SendDlgItemMessage(hwnd, COLOR_SAT, Interop.EditMessages.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); + NativeMethods.SendDlgItemMessage(hwnd, COLOR_LUM, Interop.EditMessages.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); + NativeMethods.SendDlgItemMessage(hwnd, COLOR_RED, Interop.EditMessages.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); + NativeMethods.SendDlgItemMessage(hwnd, COLOR_GREEN, Interop.EditMessages.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); + NativeMethods.SendDlgItemMessage(hwnd, COLOR_BLUE, Interop.EditMessages.EM_SETMARGINS, (IntPtr)(NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN), IntPtr.Zero); IntPtr hwndCtl = NativeMethods.GetDlgItem(hwnd, COLOR_MIX); NativeMethods.EnableWindow(hwndCtl, false); NativeMethods.SetWindowPos(hwndCtl, IntPtr.Zero, 0, 0, 0, 0, NativeMethods.SWP_HIDEWINDOW); @@ -1128,7 +1128,7 @@ protected override IntPtr HookProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr l NativeMethods.SetWindowPos(hwndCtl, IntPtr.Zero, 0, 0, 0, 0, NativeMethods.SWP_HIDEWINDOW); this.Color = Color.Empty; break; - case NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_COMMAND: switch (NativeMethods.Util.LOWORD(unchecked((int)(long)wParam))) { case COLOR_ADD: @@ -1141,7 +1141,7 @@ protected override IntPtr HookProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr l blue = (byte)NativeMethods.GetDlgItemInt(hwnd, COLOR_BLUE, err, false); Debug.Assert(!err[0], "Couldn't find dialog member COLOR_BLUE"); this.Color = Color.FromArgb(red, green, blue); - NativeMethods.PostMessage(hwnd, NativeMethods.WM_COMMAND, (IntPtr)NativeMethods.Util.MAKELONG(NativeMethods.IDOK, 0), NativeMethods.GetDlgItem(hwnd, NativeMethods.IDOK)); + NativeMethods.PostMessage(hwnd, Interop.WindowMessages.WM_COMMAND, (IntPtr)NativeMethods.Util.MAKELONG(NativeMethods.IDOK, 0), NativeMethods.GetDlgItem(hwnd, NativeMethods.IDOK)); break; } break; diff --git a/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/FontEditor.cs b/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/FontEditor.cs index 1556e9aa5dd..434f0a683c6 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/FontEditor.cs +++ b/src/System.Windows.Forms.Design.Editors/src/System/Drawing/Design/FontEditor.cs @@ -11,53 +11,42 @@ namespace System.Drawing.Design { /// - /// Provides a font editor that - /// is used to visually select and configure a Font - /// object. + /// Provides a font editor that is used to visually select and configure a Font object. /// [CLSCompliant(false)] public class FontEditor : UITypeEditor { - private FontDialog fontDialog; - private object value; + private FontDialog _fontDialog; /// - /// Edits the given object value using the editor style provided by - /// GetEditorStyle. A service provider is provided so that any - /// required editing services can be obtained. + /// Edits the given object value using the editor style provided by GetEditorStyle. + /// A service provider is provided so that any required editing services can be obtained. /// public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { - this.value = value; - - Debug.Assert(provider != null, "No service provider; we cannot edit the value"); if (provider != null) { - IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); - - Debug.Assert(edSvc != null, "No editor service; we cannot edit the value"); - if (edSvc != null) + if (provider.GetService(typeof(IWindowsFormsEditorService)) is IWindowsFormsEditorService edSvc) { - if (fontDialog == null) + if (_fontDialog == null) { - fontDialog = new FontDialog(); - fontDialog.ShowApply = false; - fontDialog.ShowColor = false; - fontDialog.AllowVerticalFonts = false; + _fontDialog = new FontDialog(); + _fontDialog.ShowApply = false; + _fontDialog.ShowColor = false; + _fontDialog.AllowVerticalFonts = false; } - Font fontvalue = value as Font; - if (fontvalue != null) + if (value is Font fontValue) { - fontDialog.Font = fontvalue; + _fontDialog.Font = fontValue; } IntPtr hwndFocus = UnsafeNativeMethods.GetFocus(); try { - if (fontDialog.ShowDialog() == DialogResult.OK) + if (_fontDialog.ShowDialog() == DialogResult.OK) { - this.value = fontDialog.Font; + return _fontDialog.Font; } } finally @@ -70,16 +59,11 @@ public override object EditValue(ITypeDescriptorContext context, IServiceProvide } } - // Now pull out the updated value, if there was one. - value = this.value; - this.value = null; - return value; } /// - /// Retrieves the editing style of the Edit method. If the method - /// is not supported, this will return None. + /// Retrieves the editing style of the Edit method.false /// public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { @@ -87,4 +71,3 @@ public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext contex } } } - diff --git a/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FileNameEditor.cs b/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FileNameEditor.cs index ba9202bf67c..e6e75c10d09 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FileNameEditor.cs +++ b/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FileNameEditor.cs @@ -2,49 +2,45 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.ComponentModel; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing.Design; namespace System.Windows.Forms.Design { /// > - /// Provides an - /// editor for filenames. + /// Provides an editor for filenames. /// [CLSCompliant(false)] public class FileNameEditor : UITypeEditor { - private OpenFileDialog openFileDialog; + private OpenFileDialog _openFileDialog; /// - /// Edits the given object value using the editor style provided by - /// GetEditorStyle. A service provider is provided so that any - /// required editing services can be obtained. + /// Edits the given object value using the editor style provided by GetEditorStyle. + /// A service provider is provided so that any required editing services can be obtained. /// - [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { - Debug.Assert(provider != null, "No service provider; we cannot edit the value"); if (provider != null) { - IWindowsFormsEditorService edSvc = - (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); - - Debug.Assert(edSvc != null, "No editor service; we cannot edit the value"); - if (edSvc != null) + if (provider.GetService(typeof(IWindowsFormsEditorService)) is IWindowsFormsEditorService edSvc) { - if (openFileDialog == null) + if (_openFileDialog == null) { - openFileDialog = new OpenFileDialog(); - InitializeDialog(openFileDialog); + _openFileDialog = new OpenFileDialog(); + InitializeDialog(_openFileDialog); } - if (value is string) openFileDialog.FileName = (string)value; + if (value is string stringValue) + { + _openFileDialog.FileName = stringValue; + } - if (openFileDialog.ShowDialog() == DialogResult.OK) value = openFileDialog.FileName; + if (_openFileDialog.ShowDialog() == DialogResult.OK) + { + return _openFileDialog.FileName; + } } } @@ -52,24 +48,26 @@ public override object EditValue(ITypeDescriptorContext context, IServiceProvide } /// > - /// Gets the editing style of the Edit method. If the method - /// is not supported, this will return None. + /// Gets the editing style of the Edit method. /// - [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] - // everything in this assembly is full trust. public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } /// - /// Initializes the open file dialog when it is created. This gives you - /// an opportunity to configure the dialog as you please. The default - /// implementation provides a generic file filter and title. + /// Initializes the open file dialog when it is created. This gives you an opportunity to + /// configure the dialog as you please. The default implementation provides a generic file + /// filter and title. /// [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] protected virtual void InitializeDialog(OpenFileDialog openFileDialog) { + if (openFileDialog == null) + { + throw new ArgumentNullException(nameof(openFileDialog)); + } + openFileDialog.Filter = SR.GenericFileFilter; openFileDialog.Title = SR.GenericOpenFile; } diff --git a/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FolderNameEditor.cs b/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FolderNameEditor.cs index 536ddeef48e..0604d42fe56 100644 --- a/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FolderNameEditor.cs +++ b/src/System.Windows.Forms.Design.Editors/src/System/Windows/Forms/Design/FolderNameEditor.cs @@ -2,51 +2,49 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Buffers; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Drawing.Design; using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; namespace System.Windows.Forms.Design { /// > - /// Provides an editor - /// for choosing a folder from the filesystem. + /// Provides an editor for choosing a folder from the filesystem. /// [CLSCompliant(false)] public class FolderNameEditor : UITypeEditor { - private FolderBrowser folderBrowser; + private FolderBrowser _folderBrowser; - [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { - if (folderBrowser == null) + if (_folderBrowser == null) { - folderBrowser = new FolderBrowser(); - InitializeDialog(folderBrowser); + _folderBrowser = new FolderBrowser(); + InitializeDialog(_folderBrowser); } - if (folderBrowser.ShowDialog() != DialogResult.OK) return value; + if (_folderBrowser.ShowDialog() == DialogResult.OK) + { + return _folderBrowser.DirectoryPath; + } - return folderBrowser.DirectoryPath; + return value; } /// - /// Retrieves the editing style of the Edit method. If the method - /// is not supported, this will return None. - /// - [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] - // everything in this assembly is full trust. + /// Retrieves the editing style of the Edit method. public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } /// - /// Initializes the folder browser dialog when it is created. This gives you - /// an opportunity to configure the dialog as you please. The default - /// implementation provides a generic folder browser. + /// Initializes the folder browser dialog when it is created. This gives you an opportunity + /// to configure the dialog as you please. The default implementation provides a generic folder browser. /// protected virtual void InitializeDialog(FolderBrowser folderBrowser) { @@ -54,128 +52,100 @@ protected virtual void InitializeDialog(FolderBrowser folderBrowser) protected sealed class FolderBrowser : Component { - private static readonly int MAX_PATH = 260; - // Description text to show. - private string descriptionText = string.Empty; - - // Folder picked by the user. - private readonly UnsafeNativeMethods.BrowseInfos privateOptions = - UnsafeNativeMethods.BrowseInfos.NewDialogStyle; + private string _descriptionText = string.Empty; /// - /// The styles the folder browser will use when browsing - /// folders. This should be a combination of flags from - /// the FolderBrowserStyles enum. + /// The styles the folder browser will use when browsing + /// folders. This should be a combination of flags from + /// the FolderBrowserStyles enum. /// public FolderBrowserStyles Style { get; set; } = FolderBrowserStyles.RestrictToFilesystem; /// - /// Gets the directory path of the folder the user picked. + /// Gets the directory path of the folder the user picked. /// public string DirectoryPath { get; private set; } = string.Empty; /// - /// Gets/sets the start location of the root node. + /// Gets/sets the start location of the root node. /// public FolderBrowserFolder StartLocation { get; set; } = FolderBrowserFolder.Desktop; /// > - /// Gets or sets a description to show above the folders. Here you can provide instructions for - /// selecting a folder. + /// Gets or sets a description to show above the folders. Here you can provide instructions for + /// selecting a folder. /// public string Description { - get => descriptionText; - set => descriptionText = value == null ? string.Empty : value; - } - - /// - /// Helper function that returns the IMalloc interface used by the shell. - /// - private static UnsafeNativeMethods.IMalloc GetSHMalloc() - { - UnsafeNativeMethods.IMalloc[] malloc = new UnsafeNativeMethods.IMalloc[1]; - - UnsafeNativeMethods.Shell32.SHGetMalloc(malloc); - - return malloc[0]; + get => _descriptionText; + set => _descriptionText = value ?? string.Empty; } /// - /// Shows the folder browser dialog. + /// Shows the folder browser dialog. /// - public DialogResult ShowDialog() - { - return ShowDialog(null); - } + public DialogResult ShowDialog() => ShowDialog(null); /// - /// Shows the folder browser dialog with the specified owner. + /// Shows the folder browser dialog with the specified owner. /// - public DialogResult ShowDialog(IWin32Window owner) + public unsafe DialogResult ShowDialog(IWin32Window owner) { - IntPtr pidlRoot = IntPtr.Zero; - // Get/find an owner HWND for this dialog - IntPtr hWndOwner; - - if (owner != null) - hWndOwner = owner.Handle; - else - hWndOwner = UnsafeNativeMethods.GetActiveWindow(); + IntPtr hWndOwner = owner == null ? owner.Handle : UnsafeNativeMethods.GetActiveWindow(); // Get the IDL for the specific startLocation - UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)StartLocation, ref pidlRoot); - - if (pidlRoot == IntPtr.Zero) return DialogResult.Cancel; - - int mergedOptions = (int)Style | (int)privateOptions; - - if ((mergedOptions & (int)UnsafeNativeMethods.BrowseInfos.NewDialogStyle) != 0) - Application.OleRequired(); - - IntPtr pidlRet = IntPtr.Zero; - - try + CoTaskMemSafeHandle listHandle; + Interop.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)StartLocation, out listHandle); + if (listHandle.IsInvalid) { - // Construct a BROWSEINFO - UnsafeNativeMethods.BROWSEINFO bi = new UnsafeNativeMethods.BROWSEINFO(); - - IntPtr buffer = Marshal.AllocHGlobal(MAX_PATH); - - bi.pidlRoot = pidlRoot; - bi.hwndOwner = hWndOwner; - bi.pszDisplayName = buffer; - bi.lpszTitle = descriptionText; - bi.ulFlags = mergedOptions; - bi.lpfn = IntPtr.Zero; - bi.lParam = IntPtr.Zero; - bi.iImage = 0; - - // And show the dialog - pidlRet = UnsafeNativeMethods.Shell32.SHBrowseForFolder(bi); - - if (pidlRet == IntPtr.Zero) return DialogResult.Cancel; - - // Then retrieve the path from the IDList - UnsafeNativeMethods.Shell32.SHGetPathFromIDList(pidlRet, buffer); - - // Convert to a string - DirectoryPath = Marshal.PtrToStringAuto(buffer); - - // Then free all the stuff we've allocated or the SH API gave us - Marshal.FreeHGlobal(buffer); + return DialogResult.Cancel; } - finally - { - UnsafeNativeMethods.IMalloc malloc = GetSHMalloc(); - malloc.Free(pidlRoot); - if (pidlRet != IntPtr.Zero) malloc.Free(pidlRet); + using (listHandle) + { + uint mergedOptions = (uint)Style | Interop.Shell32.BrowseInfoFlags.BIF_NEWDIALOGSTYLE; + if ((mergedOptions & (int)Interop.Shell32.BrowseInfoFlags.BIF_NEWDIALOGSTYLE) != 0) + { + Application.OleRequired(); + } + + char[] displayName = ArrayPool.Shared.Rent(Interop.Kernel32.MAX_PATH + 1); + try + { + fixed (char *pDisplayName = displayName) + { + var bi = new Interop.Shell32.BROWSEINFO(); + bi.pidlRoot = listHandle; + bi.hwndOwner = hWndOwner; + bi.pszDisplayName = pDisplayName; + bi.lpszTitle = _descriptionText; + bi.ulFlags = mergedOptions; + bi.lpfn = null; + bi.lParam = IntPtr.Zero; + bi.iImage = 0; + + // Show the dialog. + using (CoTaskMemSafeHandle browseHandle = Interop.Shell32.SHBrowseForFolderW(ref bi)) + { + if (browseHandle.IsInvalid) + { + return DialogResult.Cancel; + } + + // Retrieve the path from the IDList. + Interop.Shell32.SHGetPathFromIDListLongPath(browseHandle.DangerousGetHandle(), out string selectedPath); + DirectoryPath = selectedPath; + return DialogResult.OK; + } + } + } + finally + { + ArrayPool.Shared.Return(displayName); + } } - - return DialogResult.OK; } } @@ -209,19 +179,19 @@ protected enum FolderBrowserFolder [Flags] protected enum FolderBrowserStyles { - BrowseForComputer = UnsafeNativeMethods.BrowseInfos.BrowseForComputer, + BrowseForComputer = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_BROWSEFORCOMPUTER), - BrowseForEverything = UnsafeNativeMethods.BrowseInfos.BrowseForEverything, + BrowseForEverything = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_BROWSEFOREVERYTHING), - BrowseForPrinter = UnsafeNativeMethods.BrowseInfos.BrowseForPrinter, + BrowseForPrinter = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_BROWSEFORPRINTER), - RestrictToDomain = UnsafeNativeMethods.BrowseInfos.DontGoBelowDomain, + RestrictToDomain = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_DONTGOBELOWDOMAIN), - RestrictToFilesystem = UnsafeNativeMethods.BrowseInfos.ReturnOnlyFSDirs, + RestrictToFilesystem = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_RETURNONLYFSDIRS), - RestrictToSubfolders = UnsafeNativeMethods.BrowseInfos.ReturnFSAncestors, + RestrictToSubfolders = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_RETURNFSANCESTORS), - ShowTextBox = UnsafeNativeMethods.BrowseInfos.EditBox + ShowTextBox = unchecked((int)Interop.Shell32.BrowseInfoFlags.BIF_EDITBOX) } } } diff --git a/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System.Windows.Forms.Design.Editors.Tests.csproj b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System.Windows.Forms.Design.Editors.Tests.csproj index 1a2ad4a14fe..8ace057cbed 100644 --- a/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System.Windows.Forms.Design.Editors.Tests.csproj +++ b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System.Windows.Forms.Design.Editors.Tests.csproj @@ -13,6 +13,8 @@ + + diff --git a/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Drawing/Design/FontEditorTests.cs b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Drawing/Design/FontEditorTests.cs new file mode 100644 index 00000000000..c2df2d47220 --- /dev/null +++ b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Drawing/Design/FontEditorTests.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Windows.Forms.Design; +using Moq; +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class FontEditorTests + { + public static IEnumerable EditValue_InvalidProvider_TestData() + { + yield return new object[] { null }; + + var nullServiceProviderMock = new Mock(MockBehavior.Strict); + nullServiceProviderMock + .Setup(p => p.GetService(typeof(IWindowsFormsEditorService))) + .Returns(null); + yield return new object[] { nullServiceProviderMock.Object }; + + var invalidServiceProviderMock = new Mock(MockBehavior.Strict); + invalidServiceProviderMock + .Setup(p => p.GetService(typeof(IWindowsFormsEditorService))) + .Returns(new object()); + yield return new object[] { invalidServiceProviderMock.Object }; + } + + [Theory] + [MemberData(nameof(EditValue_InvalidProvider_TestData))] + public void EditValue_InvalidProvider_ReturnsValue(IServiceProvider provider) + { + var editor = new FontEditor(); + var value = new object(); + Assert.Same(value, editor.EditValue(null, provider, value)); + } + + [Fact] + public void GetEditStyle_Invoke_ReturnsModal() + { + var editor = new FontEditor(); + Assert.Equal(UITypeEditorEditStyle.Modal, editor.GetEditStyle(null)); + } + } +} diff --git a/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Windows/Forms/Design/FileNameEditorTests.cs b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Windows/Forms/Design/FileNameEditorTests.cs new file mode 100644 index 00000000000..90a245d1b92 --- /dev/null +++ b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Windows/Forms/Design/FileNameEditorTests.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Drawing.Design; +using System.Windows.Forms; +using System.Windows.Forms.Design; +using Moq; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class FileNameEditorTests + { + public static IEnumerable EditValue_InvalidProvider_TestData() + { + yield return new object[] { null }; + + var nullServiceProviderMock = new Mock(MockBehavior.Strict); + nullServiceProviderMock + .Setup(p => p.GetService(typeof(IWindowsFormsEditorService))) + .Returns(null); + yield return new object[] { nullServiceProviderMock.Object }; + + var invalidServiceProviderMock = new Mock(MockBehavior.Strict); + invalidServiceProviderMock + .Setup(p => p.GetService(typeof(IWindowsFormsEditorService))) + .Returns(new object()); + yield return new object[] { invalidServiceProviderMock.Object }; + } + + [Theory] + [MemberData(nameof(EditValue_InvalidProvider_TestData))] + public void EditValue_InvalidProvider_ReturnsValue(IServiceProvider provider) + { + var editor = new FileNameEditor(); + var value = new object(); + Assert.Same(value, editor.EditValue(null, provider, value)); + } + + [Fact] + public void GetEditStyle_Invoke_ReturnsModal() + { + var editor = new FileNameEditor(); + Assert.Equal(UITypeEditorEditStyle.Modal, editor.GetEditStyle(null)); + } + + [Fact] + public void InitializeDialog_Invoke_Success() + { + var editor = new SubFileNameEditor(); + using (var openFileDialog = new OpenFileDialog()) + { + editor.InitializeDialog(openFileDialog); + Assert.Equal("All Files(*.*)|*.*", openFileDialog.Filter); + Assert.Equal("Open File", openFileDialog.Title); + } + } + + [Fact] + public void InitializeDialog_NullOpenFileDialog_ThrowsArgumentNullException() + { + var editor = new SubFileNameEditor(); + Assert.Throws("openFileDialog", () => editor.InitializeDialog(null)); + } + + private class SubFileNameEditor : FileNameEditor + { + public new void InitializeDialog(OpenFileDialog openFileDialog) => base.InitializeDialog(openFileDialog); + } + } +} diff --git a/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Windows/Forms/Design/FolderNameEditorTests.cs b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Windows/Forms/Design/FolderNameEditorTests.cs new file mode 100644 index 00000000000..cbd3d0c71e3 --- /dev/null +++ b/src/System.Windows.Forms.Design.Editors/tests/UnitTests/System/Windows/Forms/Design/FolderNameEditorTests.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.Drawing.Design; +using System.Globalization; +using System.Reflection; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class FolderNameEditorTests + { + [Fact] + public void GetEditStyle_Invoke_ReturnsModal() + { + var editor = new FolderNameEditor(); + Assert.Equal(UITypeEditorEditStyle.Modal, editor.GetEditStyle(null)); + } + + [Fact] + public void InitializeDialog_Invoke_Nop() + { + var editor = new SubFolderNameEditor(); + editor.InitializeDialog(); + } + + public class FolderBrowserTests : FolderNameEditor + { + [Fact] + public void Ctor_Default() + { + var browser = new FolderBrowser(); + Assert.Empty(browser.DirectoryPath); + Assert.Empty(browser.Description); + Assert.Equal(FolderBrowserStyles.RestrictToFilesystem, browser.Style); + Assert.Equal(FolderBrowserFolder.Desktop, browser.StartLocation); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void Description_Set_GetReturnsExpected(string value) + { + var browser = new FolderBrowser + { + Description = value + }; + Assert.Equal(value ?? string.Empty, browser.Description); + + // Set same. + browser.Description = value; + Assert.Equal(value ?? string.Empty, browser.Description); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FolderBrowserFolder))] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(FolderBrowserFolder))] + protected void StartLocation_Set_GetReturnsExpected(FolderBrowserFolder value) + { + var browser = new FolderBrowser + { + StartLocation = value + }; + Assert.Equal(value, browser.StartLocation); + + // Set same. + browser.StartLocation = value; + Assert.Equal(value, browser.StartLocation); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FolderBrowserStyles))] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(FolderBrowserStyles))] + protected void Style_Set_GetReturnsExpected(FolderBrowserStyles value) + { + var browser = new FolderBrowser + { + Style = value + }; + Assert.Equal(value, browser.Style); + + // Set same. + browser.Style = value; + Assert.Equal(value, browser.Style); + } + } + + private class SubFolderNameEditor : FolderNameEditor + { + public void InitializeDialog() => base.InitializeDialog(null); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/Resources/SR.Designer.cs b/src/System.Windows.Forms.Design/src/Resources/SR.Designer.cs new file mode 100644 index 00000000000..0d6ba386d81 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/Resources/SR.Designer.cs @@ -0,0 +1,1907 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace System.Windows.Forms.Design.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class SR { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal SR() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Windows.Forms.Design.Resources.SR", typeof(SR).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Copy and move {0}. + /// + public static string BehaviorServiceCopyControl { + get { + return ResourceManager.GetString("BehaviorServiceCopyControl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Copy and move {0} Controls. + /// + public static string BehaviorServiceCopyControls { + get { + return ResourceManager.GetString("BehaviorServiceCopyControls", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move {0}. + /// + public static string BehaviorServiceMoveControl { + get { + return ResourceManager.GetString("BehaviorServiceMoveControl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move {0} Controls. + /// + public static string BehaviorServiceMoveControls { + get { + return ResourceManager.GetString("BehaviorServiceMoveControls", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resize {0}. + /// + public static string BehaviorServiceResizeControl { + get { + return ResourceManager.GetString("BehaviorServiceResizeControl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resize {0} Controls. + /// + public static string BehaviorServiceResizeControls { + get { + return ResourceManager.GetString("BehaviorServiceResizeControls", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Double cannot be converted to a date.. + /// + public static string CannotConvertDoubleToDate { + get { + return ResourceManager.GetString("CannotConvertDoubleToDate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Integer cannot be converted to a float.. + /// + public static string CannotConvertIntToFloat { + get { + return ResourceManager.GetString("CannotConvertIntToFloat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The serialization store is closed. New objects cannot be added to a closed store.. + /// + public static string CodeDomComponentSerializationServiceClosedStore { + get { + return ResourceManager.GetString("CodeDomComponentSerializationServiceClosedStore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Complete deserialization of {0} failed.. + /// + public static string CodeDomComponentSerializationServiceDeserializationError { + get { + return ResourceManager.GetString("CodeDomComponentSerializationServiceDeserializationError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This type of serialization store is not supported. Use a store returned by the CreateStore method.. + /// + public static string CodeDomComponentSerializationServiceUnknownStore { + get { + return ResourceManager.GetString("CodeDomComponentSerializationServiceUnknownStore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unhandled VT: {0}.. + /// + public static string COM2UnhandledVT { + get { + return ResourceManager.GetString("COM2UnhandledVT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Format {0} components (alignment). + /// + public static string CommandSetAlignByPrimary { + get { + return ResourceManager.GetString("CommandSetAlignByPrimary", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Align {0} components to grid. + /// + public static string CommandSetAlignToGrid { + get { + return ResourceManager.GetString("CommandSetAlignToGrid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cut {0} Components. + /// + public static string CommandSetCutMultiple { + get { + return ResourceManager.GetString("CommandSetCutMultiple", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete {0} components. + /// + public static string CommandSetDelete { + get { + return ResourceManager.GetString("CommandSetDelete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occurred while processing this command. + /// {0}. + /// + public static string CommandSetError { + get { + return ResourceManager.GetString("CommandSetError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Format {0} components (spacing). + /// + public static string CommandSetFormatSpacing { + get { + return ResourceManager.GetString("CommandSetFormatSpacing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Paste components. + /// + public static string CommandSetPaste { + get { + return ResourceManager.GetString("CommandSetPaste", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Size {0} components. + /// + public static string CommandSetSize { + get { + return ResourceManager.GetString("CommandSetSize", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Size {0} components to grid. + /// + public static string CommandSetSizeToGrid { + get { + return ResourceManager.GetString("CommandSetSizeToGrid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown spacing command. + /// + public static string CommandSetUnknownSpacingCommand { + get { + return ResourceManager.GetString("CommandSetUnknownSpacingCommand", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Adding event '{0}'. + /// + public static string ComponentDesignerAddEvent { + get { + return ResourceManager.GetString("ComponentDesignerAddEvent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Align To &Grid. + /// + public static string ContextMenuAlignToGrid { + get { + return ResourceManager.GetString("ContextMenuAlignToGrid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Bring To Front. + /// + public static string ContextMenuBringToFront { + get { + return ResourceManager.GetString("ContextMenuBringToFront", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to C&opy. + /// + public static string ContextMenuCopy { + get { + return ResourceManager.GetString("ContextMenuCopy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Cut. + /// + public static string ContextMenuCut { + get { + return ResourceManager.GetString("ContextMenuCut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Delete. + /// + public static string ContextMenuDelete { + get { + return ResourceManager.GetString("ContextMenuDelete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Document Outline. + /// + public static string ContextMenuDocumentOutline { + get { + return ResourceManager.GetString("ContextMenuDocumentOutline", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Lock Controls. + /// + public static string ContextMenuLockControls { + get { + return ResourceManager.GetString("ContextMenuLockControls", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Paste. + /// + public static string ContextMenuPaste { + get { + return ResourceManager.GetString("ContextMenuPaste", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Properties. + /// + public static string ContextMenuProperties { + get { + return ResourceManager.GetString("ContextMenuProperties", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Select. + /// + public static string ContextMenuSelect { + get { + return ResourceManager.GetString("ContextMenuSelect", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Send To Back. + /// + public static string ContextMenuSendToBack { + get { + return ResourceManager.GetString("ContextMenuSendToBack", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ShowCheckMargin. + /// + public static string ContextMenuStripActionList_ShowCheckMargin { + get { + return ResourceManager.GetString("ContextMenuStripActionList_ShowCheckMargin", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggles the ShowCheckMargin property. + /// + public static string ContextMenuStripActionList_ShowCheckMarginDesc { + get { + return ResourceManager.GetString("ContextMenuStripActionList_ShowCheckMarginDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ShowImageMargin. + /// + public static string ContextMenuStripActionList_ShowImageMargin { + get { + return ResourceManager.GetString("ContextMenuStripActionList_ShowImageMargin", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggles the ShowImageMargin property. + /// + public static string ContextMenuStripActionList_ShowImageMarginDesc { + get { + return ResourceManager.GetString("ContextMenuStripActionList_ShowImageMarginDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to View &Code. + /// + public static string ContextMenuViewCode { + get { + return ResourceManager.GetString("ContextMenuViewCode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The control {0} has thrown an unhandled exception in the designer and has been disabled. + /// + /// Exception: + /// {1} + /// + /// Stack trace:{2}. + /// + public static string ControlDesigner_WndProcException { + get { + return ResourceManager.GetString("ControlDesigner_WndProcException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not convert value '{0}' to the type '{1}'.. + /// + public static string DesignerActionPanel_CouldNotConvertValue { + get { + return ResourceManager.GetString("DesignerActionPanel_CouldNotConvertValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find method '{0}'.. + /// + public static string DesignerActionPanel_CouldNotFindMethod { + get { + return ResourceManager.GetString("DesignerActionPanel_CouldNotFindMethod", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find property '{0}' on '{1}'.. + /// + public static string DesignerActionPanel_CouldNotFindProperty { + get { + return ResourceManager.GetString("DesignerActionPanel_CouldNotFindProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} Tasks. + /// + public static string DesignerActionPanel_DefaultPanelTitle { + get { + return ResourceManager.GetString("DesignerActionPanel_DefaultPanelTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error using the dropdown: {0}. + /// + public static string DesignerActionPanel_ErrorActivatingDropDown { + get { + return ResourceManager.GetString("DesignerActionPanel_ErrorActivatingDropDown", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error invoking '{0}'. Details: {1}. + /// + public static string DesignerActionPanel_ErrorInvokingAction { + get { + return ResourceManager.GetString("DesignerActionPanel_ErrorInvokingAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error setting value '{0}' to property '{1}'. Details: {2}. + /// + public static string DesignerActionPanel_ErrorSettingValue { + get { + return ResourceManager.GetString("DesignerActionPanel_ErrorSettingValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Call to BeginDrag must succeed before calling drag functions.. + /// + public static string DesignerBeginDragNotCalled { + get { + return ResourceManager.GetString("DesignerBeginDragNotCalled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot remove or destroy inherited component '{0}'.. + /// + public static string DesignerHostCantDestroyInheritedComponent { + get { + return ResourceManager.GetString("DesignerHostCantDestroyInheritedComponent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot add an instance of {0} to the designer because it would create a circular dependency. Make sure that the type does not have the same namespace and type name as the root component {1}.. + /// + public static string DesignerHostCyclicAdd { + get { + return ResourceManager.GetString("DesignerHostCyclicAdd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failure initializing the designer. It has no Component member.. + /// + public static string DesignerHostDesignerNeedsComponent { + get { + return ResourceManager.GetString("DesignerHostDesignerNeedsComponent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Deleting '{0}'.. + /// + public static string DesignerHostDestroyComponentTransaction { + get { + return ResourceManager.GetString("DesignerHostDestroyComponentTransaction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The name {0} is already in use by another component.. + /// + public static string DesignerHostDuplicateName { + get { + return ResourceManager.GetString("DesignerHostDuplicateName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Component of type {0} could not be created. Make sure the type implements IComponent and provides an appropriate public constructor. Appropriate constructors either take no parameters or take a single IContainer parameter.. + /// + public static string DesignerHostFailedComponentCreate { + get { + return ResourceManager.GetString("DesignerHostFailedComponentCreate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No Description Available. + /// + public static string DesignerHostGenericTransactionName { + get { + return ResourceManager.GetString("DesignerHostGenericTransactionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A designer loader has already been configured for this design surface.. + /// + public static string DesignerHostLoaderSpecified { + get { + return ResourceManager.GetString("DesignerHostLoaderSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The designer transaction '{0}' cannot be committed or canceled because nested transaction '{1}' is still active. Commit or cancel the nested transaction first.. + /// + public static string DesignerHostNestedTransaction { + get { + return ResourceManager.GetString("DesignerHostNestedTransaction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot open a designer for the file because the class within it does not inherit from a class that can be visually designed.. + /// + public static string DesignerHostNoBaseClass { + get { + return ResourceManager.GetString("DesignerHostNoBaseClass", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is no designer for the class {0}.. + /// + public static string DesignerHostNoTopLevelDesigner { + get { + return ResourceManager.GetString("DesignerHostNoTopLevelDesigner", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New components cannot be added while a designer is unloading.. + /// + public static string DesignerHostUnloading { + get { + return ResourceManager.GetString("DesignerHostUnloading", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Inherited control. + /// + public static string DesignerInherited { + get { + return ResourceManager.GetString("DesignerInherited", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Inherited control (Private). + /// + public static string DesignerInheritedReadOnly { + get { + return ResourceManager.GetString("DesignerInheritedReadOnly", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Optimized Code Generation. + /// + public static string DesignerOptions_CodeGenDisplay { + get { + return ResourceManager.GetString("DesignerOptions_CodeGenDisplay", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Code Generation Settings. + /// + public static string DesignerOptions_CodeGenSettings { + get { + return ResourceManager.GetString("DesignerOptions_CodeGenSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to InSitu Editing. + /// + public static string DesignerOptions_EnableInSituEditingCat { + get { + return ResourceManager.GetString("DesignerOptions_EnableInSituEditingCat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Controls whether InSitu editing is enabled.. + /// + public static string DesignerOptions_EnableInSituEditingDesc { + get { + return ResourceManager.GetString("DesignerOptions_EnableInSituEditingDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enable InSitu Editing. + /// + public static string DesignerOptions_EnableInSituEditingDisplay { + get { + return ResourceManager.GetString("DesignerOptions_EnableInSituEditingDisplay", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sets the default X and Y grid setting on designers when LayoutMode = SnapToGrid.. + /// + public static string DesignerOptions_GridSizeDesc { + get { + return ResourceManager.GetString("DesignerOptions_GridSizeDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Default Grid Cell Size. + /// + public static string DesignerOptions_GridSizeDisplayName { + get { + return ResourceManager.GetString("DesignerOptions_GridSizeDisplayName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Layout Settings. + /// + public static string DesignerOptions_LayoutSettings { + get { + return ResourceManager.GetString("DesignerOptions_LayoutSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Controls whether designer smart tag windows should be shown by default.. + /// + public static string DesignerOptions_ObjectBoundSmartTagAutoShow { + get { + return ResourceManager.GetString("DesignerOptions_ObjectBoundSmartTagAutoShow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Automatically Open Smart Tags. + /// + public static string DesignerOptions_ObjectBoundSmartTagAutoShowDisplayName { + get { + return ResourceManager.GetString("DesignerOptions_ObjectBoundSmartTagAutoShowDisplayName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Object Bound Smart Tag Settings. + /// + public static string DesignerOptions_ObjectBoundSmartTagSettings { + get { + return ResourceManager.GetString("DesignerOptions_ObjectBoundSmartTagSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enabled optimized code generation. Some controls may not be compatible with this mode. For this change to take effect, Visual Studio must be closed and re-opened.. + /// + public static string DesignerOptions_OptimizedCodeGen { + get { + return ResourceManager.GetString("DesignerOptions_OptimizedCodeGen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Controls whether designers should display a sizing grid when LayoutMode = SnapToGrid.. + /// + public static string DesignerOptions_ShowGridDesc { + get { + return ResourceManager.GetString("DesignerOptions_ShowGridDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show Grid. + /// + public static string DesignerOptions_ShowGridDisplayName { + get { + return ResourceManager.GetString("DesignerOptions_ShowGridDisplayName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Controls whether designers should snap to grid dots when LayoutMode = SnapToGrid.. + /// + public static string DesignerOptions_SnapToGridDesc { + get { + return ResourceManager.GetString("DesignerOptions_SnapToGridDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Snap to Grid. + /// + public static string DesignerOptions_SnapToGridDisplayName { + get { + return ResourceManager.GetString("DesignerOptions_SnapToGridDisplayName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Controls whether designers should show smart tag popup windows.. + /// + public static string DesignerOptions_UseSmartTags { + get { + return ResourceManager.GetString("DesignerOptions_UseSmartTags", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Controls whether designers should use snap lines. If true, snap lines will be used as guides. If false, grid lines will be used.. + /// + public static string DesignerOptions_UseSnapLines { + get { + return ResourceManager.GetString("DesignerOptions_UseSnapLines", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dock in Parent Container. + /// + public static string DesignerShortcutDockInParent { + get { + return ResourceManager.GetString("DesignerShortcutDockInParent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Undock in Parent Container. + /// + public static string DesignerShortcutUndockInParent { + get { + return ResourceManager.GetString("DesignerShortcutUndockInParent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The container cannot be disposed at design time.. + /// + public static string DesignSurfaceContainerDispose { + get { + return ResourceManager.GetString("DesignSurfaceContainerDispose", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot create a view for this design surface because the designer is not loaded.. + /// + public static string DesignSurfaceDesignerNotLoaded { + get { + return ResourceManager.GetString("DesignSurfaceDesignerNotLoaded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + /// + /// {0}. + /// + public static string DesignSurfaceFatalError { + get { + return ResourceManager.GetString("DesignSurfaceFatalError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The designer loader did not provide a root component but has not indicated why.. + /// + public static string DesignSurfaceNoRootComponent { + get { + return ResourceManager.GetString("DesignSurfaceNoRootComponent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The designer loaded, but it does not offer a view compatible with this design surface.. + /// + public static string DesignSurfaceNoSupportedTechnology { + get { + return ResourceManager.GetString("DesignSurfaceNoSupportedTechnology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The service {0} cannot be removed from the service container.. + /// + public static string DesignSurfaceServiceIsFixed { + get { + return ResourceManager.GetString("DesignSurfaceServiceIsFixed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to .NET Component. + /// + public static string DotNET_ComponentType { + get { + return ResourceManager.GetString("DotNET_ComponentType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Drag {0} components. + /// + public static string DragDropDragComponents { + get { + return ResourceManager.GetString("DragDropDragComponents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move {0}. + /// + public static string DragDropMoveComponent { + get { + return ResourceManager.GetString("DragDropMoveComponent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move {0} components. + /// + public static string DragDropMoveComponents { + get { + return ResourceManager.GetString("DragDropMoveComponents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This IDataObject doesn't support SetData.. + /// + public static string DragDropSetDataError { + get { + return ResourceManager.GetString("DragDropSetDataError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Size {0}. + /// + public static string DragDropSizeComponent { + get { + return ResourceManager.GetString("DragDropSizeComponent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Size {0} components. + /// + public static string DragDropSizeComponents { + get { + return ResourceManager.GetString("DragDropSizeComponents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties.. + /// + public static string ExtenderProviderServiceDuplicateProvider { + get { + return ResourceManager.GetString("ExtenderProviderServiceDuplicateProvider", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Read-Only. + /// + public static string InheritanceServiceReadOnlyCollection { + get { + return ResourceManager.GetString("InheritanceServiceReadOnlyCollection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{1}' is not a valid value for '{0}'.. + /// + public static string InvalidArgument { + get { + return ResourceManager.GetString("InvalidArgument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}.. + /// + public static string InvalidBoundArgument { + get { + return ResourceManager.GetString("InvalidBoundArgument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Locked property determines if we can move or resize the control.. + /// + public static string lockedDescr { + get { + return ResourceManager.GetString("lockedDescr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This method/object is not implemented by design.. + /// + public static string NotImplementedByDesign { + get { + return ResourceManager.GetString("NotImplementedByDesign", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Winforms Designer is not supported on this platform.. + /// + public static string PlatformNotSupported_WinformsDesigner { + get { + return ResourceManager.GetString("PlatformNotSupported_WinformsDesigner", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to RTL_False. + /// + public static string RTL { + get { + return ResourceManager.GetString("RTL", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot create a new session because this serialization manager already has an active serialization session.. + /// + public static string SerializationManagerAreadyInSession { + get { + return ResourceManager.GetString("SerializationManagerAreadyInSession", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Duplicate declaration of member '{0}'. + /// + public static string SerializationManagerDuplicateComponentDecl { + get { + return ResourceManager.GetString("SerializationManagerDuplicateComponentDecl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The name '{0}' is already used by another object.. + /// + public static string SerializationManagerNameInUse { + get { + return ResourceManager.GetString("SerializationManagerNameInUse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' does not have a constructor with parameters of types {1}.. + /// + public static string SerializationManagerNoMatchingCtor { + get { + return ResourceManager.GetString("SerializationManagerNoMatchingCtor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This method cannot be invoked because the serialization manager does not have an active serialization session.. + /// + public static string SerializationManagerNoSession { + get { + return ResourceManager.GetString("SerializationManagerNoSession", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot name the object '{0}' because it is already named '{1}'.. + /// + public static string SerializationManagerObjectHasName { + get { + return ResourceManager.GetString("SerializationManagerObjectHasName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This method cannot be invoked because the serialization manager has an active serialization session.. + /// + public static string SerializationManagerWithinSession { + get { + return ResourceManager.GetString("SerializationManagerWithinSession", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.. + /// + public static string SerializerBadElementTypes { + get { + return ResourceManager.GetString("SerializerBadElementTypes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.. + /// + public static string SerializerFieldTargetEvalFailed { + get { + return ResourceManager.GetString("SerializerFieldTargetEvalFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.. + /// + public static string SerializerInvalidArrayRank { + get { + return ResourceManager.GetString("SerializerInvalidArrayRank", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.. + /// + public static string SerializerLostStatements { + get { + return ResourceManager.GetString("SerializerLostStatements", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Members of type '{0}' cannot be serialized.. + /// + public static string SerializerMemberTypeNotSerializable { + get { + return ResourceManager.GetString("SerializerMemberTypeNotSerializable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The source code contains a reference to the class definition, but the class definition cannot be found.. + /// + public static string SerializerNoRootExpression { + get { + return ResourceManager.GetString("SerializerNoRootExpression", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The object '{0}' failed to serialize itself. It may not support code generation.. + /// + public static string SerializerNoSerializerForComponent { + get { + return ResourceManager.GetString("SerializerNoSerializerForComponent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type '{0}' has no event named '{1}'.. + /// + public static string SerializerNoSuchEvent { + get { + return ResourceManager.GetString("SerializerNoSuchEvent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type '{0}' has no field named '{1}'.. + /// + public static string SerializerNoSuchField { + get { + return ResourceManager.GetString("SerializerNoSuchField", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type '{0}' has no property named '{1}'.. + /// + public static string SerializerNoSuchProperty { + get { + return ResourceManager.GetString("SerializerNoSuchProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error reading resources from the resource file for the culture {0}: {1}. + /// + public static string SerializerResourceException { + get { + return ResourceManager.GetString("SerializerResourceException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error reading resources from the resource file for the default culture: {0}. + /// + public static string SerializerResourceExceptionInvariant { + get { + return ResourceManager.GetString("SerializerResourceExceptionInvariant", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.. + /// + public static string SerializerTypeNotFound { + get { + return ResourceManager.GetString("SerializerTypeNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The variable '{0}' is either undeclared or was never assigned.. + /// + public static string SerializerUndeclaredName { + get { + return ResourceManager.GetString("SerializerUndeclaredName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &About.... + /// + public static string StandardMenuAbout { + get { + return ResourceManager.GetString("StandardMenuAbout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Contents. + /// + public static string StandardMenuContents { + get { + return ResourceManager.GetString("StandardMenuContents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Copy. + /// + public static string StandardMenuCopy { + get { + return ResourceManager.GetString("StandardMenuCopy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create Standard Menu. + /// + public static string StandardMenuCreateDesc { + get { + return ResourceManager.GetString("StandardMenuCreateDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Customize. + /// + public static string StandardMenuCustomize { + get { + return ResourceManager.GetString("StandardMenuCustomize", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cu&t. + /// + public static string StandardMenuCut { + get { + return ResourceManager.GetString("StandardMenuCut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Edit. + /// + public static string StandardMenuEdit { + get { + return ResourceManager.GetString("StandardMenuEdit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to E&xit. + /// + public static string StandardMenuExit { + get { + return ResourceManager.GetString("StandardMenuExit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &File. + /// + public static string StandardMenuFile { + get { + return ResourceManager.GetString("StandardMenuFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Help. + /// + public static string StandardMenuHelp { + get { + return ResourceManager.GetString("StandardMenuHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Index. + /// + public static string StandardMenuIndex { + get { + return ResourceManager.GetString("StandardMenuIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &New. + /// + public static string StandardMenuNew { + get { + return ResourceManager.GetString("StandardMenuNew", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Open. + /// + public static string StandardMenuOpen { + get { + return ResourceManager.GetString("StandardMenuOpen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Options. + /// + public static string StandardMenuOptions { + get { + return ResourceManager.GetString("StandardMenuOptions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Paste. + /// + public static string StandardMenuPaste { + get { + return ResourceManager.GetString("StandardMenuPaste", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Print. + /// + public static string StandardMenuPrint { + get { + return ResourceManager.GetString("StandardMenuPrint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Print Pre&view. + /// + public static string StandardMenuPrintPreview { + get { + return ResourceManager.GetString("StandardMenuPrintPreview", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Redo. + /// + public static string StandardMenuRedo { + get { + return ResourceManager.GetString("StandardMenuRedo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Save. + /// + public static string StandardMenuSave { + get { + return ResourceManager.GetString("StandardMenuSave", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save &As. + /// + public static string StandardMenuSaveAs { + get { + return ResourceManager.GetString("StandardMenuSaveAs", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Search. + /// + public static string StandardMenuSearch { + get { + return ResourceManager.GetString("StandardMenuSearch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select &All. + /// + public static string StandardMenuSelectAll { + get { + return ResourceManager.GetString("StandardMenuSelectAll", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Tools. + /// + public static string StandardMenuTools { + get { + return ResourceManager.GetString("StandardMenuTools", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Undo. + /// + public static string StandardMenuUndo { + get { + return ResourceManager.GetString("StandardMenuUndo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to C&ut. + /// + public static string StandardToolCut { + get { + return ResourceManager.GetString("StandardToolCut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to He&lp. + /// + public static string StandardToolHelp { + get { + return ResourceManager.GetString("StandardToolHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Argument should be a non-empty string.. + /// + public static string ToolboxItemInvalidKey { + get { + return ResourceManager.GetString("ToolboxItemInvalidKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Property {0} requires an argument of type {1}.. + /// + public static string ToolboxItemInvalidPropertyType { + get { + return ResourceManager.GetString("ToolboxItemInvalidPropertyType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toolbox item cannot be modified.. + /// + public static string ToolboxItemLocked { + get { + return ResourceManager.GetString("ToolboxItemLocked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Data type {0} is not serializable. Items added to a property dictionary must be serializable.. + /// + public static string ToolboxItemValueNotSerializable { + get { + return ResourceManager.GetString("ToolboxItemValueNotSerializable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dock:. + /// + public static string ToolStripActionList_Dock { + get { + return ResourceManager.GetString("ToolStripActionList_Dock", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Changes the Dock property. + /// + public static string ToolStripActionList_DockDesc { + get { + return ResourceManager.GetString("ToolStripActionList_DockDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GripStyle:. + /// + public static string ToolStripActionList_GripStyle { + get { + return ResourceManager.GetString("ToolStripActionList_GripStyle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Changes the GripStyle property. + /// + public static string ToolStripActionList_GripStyleDesc { + get { + return ResourceManager.GetString("ToolStripActionList_GripStyleDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Layout && Appearance. + /// + public static string ToolStripActionList_Layout { + get { + return ResourceManager.GetString("ToolStripActionList_Layout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to RenderMode:. + /// + public static string ToolStripActionList_RenderMode { + get { + return ResourceManager.GetString("ToolStripActionList_RenderMode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Changes the RenderMode property. + /// + public static string ToolStripActionList_RenderModeDesc { + get { + return ResourceManager.GetString("ToolStripActionList_RenderModeDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Adding {0} Item. + /// + public static string ToolStripAddingItem { + get { + return ResourceManager.GetString("ToolStripAddingItem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to AllowItemReorder and AllowDrop cannot both be true.. + /// + public static string ToolStripAllowItemReorderAndAllowDropCannotBeSetToTrue { + get { + return ResourceManager.GetString("ToolStripAllowItemReorderAndAllowDropCannotBeSetToTrue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ToolStrip New Item create Transaction.. + /// + public static string ToolStripCreatingNewItemTransaction { + get { + return ResourceManager.GetString("ToolStripCreatingNewItemTransaction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Embed in ToolStripContainer. + /// + public static string ToolStripDesignerEmbedVerb { + get { + return ResourceManager.GetString("ToolStripDesignerEmbedVerb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Embeds the current ToolStrip in ToolStripContainer. + /// + public static string ToolStripDesignerEmbedVerbDesc { + get { + return ResourceManager.GetString("ToolStripDesignerEmbedVerbDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Insert Standard Items. + /// + public static string ToolStripDesignerStandardItemsVerb { + get { + return ResourceManager.GetString("ToolStripDesignerStandardItemsVerb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Inserts standard items in the current ToolStrip. + /// + public static string ToolStripDesignerStandardItemsVerbDesc { + get { + return ResourceManager.GetString("ToolStripDesignerStandardItemsVerbDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type Here. + /// + public static string ToolStripDesignerTemplateNodeEnterText { + get { + return ResourceManager.GetString("ToolStripDesignerTemplateNodeEnterText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type Text for ToolStripMenuItem. + /// + public static string ToolStripDesignerTemplateNodeLabelToolTip { + get { + return ResourceManager.GetString("ToolStripDesignerTemplateNodeLabelToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add Menu Item. + /// + public static string ToolStripDesignerTemplateNodeSplitButtonStatusStripAccessibleName { + get { + return ResourceManager.GetString("ToolStripDesignerTemplateNodeSplitButtonStatusStripAccessibleName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add ToolStripStatusLabel. + /// + public static string ToolStripDesignerTemplateNodeSplitButtonStatusStripToolTip { + get { + return ResourceManager.GetString("ToolStripDesignerTemplateNodeSplitButtonStatusStripToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add ToolStripButton. + /// + public static string ToolStripDesignerTemplateNodeSplitButtonToolTip { + get { + return ResourceManager.GetString("ToolStripDesignerTemplateNodeSplitButtonToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New item selection. + /// + public static string ToolStripDesignerToolStripAccessibleName { + get { + return ResourceManager.GetString("ToolStripDesignerToolStripAccessibleName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Adding Item. + /// + public static string ToolStripDesignerTransactionAddingItem { + get { + return ResourceManager.GetString("ToolStripDesignerTransactionAddingItem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing Item. + /// + public static string ToolStripDesignerTransactionRemovingItem { + get { + return ResourceManager.GetString("ToolStripDesignerTransactionRemovingItem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Edit DropDownItems.... + /// + public static string ToolStripDropDownItemCollectionEditorVerb { + get { + return ResourceManager.GetString("ToolStripDropDownItemCollectionEditorVerb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ToolStrip MenuItem Insert in DropDown Transaction.. + /// + public static string ToolStripInsertingIntoDropDownTransaction { + get { + return ResourceManager.GetString("ToolStripInsertingIntoDropDownTransaction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Edit Items.... + /// + public static string ToolStripItemCollectionEditorVerb { + get { + return ResourceManager.GetString("ToolStripItemCollectionEditorVerb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Con&vert To. + /// + public static string ToolStripItemContextMenuConvertTo { + get { + return ResourceManager.GetString("ToolStripItemContextMenuConvertTo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Insert. + /// + public static string ToolStripItemContextMenuInsert { + get { + return ResourceManager.GetString("ToolStripItemContextMenuInsert", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set I&mage.... + /// + public static string ToolStripItemContextMenuSetImage { + get { + return ResourceManager.GetString("ToolStripItemContextMenuSetImage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ToolStripItem Property Change Transaction.. + /// + public static string ToolStripItemPropertyChangeTransaction { + get { + return ResourceManager.GetString("ToolStripItemPropertyChangeTransaction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ToolStripItem Morphing Transaction.. + /// + public static string ToolStripMorphingItemTransaction { + get { + return ResourceManager.GetString("ToolStripMorphingItemTransaction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}'. + /// + public static string ToolStripSelectMenuItem { + get { + return ResourceManager.GetString("ToolStripSelectMenuItem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot add ToolStripSeparator to MenuStrip.. + /// + public static string ToolStripSeparatorError { + get { + return ResourceManager.GetString("ToolStripSeparatorError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Auto Arrange Tray Icons. + /// + public static string TrayAutoArrange { + get { + return ResourceManager.GetString("TrayAutoArrange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Line Up Tray Icons. + /// + public static string TrayLineUpIcons { + get { + return ResourceManager.GetString("TrayLineUpIcons", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show Large or Small Icons. + /// + public static string TrayShowLargeIcons { + get { + return ResourceManager.GetString("TrayShowLargeIcons", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' is not available in the target framework.. + /// + public static string TypeNotFoundInTargetFramework { + get { + return ResourceManager.GetString("TypeNotFoundInTargetFramework", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error. + /// + public static string UIServiceHelper_ErrorCaption { + get { + return ResourceManager.GetString("UIServiceHelper_ErrorCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add Component. + /// + public static string UndoEngineComponentAdd0 { + get { + return ResourceManager.GetString("UndoEngineComponentAdd0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add {0}. + /// + public static string UndoEngineComponentAdd1 { + get { + return ResourceManager.GetString("UndoEngineComponentAdd1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change Component. + /// + public static string UndoEngineComponentChange0 { + get { + return ResourceManager.GetString("UndoEngineComponentChange0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change {0}. + /// + public static string UndoEngineComponentChange1 { + get { + return ResourceManager.GetString("UndoEngineComponentChange1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change {0}.{1}. + /// + public static string UndoEngineComponentChange2 { + get { + return ResourceManager.GetString("UndoEngineComponentChange2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove Component. + /// + public static string UndoEngineComponentRemove0 { + get { + return ResourceManager.GetString("UndoEngineComponentRemove0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove {0}. + /// + public static string UndoEngineComponentRemove1 { + get { + return ResourceManager.GetString("UndoEngineComponentRemove1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rename {0} to {1}. + /// + public static string UndoEngineComponentRename { + get { + return ResourceManager.GetString("UndoEngineComponentRename", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The service {0} is required but could not be found. If you have removed this service ensure that you provide a replacement.. + /// + public static string UndoEngineMissingService { + get { + return ResourceManager.GetString("UndoEngineMissingService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not implemented.. + /// + public static string UnsafeNativeMethodsNotImplemented { + get { + return ResourceManager.GetString("UnsafeNativeMethodsNotImplemented", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <couldn't find resource string "WindowsFormsAddEvent">. + /// + public static string WindowsFormsAddEvent { + get { + return ResourceManager.GetString("WindowsFormsAddEvent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Horizontal center of {0} component(s). + /// + public static string WindowsFormsCommandCenterX { + get { + return ResourceManager.GetString("WindowsFormsCommandCenterX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vertical center of {0} component(s). + /// + public static string WindowsFormsCommandCenterY { + get { + return ResourceManager.GetString("WindowsFormsCommandCenterY", resourceCulture); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/Resources/SR.resx b/src/System.Windows.Forms.Design/src/Resources/SR.resx index c76994d4e97..7593eb44755 100644 --- a/src/System.Windows.Forms.Design/src/Resources/SR.resx +++ b/src/System.Windows.Forms.Design/src/Resources/SR.resx @@ -214,7 +214,117 @@ Not implemented. - Could not find method '{0}' + Could not find method '{0}'. + + + Format {0} components (alignment) + + + Align {0} components to grid + + + Cut {0} Components + + + Delete {0} components + + + An error occurred while processing this command. + {0} + + + Format {0} components (spacing) + + + Paste components + + + Size {0} components + + + Size {0} components to grid + + + Unknown spacing command + + + Move {0} + + + Move {0} components + + + Horizontal center of {0} component(s) + + + Vertical center of {0} component(s) + + + Could not convert value '{0}' to the type '{1}'. + + + Could not find property '{0}' on '{1}'. + + + {0} Tasks + + + Error using the dropdown: {0} + + + Error invoking '{0}'. Details: {1} + + + Error setting value '{0}' to property '{1}'. Details: {2} + + + Inherited control + + + Inherited control (Private) + + + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + + + Auto Arrange Tray Icons + + + Line Up Tray Icons + + + Show Large or Small Icons + + + Error + + + <couldn't find resource string "WindowsFormsAddEvent"> + + + Copy and move {0} + + + Copy and move {0} Controls + + + Move {0} + + + Move {0} Controls + + + Call to BeginDrag must succeed before calling drag functions. + + + Drag {0} components + + + Size {0} + + + Size {0} components Add Component @@ -286,7 +396,9 @@ Cannot create a view for this design surface because the designer is not loaded. - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} The designer loader did not provide a root component but has not indicated why. @@ -300,15 +412,50 @@ The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. - - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + + Resize {0} + + + Resize {0} Controls + + + Dock in Parent Container + + + Undock in Parent Container + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + The Locked property determines if we can move or resize the control. + + + '{1}' is not a valid value for '{0}'. + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope. + + Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1. + + + Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization. + The source code contains a reference to the class definition, but the class definition cannot be found. + + The object '{0}' failed to serialize itself. It may not support code generation. + The type '{0}' has no event named '{1}'. @@ -318,11 +465,11 @@ The type '{0}' has no property named '{1}'. - - Error reading resources from the resource file for the culture {0}: {1} + + The object '{0}' returned null for the property '{1}' but this is not allowed. - - Error reading resources from the resource file for the default culture: {0} + + Code generation for property '{0}' failed. Error was: '{1}' Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. @@ -330,11 +477,176 @@ The variable '{0}' is either undeclared or was never assigned. + + &About... + + + &Contents + + + &Copy + + + Create Standard Menu + + + &Customize + + + Cu&t + + + &Edit + + + E&xit + + + &File + + + &Help + + + &Index + + + &New + + + &Open + + + &Options + + + &Paste + + + &Print + + + Print Pre&view + + + &Redo + + + &Save + + + Save &As + + + &Search + + + Select &All + + + &Tools + + + &Undo + + + C&ut + + + Dock: + + + Changes the Dock property + + + GripStyle: + + + Changes the GripStyle property + + + Layout && Appearance + + + RenderMode: + + + Changes the RenderMode property + + + Adding {0} Item + + + AllowItemReorder and AllowDrop cannot both be true. + + + ToolStrip New Item create Transaction. + + + Embed in ToolStripContainer + + + Embeds the current ToolStrip in ToolStripContainer + + + &Insert Standard Items + + + Inserts standard items in the current ToolStrip + + + Type Here + + + Type Text for ToolStripMenuItem + + + Add Menu Item + + + Add ToolStripStatusLabel + + + Add ToolStripButton + + + New item selection + + + Removing Item + + + ToolStrip MenuItem Insert in DropDown Transaction. + + + &Edit Items... + + + &Insert + + + ToolStripItem Property Change Transaction. + + + ToolStripItem Morphing Transaction. + + + Cannot add ToolStripSeparator to MenuStrip. + Type '{0}' is not available in the target framework. - - You cannot create a new session because this serialization manager already has an active serialization session. + + ShowCheckMargin + + + Toggles the ShowCheckMargin property + + + ShowImageMargin + + + Toggles the ShowImageMargin property Duplicate declaration of member '{0}' @@ -342,29 +654,29 @@ The name '{0}' is already used by another object. - - Type '{0}' does not have a constructor with parameters of types {1}. - - - This method cannot be invoked because the serialization manager does not have an active serialization session. - Cannot name the object '{0}' because it is already named '{1}'. - - This method cannot be invoked because the serialization manager has an active serialization session. + + Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - - Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization. + + Error reading resources from the resource file for the culture {0}: {1} - - The object '{0}' failed to serialize itself. It may not support code generation. + + Error reading resources from the resource file for the default culture: {0} - - Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1. + + Adding Item - - Members of type '{0}' cannot be serialized. + + &Edit DropDownItems... + + + Con&vert To + + + The serialization store is closed. New objects cannot be added to a closed store. Complete deserialization of {0} failed. @@ -372,7 +684,67 @@ This type of serialization store is not supported. Use a store returned by the CreateStore method. - - The serialization store is closed. New objects cannot be added to a closed store. + + Align To &Grid + + + &Bring To Front + + + C&opy + + + &Cut + + + &Delete + + + &Document Outline + + + &Lock Controls + + + &Paste + + + &Properties + + + &Select + + + &Send To Back + + + View &Code + + + You cannot create a new session because this serialization manager already has an active serialization session. + + + Type '{0}' does not have a constructor with parameters of types {1}. + + + This method cannot be invoked because the serialization manager does not have an active serialization session. + + + This method cannot be invoked because the serialization manager has an active serialization session. + + + Members of type '{0}' cannot be serialized. + + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + + + He&lp + + + Set I&mage... + + + '{0}' diff --git a/src/System.Windows.Forms.Design/src/Resources/System/WinForms/Design/InheritedGlyph.bmp b/src/System.Windows.Forms.Design/src/Resources/System/WinForms/Design/InheritedGlyph.bmp new file mode 100644 index 00000000000..0e493efc97c Binary files /dev/null and b/src/System.Windows.Forms.Design/src/Resources/System/WinForms/Design/InheritedGlyph.bmp differ diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf index f00bd3ca529..58e03b38bcc 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Kopírování a přesun - {0} + + + + Copy and move {0} Controls + Kopírování a přesun - {0} ovládacích prvků + + + + Move {0} + Přesunout: {0} + + + + Move {0} Controls + Přesun - {0} ovládacích prvků + + + + Resize {0} + Změnit velikost: {0} + + + + Resize {0} Controls + Změna velikosti - {0} ovládacích prvků + + The serialization store is closed. New objects cannot be added to a closed store. Úložiště serializace je zavřeno. Do zavřeného úložiště nelze přidávat nové objekty. @@ -17,6 +47,58 @@ Tento typ úložiště serializací není podporován. Použijte úložiště vrácené metodou CreateStore. + + Format {0} components (alignment) + Formátování (zarovnání) součástí (počet: {0}) + + + + Align {0} components to grid + Zarovnání součástí do mřížky (počet: {0}) + + + + Cut {0} Components + Vyjmutí součástí (počet: {0}) + + + + Delete {0} components + Odstranění součástí (počet: {0}) + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + Formátování (určení rozestupů) součástí (počet: {0}) + + + + Paste components + Vložení součástí + + + + Size {0} components + Změna velikosti součástí (počet: {0}) + + + + Size {0} components to grid + Změna velikosti součástí podle mřížky (počet: {0}) + + + + Unknown spacing command + Neznámý příkaz pro rozestupy + + Adding event '{0}' Přidání události {0} @@ -37,6 +119,151 @@ Nelze převést typ Integer na typ Float. + + Align To &Grid + &Zarovnat k mřížce + + + + &Bring To Front + &Přenést do popředí + + + + C&opy + &Kopírovat + + + + &Cut + &Vyjmout + + + + &Delete + O&dstranit + + + + &Document Outline + Osnova &dokumentu + + + + &Lock Controls + &Uzamknout ovládací prvky + + + + &Paste + &Vložit + + + + &Properties + &Vlastnosti + + + + &Select + Vybr&at + + + + &Send To Back + &Přenést do pozadí + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Přepíná vlastnost ShowCheckMargin. + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Přepíná vlastnost ShowImageMargin. + + + + View &Code + Zobrazit &kód + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + Hodnotu {0} nelze převést na typ {1}. + + + + Could not find method '{0}'. + Nebyla nalezena metoda {0}. + + + + Could not find property '{0}' on '{1}'. + Nebyla nalezena vlastnost {0} v {1}. + + + + {0} Tasks + {0} – úlohy + + + + Error using the dropdown: {0} + Chyba při použití rozevíracího seznamu: {0} + + + + Error invoking '{0}'. Details: {1} + Při spouštění {0} došlo k chybě. Podrobnosti: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Při nastavování hodnoty {0} vlastnosti {1} došlo k chybě. Podrobnosti: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Před voláním přetahovacích funkcí musí být úspěšně vyvolána funkce BeginDrag. + + + + Inherited control + Zděděný ovládací prvek + + + + Inherited control (Private) + Zděděný ovládací prvek (privátní) + + The container cannot be disposed at design time. Kontejner nelze uvolnit v době návrhu. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Při načítání dokumentu došlo k chybě. Opravte chybu a pak zkuste dokument načíst znovu. Následuje chybová zpráva:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ Službu {0} nelze odebrat z kontejneru služeb. - - Could not find method '{0}' - Nepovedlo se najít metodu {0}. - - Cannot remove or destroy inherited component '{0}'. Zděděnou součást {0} nelze odebrat nebo zrušit. @@ -222,16 +448,51 @@ Určuje, zda mají být v návrháři použity vodicí čáry. Pokud je tato vlastnost nastavena na hodnotu True, vodicí čáry budou použity jako vodítka. Pokud je tato vlastnost nastavena na hodnotu False, budou použity čáry mřížky. + + Dock in Parent Container + Ukotvit v nadřazeném kontejneru + + + + Undock in Parent Container + Zrušit ukotvení k nadřazenému kontejneru + + .NET Component Komponenta .NET + + Drag {0} components + Počet přetažených součástí: {0} + + + + Move {0} + Přesunout: {0} + + + + Move {0} components + Počet přesunutých součástí: {0} + + This IDataObject doesn't support SetData. Tento objekt IDataObject nepodporuje funkci SetData. + + Size {0} + Velikost {0} + + + + Size {0} components + Změna velikosti součástí (počet: {0}) + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Zprostředkovatel rozšířeného objektu {0} již byl přidán jako rozšiřující objekt. V případě přidání dalšího by došlo k duplicitě vlastností. @@ -242,6 +503,16 @@ Jen pro čtení + + '{1}' is not a valid value for '{0}'. + Hodnota {1} není platnou hodnotou pro argument {0}. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + Hodnota {1} není platnou hodnotou pro argument {0}. Hodnota {0} musí být v rozsahu od {2} do {3}. + + This method/object is not implemented by design. Tuto metodu nebo objekt návrh neimplementuje. @@ -252,6 +523,11 @@ Winforms Designer není na této platformě podporován. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Nelze vytvořit novou relaci, protože tento správce serializace již obsahuje aktivní relaci serializace. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Elementy typu {0} nejsou podporovány. Serializační procedura očekává, že se bude jednat o jeden z následujících elementů: {1}. @@ -337,6 +613,16 @@ Typ {0} neobsahuje žádnou vlastnost s názvem {1}. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Při čtení prostředků ze souboru prostředků jazykové verze {0} došlo k chybě: {1} @@ -347,6 +633,11 @@ Při čtení prostředků ze souboru prostředků výchozí jazykové verze došlo k chybě: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + Návrhář nemůže vytvořit požadovanou instanci typu {0}, protože typ je deklarován jako abstraktní. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Typ {0} nebyl nalezen. Zkontrolujte, zda je uveden odkaz na sestavení, které daný typ obsahuje. Je-li tento typ součástí vyvíjeného projektu, zkontrolujte, zda je projekt úspěšně sestaven pomocí nastavení pro aktuální platformu nebo libovolný procesor. @@ -357,6 +648,296 @@ Proměnná {0} není deklarována nebo jí dosud nebyla přiřazena hodnota. + + &About... + &O aplikaci... + + + + &Contents + &Obsah + + + + &Copy + &Kopírovat + + + + Create Standard Menu + Vytvořit standardní nabídku + + + + &Customize + &Přizpůsobit + + + + Cu&t + &Vyjmout + + + + &Edit + &Upravit + + + + E&xit + &Konec + + + + &File + &Soubor + + + + &Help + &Nápověda + + + + &Index + &Index + + + + &New + &Nový + + + + &Open + &Otevřít + + + + &Options + &Možnosti + + + + &Paste + &Vložit + + + + &Print + &Tisk + + + + Print Pre&view + Ná&hled + + + + &Redo + &Znovu + + + + &Save + &Uložit + + + + Save &As + Uložit j&ako + + + + &Search + &Hledat + + + + Select &All + &Vybrat vše + + + + &Tools + &Nástroje + + + + &Undo + &Zpět + + + + C&ut + &Vyjmout + + + + He&lp + &Nápověda + + + + Dock: + Dock: + + + + Changes the Dock property + Změní vlastnost Dock. + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Změní vlastnost GripStyle. + + + + Layout && Appearance + Rozložení a vzhled + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + Změní vlastnost RenderMode. + + + + Adding {0} Item + Přidání položky {0} + + + + AllowItemReorder and AllowDrop cannot both be true. + Vlastnosti AllowItemReorder a AllowDrop nemohou být současně nastaveny na hodnotu True. + + + + ToolStrip New Item create Transaction. + Transakce vytvoření nové položky prvku ToolStrip. + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Vloží aktuální prvek ToolStrip do prvku ToolStripContainer. + + + + &Insert Standard Items + &Vložit standardní položky + + + + Inserts standard items in the current ToolStrip + Vloží standardní položky do aktuálního prvku ToolStrip + + + + Type Here + Zadejte text + + + + Type Text for ToolStripMenuItem + Zadejte text prvku ToolStripMenuItem + + + + Add Menu Item + Přidat položku nabídky + + + + Add ToolStripStatusLabel + Přidat třídu ToolStripStatusLabel + + + + Add ToolStripButton + Přidat prvek ToolStripButton + + + + New item selection + Výběr nové položky + + + + Adding Item + Přidání položky + + + + Removing Item + Odebrání položky + + + + &Edit DropDownItems... + &Upravit vlastnost DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Vložení třídy MenuItem prvku ToolStrip v transakci prvku DropDown + + + + &Edit Items... + &Upravit položky... + + + + Con&vert To + &Převést na + + + + &Insert + &Vložit + + + + Set I&mage... + Nastavit &obrázek... + + + + ToolStripItem Property Change Transaction. + Transakce změny vlastnosti prvku ToolStripItem + + + + ToolStripItem Morphing Transaction. + Transakce morfingu prvku ToolStripItem + + + + '{0}' + {0} + + + + Cannot add ToolStripSeparator to MenuStrip. + Do prvku MenuStrip nelze přidat třídu ToolStripSeparator. + + Argument should be a non-empty string. Argument musí být neprázdný řetězec. @@ -377,11 +958,31 @@ Typ dat {0} není serializovatelný. Položky přidané do slovníku vlastností musí být serializovatelné. + + Auto Arrange Tray Icons + Automaticky uspořádat ikony hlavního panelu + + + + Line Up Tray Icons + Vyrovnat ikony hlavního panelu + + + + Show Large or Small Icons + Zobrazit velké nebo malé ikony + + Type '{0}' is not available in the target framework. Typ {0} není v cílové architektuře k dispozici. + + Error + Chyba + + Add Component Přidat součást @@ -432,6 +1033,26 @@ Není implementováno. + + <couldn't find resource string "WindowsFormsAddEvent"> + <řetězec prostředků WindowsFormsAddEvent nebyl nalezen> + + + + Horizontal center of {0} component(s) + Vodorovné zarovnání součástí na střed (počet: {0}) + + + + Vertical center of {0} component(s) + Svislé zarovnání součástí na střed (počet: {0}) + + + + The Locked property determines if we can move or resize the control. + Vlastnost Locked určuje, zda lze posunovat a měnit velikost ovládacího prvku. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf index 159cdb6d546..8d321463d56 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + {0} kopieren und verschieben + + + + Copy and move {0} Controls + {0} Steuerelemente kopieren und verschieben + + + + Move {0} + {0} verschieben + + + + Move {0} Controls + {0}-Steuerelemente verschieben + + + + Resize {0} + Größe von {0} ändern + + + + Resize {0} Controls + Größe von {0}-Steuerelementen ändern + + The serialization store is closed. New objects cannot be added to a closed store. Der Serialisierungsspeicher ist geschlossen. Neue Objekte können nicht zu einem geschlossenen Speicher hinzugefügt werden. @@ -17,6 +47,58 @@ Dieser Typ von Serialisierungsspeicher wird nicht unterstützt. Verwenden Sie einen Speicher, der von der CreateStore-Methode zurückgegeben wird. + + Format {0} components (alignment) + {0}-Komponenten formatieren (Ausrichtung) + + + + Align {0} components to grid + {0}-Komponenten am Raster ausrichten + + + + Cut {0} Components + {0}-Komponenten ausschneiden + + + + Delete {0} components + {0}-Komponenten löschen + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + {0}-Komponenten formatieren (Abstände) + + + + Paste components + Komponenten einfügen + + + + Size {0} components + {0}-Komponentengröße festlegen + + + + Size {0} components to grid + {0}-Komponentengröße an Raster anpassen + + + + Unknown spacing command + Unbekannter Befehl für Abstand + + Adding event '{0}' Das Ereignis {0} wird hinzugefügt. @@ -37,6 +119,151 @@ "Integer" kann nicht in "Float" konvertiert werden. + + Align To &Grid + Am &Raster ausrichten + + + + &Bring To Front + In den &Vordergrund + + + + C&opy + K&opieren + + + + &Cut + &Ausschneiden + + + + &Delete + &Löschen + + + + &Document Outline + &Dokumentgliederung + + + + &Lock Controls + &Steuerelemente sperren + + + + &Paste + &Einfügen + + + + &Properties + &Eigenschaften + + + + &Select + &Auswählen + + + + &Send To Back + &In den Hintergrund + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Schaltet die ShowCheckMargin -Eigenschaft um + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Schaltet die ShowImageMargin-Eigenschaft um + + + + View &Code + Code &anzeigen + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + Wert {0} konnte nicht in Typ {1} konvertiert werden. + + + + Could not find method '{0}'. + {0}-Methode konnte nicht gefunden werden. + + + + Could not find property '{0}' on '{1}'. + {0}-Eigenschaft für {1} konnte nicht gefunden werden. + + + + {0} Tasks + {0}-Aufgaben + + + + Error using the dropdown: {0} + Fehler beim Verwenden der Dropdownliste: {0} + + + + Error invoking '{0}'. Details: {1} + Fehler beim Aufrufen von {0}. Details: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Fehler beim Festlegen von {0}-Wert auf {1}-Eigenschaft. Details: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Der Aufruf von BeginDrag muss vor dem Aufrufen von Ziehfunktionen ausgeführt werden. + + + + Inherited control + Vererbtes Steuerelement + + + + Inherited control (Private) + Vererbtes Steuerelement (privat) + + The container cannot be disposed at design time. Der Container kann nicht zur Entwurfszeit verworfen werden. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Fehler beim Laden des Dokuments. Beheben Sie den Fehler, und wiederholen Sie den Vorgang. Fehlermeldung:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ Der Dienst {0} kann nicht aus dem Dienstcontainer entfernt werden. - - Could not find method '{0}' - {0}-Methode konnte nicht gefunden werden. - - Cannot remove or destroy inherited component '{0}'. Die vererbte Komponente {0} kann nicht gelöscht werden. @@ -222,16 +448,51 @@ Steuert, ob Designer Ausrichtungslinien verwenden. Wenn "true", werden Ausrichtungslinien als Führungslinien verwendet. Wenn "false", werden Rasterlinien verwendet. + + Dock in Parent Container + In übergeordnetem Container andocken + + + + Undock in Parent Container + In übergeordnetem Container abdocken + + .NET Component .NET-Komponente + + Drag {0} components + {0} Komponenten ziehen + + + + Move {0} + {0} verschieben + + + + Move {0} components + {0} Komponenten verschieben + + This IDataObject doesn't support SetData. Dieses IDataObject unterstützt SetData nicht. + + Size {0} + Größe {0} + + + + Size {0} components + {0}-Komponentengröße festlegen + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Der Extenderanbieter {0} wurde bereits als Extender hinzugefügt. Wenn ein weiterer hinzugefügt wird, führt dies zu doppelten Eigenschaften. @@ -242,6 +503,16 @@ Schreibgeschützt + + '{1}' is not a valid value for '{0}'. + {1} ist kein gültiger Wert für {0}. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + {1} ist kein gültiger Wert für {0}. {0} sollte zwischen {2} und {3} liegen. + + This method/object is not implemented by design. Diese Methode/dieses Objekt wird entwurfsbedingt nicht implementiert. @@ -252,6 +523,11 @@ Der Windows Forms-Designer wird auf dieser Plattform nicht unterstützt. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Sie können keine neue Sitzung erstellen, da dieser Serialisierungs-Manager bereits eine aktive Serialisierungssitzung besitzt. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Elemente des Typs "{0}" werden nicht unterstützt. Das Serialisierungsmodul erwartet für das Element einen der folgenden Typen: {1}. @@ -337,6 +613,16 @@ Der {0}-Typ besitzt keine Eigenschaft mit dem Namen {1}. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Fehler beim Lesen der Ressourcen aus der Ressourcendatei für die Kultur {0}: {1} @@ -347,6 +633,11 @@ Fehler beim Lesen der Ressourcen aus der Ressourcendatei für die Standardkultur: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + Der Designer kann keine Instanz des Typs {0} erstellen, da dieser als abstrakt deklariert ist. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Der Typ "{0}" wurde nicht gefunden. Stellen Sie sicher, dass auf die Assembly, die diesen Typ enthält, verwiesen wird. Wenn dieser Typ Teil Ihres Entwicklungsprojekts ist, stellen Sie sicher, dass das Projekt mithilfe der Einstellungen für die aktuelle Plattform oder eine beliebige CPU erstellt wurde. @@ -357,6 +648,296 @@ Die Variable {0} wurde nicht deklariert oder nicht zugeordnet. + + &About... + &Info... + + + + &Contents + I&nhalt + + + + &Copy + &Kopieren + + + + Create Standard Menu + Standardmenü erstellen + + + + &Customize + &Anpassen + + + + Cu&t + &Ausschneiden + + + + &Edit + &Bearbeiten + + + + E&xit + &Beenden + + + + &File + &Datei + + + + &Help + &Hilfe + + + + &Index + &Index + + + + &New + &Neu + + + + &Open + Ö&ffnen + + + + &Options + &Optionen + + + + &Paste + &Einfügen + + + + &Print + &Drucken + + + + Print Pre&view + &Seitenansicht + + + + &Redo + Wiede&rholen + + + + &Save + &Speichern + + + + Save &As + Speichern &unter + + + + &Search + &Suchen + + + + Select &All + &Alle auswählen + + + + &Tools + E&xtras + + + + &Undo + &Rückgängig + + + + C&ut + &Ausschneiden + + + + He&lp + Hi&lfe + + + + Dock: + Dock: + + + + Changes the Dock property + Ändert die Dock-Eigenschaft + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Ändert die GripStyle-Eigenschaft + + + + Layout && Appearance + Layout und Darstellung + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + Ändert die RenderMode-Eigenschaft + + + + Adding {0} Item + {0}-Element wird hinzugefügt + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder und AllowDrop können nicht beide "true" sein. + + + + ToolStrip New Item create Transaction. + Transaktion "Neues ToolStrip-Element erstellen". + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Bettet den aktuellen ToolStrip in den ToolStripContainer ein + + + + &Insert Standard Items + Standardelemente &einfügen + + + + Inserts standard items in the current ToolStrip + Fügt Standardelemente in den aktuellen ToolStrip ein + + + + Type Here + Hier eingeben + + + + Type Text for ToolStripMenuItem + Text für ToolStripMenuItem eingeben + + + + Add Menu Item + Menüelement hinzufügen + + + + Add ToolStripStatusLabel + ToolStripStatusLabel hinzufügen + + + + Add ToolStripButton + ToolStripButton hinzufügen + + + + New item selection + Neue Elementauswahl + + + + Adding Item + Element wird hinzugefügt + + + + Removing Item + Element wird entfernt + + + + &Edit DropDownItems... + DropDownItems &bearbeiten... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + "ToolStrip MenuItem Insert" in DropDown-Transaktion. + + + + &Edit Items... + Einträge &bearbeiten... + + + + Con&vert To + &Konvertieren in + + + + &Insert + &Einfügen + + + + Set I&mage... + Bild &festlegen... + + + + ToolStripItem Property Change Transaction. + Transaktion "ToolStripItem-Eigenschaft ändern". + + + + ToolStripItem Morphing Transaction. + Transaktion "ToolStripItem-Morphing". + + + + '{0}' + "{0}" + + + + Cannot add ToolStripSeparator to MenuStrip. + ToolStripSeparator kann nicht zu MenuStrip hinzugefügt werden. + + Argument should be a non-empty string. Das Argument muss eine nicht leere Zeichenfolge sein. @@ -377,11 +958,31 @@ Der Datentyp {0} kann nicht serialisiert werden. Elemente, die einem Eigenschaftswörterbuch hinzugefügt werden, müssen serialisierbar sein. + + Auto Arrange Tray Icons + Taskleistensymbole automatisch anordnen + + + + Line Up Tray Icons + Taskleistensymbole ausrichten + + + + Show Large or Small Icons + Große oder kleine Symbole anzeigen + + Type '{0}' is not available in the target framework. Der Typ "{0}" ist im Zielframework nicht vorhanden. + + Error + Fehler + + Add Component Komponente hinzufügen @@ -432,6 +1033,26 @@ Nicht implementiert. + + <couldn't find resource string "WindowsFormsAddEvent"> + <Ressourcenzeichenfolge "WindowsFormsAddEvent" konnte nicht gefunden werden> + + + + Horizontal center of {0} component(s) + {0} Komponenten horizontal zentrieren + + + + Vertical center of {0} component(s) + {0} Komponenten vertikal zentrieren + + + + The Locked property determines if we can move or resize the control. + Die Locked-Eigenschaft bestimmt, ob das Steuerelement verschoben oder seine Größe geändert werden kann. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf index ef492b1c52d..8231f74b729 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Copiar y mover {0} + + + + Copy and move {0} Controls + Copiar y mover controles {0} + + + + Move {0} + Mover {0} + + + + Move {0} Controls + Mover {0} controles + + + + Resize {0} + Cambiar tamaño de {0} + + + + Resize {0} Controls + Cambiar tamaño de {0} controles + + The serialization store is closed. New objects cannot be added to a closed store. El almacén de serialización está cerrado. No se pueden agregar nuevos objetos a un almacén cerrado. @@ -17,6 +47,58 @@ No se admite este tipo de almacén de serialización. Utilice un almacén devuelto por el método CreateStore. + + Format {0} components (alignment) + Dar formato a {0} componentes (alineación) + + + + Align {0} components to grid + Alinear {0} componentes a la cuadrícula + + + + Cut {0} Components + Cortar {0} componentes + + + + Delete {0} components + Eliminar {0} componentes + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + Dar formato a {0} componentes (espaciado) + + + + Paste components + Pegar componentes + + + + Size {0} components + Ajustar el tamaño de {0} componentes + + + + Size {0} components to grid + Ajustar el tamaño de {0} componentes a la cuadrícula + + + + Unknown spacing command + Comando de espaciado desconocido + + Adding event '{0}' Agregando un evento '{0}' @@ -37,6 +119,151 @@ No se puede convertir integer en float. + + Align To &Grid + &Alinear a la cuadrícula + + + + &Bring To Front + Traer al &frente + + + + C&opy + C&opiar + + + + &Cut + Co&rtar + + + + &Delete + &Eliminar + + + + &Document Outline + Esquema del docume&nto + + + + &Lock Controls + Bloquear co&ntroles + + + + &Paste + &Pegar + + + + &Properties + &Propiedades + + + + &Select + &Seleccionar + + + + &Send To Back + En&viar al fondo + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Alterna la propiedad ShowCheckMargin + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Alterna la propiedad ShowImageMargin + + + + View &Code + Ver códig&o + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + No se pudo convertir el valor '{0}' en el tipo '{1}'. + + + + Could not find method '{0}'. + No se pudo encontrar el método '{0}'. + + + + Could not find property '{0}' on '{1}'. + No se pudo encontrar la propiedad '{0}' en '{1}'. + + + + {0} Tasks + Tareas de {0} + + + + Error using the dropdown: {0} + Error al usar la lista desplegable: {0} + + + + Error invoking '{0}'. Details: {1} + Error al invocar '{0}'. Detalles: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Error al establecer el valor '{0}' en la propiedad '{1}'. Detalles: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Debe ejecutarse correctamente la llamada a BeginDrag antes de llamar a las funciones de arrastre. + + + + Inherited control + Control heredado + + + + Inherited control (Private) + Control heredado (privado) + + The container cannot be disposed at design time. El contenedor no se puede desechar en tiempo de diseño. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Error al cargar el documento. Corrija el error y, a continuación, intente volver a cargar el documento. Mensaje de error:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ No se puede eliminar el servicio {0} del contenedor de servicios. - - Could not find method '{0}' - No se encontró el método "{0}" - - Cannot remove or destroy inherited component '{0}'. No se puede quitar ni destruir un componente '{0}' heredado. @@ -222,16 +448,51 @@ Controla si los diseñadores deberían utilizar líneas de ajuste. Si es true, las líneas de ajuste se utilizarán como guías. Si es false, se utilizarán líneas de cuadrícula. + + Dock in Parent Container + Acoplar en contenedor primario + + + + Undock in Parent Container + Desacoplar en contenedor primario + + .NET Component Componente .NET + + Drag {0} components + Arrastrar {0} componentes + + + + Move {0} + Mover {0} + + + + Move {0} components + Mover {0} componentes + + This IDataObject doesn't support SetData. IDataObject no es compatible con SetData. + + Size {0} + Ajustar el tamaño de {0} + + + + Size {0} components + Ajustar el tamaño de {0} componentes + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. El proveedor extensor {0} ya se ha agregado como extensor. Si agrega otro habría propiedades duplicadas. @@ -242,6 +503,16 @@ Solo lectura + + '{1}' is not a valid value for '{0}'. + '{1}' no es un valor válido para '{0}'. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' no es un valor válido para '{0}'. '{0}' debería estar entre {2} y {3}. + + This method/object is not implemented by design. Este objeto o método no se implementa por diseño. @@ -252,6 +523,11 @@ Winforms Designer no se admite en esta plataforma. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. No puede crear una nueva sesión porque este administrador de serialización ya tiene una sesión de serialización activa. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + No se admiten elementos de tipo {0}. El serializador espera que el elemento sea uno de los siguientes: {1}. @@ -337,6 +613,16 @@ El tipo '{0}' no tiene ninguna propiedad denominada '{1}'. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Error al leer los recursos del archivo de recursos para la referencia cultural {0}: {1} @@ -347,6 +633,11 @@ Error al leer los recursos del archivo de recursos para la referencia cultural predeterminada: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + El diseñador debe crear una instancia de tipo '{0}', pero no se puede crear porque el tipo se ha declarado como abstracto. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. No se encuentra el tipo '{0}'. Asegúrese de que se hace referencia al ensamblado que contiene este tipo. Si el tipo forma parte de su proyecto de desarrollo, asegúrese de que el proyecto se haya compilado correctamente con el valor de la plataforma actual o Cualquier CPU. @@ -357,6 +648,296 @@ La variable '{0}' no está declarada o no se asignó nunca. + + &About... + &Acerca de... + + + + &Contents + &Contenido + + + + &Copy + &Copiar + + + + Create Standard Menu + Crear menú estándar + + + + &Customize + &Personalizar + + + + Cu&t + Cor&tar + + + + &Edit + &Editar + + + + E&xit + &Salir + + + + &File + Arc&hivo + + + + &Help + Ay&uda + + + + &Index + Índic&e + + + + &New + &Nuevo + + + + &Open + &Abrir + + + + &Options + &Opciones + + + + &Paste + &Pegar + + + + &Print + Im&primir + + + + Print Pre&view + &Vista previa de impresión + + + + &Redo + &Rehacer + + + + &Save + &Guardar + + + + Save &As + G&uardar como + + + + &Search + &Buscar + + + + Select &All + &Seleccionar todo + + + + &Tools + &Herramientas + + + + &Undo + &Deshacer + + + + C&ut + Cort&ar + + + + He&lp + Ay&uda + + + + Dock: + Dock: + + + + Changes the Dock property + Cambia la propiedad Dock + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Cambia la propiedad GripStyle + + + + Layout && Appearance + &Diseño y apariencia + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + Cambia la propiedad RenderMode + + + + Adding {0} Item + Agregando {0} elemento + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder y AllowDrop no pueden ser ambos true. + + + + ToolStrip New Item create Transaction. + Transacción de creación de nuevo elemento ToolStrip. + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Incrusta el ToolStrip actual en ToolStripContainer + + + + &Insert Standard Items + &Insertar elementos estándar + + + + Inserts standard items in the current ToolStrip + Inserta elementos estándar en el ToolStrip actual + + + + Type Here + Escriba aquí + + + + Type Text for ToolStripMenuItem + Escriba el texto para ToolStripMenuItem + + + + Add Menu Item + Agregar elemento de menú + + + + Add ToolStripStatusLabel + Agregar ToolStripStatusLabel + + + + Add ToolStripButton + Agregar ToolStripButton + + + + New item selection + Selección de nuevo elemento + + + + Adding Item + Agregando elemento + + + + Removing Item + Quitando elemento + + + + &Edit DropDownItems... + &Editar DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Inserción de MenuItem de ToolStrip en transacción DropDown. + + + + &Edit Items... + &Editar elementos... + + + + Con&vert To + &Convertir en + + + + &Insert + &Insertar + + + + Set I&mage... + &Establecer imagen... + + + + ToolStripItem Property Change Transaction. + Transacción de cambio de propiedad ToolStripItem. + + + + ToolStripItem Morphing Transaction. + Transacción de cambio de forma de ToolStripItem. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + No se puede agregar ToolStripSeparator a MenuStrip. + + Argument should be a non-empty string. El argumento no debe ser una cadena vacía. @@ -377,11 +958,31 @@ El tipo de datos {0} no se puede serializar. Los elementos agregados a un diccionario de propiedades deben ser serializables. + + Auto Arrange Tray Icons + Organizar automáticamente los iconos de la bandeja + + + + Line Up Tray Icons + Alinear los iconos de la bandeja + + + + Show Large or Small Icons + Mostrar iconos grandes o pequeños + + Type '{0}' is not available in the target framework. El tipo "{0}" no está disponible en la plataforma de destino. + + Error + Error + + Add Component Agregar componente @@ -432,6 +1033,26 @@ Sin implementar. + + <couldn't find resource string "WindowsFormsAddEvent"> + <no se pudo encontrar la cadena de recursos "WindowsFormsAddEvent"> + + + + Horizontal center of {0} component(s) + Centrado horizontal de {0} componentes + + + + Vertical center of {0} component(s) + Centrado vertical de {0} componentes + + + + The Locked property determines if we can move or resize the control. + La propiedad Locked determina si se puede mover o cambiar el tamaño del control. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf index 82d886050c4..34b4936cec0 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Copier et déplacer {0} + + + + Copy and move {0} Controls + Copier et déplacer les contrôles {0} + + + + Move {0} + Déplacer {0} + + + + Move {0} Controls + Déplacer les contrôles {0} + + + + Resize {0} + Redimensionner {0} + + + + Resize {0} Controls + Redimensionner les contrôles {0} + + The serialization store is closed. New objects cannot be added to a closed store. Le magasin de sérialisation est fermé. Impossible d'ajouter de nouveaux objets à un magasin fermé. @@ -17,6 +47,58 @@ Ce type de magasin de sérialisation n'est pas pris en charge. Utilisez un magasin retourné par la méthode CreateStore. + + Format {0} components (alignment) + Mettre en forme les composants {0} (alignement) + + + + Align {0} components to grid + Aligner les composants {0} sur la grille + + + + Cut {0} Components + Couper les composants {0} + + + + Delete {0} components + Supprimer les composants {0} + + + + An error occurred while processing this command. + {0} + Une erreur s'est produite durant le traitement de cette commande. + {0} + + + + Format {0} components (spacing) + Mettre en forme les composants {0} (espacement) + + + + Paste components + Coller les composants + + + + Size {0} components + Redimensionner les composants {0} + + + + Size {0} components to grid + Ajuster les composants {0} à la grille + + + + Unknown spacing command + Commande d'espacement inconnue + + Adding event '{0}' Ajout de l'événement '{0}' @@ -37,6 +119,151 @@ Impossible de convertir une valeur integer en float. + + Align To &Grid + &Aligner sur la grille + + + + &Bring To Front + Me&ttre au premier plan + + + + C&opy + C&opier + + + + &Cut + &Couper + + + + &Delete + &Supprimer + + + + &Document Outline + S&tructure du document + + + + &Lock Controls + V&errouiller les contrôles + + + + &Paste + &Coller + + + + &Properties + &Propriétés + + + + &Select + Sélec&tionner + + + + &Send To Back + &Mettre en arrière-plan + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Active/Désactive la propriété ShowCheckMargin + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Active/Désactive la propriété ShowImageMargin + + + + View &Code + Afficher le co&de + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + Le contrôle {0} a levé une exception non prise en charge dans le concepteur et a été désactivé. + + Exception : + {1} + + Arborescence des appels de procédure : {2} + + + + Could not convert value '{0}' to the type '{1}'. + Impossible de convertir la valeur '{0}' en type '{1}'. + + + + Could not find method '{0}'. + Impossible de trouver la méthode '{0}'. + + + + Could not find property '{0}' on '{1}'. + Impossible de trouver la propriété '{0}' sur '{1}'. + + + + {0} Tasks + Tâches {0} + + + + Error using the dropdown: {0} + Erreur lors de l'utilisation du menu déroulant : {0} + + + + Error invoking '{0}'. Details: {1} + Erreur lors de l'appel de '{0}'. Détails : {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Erreur lors de l'affectation de la valeur '{0}' à la propriété '{1}'. Détails : {2} + + + + Call to BeginDrag must succeed before calling drag functions. + L'appel à BeginDrag doit avoir lieu avant l'appel aux fonctions de glissement. + + + + Inherited control + Contrôle hérité + + + + Inherited control (Private) + Contrôle hérité (privé) + + The container cannot be disposed at design time. Le conteneur ne peut pas être supprimé au moment du design. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Une erreur s'est produite durant le chargement du document. Corrigez l'erreur, puis essayez de recharger le document. Message d'erreur :\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + Une erreur s'est produite durant le chargement du document. Corrigez l'erreur, puis essayez de recharger le document. Message d'erreur : + + {0} @@ -67,11 +298,6 @@ Impossible de supprimer le service {0} dans le conteneur de service. - - Could not find method '{0}' - Méthode '{0}' introuvable - - Cannot remove or destroy inherited component '{0}'. Impossible d'enlever ou de détruire le composant hérité '{0}'. @@ -222,16 +448,51 @@ Contrôle si les concepteurs doivent utiliser des lignes d'alignement. Si tel est le cas, les lignes d'alignement sont utilisées à titre de guides. Dans le cas contraire, un quadrillage est utilisé. + + Dock in Parent Container + Ancrer dans le conteneur parent + + + + Undock in Parent Container + Annuler l'ancrage dans le conteneur parent + + .NET Component Composant .NET + + Drag {0} components + Faire glisser les composants {0} + + + + Move {0} + Déplacer {0} + + + + Move {0} components + Déplacer les composants {0} + + This IDataObject doesn't support SetData. Ce IDataObject ne prend pas en charge SetData. + + Size {0} + Dimensionner {0} + + + + Size {0} components + Redimensionner les composants {0} + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Le fournisseur d'extendeurs {0} a déjà été ajouté en tant qu'extendeur. L'ajout d'un autre créerait des propriétés en double. @@ -242,6 +503,16 @@ En lecture seule + + '{1}' is not a valid value for '{0}'. + '{1}' n'est pas une valeur valide pour '{0}'. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' n'est pas une valeur valide pour '{0}'. '{0}' doit être compris entre {2} et {3}. + + This method/object is not implemented by design. Cette méthode ou cet objet n'est pas implémenté(e) dans la conception. @@ -252,6 +523,11 @@ Le concepteur WinForms n'est pas pris en charge sur cette plateforme. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Vous ne pouvez pas créer une nouvelle session, car ce gestionnaire de sérialisation dispose déjà d'une session de sérialisation active. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Les éléments de type {0} ne sont pas pris en charge. Le sérialiseur nécessite un élément appartenant à l'un des types suivants : {1}. @@ -337,6 +613,16 @@ Le type '{0}' n'a pas de propriété nommée '{1}'. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Erreur lors de la lecture des ressources à partir du fichier de ressources pour la culture {0} : {1} @@ -347,6 +633,11 @@ Erreur lors de la lecture des ressources à partir du fichier de ressources pour la culture par défaut : {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + Le concepteur doit créer une instance de type '{0}' mais il ne peut pas, car le type est déclaré comme abstract. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Type '{0}' introuvable. Vérifiez que l'assembly qui contient ce type est référencé. Si ce type est un composant de votre projet de développement, assurez-vous que le projet a été créé comme il se doit à l'aide des paramètres de votre plateforme actuelle ou Any CPU. @@ -357,6 +648,296 @@ La variable '{0}' n'est pas déclarée ou n'a jamais été assignée. + + &About... + &À propos de... + + + + &Contents + &Contenu + + + + &Copy + &Copier + + + + Create Standard Menu + Créer un menu standard + + + + &Customize + &Personnaliser + + + + Cu&t + Co&uper + + + + &Edit + &Edition + + + + E&xit + &Quitter + + + + &File + &Fichier + + + + &Help + &Aide + + + + &Index + &Index + + + + &New + &Nouveau + + + + &Open + &Ouvrir + + + + &Options + &Options + + + + &Paste + &Coller + + + + &Print + I&mprimer + + + + Print Pre&view + Aperçu a&vant impression + + + + &Redo + &Rétablir + + + + &Save + &Enregistrer + + + + Save &As + Enregistrer &sous + + + + &Search + &Rechercher + + + + Select &All + Sélectionner &tout + + + + &Tools + Ou&tils + + + + &Undo + &Annuler + + + + C&ut + C&ouper + + + + He&lp + &? + + + + Dock: + Dock : + + + + Changes the Dock property + Modifie la propriété Dock + + + + GripStyle: + GripStyle : + + + + Changes the GripStyle property + Modifie la propriété GripStyle + + + + Layout && Appearance + &Disposition et apparence + + + + RenderMode: + RenderMode : + + + + Changes the RenderMode property + Modifie la propriété RenderMode + + + + Adding {0} Item + Ajout de l'élément {0} + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder et AllowDrop ne peuvent pas être true en même temps. + + + + ToolStrip New Item create Transaction. + Transaction Création d'un nouvel élément ToolStrip. + + + + Embed in ToolStripContainer + Incorporer dans ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Incorpore le ToolStrip actuel dans ToolStripContainer + + + + &Insert Standard Items + &Insérer des éléments standard + + + + Inserts standard items in the current ToolStrip + Insère les éléments standard dans le ToolStrip actuel + + + + Type Here + Tapez ici + + + + Type Text for ToolStripMenuItem + Tapez le texte de ToolStripMenuItem + + + + Add Menu Item + Ajouter un élément de menu + + + + Add ToolStripStatusLabel + Ajouter ToolStripStatusLabel + + + + Add ToolStripButton + Ajouter ToolStripButton + + + + New item selection + Nouvelle sélection d'élément + + + + Adding Item + Ajout de l'élément + + + + Removing Item + Suppression de l'élément + + + + &Edit DropDownItems... + &Modifier les DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Transaction Insertion d'un MenuItem ToolStrip dans DropDown. + + + + &Edit Items... + &Modifier les éléments... + + + + Con&vert To + Con&vertir en + + + + &Insert + &Insérer + + + + Set I&mage... + Définir l'i&mage... + + + + ToolStripItem Property Change Transaction. + Transaction Modification des propriétés d'un ToolStripItem. + + + + ToolStripItem Morphing Transaction. + Transaction Transformation de ToolStripItem. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + Impossible d'ajouter ToolStripSeparator à MenuStrip. + + Argument should be a non-empty string. L'argument ne peut pas être une chaîne vide. @@ -377,11 +958,31 @@ Le type de données {0} n'est pas sérialisable. Les éléments ajoutés à un dictionnaire de propriétés doivent être sérialisables. + + Auto Arrange Tray Icons + Réorganiser automatiquement les icônes de la barre d'état système + + + + Line Up Tray Icons + Aligner les icônes de la barre d'état système + + + + Show Large or Small Icons + Afficher les grandes ou les petites icônes + + Type '{0}' is not available in the target framework. Le type '{0}' n'est pas disponible dans le Framework cible. + + Error + Erreur + + Add Component Ajouter un composant @@ -432,6 +1033,26 @@ Non implémenté. + + <couldn't find resource string "WindowsFormsAddEvent"> + <la chaîne de ressource "WindowsFormsAddEvent" est introuvable> + + + + Horizontal center of {0} component(s) + Centre horizontal des composants {0} + + + + Vertical center of {0} component(s) + Centre vertical des composants {0} + + + + The Locked property determines if we can move or resize the control. + La propriété Locked détermine si le contrôle peut être déplacé ou redimensionné. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf index e0b9a585395..28315146eca 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Copia e sposta {0} + + + + Copy and move {0} Controls + Copia e sposta {0} controlli + + + + Move {0} + Sposta {0} + + + + Move {0} Controls + Sposta {0} controlli + + + + Resize {0} + Ridimensiona {0} + + + + Resize {0} Controls + Ridimensiona {0} controlli + + The serialization store is closed. New objects cannot be added to a closed store. L'archivio di serializzazione è chiuso. Non è possibile aggiungere nuovi oggetti a un archivio chiuso. @@ -17,6 +47,58 @@ Questo tipo di archivio di serializzazione non è supportato. Usare un archivio restituito dal metodo CreateStore. + + Format {0} components (alignment) + Formatta {0} componenti (allineamento) + + + + Align {0} components to grid + Allinea {0} componenti alla griglia + + + + Cut {0} Components + Taglia {0} componenti + + + + Delete {0} components + Elimina {0} componenti + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + Formatta {0} componenti (spaziatura) + + + + Paste components + Incolla componenti + + + + Size {0} components + Ridimensiona {0} componenti + + + + Size {0} components to grid + Adatta {0} componenti alla griglia + + + + Unknown spacing command + Comando di spaziatura sconosciuto + + Adding event '{0}' Aggiunta evento '{0}' @@ -37,6 +119,151 @@ Impossibile convertire un numero intero in un valore float. + + Align To &Grid + &Allinea alla griglia + + + + &Bring To Front + &Porta in primo piano + + + + C&opy + C&opia + + + + &Cut + &Taglia + + + + &Delete + &Elimina + + + + &Document Outline + S&truttura documento + + + + &Lock Controls + &Blocca controlli + + + + &Paste + &Incolla + + + + &Properties + &Proprietà + + + + &Select + &Seleziona + + + + &Send To Back + Porta in &secondo piano + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Attiva o disattiva la proprietà ShowCheckMargin. + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Attiva o disattiva la proprietà ShowImageMargin. + + + + View &Code + Visuali&zza codice + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + Impossibile convertire il valore '{0}' nel tipo '{1}'. + + + + Could not find method '{0}'. + Impossibile trovare il metodo '{0}'. + + + + Could not find property '{0}' on '{1}'. + Impossibile trovare la proprietà '{0}' in '{1}'. + + + + {0} Tasks + Attività di {0} + + + + Error using the dropdown: {0} + Errore durante l'utilizzo del menu a discesa: {0} + + + + Error invoking '{0}'. Details: {1} + Errore durante la chiamata a '{0}'. Dettagli: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Errore durante l'impostazione del valore '{0}' sulla proprietà '{1}'. Dettagli: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Prima di chiamare le funzioni di trascinamento, è necessario eseguire correttamente una chiamata a BeginDrag. + + + + Inherited control + Controllo ereditato + + + + Inherited control (Private) + Controllo ereditato (Private) + + The container cannot be disposed at design time. Impossibile eliminare il contenitore in fase di progettazione. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Si è verificato un errore durante il caricamento del documento. Correggere l'errore e provare nuovamente a caricare il documento. Messaggio di errore:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ Impossibile rimuovere il servizio {0} dal contenitore dei servizi. - - Could not find method '{0}' - Non è stato possibile trovare il metodo '{0}' - - Cannot remove or destroy inherited component '{0}'. Impossibile rimuovere o eliminare in modo permanente il componente ereditato '{0}'. @@ -222,16 +448,51 @@ Controlla se nelle finestre di progettazione devono essere utilizzate guide di allineamento. Se è true, le guide di allineamento verranno utilizzate come riferimento. In caso contrario, verranno utilizzare le linee della griglia. + + Dock in Parent Container + Ancora nel contenitore padre + + + + Undock in Parent Container + Disancora nel contenitore padre + + .NET Component Componente .NET + + Drag {0} components + Trascina componenti {0} + + + + Move {0} + Sposta {0} + + + + Move {0} components + Sposta {0} componenti + + This IDataObject doesn't support SetData. Questo oggetto IDataObject non supporta SetData. + + Size {0} + Ridimensiona {0} + + + + Size {0} components + Ridimensiona {0} componenti + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Il provider di Extender {0} è già stato aggiunto come Extender. Aggiungendone un altro si creerebbero proprietà duplicate. @@ -242,6 +503,16 @@ Sola lettura + + '{1}' is not a valid value for '{0}'. + '{1}' non è un valore valido per '{0}'. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' non è un valore valido per '{0}'. '{0}' deve essere compreso tra {2} e {3}. + + This method/object is not implemented by design. Questo metodo/oggetto non è implementato per impostazione predefinita. @@ -252,6 +523,11 @@ Winforms Designer non è supportato in questa piattaforma. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Non è possibile creare una nuova sessione perché per questo gestore di serializzazione esiste già una sessione di serializzazione attiva. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Gli elementi di tipo {0} non sono supportati. Nel serializzatore è previsto uno degli elementi seguenti: {1}. @@ -337,6 +613,16 @@ Il tipo '{0}' non dispone di alcuna proprietà denominata '{1}'. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Errore durante la lettura delle risorse dal file di risorse per le impostazioni cultura {0}: {1} @@ -347,6 +633,11 @@ Errore durante la lettura delle risorse dal file di risorse per le impostazioni cultura predefinite: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + La finestra di progettazione deve creare un'istanza di tipo '{0}', ma non può perché il tipo è dichiarato come astratto. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Il tipo '{0}' non è stato trovato. Verificare la presenza di un riferimento all'assembly che lo contiene. Se il tipo fa parte del progetto di sviluppo, assicurarsi che quest'ultimo sia stato compilato correttamente usando le impostazioni per la piattaforma corrente o Any CPU. @@ -357,6 +648,296 @@ La variabile '{0}' non è stata dichiarata o non è mai stata assegnata. + + &About... + &Informazioni su... + + + + &Contents + &Sommario + + + + &Copy + &Copia + + + + Create Standard Menu + Crea menu standard + + + + &Customize + &Personalizza + + + + Cu&t + &Taglia + + + + &Edit + &Modifica + + + + E&xit + E&sci + + + + &File + &File + + + + &Help + &? + + + + &Index + &Indice + + + + &New + &Nuovo + + + + &Open + &Apri + + + + &Options + &Opzioni + + + + &Paste + &Incolla + + + + &Print + &Stampa + + + + Print Pre&view + &Anteprima di stampa + + + + &Redo + &Ripristina + + + + &Save + &Salva + + + + Save &As + Salva &con nome + + + + &Search + &Cerca + + + + Select &All + Seleziona &tutto + + + + &Tools + &Strumenti + + + + &Undo + &Annulla + + + + C&ut + &Taglia + + + + He&lp + &? + + + + Dock: + Dock: + + + + Changes the Dock property + Modifica la proprietà Dock. + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Modifica la proprietà GripStyle. + + + + Layout && Appearance + &Layout e aspetto + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + Modifica la proprietà RenderMode. + + + + Adding {0} Item + Aggiunta dell'elemento {0} in corso... + + + + AllowItemReorder and AllowDrop cannot both be true. + Le proprietà AllowItemReorder e AllowDrop non possono avere entrambe valore true. + + + + ToolStrip New Item create Transaction. + Transazione Crea nuovo elemento del controllo ToolStrip + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Incorpora l'elemento ToolStrip corrente in ToolStripContainer. + + + + &Insert Standard Items + &Inserisci elementi standard + + + + Inserts standard items in the current ToolStrip + Inserisce elementi standard nell'elemento ToolStrip corrente. + + + + Type Here + Digitare qui + + + + Type Text for ToolStripMenuItem + Digitare un testo per ToolStripMenuItem. + + + + Add Menu Item + Aggiungi voce di menu + + + + Add ToolStripStatusLabel + Aggiungi ToolStripStatusLabel + + + + Add ToolStripButton + Aggiungi ToolStripButton + + + + New item selection + Selezione nuovo elemento + + + + Adding Item + Aggiunta di un elemento in corso... + + + + Removing Item + Rimozione di un elemento in corso... + + + + &Edit DropDownItems... + &Modifica DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Inserisci elemento MenuItem di un controllo ToolStrip in transazione DropDown + + + + &Edit Items... + &Modifica elementi... + + + + Con&vert To + Con&verti in + + + + &Insert + &Inserisci + + + + Set I&mage... + I&mposta immagine... + + + + ToolStripItem Property Change Transaction. + Transazione Modifica proprietà del controllo ToolStripItem. + + + + ToolStripItem Morphing Transaction. + Transazione Morphing del controllo ToolStripItem. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + Impossibile aggiungere ToolStripSeparator a MenuStrip. + + Argument should be a non-empty string. L'argomento deve essere una stringa non vuota. @@ -377,11 +958,31 @@ Tipo di dati {0} non serializzabile. Gli elementi aggiunti a un dizionario di proprietà devono essere serializzabili. + + Auto Arrange Tray Icons + Disponi automaticamente icone della barra delle applicazioni + + + + Line Up Tray Icons + Allinea icone della barra delle applicazioni + + + + Show Large or Small Icons + Mostra icone grandi o piccole + + Type '{0}' is not available in the target framework. Il tipo '{0}' non è disponibile nel framework di destinazione. + + Error + Errore + + Add Component Aggiungi componente @@ -432,6 +1033,26 @@ Non implementato. + + <couldn't find resource string "WindowsFormsAddEvent"> + <impossibile trovare la stringa di risorsa "WindowsFormsAddEvent"> + + + + Horizontal center of {0} component(s) + Centro orizzontale di {0} componente/i + + + + Vertical center of {0} component(s) + Centro verticale di {0} componente/i + + + + The Locked property determines if we can move or resize the control. + La proprietà Locked determina se è possibile spostare o ridimensionare il controllo. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf index ebbcc02a293..53c89b26648 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + {0} のコピーおよび移動 + + + + Copy and move {0} Controls + {0} コントロールのコピーおよび移動 + + + + Move {0} + {0} の移動 + + + + Move {0} Controls + {0} コントロールの移動 + + + + Resize {0} + {0} のサイズ変更 + + + + Resize {0} Controls + {0} コントロールのサイズの変更 + + The serialization store is closed. New objects cannot be added to a closed store. シリアル化ストアは閉じられています。 閉じられたストアに新しいオブジェクトを追加することはできません。 @@ -17,6 +47,58 @@ シリアル化ストアのこの型はサポートされていません。 CreateStore メソッドによって返されたストアを使用してください。 + + Format {0} components (alignment) + {0} コンポーネントを設定する (配置) + + + + Align {0} components to grid + {0} コンポーネントをグリッドに合わせる + + + + Cut {0} Components + {0} コンポーネントを切り取る + + + + Delete {0} components + {0} コンポーネントを削除する + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + {0} コンポーネントのフォーマット (スペース) + + + + Paste components + コンポーネントの貼り付け + + + + Size {0} components + {0} コンポーネントのサイズを変更 + + + + Size {0} components to grid + {0} コンポーネントのサイズをグリッドに合わせて変更 + + + + Unknown spacing command + 不明なスペース コマンド + + Adding event '{0}' イベント '{0}' の追加 @@ -37,6 +119,151 @@ integer を float に変換できません。 + + Align To &Grid + グリッドに配置(&G) + + + + &Bring To Front + 最前面へ移動(&B) + + + + C&opy + コピー(&O) + + + + &Cut + 切り取り(&C) + + + + &Delete + 削除(&D) + + + + &Document Outline + ドキュメント アウトライン(&T) + + + + &Lock Controls + コントロールのロック(&L) + + + + &Paste + 貼り付け(&P) + + + + &Properties + プロパティ(&P) + + + + &Select + 選択(&S) + + + + &Send To Back + 最背面へ移動(&S) + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + ShowCheckMargin プロパティの切り替え + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + ShowImageMargin プロパティの切り替え + + + + View &Code + コードの表示(&C) + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + 値 '{0}' を型 '{1}' に変換できませんでした。 + + + + Could not find method '{0}'. + メソッド '{0}' が見つかりませんでした。 + + + + Could not find property '{0}' on '{1}'. + '{1}' 上にプロパティ '{0}' が見つかりませんでした。 + + + + {0} Tasks + {0} タスク + + + + Error using the dropdown: {0} + ドロップダウンの使用時にエラーが発生しました:{0} + + + + Error invoking '{0}'. Details: {1} + '{0}' の呼び出し中にエラーが発生しました。 詳細:{1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + 値 '{0}' をプロパティ '{1}' に設定中にエラーが発生しました。 詳細情報:{2} + + + + Call to BeginDrag must succeed before calling drag functions. + ドラッグ関数を呼び出す前に BeginDrag への呼び出しを完了しなければなりません。 + + + + Inherited control + 継承されたコントロール + + + + Inherited control (Private) + 継承コントロール (プライベート) + + The container cannot be disposed at design time. デザイン時に、コンテナーを破棄することはできません。 @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - ドキュメントの読み込み中にエラーが発生しました。このエラーを修正してから、もう一度ドキュメントを読み込んでください。エラー メッセージは以下のとおりです。\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ サービス {0} をサービス コンテナーから削除できません。 - - Could not find method '{0}' - メソッド '{0}' が見つかりませんでした - - Cannot remove or destroy inherited component '{0}'. 継承コンポーネント '{0}' を削除または破棄できません。 @@ -222,16 +448,51 @@ デザイナーでスナップ線を使用するかどうかを制御します。 true の場合、スナップ線がガイドとして使用されます。 false の場合、グリッド線が使用されます。 + + Dock in Parent Container + 親コンテナーにドッキングする + + + + Undock in Parent Container + 親コンテナーでドッキングを解除する + + .NET Component .NET コンポーネント + + Drag {0} components + {0} 個のコンポーネントをドラッグする + + + + Move {0} + {0} の移動 + + + + Move {0} components + {0} 個のコンポーネントを移動 + + This IDataObject doesn't support SetData. この IDataObject は SetData をサポートしていません。 + + Size {0} + サイズ {0} + + + + Size {0} components + {0} コンポーネントのサイズを変更 + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. 拡張プロバイダー {0} はエクステンダーとして既に追加されています。 もう 1 つ追加すると、プロパティが重複します。 @@ -242,6 +503,16 @@ 読み取り専用 + + '{1}' is not a valid value for '{0}'. + '{1}' は '{0}' に有効な値ではありません。 + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' は '{0}' に有効な値ではありません。'{0}' は {2} と {3} の間でなければなりません。 + + This method/object is not implemented by design. このメソッド/オブジェクトはデザインによって実装されていません。 @@ -252,6 +523,11 @@ Windows フォーム デザイナーは、このプラットフォームではサポートされていません。 + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. このシリアル化マネージャーにはアクティブなシリアル化セッションが既に存在するため、新しいセッションを作成できません。 @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + 型 {0} の要素はサポートされていません。シリアライザーでは要素に次のうちの 1 つが指定されている必要があります: {1}。 @@ -337,6 +613,16 @@ 型 '{0}' に '{1}' という名前のプロパティはありません。 + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} カルチャ {0} のリソース ファイルからリソースを読み取り中にエラーが発生しました:{1} @@ -347,6 +633,11 @@ 既定カルチャのリソース ファイルからリソースを読み取り中にエラーが発生しました:{0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + デザイナーは型 '{0}' のインスタンスを作成しなければなりませんが、型が abstract として宣言されているため、作成できませんでした。 + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. 型 '{0}' が見つかりませんでした。 この型を含むアセンブリが参照されていることを確認してください。 この型が開発プロジェクトの一部である場合は、現在のプラットフォームまたは Any CPU の設定を使用して、プロジェクトが正常にビルドされていることを確認してください。 @@ -357,6 +648,296 @@ 変数 '{0}' は宣言されていないか、または割り当てられていません。 + + &About... + バージョン情報(&A)... + + + + &Contents + 内容(&C) + + + + &Copy + コピー(&C) + + + + Create Standard Menu + 標準メニューの作成 + + + + &Customize + カスタマイズ(&C) + + + + Cu&t + 切り取り(&T) + + + + &Edit + 編集(&E) + + + + E&xit + 終了(&X) + + + + &File + ファイル(&F) + + + + &Help + ヘルプ(&H) + + + + &Index + インデックス(&I) + + + + &New + 新規作成(&N) + + + + &Open + 開く(&O) + + + + &Options + オプション(&O) + + + + &Paste + 貼り付け(&P) + + + + &Print + 印刷(&P) + + + + Print Pre&view + 印刷プレビュー(&V) + + + + &Redo + やり直し(&R) + + + + &Save + 保存(&S) + + + + Save &As + 名前を付けて保存(&A) + + + + &Search + 検索(&S) + + + + Select &All + すべて選択(&A) + + + + &Tools + ツール(&T) + + + + &Undo + 元に戻す(&U) + + + + C&ut + 切り取り(&U) + + + + He&lp + ヘルプ(&L) + + + + Dock: + Dock: + + + + Changes the Dock property + Dock プロパティを変更します + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + GripStyle プロパティを変更します + + + + Layout && Appearance + レイアウトおよび表示 + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + RenderMode プロパティを変更します + + + + Adding {0} Item + {0} 項目を追加しています + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder と AllowDrop の両方を true にすることはできません。 + + + + ToolStrip New Item create Transaction. + ToolStrip の新しいアイテムの作成トランザクションです。 + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + 現在の ToolStrip を ToolStripContainer に埋め込みます。 + + + + &Insert Standard Items + 標準項目の挿入(&I) + + + + Inserts standard items in the current ToolStrip + 現在の ToolStrip に標準項目を挿入します。 + + + + Type Here + ここに入力 + + + + Type Text for ToolStripMenuItem + ToolStripMenuItem のテキストの入力 + + + + Add Menu Item + メニュー項目の追加 + + + + Add ToolStripStatusLabel + ToolStripStatusLabel の追加 + + + + Add ToolStripButton + ToolStripButton の追加 + + + + New item selection + 新しい項目の選択 + + + + Adding Item + 追加項目 + + + + Removing Item + 削除項目 + + + + &Edit DropDownItems... + DropDownItems の編集(&E)... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + DropDown での ToolStrip MenuItem の挿入トランザクションです。 + + + + &Edit Items... + 項目の編集(&E)... + + + + Con&vert To + 変換後(&V) + + + + &Insert + 挿入(&I) + + + + Set I&mage... + イメージの設定(&M)... + + + + ToolStripItem Property Change Transaction. + ToolStripItem プロパティ変更のトランザクションです。 + + + + ToolStripItem Morphing Transaction. + ToolStripItem モーフィング のトランザクションです。 + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + ToolStripSeparator を MenuStrip に追加できません。 + + Argument should be a non-empty string. 引数には空ではない文字列を指定してください。 @@ -377,11 +958,31 @@ データ型 {0} はシリアル化可能ではありません。プロパティ辞書に追加される項目はシリアル化可能でなければなりません。 + + Auto Arrange Tray Icons + トレイ アイコンの自動整列 + + + + Line Up Tray Icons + トレイ アイコンを等間隔に整列 + + + + Show Large or Small Icons + 大きいアイコンおよび小さいアイコンの表示 + + Type '{0}' is not available in the target framework. 型 '{0}' は、ターゲット フレームワークでは使用できません。 + + Error + エラー + + Add Component コンポーネントの追加 @@ -432,6 +1033,26 @@ 実装されていません。 + + <couldn't find resource string "WindowsFormsAddEvent"> + <リソース文字列 "WindowsFormsAddEvent" が見つかりませんでした> + + + + Horizontal center of {0} component(s) + {0} コンポーネントの左右方向の中心 + + + + Vertical center of {0} component(s) + {0} コンポーネントの上下方向の中心 + + + + The Locked property determines if we can move or resize the control. + Locked プロパティは、コントロールを移動できるか、またはサイズを変更できるかどうかを判断します。 + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf index 198f3d5a71a..e8cb43b985c 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + {0} 복사 및 이동 + + + + Copy and move {0} Controls + {0}개 컨트롤 복사 및 이동 + + + + Move {0} + {0} 이동 + + + + Move {0} Controls + {0}개 컨트롤 이동 + + + + Resize {0} + {0} 크기 조정 + + + + Resize {0} Controls + {0}개 컨트롤 크기 조정 + + The serialization store is closed. New objects cannot be added to a closed store. Serialization 저장소가 닫혀 있습니다. 닫힌 저장소에는 새 개체를 추가할 수 없습니다. @@ -17,6 +47,58 @@ 이러한 형식의 serialization 저장소는 지원되지 않습니다. CreateStore 메서드에서 반환된 저장소를 사용하십시오. + + Format {0} components (alignment) + {0}개 구성 요소에 서식 지정(맞춤) + + + + Align {0} components to grid + {0}개 구성 요소를 모눈에 맞춤 + + + + Cut {0} Components + {0}개 구성 요소 잘라내기 + + + + Delete {0} components + {0} 구성 요소 삭제 + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + {0} 구성 요소에 서식 지정(간격) + + + + Paste components + 구성 요소 붙여넣기 + + + + Size {0} components + {0}개 구성 요소 크기 조정 + + + + Size {0} components to grid + {0}개 구성 요소 크기를 모눈에 맞춤 + + + + Unknown spacing command + 알 수 없는 간격 명령입니다. + + Adding event '{0}' '{0}' 이벤트를 추가하고 있습니다. @@ -37,6 +119,151 @@ integer 형식을 float 형식으로 변환할 수 없습니다. + + Align To &Grid + 모눈에 맞춤(&G) + + + + &Bring To Front + 맨 앞으로 가져오기(&B) + + + + C&opy + 복사(&O) + + + + &Cut + 잘라내기(&C) + + + + &Delete + 삭제(&D) + + + + &Document Outline + 문서 개요(&D) + + + + &Lock Controls + 컨트롤 잠그기(&L) + + + + &Paste + 붙여넣기 + + + + &Properties + 속성(&P) + + + + &Select + 선택(&S) + + + + &Send To Back + 맨 뒤로 보내기(&S) + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + ShowCheckMargin 속성을 설정/해제합니다. + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + ShowImageMargin 속성을 설정/해제합니다. + + + + View &Code + 코드 보기(&C) + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + '{0}' 값을 '{1}' 형식으로 변환할 수 없습니다. + + + + Could not find method '{0}'. + '{0}' 메서드를 찾을 수 없습니다. + + + + Could not find property '{0}' on '{1}'. + '{1}'에서 '{0}' 속성을 찾을 수 없습니다. + + + + {0} Tasks + {0} 작업 + + + + Error using the dropdown: {0} + 드롭다운 사용 오류: {0} + + + + Error invoking '{0}'. Details: {1} + '{0}'을(를) 호출하는 동안 오류가 발생했습니다. 자세한 정보: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + '{0}' 값을 '{1}' 속성에 설정하는 동안 오류가 발생했습니다. 자세한 정보: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + drag 함수를 호출하기 전에 먼저 BeginDrag를 호출해야 합니다. + + + + Inherited control + 상속된 컨트롤 + + + + Inherited control (Private) + 상속된 컨트롤(전용) + + The container cannot be disposed at design time. 컨테이너를 디자인 타임에 삭제할 수 없습니다. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - 문서를 로드하는 동안 오류가 발생했습니다. 오류를 수정한 다음 문서를 다시 로드해 보세요. 다음 오류 메시지가 나타납니다.\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ 서비스 컨테이너에서 {0} 서비스를 제거할 수 없습니다. - - Could not find method '{0}' - '{0}' 메서드를 찾을 수 없습니다. - - Cannot remove or destroy inherited component '{0}'. 상속된 구성 요소 '{0}'을(를) 제거하거나 소멸시킬 수 없습니다. @@ -222,16 +448,51 @@ 디자이너에서 맞춤선을 사용할지 여부를 제어합니다. true이면 맞춤선이 안내선으로 사용되고 false이면 모눈선이 사용됩니다. + + Dock in Parent Container + 부모 컨테이너에서 도킹 + + + + Undock in Parent Container + 부모 컨테이너에서 도킹 해제 + + .NET Component .NET 구성 요소 + + Drag {0} components + {0} 구성 요소 끌어 놓기 + + + + Move {0} + {0} 이동 + + + + Move {0} components + {0}개 구성 요소 이동 + + This IDataObject doesn't support SetData. IDataObject는 SetData를 지원하지 않습니다. + + Size {0} + {0} 크기 조정 + + + + Size {0} components + {0}개 구성 요소 크기 조정 + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Extender 공급자 {0}이(가) Extender로 이미 추가되었습니다. 다른 공급자를 추가하면 속성이 중복됩니다. @@ -242,6 +503,16 @@ 읽기 전용 + + '{1}' is not a valid value for '{0}'. + '{1}'은(는) '{0}'에 사용할 수 없는 값입니다. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}'은(는) '{0}'에 사용할 수 없는 값입니다. '{0}'은(는) {2}에서 {3} 사이에 있어야 합니다. + + This method/object is not implemented by design. 이 메서드/개체는 의도적으로 구현되지 않습니다. @@ -252,6 +523,11 @@ Winforms 디자이너는 이 플랫폼에서 지원되지 않습니다. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. 이 serialization 관리자에 이미 활성 serialization 세션이 있으므로 새 세션을 만들 수 없습니다. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + 형식이 {0}인 요소는 지원되지 않습니다. 직렬 변환기에 필요한 요소는 다음 중 하나입니다. {1} @@ -337,6 +613,16 @@ '{0}' 형식에 이름이 '{1}'인 속성이 없습니다. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} 문화권 {0}에 대한 리소스 파일에서 리소스를 읽는 동안 오류가 발생했습니다. {1} @@ -347,6 +633,11 @@ 기본 문화권에 대한 리소스 파일에서 리소스를 읽는 동안 오류가 발생했습니다. {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + 디자이너는 '{0}' 형식의 인스턴스를 만들어야 하지만 이 형식은 abstract로 선언되었으므로 만들 수 없습니다. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. '{0}' 형식을 찾을 수 없습니다. 이 형식을 포함하는 어셈블리가 참조되는지 확인하십시오. 이 형식이 개발 프로젝트의 일부인 경우 해당 프로젝트가 현재 플랫폼 또는 모든 CPU에 대한 설정을 사용하여 올바르게 빌드되었는지 확인하십시오. @@ -357,6 +648,296 @@ '{0}' 변수를 선언하거나 할당하지 않았습니다. + + &About... + 정보(&A)... + + + + &Contents + 내용 + + + + &Copy + 복사(&C) + + + + Create Standard Menu + 표준 메뉴 만들기 + + + + &Customize + 사용자 지정 + + + + Cu&t + 잘라내기 + + + + &Edit + 편집(&E) + + + + E&xit + 끝내기(&X) + + + + &File + 파일(&F) + + + + &Help + 도움말(&H) + + + + &Index + 인덱스 + + + + &New + 새로 만들기(&N) + + + + &Open + 열기(&O) + + + + &Options + 옵션 + + + + &Paste + 붙여넣기 + + + + &Print + 인쇄 + + + + Print Pre&view + 인쇄 미리 보기(&V) + + + + &Redo + 다시 실행 + + + + &Save + 저장(&S) + + + + Save &As + 다른 이름으로 저장 + + + + &Search + 검색(&S) + + + + Select &All + 모두 선택 + + + + &Tools + 도구(&T) + + + + &Undo + 실행 취소 + + + + C&ut + 잘라내기 + + + + He&lp + 도움말 + + + + Dock: + Dock: + + + + Changes the Dock property + Dock 속성을 변경합니다. + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + GripStyle 속성을 변경합니다. + + + + Layout && Appearance + 레이아웃 및 모양 + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + RenderMode 속성을 변경합니다. + + + + Adding {0} Item + {0} 항목 추가 + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder 및 AllowDrop이 모두 true일 수 없습니다. + + + + ToolStrip New Item create Transaction. + ToolStrip 새 항목 만들기 트랜잭션입니다. + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + 현재 ToolStrip을 ToolStripContainer에 포함합니다. + + + + &Insert Standard Items + 표준 항목 삽입(&I) + + + + Inserts standard items in the current ToolStrip + 현재 ToolStrip에 표준 항목을 삽입합니다. + + + + Type Here + 여기에 입력 + + + + Type Text for ToolStripMenuItem + ToolStripMenuItem의 형식 텍스트 + + + + Add Menu Item + 메뉴 항목 추가 + + + + Add ToolStripStatusLabel + ToolStripStatusLabel 추가 + + + + Add ToolStripButton + ToolStripButton 추가 + + + + New item selection + 새 항목 선택 + + + + Adding Item + 항목 추가 + + + + Removing Item + 항목 제거 + + + + &Edit DropDownItems... + DropDownItems 편집(&E)... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + DropDown 트랜잭션의 ToolStrip MenuItem 삽입입니다. + + + + &Edit Items... + 항목 편집(&E)... + + + + Con&vert To + 변환 대상(&V) + + + + &Insert + 삽입(&I) + + + + Set I&mage... + 이미지 설정(&M)... + + + + ToolStripItem Property Change Transaction. + ToolStripItem 속성 변경 트랜잭션입니다. + + + + ToolStripItem Morphing Transaction. + ToolStripItem 모핑 트랜잭션입니다. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + ToolStripSeparator를 MenuStrip에 추가할 수 없습니다. + + Argument should be a non-empty string. 인수는 비어 있지 않은 문자열이어야 합니다. @@ -377,11 +958,31 @@ 데이터 형식 {0}을(를) serialize할 수 없습니다. 속성 사전에 추가된 항목은 serialize할 수 있어야 합니다. + + Auto Arrange Tray Icons + 트레이 아이콘 자동 정렬 + + + + Line Up Tray Icons + 트레이 아이콘 줄 맞춤 + + + + Show Large or Small Icons + 큰 아이콘 또는 작은 아이콘 표시 + + Type '{0}' is not available in the target framework. 대상 프레임워크에서 '{0}' 형식을 사용할 수 없습니다. + + Error + 오류 + + Add Component 구성 요소 추가 @@ -432,6 +1033,26 @@ 구현되지 않았습니다. + + <couldn't find resource string "WindowsFormsAddEvent"> + <리소스 문자열 "WindowsFormsAddEvent"를 찾을 수 없음> + + + + Horizontal center of {0} component(s) + {0}개 구성 요소를 가로로 가운데에 맞춥니다. + + + + Vertical center of {0} component(s) + {0}개 구성 요소를 세로로 가운데에 맞춥니다. + + + + The Locked property determines if we can move or resize the control. + Locked 속성은 컨트롤을 이동하거나 크기 조정할 수 있는지 여부를 결정합니다. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf index 3e1725e0b4a..c480952589b 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Skopiuj i przenieś {0} + + + + Copy and move {0} Controls + Skopiuj i przenieś formanty {0} + + + + Move {0} + Przenieś element {0} + + + + Move {0} Controls + Przenieś formanty {0} + + + + Resize {0} + Zmień rozmiar elementu {0} + + + + Resize {0} Controls + Zmień rozmiar formantów {0} + + The serialization store is closed. New objects cannot be added to a closed store. Magazyn serializacji jest zamknięty. Do zamkniętego magazynu nie można dodawać nowych obiektów. @@ -17,6 +47,58 @@ Ten typ magazynu serializacji nie jest obsługiwany. Użyj magazynu zwracanego przez metodę CreateStore. + + Format {0} components (alignment) + Formatuj {0} składników (wyrównanie) + + + + Align {0} components to grid + Wyrównaj do siatki {0} składników + + + + Cut {0} Components + Wytnij {0} składników + + + + Delete {0} components + Usuń {0} składników + + + + An error occurred while processing this command. + {0} + Wystąpił błąd podczas przetwarzania tego polecenia. + {0} + + + + Format {0} components (spacing) + Formatuj {0} składników (odstępy) + + + + Paste components + Wklej składniki + + + + Size {0} components + Zmień rozmiar {0} składników + + + + Size {0} components to grid + Zmień rozmiar {0} składników względem siatki + + + + Unknown spacing command + Nieznane polecenie sterowania odstępami + + Adding event '{0}' Dodawanie zdarzenia '{0}' @@ -37,6 +119,151 @@ Nie można przekonwertować typu integer na typ float. + + Align To &Grid + &Wyrównaj do siatki + + + + &Bring To Front + Przesuń n&a wierzch + + + + C&opy + &Kopiuj + + + + &Cut + Wy&tnij + + + + &Delete + &Usuń + + + + &Document Outline + Konspekt &dokumentu + + + + &Lock Controls + Zablok&uj formanty + + + + &Paste + &Wklej + + + + &Properties + Właś&ciwości + + + + &Select + &Wybierz + + + + &Send To Back + Przesuń na &spód + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Włącza/wyłącza właściwość ShowCheckMargin + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Włącza/wyłącza właściwość ShowImageMargin + + + + View &Code + Pokaż &kod + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + Kontrolka {0} zwróciła nieobsługiwany wyjątek w projektancie i została wyłączona. + + Wyjątek: + {1} + + Ślad stosu:{2} + + + + Could not convert value '{0}' to the type '{1}'. + Nie można konwertować wartości '{0}' na typ '{1}'. + + + + Could not find method '{0}'. + Nie można znaleźć metody '{0}'. + + + + Could not find property '{0}' on '{1}'. + Nie można znaleźć właściwości '{0}' w '{1}'. + + + + {0} Tasks + Zadania {0} + + + + Error using the dropdown: {0} + Wystąpił błąd podczas używania listy rozwijanej: {0} + + + + Error invoking '{0}'. Details: {1} + Wystąpił błąd podczas wywoływania '{0}'. Szczegóły: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Wystąpił błąd podczas ustawiania właściwości '{1}' wartości '{0}'. Szczegóły: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Wywołanie elementu BeginDrag musi się zakończyć powodzeniem przed wywołaniem funkcji przeciągania. + + + + Inherited control + Formant dziedziczony + + + + Inherited control (Private) + Formant dziedziczony (prywatny) + + The container cannot be disposed at design time. Kontenera nie można usunąć podczas projektowania. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Wystąpił błąd podczas ładowania dokumentu. Usuń błąd, a następnie spróbuj załadować ponownie dokument. Oto treść komunikatu o błędzie:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + Wystąpił błąd podczas ładowania dokumentu. Usuń błąd, a następnie spróbuj załadować ponownie dokument. Komunikat o błędzie: + + {0} @@ -67,11 +298,6 @@ Nie można usunąć usługi {0} z kontenera usług. - - Could not find method '{0}' - Nie można znaleźć metody „{0}”. - - Cannot remove or destroy inherited component '{0}'. Nie można usunąć ani zniszczyć składnika dziedziczonego '{0}'. @@ -222,16 +448,51 @@ Określa, czy projektanci mają używać linii przyciągania. Jeśli tak, linie przyciągania będą używane jako prowadnice. Jeśli nie, będą używane linie siatki. + + Dock in Parent Container + Zadokuj w kontenerze nadrzędnym + + + + Undock in Parent Container + Oddokuj w kontenerze nadrzędnym + + .NET Component Składnik platformy .NET + + Drag {0} components + Przeciągnij {0} składników + + + + Move {0} + Przenieś element {0} + + + + Move {0} components + Przenieś {0} składników + + This IDataObject doesn't support SetData. Ten element IDataObject nie obsługuje elementu SetData. + + Size {0} + Zmień rozmiar {0} + + + + Size {0} components + Zmień rozmiar {0} składników + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Dostawca rozszerzony {0} został już dodany jako rozszerzenie. Dodanie kolejnego dostawcy spowodowałoby zduplikowanie właściwości. @@ -242,6 +503,16 @@ Tylko do odczytu + + '{1}' is not a valid value for '{0}'. + „{1}” nie jest prawidłową wartością elementu „{0}”. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' nie jest prawidłową wartością dla '{0}'. Wartość '{0}' powinna należeć do zakresu od {2} do {3}. + + This method/object is not implemented by design. Ta metoda/obiekt nie jest domyślnie implementowana. @@ -252,6 +523,11 @@ Projektant formularzy systemu Windows nie jest obsługiwany na tej platformie. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Nie można utworzyć nowej sesji, ponieważ jest już aktywna sesja serializacji tego menedżera. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Elementy typu {0} nie są obsługiwane. Serializator oczekuje elementu jednego z następujących typów: {1}. @@ -337,6 +613,16 @@ Typ '{0}' nie zawiera właściwości o nazwie '{1}'. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Błąd podczas odczytu zasobów z pliku zasobów dla kultury {0}: {1} @@ -347,6 +633,11 @@ Błąd podczas odczytu zasobów z pliku zasobów dla kultury domyślnej: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + Projektant musi utworzyć wystąpienie typu '{0}', ale nie może tego zrobić, ponieważ typ został zadeklarowany jako abstrakcyjny. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Nie można odnaleźć typu „{0}”. Upewnij się, że występuje odwołanie do zestawu zawierającego ten typ. Jeśli ten typ jest częścią opracowywanego projektu, upewnij się, że projekt został pomyślnie utworzony przy użyciu ustawień bieżącej platformy lub dowolnego procesora. @@ -357,6 +648,296 @@ Zmienna '{0}' nie została zadeklarowana albo nie została nigdy przypisana. + + &About... + Inform&acje o... + + + + &Contents + &Zawartość + + + + &Copy + &Kopiuj + + + + Create Standard Menu + Utwórz menu standardowe + + + + &Customize + &Dostosuj + + + + Cu&t + Wy&tnij + + + + &Edit + &Edytuj + + + + E&xit + Z&akończ + + + + &File + Pli&k + + + + &Help + Pomo&c + + + + &Index + &Indeks + + + + &New + &Nowy + + + + &Open + O&twórz + + + + &Options + &Opcje + + + + &Paste + &Wklej + + + + &Print + &Drukuj + + + + Print Pre&view + &Podgląd wydruku + + + + &Redo + &Ponów + + + + &Save + &Zapisz + + + + Save &As + &Zapisz jako + + + + &Search + &Wyszukaj + + + + Select &All + &Zaznacz wszystko + + + + &Tools + &Narzędzia + + + + &Undo + &Cofnij + + + + C&ut + &Wytnij + + + + He&lp + &Pomoc + + + + Dock: + Zadokuj: + + + + Changes the Dock property + Zmienia właściwość Dock + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Zmienia właściwość GripStyle + + + + Layout && Appearance + Układ i wygląd + + + + RenderMode: + Tryb renderowania: + + + + Changes the RenderMode property + Zmienia właściwość RenderMode + + + + Adding {0} Item + Dodawanie elementu {0} + + + + AllowItemReorder and AllowDrop cannot both be true. + Wartości AllowItemReorder i AllowDrop nie mogą być jednocześnie prawdziwe. + + + + ToolStrip New Item create Transaction. + Operacja tworzenia nowego elementu ToolStrip. + + + + Embed in ToolStripContainer + Osadzaj w elemencie ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Osadza bieżący element ToolStrip w elemencie ToolStripContainer + + + + &Insert Standard Items + &Wstaw elementy standardowe + + + + Inserts standard items in the current ToolStrip + Wstawia elementy standardowe w elemencie ToolStrip + + + + Type Here + Wpisz tutaj + + + + Type Text for ToolStripMenuItem + Wpisz tekst elementu ToolStripMenuItem + + + + Add Menu Item + Dodaj element menu + + + + Add ToolStripStatusLabel + Dodaj element ToolStripStatusLabel + + + + Add ToolStripButton + Dodaj element ToolStripButton + + + + New item selection + Nowe zaznaczenie elementu + + + + Adding Item + Dodawanie elementu + + + + Removing Item + Usuwanie elementu + + + + &Edit DropDownItems... + &Edytuj elementy DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Operacja ToolStrip MenuItem Insert w DropDown. + + + + &Edit Items... + &Edytuj elementy... + + + + Con&vert To + &Konwertuj na + + + + &Insert + Ws&taw + + + + Set I&mage... + &Ustaw obraz... + + + + ToolStripItem Property Change Transaction. + Operacja zmiany właściwości ToolStripItem. + + + + ToolStripItem Morphing Transaction. + Operacja przekształcania właściwości ToolStripItem. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + Nie można dodać elementu ToolStripSeparator do elementu MenuStrip. + + Argument should be a non-empty string. Argument powinien być niepustym ciągiem. @@ -377,11 +958,31 @@ Typu danych {0} nie można serializować. Elementy dodane do słownika właściwości muszą mieć możliwość serializowania. + + Auto Arrange Tray Icons + Rozmieść automatycznie ikony paska zadań + + + + Line Up Tray Icons + Szereguj ikony paska zadań + + + + Show Large or Small Icons + Pokaż duże lub małe ikony + + Type '{0}' is not available in the target framework. Typ „{0}” jest niedostępny w strukturze docelowej. + + Error + Błąd + + Add Component Dodaj składnik @@ -432,6 +1033,26 @@ Nie zaimplementowano. + + <couldn't find resource string "WindowsFormsAddEvent"> + <nie można znaleźć ciągu zasobu "WindowsFormsAddEvent"> + + + + Horizontal center of {0} component(s) + Wyśrodkowanie w poziomie {0} składników + + + + Vertical center of {0} component(s) + Wyśrodkowanie w pionie {0} składników + + + + The Locked property determines if we can move or resize the control. + Właściwość Locked określa, czy można przenosić formant lub zmieniać jego rozmiar. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf index 8fb0a0039a3..490d9277bd2 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Copiar e mover {0} + + + + Copy and move {0} Controls + Copiar e mover {0} Controles + + + + Move {0} + Mover {0} + + + + Move {0} Controls + Mover {0} Controles + + + + Resize {0} + Redimensionar {0} + + + + Resize {0} Controls + Redimensionar {0} Controles + + The serialization store is closed. New objects cannot be added to a closed store. O repositório de serialização está fechado. Não é possível adicionar novos objetos a um repositório fechado. @@ -17,6 +47,58 @@ Não há suporte para esse tipo de repositório de serialização. Use um repositório retornado pelo método CreateStore. + + Format {0} components (alignment) + Formatar {0} componentes (alinhamento) + + + + Align {0} components to grid + Alinhar {0} componentes à grade + + + + Cut {0} Components + Recortar {0} componentes + + + + Delete {0} components + Excluir {0} componentes + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + Formatar {0} componentes (espaçamento) + + + + Paste components + Colar componentes + + + + Size {0} components + Dimensionar componentes {0} + + + + Size {0} components to grid + Ajustar {0} componentes à grade + + + + Unknown spacing command + Comando de espaçamento desconhecido + + Adding event '{0}' Adicionando evento '{0}' @@ -37,6 +119,151 @@ Não é possível converter inteiro em flutuante. + + Align To &Grid + Alinhar à &Grade + + + + &Bring To Front + &Trazer para a Frente + + + + C&opy + &Copiar + + + + &Cut + &Recortar + + + + &Delete + E&xcluir + + + + &Document Outline + Estrutura de Tópicos de &Documentos + + + + &Lock Controls + &Bloquear Controles + + + + &Paste + C&olar + + + + &Properties + &Propriedades + + + + &Select + &Selecionar + + + + &Send To Back + &Enviar para Trás + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Alterna a propriedade ShowCheckMargin + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Alterna a propriedade ShowImageMargin + + + + View &Code + Exibir &Código + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + Não foi possível converter o valor '{0}' no tipo '{1}'. + + + + Could not find method '{0}'. + Não foi possível encontrar o método '{0}'. + + + + Could not find property '{0}' on '{1}'. + Não foi possível encontrar a propriedade '{0}' em '{1}'. + + + + {0} Tasks + {0} Tarefas + + + + Error using the dropdown: {0} + Erro ao usar o menu suspenso: {0} + + + + Error invoking '{0}'. Details: {1} + Erro ao chamar '{0}'. Detalhes: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Erro ao definir o valor '{0}' para a propriedade '{1}'. Detalhes: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Chamada para BeginDrag deve obter êxito para poder chamar as funções arrastadas. + + + + Inherited control + Controle herdado + + + + Inherited control (Private) + Controle herdado (Privado) + + The container cannot be disposed at design time. O contêiner não pode ser descartado em tempo de design. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Erro ao carregar o documento. Corrija o erro e tente carregar o documento novamente. Mensagem de erro:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ O serviço {0} não pode ser removido do contêiner de serviços. - - Could not find method '{0}' - Não foi possível encontrar o método '{0}' - - Cannot remove or destroy inherited component '{0}'. Não é possível remover ou destruir o componente herdado '{0}'. @@ -222,16 +448,51 @@ Controla se os designers devem usar linhas de ajuste. Se verdadeiro, essas linhas serão usadas como guias. Se falso, as linhas de grade serão usadas em vez das linhas de ajuste. + + Dock in Parent Container + Encaixar no Contêiner Pai + + + + Undock in Parent Container + Desencaixar do Contêiner Pai + + .NET Component Componente .NET + + Drag {0} components + Arrastar {0} componentes + + + + Move {0} + Mover {0} + + + + Move {0} components + Mover componentes {0} + + This IDataObject doesn't support SetData. Este IDataObject não oferece suporte para SetData. + + Size {0} + Dimensionar {0} + + + + Size {0} components + Dimensionar componentes {0} + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. O provedor do extensor {0} já foi adicionado como extensor. A inclusão de outro resultará em propriedades duplicadas. @@ -242,6 +503,16 @@ Somente Leitura + + '{1}' is not a valid value for '{0}'. + '{1}' não é um valor válido para '{0}'. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' não é um valor válido para '{0}'. '{0}' deve estar entre {2} e {3}. + + This method/object is not implemented by design. Este método/objeto não é implementado por design. @@ -252,6 +523,11 @@ O Designer de Formulários do Windows não é compatível com esta plataforma. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Você não pode criar uma nova sessão porque esse gerente de serialização já possui uma sessão de serialização ativa. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Elementos do tipo {0} não têm suporte. O serializador espera que o elemento seja um dos seguintes: {1}. @@ -337,6 +613,16 @@ O tipo '{0}' não tem uma propriedade chamada '{1}'. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Erro na leitura de recursos do arquivo de recursos para a cultura {0}: {1} @@ -347,6 +633,11 @@ Erro na leitura de recursos do arquivo de recursos para a cultura padrão: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + O designer deve fazer uma instância do tipo '{0}', mas ele não pode porque o tipo foi declarado como abstrato. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Não foi possível encontrar o tipo '{0}'. Verifique se o assembly que contém esse tipo é referenciado. Se esse tipo fizer parte do projeto de desenvolvimento, verifique se o projeto foi criado com êxito com o uso das configurações para sua plataforma atual ou para qualquer CPU. @@ -357,6 +648,296 @@ A variável '{0}' é não declarada ou nunca foi atribuída. + + &About... + &Sobre... + + + + &Contents + &Conteúdo + + + + &Copy + &Copiar + + + + Create Standard Menu + Criar Menu Padrão + + + + &Customize + &Personalizar + + + + Cu&t + Recor&tar + + + + &Edit + &Editar + + + + E&xit + &Saída + + + + &File + &Arquivo + + + + &Help + &Ajuda + + + + &Index + Í&ndice + + + + &New + &Novo + + + + &Open + A&brir + + + + &Options + &Opções + + + + &Paste + C&olar + + + + &Print + &Imprimir + + + + Print Pre&view + &Visualizar impressão + + + + &Redo + &Refazer + + + + &Save + &Salvar + + + + Save &As + Salvar &como + + + + &Search + &Pesquisar + + + + Select &All + Selecionar &Tudo + + + + &Tools + &Ferramentas + + + + &Undo + &Desfazer + + + + C&ut + Recor&tar + + + + He&lp + &Ajuda + + + + Dock: + Dock: + + + + Changes the Dock property + Altera a propriedade Dock + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Altera a propriedade GripStyle + + + + Layout && Appearance + Layout e Aparência + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + Altera a propriedade RenderMode + + + + Adding {0} Item + Adicionando {0} Item + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder e AllowDrop não podem ser verdadeiros. + + + + ToolStrip New Item create Transaction. + Transação de criação de Novo Item de ToolStrip. + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Insere o ToolStrip atual em ToolStripContainer + + + + &Insert Standard Items + &Inserir Itens Padrão + + + + Inserts standard items in the current ToolStrip + Insere itens padrão no ToolStrip atual + + + + Type Here + Digite Aqui + + + + Type Text for ToolStripMenuItem + Digitar Texto para ToolStripMenuItem + + + + Add Menu Item + Adicionar Item de Menu + + + + Add ToolStripStatusLabel + Adicionar ToolStripStatusLabel + + + + Add ToolStripButton + Adicionar ToolStripButton + + + + New item selection + Nova seleção de item + + + + Adding Item + Adicionando Item + + + + Removing Item + Removendo Item + + + + &Edit DropDownItems... + &Editar DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Inserção de ToolStrip MenuItem na Transação DropDown. + + + + &Edit Items... + &Editar Itens... + + + + Con&vert To + Con&verter em + + + + &Insert + &Inserir + + + + Set I&mage... + Definir I&magem... + + + + ToolStripItem Property Change Transaction. + Transação de Alteração de Propriedade de ToolStripItem. + + + + ToolStripItem Morphing Transaction. + Transação de Metamorfose de ToolStripItem. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + Não é possível adicionar ToolStripSeparator a MenuStrip. + + Argument should be a non-empty string. O argumento deve ser uma cadeia de caracteres não vazia. @@ -377,11 +958,31 @@ O tipo de dados {0} não pode ser serializado. Itens adicionados a um dicionário de propriedades devem ser serializáveis. + + Auto Arrange Tray Icons + Organizar Automaticamente Ícones de Bandeja + + + + Line Up Tray Icons + Alinhar Ícones de Bandeja + + + + Show Large or Small Icons + Mostrar Ícones Grandes e Pequenos + + Type '{0}' is not available in the target framework. O tipo '{0}' não está disponível na estrutura de destino. + + Error + Erro + + Add Component Adicionar Componente @@ -432,6 +1033,26 @@ Não implementado. + + <couldn't find resource string "WindowsFormsAddEvent"> + <não foi possível localizar cadeia de caracteres de recurso "WindowsFormsAddEvent"> + + + + Horizontal center of {0} component(s) + Centro horizontal do(s) componente(s) {0} + + + + Vertical center of {0} component(s) + Centro vertical do(s) componente(s) {0} + + + + The Locked property determines if we can move or resize the control. + A propriedade Locked determina se o controle pode ser movido ou redimensionado. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf index 3e187732fa1..5705c2302ae 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + Копировать и переместить {0} + + + + Copy and move {0} Controls + Копировать и переместить {0} элементы управления + + + + Move {0} + Переместить {0} + + + + Move {0} Controls + Переместить {0} элементы управления + + + + Resize {0} + Изменить размер {0} + + + + Resize {0} Controls + Изменить размер {0} элементов управления + + The serialization store is closed. New objects cannot be added to a closed store. Хранилище сериализованных объектов закрыто. Добавление новых объектов в закрытое хранилище невозможно. @@ -17,6 +47,58 @@ Этот тип хранилища сериализованных объектов не поддерживается. Используйте хранилище, возвращенное методом CreateStore. + + Format {0} components (alignment) + Форматировать {0} компонентов (выравнивание) + + + + Align {0} components to grid + Выровнять {0} компонентов по сетке + + + + Cut {0} Components + Вырезать {0} компонентов + + + + Delete {0} components + Удалить {0} компонентов + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + Форматировать {0} компонентов (с интервалом) + + + + Paste components + Вставить компоненты + + + + Size {0} components + Изменить размер {0} компонентов + + + + Size {0} components to grid + Изменить размер {0} компонентов по сетке + + + + Unknown spacing command + Неизвестная команда задания интервала + + Adding event '{0}' Добавляется событие '{0}' @@ -37,6 +119,151 @@ Тип integer нельзя привести к типу float. + + Align To &Grid + Выровнять по р&ешетке + + + + &Bring To Front + &На передний план + + + + C&opy + К&опировать + + + + &Cut + &Вырезать + + + + &Delete + &Удалить + + + + &Document Outline + Структура до&кумента + + + + &Lock Controls + &Блокировка элементов управления + + + + &Paste + Вст&авка + + + + &Properties + &Свойства + + + + &Select + Выб&рать + + + + &Send To Back + &На задний план + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + Переключает свойство ShowCheckMargin + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + Переключает свойство ShowImageMargin + + + + View &Code + Перейти к ко&ду + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + Невозможно преобразовать значение '{0}' в тип '{1}'. + + + + Could not find method '{0}'. + Невозможно найти метод {0}. + + + + Could not find property '{0}' on '{1}'. + Невозможно найти свойство {0} в '{1}'. + + + + {0} Tasks + {0} Задачи + + + + Error using the dropdown: {0} + Ошибка при использовании раскрывающегося списка: {0} + + + + Error invoking '{0}'. Details: {1} + Ошибка при вызове '{0}'. Подробно: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + Ошибка при установке значения '{0}' для свойства '{1}'. Подробно: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Перед вызовом функций перетаскивания необходимо, чтобы успешно завершился вызов функции BeginDrag. + + + + Inherited control + Унаследованный элемент управления + + + + Inherited control (Private) + Унаследованный элемент управления (Частный) + + The container cannot be disposed at design time. Контейнер не может быть освобожден во время конструирования. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Произошла ошибка при загрузке документа. Исправьте ошибку и повторите загрузку. Сообщение об ошибке:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ Служба {0} не может быть удалена из контейнера служб. - - Could not find method '{0}' - Не удалось найти метод "{0}". - - Cannot remove or destroy inherited component '{0}'. Невозможно удалить или уничтожить унаследованный компонент '{0}'. @@ -222,16 +448,51 @@ Определяет, будут ли конструкторы использовать линии выравнивания. Если задано значение true, линии выравнивания используются в качестве направляющих. В случае false используются линии сетки. + + Dock in Parent Container + Закрепить в родительском контейнере + + + + Undock in Parent Container + Открепить в родительском контейнере + + .NET Component Компонент .NET + + Drag {0} components + Перетащить {0} компонентов + + + + Move {0} + Переместить {0} + + + + Move {0} components + Переместить {0} компонентов + + This IDataObject doesn't support SetData. Этот объект IDataObject не поддерживает SetData. + + Size {0} + Изменить размер {0} + + + + Size {0} components + Изменить размер {0} компонентов + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. Поставщик расширений {0} уже добавлен в качестве расширения. Добавление другого поставщика приведет к появлению повторяющихся свойств. @@ -242,6 +503,16 @@ Только для чтения + + '{1}' is not a valid value for '{0}'. + '{1}' не является допустимым значением для '{0}'. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' не является допустимым значением для '{0}'. Значение '{0}' должно лежать в диапазоне от {2} до {3}. + + This method/object is not implemented by design. Этот метод или объект не реализован намеренно. @@ -252,6 +523,11 @@ Конструктор Windows Forms не поддерживается на этой платформе. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Вы не можете создать новый сеанс, так как у этого диспетчера сериализации уже есть активный сеанс сериализации. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + Элементы типа {0} не поддерживаются. Сериализатор ожидает один из следующих элементов: {1}. @@ -337,6 +613,16 @@ Тип '{0}' не содержит свойства с именем '{1}'. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} Ошибка чтения ресурсов из файла ресурсов для культуры {0}: {1} @@ -347,6 +633,11 @@ Ошибка чтения ресурсов из файла ресурсов для культуры по умолчанию: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + Проектировщик должен создать экземпляр типа '{0}', однако это невозможно, поскольку тип объявлен как абстрактный. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. Не удалось найти тип "{0}". Проверьте, что есть ссылка на сборку, содержащую этот тип. Если этот тип является частью разрабатываемого проекта, убедитесь в том, что проект успешно откомпилирован с использованием параметров для вашей текущей платформы или для любого процессора. @@ -357,6 +648,296 @@ Переменная '{0}' либо не объявлена, либо ей не было присвоено значение. + + &About... + &О программе... + + + + &Contents + &Содержание + + + + &Copy + &Копировать + + + + Create Standard Menu + Создание стандартного меню + + + + &Customize + &Настройки + + + + Cu&t + Вырезат&ь + + + + &Edit + &Правка + + + + E&xit + Вы&ход + + + + &File + &Файл + + + + &Help + &Справка + + + + &Index + &Индекс + + + + &New + Со&здать + + + + &Open + &Открыть + + + + &Options + &Параметры + + + + &Paste + Вст&авка + + + + &Print + &Печать + + + + Print Pre&view + Предварительный прос&мотр + + + + &Redo + &Отмена действия + + + + &Save + Со&хранить + + + + Save &As + Сохранить &как + + + + &Search + &Поиск + + + + Select &All + Выделить &все + + + + &Tools + Сер&вис + + + + &Undo + &Отмена действия + + + + C&ut + В&ырезать + + + + He&lp + Спр&авка + + + + Dock: + Dock: + + + + Changes the Dock property + Изменяет свойство Dock + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + Изменяет свойство GripStyle + + + + Layout && Appearance + Раскладка и внешний вид + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + Изменяет свойство RenderMode + + + + Adding {0} Item + Добавление элемента {0} + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder и AllowDrop не могут одновременно иметь значение true. + + + + ToolStrip New Item create Transaction. + Новый элемент ToolStrip создает транзакцию. + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Внедряет текущий ToolStrip в ToolStripContainer + + + + &Insert Standard Items + &Вставить стандартные элементы + + + + Inserts standard items in the current ToolStrip + Вставляет стандартные элементы в текущий ToolStrip + + + + Type Here + Прототип для текста + + + + Type Text for ToolStripMenuItem + Введите текст для ToolStripMenuItem + + + + Add Menu Item + Добавить пункт меню + + + + Add ToolStripStatusLabel + Добавить ToolStripStatusLabel + + + + Add ToolStripButton + Добавить ToolStripButton + + + + New item selection + Выбор нового элемента + + + + Adding Item + Добавление элемента + + + + Removing Item + Удаление элемента + + + + &Edit DropDownItems... + &Правка DropDownItems... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + Вставка элементов меню ToolStrip в транзакцию DropDown. + + + + &Edit Items... + &Правка элементов… + + + + Con&vert To + Пр&еобразовать в + + + + &Insert + &Вставить + + + + Set I&mage... + Задать р&исунок... + + + + ToolStripItem Property Change Transaction. + Транзакция изменения свойства ToolStripItem. + + + + ToolStripItem Morphing Transaction. + Транзакция преобразования ToolStripItem + + + + '{0}' + "{0}" + + + + Cannot add ToolStripSeparator to MenuStrip. + Не удается добавить ToolStripSeparator в MenuStrip. + + Argument should be a non-empty string. Аргумент не может быть пустой строкой. @@ -377,11 +958,31 @@ Тип данных {0} не является упорядочиваемым. В словарь свойств можно добавлять только упорядочиваемые элементы. + + Auto Arrange Tray Icons + Автоматически упорядочить значки на панели задач + + + + Line Up Tray Icons + Выстроить значки на панели задач + + + + Show Large or Small Icons + Отображать крупные или мелкие значки + + Type '{0}' is not available in the target framework. Тип "{0}" недоступен в целевой платформе. + + Error + Ошибка + + Add Component Добавить компонент @@ -432,6 +1033,26 @@ Не реализовано. + + <couldn't find resource string "WindowsFormsAddEvent"> + <невозможно найти строку ресурса "WindowsFormsAddEvent"> + + + + Horizontal center of {0} component(s) + Центр {0} компонентов по горизонтали + + + + Vertical center of {0} component(s) + Центр {0} компонентов по вертикали + + + + The Locked property determines if we can move or resize the control. + Свойство Locked определяет, можно ли перемещать элемент управления или изменять его размеры. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf index 7c47b4d33a2..a78e2255ac4 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + {0} kopyala ve taşı + + + + Copy and move {0} Controls + {0} Denetimi kopyala ve taşı + + + + Move {0} + {0} öğesini taşı + + + + Move {0} Controls + {0} Denetimi taşı + + + + Resize {0} + {0} Yeniden boyutlandır + + + + Resize {0} Controls + {0} Denetimi yeniden boyutlandır + + The serialization store is closed. New objects cannot be added to a closed store. Serileştirme deposu kapalı. Kapalı depoya yeni nesneler eklenemez. @@ -17,6 +47,58 @@ Bu tür serileştirme deposu desteklenmiyor. CreateStore metodu tarafından döndürülen bir depo kullanın. + + Format {0} components (alignment) + {0} bileşen biçimlendir (hizalama) + + + + Align {0} components to grid + {0} bileşeni kılavuza göre hizala + + + + Cut {0} Components + {0} bileşeni kes + + + + Delete {0} components + {0} bileşeni sil + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + {0} bileşeni biçimlendir (aralık) + + + + Paste components + Bileşenleri yapıştır + + + + Size {0} components + {0} bileşeni boyutlandır + + + + Size {0} components to grid + {0} bileşeni kılavuza göre boyutlandır + + + + Unknown spacing command + Geçersiz aralık komutu + + Adding event '{0}' '{0}' olayı ekleniyor @@ -37,6 +119,151 @@ Tam sayı kayan noktalıya dönüştürülemez. + + Align To &Grid + Kılavuza &Hizala + + + + &Bring To Front + &Öne Getir + + + + C&opy + K&opyala + + + + &Cut + &Kes + + + + &Delete + &Sil + + + + &Document Outline + &Belge Ana Hattı + + + + &Lock Controls + &Denetimleri Kilitle + + + + &Paste + &Yapıştır + + + + &Properties + Ö&zellikler + + + + &Select + &Seç + + + + &Send To Back + &Arkaya Gönder + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + ShowCheckMargin özelliğinde geçiş yapar + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + ShowImageMargin özelliğinde geçiş yapar + + + + View &Code + Kod&u Görüntüle + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + '{0}' değeri '{1}' türüne dönüştürülemedi. + + + + Could not find method '{0}'. + '{0}' metodu bulunamadı. + + + + Could not find property '{0}' on '{1}'. + '{1}' üzerinde '{0}' özelliği bulunamadı. + + + + {0} Tasks + {0} Görevler + + + + Error using the dropdown: {0} + Açılan menüyü kullanma hatası: {0} + + + + Error invoking '{0}'. Details: {1} + '{0}' başlatma hatası. Ayrıntılar: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + '{0}' değerini '{1}' özelliğine ayarlama hatası. Ayrıntılar: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + Sürükleme işlevleri çağrılmadan önce Call to BeginDrag başarıyla tamamlanmalıdır. + + + + Inherited control + Devralınan denetim + + + + Inherited control (Private) + Devralınan denetim (Özel) + + The container cannot be disposed at design time. Kapsayıcı tasarım sırasında atılamaz. @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - Belge yüklenirken hata oluştu. Hatayı düzeltin ve belgeyi yüklemeyi yeniden deneyin. Hata iletisi:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ {0} hizmeti, hizmet kapsayıcısından kaldırılamıyor. - - Could not find method '{0}' - '{0}' metodu bulunamadı - - Cannot remove or destroy inherited component '{0}'. Devralınan '{0}' bileşeni kaldırılamaz veya yok edilemez. @@ -222,16 +448,51 @@ Tasarımcıların dayama çizgileri kullanıp kullanmayacağını denetler. True ise, dayama çizgileri kılavuz olarak kullanılır. False ise, kılavuz çizgileri kullanılır. + + Dock in Parent Container + Ana Kapsayıcıda Yerleştir + + + + Undock in Parent Container + Ana Kapsayıcıda Yerinden Çıkar + + .NET Component .NET Bileşeni + + Drag {0} components + {0} bileşeni sürükle + + + + Move {0} + {0} öğesini taşı + + + + Move {0} components + {0} bileşeni taşı + + This IDataObject doesn't support SetData. IDataObject SetData'yı desteklemiyor. + + Size {0} + {0} öğesini boyutlandır + + + + Size {0} components + {0} bileşeni boyutlandır + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. {0} uzatma sağlayıcısı zaten bir uzatma olarak eklendi. Bir uzatma daha eklemek yinelenen özelliklere neden olabilir. @@ -242,6 +503,16 @@ Salt Okunur + + '{1}' is not a valid value for '{0}'. + '{1}' değeri '{0}' öğesi için geçerli değil. + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' değeri '{0}' öğesi için geçerli değil. '{0}' değeri {2} ile {3} arasında olmalıdır. + + This method/object is not implemented by design. Tasarım gereği, bu metot/nesne uygulanmadı. @@ -252,6 +523,11 @@ Winforms Tasarımcısı bu platformda desteklenmiyor. + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. Bu serileştirme yöneticisinin zaten etkin bir serileştirme oturumu bulunduğundan yeni oturum oluşturamazsınız. @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + {0} türündeki öğeler desteklenmez. Seri hale getirici öğenin şu türlerden birinde olmasını bekler: {1}. @@ -337,6 +613,16 @@ '{0}' türünde, '{1}' adını taşıyan bir özellik yok. + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} {0}: {1} kültürünün kaynak dosyasındaki kaynakları okuma hatası @@ -347,6 +633,11 @@ {0} varsayılan kültürünün kaynak dosyasındaki kaynakları okuma hatası + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + Tasarımcı '{0}' türünde bir örnek oluşturmalıdır, ancak tür özet olarak bildirilmediğinden bu işlem gerçekleştirilemiyor. + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. '{0}' türü bulunamadı. Lütfen bu türü içeren bütünleştirilmiş koda başvurulduğundan emin olun. Bu tür, geliştirme projenizin bir parçasıysa, projenin geçerli platformunuzun ayarları veya Herhangi Bir CPU kullanılarak başarıyla oluşturulduğundan emin olun. @@ -357,6 +648,296 @@ '{0}' değişkeni bildirilmemiş ya da hiç değer atanmamış. + + &About... + &Hakkında... + + + + &Contents + İçi&ndekiler + + + + &Copy + &Kopyala + + + + Create Standard Menu + Standart Menü Oluştur + + + + &Customize + &Özelleştir + + + + Cu&t + &Kes + + + + &Edit + &Düzenle + + + + E&xit + &Çıkış + + + + &File + &Dosya + + + + &Help + &Yardım + + + + &Index + Di&zin + + + + &New + &Yeni + + + + &Open + &Aç + + + + &Options + &Seçenekler + + + + &Paste + &Yapıştır + + + + &Print + Y&azdır + + + + Print Pre&view + Baskı Ön&izleme + + + + &Redo + Yi&nele + + + + &Save + &Kaydet + + + + Save &As + &Farklı Kaydet + + + + &Search + &Ara + + + + Select &All + &Tümünü Seç + + + + &Tools + &Araçlar + + + + &Undo + &Geri Al + + + + C&ut + K&es + + + + He&lp + &Yardım + + + + Dock: + Dock: + + + + Changes the Dock property + Dock özelliğini değiştirir + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + GripStyle özelliğini değiştirir + + + + Layout && Appearance + Düzen ve Görünüm + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + RenderMode özelliğini değiştirir + + + + Adding {0} Item + {0} Öğe Ekleniyor + + + + AllowItemReorder and AllowDrop cannot both be true. + Hem AllowItemReorder hem de AllowDrop True olamaz. + + + + ToolStrip New Item create Transaction. + ToolStrip New Item oluşturma İşlemi. + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + Geçerli ToolStrip'i ToolStripContainer'a katıştırır + + + + &Insert Standard Items + &Standart Öğe Ekle + + + + Inserts standard items in the current ToolStrip + Geçerli ToolStrip'e standart öğeler ekler + + + + Type Here + Buraya Yazın + + + + Type Text for ToolStripMenuItem + ToolStripMenuItem için Metin Yaz + + + + Add Menu Item + Menü Öğesi Ekle + + + + Add ToolStripStatusLabel + ToolStripStatusLabel Ekle + + + + Add ToolStripButton + ToolStripButton Ekle + + + + New item selection + Yeni öğe seçimi + + + + Adding Item + Öğe Ekleniyor + + + + Removing Item + Öğe Kaldırılıyor + + + + &Edit DropDownItems... + &DropDownItems Düzenle... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + DropDown İşleminde ToolStrip MenuItem Ekleme. + + + + &Edit Items... + &Öğeleri Düzenle... + + + + Con&vert To + Dö&nüştür + + + + &Insert + &Ekle + + + + Set I&mage... + &Görüntü Ayarla... + + + + ToolStripItem Property Change Transaction. + ToolStripItem Özelliği Değiştirme İşlemi. + + + + ToolStripItem Morphing Transaction. + ToolStripItem Şekillendirme İşlemi. + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + ToolStripSeparator MenuStrip'e eklenemiyor. + + Argument should be a non-empty string. Bağımsız değişken boş olmayan bir dize olmalıdır. @@ -377,11 +958,31 @@ {0} veri türü seri hale getirilemez. Özellik sözlüğüne eklenen öğelerin seri hale getirilebilir olması gerekir. + + Auto Arrange Tray Icons + Tepsi Simgelerini Otomatik Ayarla + + + + Line Up Tray Icons + Tepsi Simgelerini Hizala + + + + Show Large or Small Icons + Büyük Veya Küçük Simgeleri Göster + + Type '{0}' is not available in the target framework. Hedef çerçevede '{0}' türü yok. + + Error + Hata + + Add Component Bileşen Ekle @@ -432,6 +1033,26 @@ Uygulanmadı. + + <couldn't find resource string "WindowsFormsAddEvent"> + <"WindowsFormsAddEvent" kaynak dizesi bulunamadı> + + + + Horizontal center of {0} component(s) + {0} bileşenlerinin yatay ortası + + + + Vertical center of {0} component(s) + {0} bileşenlerinin dikey ortası + + + + The Locked property determines if we can move or resize the control. + Denetimin taşınmasının veya yeniden boyutlandırılmasının mümkün olup olmadığını Locked özelliği belirler. + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf index 071ed300bb0..fdce7ae5ea7 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + 复制并移动 {0} + + + + Copy and move {0} Controls + 复制并移动 {0} 个控件 + + + + Move {0} + 移动 {0} + + + + Move {0} Controls + 移动 {0} 控件 + + + + Resize {0} + 调整 {0} 的大小 + + + + Resize {0} Controls + 调整 {0} 控件的大小 + + The serialization store is closed. New objects cannot be added to a closed store. 序列化存储区已关闭。新对象无法添加到已关闭的存储区中。 @@ -17,6 +47,58 @@ 不支持这种类型的序列化存储区。请使用 CreateStore 方法返回的存储区。 + + Format {0} components (alignment) + 格式化 {0} 组件(对齐) + + + + Align {0} components to grid + 将 {0} 组件与网格对齐 + + + + Cut {0} Components + 剪切 {0} 组件 + + + + Delete {0} components + 删除 {0} 组件 + + + + An error occurred while processing this command. + {0} + 处理此命令时出错。 + {0} + + + + Format {0} components (spacing) + 格式化 {0} 组件(间距) + + + + Paste components + 粘贴组件 + + + + Size {0} components + 调整 {0} 组件的大小 + + + + Size {0} components to grid + 按网格调整 {0} 组件的大小 + + + + Unknown spacing command + 未知的间距命令 + + Adding event '{0}' 添加事件“{0}” @@ -37,6 +119,157 @@ 无法将 integer 转换为 float。 + + Align To &Grid + 对齐到网格(&G) + + + + &Bring To Front + 置于顶层(&B) + + + + C&opy + 复制(&O) + + + + &Cut + 剪切(&C) + + + + &Delete + 删除(&D) + + + + &Document Outline + 文档大纲(&D) + + + + &Lock Controls + 锁定控件(&L) + + + + &Paste + 粘贴(&P) + + + + &Properties + 属性(&P) + + + + &Select + 选择(&S) + + + + &Send To Back + 置于底层(&S) + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + 切换 ShowCheckMargin 属性 + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + 切换 ShowImageMargin 属性 + + + + View &Code + 查看代码(&C) + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + 控件 {0} 在设计器中引发了一个未经处理的异常,已被禁用。 + + 异常: + {1} + + 堆栈跟踪:{2} + + +异常: +{1} + +堆栈跟踪:{2} + + + + Could not convert value '{0}' to the type '{1}'. + 未能将值“{0}”转换为类型“{1}”。 + + + + Could not find method '{0}'. + 未能找到方法“{0}”。 + + + + Could not find property '{0}' on '{1}'. + 未能在“{1}”上找到属性“{0}”。 + + + + {0} Tasks + {0} 任务 + + + + Error using the dropdown: {0} + 使用下拉项时出错: {0} + + + + Error invoking '{0}'. Details: {1} + 调用“{0}”时出错。详细信息: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + 将值“{0}”设置为属性“{1}”时出错。详细信息: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + 对 BeginDrag 的调用必须成功,才能调用拖动函数。 + + + + Inherited control + 继承的控件 + + + + Inherited control (Private) + 继承的控件(私有) + + The container cannot be disposed at design time. 不能在设计时释放容器。 @@ -48,8 +281,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - 加载文档时出错。请修复此错误,然后再尝试重新加载该文档。错误消息如下所示:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + 加载文档时出错。修复此错误,然后再重新尝试加载该文档。错误消息如下所示: + + {0} @@ -67,11 +304,6 @@ 无法将服务 {0} 从服务容器移除。 - - Could not find method '{0}' - 未能找到方法“{0}” - - Cannot remove or destroy inherited component '{0}'. 无法移除或损坏继承的组件“{0}”。 @@ -222,16 +454,51 @@ 控制设计器是否应使用对齐线。如果设置为 True,则使用对齐线作为参考线。如果设置为 False,则使用网格线。 + + Dock in Parent Container + 在父容器中停靠 + + + + Undock in Parent Container + 取消在父容器中停靠 + + .NET Component .NET 组件 + + Drag {0} components + 拖动 {0} 组件 + + + + Move {0} + 移动 {0} + + + + Move {0} components + 移动 {0} 组件 + + This IDataObject doesn't support SetData. 此 IDataObject 不支持 SetData。 + + Size {0} + 调整 {0} 的大小 + + + + Size {0} components + 调整 {0} 组件的大小 + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. 扩展程序提供程序 {0} 已添加为扩展程序。添加其他扩展程序提供程序将导致重复的属性。 @@ -242,6 +509,16 @@ 只读 + + '{1}' is not a valid value for '{0}'. + “{1}”不是“{0}”的有效值。 + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + “{1}”不是“{0}”的有效值。“{0}”应介于 {2} 和 {3} 之间。 + + This method/object is not implemented by design. 未按设计实现此方法/对象。 @@ -252,6 +529,11 @@ 此平台上不支持 Winforms Designer。 + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. 此序列化管理器已有活动的序列化会话,因此不能创建新的会话。 @@ -289,7 +571,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + 不支持类型为 {0} 的元素。序列化程序要求元素为以下某项: {1}。 @@ -337,6 +619,16 @@ 类型“{0}”没有名为“{1}”的属性。 + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} 从区域性 {0} 的资源文件中读取资源时出错: {1} @@ -347,6 +639,11 @@ 从默认区域性的资源文件中读取资源时出错: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + 设计器必须创建类型“{0}”的实例,但该类型已声明为抽象,因此设计器无法创建该类型的实例。 + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. 未能找到类型“{0}”。请确保已引用包含此类型的程序集。如果此类型为开发项目的一部分,请确保已使用针对当前平台或任意 CPU 的设置成功生成该项目。 @@ -357,6 +654,296 @@ 变量“{0}”未声明或从未赋值。 + + &About... + 关于(&A)... + + + + &Contents + 内容(&C) + + + + &Copy + 复制(&C) + + + + Create Standard Menu + 创建标准菜单 + + + + &Customize + 自定义(&C) + + + + Cu&t + 剪切(&T) + + + + &Edit + 编辑(&E) + + + + E&xit + 退出(&X) + + + + &File + 文件(&F) + + + + &Help + 帮助(&H) + + + + &Index + 索引(&I) + + + + &New + 新建(&N) + + + + &Open + 打开(&O) + + + + &Options + 选项(&O) + + + + &Paste + 粘贴(&P) + + + + &Print + 打印(&P) + + + + Print Pre&view + 打印预览(&V) + + + + &Redo + 重复(&R) + + + + &Save + 保存(&S) + + + + Save &As + 另存为(&A) + + + + &Search + 搜索(&S) + + + + Select &All + 全选(&A) + + + + &Tools + 工具(&T) + + + + &Undo + 撤消(&U) + + + + C&ut + 剪切(&U) + + + + He&lp + 帮助(&L) + + + + Dock: + 停靠: + + + + Changes the Dock property + 更改 Dock 属性 + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + 更改 GripStyle 属性 + + + + Layout && Appearance + 布局和外观 + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + 更改 RenderMode 属性 + + + + Adding {0} Item + 正在添加 {0} 项 + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder 和 AllowDrop 不能同时为 True。 + + + + ToolStrip New Item create Transaction. + ToolStrip 新项创建事务。 + + + + Embed in ToolStripContainer + 在 ToolStripContainer 中嵌入 + + + + Embeds the current ToolStrip in ToolStripContainer + 将当前 ToolStrip 嵌入 ToolStripContainer 中 + + + + &Insert Standard Items + 插入标准项(&I) + + + + Inserts standard items in the current ToolStrip + 将标准项插入到当前 ToolStrip 中 + + + + Type Here + 请在此处键入 + + + + Type Text for ToolStripMenuItem + 键入 ToolStripMenuItem 的文本 + + + + Add Menu Item + 添加菜单项 + + + + Add ToolStripStatusLabel + 添加 ToolStripStatusLabel + + + + Add ToolStripButton + 添加 ToolStripButton + + + + New item selection + 新项选择 + + + + Adding Item + 添加项 + + + + Removing Item + 移除项 + + + + &Edit DropDownItems... + 编辑 DropDownItems(&E)... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + DropDown 事务中的“ToolStrip 菜单项插入”。 + + + + &Edit Items... + 编辑项(&E)... + + + + Con&vert To + 转换为(&V) + + + + &Insert + 插入(&I) + + + + Set I&mage... + 设置图像(&M)... + + + + ToolStripItem Property Change Transaction. + ToolStripItem 属性更改事务。 + + + + ToolStripItem Morphing Transaction. + ToolStripItem 变形事务。 + + + + '{0}' + “{0}” + + + + Cannot add ToolStripSeparator to MenuStrip. + 无法将 ToolStripSeparator 添加到 MenuStrip。 + + Argument should be a non-empty string. 参数应为非空的字符串。 @@ -377,11 +964,31 @@ 数据类型 {0} 无法序列化。添加到属性字典中的项必须能序列化。 + + Auto Arrange Tray Icons + 自动排列任务栏图标 + + + + Line Up Tray Icons + 排列任务栏图标 + + + + Show Large or Small Icons + 显示大图标或小图标 + + Type '{0}' is not available in the target framework. 类型“{0}”在目标框架中不可用。 + + Error + 错误 + + Add Component 添加组件 @@ -432,6 +1039,26 @@ 未实现。 + + <couldn't find resource string "WindowsFormsAddEvent"> + <未能找到资源字符串“WindowsFormsAddEvent”> + + + + Horizontal center of {0} component(s) + {0} 组件的水平中心 + + + + Vertical center of {0} component(s) + {0} 组件的垂直中心 + + + + The Locked property determines if we can move or resize the control. + Locked 属性确定是否可以移动控件或调整控件的大小。 + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf index 35e49716c2b..421e0e34e27 100644 --- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf +++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf @@ -2,6 +2,36 @@ + + Copy and move {0} + 複製並移動 {0} + + + + Copy and move {0} Controls + 複製並移動 {0} 個控制項 + + + + Move {0} + 移動 {0} + + + + Move {0} Controls + 移動 {0} 控制項 + + + + Resize {0} + 調整 {0} 的大小 + + + + Resize {0} Controls + 重新調整 {0} 控制項大小 + + The serialization store is closed. New objects cannot be added to a closed store. 序列化存放區已關閉。新物件無法加入已關閉的存放區。 @@ -17,6 +47,58 @@ 不支援這種類型的序列化存放區。請使用 CreateStore 方法傳回的存放區。 + + Format {0} components (alignment) + 格式化 {0} 元件 (對齊) + + + + Align {0} components to grid + 將 {0} 元件對齊格線 + + + + Cut {0} Components + 剪下 {0} 元件 + + + + Delete {0} components + 刪除 {0} 元件 + + + + An error occurred while processing this command. + {0} + An error occurred while processing this command. + {0} + + + + Format {0} components (spacing) + 格式化 {0} 元件 (間隔) + + + + Paste components + 貼上元件 + + + + Size {0} components + 調整 {0} 元件的大小 + + + + Size {0} components to grid + 將 {0} 元件調整為方格的大小 + + + + Unknown spacing command + 不明的間距命令 + + Adding event '{0}' 正在加入事件 '{0}' @@ -37,6 +119,151 @@ Integer 無法轉換為 Float。 + + Align To &Grid + 對齊格線(&G) + + + + &Bring To Front + 移到最上層(&B) + + + + C&opy + 複製(&O) + + + + &Cut + 剪下(&C) + + + + &Delete + 刪除(&D) + + + + &Document Outline + 文件大綱(&T) + + + + &Lock Controls + 鎖定控制項(&L) + + + + &Paste + 貼上(&P) + + + + &Properties + 屬性(&P) + + + + &Select + 選取(&S) + + + + &Send To Back + 移到最下層(&S) + + + + ShowCheckMargin + ShowCheckMargin + + + + Toggles the ShowCheckMargin property + 切換 ShowCheckMargin 屬性 + + + + ShowImageMargin + ShowImageMargin + + + + Toggles the ShowImageMargin property + 切換 ShowImageMargin 屬性 + + + + View &Code + 檢視程式碼(&C) + + + + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + The control {0} has thrown an unhandled exception in the designer and has been disabled. + + Exception: + {1} + + Stack trace:{2} + + + + Could not convert value '{0}' to the type '{1}'. + 無法將值 '{0}' 轉換為類型 '{1}'。 + + + + Could not find method '{0}'. + 找不到方法 '{0}'。 + + + + Could not find property '{0}' on '{1}'. + 在 '{1}' 上找不到屬性 '{0}'。 + + + + {0} Tasks + {0} 工作 + + + + Error using the dropdown: {0} + 使用下拉式清單時發生錯誤: {0} + + + + Error invoking '{0}'. Details: {1} + 叫用 '{0}' 時發生錯誤。詳細資料: {1} + + + + Error setting value '{0}' to property '{1}'. Details: {2} + 將值 '{0}' 設定為屬性 '{1}' 時發生錯誤。詳細資料: {2} + + + + Call to BeginDrag must succeed before calling drag functions. + 呼叫拖曳函式之前必須先成功呼叫 BeginDrag。 + + + + Inherited control + 繼承的控制項 + + + + Inherited control (Private) + 繼承的控制項 (Private) + + The container cannot be disposed at design time. 這個容器無法在設計階段處置。 @@ -48,8 +275,12 @@ - An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows:\r\n\r\n{0} - 載入文件時發生錯誤。請修正錯誤,然後重新嘗試載入文件。錯誤訊息為:\r\n\r\n{0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} + An error occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: + + {0} @@ -67,11 +298,6 @@ 無法從服務容器移除服務 {0}。 - - Could not find method '{0}' - 找不到方法 '{0}' - - Cannot remove or destroy inherited component '{0}'. 無法移除或摧毀繼承的元件 '{0}'。 @@ -222,16 +448,51 @@ 控制設計工具是否應使用對齊線。如果為 true,就會使用對齊線來對齊。如果為 false,就會使用格線。 + + Dock in Parent Container + 停駐於父容器中 + + + + Undock in Parent Container + 取消停駐於父容器中 + + .NET Component .NET 元件 + + Drag {0} components + 拖曳 {0} 個元件 + + + + Move {0} + 移動 {0} + + + + Move {0} components + 移動 {0} 個元件 + + This IDataObject doesn't support SetData. 此 IDataObject 不支援 SetData。 + + Size {0} + 大小 {0} + + + + Size {0} components + 調整 {0} 元件的大小 + + The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties. 已經將擴充性提供者 {0} 加入做為擴充項。加入另一個會產生重複的屬性。 @@ -242,6 +503,16 @@ 唯讀 + + '{1}' is not a valid value for '{0}'. + '{1}' 不是 '{0}' 的有效值。 + + + + '{1}' is not a valid value for '{0}'. '{0}' should be between {2} and {3}. + '{1}' 不是 '{0}' 的有效值。'{0}' 應該介於 {2} 與 {3} 之間。 + + This method/object is not implemented by design. 此方法/物件並非由設計實作。 @@ -252,6 +523,11 @@ 此平台不支援 WinForms Designer。 + + RTL_False + RTL_False + RTL_False in Left-to-right languages and anything else (RTL_True) for right to left. + You cannot create a new session because this serialization manager already has an active serialization session. 無法建立新工作階段,因為這個序列化管理員已經有使用中的序列化工作階段。 @@ -289,7 +565,7 @@ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. - Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}. + 不支援 {0} 類型的項目。序列化程式要求項目必須為以下其中一種: {1}。 @@ -337,6 +613,16 @@ 類型 '{0}' 沒有名為 '{1}' 的屬性。 + + The object '{0}' returned null for the property '{1}' but this is not allowed. + The object '{0}' returned null for the property '{1}' but this is not allowed. + + + + Code generation for property '{0}' failed. Error was: '{1}' + Code generation for property '{0}' failed. Error was: '{1}' + + Error reading resources from the resource file for the culture {0}: {1} 從資源檔案讀取文化特性 {0} 的資源時發生錯誤: {1} @@ -347,6 +633,11 @@ 從資源檔案讀取預設文化特性的資源時發生錯誤: {0} + + The designer must create an instance of type '{0}' but it cannot because the type is declared as abstract. + 設計工具必須建立類型 '{0}' 的執行個體,但是因為已經將這個類型宣告為抽象,所以無法建立。 + + Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. 找不到類型 '{0}'。請確認已經參考包含此類型的組件。如果此類型是您開發專案的一部分,請確認此專案是否已使用您目前平台的設定或 [Any CPU] 成功建置。 @@ -357,6 +648,296 @@ 變數名稱 '{0}' 尚未宣告或沒有指派。 + + &About... + 關於(&A)... + + + + &Contents + 內容(&C) + + + + &Copy + 複製(&C) + + + + Create Standard Menu + 建立標準功能表 + + + + &Customize + 自訂(&C) + + + + Cu&t + 剪下(&T) + + + + &Edit + 編輯(&E) + + + + E&xit + 結束(&X) + + + + &File + 檔案(&F) + + + + &Help + 說明(&H) + + + + &Index + 索引(&I) + + + + &New + 新增(&N) + + + + &Open + 開啟(&O) + + + + &Options + 選項(&O) + + + + &Paste + 貼上(&P) + + + + &Print + 列印(&P) + + + + Print Pre&view + 預覽列印(&V) + + + + &Redo + 取消復原(&R) + + + + &Save + 儲存(&S) + + + + Save &As + 另存新檔(&A) + + + + &Search + 搜尋(&S) + + + + Select &All + 全選(&A) + + + + &Tools + 工具(&T) + + + + &Undo + 復原(&U) + + + + C&ut + 剪下(&U) + + + + He&lp + 說明(&L) + + + + Dock: + Dock: + + + + Changes the Dock property + 變更 Dock 屬性 + + + + GripStyle: + GripStyle: + + + + Changes the GripStyle property + 變更 GripStyle 屬性 + + + + Layout && Appearance + 配置與外觀 + + + + RenderMode: + RenderMode: + + + + Changes the RenderMode property + 變更 RenderMode 屬性 + + + + Adding {0} Item + 加入 {0} 項目 + + + + AllowItemReorder and AllowDrop cannot both be true. + AllowItemReorder 和 AllowDrop 不能同時為 true。 + + + + ToolStrip New Item create Transaction. + ToolStrip 新項目建立異動。 + + + + Embed in ToolStripContainer + Embed in ToolStripContainer + + + + Embeds the current ToolStrip in ToolStripContainer + 將目前的 ToolStrip 嵌入 ToolStripContainer + + + + &Insert Standard Items + 插入標準項目(&I) + + + + Inserts standard items in the current ToolStrip + 將標準項目插入目前的 ToolStrip + + + + Type Here + 在此鍵入 + + + + Type Text for ToolStripMenuItem + 輸入 ToolStripMenuItem 的文字 + + + + Add Menu Item + 新增功能表項目 + + + + Add ToolStripStatusLabel + 加入 ToolStripStatusLabel + + + + Add ToolStripButton + 加入 ToolStripButton + + + + New item selection + 新增項目選取範圍 + + + + Adding Item + 加入項目 + + + + Removing Item + 移除項目 + + + + &Edit DropDownItems... + 編輯 DropDownItems(&E)... + + + + ToolStrip MenuItem Insert in DropDown Transaction. + DropDown 異動中的 ToolStrip MenuItem 插入。 + + + + &Edit Items... + 編輯項目(&E)... + + + + Con&vert To + 轉換為(&V) + + + + &Insert + 插入(&I) + + + + Set I&mage... + 設定影像(&M)... + + + + ToolStripItem Property Change Transaction. + ToolStripItem 屬性變更異動。 + + + + ToolStripItem Morphing Transaction. + ToolStripItem 變形異動。 + + + + '{0}' + '{0}' + + + + Cannot add ToolStripSeparator to MenuStrip. + 無法將 ToolStripSeparator 加入 MenuStrip。 + + Argument should be a non-empty string. 引數必須是非空白字串。 @@ -377,11 +958,31 @@ 資料類型 {0} 不可序列化。要加入至屬性字典的項目必須是可序列化的。 + + Auto Arrange Tray Icons + 自動排列匣圖示 + + + + Line Up Tray Icons + 對齊匣圖示 + + + + Show Large or Small Icons + 顯示大型圖示或小型圖示 + + Type '{0}' is not available in the target framework. 類型 '{0}' 不適用於此目標 Framework。 + + Error + 錯誤 + + Add Component 加入元件 @@ -432,6 +1033,26 @@ 未實作。 + + <couldn't find resource string "WindowsFormsAddEvent"> + <找不到資源字串 "WindowsFormsAddEvent"> + + + + Horizontal center of {0} component(s) + {0} 元件水平置中 + + + + Vertical center of {0} component(s) + {0} 元件垂直置中 + + + + The Locked property determines if we can move or resize the control. + 鎖定的屬性決定我們是否可以移動控制項或調整控制項大小。 + + \ No newline at end of file diff --git a/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj b/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj index 0e554eb7b32..b3941afdf14 100644 --- a/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj +++ b/src/System.Windows.Forms.Design/src/System.Windows.Forms.Design.csproj @@ -10,7 +10,7 @@ true $(NoWarn);618 - $(DefineConstants);WINFORMS_DESIGN_NAMESPACE; + $(DefineConstants);DRAWING_DESIGN_NAMESPACE @@ -26,10 +26,12 @@ + + @@ -38,8 +40,12 @@ + + + + diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/CodeMarkers.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/CodeMarkers.cs index 60c25b71b87..f85dcbc09ff 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/CodeMarkers.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/CodeMarkers.cs @@ -175,7 +175,7 @@ public bool CodeMarkerEx(int nTimerID, byte[] aBuff) // Check the arguments only after checking whether code markers are enabled // This allows the calling code to pass null value and avoid calculation of data if nothing is to be logged if (aBuff == null) - throw new ArgumentNullException("aBuff"); + throw new ArgumentNullException(nameof(aBuff)); try { @@ -236,7 +236,7 @@ public bool CodeMarkerEx(int nTimerID, string stringData) // Check the arguments only after checking whether code markers are enabled // This allows the calling code to pass null value and avoid calculation of data if nothing is to be logged if (stringData == null) - throw new ArgumentNullException("stringData"); + throw new ArgumentNullException(nameof(stringData)); try { @@ -328,7 +328,7 @@ private static bool UsePrivateCodeMarkers(string regRoot, RegistryView registryV { if (regRoot == null) { - throw new ArgumentNullException("regRoot"); + throw new ArgumentNullException(nameof(regRoot)); } // Reads the Performance subkey from the given registry key @@ -393,7 +393,7 @@ public bool InitPerformanceDll(int iApp, string strRegRoot, RegistryView registr if (strRegRoot == null) { - throw new ArgumentNullException("strRegRoot"); + throw new ArgumentNullException(nameof(strRegRoot)); } this.regroot = strRegRoot; diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ComponentDesigner.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ComponentDesigner.cs index 25c4ef3abfe..bf76439cd04 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ComponentDesigner.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ComponentDesigner.cs @@ -45,12 +45,11 @@ public virtual DesignerActionListCollection ActionLists /// public virtual ICollection AssociatedComponents { - get - { - return new IComponent[0]; - } + get => new IComponent[0]; } + internal virtual bool CanBeAssociatedWith(IDesigner parentDesigner) => true; + /// /// Gets or sets a value indicating whether or not this component is being inherited. /// @@ -456,6 +455,23 @@ public virtual void DoDefaultAction() } } + internal bool IsRootDesigner + { + get + { + Debug.Assert(_component != null, + "this.component needs to be set before this method is valid."); + + bool isRoot = false; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && _component == host.RootComponent) + { + isRoot = true; + } + return isRoot; + } + } + /// /// Initializes a new instance of the class using the specified component. /// @@ -880,7 +896,7 @@ public object this[string propertyName] { if (propertyName == null) { - throw new ArgumentNullException("propertyName"); + throw new ArgumentNullException(nameof(propertyName)); } // First, check to see if the name is in the given properties table @@ -940,7 +956,7 @@ internal bool ShouldSerializeValue(string propertyName, object defaultValue) { if (propertyName == null) { - throw new ArgumentNullException("propertyName"); + throw new ArgumentNullException(nameof(propertyName)); } if (Contains(propertyName)) diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionHeaderItem.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionHeaderItem.cs new file mode 100644 index 00000000000..860ca085afe --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionHeaderItem.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + internal sealed class DesignerActionHeaderItem : DesignerActionTextItem + { + public DesignerActionHeaderItem(string displayName) : base(displayName, displayName) + { + } + + public DesignerActionHeaderItem(string displayName, string category) : base(displayName, category) + { + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs index 545959df806..34d64277245 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs @@ -15,61 +15,25 @@ namespace System.ComponentModel.Design /// public abstract class DesignerActionItem { - private bool _allowAssociate; - private readonly string _displayName; - private readonly string _description; - private readonly string _category; private IDictionary _properties; - private bool _showInSourceView = true; public DesignerActionItem(string displayName, string category, string description) { - _category = category; - _description = description; - _displayName = displayName == null ? null : Regex.Replace(displayName, @"\(\&.\)", ""); + DisplayName = displayName == null ? null : Regex.Replace(displayName, @"\(\&.\)", ""); + Category = category; + Description = description; } - internal DesignerActionItem() - { - } + public bool AllowAssociate { get; set; } - public bool AllowAssociate - { - get => _allowAssociate; - set => _allowAssociate = value; - } + public virtual string Category { get; } - public virtual string Category - { - get => _category; - } + public virtual string Description { get; } - public virtual string Description - { - get => _description; - } + public virtual string DisplayName { get; } - public virtual string DisplayName - { - get => _displayName; - } + public IDictionary Properties => _properties ?? (_properties = new HybridDictionary()); - public IDictionary Properties - { - get - { - if (_properties == null) - { - _properties = new HybridDictionary(); - } - return _properties; - } - } - - public bool ShowInSourceView - { - get => _showInSourceView; - set => _showInSourceView = value; - } + public bool ShowInSourceView { get; set; } = true; } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionList.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionList.cs index 15789da42e8..0b11c725058 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionList.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionList.cs @@ -14,53 +14,23 @@ namespace System.ComponentModel.Design /// public class DesignerActionList { - private bool _autoShow = false; - private readonly IComponent _component; - - /// - /// takes the related component as a parameter - /// public DesignerActionList(IComponent component) { - _component = component; + Component = component; } - public virtual bool AutoShow - { - get => _autoShow; - set - { - if (_autoShow != value) - { - _autoShow = value; - } - } - } + public virtual bool AutoShow { get; set; } - /// - /// this will be null for list created from upgraded verbs collection... - /// - public IComponent Component - { - get => _component; - } + public IComponent Component { get; } public object GetService(Type serviceType) { - if (_component != null && _component.Site != null) - { - return _component.Site.GetService(serviceType); - } - else - { - return null; - } + return Component?.Site?.GetService(serviceType); } public virtual DesignerActionItemCollection GetSortedActionItems() { - string dispName, desc, cat; - SortedList items = new SortedList(); + var items = new SortedList(); // we want to ignore the public methods and properties for THIS class (only take the inherited ones) IList originalMethods = Array.AsReadOnly(typeof(DesignerActionList).GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)); @@ -71,11 +41,14 @@ public virtual DesignerActionItemCollection GetSortedActionItems() foreach (MethodInfo info in methods) { if (originalMethods.Contains(info)) + { continue; + } + // Make sure there are only methods that take no parameters if (info.GetParameters().Length == 0 && !info.IsSpecialName) { - GetMemberDisplayProperties(info, out dispName, out desc, out cat); + GetMemberDisplayProperties(info, out string dispName, out string desc, out string cat); items.Add(info.Name, new DesignerActionMethodItem(this, info.Name, dispName, cat, desc)); } } @@ -85,43 +58,46 @@ public virtual DesignerActionItemCollection GetSortedActionItems() foreach (PropertyInfo info in properties) { if (originalProperties.Contains(info)) + { continue; - GetMemberDisplayProperties(info, out dispName, out desc, out cat); + } + + GetMemberDisplayProperties(info, out string dispName, out string desc, out string cat); items.Add(dispName, new DesignerActionPropertyItem(info.Name, dispName, cat, desc)); } - DesignerActionItemCollection returnValue = new DesignerActionItemCollection(); + var returnValue = new DesignerActionItemCollection(); foreach (DesignerActionItem dai in items.Values) { returnValue.Add(dai); } + return returnValue; } + private object GetCustomAttribute(MemberInfo info, Type attributeType) { object[] attributes = info.GetCustomAttributes(attributeType, true); - if (attributes.Length > 0) - { - return attributes[0]; - } - else - { - return null; - } + return attributes.Length > 0 ? attributes[0] : null; } private void GetMemberDisplayProperties(MemberInfo info, out string displayName, out string description, out string category) { - displayName = description = category = ""; + displayName = string.Empty; + description = string.Empty; + category = string.Empty; + if (GetCustomAttribute(info, typeof(DescriptionAttribute)) is DescriptionAttribute descAttr) { description = descAttr.Description; } + DisplayNameAttribute dispNameAttr = GetCustomAttribute(info, typeof(DisplayNameAttribute)) as DisplayNameAttribute; if (dispNameAttr != null) { displayName = dispNameAttr.DisplayName; } + CategoryAttribute catAttr = GetCustomAttribute(info, typeof(CategoryAttribute)) as CategoryAttribute; if (dispNameAttr != null) { diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListCollection.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListCollection.cs index 29c32c4aea4..8d708ab5032 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListCollection.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListCollection.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections; -using System.Diagnostics; using System.Runtime.InteropServices; namespace System.ComponentModel.Design @@ -26,10 +25,7 @@ public DesignerActionList this[int index] set => List[index] = value; } - public int Add(DesignerActionList value) - { - return List.Add(value); - } + public int Add(DesignerActionList value) => List.Add(value); public void AddRange(DesignerActionList[] value) { @@ -37,6 +33,7 @@ public void AddRange(DesignerActionList[] value) { throw new ArgumentNullException(nameof(value)); } + for (int i = 0; i < value.Length; i++) { Add(value[i]); @@ -49,6 +46,7 @@ public void AddRange(DesignerActionListCollection value) { throw new ArgumentNullException(nameof(value)); } + int currentCount = value.Count; for (int i = 0; i < currentCount; i++) { @@ -66,22 +64,9 @@ public void AddRange(DesignerActionListCollection value) public void CopyTo(DesignerActionList[] array, int index) => List.CopyTo(array, index); - protected override void OnSet(int index, object oldValue, object newValue) - { - } - - protected override void OnInsert(int index, object value) + protected override void OnValidate(object value) { + // Don't perform any validation. } - - protected override void OnClear() - { - } - - protected override void OnRemove(int index, object value) - { - } - - protected override void OnValidate(object value) => Debug.Assert(value != null, "Don't add null actionlist!"); } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedEventArgs.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedEventArgs.cs new file mode 100644 index 00000000000..54ef87e8bae --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedEventArgs.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// This EventArgs class is used by the DesignerActionService to signify that there has been a change in DesignerActionLists (added or removed) on the related object. + /// + public class DesignerActionListsChangedEventArgs : EventArgs + { + private readonly object _relatedObject; + private readonly DesignerActionListCollection _actionLists; + private readonly DesignerActionListsChangedType _changeType; //type of change + + /// + /// Constructor that requires the object in question, the type of change and the remaining actionlists left for the object. on the related object. + /// + public DesignerActionListsChangedEventArgs(object relatedObject, DesignerActionListsChangedType changeType, DesignerActionListCollection actionLists) + { + _relatedObject = relatedObject; + _changeType = changeType; + _actionLists = actionLists; + } + + /// + /// The type of changed that caused the related event to be thrown. + /// + public DesignerActionListsChangedType ChangeType + { + get => _changeType; + } + + /// + /// The object this change is related to. + /// + public object RelatedObject + { + get => _relatedObject; + } + + /// + /// The remaining actionlists left for the related object. + /// + public DesignerActionListCollection ActionLists + { + get => _actionLists; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedEventHandler.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedEventHandler.cs new file mode 100644 index 00000000000..0c5e5b1fac0 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedEventHandler.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// This event is thown by the DesignerActionListservice when a shortcut is either added or removed to/from the related object. + /// + [System.Runtime.InteropServices.ComVisible(true)] + public delegate void DesignerActionListsChangedEventHandler(object sender, DesignerActionListsChangedEventArgs e); +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedType.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedType.cs new file mode 100644 index 00000000000..7d4d4f8d577 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionListsChangedType.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// An enum that defines what time of action happend to the related object's DesignerActionLists collection. + /// + [Runtime.InteropServices.ComVisible(true)] + public enum DesignerActionListsChangedType + { + /// + /// Signifies that one or more DesignerActionList was added. + /// + ActionListsAdded, + /// + /// Signifies that one or more DesignerActionList was removed. + /// + ActionListsRemoved + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionPanel.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionPanel.cs new file mode 100644 index 00000000000..3886677ae20 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionPanel.cs @@ -0,0 +1,2977 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Design; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Globalization; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using System.Windows.Forms.Design; +using System.Windows.Forms.VisualStyles; + +namespace System.ComponentModel.Design +{ + internal sealed class DesignerActionPanel : ContainerControl + { + private static readonly object s_eventFormActivated = new object(); + private static readonly object s_eventFormDeactivate = new object(); + + private const int EditInputWidth = 150; // The static size of edit controls + private const int ListBoxMaximumHeight = 200; // The maximum height of a dropdown listbox + private const int MinimumWidth = 150; // The minimum overall width of the panel + private const int BottomPadding = 2; // Padding at the bottom of the panel + private const int TopPadding = 2; // Padding at the top of the panel + + private const int LineLeftMargin = 5; // Left padding for all lines + private const int LineRightMargin = 4; // Right padding for all lines + private const int LineVerticalPadding = 7; // Vertical padding between lines + private const int TextBoxTopPadding = 4; // Additional padding for top of textbox lines + private const int SeparatorHorizontalPadding = 3; // Left and right padding for separator lines + private const int TextBoxLineCenterMargin = 5; // Padding between the label region and editor region of a textbox line + private const int TextBoxLineInnerPadding = 1; // Padding within the editor region of a textbox line + + private const int EditorLineSwatchPadding = 1; // Padding for the swatch of an editor line + private const int EditorLineButtonPadding = 1; // Padding for the button of an editor line + private const int PanelHeaderVerticalPadding = 3; // Vertical padding within the header of the panel + private const int PanelHeaderHorizontalPadding = 5; // Horizontal padding within the header of the panel + + private const int TextBoxHeightFixup = 2; // Countereffects the fix for VSWhidbey 359726 - we relied on the broken behavior before + private CommandID[] _filteredCommandIDs; + private readonly ToolTip _toolTip; + private readonly List _lines; + private readonly List _lineYPositions; + private readonly List _lineHeights; + + private readonly Color _gradientLightColor = SystemColors.Control; + private readonly Color _gradientDarkColor = SystemColors.Control; + private readonly Color _titleBarColor = SystemColors.ActiveCaption; + private readonly Color _titleBarUnselectedColor = SystemColors.InactiveCaption; + private readonly Color _titleBarTextColor = SystemColors.ActiveCaptionText; + private readonly Color _separatorColor = SystemColors.ControlDark; + private readonly Color _borderColor = SystemColors.ActiveBorder; + private readonly Color _linkColor = SystemColors.HotTrack; + private readonly Color _activeLinkColor = SystemColors.HotTrack; + private readonly Color _labelForeColor = SystemColors.ControlText; + + private readonly IServiceProvider _serviceProvider; + private bool _inMethodInvoke; + private bool _updatingTasks; + private bool _dropDownActive; + + public DesignerActionPanel(IServiceProvider serviceProvider) + { + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.Opaque, true); + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + SetStyle(ControlStyles.ResizeRedraw, true); + SetStyle(ControlStyles.UserPaint, true); + + _serviceProvider = serviceProvider; + _lines = new List(); + _lineHeights = new List(); + _lineYPositions = new List(); + _toolTip = new ToolTip(); + // Try to get the font from the IUIService, otherwise, use the default + IUIService uiService = (IUIService)ServiceProvider.GetService(typeof(IUIService)); + if (uiService != null) + { + Font = (Font)uiService.Styles["DialogFont"]; + if (uiService.Styles["VsColorPanelGradientDark"] is Color) + { + _gradientDarkColor = (Color)uiService.Styles["VsColorPanelGradientDark"]; + } + if (uiService.Styles["VsColorPanelGradientLight"] is Color) + { + _gradientLightColor = (Color)uiService.Styles["VsColorPanelGradientLight"]; + } + if (uiService.Styles["VsColorPanelHyperLink"] is Color) + { + _linkColor = (Color)uiService.Styles["VsColorPanelHyperLink"]; + } + if (uiService.Styles["VsColorPanelHyperLinkPressed"] is Color) + { + _activeLinkColor = (Color)uiService.Styles["VsColorPanelHyperLinkPressed"]; + } + if (uiService.Styles["VsColorPanelTitleBar"] is Color) + { + _titleBarColor = (Color)uiService.Styles["VsColorPanelTitleBar"]; + } + if (uiService.Styles["VsColorPanelTitleBarUnselected"] is Color) + { + _titleBarUnselectedColor = (Color)uiService.Styles["VsColorPanelTitleBarUnselected"]; + } + if (uiService.Styles["VsColorPanelTitleBarText"] is Color) + { + _titleBarTextColor = (Color)uiService.Styles["VsColorPanelTitleBarText"]; + } + if (uiService.Styles["VsColorPanelBorder"] is Color) + { + _borderColor = (Color)uiService.Styles["VsColorPanelBorder"]; + } + if (uiService.Styles["VsColorPanelSeparator"] is Color) + { + _separatorColor = (Color)uiService.Styles["VsColorPanelSeparator"]; + } + if (uiService.Styles["VsColorPanelText"] is Color) + { + _labelForeColor = (Color)uiService.Styles["VsColorPanelText"]; + } + } + MinimumSize = new Size(150, 0); + } + + public Color ActiveLinkColor + { + get => _activeLinkColor; + } + + public Color BorderColor + { + get => _borderColor; + } + + private bool DropDownActive + { + get => _dropDownActive; + } + + /// + /// Returns the list of commands that should be filtered by the form that hosts this panel. This is done so that these specific commands will not get passed on to VS, and can instead be handled by the panel itself. + /// + public CommandID[] FilteredCommandIDs + { + get + { + if (_filteredCommandIDs == null) + { + _filteredCommandIDs = new CommandID[] { + StandardCommands.Copy, + StandardCommands.Cut, + StandardCommands.Delete, + StandardCommands.F1Help, + StandardCommands.Paste, + StandardCommands.Redo, + StandardCommands.SelectAll, + StandardCommands.Undo, + MenuCommands.KeyCancel, + MenuCommands.KeyReverseCancel, + MenuCommands.KeyDefaultAction, + MenuCommands.KeyEnd, + MenuCommands.KeyHome, + MenuCommands.KeyMoveDown, + MenuCommands.KeyMoveLeft, + MenuCommands.KeyMoveRight, + MenuCommands.KeyMoveUp, + MenuCommands.KeyNudgeDown, + MenuCommands.KeyNudgeHeightDecrease, + MenuCommands.KeyNudgeHeightIncrease, + MenuCommands.KeyNudgeLeft, + MenuCommands.KeyNudgeRight, + MenuCommands.KeyNudgeUp, + MenuCommands.KeyNudgeWidthDecrease, + MenuCommands.KeyNudgeWidthIncrease, + MenuCommands.KeySizeHeightDecrease, + MenuCommands.KeySizeHeightIncrease, + MenuCommands.KeySizeWidthDecrease, + MenuCommands.KeySizeWidthIncrease, + MenuCommands.KeySelectNext, + MenuCommands.KeySelectPrevious, + MenuCommands.KeyShiftEnd, + MenuCommands.KeyShiftHome, + }; + } + return _filteredCommandIDs; + } + } + + /// + /// Gets the Line that currently has input focus. + /// + private Line FocusedLine + { + get + { + Control activeControl = ActiveControl; + if (activeControl != null) + { + return activeControl.Tag as Line; + } + return null; + } + } + + public Color GradientDarkColor + { + get => _gradientDarkColor; + } + + public Color GradientLightColor + { + get => _gradientLightColor; + } + + public bool InMethodInvoke + { + get => _inMethodInvoke; + internal set => _inMethodInvoke = value; + } + + public Color LinkColor + { + get => _linkColor; + } + + public Color SeparatorColor + { + get => _separatorColor; + } + + private IServiceProvider ServiceProvider + { + get => _serviceProvider; + } + + public Color TitleBarColor + { + get => _titleBarColor; + } + + public Color TitleBarTextColor + { + get => _titleBarTextColor; + } + + public Color TitleBarUnselectedColor + { + get => _titleBarUnselectedColor; + } + + public Color LabelForeColor + { + get => _labelForeColor; + } + + /// + /// Helper event so that Lines can be notified of this event. + /// + private event EventHandler FormActivated + { + add => Events.AddHandler(s_eventFormActivated, value); + remove => Events.RemoveHandler(s_eventFormActivated, value); + } + + /// + /// Helper event so that Lines can be notified of this event. + /// + private event EventHandler FormDeactivate + { + add => Events.AddHandler(s_eventFormDeactivate, value); + remove => Events.RemoveHandler(s_eventFormDeactivate, value); + } + + private void AddToCategories(LineInfo lineInfo, ListDictionary categories) + { + string categoryName = lineInfo.Item.Category; + if (categoryName == null) + { + categoryName = string.Empty; + } + + ListDictionary category = (ListDictionary)categories[categoryName]; + if (category == null) + { + category = new ListDictionary(); + categories.Add(categoryName, category); + } + + List categoryList = (List)category[lineInfo.List]; + if (categoryList == null) + { + categoryList = new List(); + category.Add(lineInfo.List, categoryList); + } + categoryList.Add(lineInfo); + } + + /// + /// Computes the best possible location (in desktop coordinates) to display the panel, given the size of the panel and the position of its anchor + /// + public static Point ComputePreferredDesktopLocation(Rectangle rectangleAnchor, Size sizePanel, out DockStyle edgeToDock) + { + Rectangle rectScreen = Screen.FromPoint(rectangleAnchor.Location).WorkingArea; + // Determine where we can draw the panel to minimize clipping. Start with the most preferred position, i.e. bottom-right of anchor For the purposes of computing the flags below, assume the anchor to be small enough to ignore its size. + bool fRightOfAnchor = true; + bool fAlignToScreenLeft = false; + + // if the panel is too wide, try flipping to left or aligning to screen left + if (rectangleAnchor.Right + sizePanel.Width > rectScreen.Right) + { // no room at right, try at left of anchor + fRightOfAnchor = false; + if (rectangleAnchor.Left - sizePanel.Width < rectScreen.Left) + { // no room at left, either + fAlignToScreenLeft = true; + } + } + + bool fBelowAnchor = (fRightOfAnchor ? true : false); + bool fAlignToScreenTop = false; + if (fBelowAnchor) + { + // if the panel is too tall, try flipping to top or aligning to screen top + if (rectangleAnchor.Bottom + sizePanel.Height > rectScreen.Bottom) + { // no room at bottom, try at top of anchor + fBelowAnchor = false; + if (rectangleAnchor.Top - sizePanel.Height < rectScreen.Top) + { // no room at top, either + fAlignToScreenTop = true; + } + } + } + else + { + // if the panel is too tall, try flipping to bottom or aligning to screen top + if (rectangleAnchor.Top - sizePanel.Height < rectScreen.Top) + { // no room at top, try at bottom of anchor + fBelowAnchor = true; + if (rectangleAnchor.Bottom + sizePanel.Height > rectScreen.Bottom) + { // no room at bottom, either + fAlignToScreenTop = true; + } + } + } + + // The flags give us a total of nine possible positions - {LeftOfAnchor, RightOfAnchor, AlignToScreenLeft} X {AboveAnchor, BelowAnchor, AlignToScreenTop} + // Out of these, we rule out one combination (AlignToScreenLeft, AlignToScreenTop) because this does not guarantee the alignment of an anchor edge with that of the panel edge + if (fAlignToScreenTop) + { + fAlignToScreenLeft = false; + } + + int x = 0, y = 0; + const int EDGE_SPACE = 0; + edgeToDock = DockStyle.None; + + // Compute the actual position now, based on the flags above, and taking the anchor size into account. + if (fAlignToScreenLeft && fBelowAnchor) + { + x = rectScreen.Left; + y = rectangleAnchor.Bottom + EDGE_SPACE; + edgeToDock = DockStyle.Bottom; + } + else if (fAlignToScreenLeft && !fBelowAnchor) + { + x = rectScreen.Left; + y = rectangleAnchor.Top - sizePanel.Height - EDGE_SPACE; + edgeToDock = DockStyle.Top; + } + else if (fRightOfAnchor && fAlignToScreenTop) + { + x = rectangleAnchor.Right + EDGE_SPACE; + y = rectScreen.Top; + edgeToDock = DockStyle.Right; + } + else if (fRightOfAnchor && fBelowAnchor) + { + x = rectangleAnchor.Right + EDGE_SPACE; + y = rectangleAnchor.Top; + edgeToDock = DockStyle.Right; + } + else if (fRightOfAnchor && !fBelowAnchor) + { + x = rectangleAnchor.Right + EDGE_SPACE; + y = rectangleAnchor.Bottom - sizePanel.Height; + edgeToDock = DockStyle.Right; + } + else if (!fRightOfAnchor && fAlignToScreenTop) + { + x = rectangleAnchor.Left - sizePanel.Width - EDGE_SPACE; + y = rectScreen.Top; + edgeToDock = DockStyle.Left; + } + else if (!fRightOfAnchor && fBelowAnchor) + { + x = rectangleAnchor.Left - sizePanel.Width - EDGE_SPACE; + y = rectangleAnchor.Top; + edgeToDock = DockStyle.Left; + } + else if (!fRightOfAnchor && !fBelowAnchor) + { + x = rectangleAnchor.Right - sizePanel.Width; + y = rectangleAnchor.Top - sizePanel.Height - EDGE_SPACE; + edgeToDock = DockStyle.Top; + } + else + { + Debug.Assert(false); // should never get here + } + return new Point(x, y); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _toolTip.Dispose(); + } + base.Dispose(disposing); + } + + private Size DoLayout(Size proposedSize, bool measureOnly) + { + // REVIEW: Is this a WinForms bug? This shouldn't be called if we're disposing since no one should care about layout + if (Disposing || IsDisposed) + { + return Size.Empty; + } + + int panelWidth = MinimumWidth; + int yPos = 0; + SuspendLayout(); + try + { + // Clear cached calculated information + _lineYPositions.Clear(); + _lineHeights.Clear(); + + // Layout each line + for (int i = 0; i < _lines.Count; i++) + { + Line line = _lines[i]; + _lineYPositions.Add(yPos); + Size size = line.LayoutControls(yPos, proposedSize.Width, measureOnly); + panelWidth = Math.Max(panelWidth, size.Width); + _lineHeights.Add(size.Height); + yPos += size.Height; + } + } + finally + { + ResumeLayout(!measureOnly); + } + return new Size(panelWidth, yPos + BottomPadding); + } + + public override Size GetPreferredSize(Size proposedSize) + { + // REVIEW: WinForms calls this inside of PerformLayout() only in DEBUG code.From the comment it looks like it's calling it to verify their own cached preferred size, so we just ignore this call. + if (proposedSize.IsEmpty) + { + return proposedSize; + } + return DoLayout(proposedSize, true); + } + + private static bool IsReadOnlyProperty(PropertyDescriptor pd) + { + if (pd.IsReadOnly) + { + return true; + } + return (pd.ComponentType.GetProperty(pd.Name).GetSetMethod() == null); + } + + protected override void OnFontChanged(EventArgs e) + { + base.OnFontChanged(e); + UpdateEditXPos(); + // REVIEW: How do we notify Lines that the font has changed? + } + + private void OnFormActivated(object sender, EventArgs e) + { + ((EventHandler)Events[s_eventFormActivated])?.Invoke(sender, e); + } + + private void OnFormClosing(object sender, CancelEventArgs e) + { + if (!e.Cancel && TopLevelControl != null) + { + Debug.Assert(TopLevelControl is Form, "DesignerActionPanel must be hosted on a Form."); + Form form = (Form)TopLevelControl; + if (form != null) + { + form.Closing -= new CancelEventHandler(OnFormClosing); + } + } + } + + private void OnFormDeactivate(object sender, EventArgs e) + { + ((EventHandler)Events[s_eventFormDeactivate])?.Invoke(sender, e); + } + + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + if (TopLevelControl is Form form) + { + form.Closing += new CancelEventHandler(OnFormClosing); + } + } + + protected override void OnLayout(LayoutEventArgs levent) + { + if (_updatingTasks) + { + return; + } + + DoLayout(Size, false); + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + if (_updatingTasks) + { + return; + } + + Rectangle rect = Bounds; + if (RightToLeft == RightToLeft.Yes) + { + using (LinearGradientBrush gradientBrush = new LinearGradientBrush(rect, GradientDarkColor, GradientLightColor, LinearGradientMode.Horizontal)) + { + e.Graphics.FillRectangle(gradientBrush, ClientRectangle); + } + } + else + { + using (LinearGradientBrush gradientBrush = new LinearGradientBrush(rect, GradientLightColor, GradientDarkColor, LinearGradientMode.Horizontal)) + { + e.Graphics.FillRectangle(gradientBrush, ClientRectangle); + } + } + + using (Pen borderPen = new Pen(BorderColor)) + { + e.Graphics.DrawRectangle(borderPen, new Rectangle(0, 0, Width - 1, Height - 1)); + } + + Rectangle originalClip = e.ClipRectangle; + // Determine the first line index to paint + int index = 0; + while ((index < (_lineYPositions.Count - 1)) && (_lineYPositions[index + 1] <= originalClip.Top)) + { + index++; + } + + Graphics g = e.Graphics; + for (int i = index; i < _lineYPositions.Count; i++) + { + Line line = _lines[i]; + int yPos = _lineYPositions[i]; + int lineHeight = _lineHeights[i]; + int lineWidth = Width; + // Set the clip rectangle so the lines can't mess with each other + g.SetClip(new Rectangle(0, yPos, lineWidth, lineHeight)); + + // Normalize the paint coordinates + g.TranslateTransform(0, yPos); + line.PaintLine(g, lineWidth, lineHeight); + g.ResetTransform(); + // Stop if we've painted all the lines in the clip rectangle + if (yPos + lineHeight > originalClip.Bottom) + { + break; + } + } + } + + protected override void OnRightToLeftChanged(EventArgs e) + { + base.OnRightToLeftChanged(e); + PerformLayout(); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + // TODO: RightToLeft management for left/right arrow keys (from old DesignerActionPanel) + Line focusedLine = FocusedLine; + if (focusedLine != null) + { + if (focusedLine.ProcessDialogKey(keyData)) + { + return true; + } + } + return base.ProcessDialogKey(keyData); + } + + // we want to loop + protected override bool ProcessTabKey(bool forward) + { + return (SelectNextControl(ActiveControl, forward, true, true, true)); + } + + private void ProcessLists(DesignerActionListCollection lists, ListDictionary categories) + { + if (lists == null) + { + return; + } + foreach (DesignerActionList list in lists) + { + if (list != null) + { + IEnumerable items = list.GetSortedActionItems(); + if (items != null) + { + foreach (DesignerActionItem item in items) + { + if (item == null) + { + continue; + } + LineInfo lineInfo = ProcessTaskItem(list, item); + if (lineInfo == null) + { + continue; + } + AddToCategories(lineInfo, categories); + // Process lists from related component + IComponent relatedComponent = null; + if (item is DesignerActionPropertyItem propItem) + { + relatedComponent = propItem.RelatedComponent; + } + else + { + if (item is DesignerActionMethodItem methodItem) + { + relatedComponent = methodItem.RelatedComponent; + } + } + if (relatedComponent != null) + { + IEnumerable relatedLineInfos = ProcessRelatedTaskItems(relatedComponent); + if (relatedLineInfos != null) + { + foreach (LineInfo relatedLineInfo in relatedLineInfos) + { + AddToCategories(relatedLineInfo, categories); + } + } + } + } + } + } + } + } + + private IEnumerable ProcessRelatedTaskItems(IComponent relatedComponent) + { + // Add the related tasks + Debug.Assert(relatedComponent != null); + DesignerActionListCollection relatedLists = null; + DesignerActionService actionService = (DesignerActionService)ServiceProvider.GetService(typeof(DesignerActionService)); + if (actionService != null) + { + relatedLists = actionService.GetComponentActions(relatedComponent); + } + else + { + // Try to use the component's service provider if it exists so that we end up getting the right IDesignerHost. + IServiceProvider serviceProvider = relatedComponent.Site; + if (serviceProvider == null) + { + serviceProvider = ServiceProvider; + } + IDesignerHost host = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + if (host != null) + { + if (host.GetDesigner(relatedComponent) is ComponentDesigner componentDesigner) + { + relatedLists = componentDesigner.ActionLists; + } + } + } + + List lineInfos = new List(); + + if (relatedLists != null) + { + foreach (DesignerActionList relatedList in relatedLists) + { + if (relatedList != null) + { + IEnumerable items = relatedList.GetSortedActionItems(); + if (items != null) + { + foreach (DesignerActionItem relatedItem in items) + { + if (relatedItem != null) + { + if (relatedItem.AllowAssociate) + { + LineInfo lineInfo = ProcessTaskItem(relatedList, relatedItem); + if (lineInfo != null) + { + lineInfos.Add(lineInfo); + } + } + } + } + } + } + } + } + return lineInfos; + } + + private LineInfo ProcessTaskItem(DesignerActionList list, DesignerActionItem item) + { + Line newLine; + if (item is DesignerActionMethodItem) + { + newLine = new MethodLine(_serviceProvider, this); + } + else if (item is DesignerActionPropertyItem pti) + { + PropertyDescriptor pd = TypeDescriptor.GetProperties(list)[pti.MemberName]; + if (pd == null) + { + throw new InvalidOperationException(string.Format(SR.DesignerActionPanel_CouldNotFindProperty, pti.MemberName, list.GetType().FullName)); + } + + TypeDescriptorContext context = new TypeDescriptorContext(_serviceProvider, pd, list); + UITypeEditor editor = (UITypeEditor)pd.GetEditor(typeof(UITypeEditor)); + bool standardValuesSupported = pd.Converter.GetStandardValuesSupported(context); + if (editor == null) + { + if (pd.PropertyType == typeof(bool)) + { + if (IsReadOnlyProperty(pd)) + { + newLine = new TextBoxPropertyLine(_serviceProvider, this); + } + else + { + newLine = new CheckBoxPropertyLine(_serviceProvider, this); + } + } + else if (standardValuesSupported) + { + newLine = new EditorPropertyLine(_serviceProvider, this); + } + else + { + newLine = new TextBoxPropertyLine(_serviceProvider, this); + } + } + else + { + newLine = new EditorPropertyLine(_serviceProvider, this); + } + } + else if (item is DesignerActionTextItem) + { + if (item is DesignerActionHeaderItem) + { + newLine = new HeaderLine(_serviceProvider, this); + } + else + { + newLine = new TextLine(_serviceProvider, this); + } + } + else + { + // Ignore unknown items + return null; + } + return new LineInfo(list, item, newLine); + } + + private void SetDropDownActive(bool active) + { + _dropDownActive = active; + } + + private void ShowError(string errorMessage) + { + IUIService uiService = (IUIService)ServiceProvider.GetService(typeof(IUIService)); + if (uiService != null) + { + uiService.ShowError(errorMessage); + } + else + { + MessageBoxOptions options = 0; + if (SR.RTL != "RTL_False") + { + options = (MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading); + } + MessageBox.Show(this, errorMessage, string.Format(SR.UIServiceHelper_ErrorCaption), MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, options); + } + } + + /// + /// Strips out ampersands used for mnemonics so that they don't show up in the rendering. + /// - Convert "&&" to "&" + /// - Convert "&x" to "x" + /// - An ampersand by itself at the end of a string is displayed as-is + /// + private static string StripAmpersands(string s) + { + if (string.IsNullOrEmpty(s)) + { + return string.Empty; + } + StringBuilder result = new StringBuilder(s.Length); + for (int i = 0; i < s.Length; i++) + { + if (s[i] == '&') + { + // Skip over the ampersand + i++; + if (i == s.Length) + { + // If we're at the last character just add the ampersand and stop + result.Append('&'); + break; + } + } + result.Append(s[i]); + } + return result.ToString(); + } + + private void UpdateEditXPos() + { + // Find the correct edit control position + int editXPos = 0; + for (int i = 0; i < _lines.Count; i++) + { + if (_lines[i] is TextBoxPropertyLine line) + { + editXPos = Math.Max(editXPos, ((TextBoxPropertyLine)line).GetEditRegionXPos()); + } + } + + // Make all the edit controls line up + for (int i = 0; i < _lines.Count; i++) + { + if (_lines[i] is TextBoxPropertyLine line) + { + line.SetEditRegionXPos(editXPos); + } + } + } + + public void UpdateTasks(DesignerActionListCollection actionLists, DesignerActionListCollection serviceActionLists, string title, string subtitle) + { + _updatingTasks = true; + SuspendLayout(); + try + { + AccessibleName = title; + AccessibleDescription = subtitle; + + // Store the focus state + string focusId = string.Empty; + Line focusedLine = FocusedLine; + if (focusedLine != null) + { + focusId = focusedLine.FocusId; + } + + // Merge the categories from the lists and create controls for each of the items + ListDictionary categories = new ListDictionary(); + ProcessLists(actionLists, categories); + ProcessLists(serviceActionLists, categories); + // Create a flat list of lines w/ separators + List newLines = new List + { + // Always add a special line for the header + new LineInfo(null, new DesignerActionPanelHeaderItem(title, subtitle), new PanelHeaderLine(_serviceProvider, this)) + }; + int categoriesIndex = 0; + foreach (ListDictionary category in categories.Values) + { + int categoryIndex = 0; + foreach (List categoryList in category.Values) + { + for (int i = 0; i < categoryList.Count; i++) + { + newLines.Add(categoryList[i]); + } + + categoryIndex++; + // Add a sub-separator + if (categoryIndex < category.Count) + { + newLines.Add(new LineInfo(null, null, new SeparatorLine(_serviceProvider, this, true))); + } + } + + categoriesIndex++; + // Add a separator + if (categoriesIndex < categories.Count) + { + newLines.Add(new LineInfo(null, null, new SeparatorLine(_serviceProvider, this))); + } + } + + // Now try to update similar lines + int currentTabIndex = 0; + for (int i = 0; i < newLines.Count; i++) + { + LineInfo newLineInfo = newLines[i]; + Line newLine = newLineInfo.Line; + // See if we can update an old line + bool updated = false; + if (i < _lines.Count) + { + Line oldLine = _lines[i]; + + if (oldLine.GetType() == newLine.GetType()) + { + oldLine.UpdateActionItem(newLineInfo.List, newLineInfo.Item, _toolTip, ref currentTabIndex); + updated = true; + } + else + { + oldLine.RemoveControls(Controls); + _lines.RemoveAt(i); + } + } + + if (!updated) + { + // Add the new controls + List newControlList = newLine.GetControls(); + Control[] controls = new Control[newControlList.Count]; + newControlList.CopyTo(controls); + Controls.AddRange(controls); + + newLine.UpdateActionItem(newLineInfo.List, newLineInfo.Item, _toolTip, ref currentTabIndex); + _lines.Insert(i, newLine); + } + } + + // Remove any excess lines + for (int i = _lines.Count - 1; i >= newLines.Count; i--) + { + Line excessLine = _lines[i]; + excessLine.RemoveControls(Controls); + _lines.RemoveAt(i); + } + + // Restore focus + if (!string.IsNullOrEmpty(focusId)) + { + foreach (Line line in _lines) + { + if (string.Equals(line.FocusId, focusId, StringComparison.Ordinal)) + { + line.Focus(); + } + } + } + } + finally + { + UpdateEditXPos(); + _updatingTasks = false; + // REVIEW: We should rely on the caller to actually perform layout since it our scenarios, the entire right pane will have to be layed out + // Actually, we do want to resume layout since invalidation causes an OnPaint, and OnPaint relies on everything being layed out already + ResumeLayout(true); + } + Invalidate(); + } + + private class LineInfo + { + public Line Line; + public DesignerActionItem Item; + public DesignerActionList List; + + public LineInfo(DesignerActionList list, DesignerActionItem item, Line line) + { + Debug.Assert(line != null); + Line = line; + Item = item; + List = list; + } + } + + internal sealed class TypeDescriptorContext : ITypeDescriptorContext + { + private readonly IServiceProvider _serviceProvider; + private readonly PropertyDescriptor _propDesc; + private readonly object _instance; + + public TypeDescriptorContext(IServiceProvider serviceProvider, PropertyDescriptor propDesc, object instance) + { + _serviceProvider = serviceProvider; + _propDesc = propDesc; + _instance = instance; + } + + private IComponentChangeService ComponentChangeService + { + get => (IComponentChangeService)_serviceProvider.GetService(typeof(IComponentChangeService)); + } + + public IContainer Container + { + get => (IContainer)_serviceProvider.GetService(typeof(IContainer)); + } + + public object Instance + { + get => _instance; + } + + public PropertyDescriptor PropertyDescriptor + { + get => _propDesc; + } + + public object GetService(Type serviceType) => _serviceProvider.GetService(serviceType); + + public bool OnComponentChanging() + { + if (ComponentChangeService != null) + { + try + { + ComponentChangeService.OnComponentChanging(_instance, _propDesc); + } + catch (CheckoutException ce) + { + if (ce == CheckoutException.Canceled) + { + return false; + } + throw ce; + } + } + return true; + } + + public void OnComponentChanged() + { + if (ComponentChangeService != null) + { + ComponentChangeService.OnComponentChanged(_instance, _propDesc, null, null); + } + } + } + + private abstract class Line + { + private readonly DesignerActionPanel _actionPanel; + private List _addedControls; + private readonly IServiceProvider _serviceProvider; + + public Line(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) + { + _serviceProvider = serviceProvider; + _actionPanel = actionPanel ?? throw new ArgumentNullException("actionPanel"); + } + + protected DesignerActionPanel ActionPanel + { + get => _actionPanel; + } + + public abstract string FocusId + { + get; + } + + protected IServiceProvider ServiceProvider + { + get => _serviceProvider; + } + + protected abstract void AddControls(List controls); + + internal List GetControls() + { + _addedControls = new List(); + AddControls(_addedControls); + // Tag all the controls with the Line so we know who owns it + foreach (Control c in _addedControls) + { + c.Tag = this; + } + return _addedControls; + } + + public abstract void Focus(); + + public abstract Size LayoutControls(int top, int width, bool measureOnly); + + public virtual void PaintLine(Graphics g, int lineWidth, int lineHeight) + { + } + + protected internal virtual bool ProcessDialogKey(Keys keyData) => false; + + internal void RemoveControls(Control.ControlCollection controls) + { + for (int i = 0; i < _addedControls.Count; i++) + { + Control c = _addedControls[i]; + c.Tag = null; + controls.Remove(c); + } + } + + internal abstract void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex); + } + + private sealed class DesignerActionPanelHeaderItem : DesignerActionItem + { + private readonly string _subtitle; + + public DesignerActionPanelHeaderItem(string title, string subtitle) : base(title, null, null) + { + _subtitle = subtitle; + } + + public string Subtitle + { + get => _subtitle; + } + } + + private sealed class PanelHeaderLine : Line + { + private DesignerActionList _actionList; + private DesignerActionPanelHeaderItem _panelHeaderItem; + private Label _titleLabel; + private Label _subtitleLabel; + private bool _formActive; + + public PanelHeaderLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + public sealed override string FocusId + { + get => string.Empty; + } + + protected override void AddControls(List controls) + { + _titleLabel = new Label + { + BackColor = Color.Transparent, + ForeColor = ActionPanel.TitleBarTextColor, + TextAlign = Drawing.ContentAlignment.MiddleLeft, + UseMnemonic = false + }; + + _subtitleLabel = new Label + { + BackColor = Color.Transparent, + ForeColor = ActionPanel.TitleBarTextColor, + TextAlign = Drawing.ContentAlignment.MiddleLeft, + UseMnemonic = false + }; + + controls.Add(_titleLabel); + controls.Add(_subtitleLabel); + } + + public sealed override void Focus() + { + Debug.Fail("Should never try to focus a PanelHeaderLine"); + } + + public override Size LayoutControls(int top, int width, bool measureOnly) + { + Size titleSize = _titleLabel.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)); + Size subtitleSize = Size.Empty; + if (!string.IsNullOrEmpty(_panelHeaderItem.Subtitle)) + { + subtitleSize = _subtitleLabel.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)); + } + + if (!measureOnly) + { + _titleLabel.Location = new Point(LineLeftMargin, top + PanelHeaderVerticalPadding); + _titleLabel.Size = titleSize; + _subtitleLabel.Location = new Point(LineLeftMargin, top + PanelHeaderVerticalPadding * 2 + titleSize.Height); + _subtitleLabel.Size = subtitleSize; + } + int newWidth = Math.Max(titleSize.Width, subtitleSize.Width) + 2 * PanelHeaderHorizontalPadding; + int newHeight = (subtitleSize.IsEmpty ? (titleSize.Height + 2 * PanelHeaderVerticalPadding) : (titleSize.Height + subtitleSize.Height + 3 * PanelHeaderVerticalPadding)); + return new Size(newWidth + 2, newHeight + 1); + } + + private void OnFormActivated(object sender, EventArgs e) + { + // TODO: Figure out better rect + _formActive = true; + ActionPanel.Invalidate(); + //ActionPanel.Invalidate(new Rectangle(EditRegionLocation, EditRegionSize), false); + } + + private void OnFormDeactivate(object sender, EventArgs e) + { + // TODO: Figure out better rect + _formActive = false; + ActionPanel.Invalidate(); + } + + private void OnParentControlFontChanged(object sender, EventArgs e) + { + if (_titleLabel != null && _subtitleLabel != null) + { + _titleLabel.Font = new Font(ActionPanel.Font, FontStyle.Bold); + _subtitleLabel.Font = ActionPanel.Font; + } + } + + public override void PaintLine(Graphics g, int lineWidth, int lineHeight) + { + Color backColor = (_formActive || ActionPanel.DropDownActive) ? ActionPanel.TitleBarColor : ActionPanel.TitleBarUnselectedColor; + using (SolidBrush b = new SolidBrush(backColor)) + { + g.FillRectangle(b, 1, 1, lineWidth - 2, lineHeight - 1); + } + + // Paint a line under the title label + using (Pen p = new Pen(ActionPanel.BorderColor)) + { + g.DrawLine(p, 0, lineHeight - 1, lineWidth, lineHeight - 1); + } + } + + internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) + { + _actionList = actionList; + _panelHeaderItem = (DesignerActionPanelHeaderItem)actionItem; + _titleLabel.Text = _panelHeaderItem.DisplayName; + _titleLabel.TabIndex = currentTabIndex++; + _subtitleLabel.Text = _panelHeaderItem.Subtitle; + _subtitleLabel.TabIndex = currentTabIndex++; + _subtitleLabel.Visible = (_subtitleLabel.Text.Length != 0); + // Force the font to update + OnParentControlFontChanged(null, EventArgs.Empty); + } + } + + private sealed class MethodLine : Line + { + private DesignerActionList _actionList; + private DesignerActionMethodItem _methodItem; + private MethodItemLinkLabel _linkLabel; + public MethodLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + public sealed override string FocusId + { + get => "METHOD:" + _actionList.GetType().FullName + "." + _methodItem.MemberName; + } + + protected override void AddControls(List controls) + { + _linkLabel = new MethodItemLinkLabel + { + ActiveLinkColor = ActionPanel.ActiveLinkColor, + AutoSize = false, + BackColor = Color.Transparent, + LinkBehavior = LinkBehavior.HoverUnderline, + LinkColor = ActionPanel.LinkColor, + TextAlign = Drawing.ContentAlignment.MiddleLeft, + UseMnemonic = false, + VisitedLinkColor = ActionPanel.LinkColor + }; + _linkLabel.LinkClicked += new LinkLabelLinkClickedEventHandler(OnLinkLabelLinkClicked); + controls.Add(_linkLabel); + } + + public sealed override void Focus() + { + _linkLabel.Focus(); + } + + public override Size LayoutControls(int top, int width, bool measureOnly) + { + Size linkLabelSize = _linkLabel.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)); + if (!measureOnly) + { + _linkLabel.Location = new Point(LineLeftMargin, top + LineVerticalPadding / 2); + _linkLabel.Size = linkLabelSize; + } + return linkLabelSize + new Size(LineLeftMargin + LineRightMargin, LineVerticalPadding); + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void OnLinkLabelLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Debug.Assert(!ActionPanel.InMethodInvoke, "Nested method invocation"); + ActionPanel.InMethodInvoke = true; + try + { + _methodItem.Invoke(); + } + catch (Exception ex) + { + if (ex is TargetInvocationException) + { + ex = ex.InnerException; + } + //NOTE: We had code to rethrow if this was one of [NullReferenceException, StackOverflowException, OutOfMemoryException, + //ThreadAbortException]. Removing this rethrow. StackOverflow and ThreadAbort can't be meaningfully caught, and + //NullRef and OutOfMemory really shouldn't be caught. Out of these, OOM is the most correct one to call, but OOM is + //thrown by GDI+ for pretty much any problem, so isn't reliable as an actual indicator that you're out of memory. If + //you really are out of memory, it's very likely you'll get another OOM shortly. + ActionPanel.ShowError(string.Format(SR.DesignerActionPanel_ErrorInvokingAction, _methodItem.DisplayName, Environment.NewLine + ex.Message)); + } + finally + { + ActionPanel.InMethodInvoke = false; + } + } + + internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) + { + _actionList = actionList; + _methodItem = (DesignerActionMethodItem)actionItem; + toolTip.SetToolTip(_linkLabel, _methodItem.Description); + _linkLabel.Text = StripAmpersands(_methodItem.DisplayName); + _linkLabel.AccessibleDescription = actionItem.Description; + _linkLabel.TabIndex = currentTabIndex++; + } + + private sealed class MethodItemLinkLabel : LinkLabel + { + protected override bool ProcessDialogKey(Keys keyData) + { + if ((keyData & Keys.Control) == Keys.Control) + { + Keys keyCode = keyData & Keys.KeyCode; + switch (keyCode) + { + case Keys.Tab: + // We specifically ignore Ctrl+Tab because it prevents the window switcher dialog from showing up in VS. Normally the key combination is only needed when a LinkLabel contains multiple links, but that can't happen inside the DesignerActionPanel. + return false; + } + } + return base.ProcessDialogKey(keyData); + } + } + } + + private abstract class PropertyLine : Line + { + private DesignerActionList _actionList; + private DesignerActionPropertyItem _propertyItem; + private object _value; + private bool _pushingValue; + private PropertyDescriptor _propDesc; + private ITypeDescriptorContext _typeDescriptorContext; + + public PropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + public sealed override string FocusId + { + get => "PROPERTY:" + _actionList.GetType().FullName + "." + _propertyItem.MemberName; + } + + protected PropertyDescriptor PropertyDescriptor + { + get + { + if (_propDesc == null) + { + _propDesc = TypeDescriptor.GetProperties(_actionList)[_propertyItem.MemberName]; + } + return _propDesc; + } + } + + protected DesignerActionPropertyItem PropertyItem + { + get => _propertyItem; + } + + protected ITypeDescriptorContext TypeDescriptorContext + { + get + { + if (_typeDescriptorContext == null) + { + _typeDescriptorContext = new TypeDescriptorContext(ServiceProvider, PropertyDescriptor, _actionList); + } + return _typeDescriptorContext; + } + } + + protected object Value + { + get => _value; + } + + protected abstract void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex); + + protected abstract void OnValueChanged(); + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + protected void SetValue(object newValue) + { + if (_pushingValue || ActionPanel.DropDownActive) + { + return; + } + _pushingValue = true; + try + { + // Only push the change if the values are different + if (newValue != null) + { + Type valueType = newValue.GetType(); + // If it's not assignable, try to convert it + if (!PropertyDescriptor.PropertyType.IsAssignableFrom(valueType)) + { + if (PropertyDescriptor.Converter != null) + { + // If we can't convert it, show an error + if (!PropertyDescriptor.Converter.CanConvertFrom(_typeDescriptorContext, valueType)) + { + ActionPanel.ShowError(string.Format(SR.DesignerActionPanel_CouldNotConvertValue, newValue, _propDesc.PropertyType)); + return; + } + else + { + newValue = PropertyDescriptor.Converter.ConvertFrom(_typeDescriptorContext, CultureInfo.CurrentCulture, newValue); + } + } + } + } + if (!object.Equals(_value, newValue)) + { + PropertyDescriptor.SetValue(_actionList, newValue); + // Update the value we're caching + _value = PropertyDescriptor.GetValue(_actionList); + OnValueChanged(); + } + } + catch (Exception e) + { + if (e is TargetInvocationException) + { + e = e.InnerException; + } + ActionPanel.ShowError(string.Format(SR.DesignerActionPanel_ErrorSettingValue, newValue, PropertyDescriptor.Name, e.Message)); + } + finally + { + _pushingValue = false; + } + } + + internal sealed override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) + { + _actionList = actionList; + _propertyItem = (DesignerActionPropertyItem)actionItem; + _propDesc = null; + _typeDescriptorContext = null; + _value = PropertyDescriptor.GetValue(actionList); + OnPropertyTaskItemUpdated(toolTip, ref currentTabIndex); + _pushingValue = true; + try + { + OnValueChanged(); + } + finally + { + _pushingValue = false; + } + } + } + + private sealed class CheckBoxPropertyLine : PropertyLine + { + private CheckBox _checkBox; + + public CheckBoxPropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel): base(serviceProvider, actionPanel) + { + } + + protected override void AddControls(List controls) + { + _checkBox = new CheckBox + { + BackColor = Color.Transparent, + CheckAlign = Drawing.ContentAlignment.MiddleLeft + }; + _checkBox.TextAlign = Drawing.ContentAlignment.MiddleLeft; + _checkBox.UseMnemonic = false; + _checkBox.ForeColor = ActionPanel.LabelForeColor; + controls.Add(_checkBox); + } + + public sealed override void Focus() => _checkBox.Focus(); + + public override Size LayoutControls(int top, int width, bool measureOnly) + { + Size checkBoxPreferredSize = _checkBox.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)); + if (!measureOnly) + { + _checkBox.Location = new Point(LineLeftMargin, top + LineVerticalPadding / 2); + _checkBox.Size = checkBoxPreferredSize; + } + return checkBoxPreferredSize + new Size(LineLeftMargin + LineRightMargin, LineVerticalPadding); + } + + private void OnCheckBoxCheckedChanged(object sender, EventArgs e) + { + SetValue(_checkBox.Checked); + } + + protected override void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex) + { + _checkBox.Text = StripAmpersands(PropertyItem.DisplayName); + _checkBox.AccessibleDescription = PropertyItem.Description; + _checkBox.TabIndex = currentTabIndex++; + + toolTip.SetToolTip(_checkBox, PropertyItem.Description); + } + + protected override void OnValueChanged() + { + _checkBox.Checked = (bool)Value; + } + } + + private class TextBoxPropertyLine : PropertyLine + { + private TextBox _textBox; + private EditorLabel _readOnlyTextBoxLabel; + private Control _editControl; + private Label _label; + private int _editXPos; + private bool _textBoxDirty; + private Point _editRegionLocation; + private Point _editRegionRelativeLocation; + private Size _editRegionSize; + + public TextBoxPropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + protected Control EditControl + { + get => _editControl; + } + + protected Point EditRegionLocation + { + get => _editRegionLocation; + } + + protected Point EditRegionRelativeLocation + { + get => _editRegionRelativeLocation; + } + + protected Size EditRegionSize + { + get => _editRegionSize; + } + + protected override void AddControls(List controls) + { + _label = new Label + { + BackColor = Color.Transparent, + ForeColor = ActionPanel.LabelForeColor, + TextAlign = Drawing.ContentAlignment.MiddleLeft, + UseMnemonic = false + }; + _readOnlyTextBoxLabel = new EditorLabel + { + BackColor = Color.Transparent, + ForeColor = SystemColors.WindowText, + TabStop = true, + TextAlign = Drawing.ContentAlignment.TopLeft, + UseMnemonic = false, + Visible = false + }; + _readOnlyTextBoxLabel.MouseClick += new MouseEventHandler(OnReadOnlyTextBoxLabelClick); + _readOnlyTextBoxLabel.KeyDown += new KeyEventHandler(OnReadOnlyTextBoxLabelKeyDown); + + _textBox = new TextBox + { + BorderStyle = BorderStyle.None, + TextAlign = System.Windows.Forms.HorizontalAlignment.Left, + Visible = false + }; + _textBox.KeyDown += new KeyEventHandler(OnTextBoxKeyDown); + + controls.Add(_readOnlyTextBoxLabel); + controls.Add(_textBox); + controls.Add(_label); + } + + public sealed override void Focus() + { + _editControl.Focus(); + } + + internal int GetEditRegionXPos() + { + if (string.IsNullOrEmpty(_label.Text)) + { + return LineLeftMargin; + } + return LineLeftMargin + _label.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)).Width + TextBoxLineCenterMargin; + } + + protected virtual int GetTextBoxLeftPadding(int textBoxHeight) => TextBoxLineInnerPadding; + + protected virtual int GetTextBoxRightPadding(int textBoxHeight) => TextBoxLineInnerPadding; + + public override Size LayoutControls(int top, int width, bool measureOnly) + { + // Figure out our minimum width, Compare to proposed width, If we are smaller, widen the textbox to fit the line based on the bonus + int textBoxPreferredHeight = _textBox.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)).Height; + textBoxPreferredHeight += TextBoxHeightFixup; + int height = textBoxPreferredHeight + LineVerticalPadding + TextBoxLineInnerPadding * 2 + 2; // 2 == border size + + int editRegionXPos = Math.Max(_editXPos, GetEditRegionXPos()); + int minimumWidth = editRegionXPos + EditInputWidth + LineRightMargin; + width = Math.Max(width, minimumWidth); + int textBoxWidthBonus = width - minimumWidth; + + if (!measureOnly) + { + _editRegionLocation = new Point(editRegionXPos, top + TextBoxTopPadding); + _editRegionRelativeLocation = new Point(editRegionXPos, TextBoxTopPadding); + _editRegionSize = new Size(EditInputWidth + textBoxWidthBonus, textBoxPreferredHeight + TextBoxLineInnerPadding * 2); + + _label.Location = new Point(LineLeftMargin, top); + int labelPreferredWidth = _label.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)).Width; + _label.Size = new Size(labelPreferredWidth, height); + int specialPadding = 0; + if (_editControl is TextBox) + { + specialPadding = 2; + } + _editControl.Location = new Point(_editRegionLocation.X + GetTextBoxLeftPadding(textBoxPreferredHeight) + 1 + specialPadding, _editRegionLocation.Y + TextBoxLineInnerPadding + 1); + _editControl.Width = _editRegionSize.Width - GetTextBoxRightPadding(textBoxPreferredHeight) - GetTextBoxLeftPadding(textBoxPreferredHeight) - specialPadding; + _editControl.Height = _editRegionSize.Height - TextBoxLineInnerPadding * 2 - 1; + } + return new Size(width, height); + } + + protected virtual bool IsReadOnly() => IsReadOnlyProperty(PropertyDescriptor); + + protected override void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex) + { + _label.Text = StripAmpersands(PropertyItem.DisplayName); + _label.TabIndex = currentTabIndex++; + toolTip.SetToolTip(_label, PropertyItem.Description); + _textBoxDirty = false; + + if (IsReadOnly()) + { + _readOnlyTextBoxLabel.Visible = true; + _textBox.Visible = false; + // REVIEW: Setting Visible to false doesn't seem to work, so position far away + _textBox.Location = new Point(int.MaxValue, int.MaxValue); + _editControl = _readOnlyTextBoxLabel; + } + else + { + _readOnlyTextBoxLabel.Visible = false; + // REVIEW: Setting Visible to false doesn't seem to work, so position far away + _readOnlyTextBoxLabel.Location = new Point(int.MaxValue, int.MaxValue); + _textBox.Visible = true; + _editControl = _textBox; + } + _editControl.AccessibleDescription = PropertyItem.Description; + _editControl.AccessibleName = StripAmpersands(PropertyItem.DisplayName); + _editControl.TabIndex = currentTabIndex++; + _editControl.BringToFront(); + } + + protected virtual void OnReadOnlyTextBoxLabelClick(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + Focus(); + } + } + + private void OnReadOnlyTextBoxLabelEnter(object sender, EventArgs e) + { + _readOnlyTextBoxLabel.ForeColor = SystemColors.HighlightText; + _readOnlyTextBoxLabel.BackColor = SystemColors.Highlight; + } + + private void OnReadOnlyTextBoxLabelLeave(object sender, EventArgs e) + { + _readOnlyTextBoxLabel.ForeColor = SystemColors.WindowText; + _readOnlyTextBoxLabel.BackColor = SystemColors.Window; + } + + protected TypeConverter.StandardValuesCollection GetStandardValues() + { + TypeConverter converter = PropertyDescriptor.Converter; + if (converter != null && + converter.GetStandardValuesSupported(TypeDescriptorContext)) + { + return converter.GetStandardValues(TypeDescriptorContext); + } + return null; + } + + private void OnEditControlKeyDown(KeyEventArgs e) + { + if (e.KeyCode == Keys.Down) + { + e.Handled = true; + // Try to find the existing value and then pick the one after it + TypeConverter.StandardValuesCollection standardValues = GetStandardValues(); + if (standardValues != null) + { + for (int i = 0; i < standardValues.Count; i++) + { + if (object.Equals(Value, standardValues[i])) + { + if (i < standardValues.Count - 1) + { + SetValue(standardValues[i + 1]); + } + return; + } + } + // Previous value wasn't found, select the first one by default + if (standardValues.Count > 0) + { + SetValue(standardValues[0]); + } + } + return; + } + + if (e.KeyCode == Keys.Up) + { + e.Handled = true; + // Try to find the existing value and then pick the one before it + TypeConverter.StandardValuesCollection standardValues = GetStandardValues(); + if (standardValues != null) + { + for (int i = 0; i < standardValues.Count; i++) + { + if (object.Equals(Value, standardValues[i])) + { + if (i > 0) + { + SetValue(standardValues[i - 1]); + } + return; + } + } + // Previous value wasn't found, select the first one by default + if (standardValues.Count > 0) + { + SetValue(standardValues[standardValues.Count - 1]); + } + } + return; + } + } + + private void OnReadOnlyTextBoxLabelKeyDown(object sender, KeyEventArgs e) + { + // Delegate the rest of the processing to a common helper + OnEditControlKeyDown(e); + } + + private void OnTextBoxKeyDown(object sender, KeyEventArgs e) + { + if (ActionPanel.DropDownActive) + { + return; + } + + if (e.KeyCode == Keys.Enter) + { + UpdateValue(); + e.Handled = true; + return; + } + // Delegate the rest of the processing to a common helper + OnEditControlKeyDown(e); + } + + private void OnTextBoxLostFocus(object sender, EventArgs e) + { + if (ActionPanel.DropDownActive) + { + return; + } + UpdateValue(); + } + + private void OnTextBoxTextChanged(object sender, EventArgs e) => _textBoxDirty = true; + + protected override void OnValueChanged() => _editControl.Text = PropertyDescriptor.Converter.ConvertToString(TypeDescriptorContext, Value); + + public override void PaintLine(Graphics g, int lineWidth, int lineHeight) + { + Rectangle editRect = new Rectangle(EditRegionRelativeLocation, EditRegionSize); + g.FillRectangle(SystemBrushes.Window, editRect); + g.DrawRectangle(SystemPens.ControlDark, editRect); + } + + internal void SetEditRegionXPos(int xPos) + { + // Ignore the x-position if we have no text. This allows the textbox to span the entire width of the panel. + if (!string.IsNullOrEmpty(_label.Text)) + { + _editXPos = xPos; + } + else + { + _editXPos = LineLeftMargin; + } + } + + private void UpdateValue() + { + if (_textBoxDirty) + { + SetValue(_editControl.Text); + _textBoxDirty = false; + } + } + + /// + /// Custom label that provides accurate accessibility information and focus abilities. + /// + private sealed class EditorLabel : Label + { + public EditorLabel() + { + SetStyle(ControlStyles.Selectable, true); + } + + protected override AccessibleObject CreateAccessibilityInstance() => new EditorLabelAccessibleObject(this); + + protected override void OnGotFocus(EventArgs e) + { + base.OnGotFocus(e); + // Since we are not a standard focusable control, we have to raise our own accessibility events. + // objectID = OBJID_WINDOW, childID = CHILDID_SELF - 1 (the -1 is because WinForms always adds 1 to the value) (these consts are defined in winuser.h) + AccessibilityNotifyClients(AccessibleEvents.Focus, 0, -1); + } + + protected override bool IsInputKey(Keys keyData) + { + if (keyData == Keys.Down || + keyData == Keys.Up) + { + return true; + } + return base.IsInputKey(keyData); + } + + private sealed class EditorLabelAccessibleObject : ControlAccessibleObject + { + public EditorLabelAccessibleObject(EditorLabel owner) : base(owner) + { + } + + public override string Value + { + get => Owner.Text; + } + } + } + } + + private sealed class EditorPropertyLine : TextBoxPropertyLine, IWindowsFormsEditorService, IServiceProvider + { + private EditorButton _button; + private UITypeEditor _editor; + private bool _hasSwatch; + private Image _swatch; + private FlyoutDialog _dropDownHolder; + private bool _ignoreNextSelectChange = false; + private bool _ignoreDropDownValue; + + public EditorPropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private void ActivateDropDown() + { + if (_editor != null) + { + try + { + object newValue = _editor.EditValue(TypeDescriptorContext, this, Value); + SetValue(newValue); + } + catch (Exception ex) + { + ActionPanel.ShowError(string.Format(SR.DesignerActionPanel_ErrorActivatingDropDown, ex.Message)); + } + } + else + { + ListBox listBox = new ListBox + { + BorderStyle = BorderStyle.None, + IntegralHeight = false, + Font = ActionPanel.Font + }; + listBox.KeyDown += new KeyEventHandler(OnListBoxKeyDown); + TypeConverter.StandardValuesCollection standardValues = GetStandardValues(); + if (standardValues != null) + { + foreach (object o in standardValues) + { + string newItem = PropertyDescriptor.Converter.ConvertToString(TypeDescriptorContext, CultureInfo.CurrentCulture, o); + listBox.Items.Add(newItem); + + if ((o != null) && o.Equals(Value)) + { + listBox.SelectedItem = newItem; + } + } + } + + // All measurement code borrowed from WinForms PropertyGridView.cs + int maxWidth = 0; + // The listbox draws with GDI, not GDI+. So, we use a normal DC here. + IntPtr hdc = UnsafeNativeMethods.GetDC(new HandleRef(listBox, listBox.Handle)); + IntPtr hFont = listBox.Font.ToHfont(); + NativeMethods.CommonHandles.GdiHandleCollector.Add(); + NativeMethods.TEXTMETRIC tm = new NativeMethods.TEXTMETRIC(); + try + { + hFont = SafeNativeMethods.SelectObject(new HandleRef(listBox, hdc), new HandleRef(listBox.Font, hFont)); + if (listBox.Items.Count > 0) + { + NativeMethods.SIZE textSize = new NativeMethods.SIZE(); + foreach (string s in listBox.Items) + { + SafeNativeMethods.GetTextExtentPoint32(new HandleRef(listBox, hdc), s, s.Length, textSize); + maxWidth = Math.Max((int)textSize.cx, maxWidth); + } + } + SafeNativeMethods.GetTextMetrics(new HandleRef(listBox, hdc), ref tm); + // border + padding + scrollbar + maxWidth += 2 + tm.tmMaxCharWidth + SystemInformation.VerticalScrollBarWidth; + hFont = SafeNativeMethods.SelectObject(new HandleRef(listBox, hdc), new HandleRef(listBox.Font, hFont)); + } + finally + { + SafeNativeMethods.DeleteObject(new HandleRef(listBox.Font, hFont)); + UnsafeNativeMethods.ReleaseDC(new HandleRef(listBox, listBox.Handle), new HandleRef(listBox, hdc)); + } + + listBox.Height = Math.Max(tm.tmHeight + 2, Math.Min(ListBoxMaximumHeight, listBox.PreferredHeight)); + listBox.Width = Math.Max(maxWidth, EditRegionSize.Width); + _ignoreDropDownValue = false; + try + { + ShowDropDown(listBox, SystemColors.ControlDark); + } + finally + { + listBox.KeyDown -= new KeyEventHandler(OnListBoxKeyDown); + } + + if (!_ignoreDropDownValue) + { + if (listBox.SelectedItem != null) + { + SetValue(listBox.SelectedItem); + } + } + } + } + + protected override void AddControls(List controls) + { + base.AddControls(controls); + _button = new EditorButton(); + controls.Add(_button); + } + + private void CloseDropDown() + { + if (_dropDownHolder != null) + { + _dropDownHolder.Visible = false; + } + } + + protected override int GetTextBoxLeftPadding(int textBoxHeight) + { + if (_hasSwatch) + { + return base.GetTextBoxLeftPadding(textBoxHeight) + textBoxHeight + 2 * EditorLineSwatchPadding; + } + else + { + return base.GetTextBoxLeftPadding(textBoxHeight); + } + } + + protected override int GetTextBoxRightPadding(int textBoxHeight) => base.GetTextBoxRightPadding(textBoxHeight) + textBoxHeight + 2 * EditorLineButtonPadding; + + protected override bool IsReadOnly() + { + if (base.IsReadOnly()) + { + return true; + } + + // If we can't convert from string, we are readonly because we can't convert the user's input + bool converterReadOnly = !PropertyDescriptor.Converter.CanConvertFrom(TypeDescriptorContext, typeof(string)); + // If standard values are supported and are exclusive, we are readonly + bool standardValuesExclusive = + PropertyDescriptor.Converter.GetStandardValuesSupported(TypeDescriptorContext) && + PropertyDescriptor.Converter.GetStandardValuesExclusive(TypeDescriptorContext); + return converterReadOnly || standardValuesExclusive; + } + + public override Size LayoutControls(int top, int width, bool measureOnly) + { + Size size = base.LayoutControls(top, width, measureOnly); + if (!measureOnly) + { + int buttonHeight = EditRegionSize.Height - EditorLineButtonPadding * 2 - 1; + _button.Location = new Point(EditRegionLocation.X + EditRegionSize.Width - buttonHeight - EditorLineButtonPadding, EditRegionLocation.Y + EditorLineButtonPadding + 1); + _button.Size = new Size(buttonHeight, buttonHeight); + } + return size; + } + + private void OnButtonClick(object sender, EventArgs e) + { + ActivateDropDown(); + } + + private void OnButtonGotFocus(object sender, EventArgs e) + { + if (!_button.Ellipsis) + { + Focus(); + } + } + + private void OnListBoxKeyDown(object sender, KeyEventArgs e) + { + // Always respect the enter key and F4 + if (e.KeyData == Keys.Enter) + { + _ignoreNextSelectChange = false; + CloseDropDown(); + e.Handled = true; + } + else + { + // Ignore selected index change events when the user is navigating via the keyboard + _ignoreNextSelectChange = true; + } + } + + private void OnListBoxSelectedIndexChanged(object sender, EventArgs e) + { + // If we're ignoring this selected index change, do nothing + if (_ignoreNextSelectChange) + { + _ignoreNextSelectChange = false; + } + else + { + CloseDropDown(); + } + } + + protected override void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex) + { + _editor = (UITypeEditor)PropertyDescriptor.GetEditor(typeof(UITypeEditor)); + base.OnPropertyTaskItemUpdated(toolTip, ref currentTabIndex); + if (_editor != null) + { + _button.Ellipsis = (_editor.GetEditStyle(TypeDescriptorContext) == UITypeEditorEditStyle.Modal); + _hasSwatch = _editor.GetPaintValueSupported(TypeDescriptorContext); + } + else + { + _button.Ellipsis = false; + } + + if (_button.Ellipsis) + { + EditControl.AccessibleRole = (IsReadOnly() ? AccessibleRole.StaticText : AccessibleRole.Text); + } + else + { + EditControl.AccessibleRole = (IsReadOnly() ? AccessibleRole.DropList : AccessibleRole.ComboBox); + } + + _button.TabStop = _button.Ellipsis; + _button.TabIndex = currentTabIndex++; + _button.AccessibleRole = (_button.Ellipsis ? AccessibleRole.PushButton : AccessibleRole.ButtonDropDown); + _button.AccessibleDescription = EditControl.AccessibleDescription; + _button.AccessibleName = EditControl.AccessibleName; + } + + protected override void OnReadOnlyTextBoxLabelClick(object sender, MouseEventArgs e) + { + base.OnReadOnlyTextBoxLabelClick(sender, e); + if (e.Button == MouseButtons.Left) + { + if (ActionPanel.DropDownActive) + { + _ignoreDropDownValue = true; + CloseDropDown(); + } + else + { + ActivateDropDown(); + } + } + } + + protected override void OnValueChanged() + { + base.OnValueChanged(); + _swatch = null; + if (_hasSwatch) + { + ActionPanel.Invalidate(new Rectangle(EditRegionLocation, EditRegionSize), false); + } + } + + public override void PaintLine(Graphics g, int lineWidth, int lineHeight) + { + base.PaintLine(g, lineWidth, lineHeight); + if (_hasSwatch) + { + if (_swatch == null) + { + int width = EditRegionSize.Height - EditorLineSwatchPadding * 2; + int height = width - 1; + _swatch = new Bitmap(width, height); + Rectangle rect = new Rectangle(1, 1, width - 2, height - 2); + using (Graphics swatchGraphics = Graphics.FromImage(_swatch)) + { + _editor.PaintValue(Value, swatchGraphics, rect); + swatchGraphics.DrawRectangle(SystemPens.ControlDark, new Rectangle(0, 0, width - 1, height - 1)); + } + } + g.DrawImage(_swatch, new Point(EditRegionRelativeLocation.X + 2, EditorLineSwatchPadding + 5)); + } + } + + protected internal override bool ProcessDialogKey(Keys keyData) + { + // Do this here rather than in OnKeyDown because if hierarchy is properly set, VS is going to eat the F4 in PreProcessMessage, preventing it from ever getting to an OnKeyDown on this control. Doing it here also allow to not hook up to multiple events for each button. + if (!_button.Focused && !_button.Ellipsis) + { + if ((keyData == (Keys.Alt | Keys.Down)) || (keyData == (Keys.Alt | Keys.Up)) || (keyData == Keys.F4)) + { + if (!ActionPanel.DropDownActive) + { + ActivateDropDown(); + } + else + CloseDropDown(); + return true; + } + // Not passing Alt key event to base class to prevent closing 'Combobox Tasks window' + else if ((keyData & Keys.Alt) == Keys.Alt) + return true; + } + return base.ProcessDialogKey(keyData); + } + + private void ShowDropDown(Control hostedControl, Color borderColor) + { + hostedControl.Width = Math.Max(hostedControl.Width, EditRegionSize.Width - 2); + _dropDownHolder = new DropDownHolder(hostedControl, ActionPanel, borderColor, ActionPanel.Font, this); + if (ActionPanel.RightToLeft != RightToLeft.Yes) + { + Rectangle editorBounds = new Rectangle(Point.Empty, EditRegionSize); + Size dropDownSize = _dropDownHolder.Size; + Point editorLocation = ActionPanel.PointToScreen(EditRegionLocation); + Rectangle rectScreen = Screen.FromRectangle(ActionPanel.RectangleToScreen(editorBounds)).WorkingArea; + dropDownSize.Width = Math.Max(editorBounds.Width + 1, dropDownSize.Width); + editorLocation.X = Math.Min(rectScreen.Right - dropDownSize.Width, // min = right screen edge clip + Math.Max(rectScreen.X, editorLocation.X + editorBounds.Right - dropDownSize.Width)); // max = left screen edge clip + editorLocation.Y += editorBounds.Y; + if (rectScreen.Bottom < (dropDownSize.Height + editorLocation.Y + editorBounds.Height)) + { + editorLocation.Y -= dropDownSize.Height + 1; + } + else + { + editorLocation.Y += editorBounds.Height; + } + _dropDownHolder.Location = editorLocation; + } + else + { + _dropDownHolder.RightToLeft = ActionPanel.RightToLeft; + Rectangle editorBounds = new Rectangle(Point.Empty, EditRegionSize); + Size dropDownSize = _dropDownHolder.Size; + Point editorLocation = ActionPanel.PointToScreen(EditRegionLocation); + Rectangle rectScreen = Screen.FromRectangle(ActionPanel.RectangleToScreen(editorBounds)).WorkingArea; + dropDownSize.Width = Math.Max(editorBounds.Width + 1, dropDownSize.Width); + editorLocation.X = Math.Min(rectScreen.Right - dropDownSize.Width, // min = right screen edge clip + Math.Max(rectScreen.X, editorLocation.X - editorBounds.Width)); // max = left screen edge clip + editorLocation.Y += editorBounds.Y; + if (rectScreen.Bottom < (dropDownSize.Height + editorLocation.Y + editorBounds.Height)) + { + editorLocation.Y -= dropDownSize.Height + 1; + } + else + { + editorLocation.Y += editorBounds.Height; + } + _dropDownHolder.Location = editorLocation; + } + + ActionPanel.InMethodInvoke = true; + ActionPanel.SetDropDownActive(true); + try + { + _dropDownHolder.ShowDropDown(_button); + } + finally + { + _button.ResetMouseStates(); + ActionPanel.SetDropDownActive(false); + ActionPanel.InMethodInvoke = false; + } + } + + #region IWindowsFormsEditorService implementation + void IWindowsFormsEditorService.CloseDropDown() + { + CloseDropDown(); + } + + void IWindowsFormsEditorService.DropDownControl(Control control) + { + ShowDropDown(control, ActionPanel.BorderColor); + } + + DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog) + { + IUIService uiService = (IUIService)ServiceProvider.GetService(typeof(IUIService)); + if (uiService != null) + { + return uiService.ShowDialog(dialog); + } + return dialog.ShowDialog(); + } + #endregion + + #region IServiceProvider implementation + object IServiceProvider.GetService(Type serviceType) + { + // Inject this class as the IWindowsFormsEditroService so drop-down custom editors can work + if (serviceType == typeof(IWindowsFormsEditorService)) + { + return this; + } + return ServiceProvider.GetService(serviceType); + } + #endregion + + private class DropDownHolder : FlyoutDialog + { + private readonly EditorPropertyLine _parent; + public DropDownHolder(Control hostedControl, Control parentControl, Color borderColor, Font font, EditorPropertyLine parent) : base(hostedControl, parentControl, borderColor, font) + { + _parent = parent; + _parent.ActionPanel.SetDropDownActive(true); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + _parent.ActionPanel.SetDropDownActive(false); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + if (keyData == Keys.Escape) + { + // Indicates that the selection was aborted so we should ignore the value + _parent._ignoreDropDownValue = true; + Visible = false; + return true; + } + + return base.ProcessDialogKey(keyData); + } + } + + internal class FlyoutDialog : Form + { + private readonly Control _hostedControl; + private readonly Control _parentControl; + + public FlyoutDialog(Control hostedControl, Control parentControl, Color borderColor, Font font) + { + _hostedControl = hostedControl; + _parentControl = parentControl; + BackColor = SystemColors.Window; + ControlBox = false; + Font = font; + FormBorderStyle = FormBorderStyle.None; + MinimizeBox = false; + MaximizeBox = false; + ShowInTaskbar = false; + StartPosition = FormStartPosition.Manual; + Text = string.Empty; + SuspendLayout(); + try + { + Controls.Add(hostedControl); + int width = Math.Max(_hostedControl.Width, SystemInformation.MinimumWindowSize.Width); + int height = Math.Max(_hostedControl.Height, SystemInformation.MinimizedWindowSize.Height); + if (!borderColor.IsEmpty) + { + DockPadding.All = 1; + BackColor = borderColor; + width += 2; + height += 4; + } + _hostedControl.Dock = DockStyle.Fill; + + Width = width; + Height = height; + } + finally + { + ResumeLayout(); + } + } + + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.ExStyle |= NativeMethods.WS_EX_TOOLWINDOW; + cp.Style |= NativeMethods.WS_POPUP | NativeMethods.WS_BORDER; + cp.ClassStyle |= NativeMethods.CS_SAVEBITS; + if (_parentControl != null) + { + if (!_parentControl.IsDisposed) + { + cp.Parent = _parentControl.Handle; + } + } + return cp; + } + } + + public virtual void FocusComponent() + { + if (_hostedControl != null && Visible) + { + _hostedControl.Focus(); + } + } + // Lifted directly from PropertyGridView.DropDownHolder. Less destructive than using ShowDialog(). + public void DoModalLoop() + { + while (Visible) + { + Application.DoEvents(); + UnsafeNativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 250, NativeMethods.QS_ALLINPUT, NativeMethods.MWMO_INPUTAVAILABLE); + } + } + + /// + /// General purpose method, based on Control.Contains()... Determines whether a given window (specified using native window handle) is a descendant of this control. This catches both contained descendants and 'owned' windows such as modal dialogs. Using window handles rather than Control objects allows it to catch un-managed windows as well. + /// + private bool OwnsWindow(IntPtr hWnd) + { + while (hWnd != IntPtr.Zero) + { + hWnd = UnsafeNativeMethods.GetWindowLong(new HandleRef(null, hWnd), NativeMethods.GWL_HWNDPARENT); + if (hWnd == IntPtr.Zero) + { + return false; + } + if (hWnd == Handle) + { + return true; + } + } + return false; + } + + protected override bool ProcessDialogKey(Keys keyData) + { + if ((keyData == (Keys.Alt | Keys.Down)) || + (keyData == (Keys.Alt | Keys.Up)) || + (keyData == Keys.F4)) + { + // Any of these keys indicates the selection is accepted + Visible = false; + return true; + } + return base.ProcessDialogKey(keyData); + } + + public void ShowDropDown(Control parent) + { + try + { + UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT, new HandleRef(parent, parent.Handle)); + // Lifted directly from Form.ShowDialog()... + IntPtr hWndCapture = UnsafeNativeMethods.GetCapture(); + if (hWndCapture != IntPtr.Zero) + { + UnsafeNativeMethods.SendMessage(new HandleRef(null, hWndCapture), Interop.WindowMessages.WM_CANCELMODE, 0, 0); + SafeNativeMethods.ReleaseCapture(); + } + Visible = true; // NOTE: Do this AFTER creating handle and setting parent + FocusComponent(); + DoModalLoop(); + } + finally + { + + UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT, new HandleRef(null, IntPtr.Zero)); + // sometimes activation goes to LALA land - if our parent control is still around, remind it to take focus. + if (parent != null && parent.Visible) + { + parent.Focus(); + } + } + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == Interop.WindowMessages.WM_ACTIVATE) + { + if (Visible && NativeMethods.Util.LOWORD(unchecked((int)(long)m.WParam)) == NativeMethods.WA_INACTIVE) + { + if (!OwnsWindow((IntPtr)m.LParam)) + { + Visible = false; + if (m.LParam == IntPtr.Zero) + { //we 're switching process, also dismiss the parent + Control toplevel = _parentControl.TopLevelControl; + if (toplevel is ToolStripDropDown dropDown) + { + // if it's a toolstrip dropdown let it know that we have a specific close reason. + dropDown.Close(); + } + else if (toplevel != null) + { + toplevel.Visible = false; + } + } + return; + } + } + } + base.WndProc(ref m); + } + } + + #region Interop definitions + private static class NativeMethods + { + public const int WA_INACTIVE = 0; + public const int WA_ACTIVE = 1; + public const int WS_EX_TOOLWINDOW = 0x00000080; + public const int WS_POPUP = unchecked((int)0x80000000); + public const int WS_BORDER = 0x00800000; + public const int GWL_HWNDPARENT = (-8); + public const int QS_KEY = 0x0001; + public const int QS_MOUSEMOVE = 0x0002; + public const int QS_MOUSEBUTTON = 0x0004; + public const int QS_POSTMESSAGE = 0x0008; + public const int QS_TIMER = 0x0010; + public const int QS_PAINT = 0x0020; + public const int QS_SENDMESSAGE = 0x0040; + public const int QS_HOTKEY = 0x0080; + public const int QS_ALLPOSTMESSAGE = 0x0100; + public const int QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON; + public const int QS_INPUT = QS_MOUSE | QS_KEY; + public const int QS_ALLEVENTS = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY; + public const int QS_ALLINPUT = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE; + public const int CS_SAVEBITS = 0x0800; + + public const int MWMO_INPUTAVAILABLE = 0x0004; // don't use MWMO_WAITALL, see ddb#176342 + + internal static class Util + { + public static int LOWORD(int n) => n & 0xffff; + } + + public static class CommonHandles + { + public static HandleCollector GdiHandleCollector = new HandleCollector("GDI", 500); + public static HandleCollector HdcHandleCollector = new HandleCollector("HDC", 2); + } + + [StructLayout(LayoutKind.Sequential)] + public class SIZE + { + public int cx = 0; + public int cy = 0; + public SIZE() + { + } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TEXTMETRIC + { + public int tmHeight; + public int tmAscent; + public int tmDescent; + public int tmInternalLeading; + public int tmExternalLeading; + public int tmAveCharWidth; + public int tmMaxCharWidth; + public int tmWeight; + public int tmOverhang; + public int tmDigitizedAspectX; + public int tmDigitizedAspectY; + public char tmFirstChar; + public char tmLastChar; + public char tmDefaultChar; + public char tmBreakChar; + public byte tmItalic; + public byte tmUnderlined; + public byte tmStruckOut; + public byte tmPitchAndFamily; + public byte tmCharSet; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct TEXTMETRICA + { + public int tmHeight; + public int tmAscent; + public int tmDescent; + public int tmInternalLeading; + public int tmExternalLeading; + public int tmAveCharWidth; + public int tmMaxCharWidth; + public int tmWeight; + public int tmOverhang; + public int tmDigitizedAspectX; + public int tmDigitizedAspectY; + public byte tmFirstChar; + public byte tmLastChar; + public byte tmDefaultChar; + public byte tmBreakChar; + public byte tmItalic; + public byte tmUnderlined; + public byte tmStruckOut; + public byte tmPitchAndFamily; + public byte tmCharSet; + } + } + + private static class SafeNativeMethods + { + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "DeleteObject", CharSet = System.Runtime.InteropServices.CharSet.Auto)] + private static extern bool IntDeleteObject(HandleRef hObject); + public static bool DeleteObject(HandleRef hObject) + { + NativeMethods.CommonHandles.GdiHandleCollector.Remove(); + return IntDeleteObject(hObject); + } + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public static extern bool ReleaseCapture(); + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern IntPtr SelectObject(HandleRef hDC, HandleRef hObject); + + [DllImport(ExternDll.Gdi32, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetTextExtentPoint32(HandleRef hDC, string str, int len, [In, Out] NativeMethods.SIZE size); + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] + public static extern int GetTextMetricsW(HandleRef hDC, [In, Out] ref NativeMethods.TEXTMETRIC lptm); + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi)] + public static extern int GetTextMetricsA(HandleRef hDC, [In, Out] ref NativeMethods.TEXTMETRICA lptm); + + public static int GetTextMetrics(HandleRef hDC, ref NativeMethods.TEXTMETRIC lptm) + { + if (Marshal.SystemDefaultCharSize == 1) + { + // ANSI + NativeMethods.TEXTMETRICA lptmA = new NativeMethods.TEXTMETRICA(); + int retVal = SafeNativeMethods.GetTextMetricsA(hDC, ref lptmA); + lptm.tmHeight = lptmA.tmHeight; + lptm.tmAscent = lptmA.tmAscent; + lptm.tmDescent = lptmA.tmDescent; + lptm.tmInternalLeading = lptmA.tmInternalLeading; + lptm.tmExternalLeading = lptmA.tmExternalLeading; + lptm.tmAveCharWidth = lptmA.tmAveCharWidth; + lptm.tmMaxCharWidth = lptmA.tmMaxCharWidth; + lptm.tmWeight = lptmA.tmWeight; + lptm.tmOverhang = lptmA.tmOverhang; + lptm.tmDigitizedAspectX = lptmA.tmDigitizedAspectX; + lptm.tmDigitizedAspectY = lptmA.tmDigitizedAspectY; + lptm.tmFirstChar = (char)lptmA.tmFirstChar; + lptm.tmLastChar = (char)lptmA.tmLastChar; + lptm.tmDefaultChar = (char)lptmA.tmDefaultChar; + lptm.tmBreakChar = (char)lptmA.tmBreakChar; + lptm.tmItalic = lptmA.tmItalic; + lptm.tmUnderlined = lptmA.tmUnderlined; + lptm.tmStruckOut = lptmA.tmStruckOut; + lptm.tmPitchAndFamily = lptmA.tmPitchAndFamily; + lptm.tmCharSet = lptmA.tmCharSet; + return retVal; + } + else + { + // Unicode + return SafeNativeMethods.GetTextMetricsW(hDC, ref lptm); + } + } + } + + private static class UnsafeNativeMethods + { + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")] + public static extern IntPtr GetWindowLong(HandleRef hWnd, int nIndex); + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")] + public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLong); + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public static extern int MsgWaitForMultipleObjectsEx(int nCount, IntPtr pHandles, int dwMilliseconds, int dwWakeMask, int dwFlags); + + [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam); + + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public static extern IntPtr GetCapture(); + + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "GetDC", CharSet = CharSet.Auto)] + private static extern IntPtr IntGetDC(HandleRef hWnd); + public static IntPtr GetDC(HandleRef hWnd) + { + NativeMethods.CommonHandles.HdcHandleCollector.Add(); + return IntGetDC(hWnd); + } + + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "ReleaseDC", CharSet = CharSet.Auto)] + private static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC); + public static int ReleaseDC(HandleRef hWnd, HandleRef hDC) + { + NativeMethods.CommonHandles.HdcHandleCollector.Remove(); + return IntReleaseDC(hWnd, hDC); + } + } + #endregion + + // Class that renders either the ellipsis or dropdown button + internal sealed class EditorButton : Button + { + private bool _mouseOver; + private bool _mouseDown; + private bool _ellipsis; + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + + if (e.Button == MouseButtons.Left) + { + _mouseDown = true; + } + } + + protected override void OnMouseEnter(EventArgs e) + { + base.OnMouseEnter(e); + _mouseOver = true; + } + + protected override void OnMouseLeave(EventArgs e) + { + base.OnMouseLeave(e); + _mouseOver = false; + } + + protected override void OnMouseUp(MouseEventArgs e) + { + base.OnMouseUp(e); + + if (e.Button == MouseButtons.Left) + { + _mouseDown = false; + } + } + + public bool Ellipsis + { + get => _ellipsis; + set => _ellipsis = value; + } + + protected override void OnPaint(PaintEventArgs e) + { + Graphics g = e.Graphics; + if (_ellipsis) + { + PushButtonState buttonState = PushButtonState.Normal; + if (_mouseDown) + { + buttonState = PushButtonState.Pressed; + } + else if (_mouseOver) + { + buttonState = PushButtonState.Hot; + } + ButtonRenderer.DrawButton(g, new Rectangle(-1, -1, Width + 2, Height + 2), "…", Font, Focused, buttonState); + } + else + { + if (ComboBoxRenderer.IsSupported) + { + ComboBoxState state = ComboBoxState.Normal; + if (Enabled) + { + if (_mouseDown) + { + state = ComboBoxState.Pressed; + } + else if (_mouseOver) + { + state = ComboBoxState.Hot; + } + } + else + { + state = ComboBoxState.Disabled; + } + ComboBoxRenderer.DrawDropDownButton(g, new Rectangle(0, 0, Width, Height), state); + } + else + { + PushButtonState buttonState = PushButtonState.Normal; + if (Enabled) + { + if (_mouseDown) + { + buttonState = PushButtonState.Pressed; + } + else if (_mouseOver) + { + buttonState = PushButtonState.Hot; + } + } + else + { + buttonState = PushButtonState.Disabled; + } + + ButtonRenderer.DrawButton(g, new Rectangle(-1, -1, Width + 2, Height + 2), string.Empty, Font, Focused, buttonState); + // Draw the arrow icon + try + { + Icon icon = new Icon(typeof(DesignerActionPanel), "Arrow.ico"); + try + { + Bitmap arrowBitmap = icon.ToBitmap(); + // Make sure we draw properly under high contrast by re-mapping the arrow color to the WindowText color + ImageAttributes attrs = new ImageAttributes(); + try + { + ColorMap cm = new ColorMap + { + OldColor = Color.Black, + NewColor = SystemColors.WindowText + }; + attrs.SetRemapTable(new ColorMap[] { cm }, ColorAdjustType.Bitmap); + int imageWidth = arrowBitmap.Width; + int imageHeight = arrowBitmap.Height; + g.DrawImage(arrowBitmap, new Rectangle((Width - imageWidth + 1) / 2, (Height - imageHeight + 1) / 2, imageWidth, imageHeight), + 0, 0, imageWidth, imageWidth, GraphicsUnit.Pixel, attrs, null, IntPtr.Zero); + } + finally + { + if (attrs != null) + { + attrs.Dispose(); + } + } + } + finally + { + if (icon != null) + { + icon.Dispose(); + } + } + } + catch + { + } + } + if (Focused) + { + ControlPaint.DrawFocusRectangle(g, new Rectangle(2, 2, Width - 5, Height - 5)); + } + } + } + + public void ResetMouseStates() + { + _mouseDown = false; + _mouseOver = false; + Invalidate(); + } + } + } + + private class TextLine : Line + { + private Label _label; + private DesignerActionTextItem _textItem; + + public TextLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + public sealed override string FocusId + { + get => string.Empty; + } + + protected override void AddControls(List controls) + { + _label = new Label + { + BackColor = Color.Transparent, + ForeColor = ActionPanel.LabelForeColor, + TextAlign = Drawing.ContentAlignment.MiddleLeft, + UseMnemonic = false + }; + controls.Add(_label); + } + + public sealed override void Focus() + { + Debug.Fail("Should never try to focus a TextLine"); + } + + public override Size LayoutControls(int top, int width, bool measureOnly) + { + Size labelSize = _label.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)); + if (!measureOnly) + { + _label.Location = new Point(LineLeftMargin, top + LineVerticalPadding / 2); + _label.Size = labelSize; + } + return labelSize + new Size(LineLeftMargin + LineRightMargin, LineVerticalPadding); + } + + private void OnParentControlFontChanged(object sender, EventArgs e) + { + if (_label != null && _label.Font != null) + { + _label.Font = GetFont(); + } + } + + protected virtual Font GetFont() + { + return ActionPanel.Font; + } + + internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) + { + _textItem = (DesignerActionTextItem)actionItem; + _label.Text = StripAmpersands(_textItem.DisplayName); + _label.Font = GetFont(); + _label.TabIndex = currentTabIndex++; + toolTip.SetToolTip(_label, _textItem.Description); + } + } + + private sealed class HeaderLine : TextLine + { + public HeaderLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : base(serviceProvider, actionPanel) + { + } + + protected override Font GetFont() => new Font(ActionPanel.Font, FontStyle.Bold); + } + + private sealed class SeparatorLine : Line + { + private readonly bool _isSubSeparator; + public SeparatorLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) : this(serviceProvider, actionPanel, false) + { + } + + public SeparatorLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel, bool isSubSeparator) : base(serviceProvider, actionPanel) + { + _isSubSeparator = isSubSeparator; + } + + public sealed override string FocusId + { + get => string.Empty; + } + + public bool IsSubSeparator => _isSubSeparator; + + protected override void AddControls(List controls) + { + } + + public sealed override void Focus() => Debug.Fail("Should never try to focus a SeparatorLine"); + + public override Size LayoutControls(int top, int width, bool measureOnly) => new Size(MinimumWidth, 1); + + public override void PaintLine(Graphics g, int lineWidth, int lineHeight) + { + using (Pen p = new Pen(ActionPanel.SeparatorColor)) + { + g.DrawLine(p, SeparatorHorizontalPadding, 0, lineWidth - (SeparatorHorizontalPadding + 1), 0); + } + } + + internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) + { + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionTextItem.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionTextItem.cs new file mode 100644 index 00000000000..61607c58347 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionTextItem.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + internal class DesignerActionTextItem : DesignerActionItem + { + public DesignerActionTextItem(string displayName, string category) : base(displayName, category, null) + { + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIService.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIService.cs new file mode 100644 index 00000000000..1d5eecdb41d --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIService.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Windows.Forms.Design; + +namespace System.ComponentModel.Design +{ + public sealed class DesignerActionUIService : IDisposable + { + private DesignerActionUIStateChangeEventHandler _designerActionUIStateChangedEventHandler; + private readonly IServiceProvider _serviceProvider; //standard service provider + private readonly DesignerActionService _designerActionService; + + internal DesignerActionUIService(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + if (serviceProvider != null) + { + _serviceProvider = serviceProvider; + IDesignerHost host = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + host.AddService(typeof(DesignerActionUIService), this); + _designerActionService = serviceProvider.GetService(typeof(DesignerActionService)) as DesignerActionService; + Debug.Assert(_designerActionService != null, "we should have created and registered the DAService first"); + } + } + + /// + /// Disposes all resources and unhooks all events. + /// + [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public void Dispose() + { + if (_serviceProvider != null) + { + IDesignerHost host = (IDesignerHost)_serviceProvider.GetService(typeof(IDesignerHost)); + if (host != null) + { + host.RemoveService(typeof(DesignerActionUIService)); + } + } + } + + /// + /// This event is thrown whenever a request is made to show/hide the ui + /// + public event DesignerActionUIStateChangeEventHandler DesignerActionUIStateChange + { + add => _designerActionUIStateChangedEventHandler += value; + remove => _designerActionUIStateChangedEventHandler -= value; + } + + public void HideUI(IComponent component) + { + OnDesignerActionUIStateChange(new DesignerActionUIStateChangeEventArgs(component, DesignerActionUIStateChangeType.Hide)); + } + + public void ShowUI(IComponent component) + { + OnDesignerActionUIStateChange(new DesignerActionUIStateChangeEventArgs(component, DesignerActionUIStateChangeType.Show)); + } + + /// + /// This is a new Helper Method that the service provides to refresh the DesignerActionGlyph as well as DesignerActionPanels. + /// + public void Refresh(IComponent component) + { + OnDesignerActionUIStateChange(new DesignerActionUIStateChangeEventArgs(component, DesignerActionUIStateChangeType.Refresh)); + } + + /// + /// This fires our DesignerActionsChanged event. + /// + private void OnDesignerActionUIStateChange(DesignerActionUIStateChangeEventArgs e) + { + _designerActionUIStateChangedEventHandler?.Invoke(this, e); + } + + + public bool ShouldAutoShow(IComponent component) + { + // Check the designer options... + if (_serviceProvider != null) + { + if (_serviceProvider.GetService(typeof(DesignerOptionService)) is DesignerOptionService opts) + { + PropertyDescriptor p = opts.Options.Properties["ObjectBoundSmartTagAutoShow"]; + if (p != null && p.PropertyType == typeof(bool) && !(bool)p.GetValue(null)) + { + return false; + } + } + } + if (_designerActionService != null) + { + DesignerActionListCollection coll = _designerActionService.GetComponentActions(component); + if (coll != null && coll.Count > 0) + { + for (int i = 0; i < coll.Count; i++) + { + if (coll[i].AutoShow) + { + return true; + } + } + } + } + return false; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeEventArgs.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeEventArgs.cs new file mode 100644 index 00000000000..1489cf48b32 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeEventArgs.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + /// + /// This EventArgs class is used by the DesignerActionService to signify that there has been a change in DesignerActionLists (added or removed) on the related object. + /// + public class DesignerActionUIStateChangeEventArgs : EventArgs + { + /// + /// Constructor that requires the object in question, the type of change and the remaining actionlists left for the object on the related object. + /// + public DesignerActionUIStateChangeEventArgs(object relatedObject, DesignerActionUIStateChangeType changeType) + { + RelatedObject = relatedObject; + ChangeType = changeType; + } + + /// + /// The object this change is related to. + /// + public object RelatedObject { get; } + + /// + /// The type of changed that caused the related event to be thrown. + /// + public DesignerActionUIStateChangeType ChangeType { get; } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeEventHandler.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeEventHandler.cs new file mode 100644 index 00000000000..48b12fe08b6 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeEventHandler.cs @@ -0,0 +1,8 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + public delegate void DesignerActionUIStateChangeEventHandler(object sender, DesignerActionUIStateChangeEventArgs e); +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeType.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeType.cs new file mode 100644 index 00000000000..e4f35eed025 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionUIStateChangeType.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + public enum DesignerActionUIStateChangeType + { + Show, + Hide, + Refresh + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs index aa4897ea3f0..03bc5877338 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs @@ -174,7 +174,7 @@ internal bool AddToContainerPreProcess(IComponent component, string name, IConta { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } // We should never add anything while we're unloading. @@ -482,7 +482,7 @@ protected override object GetService(Type service) object serviceInstance = null; if (service == null) { - throw new ArgumentNullException("service"); + throw new ArgumentNullException(nameof(service)); } if (service == typeof(IMultitargetHelperService)) @@ -620,7 +620,7 @@ internal bool RemoveFromContainerPreProcess(IComponent component, IContainer con { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } ISite site = component.Site; @@ -1110,7 +1110,7 @@ IComponent IDesignerHost.CreateComponent(Type componentType, string name) { if (componentType == null) { - throw new ArgumentNullException("componentType"); + throw new ArgumentNullException(nameof(componentType)); } IComponent component; @@ -1191,7 +1191,7 @@ void IDesignerHost.DestroyComponent(IComponent component) string name; if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } if (component.Site != null && component.Site.Name != null) @@ -1238,7 +1238,7 @@ IDesigner IDesignerHost.GetDesigner(IComponent component) { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } return _designers[component] as IDesigner; } @@ -1250,7 +1250,7 @@ Type IDesignerHost.GetType(string typeName) { if (typeName == null) { - throw new ArgumentNullException("typeName"); + throw new ArgumentNullException(nameof(typeName)); } if (GetService(typeof(ITypeResolutionService)) is ITypeResolutionService ts) @@ -1841,7 +1841,7 @@ object IServiceProvider.GetService(Type service) { if (service == null) { - throw new ArgumentNullException("service"); + throw new ArgumentNullException(nameof(service)); } // We always resolve IDictionaryService to ourselves. @@ -2023,7 +2023,7 @@ protected override ISite CreateSite(IComponent component, string name) { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } return new NestedSite(component, _host, name, this); } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExceptionCollection.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExceptionCollection.cs index af19d3b4f67..65e09f954b2 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExceptionCollection.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExceptionCollection.cs @@ -4,43 +4,26 @@ using System.Collections; using System.Runtime.Serialization; -using System.Security; namespace System.ComponentModel.Design { [Serializable] public sealed class ExceptionCollection : Exception { - readonly ArrayList _exceptions; + private readonly ArrayList _exceptions; public ExceptionCollection(ArrayList exceptions) { _exceptions = exceptions; } - /// - /// Need this constructor since Exception implements ISerializable. - /// private ExceptionCollection(SerializationInfo info, StreamingContext context) : base(info, context) { _exceptions = (ArrayList)info.GetValue("exceptions", typeof(ArrayList)); } - public ArrayList Exceptions - { - get - { - if (_exceptions != null) - { - return (ArrayList)_exceptions.Clone(); - } - return null; - } - } + public ArrayList Exceptions => (ArrayList)_exceptions?.Clone(); - /// - /// Need this since Exception implements ISerializable and we have fields to save out. - /// public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExtenderProviderService.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExtenderProviderService.cs index 78d7ae7f412..3cc6a6e408c 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExtenderProviderService.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ExtenderProviderService.cs @@ -41,7 +41,7 @@ void IExtenderProviderService.AddExtenderProvider(IExtenderProvider provider) { if (provider == null) { - throw new ArgumentNullException("provider"); + throw new ArgumentNullException(nameof(provider)); } if (_providers == null) @@ -64,7 +64,7 @@ void IExtenderProviderService.RemoveExtenderProvider(IExtenderProvider provider) { if (provider == null) { - throw new ArgumentNullException("provider"); + throw new ArgumentNullException(nameof(provider)); } if (_providers != null) diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventArgs.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventArgs.cs new file mode 100644 index 00000000000..d0f45bb2d8b --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventArgs.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; + +namespace System.ComponentModel.Design +{ + /// + /// Provides additional information for the Loaded event. + /// + public sealed class LoadedEventArgs : EventArgs + { + /// + /// Creates a new LoadedEventArgs object. + /// + public LoadedEventArgs(bool succeeded, ICollection errors) + { + HasSucceeded = succeeded; + Errors = errors ?? Array.Empty(); + } + + /// + /// True to indicate the designer load was successful. Even successful loads can have errors, if the errors were not too servere to prevent the designer from loading. + /// + public bool HasSucceeded { get; } + + /// + /// A collection of errors that occurred while the designer was loading. + /// + public ICollection Errors { get; } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventHandler.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventHandler.cs index c93d6141769..afcca44f685 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventHandler.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/LoadedEventHandler.cs @@ -2,49 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections; - namespace System.ComponentModel.Design { /// /// Represents the method that will handle a Loaded event. /// public delegate void LoadedEventHandler(object sender, LoadedEventArgs e); - - /// - /// Provides additional information for the Loaded event. - /// - public sealed class LoadedEventArgs : EventArgs - { - private readonly bool _succeeded; - private readonly ICollection _errors; - /// - /// Creates a new LoadedEventArgs object. - /// - public LoadedEventArgs(bool succeeded, ICollection errors) - { - _succeeded = succeeded; - _errors = errors; - if (_errors == null) - { - _errors = new object[0]; - } - } - - /// - /// A collection of errors that occurred while the designer was loading. - /// - public ICollection Errors - { - get => _errors; - } - - /// - /// True to indicate the designer load was successful. Even successful loads can have errors, if the errors were not too servere to prevent the designer from loading. - /// - public bool HasSucceeded - { - get => _succeeded; - } - } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ProjectTargetFrameworkAttribute.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ProjectTargetFrameworkAttribute.cs index 24956e289c2..7a0c4917196 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ProjectTargetFrameworkAttribute.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/ProjectTargetFrameworkAttribute.cs @@ -7,15 +7,11 @@ namespace System.ComponentModel.Design [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct)] public sealed class ProjectTargetFrameworkAttribute : Attribute { - private string _targetFrameworkMoniker; public ProjectTargetFrameworkAttribute(string targetFrameworkMoniker) { - _targetFrameworkMoniker = targetFrameworkMoniker; + TargetFrameworkMoniker = targetFrameworkMoniker; } - public string TargetFrameworkMoniker - { - get => _targetFrameworkMoniker; - } + public string TargetFrameworkMoniker { get; } } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/SelectionService.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/SelectionService.cs index 7860cbc1f09..b69c969dc9b 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/SelectionService.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/SelectionService.cs @@ -166,6 +166,11 @@ private void OnTransactionOpened(object sender, EventArgs e) _state[s_stateTransaction] = true; } + internal object PrimarySelection + { + get => (_selection != null && _selection.Count > 0) ? _selection[0] : null; + } + /// /// Removes the given selection from the selection list. /// @@ -267,7 +272,7 @@ void IDisposable.Dispose() { if (GetService(typeof(IDesignerHost)) is IDesignerHost host) { - host.TransactionOpened -= new EventHandler(this.OnTransactionOpened); + host.TransactionOpened -= new EventHandler(OnTransactionOpened); host.TransactionClosed -= new DesignerTransactionCloseEventHandler(OnTransactionClosed); if (host.InTransaction) { @@ -353,7 +358,7 @@ bool ISelectionService.GetComponentSelected(object component) { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } return (_selection != null && _selection.Contains(component)); } @@ -423,7 +428,7 @@ void ISelectionService.SetSelectedComponents(ICollection components, SelectionTy requestedPrimary = o; if (o == null) { - throw new ArgumentNullException("components"); + throw new ArgumentNullException(nameof(components)); } break; } @@ -455,7 +460,7 @@ void ISelectionService.SetSelectedComponents(ICollection components, SelectionTy foreach (object comp in components) { if (comp == null) - throw new ArgumentNullException("components"); + throw new ArgumentNullException(nameof(components)); if (object.ReferenceEquals(comp, item)) { remove = false; @@ -476,7 +481,7 @@ void ISelectionService.SetSelectedComponents(ICollection components, SelectionTy foreach (object comp in components) { if (comp == null) - throw new ArgumentNullException("components"); + throw new ArgumentNullException(nameof(components)); if (_selection != null && _selection.Contains(comp)) { diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializationProvider.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializationProvider.cs index ac52211ba06..289c42664e0 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializationProvider.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializationProvider.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections; +using System.Resources; + namespace System.ComponentModel.Design.Serialization { /// @@ -9,10 +12,135 @@ namespace System.ComponentModel.Design.Serialization /// internal sealed class CodeDomSerializationProvider : IDesignerSerializationProvider { - public object GetSerializer(IDesignerSerializationManager manager, object currentSerializer, Type objectType, - Type serializerType) + /// + /// This will be called by the serialization manager when it + /// is trying to locate a serialzer for an object type. + /// If this serialization provider can provide a serializer + /// that is of the correct type, it should return it. + /// Otherwise, it should return null. + /// + object IDesignerSerializationProvider.GetSerializer(IDesignerSerializationManager manager, object currentSerializer, Type objectType, Type serializerType) + { + if (serializerType == typeof(CodeDomSerializer)) + { + return GetCodeDomSerializer(manager, currentSerializer, objectType, serializerType); + } + else if (serializerType == typeof(MemberCodeDomSerializer)) + { + return GetMemberCodeDomSerializer(manager, currentSerializer, objectType, serializerType); + } + else if (serializerType == typeof(TypeCodeDomSerializer)) + { + return GetTypeCodeDomSerializer(manager, currentSerializer, objectType, serializerType); + } + + return null; // don't understand this type of serializer. + } + + /// + /// Returns a code dom serializer + /// + private object GetCodeDomSerializer(IDesignerSerializationManager manager, object currentSerializer, Type objectType, Type serializerType) + { + // If this isn't a serializer type we recognize, do nothing. Also, if metadata specified + // a custom serializer, then use it. + if (currentSerializer != null) + { + return null; + } + + // Null is a valid value that can be passed into GetSerializer. It indicates + // that the value we need to serialize is null, in which case we handle it + // through the PrimitiveCodeDomSerializer. + // + if (objectType == null) + { + return PrimitiveCodeDomSerializer.Default; + } + + // Support for components. + if (typeof(IComponent).IsAssignableFrom(objectType)) + { + return ComponentCodeDomSerializer.Default; + } + + // We special case enums. They do have instance descriptors, but we want + // better looking code than the instance descriptor can provide for flags, + // so we do it ourselves. + if (typeof(Enum).IsAssignableFrom(objectType)) + { + return EnumCodeDomSerializer.Default; + } + + // We will provide a serializer for any intrinsic types. + if (objectType.IsPrimitive || objectType.IsEnum || objectType == typeof(string)) + { + return PrimitiveCodeDomSerializer.Default; + } + + // And one for collections. + if (typeof(ICollection).IsAssignableFrom(objectType)) + { + return CollectionCodeDomSerializer.Default; + } + + // And one for IContainer + if (typeof(IContainer).IsAssignableFrom(objectType)) + { + return ContainerCodeDomSerializer.Default; + } + + // And one for resources + if (typeof(ResourceManager).IsAssignableFrom(objectType)) + { + return ResourceCodeDomSerializer.Default; + } + + // The default serializer can do any object including those with instance descriptors. + return CodeDomSerializer.Default; + } + + /// + /// Returns a code dom serializer for members + /// + private object GetMemberCodeDomSerializer(IDesignerSerializationManager manager, object currentSerializer, Type objectType, Type serializerType) + { + // Don't provide our serializer if someone else already had one + if (currentSerializer != null) + { + return null; + } + + if (typeof(PropertyDescriptor).IsAssignableFrom(objectType)) + { + return PropertyMemberCodeDomSerializer.Default; + } + + if (typeof(EventDescriptor).IsAssignableFrom(objectType)) + { + return EventMemberCodeDomSerializer.Default; + } + + return null; + } + + /// + /// Returns a code dom serializer for types + /// + private object GetTypeCodeDomSerializer(IDesignerSerializationManager manager, object currentSerializer, Type objectType, Type serializerType) { - throw new NotImplementedException(); + // Don't provide our serializer if someone else already had one + if (currentSerializer != null) + { + return null; + } + + if (typeof(IComponent).IsAssignableFrom(objectType)) + { + return ComponentTypeCodeDomSerializer.Default; + } + + return TypeCodeDomSerializer.Default; } } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs index c995e73f452..efdb96ef94c 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs @@ -15,10 +15,24 @@ namespace System.ComponentModel.Design.Serialization [DefaultSerializationProvider(typeof(CodeDomSerializationProvider))] public class CodeDomSerializer : CodeDomSerializerBase { + private static CodeDomSerializer s_default; private static readonly Attribute[] _runTimeFilter = new Attribute[] { DesignOnlyAttribute.No }; private static readonly Attribute[] _designTimeFilter = new Attribute[] { DesignOnlyAttribute.Yes }; private static CodeThisReferenceExpression _thisRef = new CodeThisReferenceExpression(); + internal static CodeDomSerializer Default + { + get + { + if (s_default == null) + { + s_default = new CodeDomSerializer(); + } + + return s_default; + } + } + /// /// Determines which statement group the given statement should belong to. The expression parameter /// is an expression that the statement has been reduced to, and targetType represents the type @@ -151,9 +165,16 @@ protected object DeserializeStatementToInstance(IDesignerSerializationManager ma public virtual object Serialize(IDesignerSerializationManager manager, object value) { object result = null; - if (manager == null || value == null) throw new ArgumentNullException(manager == null ? "manager" : "value"); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if(value == null) + { + throw new ArgumentNullException(nameof(value)); + } - using (TraceScope("CodeDomSerializer::Serialize")) + using (TraceScope("CodeDomSerializer::" + nameof(Serialize))) { Trace("Type: {0}", value.GetType().Name); @@ -250,9 +271,9 @@ public virtual object SerializeAbsolute(IDesignerSerializationManager manager, o /// public virtual CodeStatementCollection SerializeMember(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member) { - if (manager == null) throw new ArgumentNullException("manager"); - if (owningObject == null) throw new ArgumentNullException("owningObject"); - if (member == null) throw new ArgumentNullException("member"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (owningObject == null) throw new ArgumentNullException(nameof(owningObject)); + if (member == null) throw new ArgumentNullException(nameof(member)); CodeStatementCollection statements = new CodeStatementCollection(); // See if we have an existing expression for this member. If not, fabricate one @@ -287,9 +308,9 @@ public virtual CodeStatementCollection SerializeMember(IDesignerSerializationMan /// public virtual CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member) { - if (manager == null) throw new ArgumentNullException("manager"); - if (owningObject == null) throw new ArgumentNullException("owningObject"); - if (member == null) throw new ArgumentNullException("member"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (owningObject == null) throw new ArgumentNullException(nameof(owningObject)); + if (member == null) throw new ArgumentNullException(nameof(member)); CodeStatementCollection statements; SerializeAbsoluteContext abs = new SerializeAbsoluteContext(member); @@ -318,7 +339,7 @@ public virtual CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializ protected CodeExpression SerializeToReferenceExpression(IDesignerSerializationManager manager, object value) { CodeExpression expression = null; - using (TraceScope("CodeDomSerializer::SerializeToReferenceExpression")) + using (TraceScope("CodeDomSerializer::" + nameof(SerializeToReferenceExpression))) { // First - try GetExpression expression = GetExpression(manager, value); diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs index cb71e079120..3e3c96688f3 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs @@ -38,8 +38,15 @@ internal CodeDomSerializerBase() /// protected virtual object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer) { - if (manager == null) throw new ArgumentNullException("manager"); - if (type == null) throw new ArgumentNullException("type"); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + return manager.CreateInstance(type, parameters, name, addToContainer); } @@ -139,10 +146,16 @@ protected static Type GetReflectionTypeFromTypeHelper(IDesignerSerializationMana return TypeDescriptor.GetReflectionType(type); } - private static void Error(IDesignerSerializationManager manager, string exceptionText, string helpLink) + internal static void Error(IDesignerSerializationManager manager, string exceptionText, string helpLink) { - if (manager == null) throw new ArgumentNullException("manager"); - if (exceptionText == null) throw new ArgumentNullException("exceptionText"); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (exceptionText == null) + { + throw new ArgumentNullException(nameof(exceptionText)); + } CodeStatement statement = (CodeStatement)manager.Context[typeof(CodeStatement)]; CodeLinePragma linePragma = null; @@ -368,10 +381,10 @@ protected void DeserializePropertiesFromResources(IDesignerSerializationManager using (TraceScope("ComponentCodeDomSerializerBase::DeserializePropertiesFromResources")) { // It is much faster to dig through the resources first, and then map these resources to properties than it is to filter properties at each turn. Why? Because filtering properties requires a separate filter call for each object (because designers get a chance to filter, the cache is per-component), while resources are loaded once per document. - IDictionaryEnumerator de = ResourceCodeDomSerializer.GetDefault().GetMetadataEnumerator(manager); + IDictionaryEnumerator de = ResourceCodeDomSerializer.Default.GetMetadataEnumerator(manager); if (de == null) { - de = ResourceCodeDomSerializer.GetDefault().GetEnumerator(manager, CultureInfo.InvariantCulture); + de = ResourceCodeDomSerializer.Default.GetEnumerator(manager, CultureInfo.InvariantCulture); } if (de != null) @@ -498,7 +511,7 @@ public void Dispose() [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] protected void DeserializeStatement(IDesignerSerializationManager manager, CodeStatement statement) { - using (TraceScope("CodeDomSerializerBase::DeserializeStatement")) + using (TraceScope("CodeDomSerializerBase::" + nameof(DeserializeStatement))) { Trace("Statement : {0}", statement.GetType().Name); @@ -593,7 +606,7 @@ protected void DeserializeStatement(IDesignerSerializationManager manager, CodeS private void DeserializeVariableDeclarationStatement(IDesignerSerializationManager manager, CodeVariableDeclarationStatement statement) { - using (TraceScope("CodeDomSerializerBase::DeserializeVariableDeclarationStatement")) + using (TraceScope("CodeDomSerializerBase::" + nameof(DeserializeVariableDeclarationStatement))) { if (statement.InitExpression != null) { @@ -605,7 +618,7 @@ private void DeserializeVariableDeclarationStatement(IDesignerSerializationManag private void DeserializeDetachEventStatement(IDesignerSerializationManager manager, CodeRemoveEventStatement statement) { - using (TraceScope("CodeDomSerializerBase::DeserializeDetachEventStatement")) + using (TraceScope("CodeDomSerializerBase::" + nameof(DeserializeDetachEventStatement))) { object eventListener = DeserializeExpression(manager, null, statement.Listener); TraceErrorIf(!(eventListener is CodeDelegateCreateExpression), "Unable to simplify event attach RHS to a delegate create."); @@ -646,7 +659,7 @@ private void DeserializeDetachEventStatement(IDesignerSerializationManager manag private void DeserializeAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement) { - using (TraceScope("CodeDomSerializerBase::DeserializeAssignStatement")) + using (TraceScope("CodeDomSerializerBase::" + nameof(DeserializeAssignStatement))) { // Since we're doing an assignment into something, we need to know what that something is. It can be a property, a variable, or a member. Anything else is invalid. //Perf: is -> as changes, change ordering based on possibility of occurence @@ -840,7 +853,7 @@ internal static void TraceError(string message, params object[] values) protected object DeserializeExpression(IDesignerSerializationManager manager, string name, CodeExpression expression) { object result = expression; - using (TraceScope("CodeDomSerializerBase::DeserializeExpression")) + using (TraceScope("CodeDomSerializerBase::" + nameof(DeserializeExpression))) { // Perf: is -> as changes, change ordering based on possibility of occurance // If you are adding to this, use as instead of is + cast and order new expressions in order of frequency in typical user code. @@ -1426,7 +1439,7 @@ protected object DeserializeExpression(IDesignerSerializationManager manager, st private void DeserializeAttachEventStatement(IDesignerSerializationManager manager, CodeAttachEventStatement statement) { - using (TraceScope("CodeDomSerializerBase::DeserializeAttachEventStatement")) + using (TraceScope("CodeDomSerializerBase::" + nameof(DeserializeAttachEventStatement))) { string handlerMethodName = null; object eventAttachObject = null; @@ -1517,7 +1530,8 @@ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, Co { // "Binary" operator type is actually a combination of several types of operators: boolean, binary and math. Group them into categories here. - CodeBinaryOperatorType[] booleanOperators = new CodeBinaryOperatorType[] { + CodeBinaryOperatorType[] booleanOperators = new CodeBinaryOperatorType[] + { CodeBinaryOperatorType.IdentityInequality, CodeBinaryOperatorType.IdentityEquality, CodeBinaryOperatorType.ValueEquality, @@ -1529,7 +1543,8 @@ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, Co CodeBinaryOperatorType.GreaterThanOrEqual }; - CodeBinaryOperatorType[] mathOperators = new CodeBinaryOperatorType[] { + CodeBinaryOperatorType[] mathOperators = new CodeBinaryOperatorType[] + { CodeBinaryOperatorType.Add, CodeBinaryOperatorType.Subtract, CodeBinaryOperatorType.Multiply, @@ -1537,7 +1552,8 @@ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, Co CodeBinaryOperatorType.Modulus }; - CodeBinaryOperatorType[] binaryOperators = new CodeBinaryOperatorType[] { + CodeBinaryOperatorType[] binaryOperators = new CodeBinaryOperatorType[] + { CodeBinaryOperatorType.BitwiseOr, CodeBinaryOperatorType.BitwiseAnd }; @@ -1550,6 +1566,7 @@ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, Co return ExecuteBinaryOperator(left, right, op); } } + for (int i = 0; i < mathOperators.Length; i++) { if (op == mathOperators[i]) @@ -1557,6 +1574,7 @@ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, Co return ExecuteMathOperator(left, right, op); } } + for (int i = 0; i < booleanOperators.Length; i++) { if (op == booleanOperators[i]) @@ -1564,6 +1582,7 @@ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, Co return ExecuteBooleanOperator(left, right, op); } } + Debug.Fail("Unsupported binary operator type: " + op.ToString()); return left; } @@ -1573,7 +1592,8 @@ private object ExecuteBinaryOperator(IConvertible left, IConvertible right, Code TypeCode rightType = right.GetTypeCode(); // The compatible types are listed in order from lowest bitness to highest. We must operate on the highest bitness to keep fidelity. - TypeCode[] compatibleTypes = new TypeCode[] { + TypeCode[] compatibleTypes = new TypeCode[] + { TypeCode.Byte, TypeCode.Char, TypeCode.Int16, @@ -1581,7 +1601,8 @@ private object ExecuteBinaryOperator(IConvertible left, IConvertible right, Code TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, - TypeCode.UInt64}; + TypeCode.UInt64 + }; int leftTypeIndex = -1; int rightTypeIndex = -1; @@ -1613,117 +1634,117 @@ private object ExecuteBinaryOperator(IConvertible left, IConvertible right, Code switch (compatibleTypes[maxIndex]) { case TypeCode.Byte: + { + byte leftValue = left.ToByte(null); + byte rightValue = right.ToByte(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - byte leftValue = left.ToByte(null); - byte rightValue = right.ToByte(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.Char: + { + char leftValue = left.ToChar(null); + char rightValue = right.ToChar(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - char leftValue = left.ToChar(null); - char rightValue = right.ToChar(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.Int16: + { + short leftValue = left.ToInt16(null); + short rightValue = right.ToInt16(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - short leftValue = left.ToInt16(null); - short rightValue = right.ToInt16(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = (short)((ushort)leftValue | (ushort)rightValue); - } - else - { - result = leftValue & rightValue; - } - break; + result = (short)((ushort)leftValue | (ushort)rightValue); + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.UInt16: + { + ushort leftValue = left.ToUInt16(null); + ushort rightValue = right.ToUInt16(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - ushort leftValue = left.ToUInt16(null); - ushort rightValue = right.ToUInt16(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.Int32: + { + int leftValue = left.ToInt32(null); + int rightValue = right.ToInt32(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - int leftValue = left.ToInt32(null); - int rightValue = right.ToInt32(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.UInt32: + { + uint leftValue = left.ToUInt32(null); + uint rightValue = right.ToUInt32(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - uint leftValue = left.ToUInt32(null); - uint rightValue = right.ToUInt32(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.Int64: + { + long leftValue = left.ToInt64(null); + long rightValue = right.ToInt64(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - long leftValue = left.ToInt64(null); - long rightValue = right.ToInt64(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } case TypeCode.UInt64: + { + ulong leftValue = left.ToUInt64(null); + ulong rightValue = right.ToUInt64(null); + if (op == CodeBinaryOperatorType.BitwiseOr) { - ulong leftValue = left.ToUInt64(null); - ulong rightValue = right.ToUInt64(null); - if (op == CodeBinaryOperatorType.BitwiseOr) - { - result = leftValue | rightValue; - } - else - { - result = leftValue & rightValue; - } - break; + result = leftValue | rightValue; + } + else + { + result = leftValue & rightValue; } + break; + } } if (result != left && left is Enum) @@ -1776,9 +1797,8 @@ private object ExecuteBooleanOperator(IConvertible left, IConvertible right, Cod private object ExecuteMathOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op) { - switch (op) + if (op == CodeBinaryOperatorType.Add) { - case CodeBinaryOperatorType.Add: string leftString = left as string; string rightString = right as string; @@ -1799,12 +1819,13 @@ private object ExecuteMathOperator(IConvertible left, IConvertible right, CodeBi else { Debug.Fail("Addition operator not supported for this type"); - return left; } - default: + } + else + { Debug.Fail("Math operators are not supported"); - return left; } + return left; } [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] @@ -1858,13 +1879,19 @@ private object DeserializePropertyReferenceExpression(IDesignerSerializationMana [Conditional("DEBUG")] internal static void TraceErrorIf(bool condition, string message, params object[] values) { - if (condition) TraceError(message, values); + if (condition) + { + TraceError(message, values); + } } [Conditional("DEBUG")] internal static void TraceWarningIf(bool condition, string message, params object[] values) { - if (condition) TraceWarning(message, values); + if (condition) + { + TraceWarning(message, values); + } } [Conditional("DEBUG")] @@ -2031,12 +2058,12 @@ protected CodeExpression GetExpression(IDesignerSerializationManager manager, ob if (manager == null) { - throw new ArgumentNullException("manager"); + throw new ArgumentNullException(nameof(manager)); } if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Trace("GetExpression called for object {0}", value.ToString()); @@ -2151,7 +2178,7 @@ protected CodeDomSerializer GetSerializer(IDesignerSerializationManager manager, { if (manager == null) { - throw new ArgumentNullException("manager"); + throw new ArgumentNullException(nameof(manager)); } if (value != null) { @@ -2263,8 +2290,8 @@ protected bool IsSerialized(IDesignerSerializationManager manager, object value) protected bool IsSerialized(IDesignerSerializationManager manager, object value, bool honorPreset) { bool hasExpression = false; - if (manager == null) throw new ArgumentNullException("manager"); - if (value == null) throw new ArgumentNullException("value"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (value == null) throw new ArgumentNullException(nameof(value)); // Is the expression part of a prior SetExpression call? if (manager.Context[typeof(ExpressionTable)] is ExpressionTable table && table.GetExpression(value) != null && (!honorPreset || !table.ContainsPresetExpression(value))) @@ -2284,8 +2311,8 @@ protected bool IsSerialized(IDesignerSerializationManager manager, object value, protected CodeExpression SerializeCreationExpression(IDesignerSerializationManager manager, object value, out bool isComplete) { isComplete = false; - if (manager == null) throw new ArgumentNullException("manager"); - if (value == null) throw new ArgumentNullException("value"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (value == null) throw new ArgumentNullException(nameof(value)); TypeConverter converter = TypeDescriptor.GetConverter(value); // See if there is an ExpressionContext with a preset value we're interested in. If so, that will dictate our creation expression. @@ -2465,8 +2492,14 @@ private CodeExpression SerializeInstanceDescriptor(IDesignerSerializationManager /// protected string GetUniqueName(IDesignerSerializationManager manager, object value) { - if (manager == null) throw new ArgumentNullException("manager"); - if (value == null) throw new ArgumentNullException("value"); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } string name = manager.GetName(value); if (name == null) @@ -2510,12 +2543,12 @@ protected string GetUniqueName(IDesignerSerializationManager manager, object val /// protected void SerializeEvent(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, EventDescriptor descriptor) { - if (manager == null) throw new ArgumentNullException("manager"); - if (statements == null) throw new ArgumentNullException("statements"); - if (value == null) throw new ArgumentNullException("value"); - if (descriptor == null) throw new ArgumentNullException("descriptor"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (statements == null) throw new ArgumentNullException(nameof(statements)); + if (value == null) throw new ArgumentNullException(nameof(value)); + if (descriptor == null) throw new ArgumentNullException(nameof(descriptor)); - using (TraceScope("CodeDomSerializerBase::SerializeEvent")) + using (TraceScope("CodeDomSerializerBase::" + nameof(SerializeEvent))) { Trace("Name: {0}", descriptor.Name); // Now look for a MemberCodeDomSerializer for the property. If we can't find one, then we can't serialize the property @@ -2545,7 +2578,7 @@ protected void SerializeEvent(IDesignerSerializationManager manager, CodeStateme /// protected void SerializeEvents(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, params Attribute[] filter) { - Trace("CodeDomSerializerBase::SerializeEvents"); + Trace("CodeDomSerializerBase::" + nameof(SerializeEvents)); EventDescriptorCollection events = GetEventsHelper(manager, value, filter).Sort(); foreach (EventDescriptor evt in events) { @@ -2558,7 +2591,7 @@ protected void SerializeEvents(IDesignerSerializationManager manager, CodeStatem /// protected void SerializeProperties(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, Attribute[] filter) { - using (TraceScope("CodeDomSerializerBase::SerializeProperties")) + using (TraceScope("CodeDomSerializerBase::" + nameof(SerializeProperties))) { PropertyDescriptorCollection properties = GetFilteredProperties(manager, value, filter).Sort(); InheritanceAttribute inheritance = (InheritanceAttribute)GetAttributesHelper(manager, value)[typeof(InheritanceAttribute)]; @@ -2618,7 +2651,7 @@ private PropertyDescriptorCollection GetFilteredProperties(IDesignerSerializatio /// protected void SerializePropertiesToResources(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, Attribute[] filter) { - using (TraceScope("ComponentCodeDomSerializerBase::SerializePropertiesToResources")) + using (TraceScope("ComponentCodeDomSerializerBase::" + nameof(SerializePropertiesToResources))) { PropertyDescriptorCollection props = GetPropertiesHelper(manager, value, filter); manager.Context.Push(statements); @@ -2651,7 +2684,7 @@ protected void SerializePropertiesToResources(IDesignerSerializationManager mana } name = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", name, property.Name); - ResourceCodeDomSerializer.GetDefault().SerializeMetadata(manager, name, property.GetValue(value), property.ShouldSerializeValue(value)); + ResourceCodeDomSerializer.Default.SerializeMetadata(manager, name, property.GetValue(value), property.ShouldSerializeValue(value)); } } finally @@ -2675,12 +2708,12 @@ protected void SerializePropertiesToResources(IDesignerSerializationManager mana /// protected void SerializeProperty(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, PropertyDescriptor propertyToSerialize) { - if (manager == null) throw new ArgumentNullException("manager"); - if (value == null) throw new ArgumentNullException("value"); - if (propertyToSerialize == null) throw new ArgumentNullException("propertyToSerialize"); - if (statements == null) throw new ArgumentNullException("statements"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (value == null) throw new ArgumentNullException(nameof(value)); + if (propertyToSerialize == null) throw new ArgumentNullException(nameof(propertyToSerialize)); + if (statements == null) throw new ArgumentNullException(nameof(statements)); - Trace("CodeDomSerializerBase::SerializeProperty {0}", propertyToSerialize.Name); + Trace("CodeDomSerializerBase::" + nameof(SerializeProperty) + " {0}", propertyToSerialize.Name); // Now look for a MemberCodeDomSerializer for the property. If we can't find one, then we can't serialize the property manager.Context.Push(statements); manager.Context.Push(propertyToSerialize); @@ -2707,7 +2740,7 @@ protected void SerializeProperty(IDesignerSerializationManager manager, CodeStat /// protected void SerializeResource(IDesignerSerializationManager manager, string resourceName, object value) { - ResourceCodeDomSerializer.GetDefault().WriteResource(manager, resourceName, value); + ResourceCodeDomSerializer.Default.WriteResource(manager, resourceName, value); } /// @@ -2716,7 +2749,7 @@ protected void SerializeResource(IDesignerSerializationManager manager, string r /// protected void SerializeResourceInvariant(IDesignerSerializationManager manager, string resourceName, object value) { - ResourceCodeDomSerializer.GetDefault().WriteResourceInvariant(manager, resourceName, value); + ResourceCodeDomSerializer.Default.WriteResourceInvariant(manager, resourceName, value); } /// @@ -2738,7 +2771,7 @@ protected CodeExpression SerializeToExpression(IDesignerSerializationManager man { CodeExpression expression = null; - using (TraceScope("SerializeToExpression")) + using (TraceScope("CodeDomSerializerBase::" + nameof(SerializeToExpression))) { // We do several things here: // First, we check to see if there is already an expression for this object by calling IsSerialized / GetExpression. @@ -2989,7 +3022,7 @@ protected CodeExpression SerializeToResourceExpression(IDesignerSerializationMan try { - result = ResourceCodeDomSerializer.GetDefault().Serialize(manager, value, false, ensureInvariant) as CodeExpression; + result = ResourceCodeDomSerializer.Default.Serialize(manager, value, false, ensureInvariant) as CodeExpression; } finally { @@ -3018,9 +3051,9 @@ protected void SetExpression(IDesignerSerializationManager manager, object value [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")] protected void SetExpression(IDesignerSerializationManager manager, object value, CodeExpression expression, bool isPreset) { - if (manager == null) throw new ArgumentNullException("manager"); - if (value == null) throw new ArgumentNullException("value"); - if (expression == null) throw new ArgumentNullException("expression"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (value == null) throw new ArgumentNullException(nameof(value)); + if (expression == null) throw new ArgumentNullException(nameof(expression)); ExpressionTable table = (ExpressionTable)manager.Context[typeof(ExpressionTable)]; if (table == null) @@ -3062,7 +3095,7 @@ internal static void FillStatementTable(IDesignerSerializationManager manager, I internal static void FillStatementTable(IDesignerSerializationManager manager, IDictionary table, Dictionary names, CodeStatementCollection statements, string className) { - using (TraceScope("CodeDomSerializerBase::FillStatementTable")) + using (TraceScope("CodeDomSerializerBase::" + nameof(FillStatementTable))) { // Look in the method body to try to find statements with a LHS that points to a name in our nametable. foreach (CodeStatement statement in statements) diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs index 0f93edcecaa..02b56516b6e 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs @@ -9,76 +9,56 @@ namespace System.ComponentModel.Design.Serialization { /// - /// The exception that is thrown when the code dom serializer experiences an error. + /// The exception that is thrown when the code dom serializer experiences an error. /// [Serializable] [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] public class CodeDomSerializerException : SystemException { - - private readonly CodeLinePragma _linePragma; - - /// - /// Initializes a new instance of the CodeDomSerializerException class. - /// public CodeDomSerializerException(string message, CodeLinePragma linePragma) : base(message) { - _linePragma = linePragma; + LinePragma = linePragma; } - /// - /// Initializes a new instance of the CodeDomSerializerException class. - /// - public CodeDomSerializerException(Exception ex, CodeLinePragma linePragma) : base(ex.Message, ex) + public CodeDomSerializerException(Exception ex, CodeLinePragma linePragma) : base(ex?.Message, ex) { - _linePragma = linePragma; + LinePragma = linePragma; } - /// - /// Initializes a new instance of the CodeDomSerializerException class. - /// public CodeDomSerializerException(string message, IDesignerSerializationManager manager) : base(message) { - FillLinePragmaFromContext(manager); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } } - /// - /// Initializes a new instance of the CodeDomSerializerException class. - /// - public CodeDomSerializerException(Exception ex, IDesignerSerializationManager manager) : base(ex.Message, ex) + public CodeDomSerializerException(Exception ex, IDesignerSerializationManager manager) : base(ex?.Message, ex) { - FillLinePragmaFromContext(manager); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } } protected CodeDomSerializerException(SerializationInfo info, StreamingContext context) : base(info, context) { - _linePragma = (CodeLinePragma)info.GetValue("linePragma", typeof(CodeLinePragma)); + LinePragma = (CodeLinePragma)info.GetValue("linePragma", typeof(CodeLinePragma)); } /// /// Gets the line pragma object that is related to this error. /// - public CodeLinePragma LinePragma - { - get => _linePragma; - } - - /// - /// Sniffs around in the context looking for a code statement. if it finds one, it will add the statement's line # information to the exception. - /// - private void FillLinePragmaFromContext(IDesignerSerializationManager manager) - { - if (manager == null) - throw new ArgumentNullException("manager"); - } + public CodeLinePragma LinePragma { get; } public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } - info.AddValue("linePragma", _linePragma); + + info.AddValue("linePragma", LinePragma); base.GetObjectData(info, context); } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs index f530fc8ffa0..33805db9a58 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs @@ -22,13 +22,16 @@ public class CollectionCodeDomSerializer : CodeDomSerializer /// /// Retrieves a default static instance of this serializer. /// - internal static CollectionCodeDomSerializer GetDefault() + internal new static CollectionCodeDomSerializer Default { - if (s_defaultSerializer == null) - { - s_defaultSerializer = new CollectionCodeDomSerializer(); + get + { + if (s_defaultSerializer == null) + { + s_defaultSerializer = new CollectionCodeDomSerializer(); + } + return s_defaultSerializer; } - return s_defaultSerializer; } /// @@ -119,7 +122,7 @@ protected bool MethodSupportsSerialization(MethodInfo method) { if (method == null) { - throw new ArgumentNullException("method"); + throw new ArgumentNullException(nameof(method)); } object[] attrs = method.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true); @@ -143,15 +146,15 @@ public override object Serialize(IDesignerSerializationManager manager, object v { if (manager == null) { - throw new ArgumentNullException("manager"); + throw new ArgumentNullException(nameof(manager)); } if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } object result = null; - using (TraceScope("CollectionCodeDomSerializer::Serialize")) + using (TraceScope("CollectionCodeDomSerializer::" + nameof(Serialize))) { // We serialize collections as follows: // If the collection is an array, we write out the array. @@ -305,10 +308,10 @@ private static MethodInfo ChooseMethodByType(TypeDescriptionProvider provider, L /// protected virtual object SerializeCollection(IDesignerSerializationManager manager, CodeExpression targetExpression, Type targetType, ICollection originalCollection, ICollection valuesToSerialize) { - if (manager == null) throw new ArgumentNullException("manager"); - if (targetType == null) throw new ArgumentNullException("targetType"); - if (originalCollection == null) throw new ArgumentNullException("originalCollection"); - if (valuesToSerialize == null) throw new ArgumentNullException("valuesToSerialize"); + if (manager == null) throw new ArgumentNullException(nameof(manager)); + if (targetType == null) throw new ArgumentNullException(nameof(targetType)); + if (originalCollection == null) throw new ArgumentNullException(nameof(originalCollection)); + if (valuesToSerialize == null) throw new ArgumentNullException(nameof(valuesToSerialize)); object result = null; bool serialized = false; @@ -406,7 +409,7 @@ protected virtual object SerializeCollection(IDesignerSerializationManager manag private CodeArrayCreateExpression SerializeArray(IDesignerSerializationManager manager, Type targetType, ICollection array, ICollection valuesToSerialize) { CodeArrayCreateExpression result = null; - using (TraceScope("CollectionCodeDomSerializer::SerializeArray")) + using (TraceScope("CollectionCodeDomSerializer::" + nameof(SerializeArray))) { if (((Array)array).Rank != 1) { @@ -494,7 +497,7 @@ private object SerializeViaAdd( ICollection valuesToSerialize) { CodeStatementCollection statements = new CodeStatementCollection(); - using (TraceScope("CollectionCodeDomSerializer::SerializeViaAdd")) + using (TraceScope("CollectionCodeDomSerializer::" + nameof(SerializeViaAdd))) { Trace("Elements: {0}", valuesToSerialize.Count.ToString(CultureInfo.InvariantCulture)); // Here we need to invoke Add once for each and every item in the collection. We can re-use the property reference and method reference, but we will need to recreate the invoke statement each time. @@ -582,7 +585,7 @@ private object SerializeViaAddRange( ICollection valuesToSerialize) { CodeStatementCollection statements = new CodeStatementCollection(); - using (TraceScope("CollectionCodeDomSerializer::SerializeViaAddRange")) + using (TraceScope("CollectionCodeDomSerializer::" + nameof(SerializeViaAddRange))) { Trace("Elements: {0}", valuesToSerialize.Count.ToString(CultureInfo.InvariantCulture)); diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs index 254d746654a..976393825f4 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs @@ -59,7 +59,7 @@ internal Entry this[object component] { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } if (_cache != null && _cache.TryGetValue(component, out Entry result)) @@ -160,7 +160,7 @@ private void OnComponentChanging(object source, ComponentChangingEventArgs ce) } else { - // Hmm. We were notified about an object change, but were unable to relate it back to a component we know about. In this situation, we have no option but to clear the whole cache, since we don't want serialization to miss something. See VSWhidbey #404813 for an example of what we would have missed. + // Hmm. We were notified about an object change, but were unable to relate it back to a component we know about. In this situation, we have no option but to clear the whole cache, since we don't want serialization to miss something. _cache.Clear(); } } @@ -191,7 +191,7 @@ private void OnComponentChanged(object source, ComponentChangedEventArgs ce) } else { - // Hmm. We were notified about an object change, but were unable to relate it back to a component we know about. In this situation, we have no option but to clear the whole cache, since we don't want serialization to miss something. See VSWhidbey #404813 for an example of what we would have missed. + // Hmm. We were notified about an object change, but were unable to relate it back to a component we know about. In this situation, we have no option but to clear the whole cache, since we don't want serialization to miss something. _cache.Clear(); } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCodeDomSerializer.cs new file mode 100644 index 00000000000..2cb9eb41dd5 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCodeDomSerializer.cs @@ -0,0 +1,608 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CodeDom; +using System.Configuration; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Reflection; +using System.Text; + +namespace System.ComponentModel.Design.Serialization +{ + + internal class ComponentCodeDomSerializer : CodeDomSerializer + { + + private Type[] _containerConstructor = null; + private static readonly Attribute[] _runTimeFilter = new Attribute[] { DesignOnlyAttribute.No }; + private static readonly Attribute[] _designTimeFilter = new Attribute[] { DesignOnlyAttribute.Yes }; + private static WeakReference s_defaultSerializerRef; + + private Type[] GetContainerConstructor(IDesignerSerializationManager manager) + { + if (_containerConstructor == null) + { + _containerConstructor = new Type[] + { + GetReflectionTypeFromTypeHelper(manager, typeof(IContainer)) + }; + } + return _containerConstructor; + } + + /// + /// Retrieves a default static instance of this serializer. + /// + internal new static ComponentCodeDomSerializer Default + { + get + { + ComponentCodeDomSerializer defaultSerializer; + if (s_defaultSerializerRef != null) + { + defaultSerializer = s_defaultSerializerRef.Target as ComponentCodeDomSerializer; + if (defaultSerializer != null) + { + return defaultSerializer; + } + } + + defaultSerializer = new ComponentCodeDomSerializer(); + s_defaultSerializerRef = new WeakReference(defaultSerializer); + return defaultSerializer; + } + } + + /// + /// Determines if we can cache the results of serializing a component. + /// + private bool CanCacheComponent(IDesignerSerializationManager manager, object value, PropertyDescriptorCollection props) + { + IComponent comp = value as IComponent; + + if (comp != null) + { + if (comp.Site != null) + { + INestedSite nestedSite = comp.Site as INestedSite; + if (nestedSite != null && !string.IsNullOrEmpty(nestedSite.FullName)) + { + return false; + } + } + + if (props == null) + { + props = TypeDescriptor.GetProperties(comp); + } + foreach (PropertyDescriptor property in props) + { + if (typeof(IComponent).IsAssignableFrom(property.PropertyType) && + !property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden)) + { + MemberCodeDomSerializer memberSerializer = (MemberCodeDomSerializer)manager.GetSerializer(property.GetType(), typeof(MemberCodeDomSerializer)); + + if (memberSerializer != null && memberSerializer.ShouldSerialize(manager, value, property)) + { + return false; + } + } + } + } + + return true; + } + + /// + /// This method is invoked during deserialization to obtain an instance of an object. When this is called, an instance + /// of the requested type should be returned. This implementation calls base and then tries to deserialize design + /// time properties for the component. + /// + protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer) + { + + object instance = base.DeserializeInstance(manager, type, parameters, name, addToContainer); + + if (instance != null) + { + Trace("Deserializing design time properties for {0}", manager.GetName(instance)); + DeserializePropertiesFromResources(manager, instance, _designTimeFilter); + } + + return instance; + } + + /// + /// Serializes the given object into a CodeDom object. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + public override object Serialize(IDesignerSerializationManager manager, object value) + { + CodeStatementCollection statements = null; + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value); + using (TraceScope("ComponentCodeDomSerializer::Serialize")) + { + if (manager == null || value == null) + { + throw new ArgumentNullException(manager == null ? "manager" : "value"); + } + + if (IsSerialized(manager, value)) + { + Debug.Fail("Serialize is being called twice for the same component"); + return GetExpression(manager, value); + } + + // If the object is being inherited, we will will not emit a variable declaration. Also, we won't + // do any serialization at all if the object is privately inherited. + InheritanceLevel inheritanceLevel = InheritanceLevel.NotInherited; + InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(value)[typeof(InheritanceAttribute)]; + + if (inheritanceAttribute != null) + { + inheritanceLevel = inheritanceAttribute.InheritanceLevel; + } + + // First, skip everything if we're privately inherited. We cannot write any code that would affect this + // component. + TraceIf(inheritanceLevel == InheritanceLevel.InheritedReadOnly, "Skipping read only inherited component"); + if (inheritanceLevel != InheritanceLevel.InheritedReadOnly) + { + // Things we need to know: + // + // 1. What expression should we use for the left hand side + // a) already given to us via GetExpression? + // b) a local variable? + // c) a member variable? + // + // 2. Should we generate an init expression for this + // object? + // a) Inherited or existing expression: no + // b) otherwise, yes. + + statements = new CodeStatementCollection(); + CodeTypeDeclaration typeDecl = manager.Context[typeof(CodeTypeDeclaration)] as CodeTypeDeclaration; + RootContext rootCxt = manager.Context[typeof(RootContext)] as RootContext; + CodeExpression assignLhs = null; + CodeExpression assignRhs; + + // Defaults for components + bool generateLocal = false; + bool generateField = true; + bool generateObject = true; + bool isComplete = false; + + assignLhs = GetExpression(manager, value); + + if (assignLhs != null) + { + Trace("Existing expression for LHS of value"); + generateLocal = false; + generateField = false; + generateObject = false; + + // if we have an existing expression and this is not + // a sited component, do not serialize it. We need this for Everett / 1.0 + // backwards compat (even though it's wrong). + IComponent comp = value as IComponent; + if (comp != null && comp.Site == null) + { + // We were in a serialize content + // property and would still serialize it. This code reverses what the + // outer if block does for this specific case. We also need this + // for Everett / 1.0 backwards compat. + ExpressionContext expCxt = manager.Context[typeof(ExpressionContext)] as ExpressionContext; + if (expCxt == null || expCxt.PresetValue != value) + { + isComplete = true; + } + } + } + else + { + Trace("Creating LHS expression"); + if (inheritanceLevel == InheritanceLevel.NotInherited) + { + // See if there is a "GenerateMember" property. If so, + // we might want to generate a local variable. Otherwise, + // we want to generate a field. + PropertyDescriptor generateProp = props["GenerateMember"]; + if (generateProp != null && generateProp.PropertyType == typeof(bool) && !(bool)generateProp.GetValue(value)) + { + Trace("Object GenerateMember property wants a local variable"); + generateLocal = true; + generateField = false; + } + } + else + { + generateObject = false; + } + + if (rootCxt == null) + { + generateLocal = true; + generateField = false; + } + } + + // Push the component being serialized onto the stack. It may be handy to + // be able to discover this. + manager.Context.Push(value); + manager.Context.Push(statements); + + try + { + + string name = manager.GetName(value); + + string typeName = TypeDescriptor.GetClassName(value); + + // Output variable / field declarations if we need to + if ((generateField || generateLocal) && name != null) + { + if (generateField) + { + + if (inheritanceLevel == InheritanceLevel.NotInherited) + { + // We need to generate the field declaration. See if there is a modifiers property on + // the object. If not, look for a DefaultModifies, and finally assume it's private. + CodeMemberField field = new CodeMemberField(typeName, name); + PropertyDescriptor modifersProp = props["Modifiers"]; + MemberAttributes fieldAttrs; + + if (modifersProp == null) + { + modifersProp = props["DefaultModifiers"]; + } + + if (modifersProp != null && modifersProp.PropertyType == typeof(MemberAttributes)) + { + fieldAttrs = (MemberAttributes)modifersProp.GetValue(value); + } + else + { + TraceWarning("No Modifiers or DefaultModifiers property on component {0}. We must assume private.", name); + fieldAttrs = MemberAttributes.Private; + } + + field.Attributes = fieldAttrs; + typeDecl.Members.Add(field); + Trace("Field {0} {1} {2} created.", fieldAttrs, typeName, name); + } + + // Next, create a nice LHS for our pending assign statement, when we hook up the variable. + assignLhs = new CodeFieldReferenceExpression(rootCxt.Expression, name); + } + else + { + if (inheritanceLevel == InheritanceLevel.NotInherited) + { + CodeVariableDeclarationStatement local = new CodeVariableDeclarationStatement(typeName, name); + + statements.Add(local); + Trace("Local {0} {1} created.", typeName, name); + } + + assignLhs = new CodeVariableReferenceExpression(name); + } + } + + // Now output an object create if we need to. We always see if there is a + // type converter that can provide us guidance + + if (generateObject) + { + // Ok, now that we've decided if we have a local or a member variable, its now time to serialize the rest of the code. + // The first step is to create an assign statement to "new" the object. For that, we need to know if + // the component wants a special IContainer constructor or not. For that to be valid we must also know + // that we can get to an actual IContainer. + IContainer container = manager.GetService(typeof(IContainer)) as IContainer; + ConstructorInfo ctor = null; + if (container != null) + { + ctor = GetReflectionTypeHelper(manager, value).GetConstructor(BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, GetContainerConstructor(manager), null); + } + + if (ctor != null) + { + Trace("Component has IContainer constructor."); + assignRhs = new CodeObjectCreateExpression(typeName, new CodeExpression[] + { + SerializeToExpression(manager, container) + }); + } + else + { + // For compat reasons we ignore the isCompleteOld value here. + bool isCompleteOld; + assignRhs = SerializeCreationExpression(manager, value, out isCompleteOld); + Debug.Assert(isCompleteOld == isComplete, "CCDS Differing"); + } + + TraceErrorIf(assignRhs == null, "No RHS code assign for object {0}", value); + if (assignRhs != null) + { + if (assignLhs == null) + { + // We cannot do much more for this object. If isComplete is true, + // then the RHS now becomes our LHS. Otherwise, I'm afraid we have + // just failed to serialize this object. + if (isComplete) + { + assignLhs = assignRhs; + } + else + { + TraceError("Incomplete serialization of object, abandoning serialization."); + } + } + else + { + CodeAssignStatement assign = new CodeAssignStatement(assignLhs, assignRhs); + statements.Add(assign); + } + } + } + + if (assignLhs != null) + { + SetExpression(manager, value, assignLhs); + } + + // It should practically be an assert that isComplete is false, but someone may + // have an unusual component. + if (assignLhs != null && !isComplete) + { + // .NET CF needs us to verify that the ISupportInitialize interface exists + // (they do not support this interface and will modify their DSM to resolve the type to null). + + bool supportInitialize = (value is ISupportInitialize); + if (supportInitialize) + { + string fullName = typeof(ISupportInitialize).FullName; + supportInitialize = manager.GetType(fullName) != null; + } + Type reflectionType = null; + if (supportInitialize) + { + // Now verify that this control implements ISupportInitialize in the project target framework + // Don't use operator "is" but rather use IsAssignableFrom on the reflection types. + // We have other places where we use operator "is", for example "is IComponent" to generate + // specific CodeDOM objects, however we don't have cases of objects which were not an IComponent + // in a downlevel framework and became an IComponent in a newer framework, so I'm not replacing + // all instances of operator "is" by IsAssignableFrom. + reflectionType = GetReflectionTypeHelper(manager, value); + supportInitialize = GetReflectionTypeFromTypeHelper(manager, typeof(ISupportInitialize)).IsAssignableFrom(reflectionType); + } + + bool persistSettings = (value is IPersistComponentSettings) && ((IPersistComponentSettings)value).SaveSettings; + if (persistSettings) + { + string fullName = typeof(IPersistComponentSettings).FullName; + persistSettings = manager.GetType(fullName) != null; + } + if (persistSettings) + { + reflectionType = reflectionType ?? GetReflectionTypeHelper(manager, value); + persistSettings = GetReflectionTypeFromTypeHelper(manager, typeof(IPersistComponentSettings)).IsAssignableFrom(reflectionType); + } + // We implement statement caching only for the main code generation phase. We don't implement it for other + // serialization managers. How do we tell the difference? The main serialization manager exists as a service. + IDesignerSerializationManager mainManager = (IDesignerSerializationManager)manager.GetService(typeof(IDesignerSerializationManager)); + + if (supportInitialize) + { + Trace("Object implements ISupportInitialize."); + SerializeSupportInitialize(manager, statements, assignLhs, value, "BeginInit"); + } + + SerializePropertiesToResources(manager, statements, value, _designTimeFilter); + + // Writing out properties is expensive. But, we're very smart and we cache the results + // in ComponentCache. See if we have cached results. If so, use 'em. If not, generate + // code and then see if we can cache the results for later. + ComponentCache cache = (ComponentCache)manager.GetService(typeof(ComponentCache)); + ComponentCache.Entry entry = null; + if (cache == null) + { + IServiceContainer sc = (IServiceContainer)manager.GetService(typeof(IServiceContainer)); + + if (sc != null) + { + cache = new ComponentCache(manager); + sc.AddService(typeof(ComponentCache), cache); + } + } + else + { + if (manager == mainManager && cache != null && cache.Enabled) { + entry = cache[value]; + } + } + + if (entry == null || entry.Tracking) + { + // Pushing the entry here allows it to be found by the resource code dom serializer, + // which will add data to the ResourceBlob property on the entry. + if (entry == null) + { + entry = new ComponentCache.Entry(cache); + + // We cache components even if they're not valid so dependencies are + // still tracked correctly (see comment below). The problem is, we will create a + // new entry object even if there is still an existing one that is just invalid, and it + // might have dependencies that will be lost. + // we need to make sure we copy over any dependencies that are also tracked. + ComponentCache.Entry oldEntry = null; + oldEntry = cache.GetEntryAll(value); + if (oldEntry != null && oldEntry.Dependencies != null && oldEntry.Dependencies.Count > 0) + { + foreach(object dependency in oldEntry.Dependencies) + { + entry.AddDependency(dependency); + } + } + + } + entry.Component = value; + // we need to link the cached entry with its corresponding component right away, before it's put in the context + // see CodeDomSerializerBase.cs::GetExpression for usage + + // This entry will only be used if the valid bit is set. + // This is useful because we still need to setup depedency relationships + // between components even if they are not cached. See VSWhidbey 263053. + bool correctManager = manager == mainManager; + entry.Valid = correctManager && CanCacheComponent(manager, value, props); + + if (correctManager && cache != null && cache.Enabled) + { + manager.Context.Push(cache); + manager.Context.Push(entry); + } + + try + { + entry.Statements = new CodeStatementCollection(); + SerializeProperties(manager, entry.Statements, value, _runTimeFilter); + SerializeEvents(manager, entry.Statements, value, null); + + foreach (CodeStatement statement in entry.Statements) + { + CodeVariableDeclarationStatement local = statement as CodeVariableDeclarationStatement; + if (local != null) + { + entry.Tracking = true; + break; + } + } + + if (entry.Statements.Count > 0) + { + // if we added some statements, insert the comments + // + entry.Statements.Insert(0, new CodeCommentStatement(string.Empty)); + entry.Statements.Insert(0, new CodeCommentStatement(name)); + entry.Statements.Insert(0, new CodeCommentStatement(string.Empty)); + + // + // cache the statements for future usage if possible. We only do this for the main serialization manager, not + // for any other seriallization managers that may be calling us for undo or clipboard functions. + if (correctManager && cache != null && cache.Enabled) + { + cache[value] = entry; + } + } + } + finally + { + if (correctManager && cache != null && cache.Enabled) + { + Debug.Assert(manager.Context.Current == entry, "Context stack corrupted"); + manager.Context.Pop(); + manager.Context.Pop(); + } + } + } + else + { + // If we got a cache entry, we will need to take all the resources out of + // it and apply them too. + if ((entry.Resources != null || entry.Metadata != null) && cache != null && cache.Enabled) + { + ResourceCodeDomSerializer res = ResourceCodeDomSerializer.Default; + res.ApplyCacheEntry(manager, entry); + } + } + + // Regarless, apply statements. Either we created them or we got them + // out of the cache. + statements.AddRange(entry.Statements); + + if (persistSettings) + { + SerializeLoadComponentSettings(manager, statements, assignLhs, value); + } + + if (supportInitialize) + { + SerializeSupportInitialize(manager, statements, assignLhs, value, "EndInit"); + } + } + } + catch (CheckoutException) + { + throw; + } + catch (Exception ex) + { + manager.ReportError(ex); + } + finally + { + Debug.Assert(manager.Context.Current == statements, "Context stack corrupted"); + manager.Context.Pop(); + manager.Context.Pop(); + } + } + } + + return statements; + } + + /// + /// This emits a method invoke to IPersistComponentSettings.LoadComponentSettings. + /// + private void SerializeLoadComponentSettings(IDesignerSerializationManager manager, CodeStatementCollection statements, CodeExpression valueExpression, object value) + { + Trace("Emitting LoadComponentSettings"); + + CodeTypeReference type = new CodeTypeReference(typeof(IPersistComponentSettings)); + CodeCastExpression castExp = new CodeCastExpression(type, valueExpression); + CodeMethodReferenceExpression method = new CodeMethodReferenceExpression(castExp, "LoadComponentSettings"); + CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); + + methodInvoke.Method = method; + + CodeExpressionStatement statement = new CodeExpressionStatement(methodInvoke); + statement.UserData["statement-ordering"] = "end"; + + statements.Add(statement); + } + + /// + /// This emits a method invoke to ISupportInitialize. + /// + private void SerializeSupportInitialize(IDesignerSerializationManager manager, CodeStatementCollection statements, CodeExpression valueExpression, object value, string methodName) + { + Trace("Emitting {0}", methodName); + + CodeTypeReference type = new CodeTypeReference(typeof(ISupportInitialize)); + CodeCastExpression castExp = new CodeCastExpression(type, valueExpression); + CodeMethodReferenceExpression method = new CodeMethodReferenceExpression(castExp, methodName); + CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); + + methodInvoke.Method = method; + + CodeExpressionStatement statement = new CodeExpressionStatement(methodInvoke); + + if (methodName == "BeginInit") + { + statement.UserData["statement-ordering"] = "begin"; + } + else + { + statement.UserData["statement-ordering"] = "end"; + } + + statements.Add(statement); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentTypeCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentTypeCodeDomSerializer.cs new file mode 100644 index 00000000000..5423c024724 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentTypeCodeDomSerializer.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; +using System.CodeDom; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// This class performs the same tasks as a CodeDomSerializer only serializing an object through this class defines a new type. + /// + internal class ComponentTypeCodeDomSerializer : TypeCodeDomSerializer + { + private static object _initMethodKey = new object(); + private const string _initMethodName = "InitializeComponent"; + private static ComponentTypeCodeDomSerializer s_default; + + internal new static ComponentTypeCodeDomSerializer Default + { + get + { + if (s_default == null) + { + s_default = new ComponentTypeCodeDomSerializer(); + } + + return s_default; + } + } + + /// + /// This method returns the method to emit all of the initialization code to for the given member. + /// The default implementation returns an empty constructor. + /// + protected override CodeMemberMethod GetInitializeMethod(IDesignerSerializationManager manager, CodeTypeDeclaration typeDecl, object value) + { + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + + if (typeDecl == null) + { + throw new ArgumentNullException(nameof(typeDecl)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + CodeMemberMethod method = typeDecl.UserData[_initMethodKey] as CodeMemberMethod; + + if (method == null) + { + method = new CodeMemberMethod(); + method.Name = _initMethodName; + method.Attributes = MemberAttributes.Private; + typeDecl.UserData[_initMethodKey] = method; + + // Now create a ctor that calls this method. + CodeConstructor ctor = new CodeConstructor(); + + ctor.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), _initMethodName)); + typeDecl.Members.Add(ctor); + } + + return method; + } + + /// + /// This method returns an array of methods that need to be interpreted during deserialization. + /// The default implementation returns a single element array with the constructor in it. + /// + protected override CodeMemberMethod[] GetInitializeMethods(IDesignerSerializationManager manager, CodeTypeDeclaration typeDecl) + { + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + + if (typeDecl == null) + { + throw new ArgumentNullException(nameof(typeDecl)); + } + + foreach (CodeTypeMember member in typeDecl.Members) + { + CodeMemberMethod method = member as CodeMemberMethod; + + // Note: the order is important here for performance! + // method.Parameters causes OnMethodPopulateParameters callback and therefore it is much more + // expensive than method.Name.Equals + + if (method != null && method.Name.Equals(_initMethodName) && method.Parameters.Count == 0 ) + { + return new CodeMemberMethod[] + { + method + }; + } + } + + return new CodeMemberMethod[0]; + } + } +} + diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ContainerCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ContainerCodeDomSerializer.cs new file mode 100644 index 00000000000..5599b5a53e7 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ContainerCodeDomSerializer.cs @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CodeDom; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Reflection; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// This class is used to serialize things of type "IContainer". We route all containers + /// to the designer host's container. + /// + internal class ContainerCodeDomSerializer : CodeDomSerializer + { + private const string _containerName = "components"; + private static ContainerCodeDomSerializer s_defaultSerializer; + + /// + /// Retrieves a default static instance of this serializer. + /// + internal new static ContainerCodeDomSerializer Default + { + get + { + if (s_defaultSerializer == null) + { + s_defaultSerializer = new ContainerCodeDomSerializer(); + } + + return s_defaultSerializer; + } + } + + /// + /// We override this so we can always provide the correct container as a reference. + /// + protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer) + { + if (typeof(IContainer).IsAssignableFrom(type)) + { + object obj = manager.GetService(typeof(IContainer)); + + if (obj != null) + { + Trace("Returning IContainer service as container"); + manager.SetName(obj, name); + return obj; + } + } + + Trace("No IContainer service, creating default container."); + return base.DeserializeInstance(manager, type, parameters, name, addToContainer); + } + + /// + /// Serializes the given object into a CodeDom object. We serialize an IContainer by + /// declaring an IContainer member variable and then assigning a Container into it. + /// + public override object Serialize(IDesignerSerializationManager manager, object value) + { + // See if there is a type declaration on the stack. If there is, create a field representing + // the container member variable. + CodeTypeDeclaration typeDecl = manager.Context[typeof(CodeTypeDeclaration)] as CodeTypeDeclaration; + RootContext rootCxt = manager.Context[typeof(RootContext)] as RootContext; + CodeStatementCollection statements = new CodeStatementCollection(); + CodeExpression lhs; + + if (typeDecl != null && rootCxt != null) + { + CodeMemberField field = new CodeMemberField(typeof(IContainer), _containerName); + + field.Attributes = MemberAttributes.Private; + typeDecl.Members.Add(field); + lhs = new CodeFieldReferenceExpression(rootCxt.Expression, _containerName); + } + else + { + CodeVariableDeclarationStatement var = new CodeVariableDeclarationStatement(typeof(IContainer), _containerName); + + statements.Add(var); + lhs = new CodeVariableReferenceExpression(_containerName); + } + + // Now create the container + SetExpression(manager, value, lhs); + CodeObjectCreateExpression objCreate = new CodeObjectCreateExpression(typeof(Container)); + CodeAssignStatement assign = new CodeAssignStatement(lhs, objCreate); + + assign.UserData[nameof(IContainer)] = nameof(IContainer); + + statements.Add(assign); + return statements; + } + } +} + diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/DesignerSerializationManager.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/DesignerSerializationManager.cs index e53cfc2c609..7fbb97335c8 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/DesignerSerializationManager.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/DesignerSerializationManager.cs @@ -51,7 +51,7 @@ public DesignerSerializationManager() /// public DesignerSerializationManager(IServiceProvider provider) { - this.provider = provider ?? throw new ArgumentNullException("provider"); + this.provider = provider ?? throw new ArgumentNullException(nameof(provider)); preserveNames = true; validateRecycledTypes = true; } @@ -412,7 +412,7 @@ public object GetSerializer(Type objectType, Type serializerType) { if (serializerType == null) { - throw new ArgumentNullException("serializerType"); + throw new ArgumentNullException(nameof(serializerType)); } object serializer = null; @@ -624,7 +624,7 @@ private PropertyDescriptor WrapProperty(PropertyDescriptor property, object owne { if (property == null) { - throw new ArgumentNullException("property"); + throw new ArgumentNullException(nameof(property)); } // owner can be null for static properties. return new WrappedPropertyDescriptor(property, owner); @@ -766,7 +766,7 @@ object IDesignerSerializationManager.GetInstance(string name) object instance = null; if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } CheckSession(); @@ -798,7 +798,7 @@ string IDesignerSerializationManager.GetName(object value) string name = null; if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } CheckSession(); @@ -891,8 +891,8 @@ internal ArrayList SerializationProviders void IDesignerSerializationManager.SetName(object instance, string name) { CheckSession(); - if (instance == null) throw new ArgumentNullException("instance"); - if (name == null) throw new ArgumentNullException("name"); + if (instance == null) throw new ArgumentNullException(nameof(instance)); + if (name == null) throw new ArgumentNullException(nameof(name)); if (instancesByName == null) { diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/EnumCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/EnumCodeDomSerializer.cs new file mode 100644 index 00000000000..0ad047ee9ce --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/EnumCodeDomSerializer.cs @@ -0,0 +1,115 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CodeDom; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Reflection; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// Code model serializer for enum types. + /// + internal class EnumCodeDomSerializer : CodeDomSerializer + { + private static EnumCodeDomSerializer s_defaultSerializer; + + /// + /// Retrieves a default static instance of this serializer. + /// + internal new static EnumCodeDomSerializer Default + { + get + { + if (s_defaultSerializer == null) + { + s_defaultSerializer = new EnumCodeDomSerializer(); + } + return s_defaultSerializer; + } + } + + /// + /// Serializes the given object into a CodeDom object. + /// + public override object Serialize(IDesignerSerializationManager manager, object value) + { + CodeExpression expression = null; + + using (TraceScope("EnumCodeDomSerializer::" + nameof(Serialize))) + { + Trace("Type: {0}", (value == null ? "(null)" : value.GetType().Name)); + if (value is Enum) + { + bool needCast = false; + Enum[] values; + TypeConverter converter = TypeDescriptor.GetConverter(value); + if (converter != null && converter.CanConvertTo(typeof(Enum[]))) + { + values = (Enum[])converter.ConvertTo(value, typeof(Enum[])); + needCast = (values.Length > 1); + } + else + { + values = new Enum[] {(Enum)value}; + needCast = true; + } + + // EnumConverter (and anything that is overridden to support enums) + // should be providing us a conversion to Enum[] for flag styles. + // If it doesn't, we will emit a warning and just do a cast from the enum value. + + CodeTypeReferenceExpression enumType = new CodeTypeReferenceExpression(value.GetType()); + + // If names is of length 1, then this is a simple field reference. Otherwise, + // it is an or-d combination of expressions. + // + TraceIf(values.Length == 1, "Single field entity."); + TraceIf(values.Length > 1, "Multi field entity."); + + // We now need to serialize the enum terms as fields. We new up an EnumConverter to do + // that. We cannot use the type's own converter since it might have a different string + // representation for its values. Hardcoding is okay in this case, since all we want is + // the enum's field name. Simply doing ToString() will not give us any validation. + TypeConverter enumConverter = new EnumConverter(value.GetType()); + foreach (Enum term in values) + { + string termString = (enumConverter != null) ? enumConverter.ConvertToString(term) : null; + CodeExpression newExpression = !String.IsNullOrEmpty(termString) ? new CodeFieldReferenceExpression(enumType, termString) : null; + + if (newExpression != null) + { + if (expression == null) + { + expression = newExpression; + } + else + { + expression = new CodeBinaryOperatorExpression(expression, CodeBinaryOperatorType.BitwiseOr, newExpression); + } + } + } + + // If we had to combine multiple names, wrap the result in an appropriate cast. + // + if (expression != null && needCast) + { + expression = new CodeCastExpression(value.GetType(), expression); + } + } + else + { + Debug.Fail("Enum serializer called for non-enum object."); + TraceError("Enum serializer called for non-enum object {0}", (value == null ? "(null)" : value.GetType().Name)); + } + } + + return expression; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/EventMemberCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/EventMemberCodeDomSerializer.cs new file mode 100644 index 00000000000..7f2a3cd1f00 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/EventMemberCodeDomSerializer.cs @@ -0,0 +1,109 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CodeDom; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Reflection; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// A MemberCodeDomSerializer for events. + /// + internal sealed class EventMemberCodeDomSerializer : MemberCodeDomSerializer + { + private static CodeThisReferenceExpression _thisRef = new CodeThisReferenceExpression(); + private static EventMemberCodeDomSerializer s_default; + + internal static EventMemberCodeDomSerializer Default + { + get + { + if (s_default == null) + { + s_default = new EventMemberCodeDomSerializer(); + } + + return s_default; + } + } + + /// + /// This method actually performs the serialization. When the member is serialized + /// the necessary statements will be added to the statements collection. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + public override void Serialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements) + { + EventDescriptor eventToSerialize = descriptor as EventDescriptor; + + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + if (eventToSerialize == null) + { + throw new ArgumentNullException(nameof(descriptor)); + } + if (statements == null) + { + throw new ArgumentNullException(nameof(statements)); + } + + try + { + IEventBindingService eventBindings = (IEventBindingService)manager.GetService(typeof(IEventBindingService)); + + // If the IEventBindingService is not available, we don't throw - we just don't do anything. + if (eventBindings != null) + { + PropertyDescriptor prop = eventBindings.GetEventProperty(eventToSerialize); + string methodName = (string)prop.GetValue(value); + + if (methodName != null) + { + CodeDomSerializer.Trace("Event {0} bound to {1}", eventToSerialize.Name, methodName); + CodeExpression eventTarget = SerializeToExpression(manager, value); + CodeDomSerializer.TraceWarningIf(eventTarget == null, "Object has no name and no propery ref in context so we cannot serialize events: {0}", value); + if (eventTarget != null) + { + CodeTypeReference delegateTypeRef = new CodeTypeReference(eventToSerialize.EventType); + CodeDelegateCreateExpression delegateCreate = new CodeDelegateCreateExpression(delegateTypeRef, _thisRef, methodName); + CodeEventReferenceExpression eventRef = new CodeEventReferenceExpression(eventTarget, eventToSerialize.Name); + CodeAttachEventStatement attach = new CodeAttachEventStatement(eventRef, delegateCreate); + + attach.UserData[typeof(Delegate)] = eventToSerialize.EventType; + statements.Add(attach); + } + } + } + } + catch (Exception e) + { + // Since we usually go through reflection, don't + // show what our engine does, show what caused + // the problem. + // + if (e is TargetInvocationException) + { + e = e.InnerException; + } + + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerPropertyGenFailed, eventToSerialize.Name, e.Message), manager)); + } + } + + /// + /// This method returns true if the given member descriptor should be serialized, + /// or false if there is no need to serialize the member. + /// + public override bool ShouldSerialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor) => true; + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ExpressionContext.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ExpressionContext.cs index 9688d0684b4..051de753676 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ExpressionContext.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ExpressionContext.cs @@ -16,27 +16,14 @@ namespace System.ComponentModel.Design.Serialization /// public sealed class ExpressionContext { - private readonly CodeExpression _expression; - private readonly Type _expressionType; - private readonly object _owner; - private readonly object _presetValue; - - /// - /// Creates a new expression context. - /// public ExpressionContext(CodeExpression expression, Type expressionType, object owner, object presetValue) { - // To make this public, we cannot have random special cases for what the args mean. - Debug.Assert(expression != null && expressionType != null && owner != null, "Obsolete use of expression context."); - _expression = expression ?? throw new ArgumentNullException("expression"); - _expressionType = expressionType ?? throw new ArgumentNullException("expressionType"); - _owner = owner ?? throw new ArgumentNullException("owner"); - _presetValue = presetValue; + Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + ExpressionType = expressionType ?? throw new ArgumentNullException(nameof(expressionType)); + Owner = owner ?? throw new ArgumentNullException(nameof(owner)); + PresetValue = presetValue; } - /// - /// Creates a new expression context. - /// public ExpressionContext(CodeExpression expression, Type expressionType, object owner) : this(expression, expressionType, owner, null) { } @@ -44,38 +31,42 @@ public ExpressionContext(CodeExpression expression, Type expressionType, object /// /// The expression this context represents. /// - public CodeExpression Expression - { - get => _expression; - } + public CodeExpression Expression { get; } /// - /// The type of the expression. This can be used to determine if a cast is needed when assigning to the expression. + /// The type of the expression. This can be used to determine if a + /// cast is needed when assigning to the expression. /// - public Type ExpressionType - { - get => _expressionType; - } + public Type ExpressionType { get; } /// - /// The object owning this expression. For example, if the expression was a property reference to button1's Text property, Owner would return button1. + /// The object owning this expression. For example, if the expression + /// was a property reference to button1's Text property, Owner would + /// return button1. /// - public object Owner - { - get => _owner; - } + public object Owner { get; } /// - /// Contains the preset value of an expression, should one exist. For example, if the expression is a property reference expression referring to the Controls property of a button, PresetValue will contain the instance of Controls property because the property is read-only and preset by the object to contain a value. On the other hand, a property such as Text or Visible does not have a preset value and therefore the PresetValue property will return null. Serializers can use this information to guide serialization. For example, take the following two snippts of code: + /// Contains the preset value of an expression, should one exist. + /// For example, if the expression is a property reference expression + /// referring to the Controls property of a button, PresetValue will + /// contain the instance of Controls property because the property is + /// read-only and preset by the object to contain a value. On the other + /// hand, a property such as Text or Visible does not have a preset + /// value and therefore the PresetValue property will return null. + /// Serializers can use this information to guide serialization. + /// For example, take the following two snippts of code: /// Padding p = new Padding(); /// p.Left = 5; /// button1.Padding = p; /// button1.Padding.Left = 5; - /// The serializer of the Padding class needs to know if it should generate the first or second form. The first form would be generated by default. The second form will only be generated if there is an ExpressionContext on the stack that contains a PresetValue equal to the value of the Padding object currently being serialized. + /// The serializer of the Padding class needs to know if it should + /// generate the first or second form. The first form would be + /// generated by default. The second form will only be generated + /// if there is an ExpressionContext on the stack that contains a + /// PresetValue equal to the value of the Padding object currently + /// being serialized. /// - public object PresetValue - { - get => _presetValue; - } + public object PresetValue { get; } } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/PrimitiveCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/PrimitiveCodeDomSerializer.cs new file mode 100644 index 00000000000..7be8a164c3e --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/PrimitiveCodeDomSerializer.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Reflection; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// Code model serializer for primitive types. + /// + internal class PrimitiveCodeDomSerializer : CodeDomSerializer + { + private static PrimitiveCodeDomSerializer s_defaultSerializer; + + /// + /// Retrieves a default static instance of this serializer. + /// + internal new static PrimitiveCodeDomSerializer Default + { + get + { + if (s_defaultSerializer == null) + { + s_defaultSerializer = new PrimitiveCodeDomSerializer(); + } + return s_defaultSerializer; + } + } + + /// + /// Serializes the given object into a CodeDom object. + /// + public override object Serialize(IDesignerSerializationManager manager, object value) + { + using (TraceScope("PrimitiveCodeDomSerializer::" + nameof(Serialize))) + { + Trace("Value: {0}", (value == null ? "(null)" : value.ToString())); + } + + CodeExpression expression = new CodePrimitiveExpression(value); + + if (value != null) + { + if (value is string) + { + string stringValue = value as string; + if (stringValue != null && stringValue.Length > 200) + { + expression = SerializeToResourceExpression(manager, stringValue); + } + } + else + { + // Generate a cast for all other types because we won't parse them properly otherwise + // because we won't know to convert them to the narrow form. + expression = new CodeCastExpression(new CodeTypeReference(value.GetType()), expression); + } + } + + return expression; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/PropertyMemberCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/PropertyMemberCodeDomSerializer.cs new file mode 100644 index 00000000000..e7e3862c951 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/PropertyMemberCodeDomSerializer.cs @@ -0,0 +1,511 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CodeDom; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Reflection; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// A MemberCodeDomSerializer for properties. + /// + internal sealed class PropertyMemberCodeDomSerializer : MemberCodeDomSerializer + { + private static PropertyMemberCodeDomSerializer s_default; + + internal static PropertyMemberCodeDomSerializer Default + { + get + { + if (s_default == null) + { + s_default = new PropertyMemberCodeDomSerializer(); + } + + return s_default; + } + } + + /// + /// This retrieves the value of this property. If the property returns false + /// from ShouldSerializeValue (indicating the ambient value for this property) + /// This will look for an AmbientValueAttribute and use it if it can. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private object GetPropertyValue(IDesignerSerializationManager manager, PropertyDescriptor property, object value, out bool validValue) + { + object propertyValue = null; + validValue = true; + try + { + if (!property.ShouldSerializeValue(value)) + { + // We aren't supposed to be serializing this property, but we decided to do + // it anyway. Check the property for an AmbientValue attribute and if we + // find one, use it's value to serialize. + AmbientValueAttribute attr = (AmbientValueAttribute)property.Attributes[typeof(AmbientValueAttribute)]; + + if (attr != null) + { + return attr.Value; + } + else + { + DefaultValueAttribute defAttr = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)]; + + if (defAttr != null) + { + return defAttr.Value; + } + else + { + // nope, we're not valid... + // + validValue = false; + } + } + } + propertyValue = property.GetValue(value); + } + catch (Exception e) + { + // something failed -- we don't have a valid value + validValue = false; + + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerPropertyGenFailed, property.Name, e.Message), manager)); + } + + if ((propertyValue != null) && (!propertyValue.GetType().IsValueType) && !(propertyValue is Type)) + { + // DevDiv2 (Dev11) bug 187766 : property whose type implements ISupportInitialize is not + // serialized with Begin/EndInit. + Type type = TypeDescriptor.GetProvider(propertyValue).GetReflectionType(typeof(object)); + if (!type.IsDefined(typeof(ProjectTargetFrameworkAttribute), false)) + { + // TargetFrameworkProvider is not attached + TypeDescriptionProvider typeProvider = CodeDomSerializerBase.GetTargetFrameworkProvider(manager, propertyValue); + if (typeProvider != null) + { + TypeDescriptor.AddProvider(typeProvider, propertyValue); + } + } + } + + return propertyValue; + + } + + /// + /// This method actually performs the serialization. When the member is serialized + /// the necessary statements will be added to the statements collection. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + public override void Serialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements) + { + PropertyDescriptor propertyToSerialize = descriptor as PropertyDescriptor; + + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + if (propertyToSerialize == null) + { + throw new ArgumentNullException(nameof(descriptor)); + } + if (statements == null) + { + throw new ArgumentNullException(nameof(statements)); + } + + try + { + ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)propertyToSerialize.Attributes[typeof(ExtenderProvidedPropertyAttribute)]; + bool isExtender = (exAttr != null && exAttr.Provider != null); + bool serializeContents = propertyToSerialize.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content); + + CodeDomSerializer.Trace("Serializing property {0}", propertyToSerialize.Name); + if (serializeContents) + { + SerializeContentProperty(manager, value, propertyToSerialize, isExtender, statements); + } + else if (isExtender) + { + SerializeExtenderProperty(manager, value, propertyToSerialize, statements); + } + else + { + SerializeNormalProperty(manager, value, propertyToSerialize, statements); + } + } + catch (Exception e) + { + // Since we usually go through reflection, don't + // show what our engine does, show what caused + // the problem. + if (e is TargetInvocationException) + { + e = e.InnerException; + } + + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerPropertyGenFailed, propertyToSerialize.Name, e.Message), manager)); + } + } + + /// + /// This serializes the given property on this object as a content property. + /// + private void SerializeContentProperty(IDesignerSerializationManager manager, object value, PropertyDescriptor property, bool isExtender, CodeStatementCollection statements) + { + CodeDomSerializer.Trace("Property is marked as Visibility.Content. Recursing."); + + bool validValue; + object propertyValue = GetPropertyValue(manager, property, value, out validValue); + + // For persist contents objects, we don't just serialize the properties on the object; we + // serialize everything. + // + CodeDomSerializer serializer = null; + + if (propertyValue == null) + { + CodeDomSerializer.TraceError("Property {0} is marked as Visibility.Content but it is returning null.", property.Name); + + string name = manager.GetName(value); + + if (name == null) + { + name = value.GetType().FullName; + } + + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerNullNestedProperty, name, property.Name), manager)); + } + else + { + serializer = (CodeDomSerializer)manager.GetSerializer(propertyValue.GetType(), typeof(CodeDomSerializer)); + if (serializer != null) + { + // Create a property reference expression and push it on the context stack. + // This allows the serializer to gain some context as to what it should be + // serializing. + CodeExpression target = SerializeToExpression(manager, value); + + if (target == null) + { + CodeDomSerializer.TraceWarning("Unable to convert value to expression object"); + } + else + { + CodeExpression propertyRef = null; + + if (isExtender) + { + CodeDomSerializer.Trace("Content property is an extender."); + ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)property.Attributes[typeof(ExtenderProvidedPropertyAttribute)]; + + // Extender properties are method invokes on a target "extender" object. + // + CodeExpression extender = SerializeToExpression(manager, exAttr.Provider); + CodeExpression extended = SerializeToExpression(manager, value); + + CodeDomSerializer.TraceWarningIf(extender == null, "Extender object {0} could not be serialized.", manager.GetName(exAttr.Provider)); + CodeDomSerializer.TraceWarningIf(extended == null, "Extended object {0} could not be serialized.", manager.GetName(value)); + if (extender != null && extended != null) + { + CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(extender, "Get" + property.Name); + CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); + methodInvoke.Method = methodRef; + methodInvoke.Parameters.Add(extended); + propertyRef = methodInvoke; + } + } + else + { + propertyRef = new CodePropertyReferenceExpression(target, property.Name); + } + + if (propertyRef != null) + { + ExpressionContext tree = new ExpressionContext(propertyRef, property.PropertyType, value, propertyValue); + manager.Context.Push(tree); + + object result = null; + + try + { + SerializeAbsoluteContext absolute = (SerializeAbsoluteContext)manager.Context[typeof(SerializeAbsoluteContext)]; + + if (IsSerialized(manager, propertyValue, absolute != null)) + { + result = GetExpression(manager, propertyValue); + } + else + { + result = serializer.Serialize(manager, propertyValue); + } + } + finally + { + Debug.Assert(manager.Context.Current == tree, "Serializer added a context it didn't remove."); + manager.Context.Pop(); + } + + CodeStatementCollection csc = result as CodeStatementCollection; + + if (csc != null) + { + foreach (CodeStatement statement in csc) + { + statements.Add(statement); + } + } + else + { + CodeStatement cs = result as CodeStatement; + + if (cs != null) + { + statements.Add(cs); + } + } + } + } + } + else + { + CodeDomSerializer.TraceError("Property {0} is marked as Visibilty.Content but there is no serializer for it.", property.Name); + + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerNoSerializerForComponent, property.PropertyType.FullName), manager)); + } + } + } + + /// + /// This serializes the given property on this object. + /// + private void SerializeExtenderProperty(IDesignerSerializationManager manager, object value, PropertyDescriptor property, CodeStatementCollection statements) + { + AttributeCollection attributes = property.Attributes; + + using (CodeDomSerializer.TraceScope("PropertyMemberCodeDomSerializer::" + nameof(SerializeExtenderProperty))) + { + ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)attributes[typeof(ExtenderProvidedPropertyAttribute)]; + + // Extender properties are method invokes on a target "extender" object. + // + CodeExpression extender = SerializeToExpression(manager, exAttr.Provider); + CodeExpression extended = SerializeToExpression(manager, value); + + CodeDomSerializer.TraceWarningIf(extender == null, "Extender object {0} could not be serialized.", manager.GetName(exAttr.Provider)); + CodeDomSerializer.TraceWarningIf(extended == null, "Extended object {0} could not be serialized.", manager.GetName(value)); + if (extender != null && extended != null) + { + CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(extender, "Set" + property.Name); + bool validValue; + object propValue = GetPropertyValue(manager, property, value, out validValue); + CodeExpression serializedPropertyValue = null; + + // Serialize the value of this property into a code expression. If we can't get one, + // then we won't serialize the property. + if (validValue) + { + ExpressionContext tree = null; + + if (propValue != value) { + // make sure the value isn't the object or we'll end up printing + // this property instead of the value. + tree = new ExpressionContext(methodRef, property.PropertyType, value); + manager.Context.Push(tree); + } + + try + { + serializedPropertyValue = SerializeToExpression(manager, propValue); + } + finally + { + if (tree != null) + { + Debug.Assert(manager.Context.Current == tree, "Context stack corrupted."); + manager.Context.Pop(); + } + } + } + + if (serializedPropertyValue != null) + { + CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); + + methodInvoke.Method = methodRef; + methodInvoke.Parameters.Add(extended); + methodInvoke.Parameters.Add(serializedPropertyValue); + statements.Add(methodInvoke); + } + } + } + } + + /// + /// This serializes the given property on this object. + /// + private void SerializeNormalProperty(IDesignerSerializationManager manager, object value, PropertyDescriptor property, CodeStatementCollection statements) + { + + using (CodeDomSerializer.TraceScope("CodeDomSerializer::" + nameof(SerializeProperty))) + { + CodeExpression target = SerializeToExpression(manager, value); + + CodeDomSerializer.TraceWarningIf(target == null, "Unable to serialize target for property {0}", property.Name); + if (target != null) + { + CodeExpression propertyRef = new CodePropertyReferenceExpression(target, property.Name); + + CodeExpression serializedPropertyValue = null; + + // First check for a member relationship service to see if this property + // is related to another member. If it is, then we will use that + // relationship to construct the property assign statement. if + // it isn't, then we're serialize ourselves. + MemberRelationshipService relationships = manager.GetService(typeof(MemberRelationshipService)) as MemberRelationshipService; + + if (relationships != null) + { + MemberRelationship relationship = relationships[value, property]; + + if (relationship != MemberRelationship.Empty) + { + CodeExpression rhsTarget = SerializeToExpression(manager, relationship.Owner); + + if (rhsTarget != null) + { + serializedPropertyValue = new CodePropertyReferenceExpression(rhsTarget, relationship.Member.Name); + } + } + } + + if (serializedPropertyValue == null) + { + // Serialize the value of this property into a code expression. If we can't get one, + // then we won't serialize the property. + // + bool validValue; + object propValue = GetPropertyValue(manager, property, value, out validValue); + + if (validValue) + { + ExpressionContext tree = null; + + if (propValue != value) + { + // make sure the value isn't the object or we'll end up printing + // this property instead of the value. + tree = new ExpressionContext(propertyRef, property.PropertyType, value); + manager.Context.Push(tree); + } + + try + { + serializedPropertyValue = SerializeToExpression(manager, propValue); + } + finally + { + if (tree != null) + { + Debug.Assert(manager.Context.Current == tree, "Context stack corrupted."); + manager.Context.Pop(); + } + } + } + } + + if (serializedPropertyValue != null) + { + CodeAssignStatement assign = new CodeAssignStatement(propertyRef, serializedPropertyValue); + statements.Add(assign); + } + } + } + } + + /// + /// This method returns true if the given member descriptor should be serialized, + /// or false if there is no need to serialize the member. + /// + public override bool ShouldSerialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor) + { + + PropertyDescriptor propertyToSerialize = descriptor as PropertyDescriptor; + + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + if (propertyToSerialize == null) + { + throw new ArgumentNullException(nameof(descriptor)); + } + + bool shouldSerializeProperty = propertyToSerialize.ShouldSerializeValue(value); + + if (!shouldSerializeProperty) + { + SerializeAbsoluteContext absolute = (SerializeAbsoluteContext)manager.Context[typeof(SerializeAbsoluteContext)]; + + if (absolute != null && absolute.ShouldSerialize(propertyToSerialize)) + { + + // For ReadOnly properties, we only want to override the value returned from + // ShouldSerializeValue() if the property is marked with DesignerSerializationVisibilityAttribute(Content). + // Consider the case of a property with just a getter - we only want to serialize those + // if they're marked in this way (see ReflectPropertyDescriptor::ShouldSerializeValue()) + if (!propertyToSerialize.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content)) + { + shouldSerializeProperty = false; // it's already false at this point, but this is clearer. + } + else + { + shouldSerializeProperty = true; // Always serialize difference properties + } + } + } + + if (shouldSerializeProperty) + { + bool isDesignTime = propertyToSerialize.Attributes.Contains(DesignOnlyAttribute.Yes); + if (!isDesignTime) + { + return true; + } + } + + // If we don't have to serialize, we need to make sure there isn't a member + // relationship with this property. If there is, we still need to serialize. + + MemberRelationshipService relationships = manager.GetService(typeof(MemberRelationshipService)) as MemberRelationshipService; + + if (relationships != null) + { + MemberRelationship relationship = relationships[value, descriptor]; + + if (relationship != MemberRelationship.Empty) + { + return true; + } + } + + + return false; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ResourceCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ResourceCodeDomSerializer.cs index 7ef5a79c6dd..f3b0e53ccb3 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ResourceCodeDomSerializer.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ResourceCodeDomSerializer.cs @@ -23,13 +23,16 @@ internal class ResourceCodeDomSerializer : CodeDomSerializer /// /// Retrieves a default static instance of this serializer. /// - internal static ResourceCodeDomSerializer GetDefault() + internal new static ResourceCodeDomSerializer Default { - if (s_defaultSerializer == null) + get { - s_defaultSerializer = new ResourceCodeDomSerializer(); + if (s_defaultSerializer == null) + { + s_defaultSerializer = new ResourceCodeDomSerializer(); + } + return s_defaultSerializer; } - return s_defaultSerializer; } public override string GetTargetComponentName(CodeStatement statement, CodeExpression expression, Type type) @@ -151,8 +154,14 @@ private SerializationResourceManager CreateResourceManager(IDesignerSerializatio /// protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer) { - if (manager == null) throw new ArgumentNullException("manager"); - if (type == null) throw new ArgumentNullException("type"); + if (manager == null) + { + throw new ArgumentNullException(nameof(manager)); + } + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } if (name != null && name.Equals(ResourceManagerName) && typeof(ResourceManager).IsAssignableFrom(type)) { @@ -373,7 +382,7 @@ public object SerializeInvariant(IDesignerSerializationManager manager, object v /// public void SerializeMetadata(IDesignerSerializationManager manager, string name, object value, bool shouldSerializeValue) { - using (TraceScope("ResourceCodeDomSerializer::SerializeMetadata")) + using (TraceScope("ResourceCodeDomSerializer::" + nameof(SerializeMetadata))) { Trace("Name: {0}", name); Trace("Value: {0}", (value == null ? "(null)" : value.ToString())); @@ -387,13 +396,7 @@ public void SerializeMetadata(IDesignerSerializationManager manager, string name /// public void WriteResource(IDesignerSerializationManager manager, string name, object value) { - using (TraceScope("ResourceCodeDomSerializer::WriteResource")) - { - Trace("Name: {0}", name); - Trace("Value: {0}", (value == null ? "(null)" : value.ToString())); - SerializationResourceManager sm = GetResourceManager(manager); - sm.SetValue(manager, name, value, false, false, true, false); - } + SetValueUsingCommonTraceScope(manager, name, value, nameof(WriteResource), false, false, true, false); } /// @@ -401,12 +404,18 @@ public void WriteResource(IDesignerSerializationManager manager, string name, ob /// public void WriteResourceInvariant(IDesignerSerializationManager manager, string name, object value) { - using (TraceScope("ResourceCodeDomSerializer::WriteResourceInvariant")) + SetValueUsingCommonTraceScope(manager, name, value, nameof(WriteResourceInvariant), true, true, true, false); + } + + private void SetValueUsingCommonTraceScope(IDesignerSerializationManager manager, string name, object value, string calleeName, + bool forceInvariant, bool shouldSerializeInvariant, bool ensureInvariant, bool applyingCachedResources) + { + using (TraceScope("ResourceCodeDomSerializer::" + calleeName)) { Trace("Name: {0}", name); Trace("Value: {0}", (value == null ? "(null)" : value.ToString())); SerializationResourceManager sm = GetResourceManager(manager); - sm.SetValue(manager, name, value, true, true, true, false); + sm.SetValue(manager, name, value, forceInvariant, shouldSerializeInvariant, ensureInvariant, applyingCachedResources); } } @@ -461,8 +470,6 @@ internal class SerializationResourceManager : ComponentResourceManager private Hashtable _metadata; private Hashtable _mergedMetadata; private object _rootComponent; - private bool _declarationAdded = false; - private bool _expressionAdded = false; private Hashtable _propertyFillAdded; private bool _invariantCultureResourcesDirty = false; private bool _metadataResourcesDirty = false; @@ -478,20 +485,12 @@ public SerializationResourceManager(IDesignerSerializationManager manager) /// /// State the serializers use to determine if the declaration of this resource manager has been performed. This is just per-document state we keep; we do not actually care about this value. /// - public bool DeclarationAdded - { - get => _declarationAdded; - set => _declarationAdded = value; - } + public bool DeclarationAdded { get; set; } = false; /// /// When a declaration is added, we also setup an expression other serializers can use to reference our resource declaration. This bit tracks if we have setup this expression yet. Note that the expression and declaration may be added at diffrerent times, if the declaration was added by a cached component. /// - public bool ExpressionAdded - { - get => _expressionAdded; - set => _expressionAdded = value; - } + public bool ExpressionAdded { get; set; } = false; /// /// The language we should be localizing into. @@ -953,7 +952,7 @@ public override ResourceSet GetResourceSet(CultureInfo culture, bool createIfNot { if (culture == null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } CultureInfo lastCulture; @@ -1327,7 +1326,6 @@ public string SetValue(IDesignerSerializationManager manager, ExpressionContext private class CodeDomResourceSet : ResourceSet { - public CodeDomResourceSet() { } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/RootContext.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/RootContext.cs index 9017e1854ea..123c7f8096c 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/RootContext.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/RootContext.cs @@ -3,39 +3,35 @@ // See the LICENSE file in the project root for more information. using System.CodeDom; + namespace System.ComponentModel.Design.Serialization { /// - /// The root context is added by a type code dom serailizier to provide a definiton of the "root" object. + /// The root context is added by a type code dom serailizier to provide a + /// definiton of the "root" object. /// public sealed class RootContext { - private readonly CodeExpression _expression; - private readonly object _value; - /// - /// This object can be placed on the context stack to represent the object that is the root of the serialization hierarchy. In addition to this instance, the RootContext also contains an expression that can be used to reference the RootContext. + /// This object can be placed on the context stack to represent the + /// object that is the root of the serialization hierarchy. In addition + /// to this instance, the RootContext also contains an expression that + /// can be used to reference the RootContext. /// public RootContext(CodeExpression expression, object value) { - _expression = expression ?? throw new ArgumentNullException("expression"); - _value = value ?? throw new ArgumentNullException("value"); + Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + Value = value ?? throw new ArgumentNullException(nameof(value)); } /// - /// The expression representing the root object in the object graph. + /// The expression representing the root object in the object graph. /// - public CodeExpression Expression - { - get => _expression; - } + public CodeExpression Expression { get; } /// - /// The root object of the object graph. + /// The root object of the object graph. /// - public object Value - { - get => _value; - } + public object Value { get; } } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/SerializeAbsoluteContext.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/SerializeAbsoluteContext.cs index a9d99a9ba96..05ad465d3db 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/SerializeAbsoluteContext.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/SerializeAbsoluteContext.cs @@ -5,40 +5,47 @@ namespace System.ComponentModel.Design.Serialization { /// - /// The ComponentSerializationService supports "absolute" serialization, where instead of just serializing values that differ from an object's default values, all values are serialized in such a way as to be able to reset values to their defaults for objects that may have already been initialized. When a component serialization service wishes to indicate this to CodeDomSerializer objects, it will place a SerializeAbsoluteContext on the context stack. The member in this context may be null, to indicate that all members are serialized, or a member indicating that only a specific member is being serialized at this time. + /// The ComponentSerializationService supports "absolute" serialization, + /// where instead of just serializing values that differ from an object's + // default values, all values are serialized in such a way as to be able + /// to reset values to their defaults for objects that may have already + /// been initialized. When a component serialization service wishes to + /// indicate this to CodeDomSerializer objects, it will place a + /// SerializeAbsoluteContext on the context stack. The member in this + /// context may be null, to indicate that all members are serialized, or + /// a member indicating that only a specific member is being serialized at + /// this time. /// public sealed class SerializeAbsoluteContext { - private readonly MemberDescriptor _member; /// - /// Creeates a new SerializeAbsoluteContext. Member can be null or omitted to indicate this context should be used for all members. + /// Creeates a new SerializeAbsoluteContext. Member can be null or + /// omitted to indicate this context should be used for all members. /// public SerializeAbsoluteContext() { } /// - /// Creeates a new SerializeAbsoluteContext. Member can be null or omitted to indicate this context should be used for all members. + /// Creeates a new SerializeAbsoluteContext. Member can be null or + /// omitted to indicate this context should be used for all members. /// public SerializeAbsoluteContext(MemberDescriptor member) { - _member = member; + Member = member; } /// /// This property returns the member this context is bound to. It may be null to indicate the context is bound to all members of an object. /// - public MemberDescriptor Member - { - get => _member; - } + public MemberDescriptor Member { get; } /// /// Returns true if the given member should be serialized in this context. /// public bool ShouldSerialize(MemberDescriptor member) { - return (_member == null || _member == member); + return Member == null || Member == member; } } } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/StatementContext.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/StatementContext.cs index f8a658e7273..659ceb462c7 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/StatementContext.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/StatementContext.cs @@ -9,7 +9,16 @@ namespace System.ComponentModel.Design.Serialization { /// - /// This object can be placed on the context stack to provide a place for statements to be serialized into. Normally, statements are serialized into whatever statement collection that is on the context stack. You can modify this behavior by creating a statement context and calling Populate with a collection of objects whose statements you would like stored in the statement table. As each object is serialized in SerializeToExpression it will have its contents placed in the statement table. saved in a table within the context. If you push this object on the stack it is your responsibility to integrate the statements added to it into your own collection of statements. + /// This object can be placed on the context stack to provide a place for + /// statements to be serialized into. Normally, statements are serialized + /// into whatever statement collection that is on the context stack. You + /// can modify this behavior by creating a statement context and calling + /// Populate with a collection of objects whose statements you would like + /// stored in the statement table. As each object is serialized in + /// SerializeToExpression it will have its contents placed in the statement + /// table. saved in a table within the context. If you push this object on + /// the stack it is your responsibility to integrate the statements added + /// to it into your own collection of statements. /// public sealed class StatementContext { @@ -20,15 +29,7 @@ public sealed class StatementContext /// public ObjectStatementCollection StatementCollection { - get - { - if (_statements == null) - { - _statements = new ObjectStatementCollection(); - } - - return _statements; - } + get => _statements ?? (_statements = new ObjectStatementCollection()); } } @@ -91,7 +92,7 @@ public CodeStatementCollection this[object statementOwner] { if (statementOwner == null) { - throw new ArgumentNullException("statementOwner"); + throw new ArgumentNullException(nameof(statementOwner)); } if (_table != null) @@ -126,7 +127,7 @@ public bool ContainsKey(object statementOwner) { if (statementOwner == null) { - throw new ArgumentNullException("statementOwner"); + throw new ArgumentNullException(nameof(statementOwner)); } if (_table != null) @@ -151,7 +152,7 @@ public void Populate(ICollection statementOwners) { if (statementOwners == null) { - throw new ArgumentNullException("statementOwners"); + throw new ArgumentNullException(nameof(statementOwners)); } foreach (object o in statementOwners) { @@ -166,7 +167,7 @@ public void Populate(object owner) { if (owner == null) { - throw new ArgumentNullException("owner"); + throw new ArgumentNullException(nameof(owner)); } AddOwner(owner, null); } diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/TypeCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/TypeCodeDomSerializer.cs new file mode 100644 index 00000000000..45a72de6371 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/TypeCodeDomSerializer.cs @@ -0,0 +1,622 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.ComponentModel.Design.Serialization +{ + /// + /// This class performs the same tasks as a CodeDomSerializer only serializing an object through this class defines a new type. + /// + [DefaultSerializationProvider(typeof(CodeDomSerializationProvider))] + public class TypeCodeDomSerializer : CodeDomSerializerBase + { + // Used only during deserialization to provide name to object mapping. + private IDictionary _nameTable; + private Dictionary _statementTable; + private static readonly Attribute[] s_designTimeFilter = new Attribute[] { DesignOnlyAttribute.Yes }; + private static readonly Attribute[] s_runTimeFilter = new Attribute[] { DesignOnlyAttribute.No }; + private static readonly object s_initMethodKey = new object(); + private static TypeCodeDomSerializer s_default; + + + internal static TypeCodeDomSerializer Default + { + get + { + if (s_default == null) + { + s_default = new TypeCodeDomSerializer(); + } + + return s_default; + } + } + + /// + /// This method deserializes a previously serialized code type declaration. The default implementation performs the following tasks: + /// • Case Sensitivity Checks: It looks for a CodeDomProvider service to decide if it should treat members as case sensitive or case insensitive. + /// • Statement Sorting: All member variables and local variables from init methods are stored in a table. Then each statement in an init method is added to a statement collection grouped according to its left hand side. So all statements assigning or operating on a particular variable are grouped under that variable. Variables that have no statements are discarded. + /// • Deserialization: Finally, the statement collections for each variable are deserialized according to the variable. Deserialize returns an instance of the root object. + /// + public virtual object Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration) + { + if (manager == null) + { + throw new ArgumentNullException("manager"); + } + + if (declaration == null) + { + throw new ArgumentNullException("declaration"); + } + + object rootObject = null; + using (TraceScope("TypeCodeDomSerializer::Deserialize")) + { + // Determine case-sensitivity + bool caseInsensitive = false; + CodeDomProvider provider = manager.GetService(typeof(CodeDomProvider)) as CodeDomProvider; + TraceWarningIf(provider == null, "Unable to determine case sensitivity. Make sure CodeDomProvider is a service of the manager."); + if (provider != null) + { + caseInsensitive = ((provider.LanguageOptions & LanguageOptions.CaseInsensitive) != 0); + } + + // Get and initialize the document type. + Type baseType = null; + string baseTypeName = declaration.Name; + + foreach (CodeTypeReference typeRef in declaration.BaseTypes) + { + Type t = manager.GetType(GetTypeNameFromCodeTypeReference(manager, typeRef)); + baseTypeName = typeRef.BaseType; + if (t != null && !(t.IsInterface)) + { + baseType = t; + break; + } + } + + if (baseType == null) + { + TraceError("Base type for type declaration {0} could not be loaded. Closest base type name: {1}", declaration.Name, baseTypeName); + Error(manager, string.Format(SR.SerializerTypeNotFound, baseTypeName), SR.SerializerTypeNotFound); + } + + if (GetReflectionTypeFromTypeHelper(manager, baseType).IsAbstract) + { + TraceError("Base type {0} is abstract, which isn't allowed", baseType.FullName); + Error(manager, string.Format(SR.SerializerTypeAbstract, baseType.FullName), SR.SerializerTypeAbstract); + } + + ResolveNameEventHandler onResolveName = new ResolveNameEventHandler(OnResolveName); + manager.ResolveName += onResolveName; + rootObject = manager.CreateInstance(baseType, null, declaration.Name, true); + + // Now that we have the root object, we create a nametable and fill it with member declarations. + int count = declaration.Members.Count; + _nameTable = new HybridDictionary(count, caseInsensitive); + _statementTable = new Dictionary(count); + Dictionary names = new Dictionary(count); + RootContext rootCxt = new RootContext(new CodeThisReferenceExpression(), rootObject); + manager.Context.Push(rootCxt); + try + { + StringComparison compare = caseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + foreach (CodeTypeMember typeMember in declaration.Members) + { + if (typeMember is CodeMemberField member) + { + if (!string.Equals(member.Name, declaration.Name, compare)) + { + // always skip members with the same name as the type -- because that's the name we use when we resolve "base" and "this" items... + _nameTable[member.Name] = member; + + if (member.Type != null && !string.IsNullOrEmpty(member.Type.BaseType)) + { + names[member.Name] = GetTypeNameFromCodeTypeReference(manager, member.Type); + } + } + } + } + + CodeMemberMethod[] methods = GetInitializeMethods(manager, declaration); + if (methods == null) + { + throw new InvalidOperationException(); + } + + Trace("Members to deserialize: {0}", _nameTable.Keys.Count); + Trace("Methods to deserialize: {0}", methods.Length); + TraceWarningIf(methods.Length == 0, "Serializer did not find any methods to deserialize."); + // Walk through all of our methods and search for local variables. These guys get added to our nametable too. + foreach (CodeMemberMethod method in methods) + { + foreach (CodeStatement statement in method.Statements) + { + + if (statement is CodeVariableDeclarationStatement local) + { + _nameTable[local.Name] = statement; + } + } + } + + // The name table should come pre-populated with our root expression. + _nameTable[declaration.Name] = rootCxt.Expression; + + // We fill a "statement table" for everything in our init methods. This statement table is a dictionary whose keys contain object names and whose values contain a statement collection of all statements with a LHS resolving to an object by that name. If supportGenerate is true, FillStatementTable will skip methods that are marked with the tag "GeneratedStatement". + foreach (CodeMemberMethod method in methods) + { + FillStatementTable(manager, _statementTable, names, method.Statements, declaration.Name); + } + + // Interesting problem. The CodeDom parser may auto generate statements that are associated with other methods. VB does this, for example, to create statements automatically for Handles clauses. The problem with this technique is that we will end up with statements that are related to variables that live solely in user code and not in InitializeComponent. We will attempt to construct instances of these objects with limited success. To guard against this, we check to see if the manager even supports this feature, and if it does, we must look out for these statements while filling the statement collections. + PropertyDescriptor supportGenerate = manager.Properties["SupportsStatementGeneration"]; + if (supportGenerate != null && supportGenerate.PropertyType == typeof(bool) && ((bool)supportGenerate.GetValue(manager)) == true) + { + // Ok, we must do the more expensive work of validating the statements we get. + foreach (string name in _nameTable.Keys) + { + if (!name.Equals(declaration.Name) && _statementTable.ContainsKey(name)) + { + CodeStatementCollection statements = _statementTable[name]; + bool acceptStatement = false; + foreach (CodeStatement statement in statements) + { + object genFlag = statement.UserData["GeneratedStatement"]; + if (genFlag == null || !(genFlag is bool) || !((bool)genFlag)) + { + acceptStatement = true; + break; + } + } + + if (!acceptStatement) + { + _statementTable.Remove(name); + } + } + } + } + + // Design time properties must be resolved before runtime properties to make sure that properties like "language" get established before we need to read values out the resource bundle + Trace("--------------------------------------------------------------------"); + Trace(" Beginning deserialization of {0} (design time)", declaration.Name); + Trace("--------------------------------------------------------------------"); + // Deserialize design time properties for the root component. + DeserializePropertiesFromResources(manager, rootObject, s_designTimeFilter); + // sort by the order so we deserialize in the same order the objects were decleared in. + OrderedCodeStatementCollection[] statementArray = new OrderedCodeStatementCollection[_statementTable.Count]; + _statementTable.Values.CopyTo(statementArray, 0); + Array.Sort(statementArray, StatementOrderComparer.s_default); + // make sure we have fully deserialized everything that is referenced in the statement table. Skip the root object for last + OrderedCodeStatementCollection rootStatements = null; + foreach (OrderedCodeStatementCollection statements in statementArray) + { + if (statements.Name.Equals(declaration.Name)) + { + rootStatements = statements; + } + else + { + DeserializeName(manager, statements.Name, statements); + } + } + if (rootStatements != null) + { + DeserializeName(manager, rootStatements.Name, rootStatements); + } + } + finally + { + _nameTable = null; + _statementTable = null; + Debug.Assert(manager.Context.Current == rootCxt, "Context stack corrupted"); + manager.ResolveName -= onResolveName; + manager.Context.Pop(); + } + } + return rootObject; + } + + /// + /// This takes the given name and deserializes it from our name table. Before blindly deserializing it checks the contents of the name table to see if the object already exists within it. We do this because deserializing one object may call back into us through OnResolveName and deserialize another. + /// + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private object DeserializeName(IDesignerSerializationManager manager, string name, CodeStatementCollection statements) + { + object value = null; + using (TraceScope("RootCodeDomSerializer::DeserializeName")) + { + // If the name we're looking for isn't in our dictionary, we return null. It is up to the caller to decide if this is an error or not. + value = _nameTable[name]; + CodeObject codeObject = value as CodeObject; + string typeName = null; + CodeMemberField field = null; + TraceIf(codeObject == null, "Name already deserialized. Type: {0}", (value == null ? "(null)" : value.GetType().Name)); + if (codeObject != null) + { + // If we fail, don't return a CodeDom element to the caller! Also clear out our nametable entry here -- A badly written serializer may cause a recursion here, and we want to stop it. + value = null; + _nameTable[name] = null; + // What kind of code object is this? + Trace("CodeDom type: {0}", codeObject.GetType().Name); + if (codeObject is CodeVariableDeclarationStatement declaration) + { + typeName = GetTypeNameFromCodeTypeReference(manager, declaration.Type); + } + else + { + field = codeObject as CodeMemberField; + if (field != null) + { + typeName = GetTypeNameFromCodeTypeReference(manager, field.Type); + } + else + { + if (manager.Context[typeof(RootContext)] is RootContext rootCxt && codeObject is CodeExpression exp && rootCxt.Expression == exp) + { + value = rootCxt.Value; + typeName = TypeDescriptor.GetClassName(value); + } + else + { + Debug.Fail("Unrecognized code object in nametable."); + } + } + } + } + else if (value == null) + { + // See if the container has this object. This may be necessary for visual inheritance. + IContainer container = (IContainer)manager.GetService(typeof(IContainer)); + if (container != null) + { + Trace("Try to get the type name from the container: {0}", name); + IComponent comp = container.Components[name]; + if (comp != null) + { + typeName = comp.GetType().FullName; + // we had to go to the host here, so there isn't a nametable entry here -- push in the component here so we don't accidentally recurse when we try to deserialize this object. + _nameTable[name] = comp; + } + } + } + + if (typeName != null) + { + // Default case -- something that needs to be deserialized + Type type = manager.GetType(typeName); + if (type == null) + { + TraceError("Type does not exist: {0}", typeName); + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerTypeNotFound, typeName), manager)); + } + else + { + if (statements == null && _statementTable.ContainsKey(name)) + { + statements = _statementTable[name]; + } + + if (statements != null && statements.Count > 0) + { + CodeDomSerializer serializer = GetSerializer(manager, type); + if (serializer == null) + { + // We report this as an error. This indicates that there are code statements in initialize component that we do not know how to load. + TraceError("Type referenced in init method has no serializer: {0}", type.Name); + manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerNoSerializerForComponent, type.FullName), manager)); + } + else + { + Trace("--------------------------------------------------------------------"); + Trace(" Beginning deserialization of {0}", name); + Trace("--------------------------------------------------------------------"); + try + { + value = serializer.Deserialize(manager, statements); + // Search for a modifiers property, and set it. + if (value != null && field != null) + { + PropertyDescriptor prop = TypeDescriptor.GetProperties(value)["Modifiers"]; + + if (prop != null && prop.PropertyType == typeof(MemberAttributes)) + { + MemberAttributes modifiers = field.Attributes & MemberAttributes.AccessMask; + + prop.SetValue(value, modifiers); + } + } + _nameTable[name] = value; + } + catch (Exception ex) + { + manager.ReportError(ex); + } + } + } + } + } + } + return value; + } + + /// + /// This method returns the method to emit all of the initialization code to for the given member. The default implementation returns an empty constructor. + /// + protected virtual CodeMemberMethod GetInitializeMethod(IDesignerSerializationManager manager, CodeTypeDeclaration declaration, object value) + { + if (manager == null) + { + throw new ArgumentNullException("manager"); + } + if (declaration == null) + { + throw new ArgumentNullException("declaration"); + } + if (value == null) + { + throw new ArgumentNullException("value"); + } + if (!(declaration.UserData[s_initMethodKey] is CodeConstructor ctor)) + { + ctor = new CodeConstructor(); + declaration.UserData[s_initMethodKey] = ctor; + } + return ctor; + } + + /// + /// This method returns an array of methods that need to be interpreted during deserialization. The default implementation returns a single element array with the constructor in it. + /// + protected virtual CodeMemberMethod[] GetInitializeMethods(IDesignerSerializationManager manager, CodeTypeDeclaration declaration) + { + if (manager == null) + { + throw new ArgumentNullException("manager"); + } + if (declaration == null) + { + throw new ArgumentNullException("declaration"); + } + foreach (CodeTypeMember member in declaration.Members) + { + if (member is CodeConstructor ctor && ctor.Parameters.Count == 0) + { + return new CodeMemberMethod[] { ctor }; + } + } + return new CodeMemberMethod[0]; + } + + /// + /// Called by the serialization manager to resolve a name to an object. + /// + private void OnResolveName(object sender, ResolveNameEventArgs e) + { + Debug.Assert(_nameTable != null, "OnResolveName called and we are not deserializing!"); + using (TraceScope("RootCodeDomSerializer::OnResolveName")) + { + Trace("Name: {0}", e.Name); + // If someone else already found a value, who are we to complain? + if (e.Value != null) + { + TraceWarning("Another name resolver has already found the value for {0}.", e.Name); + } + else + { + IDesignerSerializationManager manager = (IDesignerSerializationManager)sender; + e.Value = DeserializeName(manager, e.Name, null); + } + } + } + + /// + /// This method serializes the given root object and optional collection of members to create a new type definition. The members collection can be null or empty. If it contains values, these values will be serialized. Values themselves may decide to serialize as either member variables or local variables. This determination is done by looking for an extender property on the object called GenerateMember. If true, a member is generated. Otherwise, a local variable is generated. For convenience, the members collection can contain the root object. In this case the root object will not also be added as a member or local variable. The return value is a CodeTypeDeclaration that defines the root object. The name of the type will be taken from the root object’s name, if it was a named object. If not, a name will be fabricated from the simple type name of the root class. + /// The default implementation of Serialize performs the following tasks: + /// • Context Seeding. The serialization context will be “seeded” with data including the RootContext, and CodeTypeDeclaration. + /// • Member Serialization. Next Serialize will walk all of the members and call SerializeToExpression. Because serialization is done opportunistically in SerializeToExpression, this ensures that we do not serialize twice. + /// • Root Seralization. Finally, the root object is serialized and its statements are added to the statement collection. + /// • Statement Integration. After all objects have been serialized the Serialize method orders the statements and adds them to a method returned from GetInitializeMethod. Finally, a constructor is fabricated that calls all of the methods returned from GetInitializeMethod (this step is skipped for cases when GetInitializeMethod returns a constructor. + /// + public virtual CodeTypeDeclaration Serialize(IDesignerSerializationManager manager, object root, ICollection members) + { + if (manager == null) + { + throw new ArgumentNullException("manager"); + } + if (root == null) + { + throw new ArgumentNullException("root"); + } + Trace("TypeCodeDomSerializer::Serialize"); + + // As a type serializer we are responsible for creating the type declaration. Other serializers may access this type declaration and add members to it, so we need to place it on the context stack. The serialization process also looks at the root context to see if there is a root component. The root context is also used by the serializers to add statement collections for serialized components. + CodeTypeDeclaration docType = new CodeTypeDeclaration(manager.GetName(root)); + CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression(); + RootContext rootCxt = new RootContext(thisRef, root); + StatementContext statementCxt = new StatementContext(); + // Populate the statement context with a list of members we'd like to see statements for + statementCxt.StatementCollection.Populate(root); + if (members != null) + { + statementCxt.StatementCollection.Populate(members); + } + + docType.BaseTypes.Add(root.GetType()); + manager.Context.Push(docType); + manager.Context.Push(rootCxt); + manager.Context.Push(statementCxt); + try + { + // Do each component, skipping us, since we handle our own serialization. This looks really sweet, but is it worth it? We take the perf hit of a quicksort + the allocation overhead of 4 bytes for each component. Profiles show this as a 2% cost for a form with 100 controls. Let's meet the perf goals first, then consider uncommenting this. + if (members != null) + { + foreach (object member in members) + { + if (member != root) + { +#if DEBUG + string memberName = manager.GetName(member); + if (memberName == null) + memberName = member.ToString(); + Trace("--------------------------------------------------------------------"); + Trace(" Beginning serialization of {0}", memberName); + Trace("--------------------------------------------------------------------"); +#endif + // This returns an expression for the object, if possible. We ignore that. Besides returning an expression, it fills the statement table in the statement context and we're very interested in that. After serializing everything we will walk over the statement context's statement table. We will validate that each and every member we've serialized has a presence in the statement table. If it doesn't, that's an error in the member's serializer. + SerializeToExpression(manager, member); + } + } + } + // Now do the root object last. +#if DEBUG + string rootName = manager.GetName(root); + if (rootName == null) + rootName = root.ToString(); + Trace("--------------------------------------------------------------------"); + Trace(" Bedginning serialization of root object {0}", rootName); + Trace("--------------------------------------------------------------------"); +#endif + // Now, do the root object last. + SerializeToExpression(manager, root); + // After serializing everything we will walk over the statement context's statement table. We will validate that each and every member we've serialized has a presence in the statement table. If it doesn't, that's an error in the member's serializer. + IntegrateStatements(manager, root, members, statementCxt, docType); + } + finally + { + Debug.Assert(manager.Context.Current == statementCxt, "Somebody messed up our context stack"); + manager.Context.Pop(); + manager.Context.Pop(); + manager.Context.Pop(); + } + Trace("--------------------------------------------------------------------"); + Trace(" Generated code for ", manager.GetName(root)); + Trace("--------------------------------------------------------------------"); + Trace(docType.Name); + return docType; + } + + /// + /// Takes the statement context and integrates all the statements into the correct methods. Then, those methods are added to the code type declaration. + /// + private void IntegrateStatements(IDesignerSerializationManager manager, object root, ICollection members, StatementContext statementCxt, CodeTypeDeclaration typeDecl) + { + Dictionary methodMapIndex = new Dictionary(); + List methodMap = new List(); + // Go through all of our members and root object and fish out matching statement context info for each object. The statement context will probably contain more objects than our members, because each object that returned a statement collection was placed in the context. That's fine, because for each major component we serialized it pushed its statement collection on the context stack and statements were added there as well, forming a comlete graph. + if (members != null) + { + foreach (object member in members) + { + if (member != root) + { // always skip the root and do it last + CodeStatementCollection statements = statementCxt.StatementCollection[member]; + if (statements != null) + { + CodeMemberMethod method = GetInitializeMethod(manager, typeDecl, member); + if (method == null) + { + throw new InvalidOperationException(); + } + CodeMethodMap map; + if (methodMapIndex.TryGetValue(method.Name, out int mapIndex)) + { + map = methodMap[mapIndex]; + } + else + { + map = new CodeMethodMap(method); + methodMap.Add(map); + methodMapIndex[method.Name] = methodMap.Count - 1; + } + + if (statements.Count > 0) + { + map.Add(statements); + } + } + } + } + } + + // Finally, do the same thing for the root object. + CodeStatementCollection rootStatements = statementCxt.StatementCollection[root]; + if (rootStatements != null) + { + CodeMemberMethod rootMethod = GetInitializeMethod(manager, typeDecl, root); + if (rootMethod == null) + { + throw new InvalidOperationException(); + } + CodeMethodMap rootMap; + if (methodMapIndex.TryGetValue(rootMethod.Name, out int rootMapIndex)) + { + rootMap = methodMap[rootMapIndex]; + } + else + { + rootMap = new CodeMethodMap(rootMethod); + methodMap.Add(rootMap); + methodMapIndex[rootMethod.Name] = methodMap.Count - 1; + } + + if (rootStatements.Count > 0) + { + rootMap.Add(rootStatements); + } + } + + + // Final step -- walk through all of the sections and emit them to the type declaration. + foreach (CodeMethodMap map in methodMap) + { + map.Combine(); + typeDecl.Members.Add(map.Method); + Trace("...generated {0} statements into method {1}", map.Method.Statements.Count, map.Method.Name); + } + } + + + #region OrderedStatementsCollection Class + private class StatementOrderComparer : IComparer + { + public static readonly StatementOrderComparer s_default = new StatementOrderComparer(); + + private StatementOrderComparer() + { + } + + public int Compare(object left, object right) + { + OrderedCodeStatementCollection cscLeft = left as OrderedCodeStatementCollection; + OrderedCodeStatementCollection cscRight = right as OrderedCodeStatementCollection; + if (left == null) + { + return 1; + } + else if (right == null) + { + return -1; + } + else if (right == left) + { + return 0; + } + return cscLeft.Order - cscRight.Order; + } + } + #endregion + } +} diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/TypeDescriptorFilterService.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/TypeDescriptorFilterService.cs index 6487df95894..ec9d8ee2629 100644 --- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/TypeDescriptorFilterService.cs +++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/TypeDescriptorFilterService.cs @@ -41,11 +41,11 @@ bool ITypeDescriptorFilterService.FilterAttributes(IComponent component, IDictio { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } if (attributes == null) { - throw new ArgumentNullException("attributes"); + throw new ArgumentNullException(nameof(attributes)); } IDesigner designer = GetDesigner(component); @@ -65,11 +65,11 @@ bool ITypeDescriptorFilterService.FilterEvents(IComponent component, IDictionary { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } if (events == null) { - throw new ArgumentNullException("events"); + throw new ArgumentNullException(nameof(events)); } IDesigner designer = GetDesigner(component); @@ -89,11 +89,11 @@ bool ITypeDescriptorFilterService.FilterProperties(IComponent component, IDictio { if (component == null) { - throw new ArgumentNullException("component"); + throw new ArgumentNullException(nameof(component)); } if (properties == null) { - throw new ArgumentNullException("properties"); + throw new ArgumentNullException(nameof(properties)); } IDesigner designer = GetDesigner(component); diff --git a/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxService.cs b/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxService.cs index e549316828b..1b9433c8c30 100644 --- a/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxService.cs +++ b/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxService.cs @@ -11,7 +11,9 @@ namespace System.Drawing.Design /// /// Provides access to the toolbox in the development environment. /// - [ComImport(), Guid("4BACD258-DE64-4048-BC4E-FEDBEF9ACB76"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + [Guid("4BACD258-DE64-4048-BC4E-FEDBEF9ACB76")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IToolboxService { /// @@ -167,4 +169,3 @@ public interface IToolboxService void SetSelectedToolboxItem(ToolboxItem toolboxItem); } } - diff --git a/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxUser.cs b/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxUser.cs index 51b2558b542..9ecc48c7cfe 100644 --- a/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxUser.cs +++ b/src/System.Windows.Forms.Design/src/System/Drawing/Design/IToolboxUser.cs @@ -21,4 +21,3 @@ public interface IToolboxUser void ToolPicked(ToolboxItem tool); } } - diff --git a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatedEventArgs.cs b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatedEventArgs.cs index 25b7080bd06..c00465ce485 100644 --- a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatedEventArgs.cs +++ b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatedEventArgs.cs @@ -12,14 +12,19 @@ namespace System.Drawing.Design /// public class ToolboxComponentsCreatedEventArgs : EventArgs { + private IComponent[] _components; + /// /// Initializes a new instance of the - public ToolboxComponentsCreatedEventArgs(IComponent[] components) => throw new NotImplementedException(SR.NotImplementedByDesign); + public ToolboxComponentsCreatedEventArgs(IComponent[] components) + { + _components = components; + } /// /// An array storing the toolbox components. /// - public IComponent[] Components => throw new NotImplementedException(SR.NotImplementedByDesign); + public IComponent[] Components => (IComponent[])_components?.Clone(); } } diff --git a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatingEventArgs.cs b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatingEventArgs.cs index 7da77cff477..a104a81ec72 100644 --- a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatingEventArgs.cs +++ b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxComponentsCreatingEventArgs.cs @@ -15,12 +15,15 @@ public class ToolboxComponentsCreatingEventArgs : EventArgs /// /// Initializes a new instance of the object. /// - public ToolboxComponentsCreatingEventArgs(IDesignerHost host) => throw new NotImplementedException(SR.NotImplementedByDesign); + public ToolboxComponentsCreatingEventArgs(IDesignerHost host) + { + DesignerHost = host; + } /// - /// An instance of IDesignerHost that has made the creat request. This can be null if no designer host - /// was provided to the toolbox item. + /// An instance of IDesignerHost that has made the creat request. + /// This can be null if no designer host was provided to the toolbox item. /// - public IDesignerHost DesignerHost => throw new NotImplementedException(SR.NotImplementedByDesign); + public IDesignerHost DesignerHost { get; } } } diff --git a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs index 7583e8f57ab..55db747a9cc 100644 --- a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs +++ b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs @@ -101,7 +101,7 @@ public AssemblyName[] DependentAssemblies } set { - Properties["DependentAssemblies"] = value.Clone(); + Properties["DependentAssemblies"] = value?.Clone(); } } @@ -277,23 +277,15 @@ public string TypeName } /// - /// Gets the version for this toolboxitem. It defaults to AssemblyName.Version unless - /// overridden in a derived toolboxitem. This can be overridden to return an empty string - /// to suppress its display in the toolbox tooltip. + /// Gets the version for this toolboxitem. It defaults to AssemblyName.Version unless + /// overridden in a derived toolboxitem. This can be overridden to + /// return an empty string to suppress its display in the toolbox tooltip. /// public virtual string Version { - get - { - if (AssemblyName != null) - { - return AssemblyName.Version.ToString(); - } - return string.Empty; - } + get => AssemblyName?.Version?.ToString() ?? string.Empty; } - /// /// Occurs when components are created. /// @@ -408,7 +400,7 @@ protected virtual IComponent[] CreateComponentsCore(IDesignerHost host, IDiction { IComponent[] components = CreateComponentsCore(host); - if (host != null) + if (host != null && components != null) { for (int i = 0; i < components.Length; i++) { @@ -527,10 +519,9 @@ private static bool AreAssemblyNamesEqual(AssemblyName name1, AssemblyName name2 public override int GetHashCode() { - string typeName = TypeName; - int hash = (typeName != null) ? typeName.GetHashCode() : 0; - - return unchecked(hash ^ DisplayName.GetHashCode()); + int typeHash = TypeName?.GetHashCode() ?? 0; + int displayHash = DisplayName?.GetHashCode() ?? 0; + return unchecked(typeHash ^ displayHash); } /// @@ -542,8 +533,8 @@ protected virtual object FilterPropertyValue(string propertyName, object value) switch (propertyName) { case "AssemblyName": - if (value != null) - value = ((AssemblyName)value).Clone(); + if (value is AssemblyName valueName) + value = valueName.Clone(); break; @@ -598,7 +589,7 @@ protected virtual Type GetType(IDesignerHost host, AssemblyName assemblyName, st if (host != null) { - ts = (ITypeResolutionService)host.GetService(typeof(ITypeResolutionService)); + ts = host.GetService(typeof(ITypeResolutionService)) as ITypeResolutionService; } if (ts != null) @@ -664,7 +655,7 @@ protected virtual Type GetType(IDesignerHost host, AssemblyName assemblyName, st { } - if (a == null && assemblyName.CodeBase != null && assemblyName.CodeBase.Length > 0) + if (a == null && !string.IsNullOrEmpty(assemblyName.CodeBase)) { try { @@ -708,10 +699,6 @@ public virtual void Initialize(Type type) { TypeName = type.FullName; AssemblyName assemblyName = type.Assembly.GetName(true); - if (type.Assembly.GlobalAssemblyCache) - { - assemblyName.CodeBase = null; - } Dictionary parents = new Dictionary(); Type parentType = type; @@ -804,7 +791,8 @@ public virtual void Initialize(Type type) private AssemblyName GetNonRetargetedAssemblyName(Type type, AssemblyName policiedAssemblyName) { - if (type == null || policiedAssemblyName == null) + Debug.Assert(type != null); + if (policiedAssemblyName == null) return null; //if looking for myself, just return it. (not a reference) @@ -833,17 +821,17 @@ private AssemblyName GetNonRetargetedAssemblyName(Type type, AssemblyName polici // in assemblyname. foreach (AssemblyName name in type.Assembly.GetReferencedAssemblies()) { - Assembly a = null; - try { - a = Assembly.Load(name); - if (a != null && a.FullName == policiedAssemblyName.FullName) + Assembly a = Assembly.Load(name); + if (a.FullName == policiedAssemblyName.FullName) + { return name; + } } catch { - //ignore all exceptions and just fall through if it fails (it shouldn't, but who knows). + // Ignore all exceptions and just fall through if it fails (it shouldn't, but who knows). } } @@ -900,10 +888,7 @@ protected virtual void OnComponentsCreating(ToolboxComponentsCreatingEventArgs a _componentsCreatingEvent?.Invoke(this, args); } - public override string ToString() - { - return DisplayName; - } + public override string ToString() => DisplayName ?? string.Empty; /// /// Called as a helper to ValidatePropertyValue to validate that an object @@ -992,6 +977,10 @@ protected virtual object ValidatePropertyValue(string propertyName, object value value = filter; break; + case "DependentAssemblies": + ValidatePropertyType(propertyName, value, typeof(AssemblyName[]), true); + break; + case "IsTransient": ValidatePropertyType(propertyName, value, typeof(bool), false); break; @@ -1002,7 +991,6 @@ protected virtual object ValidatePropertyValue(string propertyName, object value [SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")] void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { - //IntSecurity.UnmanagedCode.Demand(); Serialize(info, context); } diff --git a/src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs b/src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs new file mode 100644 index 00000000000..8e222217022 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices.ComTypes; + +namespace System.Runtime.InteropServices +{ + // UCOMITypeLib is not yet ported to interop on core. + [Guid("00020402-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface UCOMITypeLib + { + [PreserveSig] + int GetTypeInfoCount(); + + void GetTypeInfoType(int index, out TYPEKIND pTKind); + + void GetLibAttr(out IntPtr ppTLibAttr); + + void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile); + + [return: MarshalAs(UnmanagedType.Bool)] + bool IsName([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal); + + [PreserveSig] + void ReleaseTLibAttr(IntPtr pTLibAttr); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AdornmentType.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AdornmentType.cs new file mode 100644 index 00000000000..bbcf7cebd91 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AdornmentType.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// Specifies numeric IDs for different types of adornments on a component. + /// + internal enum AdornmentType + { + /// + /// Specifies the type as grab handle adornments. + /// + GrabHandle = 1, + /// + /// Specifies the type as container selector adornments. + /// + ContainerSelector = 2, + /// + /// Specifies the type as the maximum size of any adornment. + /// + Maximum = 3, + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs index a4306573745..77c40c7f95e 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs @@ -10,10 +10,7 @@ namespace System.Windows.Forms.Design { /// - /// - /// Imports ActiveX controls and generates a wrapper that can be accessed by a - /// designer. - /// + /// Imports ActiveX controls and generates a wrapper that can be accessed by a designer. /// public class AxImporter { @@ -21,60 +18,91 @@ public AxImporter(Options options) { throw new NotImplementedException(SR.NotImplementedByDesign); } + public sealed class Options { + /// /// The flag that controls when we sign the generated assemblies. + /// public bool delaySign = false; + /// /// Flag that controls whether we are to generate sources for the ActiveX control wrapper. + /// public bool genSources = false; + /// /// Regardless of which version of the library is registered, if at all, use the /// path supplied on the command line for AxImp to generate the Windows Forms wrappers. - [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")] - //This class is used to communicate option values between components, it does not have any functionality which might modify these values. + /// + [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Justification = "This class is used to communicate option values between components, it does not have any functionality which might modify these values.")] public bool ignoreRegisteredOcx; + /// /// The file containing the strong name key container for the generated assemblies. + /// public string keyContainer = null; + /// /// The file containing the strong name key for the generated assemblies. + /// public string keyFile = null; + /// /// The strong name used for the generated assemblies. + /// public StrongNameKeyPair keyPair = null; + /// /// Flag that controls whether we should output errors in the MSBuild format. + /// public bool msBuildErrors = false; + /// /// Flag that controls whether we should show the logo. + /// public bool noLogo = false; + /// /// The output directory for all the generated assemblies. + /// public string outputDirectory = null; + /// /// The path-included filename of type library containing the definition of the ActiveX control. + /// public string outputName = null; + /// /// The flag that controls whether we try to overwrite existing generated assemblies. + /// public bool overwriteRCW = false; + + /// /// The public key used to sign the generated assemblies. + /// public byte[] publicKey = null; + /// /// The object that allows us to resolve types and references needed to generate assemblies. + /// public IReferenceResolver references = null; + /// /// Flag that controls the output generated. + /// public bool silentMode = false; + /// /// Flag that controls the output generated. + /// public bool verboseMode = false; } /// - /// The Reference Resolver service will try to look through the references it can obtain, - /// for a reference that matches the given criterion. For now, the only kind of references - /// it can look for are COM (RCW) references and ActiveX wrapper references. + /// The Reference Resolver service will try to look through the references it can obtain, + /// for a reference that matches the given criterion. For now, the only kind of references + /// it can look for are COM (RCW) references and ActiveX wrapper references. /// public interface IReferenceResolver { @@ -88,36 +116,3 @@ public interface IReferenceResolver } } } - -namespace System.Runtime.InteropServices -{ - - // UCOMITypeLib is not yet ported to interop on core. - - [Guid("00020402-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface UCOMITypeLib - { - [PreserveSig] - int GetTypeInfoCount(); - - //void GetTypeInfo(int index, out UCOMITypeInfo ppTI); - void GetTypeInfoType(int index, out TYPEKIND pTKind); - - //void GetTypeInfoOfGuid(ref Guid guid, out UCOMITypeInfo ppTInfo); - void GetLibAttr(out IntPtr ppTLibAttr); - - //void GetTypeComp(out UCOMITypeComp ppTComp); - void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, - out string strHelpFile); - - [return: MarshalAs(UnmanagedType.Bool)] - bool IsName([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal); - - //void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] UCOMITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound); - [PreserveSig] - void ReleaseTLibAttr(IntPtr pTLibAttr); - } - -} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/BaseContextMenuStrip.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/BaseContextMenuStrip.cs new file mode 100644 index 00000000000..a424dc3444b --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/BaseContextMenuStrip.cs @@ -0,0 +1,318 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// This class is going to replace the shell contextMenu and uses the ContextMenuStrip. The ContextMenuStrip contains groups and groupOrder which it uses to add items to itself. ControlDesigners can add custom items to the contextMenu, using the new member to the group and add the groupOrder to the ContextMenu. + /// + internal class BaseContextMenuStrip : GroupedContextMenuStrip + { + private IServiceProvider serviceProvider; + private Component component; + private ToolStripMenuItem selectionMenuItem; + + public BaseContextMenuStrip(IServiceProvider provider, Component component) : base() + { + serviceProvider = provider; + this.component = component; + // Now initialiaze the contextMenu + InitializeContextMenu(); + } + + /// + /// Helper function to add the "View Code" menuItem. + /// + private void AddCodeMenuItem() + { + StandardCommandToolStripMenuItem codeMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.ViewCode, SR.ContextMenuViewCode, "viewcode", serviceProvider); + Groups[StandardGroups.Code].Items.Add(codeMenuItem); + } + + /// + /// Helper function to add the "SendToBack/BringToFront" menuItem. + /// + private void AddZorderMenuItem() + { + StandardCommandToolStripMenuItem ZOrderMenuItem = new StandardCommandToolStripMenuItem(MenuCommands.BringToFront, SR.ContextMenuBringToFront, "bringToFront", serviceProvider); + Groups[StandardGroups.ZORder].Items.Add(ZOrderMenuItem); + ZOrderMenuItem = new StandardCommandToolStripMenuItem(MenuCommands.SendToBack, SR.ContextMenuSendToBack, "sendToBack", serviceProvider); + Groups[StandardGroups.ZORder].Items.Add(ZOrderMenuItem); + } + + /// + /// Helper function to add the "Alignment" menuItem. + /// + private void AddGridMenuItem() + { + StandardCommandToolStripMenuItem gridMenuItem = new StandardCommandToolStripMenuItem(MenuCommands.AlignToGrid, SR.ContextMenuAlignToGrid, "alignToGrid", serviceProvider); + Groups[StandardGroups.Grid].Items.Add(gridMenuItem); + } + + /// + /// Helper function to add the "Locked" menuItem. + /// + private void AddLockMenuItem() + { + StandardCommandToolStripMenuItem lockMenuItem = new StandardCommandToolStripMenuItem(MenuCommands.LockControls, SR.ContextMenuLockControls, "lockControls", serviceProvider); + Groups[StandardGroups.Lock].Items.Add(lockMenuItem); + } + + /// + /// Helper function to add the Select Parent menuItem. + /// + private void RefreshSelectionMenuItem() + { + int index = -1; + if (selectionMenuItem != null) + { + index = Items.IndexOf(selectionMenuItem); + Groups[StandardGroups.Selection].Items.Remove(selectionMenuItem); + Items.Remove(selectionMenuItem); + } + ArrayList parentControls = new ArrayList(); + int nParentControls = 0; + + // Get the currently selected Control + if (serviceProvider.GetService(typeof(ISelectionService)) is ISelectionService selectionService && serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host) + { + IComponent root = host.RootComponent; + Debug.Assert(root != null, "Null root component. Will be unable to build selection menu"); + if (selectionService.PrimarySelection is Control selectedControl && root != null && selectedControl != root) + { + Control parentControl = selectedControl.Parent; + while (parentControl != null) + { + if (parentControl.Site != null) + { + parentControls.Add(parentControl); + nParentControls++; + } + if (parentControl == root) + { + break; + } + parentControl = parentControl.Parent; + } + } + else if (selectionService.PrimarySelection is ToolStripItem) + { + ToolStripItem selectedItem = selectionService.PrimarySelection as ToolStripItem; + if (host.GetDesigner(selectedItem) is ToolStripItemDesigner itemDesigner) + { + parentControls = itemDesigner.AddParentTree(); + nParentControls = parentControls.Count; + } + } + } + if (nParentControls > 0) + { + selectionMenuItem = new ToolStripMenuItem(); + + IUIService uis = serviceProvider.GetService(typeof(IUIService)) as IUIService; + if (uis != null) + { + selectionMenuItem.DropDown.Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]; + //Set the right Font + selectionMenuItem.DropDown.Font = (Font)uis.Styles["DialogFont"]; + if (uis.Styles["VsColorPanelText"] is Color) + { + selectionMenuItem.DropDown.ForeColor = (Color)uis.Styles["VsColorPanelText"]; + } + + } + + selectionMenuItem.Text = SR.ContextMenuSelect; + foreach (Component parent in parentControls) + { + ToolStripMenuItem selectListItem = new SelectToolStripMenuItem(parent, serviceProvider); + selectionMenuItem.DropDownItems.Add(selectListItem); + } + Groups[StandardGroups.Selection].Items.Add(selectionMenuItem); + // Re add the newly refreshed item.. + if (index != -1) + { + Items.Insert(index, selectionMenuItem); + } + } + } + + /// + /// Helper function to add the Verbs. + /// + private void AddVerbMenuItem() + { + //Add Designer Verbs.. + IMenuCommandService menuCommandService = (IMenuCommandService)serviceProvider.GetService(typeof(IMenuCommandService)); + if (menuCommandService != null) + { + DesignerVerbCollection verbCollection = menuCommandService.Verbs; + foreach (DesignerVerb verb in verbCollection) + { + DesignerVerbToolStripMenuItem verbItem = new DesignerVerbToolStripMenuItem(verb); + Groups[StandardGroups.Verbs].Items.Add(verbItem); + } + } + } + + /// + /// Helper function to add the "Cut/Copy/Paste/Delete" menuItem. + /// + private void AddEditMenuItem() + { + StandardCommandToolStripMenuItem stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Cut, SR.ContextMenuCut, "cut", serviceProvider); + Groups[StandardGroups.Edit].Items.Add(stdMenuItem); + stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Copy, SR.ContextMenuCopy, "copy", serviceProvider); + Groups[StandardGroups.Edit].Items.Add(stdMenuItem); + stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Paste, SR.ContextMenuPaste, "paste", serviceProvider); + Groups[StandardGroups.Edit].Items.Add(stdMenuItem); + stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Delete, SR.ContextMenuDelete, "delete", serviceProvider); + Groups[StandardGroups.Edit].Items.Add(stdMenuItem); + } + + /// + /// Helper function to add the "Properties" menuItem. + /// + private void AddPropertiesMenuItem() + { + StandardCommandToolStripMenuItem stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.DocumentOutline, SR.ContextMenuDocumentOutline, "", serviceProvider); + Groups[StandardGroups.Properties].Items.Add(stdMenuItem); + stdMenuItem = new StandardCommandToolStripMenuItem(MenuCommands.DesignerProperties, SR.ContextMenuProperties, "properties", serviceProvider); + Groups[StandardGroups.Properties].Items.Add(stdMenuItem); + } + + /// + /// Basic Initialize method. + /// + private void InitializeContextMenu() + { + //this.Opening += new CancelEventHandler(OnContextMenuOpening); + Name = "designerContextMenuStrip"; + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]; + if (uis.Styles["VsColorPanelText"] is Color) + { + ForeColor = (Color)uis.Styles["VsColorPanelText"]; + } + } + GroupOrdering.AddRange(new string[] { StandardGroups.Code, StandardGroups.ZORder, StandardGroups.Grid, StandardGroups.Lock, StandardGroups.Verbs, StandardGroups.Custom, StandardGroups.Selection, StandardGroups.Edit, StandardGroups.Properties}); + // ADD MENUITEMS + AddCodeMenuItem(); + AddZorderMenuItem(); + AddGridMenuItem(); + AddLockMenuItem(); + AddVerbMenuItem(); + RefreshSelectionMenuItem(); + AddEditMenuItem(); + AddPropertiesMenuItem(); + } + + /// + /// Public function that allows the individual MenuItems to get refreshed each time the ContextMenu is opened. + /// + public override void RefreshItems() + { + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + Font = (Font)uis.Styles["DialogFont"]; + } + + foreach (ToolStripItem item in this.Items) + { + StandardCommandToolStripMenuItem stdItem = item as StandardCommandToolStripMenuItem; + if (stdItem != null) + { + stdItem.RefreshItem(); + } + } + RefreshSelectionMenuItem(); + } + + /// + /// A ToolStripMenuItem that gets added for the "Select" menuitem. + /// + private class SelectToolStripMenuItem : ToolStripMenuItem + { + private readonly Component _comp; + private readonly IServiceProvider _serviceProvider; + private readonly Type _itemType; + private bool _cachedImage = false; + private Image _image = null; + private static readonly string s_systemWindowsFormsNamespace = typeof(System.Windows.Forms.ToolStripItem).Namespace; + + public SelectToolStripMenuItem(Component c, IServiceProvider provider) + { + _comp = c; + _serviceProvider = provider; + // Get NestedSiteName... + string compName = null; + if (_comp != null) + { + ISite site = _comp.Site; + if (site != null) + { + if (site is INestedSite nestedSite && !string.IsNullOrEmpty(nestedSite.FullName)) + { + compName = nestedSite.FullName; + } + else if (!string.IsNullOrEmpty(site.Name)) + { + compName = site.Name; + } + } + } + Text = string.Format(SR.ToolStripSelectMenuItem, compName); + _itemType = c.GetType(); + } + + public override Image Image + { + get + { + // Defer loading the image until we're sure we need it + if (!_cachedImage) + { + _cachedImage = true; + // else attempt to get the resource from a known place in the manifest. if and only if the namespace of the type is System.Windows.Forms. else attempt to get the resource from a known place in the manifest + if (_itemType.Namespace == s_systemWindowsFormsNamespace) + { + _image = ToolboxBitmapAttribute.GetImageFromResource(_itemType, null, false); + } + + // if all else fails, throw up a default image. + if (_image == null) + { + _image = ToolboxBitmapAttribute.GetImageFromResource(_comp.GetType(), null, false); + } + } + return _image; + } + set + { + _image = value; + _cachedImage = true; + } + } + + /// + /// Items OnClick event, to select the Parent Control. + /// + protected override void OnClick(System.EventArgs e) + { + if (_serviceProvider.GetService(typeof(ISelectionService)) is ISelectionService selectionService) + { + selectionService.SetSelectedComponents(new object[] { _comp }, SelectionTypes.Replace); + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/Adorner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/Adorner.cs index 5f8bba74855..33734fea269 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/Adorner.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/Adorner.cs @@ -14,12 +14,16 @@ namespace System.Windows.Forms.Design.Behavior /// public sealed class Adorner { + private BehaviorService _behaviorService; //ptr back to the BehaviorService + private readonly GlyphCollection _glyphs; //collection of Glyphs that this particular Adorner manages + /// /// Standard constructor. Creates a new GlyphCollection and by default is enabled. /// public Adorner() { - throw new NotImplementedException(SR.NotImplementedByDesign); + _glyphs = new GlyphCollection(); + EnabledInternal = true; } /// @@ -28,8 +32,8 @@ public Adorner() /// public BehaviorService BehaviorService { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); + get => _behaviorService; + set => _behaviorService = value; } /// @@ -38,14 +42,26 @@ public BehaviorService BehaviorService /// public bool Enabled { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); + get => EnabledInternal; + set + { + if (value != EnabledInternal) + { + EnabledInternal = value; + Invalidate(); + } + } } + internal bool EnabledInternal { get; set; } + /// /// Returns the stronly-typed Glyph collection. /// - public GlyphCollection Glyphs => throw new NotImplementedException(SR.NotImplementedByDesign); + public GlyphCollection Glyphs + { + get => _glyphs; + } /// /// /// @@ -53,7 +69,7 @@ public bool Enabled /// public void Invalidate() { - throw new NotImplementedException(SR.NotImplementedByDesign); + _behaviorService?.Invalidate(); } /// @@ -61,7 +77,10 @@ public void Invalidate() /// public void Invalidate(Rectangle rectangle) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (_behaviorService != null) + { + _behaviorService.Invalidate(rectangle); + } } /// @@ -69,7 +88,10 @@ public void Invalidate(Rectangle rectangle) /// public void Invalidate(Region region) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (_behaviorService != null) + { + _behaviorService.Invalidate(region); + } } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgs.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgs.cs index dcb2410a1f1..ddfa7e6fd36 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgs.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgs.cs @@ -7,23 +7,19 @@ namespace System.Windows.Forms.Design.Behavior { /// - /// This class represents the arguments describing a BehaviorDragDrop event - /// fired by the BehaviorService. + /// This class represents the arguments describing a BehaviorDragDrop event + /// fired by the BehaviorService. /// public class BehaviorDragDropEventArgs : EventArgs { - /// - /// Constructor. This class is created by the BehaviorService directly - /// before a drag operation begins. - /// public BehaviorDragDropEventArgs(ICollection dragComponents) { - throw new NotImplementedException(SR.NotImplementedByDesign); + DragComponents = dragComponents; } /// - /// Returns the list of IComponents currently being dragged. + /// Returns the list of IComponents currently being dragged. /// - public ICollection DragComponents => throw new NotImplementedException(SR.NotImplementedByDesign); + public ICollection DragComponents { get; } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorService.cs index 3dea94441df..3e45fede73f 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorService.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/BehaviorService.cs @@ -2,8 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; +using System.Drawing.Design; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Security; +using Microsoft.Win32; namespace System.Windows.Forms.Design.Behavior { @@ -23,30 +33,296 @@ namespace System.Windows.Forms.Design.Behavior /// public sealed class BehaviorService : IDisposable { + private readonly IServiceProvider _serviceProvider; //standard service provider + private readonly AdornerWindow _adornerWindow; //the transparent window all glyphs are drawn to + private readonly BehaviorServiceAdornerCollection _adorners; //we manage all adorners (glyph-containers) here + private readonly ArrayList _behaviorStack; //the stack behavior objects can be pushed to and popped from + private Behavior _captureBehavior; //the behavior that currently has capture; may be null + private Glyph _hitTestedGlyph; //the last valid glyph that was hit tested + private IToolboxService _toolboxSvc; //allows us to have the toolbox choose a cursor + private Control _dropSource; //actual control used to call .dodragdrop + private DragEventArgs _validDragArgs; //if valid - this is used to fabricate drag enter/leave envents + private BehaviorDragDropEventHandler _beginDragHandler; //fired directly before we call .DoDragDrop() + private BehaviorDragDropEventHandler _endDragHandler; //fired directly after we call .DoDragDrop() + private EventHandler _synchronizeEventHandler; //fired when we want to synchronize the selection + private NativeMethods.TRACKMOUSEEVENT _trackMouseEvent; //demand created (once) used to track the mouse hover event + private bool _trackingMouseEvent; //state identifying current mouse tracking + private string[] _testHook_RecentSnapLines; //we keep track of the last snaplines we found - for testing purposes + private readonly MenuCommandHandler _menuCommandHandler; //private object that handles all menu commands + private bool _useSnapLines; //indicates if this designer session is using snaplines or snapping to a grid + private bool _queriedSnapLines; //only query for this once since we require the user restart design sessions when this changes + private readonly Hashtable _dragEnterReplies; // we keep track of whether glyph has already responded to a DragEnter this D&D. + private static readonly TraceSwitch s_dragDropSwitch = new TraceSwitch("BSDRAGDROP", "Behavior service drag & drop messages"); + + private bool _dragging = false; // are we in a drag + private bool _cancelDrag = false; // should we cancel the drag on the next QueryContinueDrag + + + private int _adornerWindowIndex = -1; + + //test hooks for SnapLines + private static int WM_GETALLSNAPLINES; + private static int WM_GETRECENTSNAPLINES; + + private DesignerActionUI _actionPointer; // pointer to the designer action service so we can supply mouse over notifications + + private const string ToolboxFormat = ".NET Toolbox Item"; // used to detect if a drag is coming from the toolbox. [SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] internal BehaviorService(IServiceProvider serviceProvider, Control windowFrame) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _serviceProvider = serviceProvider; + //create the AdornerWindow + _adornerWindow = new AdornerWindow(this, windowFrame); + + //use the adornerWindow as an overlay + IOverlayService os = (IOverlayService)serviceProvider.GetService(typeof(IOverlayService)); + if (os != null) + { + _adornerWindowIndex = os.PushOverlay(_adornerWindow); + } + + _dragEnterReplies = new Hashtable(); + + //start with an empty adorner collection & no behavior on the stack + _adorners = new BehaviorServiceAdornerCollection(this); + _behaviorStack = new ArrayList(); + + _hitTestedGlyph = null; + _validDragArgs = null; + _actionPointer = null; + _trackMouseEvent = null; + _trackingMouseEvent = false; + + //create out object that will handle all menucommands + if (serviceProvider.GetService(typeof(IMenuCommandService)) is IMenuCommandService menuCommandService && serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host) + { + _menuCommandHandler = new MenuCommandHandler(this, menuCommandService); + host.RemoveService(typeof(IMenuCommandService)); + host.AddService(typeof(IMenuCommandService), _menuCommandHandler); + } + + //default layoutmode is SnapToGrid. + _useSnapLines = false; + _queriedSnapLines = false; + + //test hooks + WM_GETALLSNAPLINES = SafeNativeMethods.RegisterWindowMessage("WM_GETALLSNAPLINES"); + WM_GETRECENTSNAPLINES = SafeNativeMethods.RegisterWindowMessage("WM_GETRECENTSNAPLINES"); + + // Listen to the SystemEvents so that we can resync selection based on display settings etc. + SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(OnUserPreferenceChanged); } /// /// Read-only property that returns the AdornerCollection that the BehaivorService manages. /// - public BehaviorServiceAdornerCollection Adorners => - throw new NotImplementedException(SR.NotImplementedByDesign); + public BehaviorServiceAdornerCollection Adorners + { + get => _adorners; + } + + /// + /// Returns the actual Control that represents the transparent AdornerWindow. + /// + internal Control AdornerWindowControl + { + get => _adornerWindow; + } + + internal int AdornerWindowIndex + { + get => _adornerWindowIndex; + } + + internal bool HasCapture + { + get => _captureBehavior != null; + } + + /// + /// Returns the LayoutMode setting of the current designer session. Either SnapLines or SnapToGrid. + /// + internal bool UseSnapLines + { + get + { + //we only check for this service/value once since we require the user to re-open the designer session after these types of option have been modified + if (!_queriedSnapLines) + { + _queriedSnapLines = true; + _useSnapLines = DesignerUtils.UseSnapLines(_serviceProvider); + } + + return _useSnapLines; + } + } /// /// Creates and returns a Graphics object for the AdornerWindow /// - public Graphics AdornerWindowGraphics => throw new NotImplementedException(SR.NotImplementedByDesign); + public Graphics AdornerWindowGraphics + { + [ResourceExposure(ResourceScope.Process)] + [ResourceConsumption(ResourceScope.Process)] + get + { + Graphics result = _adornerWindow.CreateGraphics(); + result.Clip = new Region(_adornerWindow.DesignerFrameDisplayRectangle); + return result; + } + } + + public Behavior CurrentBehavior + { + get + { + if (_behaviorStack != null && _behaviorStack.Count > 0) + { + return (_behaviorStack[0] as Behavior); + } + else + { + return null; + } + } + } + + internal bool Dragging + { + get => _dragging; + } - public Behavior CurrentBehavior => throw new NotImplementedException(SR.NotImplementedByDesign); + internal bool CancelDrag + { + get => _cancelDrag; + set => _cancelDrag = value; + } + internal DesignerActionUI DesignerActionUI + { + get => _actionPointer; + set => _actionPointer = value; + } + /// + /// Called by the DragAssistanceManager after a snapline/drag op has completed - we store this data for testing purposes. See TestHook_GetRecentSnapLines method. + /// + internal string[] RecentSnapLines + { + set => _testHook_RecentSnapLines = value; + } /// /// Disposes the behavior service. /// public void Dispose() { - throw new NotImplementedException(SR.NotImplementedByDesign); + // remove adorner window from overlay service + IOverlayService os = (IOverlayService)_serviceProvider.GetService(typeof(IOverlayService)); + if (os != null) + { + os.RemoveOverlay(_adornerWindow); + } + + MenuCommandHandler menuCommandHandler = null; + if (_serviceProvider.GetService(typeof(IMenuCommandService)) is IMenuCommandService menuCommandService) + menuCommandHandler = menuCommandService as MenuCommandHandler; + + if (menuCommandHandler != null && _serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host) + { + IMenuCommandService oldMenuCommandService = menuCommandHandler.MenuService; + host.RemoveService(typeof(IMenuCommandService)); + host.AddService(typeof(IMenuCommandService), oldMenuCommandService); + } + + _adornerWindow.Dispose(); + SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(OnUserPreferenceChanged); + } + + private Control DropSource + { + get + { + if (_dropSource == null) + { + _dropSource = new Control(); + } + return _dropSource; + } + } + + internal DragDropEffects DoDragDrop(DropSourceBehavior dropSourceBehavior) + { + //hook events + DropSource.QueryContinueDrag += new QueryContinueDragEventHandler(dropSourceBehavior.QueryContinueDrag); + DropSource.GiveFeedback += new GiveFeedbackEventHandler(dropSourceBehavior.GiveFeedback); + + DragDropEffects res = DragDropEffects.None; + + //build up the eventargs for firing our dragbegin/end events + ICollection dragComponents = ((DropSourceBehavior.BehaviorDataObject)dropSourceBehavior.DataObject).DragComponents; + BehaviorDragDropEventArgs eventArgs = new BehaviorDragDropEventArgs(dragComponents); + + try + { + try + { + OnBeginDrag(eventArgs); + _dragging = true; + _cancelDrag = false; + // This is normally cleared on OnMouseUp, but we might not get an OnMouseUp to clear it. VSWhidbey #474259 + // So let's make sure it is really cleared when we start the drag. + _dragEnterReplies.Clear(); + res = DropSource.DoDragDrop(dropSourceBehavior.DataObject, dropSourceBehavior.AllowedEffects); + } + finally + { + DropSource.QueryContinueDrag -= new QueryContinueDragEventHandler(dropSourceBehavior.QueryContinueDrag); + DropSource.GiveFeedback -= new GiveFeedbackEventHandler(dropSourceBehavior.GiveFeedback); + //If the drop gets cancelled, we won't get a OnDragDrop, so let's make sure that we stop + //processing drag notifications. Also VSWhidbey #354552 and 133339. + EndDragNotification(); + _validDragArgs = null; + _dragging = false; + _cancelDrag = false; + OnEndDrag(eventArgs); + } + } + catch (CheckoutException cex) + { + if (cex == CheckoutException.Canceled) + { + res = DragDropEffects.None; + } + else + { + throw; + } + } + finally + { + // It's possible we did not receive an EndDrag, and therefore we weren't able to cleanup the drag. We will do that here. Scenarios where this happens: dragging from designer to recycle-bin, or over the taskbar. + if (dropSourceBehavior != null) + { + dropSourceBehavior.CleanupDrag(); + } + } + return res; + } + + internal void EndDragNotification() + { + _adornerWindow.EndDragNotification(); + } + + private void OnEndDrag(BehaviorDragDropEventArgs e) + { + _endDragHandler?.Invoke(this, e); + } + + private void OnBeginDrag(BehaviorDragDropEventArgs e) + { + if (_beginDragHandler != null) + { + _beginDragHandler(this, e); + } } /// @@ -54,7 +330,9 @@ public void Dispose() /// public Point AdornerWindowPointToScreen(Point p) { - throw new NotImplementedException(SR.NotImplementedByDesign); + NativeMethods.POINT offset = new NativeMethods.POINT(p.X, p.Y); + NativeMethods.MapWindowPoints(_adornerWindow.Handle, IntPtr.Zero, offset, 1); + return new Point(offset.x, offset.y); } /// @@ -62,7 +340,8 @@ public Point AdornerWindowPointToScreen(Point p) /// public Point AdornerWindowToScreen() { - throw new NotImplementedException(SR.NotImplementedByDesign); + Point origin = new Point(0, 0); + return AdornerWindowPointToScreen(origin); } /// @@ -70,7 +349,20 @@ public Point AdornerWindowToScreen() /// public Point ControlToAdornerWindow(Control c) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (c.Parent == null) + { + return Point.Empty; + } + + NativeMethods.POINT pt = new NativeMethods.POINT(); + pt.x = c.Left; + pt.y = c.Top; + NativeMethods.MapWindowPoints(c.Parent.Handle, _adornerWindow.Handle, pt, 1); + if (c.Parent.IsMirrored) + { + pt.x -= c.Width; + } + return new Point(pt.x, pt.y); } /// @@ -78,7 +370,11 @@ public Point ControlToAdornerWindow(Control c) /// public Point MapAdornerWindowPoint(IntPtr handle, Point pt) { - throw new NotImplementedException(SR.NotImplementedByDesign); + NativeMethods.POINT nativePoint = new NativeMethods.POINT(); + nativePoint.x = pt.X; + nativePoint.y = pt.Y; + NativeMethods.MapWindowPoints(handle, _adornerWindow.Handle, nativePoint, 1); + return new Point(nativePoint.x, nativePoint.y); } /// @@ -86,7 +382,13 @@ public Point MapAdornerWindowPoint(IntPtr handle, Point pt) /// public Rectangle ControlRectInAdornerWindow(Control c) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (c.Parent == null) + { + return Rectangle.Empty; + } + Point loc = ControlToAdornerWindow(c); + + return new Rectangle(loc, c.Size); } /// @@ -95,8 +397,14 @@ public Rectangle ControlRectInAdornerWindow(Control c) /// public event BehaviorDragDropEventHandler BeginDrag { - add => throw new NotImplementedException(SR.NotImplementedByDesign); - remove => throw new NotImplementedException(SR.NotImplementedByDesign); + add + { + _beginDragHandler += value; + } + remove + { + _beginDragHandler -= value; + } } /// @@ -105,8 +413,14 @@ public event BehaviorDragDropEventHandler BeginDrag /// public event BehaviorDragDropEventHandler EndDrag { - add => throw new NotImplementedException(SR.NotImplementedByDesign); - remove => throw new NotImplementedException(SR.NotImplementedByDesign); + add + { + _endDragHandler += value; + } + remove + { + _endDragHandler -= value; + } } /// @@ -114,9 +428,15 @@ public event BehaviorDragDropEventHandler EndDrag /// public event EventHandler Synchronize { - add => throw new NotImplementedException(SR.NotImplementedByDesign); + add + { + _synchronizeEventHandler += value; + } - remove => throw new NotImplementedException(SR.NotImplementedByDesign); + remove + { + _synchronizeEventHandler -= value; + } } /// @@ -126,7 +446,24 @@ public event EventHandler Synchronize /// public Behavior GetNextBehavior(Behavior behavior) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (_behaviorStack != null && _behaviorStack.Count > 0) + { + int index = _behaviorStack.IndexOf(behavior); + if ((index != -1) && (index < _behaviorStack.Count - 1)) + { + return _behaviorStack[index + 1] as Behavior; + } + } + return null; + } + + internal void EnableAllAdorners(bool enabled) + { + foreach (Adorner adorner in Adorners) + { + adorner.EnabledInternal = enabled; + } + Invalidate(); } /// @@ -135,7 +472,7 @@ public Behavior GetNextBehavior(Behavior behavior) /// public void Invalidate() { - throw new NotImplementedException(SR.NotImplementedByDesign); + _adornerWindow.InvalidateAdornerWindow(); } /// @@ -144,7 +481,7 @@ public void Invalidate() /// public void Invalidate(Rectangle rect) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _adornerWindow.InvalidateAdornerWindow(rect); } /// @@ -153,7 +490,7 @@ public void Invalidate(Rectangle rect) /// public void Invalidate(Region r) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _adornerWindow.InvalidateAdornerWindow(r); } /// @@ -161,7 +498,10 @@ public void Invalidate(Region r) /// public void SyncSelection() { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (_synchronizeEventHandler != null) + { + _synchronizeEventHandler(this, EventArgs.Empty); + } } /// @@ -169,7 +509,36 @@ public void SyncSelection() /// public Behavior PopBehavior(Behavior behavior) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (_behaviorStack.Count == 0) + { + throw new InvalidOperationException(); + } + + int index = _behaviorStack.IndexOf(behavior); + if (index == -1) + { + Debug.Assert(false, "Could not find the behavior to pop - did it already get popped off? " + behavior.ToString()); + return null; + } + + _behaviorStack.RemoveAt(index); + if (behavior == _captureBehavior) + { + _adornerWindow.Capture = false; + // Defensive: adornerWindow should get a WM_CAPTURECHANGED, but do this by hand if it didn't. + if (_captureBehavior != null) + { + OnLoseCapture(); + Debug.Assert(_captureBehavior == null, "OnLostCapture should have cleared captureBehavior"); + } + } + return behavior; + } + + internal void ProcessPaintMessage(Rectangle paintRect) + { + //Note, we don't call BehSvc.Invalidate because this will just cause the messages to recurse. Instead, invalidating this adornerWindow will just cause a "propagatePaint" and draw the glyphs. + _adornerWindow.Invalidate(paintRect); } /// @@ -178,7 +547,18 @@ public Behavior PopBehavior(Behavior behavior) /// public void PushBehavior(Behavior behavior) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (behavior == null) + { + throw new ArgumentNullException(nameof(behavior)); + } + + // Should we catch this + _behaviorStack.Insert(0, behavior); + // If there is a capture behavior, and it isn't this behavior, notify it that it no longer has capture. + if (_captureBehavior != null && _captureBehavior != behavior) + { + OnLoseCapture(); + } } /// @@ -188,7 +568,20 @@ public void PushBehavior(Behavior behavior) /// public void PushCaptureBehavior(Behavior behavior) { - throw new NotImplementedException(SR.NotImplementedByDesign); + PushBehavior(behavior); + _captureBehavior = behavior; + _adornerWindow.Capture = true; + + //VSWhidbey #373836. Since we are now capturing all mouse messages, we might miss some WM_MOUSEACTIVATE which would have activated the app. So if the DialogOwnerWindow (e.g. VS) is not the active window, let's activate it here. + IUIService uiService = (IUIService)_serviceProvider.GetService(typeof(IUIService)); + if (uiService != null) + { + IWin32Window hwnd = uiService.GetDialogOwnerWindow(); + if (hwnd != null && hwnd.Handle != IntPtr.Zero && hwnd.Handle != UnsafeNativeMethods.GetActiveWindow()) + { + UnsafeNativeMethods.SetActiveWindow(new HandleRef(this, hwnd.Handle)); + } + } } /// @@ -196,7 +589,1220 @@ public void PushCaptureBehavior(Behavior behavior) /// public Point ScreenToAdornerWindow(Point p) { - throw new NotImplementedException(SR.NotImplementedByDesign); + NativeMethods.POINT offset = new NativeMethods.POINT(); + offset.x = p.X; + offset.y = p.Y; + NativeMethods.MapWindowPoints(IntPtr.Zero, _adornerWindow.Handle, offset, 1); + return new Point(offset.x, offset.y); + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + internal void OnLoseCapture() + { + if (_captureBehavior != null) + { + Behavior b = _captureBehavior; + _captureBehavior = null; + try + { + b.OnLoseCapture(_hitTestedGlyph, EventArgs.Empty); + } + catch + { + } + } + } + + /// + /// The AdornerWindow is a transparent window that resides ontop of the Designer's Frame. This window is used by the BehaviorService to intercept all messages. It also serves as a unified canvas on which to paint Glyphs. + /// + private class AdornerWindow : Control + { + private BehaviorService _behaviorService;//ptr back to BehaviorService + private Control _designerFrame;//the designer's frame + private static MouseHook s_mouseHook; // shared mouse hook + private static List s_adornerWindowList = new List(); + private bool _processingDrag; // is this particular window in a drag operation + + /// + /// Constructor that parents itself to the Designer Frame and hooks all + /// necessary events. + /// + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + internal AdornerWindow(BehaviorService behaviorService, Control designerFrame) + { + this._behaviorService = behaviorService; + this._designerFrame = designerFrame; + Dock = DockStyle.Fill; + AllowDrop = true; + Text = "AdornerWindow"; + SetStyle(ControlStyles.Opaque, true); + } + + /// + /// The key here is to set the appropriate TransparetWindow style. + /// + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.Style &= ~(NativeMethods.WS_CLIPCHILDREN | NativeMethods.WS_CLIPSIBLINGS); + cp.ExStyle |= NativeMethods.WS_EX_TRANSPARENT; + return cp; + } + } + + internal bool ProcessingDrag + { + get => _processingDrag; + set => _processingDrag = value; + } + + /// + /// We'll use CreateHandle as our notification for creating our mouse hooker. + /// + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + s_adornerWindowList.Add(this); + if (s_mouseHook == null) + { + s_mouseHook = new MouseHook(); + } + } + + /// + /// Unhook and null out our mouseHook. + /// + protected override void OnHandleDestroyed(EventArgs e) + { + s_adornerWindowList.Remove(this); + // unregister the mouse hook once all adorner windows have been disposed. + if (s_adornerWindowList.Count == 0 && s_mouseHook != null) + { + s_mouseHook.Dispose(); + s_mouseHook = null; + } + base.OnHandleDestroyed(e); + } + + /// + /// Null out our mouseHook and unhook any events. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_designerFrame != null) + { + _designerFrame = null; + } + } + base.Dispose(disposing); + } + + /// + /// Returns true if the DesignerFrame is created & not being disposed. + /// + internal Control DesignerFrame + { + get => _designerFrame; + } + + /// + /// Returns the display rectangle for the adorner window + /// + internal Rectangle DesignerFrameDisplayRectangle + { + get + { + if (DesignerFrameValid) + { + return ((DesignerFrame)_designerFrame).DisplayRectangle; + } + else + { + return Rectangle.Empty; + } + } + } + + /// + /// Returns true if the DesignerFrame is created & not being disposed. + /// + internal bool DesignerFrameValid + { + get + { + if (_designerFrame == null || _designerFrame.IsDisposed || !_designerFrame.IsHandleCreated) + { + return false; + } + return true; + } + } + + public IEnumerable Adorners { get; private set; } + + /// + /// Ultimately called by ControlDesigner when it receives a DragDrop message - here, we'll exit from 'drag mode'. + /// + internal void EndDragNotification() + { + ProcessingDrag = false; + } + + /// + /// Invalidates the transparent AdornerWindow by asking the Designer Frame beneath it to invalidate. Note the they use of the .Update() call for perf. purposes. + /// + internal void InvalidateAdornerWindow() + { + if (DesignerFrameValid) + { + _designerFrame.Invalidate(true); + _designerFrame.Update(); + } + } + + /// + /// Invalidates the transparent AdornerWindow by asking the Designer Frame beneath it to invalidate. Note the they use of the .Update() call for perf. purposes. + /// + internal void InvalidateAdornerWindow(Region region) + { + if (DesignerFrameValid) + { + //translate for non-zero scroll positions + Point scrollPosition = ((DesignerFrame)_designerFrame).AutoScrollPosition; + region.Translate(scrollPosition.X, scrollPosition.Y); + + _designerFrame.Invalidate(region, true); + _designerFrame.Update(); + } + } + + /// + /// Invalidates the transparent AdornerWindow by asking the Designer Frame beneath it to invalidate. Note the they use of the .Update() call for perf. purposes. + /// + internal void InvalidateAdornerWindow(Rectangle rectangle) + { + if (DesignerFrameValid) + { + //translate for non-zero scroll positions + Point scrollPosition = ((DesignerFrame)_designerFrame).AutoScrollPosition; + rectangle.Offset(scrollPosition.X, scrollPosition.Y); + + _designerFrame.Invalidate(rectangle, true); + _designerFrame.Update(); + } + } + + /// + /// The AdornerWindow hooks all Drag/Drop notification so they can be forwarded to the appropriate Behavior via the BehaviorService. + /// + protected override void OnDragDrop(DragEventArgs e) + { + try + { + _behaviorService.OnDragDrop(e); + } + finally + { + ProcessingDrag = false; + } + } + + internal void EnableAllAdorners(bool enabled) + { + foreach (Adorner adorner in Adorners) + { + adorner.EnabledInternal = enabled; + } + Invalidate(); + } + + private static bool IsLocalDrag(DragEventArgs e) + { + if (e.Data is DropSourceBehavior.BehaviorDataObject) + { + return true; + } + else + { + // Gets all the data formats and data conversion formats in the data object. + string[] allFormats = e.Data.GetFormats(); + + for (int i = 0; i < allFormats.Length; i++) + { + if (allFormats[i].Length == ToolboxFormat.Length && + string.Equals(ToolboxFormat, allFormats[i])) + { + return true; + } + } + } + return false; + } + + /// + /// The AdornerWindow hooks all Drag/Drop notification so they can be forwarded to the appropriate Behavior via the BehaviorService. + /// + protected override void OnDragEnter(DragEventArgs e) + { + ProcessingDrag = true; + + // determine if this is a local drag, if it is, do normal processing otherwise, force a PropagateHitTest. We need to force this because the OLE D&D service suspends mouse messages when the drag is not local so the mouse hook never sees them. + if (!IsLocalDrag(e)) + { + _behaviorService._validDragArgs = e; + NativeMethods.POINT pt = new NativeMethods.POINT(); + NativeMethods.GetCursorPos(pt); + NativeMethods.MapWindowPoints(IntPtr.Zero, Handle, pt, 1); + Point mousePos = new Point(pt.x, pt.y); + _behaviorService.PropagateHitTest(mousePos); + + } + _behaviorService.OnDragEnter(null, e); + } + + /// + /// The AdornerWindow hooks all Drag/Drop notification so they can be forwarded to the appropriate Behavior via the BehaviorService. + /// + protected override void OnDragLeave(EventArgs e) + { + // set our dragArgs to null so we know not to send drag enter/leave events when we re-enter the dragging area + _behaviorService._validDragArgs = null; + try + { + _behaviorService.OnDragLeave(null, e); + } + finally + { + ProcessingDrag = false; + } + } + + /// + /// The AdornerWindow hooks all Drag/Drop notification so they can be forwarded to the appropriate Behavior via the BehaviorService. + /// + protected override void OnDragOver(DragEventArgs e) + { + ProcessingDrag = true; + if (!IsLocalDrag(e)) + { + _behaviorService._validDragArgs = e; + NativeMethods.POINT pt = new NativeMethods.POINT(); + NativeMethods.GetCursorPos(pt); + NativeMethods.MapWindowPoints(IntPtr.Zero, Handle, pt, 1); + Point mousePos = new Point(pt.x, pt.y); + _behaviorService.PropagateHitTest(mousePos); + } + + _behaviorService.OnDragOver(e); + } + + /// + /// The AdornerWindow hooks all Drag/Drop notification so they can be forwarded to the appropriate Behavior via the BehaviorService. + /// + protected override void OnGiveFeedback(GiveFeedbackEventArgs e) + { + _behaviorService.OnGiveFeedback(e); + } + + /// + /// The AdornerWindow hooks all Drag/Drop notification so they can be forwarded to the appropriate Behavior via the BehaviorService. + /// + protected override void OnQueryContinueDrag(QueryContinueDragEventArgs e) + { + _behaviorService.OnQueryContinueDrag(e); + } + + /// + /// Called by ControlDesigner when it receives a DragEnter message - we'll let listen to all Mouse Messages so we can send drag notifcations. + /// + internal void StartDragNotification() + { + ProcessingDrag = true; + } + + /// + /// The AdornerWindow intercepts all designer-related messages and forwards them to the BehaviorService for appropriate actions. Note that Paint and HitTest messages are correctly parsed and translated to AdornerWindow coords. + /// + protected override void WndProc(ref Message m) + { + //special test hooks + if (m.Msg == BehaviorService.WM_GETALLSNAPLINES) + { + _behaviorService.TestHook_GetAllSnapLines(ref m); + } + else if (m.Msg == BehaviorService.WM_GETRECENTSNAPLINES) + { + _behaviorService.TestHook_GetRecentSnapLines(ref m); + } + + switch (m.Msg) + { + case Interop.WindowMessages.WM_PAINT: + // Stash off the region we have to update + IntPtr hrgn = NativeMethods.CreateRectRgn(0, 0, 0, 0); + NativeMethods.GetUpdateRgn(m.HWnd, hrgn, true); + // The region we have to update in terms of the smallest rectangle that completely encloses the update region of the window gives us the clip rectangle + NativeMethods.RECT clip = new NativeMethods.RECT(); + NativeMethods.GetUpdateRect(m.HWnd, ref clip, true); + Rectangle paintRect = new Rectangle(clip.left, clip.top, clip.right - clip.left, clip.bottom - clip.top); + + try + { + using (Region r = Region.FromHrgn(hrgn)) + { + // Call the base class to do its painting. + DefWndProc(ref m); + // Now do our own painting. + using (Graphics g = Graphics.FromHwnd(m.HWnd)) + { + using (PaintEventArgs pevent = new PaintEventArgs(g, paintRect)) + { + g.Clip = r; + _behaviorService.PropagatePaint(pevent); + } + } + } + } + finally + { + NativeMethods.DeleteObject(hrgn); + } + break; + + case Interop.WindowMessages.WM_NCHITTEST: + Point pt = new Point((short)NativeMethods.Util.LOWORD(unchecked((int)(long)m.LParam)), + (short)NativeMethods.Util.HIWORD(unchecked((int)(long)m.LParam))); + NativeMethods.POINT pt1 = new NativeMethods.POINT + { + x = 0, + y = 0 + }; + NativeMethods.MapWindowPoints(IntPtr.Zero, Handle, pt1, 1); + pt.Offset(pt1.x, pt1.y); + if (_behaviorService.PropagateHitTest(pt) && !ProcessingDrag) + { + m.Result = (IntPtr)(NativeMethods.HTTRANSPARENT); + } + else + { + m.Result = (IntPtr)(NativeMethods.HTCLIENT); + } + break; + + case Interop.WindowMessages.WM_CAPTURECHANGED: + base.WndProc(ref m); + _behaviorService.OnLoseCapture(); + break; + + default: + base.WndProc(ref m); + break; + } + } + + /// + /// Called by our mouseHook when it spies a mouse message that the adornerWindow would be interested in. + /// Returning 'true' signifies that the message was processed and should not continue to child windows. + /// + private bool WndProcProxy(ref Message m, int x, int y) + { + Point mouseLoc = new Point(x, y); + _behaviorService.PropagateHitTest(mouseLoc); + switch (m.Msg) + { + case Interop.WindowMessages.WM_LBUTTONDOWN: + if (_behaviorService.OnMouseDown(MouseButtons.Left, mouseLoc)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_RBUTTONDOWN: + if (_behaviorService.OnMouseDown(MouseButtons.Right, mouseLoc)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_MOUSEMOVE: + if (_behaviorService.OnMouseMove(Control.MouseButtons, mouseLoc)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_LBUTTONUP: + if (_behaviorService.OnMouseUp(MouseButtons.Left)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_RBUTTONUP: + if (_behaviorService.OnMouseUp(MouseButtons.Right)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_MOUSEHOVER: + if (_behaviorService.OnMouseHover(mouseLoc)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_LBUTTONDBLCLK: + if (_behaviorService.OnMouseDoubleClick(MouseButtons.Left, mouseLoc)) + { + return false; + } + break; + + case Interop.WindowMessages.WM_RBUTTONDBLCLK: + if (_behaviorService.OnMouseDoubleClick(MouseButtons.Right, mouseLoc)) + { + return false; + } + break; + } + return true; + } + + /// + /// This class knows how to hook all the messages to a given process/thread. + /// On any mouse clicks, it asks the designer what to do with the message, that is to eat it or propogate it to the control it was meant for. This allows us to synchrounously process mouse messages when the AdornerWindow itself may be pumping messages. + /// + [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] + private class MouseHook + { + private AdornerWindow _currentAdornerWindow; + private int _thisProcessID = 0; + private GCHandle _mouseHookRoot; + [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] + private IntPtr _mouseHookHandle = IntPtr.Zero; + private bool _processingMessage; + + private bool _isHooked = false; //VSWHIDBEY # 474112 + private int _lastLButtonDownTimeStamp; + + public MouseHook() + { +#if DEBUG + _callingStack = Environment.StackTrace; +#endif + HookMouse(); + } +#if DEBUG + readonly string _callingStack; + ~MouseHook() + { + Debug.Assert(_mouseHookHandle == IntPtr.Zero, "Finalizing an active mouse hook. This will crash the process. Calling stack: " + _callingStack); + } +#endif + + public void Dispose() + { + UnhookMouse(); + } + + private void HookMouse() + { + Debug.Assert(AdornerWindow.s_adornerWindowList.Count > 0, "No AdornerWindow available to create the mouse hook"); + lock (this) + { + if (_mouseHookHandle != IntPtr.Zero || AdornerWindow.s_adornerWindowList.Count == 0) + { + return; + } + + if (_thisProcessID == 0) + { + AdornerWindow adornerWindow = AdornerWindow.s_adornerWindowList[0]; + SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(adornerWindow, adornerWindow.Handle), out _thisProcessID); + } + + NativeMethods.HookProc hook = new NativeMethods.HookProc(MouseHookProc); + _mouseHookRoot = GCHandle.Alloc(hook); + +#pragma warning disable 618 + _mouseHookHandle = UnsafeNativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE, + hook, + new HandleRef(null, IntPtr.Zero), + AppDomain.GetCurrentThreadId()); +#pragma warning restore 618 + if (_mouseHookHandle != IntPtr.Zero) + { + _isHooked = true; + } + Debug.Assert(_mouseHookHandle != IntPtr.Zero, "Failed to install mouse hook"); + } + } + + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private unsafe IntPtr MouseHookProc(int nCode, IntPtr wparam, IntPtr lparam) + { + if (_isHooked && nCode == NativeMethods.HC_ACTION) + { + NativeMethods.MOUSEHOOKSTRUCT mhs = Marshal.PtrToStructure(lparam); + if (mhs != null) + { + try + { + if (ProcessMouseMessage(mhs.hWnd, unchecked((int)(long)wparam), mhs.pt_x, mhs.pt_y)) + { + return (IntPtr)1; + } + } + catch (Exception ex) + { + _currentAdornerWindow.Capture = false; + if (ex != CheckoutException.Canceled) + { + _currentAdornerWindow._behaviorService.ShowError(ex); + } + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + finally + { + _currentAdornerWindow = null; + } + } + } + + Debug.Assert(_isHooked, "How did we get here when we are diposed?"); + return UnsafeNativeMethods.CallNextHookEx(new HandleRef(this, _mouseHookHandle), nCode, wparam, lparam); + } + + private void UnhookMouse() + { + lock (this) + { + if (_mouseHookHandle != IntPtr.Zero) + { + UnsafeNativeMethods.UnhookWindowsHookEx(new HandleRef(this, _mouseHookHandle)); + _mouseHookRoot.Free(); + _mouseHookHandle = IntPtr.Zero; + _isHooked = false; + } + } + } + + private bool ProcessMouseMessage(IntPtr hWnd, int msg, int x, int y) + { + if (_processingMessage) + { + return false; + } + + foreach (AdornerWindow adornerWindow in AdornerWindow.s_adornerWindowList) + { + if (!adornerWindow.DesignerFrameValid) + { + continue; + } + + _currentAdornerWindow = adornerWindow; + IntPtr handle = adornerWindow.DesignerFrame.Handle; + + // if it's us or one of our children, just process as normal + if (adornerWindow.ProcessingDrag || (hWnd != handle && SafeNativeMethods.IsChild(new HandleRef(this, handle), new HandleRef(this, hWnd)))) + { + Debug.Assert(_thisProcessID != 0, "Didn't get our process id!"); + // make sure the window is in our process + SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(null, hWnd), out int pid); + // if this isn't our process, bail + if (pid != _thisProcessID) + { + return false; + } + + try + { + _processingMessage = true; + NativeMethods.POINT pt = new NativeMethods.POINT + { + x = x, + y = y + }; + NativeMethods.MapWindowPoints(IntPtr.Zero, adornerWindow.Handle, pt, 1); + Message m = Message.Create(hWnd, msg, (IntPtr)0, (IntPtr)MAKELONG(pt.y, pt.x)); + // No one knows why we get an extra click here from VS. As a workaround, we check the TimeStamp and discard it. + if (m.Msg == Interop.WindowMessages.WM_LBUTTONDOWN) + { + _lastLButtonDownTimeStamp = UnsafeNativeMethods.GetMessageTime(); + } + else if (m.Msg == Interop.WindowMessages.WM_LBUTTONDBLCLK) + { + int lButtonDoubleClickTimeStamp = UnsafeNativeMethods.GetMessageTime(); + if (lButtonDoubleClickTimeStamp == _lastLButtonDownTimeStamp) + { + return true; + } + } + + if (!adornerWindow.WndProcProxy(ref m, pt.x, pt.y)) + { + // we did the work, stop the message propogation + return true; + } + + } + finally + { + _processingMessage = false; + } + break; // no need to enumerate the other adorner windows since only one can be focused at a time. + } + } + return false; + } + + public static int MAKELONG(int low, int high) + { + return (high << 16) | (low & 0xffff); + } + } + } + + private bool PropagateHitTest(Point pt) + { + for (int i = _adorners.Count - 1; i >= 0; i--) + { + if (!_adorners[i].Enabled) + { + continue; + } + + for (int j = 0; j < _adorners[i].Glyphs.Count; j++) + { + Cursor hitTestCursor = _adorners[i].Glyphs[j].GetHitTest(pt); + if (hitTestCursor != null) + { + // InvokeMouseEnterGlyph will cause the selection to change, which might change the number of glyphs, so we need to remember the new glyph before calling InvokeMouseEnterLeave. VSWhidbey #396611 + Glyph newGlyph = _adorners[i].Glyphs[j]; + + //with a valid hit test, fire enter/leave events + InvokeMouseEnterLeave(_hitTestedGlyph, newGlyph); + if (_validDragArgs == null) + { + //if we're not dragging, set the appropriate cursor + SetAppropriateCursor(hitTestCursor); + } + + _hitTestedGlyph = newGlyph; + //return true if we hit on a transparentBehavior, otherwise false + return (_hitTestedGlyph.Behavior is ControlDesigner.TransparentBehavior); + } + } + } + + InvokeMouseEnterLeave(_hitTestedGlyph, null); + if (_validDragArgs == null) + { + Cursor cursor = Cursors.Default; + if ((_behaviorStack != null) && (_behaviorStack.Count > 0)) + { + if (_behaviorStack[0] is Behavior behavior) + { + cursor = behavior.Cursor; + } + } + SetAppropriateCursor(cursor); + } + _hitTestedGlyph = null; + return true; // Returning false will cause the transparent window to return HTCLIENT when handling WM_NCHITTEST, thus blocking underline window to receive mouse events. + } + + private class MenuCommandHandler : IMenuCommandService + { + private readonly BehaviorService _owner; // ptr back to the behavior service + private readonly IMenuCommandService _menuService; // core service used for most implementations of the IMCS interface + private readonly Stack _currentCommands = new Stack(); + + public MenuCommandHandler(BehaviorService owner, IMenuCommandService menuService) + { + _owner = owner; + _menuService = menuService; + } + + public IMenuCommandService MenuService + { + get => _menuService; + } + + void IMenuCommandService.AddCommand(MenuCommand command) + { + _menuService.AddCommand(command); + } + + void IMenuCommandService.RemoveVerb(DesignerVerb verb) + { + _menuService.RemoveVerb(verb); + } + + void IMenuCommandService.RemoveCommand(MenuCommand command) + { + _menuService.RemoveCommand(command); + } + + MenuCommand IMenuCommandService.FindCommand(CommandID commandID) + { + try + { + if (_currentCommands.Contains(commandID)) + { + return null; + } + _currentCommands.Push(commandID); + return _owner.FindCommand(commandID, _menuService); + } + finally + { + _currentCommands.Pop(); + } + } + + bool IMenuCommandService.GlobalInvoke(CommandID commandID) + { + return _menuService.GlobalInvoke(commandID); + } + + void IMenuCommandService.ShowContextMenu(CommandID menuID, int x, int y) + { + _menuService.ShowContextMenu(menuID, x, y); + } + + void IMenuCommandService.AddVerb(DesignerVerb verb) + { + _menuService.AddVerb(verb); + } + + DesignerVerbCollection IMenuCommandService.Verbs + { + get => _menuService.Verbs; + } + } + + internal void StartDragNotification() + { + _adornerWindow.StartDragNotification(); + } + + private MenuCommand FindCommand(CommandID commandID, IMenuCommandService menuService) + { + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior != null) + { + //if the behavior wants all commands disabled.. + if (behavior.DisableAllCommands) + { + MenuCommand menuCommand = menuService.FindCommand(commandID); + if (menuCommand != null) + { + menuCommand.Enabled = false; + } + return menuCommand; + } + // check to see if the behavior wants to interrupt this command + else + { + MenuCommand menuCommand = behavior.FindCommand(commandID); + if (menuCommand != null) + { + // the behavior chose to interrupt - so return the new command + return menuCommand; + } + } + } + return menuService.FindCommand(commandID); + } + + private Behavior GetAppropriateBehavior(Glyph g) { + if (_behaviorStack != null && _behaviorStack.Count > 0) { + return _behaviorStack[0] as Behavior; + } + + if (g != null && g.Behavior != null) { + return g.Behavior; + } + + return null; + } + + private void ShowError(Exception ex) + { + if (_serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + uis.ShowError(ex); + } + } + + private void SetAppropriateCursor(Cursor cursor) + { + //default cursors will let the toolbox svc set a cursor if needed + if (cursor == Cursors.Default) + { + if (_toolboxSvc == null) + { + _toolboxSvc = (IToolboxService)_serviceProvider.GetService(typeof(IToolboxService)); + } + + if (_toolboxSvc != null && _toolboxSvc.SetCursor()) + { + cursor = new Cursor(NativeMethods.GetCursor()); + } + } + _adornerWindow.Cursor = cursor; + } + + private void InvokeMouseEnterLeave(Glyph leaveGlyph, Glyph enterGlyph) + { + if (leaveGlyph != null) + { + if (enterGlyph != null && leaveGlyph.Equals(enterGlyph)) + { + //same glyph - no change + return; + } + if (_validDragArgs != null) + { + OnDragLeave(leaveGlyph, EventArgs.Empty); + } + else + { + OnMouseLeave(leaveGlyph); + } + } + + if (enterGlyph != null) + { + if (_validDragArgs != null) + { + OnDragEnter(enterGlyph, _validDragArgs); + } + else + { + OnMouseEnter(enterGlyph); + } + } + } + private void OnDragEnter(Glyph g, DragEventArgs e) + { + // if the AdornerWindow receives a drag message, this fn() will be called w/o a glyph - so we'll assign the last hit tested one + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "BS::OnDragEnter"); + if (g == null) + { + g = _hitTestedGlyph; + } + + Behavior behavior = GetAppropriateBehavior(g); + if (behavior == null) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tNo behavior, returning"); + return; + } + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tForwarding to behavior"); + behavior.OnDragEnter(g, e); + + if (g != null && g is ControlBodyGlyph && e.Effect == DragDropEffects.None) + { + _dragEnterReplies[g] = this; // dummy value, we just need to set something. + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tCalled DragEnter on this glyph. Caching"); + } + } + + private void OnDragLeave(Glyph g, EventArgs e) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "BS::DragLeave"); + // This is normally cleared on OnMouseUp, but we might not get an OnMouseUp to clear it. VSWhidbey #474259 + // So let's make sure it is really cleared when we start the drag. + _dragEnterReplies.Clear(); + + // if the AdornerWindow receives a drag message, this fn() will be called w/o a glyph - so we'll assign the last hit tested one + if (g == null) + { + g = _hitTestedGlyph; + } + + Behavior behavior = GetAppropriateBehavior(g); + if (behavior == null) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\t No behavior returning "); + return; + } + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tBehavior found calling OnDragLeave"); + behavior.OnDragLeave(g, e); + } + + private bool OnMouseDoubleClick(MouseButtons button, Point mouseLoc) + { + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return false; + } + return behavior.OnMouseDoubleClick(_hitTestedGlyph, button, mouseLoc); + } + + private bool OnMouseDown(MouseButtons button, Point mouseLoc) + { + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return false; + } + return behavior.OnMouseDown(_hitTestedGlyph, button, mouseLoc); + } + + private bool OnMouseEnter(Glyph g) + { + Behavior behavior = GetAppropriateBehavior(g); + if (behavior == null) + { + return false; + } + return behavior.OnMouseEnter(g); + } + + private bool OnMouseHover(Point mouseLoc) + { + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return false; + } + return behavior.OnMouseHover(_hitTestedGlyph, mouseLoc); + } + + private bool OnMouseLeave(Glyph g) + { + //stop tracking mouse events for MouseHover + UnHookMouseEvent(); + + Behavior behavior = GetAppropriateBehavior(g); + if (behavior == null) + { + return false; + } + return behavior.OnMouseLeave(g); + } + + private bool OnMouseMove(MouseButtons button, Point mouseLoc) + { + //hook mouse events (if we haven't already) for MouseHover + HookMouseEvent(); + + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return false; + } + return behavior.OnMouseMove(_hitTestedGlyph, button, mouseLoc); + } + + private bool OnMouseUp(MouseButtons button) + { + _dragEnterReplies.Clear(); + _validDragArgs = null; + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return false; + } + return behavior.OnMouseUp(_hitTestedGlyph, button); + } + private void HookMouseEvent() + { + if (!_trackingMouseEvent) + { + _trackingMouseEvent = true; + if (_trackMouseEvent == null) + { + _trackMouseEvent = new NativeMethods.TRACKMOUSEEVENT + { + dwFlags = NativeMethods.TME_HOVER, + hwndTrack = _adornerWindow.Handle + }; + } + SafeNativeMethods.TrackMouseEvent(_trackMouseEvent); + } + } + private void UnHookMouseEvent() + { + _trackingMouseEvent = false; + } + + private void OnDragDrop(DragEventArgs e) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "BS::OnDragDrop"); + _validDragArgs = null;//be sure to null out our cached drag args + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tNo behavior. returning"); + return; + } + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tForwarding to behavior"); + behavior.OnDragDrop(_hitTestedGlyph, e); + } + private void PropagatePaint(PaintEventArgs pe) + { + for (int i = 0; i < _adorners.Count; i++) + { + if (!_adorners[i].Enabled) + { + continue; + } + for (int j = _adorners[i].Glyphs.Count - 1; j >= 0; j--) + { + _adorners[i].Glyphs[j].Paint(pe); + } + } + } + + [SuppressMessage("Microsoft.Performance", "CA1818:DoNotConcatenateStringsInsideLoops")] + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + private void TestHook_GetRecentSnapLines(ref Message m) + { + string snapLineInfo = ""; + if (_testHook_RecentSnapLines != null) + { + foreach (string line in _testHook_RecentSnapLines) + { + snapLineInfo += line + "\n"; + } + } + TestHook_SetText(ref m, snapLineInfo); + } + + [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")] + private void TestHook_SetText(ref Message m, string text) + { + if (m.LParam == IntPtr.Zero) + { + m.Result = (IntPtr)((text.Length + 1) * Marshal.SystemDefaultCharSize); + return; + } + + if (unchecked((int)(long)m.WParam) < text.Length + 1) + { + m.Result = (IntPtr)(-1); + return; + } + + // Copy the name into the given IntPtr + char[] nullChar = new char[] { (char)0 }; + byte[] nullBytes; + byte[] bytes; + + if (Marshal.SystemDefaultCharSize == 1) + { + bytes = System.Text.Encoding.Default.GetBytes(text); + nullBytes = System.Text.Encoding.Default.GetBytes(nullChar); + } + else + { + bytes = System.Text.Encoding.Unicode.GetBytes(text); + nullBytes = System.Text.Encoding.Unicode.GetBytes(nullChar); + } + + Marshal.Copy(bytes, 0, m.LParam, bytes.Length); + Marshal.Copy(nullBytes, 0, unchecked((IntPtr)((long)m.LParam + (long)bytes.Length)), nullBytes.Length); + m.Result = (IntPtr)((bytes.Length + nullBytes.Length) / Marshal.SystemDefaultCharSize); + } + + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + private void TestHook_GetAllSnapLines(ref Message m) + { + string snapLineInfo = ""; + if (!(_serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host)) + { + return; + } + + foreach (Component comp in host.Container.Components) + { + if (!(comp is Control)) + { + continue; + } + + if (host.GetDesigner(comp) is ControlDesigner designer) + { + foreach (SnapLine line in designer.SnapLines) + { + snapLineInfo += line.ToString() + "\tAssociated Control = " + designer.Control.Name + ":::"; + } + } + } + TestHook_SetText(ref m, snapLineInfo); + } + + private void OnDragOver(DragEventArgs e) + { + // cache off our validDragArgs so we can re-fabricate enter/leave drag events + _validDragArgs = e; + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "BS::DragOver"); + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tNo behavior, exiting with DragDropEffects.None"); + e.Effect = DragDropEffects.None; + return; + } + if (_hitTestedGlyph == null || + (_hitTestedGlyph != null && !_dragEnterReplies.ContainsKey(_hitTestedGlyph))) + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tFound glyph, forwarding to behavior"); + behavior.OnDragOver(_hitTestedGlyph, e); + } + else + { + Debug.WriteLineIf(s_dragDropSwitch.TraceVerbose, "\tFell through"); + e.Effect = DragDropEffects.None; + } + } + + private void OnGiveFeedback(GiveFeedbackEventArgs e) + { + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return; + } + behavior.OnGiveFeedback(_hitTestedGlyph, e); + } + + private void OnQueryContinueDrag(QueryContinueDragEventArgs e) + { + Behavior behavior = GetAppropriateBehavior(_hitTestedGlyph); + if (behavior == null) + { + return; + } + behavior.OnQueryContinueDrag(_hitTestedGlyph, e); + } + + private void OnSystemSettingChanged(object sender, EventArgs e) + { + SyncSelection(); + DesignerUtils.SyncBrushes(); + } + + private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) + { + SyncSelection(); + DesignerUtils.SyncBrushes(); } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ContainerSelectorBehavior.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ContainerSelectorBehavior.cs new file mode 100644 index 00000000000..4fb6b7b609e --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ContainerSelectorBehavior.cs @@ -0,0 +1,247 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// This behavior is associated with the ContainerGlyph offered up by ParentControlDesigner. This Behavior simply starts a new dragdrop behavior. + /// + internal sealed class ContainerSelectorBehavior : Behavior + { + private Control _containerControl; //our related control + private IServiceProvider _serviceProvider; //used for starting a drag/drop + private BehaviorService _behaviorService; //ptr to where we start our drag/drop operation + private bool _okToMove; //state identifying if we are allowed to move the container + private Point _initialDragPoint; //cached "mouse down" point + + // For some controls, we want to change the original drag point to be the upper-left of the control in order to make it easier to drop the control at a desired location. But not all controls want this behavior. E.g. we want to do it for Panel and ToolStrip, but not for Label. Label has a ContainerSelectorBehavior via the NoResizeSelectionBorder glyph. + private readonly bool _setInitialDragPoint; + + /// + /// Constructor, here we cache off all of our member vars and sync location & size changes. + /// + internal ContainerSelectorBehavior(Control containerControl, IServiceProvider serviceProvider) + { + Init(containerControl, serviceProvider); + _setInitialDragPoint = false; + } + + /// + /// Constructor, here we cache off all of our member vars and sync location & size changes. + /// + internal ContainerSelectorBehavior(Control containerControl, IServiceProvider serviceProvider, bool setInitialDragPoint) + { + Init(containerControl, serviceProvider); + _setInitialDragPoint = setInitialDragPoint; + } + + private void Init(Control containerControl, IServiceProvider serviceProvider) + { + _behaviorService = (BehaviorService)serviceProvider.GetService(typeof(BehaviorService)); + if (_behaviorService == null) + { + Debug.Fail("Could not get the BehaviorService from ContainerSelectroBehavior!"); + return; + } + + _containerControl = containerControl; + _serviceProvider = serviceProvider; + _initialDragPoint = Point.Empty; + _okToMove = false; + } + + + public Control ContainerControl + { + get => _containerControl; + } + + /// + /// This will be true when we detect a mousedown on our glyph. The Glyph can use this state to always return 'true' from hittesting indicating that it would like all messages (like mousemove). + /// + public bool OkToMove + { + get => _okToMove; + set => _okToMove = value; + } + + public Point InitialDragPoint + { + get => _initialDragPoint; + set => _initialDragPoint = value; + } + + /// + /// If the user selects the containerglyph - select our related component. + /// + public override bool OnMouseDown(Glyph g, MouseButtons button, Point mouseLoc) + { + if (button == MouseButtons.Left) + { + //select our component + ISelectionService selSvc = (ISelectionService)_serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc != null && !_containerControl.Equals(selSvc.PrimarySelection as Control)) + { + selSvc.SetSelectedComponents(new object[] { _containerControl }, SelectionTypes.Primary | SelectionTypes.Toggle); + // Setting the selected component will create a new glyph, so this instance of the glyph won't receive any more mouse messages. So we need to tell the new glyph what the initialDragPoint and okToMove are. + if (!(g is ContainerSelectorGlyph selOld)) + { + return false; + } + foreach (Adorner a in _behaviorService.Adorners) + { + foreach (Glyph glyph in a.Glyphs) + { + if (!(glyph is ContainerSelectorGlyph selNew)) + { + continue; + } + // Don't care if we are looking at the same containerselectorglyph + if (selNew.Equals(selOld)) + { + continue; + } + // Check if the containercontrols are the same + if (!(selNew.RelatedBehavior is ContainerSelectorBehavior behNew) || !(selOld.RelatedBehavior is ContainerSelectorBehavior behOld)) + { + continue; + } + + // and the relatedcomponents are the same, then we have found the new glyph that just got added + if (behOld.ContainerControl.Equals(behNew.ContainerControl)) + { + behNew.OkToMove = true; + behNew.InitialDragPoint = DetermineInitialDragPoint(mouseLoc); + break; + } + } + } + } + else + { + InitialDragPoint = DetermineInitialDragPoint(mouseLoc); + //set 'okToMove' to true since the user actually clicked down on the glyph + OkToMove = true; + } + } + return false; + } + + private Point DetermineInitialDragPoint(Point mouseLoc) + { + if (_setInitialDragPoint) + { + // Set the mouse location to be to control's location. + Point controlOrigin = _behaviorService.ControlToAdornerWindow(_containerControl); + controlOrigin = _behaviorService.AdornerWindowPointToScreen(controlOrigin); + Cursor.Position = controlOrigin; + return controlOrigin; + } + else + { + // This really amounts to doing nothing + return mouseLoc; + } + } + + /// + /// We will compare the mouse loc to the initial point (set in onmousedown) and if we're far enough, we'll create a dropsourcebehavior object and start out drag operation! + /// + public override bool OnMouseMove(Glyph g, MouseButtons button, Point mouseLoc) + { + if (button == MouseButtons.Left && OkToMove) + { + if (InitialDragPoint == Point.Empty) + { + InitialDragPoint = DetermineInitialDragPoint(mouseLoc); + } + Size delta = new Size(Math.Abs(mouseLoc.X - InitialDragPoint.X), Math.Abs(mouseLoc.Y - InitialDragPoint.Y)); + if (delta.Width >= DesignerUtils.MinDragSize.Width / 2 || delta.Height >= DesignerUtils.MinDragSize.Height / 2) + { + //start our drag! + Point screenLoc = _behaviorService.AdornerWindowToScreen(); + screenLoc.Offset(mouseLoc.X, mouseLoc.Y); + StartDragOperation(screenLoc); + } + } + return false; + } + + /// + /// Simply clear the initial drag point, so we can start again on the next mouse down. + /// + public override bool OnMouseUp(Glyph g, MouseButtons button) + { + InitialDragPoint = Point.Empty; + OkToMove = false; + return false; + } + + /// + /// Called when we've identified that we want to start a drag operation with our data container. + /// + private void StartDragOperation(Point initialMouseLocation) + { + //need to grab a hold of some services + ISelectionService selSvc = (ISelectionService)_serviceProvider.GetService(typeof(ISelectionService)); + IDesignerHost host = (IDesignerHost)_serviceProvider.GetService(typeof(IDesignerHost)); + if (selSvc == null || host == null) + { + Debug.Fail("Can't drag this Container! Either SelectionService is null or DesignerHost is null"); + return; + } + //must identify a required parent to avoid dragging mixes of children + Control requiredParent = _containerControl.Parent; + ArrayList dragControls = new ArrayList(); + ICollection selComps = selSvc.GetSelectedComponents(); + //create our list of controls-to-drag + foreach (IComponent comp in selComps) + { + if ((comp is Control ctrl) && (ctrl.Parent != null)) + { + if (!ctrl.Parent.Equals(requiredParent)) + { + continue; //mixed selection of different parents - don't add this + } + if (host.GetDesigner(ctrl) is ControlDesigner des && (des.SelectionRules & SelectionRules.Moveable) != 0) + { + dragControls.Add(ctrl); + } + } + } + + //if we have controls-to-drag, create our new behavior and start the drag/drop operation + if (dragControls.Count > 0) + { + Point controlOrigin; + if (_setInitialDragPoint) + { + // In this case we want the initialmouselocation to be the control's origin. + controlOrigin = _behaviorService.ControlToAdornerWindow(_containerControl); + controlOrigin = _behaviorService.AdornerWindowPointToScreen(controlOrigin); + } + else + { + controlOrigin = initialMouseLocation; + } + DropSourceBehavior dsb = new DropSourceBehavior(dragControls, _containerControl.Parent, controlOrigin); + try + { + _behaviorService.DoDragDrop(dsb); + } + finally + { + OkToMove = false; + InitialDragPoint = Point.Empty; + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ContainerSelectorGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ContainerSelectorGlyph.cs new file mode 100644 index 00000000000..7012cc0b1e0 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ContainerSelectorGlyph.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// This is the glyph used to drag container controls around the designer. This glyph (and associated behavior) is created by the ParentControlDesigner. + /// + internal sealed class ContainerSelectorGlyph : Glyph + { + private Rectangle _glyphBounds; + private readonly ContainerSelectorBehavior _relatedBehavior; + + /// + /// ContainerSelectorGlyph constructor. + /// + internal ContainerSelectorGlyph(Rectangle containerBounds, int glyphSize, int glyphOffset, ContainerSelectorBehavior behavior) : base(behavior) + { + _relatedBehavior = (ContainerSelectorBehavior)behavior; + _glyphBounds = new Rectangle(containerBounds.X + glyphOffset, containerBounds.Y - (int)(glyphSize * .5), glyphSize, glyphSize); + } + + /// + /// The bounds of this Glyph. + /// + public override Rectangle Bounds + { + get => _glyphBounds; + } + + public Behavior RelatedBehavior + { + get => _relatedBehavior; + } + + /// + /// Simple hit test rule: if the point is contained within the bounds - then it is a positive hit test. + /// + public override Cursor GetHitTest(Point p) + { + if (_glyphBounds.Contains(p) || _relatedBehavior.OkToMove) + { + return Cursors.SizeAll; + } + return null; + } + + private Bitmap _glyph = null; + private Bitmap MoveGlyph + { + get + { + if (_glyph == null) + { + _glyph = new Bitmap(typeof(ContainerSelectorGlyph), "MoverGlyph.bmp"); + _glyph.MakeTransparent(); + } + return _glyph; + } + } + + /// + /// Very simple paint logic. + /// + public override void Paint(PaintEventArgs pe) + { + pe.Graphics.DrawImage(MoveGlyph, _glyphBounds); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionBehavior.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionBehavior.cs new file mode 100644 index 00000000000..c5dce31b979 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionBehavior.cs @@ -0,0 +1,154 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// This is the Behavior that represents DesignerActions for a particular control. The DesignerActionBehavior is responsible for responding to the MouseDown message and either 1) selecting the control and changing the DesignerActionGlyph's image or 2) building up a chrome menu and requesting it to be shown. Also, this Behavior acts as a proxy between "clicked" context menu items and the actual DesignerActions that they represent. + /// + internal sealed class DesignerActionBehavior : Behavior + { + private readonly IComponent _relatedComponent; //The component we are bound to + private readonly DesignerActionUI _parentUI; //ptr to the parenting UI, used for showing menus and setting selection + private DesignerActionListCollection _actionLists; //all the shortcuts! + private readonly IServiceProvider _serviceProvider; // we need to cache the service provider here to be able to create the panel with the proper arguments + private bool _ignoreNextMouseUp = false; + + /// + /// Constructor that calls base and caches off the action lists. + /// + internal DesignerActionBehavior(IServiceProvider serviceProvider, IComponent relatedComponent, DesignerActionListCollection actionLists, DesignerActionUI parentUI) + { + _actionLists = actionLists; + _serviceProvider = serviceProvider; + _relatedComponent = relatedComponent; + _parentUI = parentUI; + } + + /// + /// Returns the collection of DesignerActionLists this Behavior is managing. These will be dynamically updated (some can be removed, new ones can be added, etc...). + /// + internal DesignerActionListCollection ActionLists + { + get => _actionLists; + set => _actionLists = value; + } + + /// + /// Returns the parenting UI (a DesignerActionUI) + /// + internal DesignerActionUI ParentUI + { + get => _parentUI; + } + + /// + /// Returns the Component that this glyph is attached to. + /// + internal IComponent RelatedComponent + { + get => _relatedComponent; + } + + /// + /// Hides the designer action panel UI. + /// + internal void HideUI() + { + ParentUI.HideDesignerActionPanel(); + } + + internal DesignerActionPanel CreateDesignerActionPanel(IComponent relatedComponent) + { + // BUILD AND SHOW THE CHROME UI + DesignerActionListCollection lists = new DesignerActionListCollection(); + lists.AddRange(ActionLists); + DesignerActionPanel dap = new DesignerActionPanel(_serviceProvider); + dap.UpdateTasks(lists, new DesignerActionListCollection(), string.Format(SR.DesignerActionPanel_DefaultPanelTitle, relatedComponent.GetType().Name), null); + return dap; + } + + /// + /// Shows the designer action panel UI associated with this glyph. + /// + internal void ShowUI(Glyph g) + { + if (!(g is DesignerActionGlyph glyph)) + { + Debug.Fail("Why are we trying to 'showui' on a glyph that's not a DesignerActionGlyph?"); + return; + } + DesignerActionPanel dap = CreateDesignerActionPanel(RelatedComponent); + ParentUI.ShowDesignerActionPanel(RelatedComponent, dap, glyph); + } + + internal bool IgnoreNextMouseUp + { + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + set + { + _ignoreNextMouseUp = value; + } + } + + public override bool OnMouseDoubleClick(Glyph g, MouseButtons button, Point mouseLoc) + { + _ignoreNextMouseUp = true; + return true; + } + + public override bool OnMouseDown(Glyph g, MouseButtons button, Point mouseLoc) + { // we take the msg + return (!ParentUI.IsDesignerActionPanelVisible); + } + + /// + /// In response to a MouseUp, we will either 1) select the Glyph and control if not selected, or 2) Build up our context menu representing our DesignerActions and show it. + /// + public override bool OnMouseUp(Glyph g, MouseButtons button) + { + if (button != MouseButtons.Left || ParentUI == null) + { + return true; + } + bool returnValue = true; + if (ParentUI.IsDesignerActionPanelVisible) + { + HideUI(); + } + else if (!_ignoreNextMouseUp) + { + if (_serviceProvider != null) + { + ISelectionService selectionService = (ISelectionService)_serviceProvider.GetService(typeof(ISelectionService)); + if (selectionService != null) + { + if (selectionService.PrimarySelection != RelatedComponent) + { + List componentList = new List + { + RelatedComponent + }; + selectionService.SetSelectedComponents(componentList, SelectionTypes.Primary); + } + } + } + ShowUI(g); + } + else + { + returnValue = false; + } + _ignoreNextMouseUp = false; + return returnValue; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionGlyph.cs new file mode 100644 index 00000000000..70a2bc447dc --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionGlyph.cs @@ -0,0 +1,235 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// This Glyph represents the UI appended to a control when DesignerActions are available. Each image that represents these states are demand created. This is done because it is entirely possible that a DesignerActionGlyph will only ever be in one of these states during its lifetime... kind of sad really. + /// + internal sealed class DesignerActionGlyph : Glyph + { + internal const int CONTROLOVERLAP_X = 5; // number of pixels the anchor should be offset to the left of the control's upper-right + internal const int CONTROLOVERLAP_Y = 2; // number of pixels the anchor overlaps the control in the y-direction + + private Rectangle _bounds; // the bounds of our glyph + private readonly Adorner _adorner; // A ptr back to our adorner - so when we decide to change state, we can invalidate + private bool _mouseOver; // on mouse over, we shade our image differently, this is used to track that state + private Rectangle _alternativeBounds = Rectangle.Empty; // if !empty, this represents the bounds of the tray control this gyph is related to + private readonly Control _alternativeParent; // if this is valid - then the glyph will invalidate itself here instead of on the adorner + private bool _insidePaint; + private DockStyle _dockStyle; + private Bitmap _glyphImageClosed; + private Bitmap _glyphImageOpened; + + /// + /// Constructor that passes empty alternative bounds and parents. Typically this is done for control on the designer's surface since component tray glyphs will have these alternative values. + /// + public DesignerActionGlyph(DesignerActionBehavior behavior, Adorner adorner) : this(behavior, adorner, Rectangle.Empty, null) + { } + public DesignerActionGlyph(DesignerActionBehavior behavior, Rectangle alternativeBounds, Control alternativeParent) : this(behavior, null, alternativeBounds, alternativeParent) + { } + + /// + /// Constructor that sets the dropdownbox size, creates a our hottrack brush and invalidates the glyph (to configure location). + /// + private DesignerActionGlyph(DesignerActionBehavior behavior, Adorner adorner, Rectangle alternativeBounds, Control alternativeParent) : base(behavior) + { + _adorner = adorner; + _alternativeBounds = alternativeBounds; + _alternativeParent = alternativeParent; + Invalidate(); + } + + /// + /// Returns the bounds of our glyph. This is used by the related Behavior to determine where to show the contextmenu (list of actions). + /// + public override Rectangle Bounds + { + get => _bounds; + } + + + public DockStyle DockEdge + { + get => _dockStyle; + set + { + if (_dockStyle != value) + { + _dockStyle = value; + } + } + } + + public bool IsInComponentTray + { + get => (_adorner == null); // adorner and alternative bounds are exclusive + } + + /// + /// Standard hit test logic that returns true if the point is contained within our bounds. This is also used to manage out mouse over state. + /// + public override Cursor GetHitTest(Point p) + { + if (_bounds.Contains(p)) + { + MouseOver = true; + return Cursors.Default; + } + MouseOver = false; + return null; + } + + /// + /// Returns an image representing the + /// + private Image GlyphImageClosed + { + get + { + if (_glyphImageClosed == null) + { + _glyphImageClosed = new Bitmap(typeof(DesignerActionGlyph), "Close_left.bmp"); + _glyphImageClosed.MakeTransparent(Color.Magenta); + if (DpiHelper.IsScalingRequired) + { + DpiHelper.ScaleBitmapLogicalToDevice(ref _glyphImageClosed); + } + } + return _glyphImageClosed; + } + } + + private Image GlyphImageOpened + { + get + { + if (_glyphImageOpened == null) + { + _glyphImageOpened = new Bitmap(typeof(DesignerActionGlyph), "Open_left.bmp"); + _glyphImageOpened.MakeTransparent(Color.Magenta); + if (DpiHelper.IsScalingRequired) + { + DpiHelper.ScaleBitmapLogicalToDevice(ref _glyphImageOpened); + } + } + return _glyphImageOpened; + } + } + + internal void InvalidateOwnerLocation() + { + if (_alternativeParent != null) + { // alternative parent and adoner are exclusive... + _alternativeParent.Invalidate(_bounds); + } + else + { + _adorner.Invalidate(_bounds); + } + } + + /// + /// Called when the state for this DesignerActionGlyph changes. Or when the related component's size or location change. Here, we re-calculate the Glyph's bounds and change our image. + /// + internal void Invalidate() + { + IComponent relatedComponent = ((DesignerActionBehavior)Behavior).RelatedComponent; + Point topRight = Point.Empty; + //handle the case that our comp is a control + if (relatedComponent is Control relatedControl && !(relatedComponent is ToolStripDropDown) && _adorner != null) + { + topRight = _adorner.BehaviorService.ControlToAdornerWindow(relatedControl); + topRight.X += relatedControl.Width; + } + // ISSUE: we can't have this special cased here - we should find a more generic approach to solving this problem special logic here for our comp being a toolstrip item + else + { + // update alternative bounds if possible... + if (_alternativeParent is ComponentTray compTray) + { + ComponentTray.TrayControl trayControl = compTray.GetTrayControlFromComponent(relatedComponent); + if (trayControl != null) + { + _alternativeBounds = trayControl.Bounds; + } + } + Rectangle newRect = DesignerUtils.GetBoundsForNoResizeSelectionType(_alternativeBounds, SelectionBorderGlyphType.Top); + topRight.X = newRect.Right; + topRight.Y = newRect.Top; + } + topRight.X -= (GlyphImageOpened.Width + CONTROLOVERLAP_X); + topRight.Y -= (GlyphImageOpened.Height - CONTROLOVERLAP_Y); + _bounds = (new Rectangle(topRight.X, topRight.Y, GlyphImageOpened.Width, GlyphImageOpened.Height)); + } + + /// + /// Used to manage the mouse-pointer-is-over-glyph state. If this is true, then we will shade our BoxImage in the Paint logic. + /// + private bool MouseOver + { + get => _mouseOver; + set + { + if (_mouseOver != value) + { + _mouseOver = value; + + InvalidateOwnerLocation(); + } + } + } + + /// + /// Responds to a paint event. This Glyph will paint its current image and, if MouseHover is true, we'll paint over the image with the 'hoverBrush'. + /// + public override void Paint(PaintEventArgs pe) + { + Image image; + if (Behavior is DesignerActionBehavior) + { + if (_insidePaint) + { + return; + } + IComponent panelComponent = ((DesignerActionUI)((DesignerActionBehavior)Behavior).ParentUI).LastPanelComponent; + IComponent relatedComponent = ((DesignerActionBehavior)Behavior).RelatedComponent; + if (panelComponent != null && panelComponent == relatedComponent) + { + image = GlyphImageOpened; + } + else + { + image = GlyphImageClosed; + } + try + { + _insidePaint = true; + pe.Graphics.DrawImage(image, _bounds.Left, _bounds.Top); + if (MouseOver || (panelComponent != null && panelComponent == relatedComponent)) + { + pe.Graphics.FillRectangle(DesignerUtils.HoverBrush, Rectangle.Inflate(_bounds, -1, -1)); + } + } + finally + { + _insidePaint = false; + } + } + } + + /// + /// Called by the ComponentTray when a tray control changes location. + /// + internal void UpdateAlternativeBounds(Rectangle newBounds) + { + _alternativeBounds = newBounds; + Invalidate(); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionKeyboardBehavior.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionKeyboardBehavior.cs new file mode 100644 index 00000000000..21ff6c6082e --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DesignerActionKeyboardBehavior.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Design; +using System.Diagnostics; + +namespace System.Windows.Forms.Design.Behavior +{ + internal sealed class DesignerActionKeyboardBehavior : Behavior + { + private readonly DesignerActionPanel _panel; + private readonly IMenuCommandService _menuService; + private readonly DesignerActionUIService _daUISvc; + private static readonly Guid s_vSStandardCommandSet97 = new Guid("{5efc7975-14bc-11cf-9b2b-00aa00573819}"); + + public DesignerActionKeyboardBehavior(DesignerActionPanel panel, IServiceProvider serviceProvider, BehaviorService behaviorService) : + base(true, behaviorService) + { + _panel = panel; + if (serviceProvider != null) + { + _menuService = serviceProvider.GetService(typeof(IMenuCommandService)) as IMenuCommandService; + Debug.Assert(_menuService != null, "we should have found a menu service here..."); + _daUISvc = serviceProvider.GetService(typeof(DesignerActionUIService)) as DesignerActionUIService; + } + } + // THIS should not stay here, creation of a custom command or of the real thing should be handled in the designeractionpanel itself + public override MenuCommand FindCommand(CommandID commandId) + { + if (_panel != null && _menuService != null) + { + // if the command we're looking for is handled by the panel, just tell VS that this command is disabled. otherwise let it through as usual... + foreach (CommandID candidateCommandId in _panel.FilteredCommandIDs) + { + // VisualStudio shell implements a mutable derived class from the base CommandID. The mutable class compares overridden properties instead of the read-only backing fields when testing equality of command IDs. Thus Equals method is asymmetrical derived class's override that compares properties is the accurate one. + if (commandId.Equals(candidateCommandId)) + { + MenuCommand dummyMC = new MenuCommand(delegate { }, commandId) + { + Enabled = false + }; + return dummyMC; + } + } + // in case of a ctrl-tab we need to close the DAP + if (_daUISvc != null && commandId.Guid == DesignerActionKeyboardBehavior.s_vSStandardCommandSet97 && commandId.ID == 1124) + { + _daUISvc.HideUI(null); + } + } + return base.FindCommand(commandId); // this will route the request to the parent behavior + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DragAssistanceManager.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DragAssistanceManager.cs new file mode 100644 index 00000000000..60db5abacd8 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DragAssistanceManager.cs @@ -0,0 +1,1169 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The DragAssistanceManager, for lack of a better name, is responsible for integrating SnapLines into the DragBehavior. At the beginning of a DragBehavior this class is instantiated and at every mouse move this class is called and given the opportunity to adjust the position of the drag. The DragAssistanceManager needs to work as fast as possible - so not to interupt a drag operation. Because of this, this class has many global variables that are re-used, in hopes to limit the # of allocations per mouse move / drag operation. Also, for loops are used extensively (instead of foreach calls) to eliminate the creation of an enumerator. + /// + [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] + internal sealed class DragAssistanceManager + { + private readonly BehaviorService _behaviorService; + private readonly IServiceProvider _serviceProvider; + private readonly Graphics _graphics; //graphics to the adornerwindow + private readonly IntPtr _rootComponentHandle; //used for mapping window points of nested controls + private Point _dragOffset; //the offset from the new drag pos compared to the last + private Rectangle _cachedDragRect; //used to store drag rect between erasing & waiting to render + private readonly Pen _edgePen = SystemPens.Highlight; + private readonly bool _disposeEdgePen = false; + private readonly Pen _baselinePen = new Pen(Color.Fuchsia); + // These are global lists of all the existing vertical and hoirizontal snaplineson the designer's surface excluding the targetControl. All SnapLine coords in theselists have been properly adjusted for the AdornerWindow coords. + private readonly ArrayList _verticalSnapLines = new ArrayList(); + private readonly ArrayList _horizontalSnapLines = new ArrayList(); + // These are SnapLines that represent our target control. + private readonly ArrayList _targetVerticalSnapLines = new ArrayList(); + private readonly ArrayList _targetHorizontalSnapLines = new ArrayList(); + // This is a list of all the different type of SnapLines our target controlhas. When compiling our global SnapLine lists, if we see a SnapLineTypethat doesn't exist on our target - we can safely ignore it + private readonly ArrayList _targetSnapLineTypes = new ArrayList(); + // These are created in our init() method (so we don't have to recreate them for every mousemove). These arrays represent the closest distance to any snap point on our target control. Once these are calculated - we can: 1) remove anything > than snapDistance and 2) determine the smallest distanceoverall + private int[] _verticalDistances; + private int[] _horizontalDistances; + //T hese are cleared and populated on every mouse move. These lists contain all the new vertical and horizontal lines we need to draw. At the end of each mouse move - these lines are stored off in the vertLines and horzLines arrays. This way - we can keep track of old snap lines and can avoid erasing and redrawing the same line. HA. + private readonly ArrayList _tempVertLines = new ArrayList(); + private readonly ArrayList _tempHorzLines = new ArrayList(); + private Line[] _vertLines = new Line[0]; + private Line[] _horzLines = new Line[0]; + // When we draw snap lines - we only draw lines from the targetControl to the control we're snapping to. To do this, we'll keep a hashtable... format: snapLineToBounds[SnapLine]=ControlBounds. + private readonly Hashtable _snapLineToBounds = new Hashtable(); + // We remember the last set of (vert & horz) lines we draw so that we can push them to the beh. svc. From there, if we receive a test hook message requesting these - we got 'em + private Line[] _recentLines; + private readonly Image _backgroundImage; //instead of calling .invalidate on the windows below us, we'll just draw over w/the background image + private const int SnapDistance = 8; //default snapping distance (pixels) + private int _snapPointX, _snapPointY; //defines the snap adjustment that needs to be made during the mousemove/drag operation + private const int INVALID_VALUE = 0x1111; //used to represent 'un-set' distances + private readonly bool _resizing; // Are we resizing? + private readonly bool _ctrlDrag; // Are we in a ctrl-drag? + + /// + /// Internal constructor called that only takes a service provider. Here it is assumed that all painting will be done to the AdornerWindow and that there are no target controsl to exclude from snapping. + /// + internal DragAssistanceManager(IServiceProvider serviceProvider) : this(serviceProvider, null, null, null, false, false) + { + } + + /// + /// Internal constructor that takes the service provider and the list of dragCompoents. + /// + internal DragAssistanceManager(IServiceProvider serviceProvider, ArrayList dragComponents) : this(serviceProvider, null, dragComponents, null, false, false) + { + } + + /// + /// Internal constructor that takes the service provider, the list of dragCompoents, and a boolean + /// indicating that we are resizing. + /// + internal DragAssistanceManager(IServiceProvider serviceProvider, ArrayList dragComponents, bool resizing) : this(serviceProvider, null, dragComponents, null, resizing, false) + { + } + + /// + /// Internal constructor called by DragBehavior. + /// + internal DragAssistanceManager(IServiceProvider serviceProvider, Graphics graphics, ArrayList dragComponents, Image backgroundImage, bool ctrlDrag) : this(serviceProvider, graphics, dragComponents, backgroundImage, false, ctrlDrag) + { + } + + /// + /// Internal constructor called by DragBehavior. + /// + [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] + internal DragAssistanceManager(IServiceProvider serviceProvider, Graphics graphics, ArrayList dragComponents, Image backgroundImage, bool resizing, bool ctrlDrag) + { + _serviceProvider = serviceProvider; + _behaviorService = serviceProvider.GetService(typeof(BehaviorService)) as BehaviorService; + if (!(serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host) || _behaviorService == null) + { + Debug.Fail("Cannot get DesignerHost or BehaviorService"); + return; + } + + if (graphics == null) + { + _graphics = _behaviorService.AdornerWindowGraphics; + } + else + { + _graphics = graphics; + } + + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uiService) + { + //Can't use 'as' here since Color is a value type + if (uiService.Styles["VsColorSnaplines"] is Color) + { + _edgePen = new Pen((Color)uiService.Styles["VsColorSnaplines"]); + _disposeEdgePen = true; + } + + if (uiService.Styles["VsColorSnaplinesTextBaseline"] is Color) + { + _baselinePen.Dispose(); + _baselinePen = new Pen((Color)uiService.Styles["VsColorSnaplinesTextBaseline"]); + } + } + _backgroundImage = backgroundImage; + _rootComponentHandle = host.RootComponent is Control ? ((Control)host.RootComponent).Handle : IntPtr.Zero; + _resizing = resizing; + _ctrlDrag = ctrlDrag; + Initialize(dragComponents, host); + } + + /// + /// Adjusts then adds each snap line the designer has to offer to either our global horizontal and vertical lists or our target lists. Note that we also keep track of our target snapline types - 'cause we can safely ignore all other types. If valid target is false- then we don't yet know what we're snapping against - so we'll exclude the check below to skip unwanted snap line types. + /// + private void AddSnapLines(ControlDesigner controlDesigner, ArrayList horizontalList, ArrayList verticalList, bool isTarget, bool validTarget) + { + IList snapLines = controlDesigner.SnapLines; + //Used for padding snaplines + Rectangle controlRect = controlDesigner.Control.ClientRectangle; + //Used for all others + Rectangle controlBounds = controlDesigner.Control.Bounds; + // Now map the location + controlBounds.Location = controlRect.Location = _behaviorService.ControlToAdornerWindow(controlDesigner.Control); + // Remember the offset -- we need those later + int xOffset = controlBounds.Left; + int yOffset = controlBounds.Top; + + // THIS IS ONLY NEEDED FOR PADDING SNAPLINES + // We need to adjust the bounds to the client area. This is so that we don't include borders + titlebar in the snaplines. In order to add padding, we need to get the offset from the usable client area of our control and the actual origin of our control. In other words: how big is the non-client area here? Ex: we want to add padding on a form to the insides of the borders and below the titlebar. + Point offset = controlDesigner.GetOffsetToClientArea(); + controlRect.X += offset.X; //offset for non-client area + controlRect.Y += offset.Y; //offset for non-client area + + //Adjust each snapline to local coords and add it to our global list + foreach (SnapLine snapLine in snapLines) + { + if (isTarget) + { + //we will remove padding snaplines from targets - it doesn't make sense to snap to the target's padding lines + if (snapLine.Filter != null && snapLine.Filter.StartsWith(SnapLine.Padding)) + { + continue; + } + + if (validTarget && !_targetSnapLineTypes.Contains(snapLine.SnapLineType)) + { + _targetSnapLineTypes.Add(snapLine.SnapLineType); + } + } + else + { + if (validTarget && !_targetSnapLineTypes.Contains(snapLine.SnapLineType)) + { + continue; + } + // store off the bounds in our hashtable, so if we draw snaplines we know the length of the line we need to remember different bounds based on what type of snapline this is. + if ((snapLine.Filter != null) && snapLine.Filter.StartsWith(SnapLine.Padding)) + { + _snapLineToBounds.Add(snapLine, controlRect); + } + else + { + _snapLineToBounds.Add(snapLine, controlBounds); + } + } + + if (snapLine.IsHorizontal) + { + snapLine.AdjustOffset(yOffset); + horizontalList.Add(snapLine); + } + else + { + snapLine.AdjustOffset(xOffset); + verticalList.Add(snapLine); + } + } + } + + /// + /// Build up a distance array of all same-type-alignment pts to the closest point on our targetControl. Also, keep track of the smallest distance overall. + /// + private int BuildDistanceArray(ArrayList snapLines, ArrayList targetSnapLines, int[] distances, Rectangle dragBounds) + { + int smallestDistance = INVALID_VALUE; + int highestPriority = 0; + + for (int i = 0; i < snapLines.Count; i++) + { + SnapLine snapLine = (SnapLine)snapLines[i]; + if (IsMarginOrPaddingSnapLine(snapLine)) + { + // validate margin and padding snaplines (to make sure it intersects with the dragbounds) if not, skip this guy + if (!ValidateMarginOrPaddingLine(snapLine, dragBounds)) + { + distances[i] = INVALID_VALUE; + continue; + } + } + + int smallestDelta = INVALID_VALUE; //some large # + for (int j = 0; j < targetSnapLines.Count; j++) + { + SnapLine targetSnapLine = (SnapLine)targetSnapLines[j]; + + if (SnapLine.ShouldSnap(snapLine, targetSnapLine)) + { + int delta = targetSnapLine.Offset - snapLine.Offset; + if (Math.Abs(delta) < Math.Abs(smallestDelta)) + { + smallestDelta = delta; + } + } + } + + distances[i] = smallestDelta; + int pri = (int)((SnapLine)snapLines[i]).Priority; + //save off this delta for the overall smallest delta! Need to check the priority here as well if the distance is the same. E.g. smallestDistance so far is 1, for a Low snapline. We now find another distance of -1, for a Medium snapline. The old check if (Math.Abs(smallestDelta) < Math.Abs(smallestDistance)) would not set smallestDistance to -1, since the ABSOLUTE values are the same. Since the return value is used to phycially move the control, we would move the control in the direction of the Low snapline, but draw the Medium snapline in the opposite direction. + if ((Math.Abs(smallestDelta) < Math.Abs(smallestDistance)) || + ((Math.Abs(smallestDelta) == Math.Abs(smallestDistance)) && (pri > highestPriority))) + { + smallestDistance = smallestDelta; + if (pri != (int)SnapLinePriority.Always) + { + highestPriority = pri; + } + } + } + return smallestDistance; + } + + /// + /// Here, we erase all of our old horizontal and vertical snaplines UNLESS they are also contained in our tempHorzLines or tempVertLines arrays - if they are - then erasing them would be redundant (since we know we want to draw them on this mousemove) + /// + private Line[] EraseOldSnapLines(Line[] lines, ArrayList tempLines) + { + if (lines != null) + { + for (int i = 0; i < lines.Length; i++) + { + Rectangle invalidRect = Rectangle.Empty; + bool foundMatch = false; + Line line = lines[i]; + if (tempLines != null) + { + for (int j = 0; j < tempLines.Count; j++) + { + if (line.LineType != ((Line)tempLines[j]).LineType) + { + // If the lines are not the same type, then we should forcefully try to remove it. Say you have a Panel with a Button in it. By default Panel.Padding = 0, and Button.Margin = 3. As you move the button to the left, you will first get the combined LEFT margin+padding snap line. If you keep moving the button, you will now snap to the Left edge, and you will get the Blue snapline. You now move the button back to the right, and you will immediately snap to the LEFT Padding snapline. But what's gonna happen. Both the old (Left) snapline, and the LEFT Padding snapline (remember these are the panels) have the same coordinates, since Panel.Padding is 0. Thus Line.GetDiffs will return a non-null diffs. BUT e.g the first line will result in an invalidRect of (x1,y1,0,0), this we end up invalidating only a small portion of the existing Blue (left) Snapline. That's actually not okay since VERTICAL (e.g. LEFT) padding snaplines actually end up getting drawn HORIZONTALLY - thus we didn't really invalidate correctly. + continue; + } + Line[] diffs = Line.GetDiffs(line, (Line)tempLines[j]); + if (diffs != null) + { + for (int k = 0; k < diffs.Length; k++) + { + invalidRect = new Rectangle(diffs[k].x1, diffs[k].y1, diffs[k].x2 - diffs[k].x1, diffs[k].y2 - diffs[k].y1); + + invalidRect.Inflate(1, 1); + if (_backgroundImage != null) + { + _graphics.DrawImage(_backgroundImage, invalidRect, invalidRect, GraphicsUnit.Pixel); + } + else + { + _behaviorService.Invalidate(invalidRect); + } + } + foundMatch = true; + break; + } + } + } + + if (!foundMatch) + { + invalidRect = new Rectangle(line.x1, line.y1, line.x2 - line.x1, line.y2 - line.y1); + invalidRect.Inflate(1, 1); + if (_backgroundImage != null) + { + _graphics.DrawImage(_backgroundImage, invalidRect, invalidRect, GraphicsUnit.Pixel); + } + else + { + _behaviorService.Invalidate(invalidRect); + } + } + } + } + + if (tempLines != null) + { + // Now, store off all the new lines (from the temp structures), so next time around (next mousemove message) we know which lines to erase and which ones to keep + lines = new Line[tempLines.Count]; + tempLines.CopyTo(lines); + } + else + { + lines = new Line[0]; + } + return lines; + } + + internal void EraseSnapLines() + { + EraseOldSnapLines(_vertLines, null); + EraseOldSnapLines(_horzLines, null); + } + + /// + /// This internal method returns a snap line[] representing the last SnapLines that were rendered before this algorithm was stopped (usually by an OnMouseUp). This is used for storing additional toolbox drag/drop info and testing hooks. + /// + internal Line[] GetRecentLines() + { + if (_recentLines != null) + { + return _recentLines; + } + return new Line[0]; + } + + private void IdentifyAndStoreValidLines(ArrayList snapLines, int[] distances, Rectangle dragBounds, int smallestDistance) + { + int highestPriority = 1; //low + //identify top pri + for (int i = 0; i < distances.Length; i++) + { + if (distances[i] == smallestDistance) + { + int pri = (int)((SnapLine)snapLines[i]).Priority; + if ((pri > highestPriority) && (pri != (int)SnapLinePriority.Always)) + { // Always is a special category + highestPriority = pri; + } + } + } + + //store all snapLines equal to the smallest distance (of the highest priority) + for (int i = 0; i < distances.Length; i++) + { + if ((distances[i] == smallestDistance) && + (((int)((SnapLine)snapLines[i]).Priority == highestPriority) || + ((int)((SnapLine)snapLines[i]).Priority == (int)SnapLinePriority.Always))) + { //always render SnapLines with Priority.Always which has the same distance. + StoreSnapLine((SnapLine)snapLines[i], dragBounds); + } + } + } + + // Returns true of this child component (off the root control) should add its snaplines to the collection + private bool AddChildCompSnaplines(IComponent comp, ArrayList dragComponents, Rectangle clipBounds, Control targetControl) + { + if (!(comp is Control control) || //has to be a control to get snaplines + (dragComponents != null && dragComponents.Contains(comp) && !_ctrlDrag) || //cannot be something that we are dragging, unless we are in a ctrlDrag + IsChildOfParent(control, targetControl) ||//cannot be a child of the control we will drag + !clipBounds.IntersectsWith(control.Bounds) || //has to be partially visible on the rootcomp's surface + control.Parent == null || // control must have a parent. + !control.Visible) + { //control itself has to be visible -- we do mean visible, not ShadowedVisible + return false; + } + + Control c = control; + if (!c.Equals(targetControl)) + { + if (_serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host) + { + if (host.GetDesigner(c) is ControlDesigner controlDesigner) + { + return controlDesigner.ControlSupportsSnaplines; + } + } + } + return true; + } + + // Returns true if we should add snaplines for this control + private bool AddControlSnaplinesWhenResizing(ControlDesigner designer, Control control, Control targetControl) + { + // do not add snaplines if we are resizing the control is a container control with AutoSize set to true and the control is the parent of the targetControl + if (_resizing && + (designer is ParentControlDesigner) && + (control.AutoSize == true) && + (targetControl != null) && + (targetControl.Parent != null) && + (targetControl.Parent.Equals(control))) + { + return false; + } + return true; + } + + /// + /// Initializes our class - we cache all snap lines for every control we can find. This is done for perf. reasons. + /// + private void Initialize(ArrayList dragComponents, IDesignerHost host) + { + // our targetControl will always be the 0th component in our dragComponents array list (a.k.a. the primary selected component). + Control targetControl = null; + if (dragComponents != null && dragComponents.Count > 0) + { + targetControl = dragComponents[0] as Control; + } + Control rootControl = host.RootComponent as Control; + // the clipping bounds will be used to ignore all controls that are completely outside of our rootcomponent's bounds -this way we won't end up snapping to controls that are not visible on the form's surface + Rectangle clipBounds = new Rectangle(0, 0, rootControl.ClientRectangle.Width, rootControl.ClientRectangle.Height); + clipBounds.Inflate(-1, -1); + //determine the screen offset from our rootComponent to the AdornerWindow (since all drag notification coords will be in adorner window coords) + if (targetControl != null) + { + _dragOffset = _behaviorService.ControlToAdornerWindow(targetControl); + } + else + { + _dragOffset = _behaviorService.MapAdornerWindowPoint(rootControl.Handle, Point.Empty); + if (rootControl.Parent != null && rootControl.Parent.IsMirrored) + { + _dragOffset.Offset(-rootControl.Width, 0); + } + } + + if (targetControl != null) + { + bool disposeDesigner = false; + //get all the target snapline information we need to create one then + if (!(host.GetDesigner(targetControl) is ControlDesigner designer)) + { + designer = TypeDescriptor.CreateDesigner(targetControl, typeof(IDesigner)) as ControlDesigner; + if (designer != null) + { + //Make sure the control is not forced visible + designer.ForceVisible = false; + designer.Initialize(targetControl); + disposeDesigner = true; + } + } + AddSnapLines(designer, _targetHorizontalSnapLines, _targetVerticalSnapLines, true, targetControl != null); + if (disposeDesigner) + { + designer.Dispose(); + } + } + + //get SnapLines for all our children (nested too) off our root control + foreach (IComponent comp in host.Container.Components) + { + if (!AddChildCompSnaplines(comp, dragComponents, clipBounds, targetControl)) + { + continue; + } + + if (host.GetDesigner(comp) is ControlDesigner designer) + { + if (AddControlSnaplinesWhenResizing(designer, comp as Control, targetControl)) + { + AddSnapLines(designer, _horizontalSnapLines, _verticalSnapLines, false, targetControl != null); + } + + // Does the designer have internal control designers for which we need to add snaplines (like SplitPanelContainer, ToolStripContainer) + int numInternalDesigners = designer.NumberOfInternalControlDesigners(); + for (int i = 0; i < numInternalDesigners; i++) + { + ControlDesigner internalDesigner = designer.InternalControlDesigner(i); + if (internalDesigner != null && + AddChildCompSnaplines(internalDesigner.Component, dragComponents, clipBounds, targetControl) && + AddControlSnaplinesWhenResizing(internalDesigner, internalDesigner.Component as Control, targetControl)) + { + AddSnapLines(internalDesigner, _horizontalSnapLines, _verticalSnapLines, false, targetControl != null); + } + } + } + } + + // Now that we know how many snaplines everyone has, we can create temp arrays now. Intentionally avoiding this on every mousemove. + _verticalDistances = new int[_verticalSnapLines.Count]; + _horizontalDistances = new int[_horizontalSnapLines.Count]; + } + + /// + /// Helper function that determines if the child control is related to the parent. + /// + private static bool IsChildOfParent(Control child, Control parent) + { + if (child == null || parent == null) + { + return false; + } + Control currentParent = child.Parent; + while (currentParent != null) + { + if (currentParent.Equals(parent)) + { + return true; + } + currentParent = currentParent.Parent; + } + return false; + } + + /// + /// Helper function that identifies margin or padding snaplines + /// + private static bool IsMarginOrPaddingSnapLine(SnapLine snapLine) + { + return snapLine.Filter != null && (snapLine.Filter.StartsWith(SnapLine.Margin) || snapLine.Filter.StartsWith(SnapLine.Padding)); + } + + /// + /// Returns the offset in which the targetControl's rect needs to be re-positioned (given the direction by 'directionOffset') in order to align with the nearest possible snapline. This is called by commandSet during keyboard movements to auto-snap the control around the designer. + /// + internal Point OffsetToNearestSnapLocation(Control targetControl, IList targetSnaplines, Point directionOffset) + { + _targetHorizontalSnapLines.Clear(); + _targetVerticalSnapLines.Clear(); + //manually add our snaplines as targets + foreach (SnapLine snapline in targetSnaplines) + { + if (snapline.IsHorizontal) + { + _targetHorizontalSnapLines.Add(snapline); + } + else + { + _targetVerticalSnapLines.Add(snapline); + } + } + return OffsetToNearestSnapLocation(targetControl, directionOffset); + } + + /// + /// Returns the offset in which the targetControl's rect needs to be re-positioned (given the direction by 'directionOffset') in order to align with the nearest possible snapline. This is called by commandSet during keyboard movements to auto-snap the control around the designer. + /// + internal Point OffsetToNearestSnapLocation(Control targetControl, Point directionOffset) + { + Point offset = Point.Empty; + Rectangle currentBounds = new Rectangle(_behaviorService.ControlToAdornerWindow(targetControl), targetControl.Size); + if (directionOffset.X != 0) + {//movement somewhere in the x dir + //first, build up our distance array + BuildDistanceArray(_verticalSnapLines, _targetVerticalSnapLines, _verticalDistances, currentBounds); + //now start with the smallest distance and find the first snapline we would intercept given our horizontal direction + int minRange = directionOffset.X < 0 ? 0 : currentBounds.X; + int maxRange = directionOffset.X < 0 ? currentBounds.Right : int.MaxValue; + offset.X = FindSmallestValidDistance(_verticalSnapLines, _verticalDistances, minRange, maxRange, directionOffset.X); + if (offset.X != 0) + { + //store off the line structs for actual rendering + IdentifyAndStoreValidLines(_verticalSnapLines, _verticalDistances, currentBounds, offset.X); + if (directionOffset.X < 0) + { + offset.X *= -1; + } + } + } + if (directionOffset.Y != 0) + {//movement somewhere in the y dir + //first, build up our distance array + BuildDistanceArray(_horizontalSnapLines, _targetHorizontalSnapLines, _horizontalDistances, currentBounds); + //now start with the smallest distance and find the first snapline we would intercept given our horizontal direction + int minRange = directionOffset.Y < 0 ? 0 : currentBounds.Y; + int maxRange = directionOffset.Y < 0 ? currentBounds.Bottom : int.MaxValue; + offset.Y = FindSmallestValidDistance(_horizontalSnapLines, _horizontalDistances, minRange, maxRange, directionOffset.Y); + if (offset.Y != 0) + { + //store off the line structs for actual rendering + IdentifyAndStoreValidLines(_horizontalSnapLines, _horizontalDistances, currentBounds, offset.Y); + if (directionOffset.Y < 0) + { + offset.Y *= -1; + } + } + } + + if (!offset.IsEmpty) + { + //setup the cached info for drawing + _cachedDragRect = currentBounds; + _cachedDragRect.Offset(offset.X, offset.Y); + if (offset.X != 0) + { + _vertLines = new Line[_tempVertLines.Count]; + _tempVertLines.CopyTo(_vertLines); + } + if (offset.Y != 0) + { + _horzLines = new Line[_tempHorzLines.Count]; + _tempHorzLines.CopyTo(_horzLines); + } + } + + return offset; + } + + private static int FindSmallestValidDistance(ArrayList snapLines, int[] distances, int min, int max, int direction) + { + int distanceValue = 0; + int snapLineIndex = 0; + // loop while we still have valid distance to check and try to find the smallest valid distance + while (true) + { + // get the next smallest snapline index + snapLineIndex = SmallestDistanceIndex(distances, direction, out distanceValue); + + if (snapLineIndex == INVALID_VALUE) + { + // ran out of valid distances + break; + } + if (IsWithinValidRange(((SnapLine)snapLines[snapLineIndex]).Offset, min, max)) + { + // found it - make sure we restore the original value for rendering the snap line in the future + distances[snapLineIndex] = distanceValue; + return distanceValue; + } + } + return 0; + } + + private static bool IsWithinValidRange(int offset, int min, int max) => offset > min && offset < max; + + private static int SmallestDistanceIndex(int[] distances, int direction, out int distanceValue) + { + distanceValue = INVALID_VALUE; + int smallestIndex = INVALID_VALUE; + //check for valid array + if (distances.Length == 0) + { + return smallestIndex; + } + + //find the next smallest + for (int i = 0; i < distances.Length; i++) + { + // If a distance is 0 or if it is to our left and we're heading right or if it is to our right and we're heading left then we can null this value out + if (distances[i] == 0 || + distances[i] > 0 && direction > 0 || + distances[i] < 0 && direction < 0) + { + distances[i] = INVALID_VALUE; + } + + if (Math.Abs(distances[i]) < distanceValue) + { + distanceValue = Math.Abs(distances[i]); + smallestIndex = i; + } + } + + if (smallestIndex < distances.Length) + { + //return and clear the smallest one we found + distances[smallestIndex] = INVALID_VALUE; + } + return smallestIndex; + } + + /// + /// Actually draws the snaplines based on type, location, and specified pen + /// + private void RenderSnapLines(Line[] lines, Rectangle dragRect) + { + Pen currentPen; + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].LineType == LineType.Margin || lines[i].LineType == LineType.Padding) + { + currentPen = _edgePen; + if (lines[i].x1 == lines[i].x2) + {//vertical margin + int coord = Math.Max(dragRect.Top, lines[i].OriginalBounds.Top); + coord += (Math.Min(dragRect.Bottom, lines[i].OriginalBounds.Bottom) - coord) / 2; + lines[i].y1 = lines[i].y2 = coord; + if (lines[i].LineType == LineType.Margin) + { + lines[i].x1 = Math.Min(dragRect.Right, lines[i].OriginalBounds.Right); + lines[i].x2 = Math.Max(dragRect.Left, lines[i].OriginalBounds.Left); + } + else if (lines[i].PaddingLineType == PaddingLineType.PaddingLeft) + { + lines[i].x1 = lines[i].OriginalBounds.Left; + lines[i].x2 = dragRect.Left; + } + else + { + Debug.Assert(lines[i].PaddingLineType == PaddingLineType.PaddingRight); + lines[i].x1 = dragRect.Right; + lines[i].x2 = lines[i].OriginalBounds.Right; + } + lines[i].x2--; //off by 1 adjust + } + else + {//horizontal margin + int coord = Math.Max(dragRect.Left, lines[i].OriginalBounds.Left); + coord += (Math.Min(dragRect.Right, lines[i].OriginalBounds.Right) - coord) / 2; + lines[i].x1 = lines[i].x2 = coord; + if (lines[i].LineType == LineType.Margin) + { + lines[i].y1 = Math.Min(dragRect.Bottom, lines[i].OriginalBounds.Bottom); + lines[i].y2 = Math.Max(dragRect.Top, lines[i].OriginalBounds.Top); + } + else if (lines[i].PaddingLineType == PaddingLineType.PaddingTop) + { + lines[i].y1 = lines[i].OriginalBounds.Top; + lines[i].y2 = dragRect.Top; + } + else + { + Debug.Assert(lines[i].PaddingLineType == PaddingLineType.PaddingBottom); + lines[i].y1 = dragRect.Bottom; + lines[i].y2 = lines[i].OriginalBounds.Bottom; + } + lines[i].y2--; //off by 1 adjust + } + } + else if (lines[i].LineType == LineType.Baseline) + { + currentPen = _baselinePen; + lines[i].x2 -= 1; //off by 1 adjust + } + else + { + //default to edgePen + currentPen = _edgePen; + if (lines[i].x1 == lines[i].x2) + { + lines[i].y2--; //off by 1 adjustment + } + else + { + lines[i].x2--; //off by 1 adjustment + } + } + _graphics.DrawLine(currentPen, lines[i].x1, lines[i].y1, lines[i].x2, lines[i].y2); + } + } + + /// + /// Performance improvement: Given an snapline we will render, check if it overlaps with an existing snapline. If so, combine the two. + /// + private static void CombineSnaplines(Line snapLine, ArrayList currentLines) + { + bool merged = false; + for (int i = 0; i < currentLines.Count; i++) + { + Line curLine = (Line)currentLines[i]; + Line mergedLine = Line.Overlap(snapLine, curLine); + if (mergedLine != null) + { + currentLines[i] = mergedLine; + merged = true; + } + } + if (!merged) + { + currentLines.Add(snapLine); + } + } + + /// + /// Here, we store all the SnapLines we will render. This way we can erase them when they are no longer needed. + /// + [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] + private void StoreSnapLine(SnapLine snapLine, Rectangle dragBounds) + { + Rectangle bounds = (Rectangle)_snapLineToBounds[snapLine]; + // In order for CombineSnapelines to work correctly, we have to determine the type first + LineType type = LineType.Standard; + if (IsMarginOrPaddingSnapLine(snapLine)) + { + type = snapLine.Filter.StartsWith(SnapLine.Margin) ? LineType.Margin : LineType.Padding; + } + //propagate the baseline through to the linetype + else if (snapLine.SnapLineType == SnapLineType.Baseline) + { + type = LineType.Baseline; + } + + Line line; + if (snapLine.IsVertical) + { + line = new Line(snapLine.Offset, Math.Min(dragBounds.Top + (_snapPointY != INVALID_VALUE ? _snapPointY : 0), bounds.Top), + snapLine.Offset, Math.Max(dragBounds.Bottom + (_snapPointY != INVALID_VALUE ? _snapPointY : 0), bounds.Bottom)) + { + LineType = type + }; + // Performance improvement: Check if the newly added line overlaps existing lines and if so, combine them. + CombineSnaplines(line, _tempVertLines); + } + else + { + line = new Line(Math.Min(dragBounds.Left + (_snapPointX != INVALID_VALUE ? _snapPointX : 0), bounds.Left), snapLine.Offset, + Math.Max(dragBounds.Right + (_snapPointX != INVALID_VALUE ? _snapPointX : 0), bounds.Right), snapLine.Offset) + { + LineType = type + }; + // Performance improvement: Check if the newly added line overlaps existing lines and if so, combine them. + CombineSnaplines(line, _tempHorzLines); + } + + if (IsMarginOrPaddingSnapLine(snapLine)) + { + line.OriginalBounds = bounds; + // need to know which padding line (left, right) we are storing. The original check in RenderSnapLines was wrong. It assume that the dragRect was completely within the OriginalBounds which is not necessarily true + if (line.LineType == LineType.Padding) + { + switch (snapLine.Filter) + { + case SnapLine.PaddingRight: + line.PaddingLineType = PaddingLineType.PaddingRight; + break; + case SnapLine.PaddingLeft: + line.PaddingLineType = PaddingLineType.PaddingLeft; + break; + case SnapLine.PaddingTop: + line.PaddingLineType = PaddingLineType.PaddingTop; + break; + case SnapLine.PaddingBottom: + line.PaddingLineType = PaddingLineType.PaddingBottom; + break; + default: + Debug.Fail("Unknown snapline filter type"); + break; + } + } + } + } + + /// + /// This function validates a Margin or Padding SnapLine. A valid Margin SnapLine is one that will be drawn only if the target control being dragged somehow intersects (vertically or horizontally) the coords of the given snapLine. This is done so we don't start drawing margin lines when controls are large distances apart (too much mess); + /// + [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] + private bool ValidateMarginOrPaddingLine(SnapLine snapLine, Rectangle dragBounds) + { + Rectangle bounds = (Rectangle)_snapLineToBounds[snapLine]; + if (snapLine.IsVertical) + { + if (bounds.Top < dragBounds.Top) + { + if (bounds.Top + bounds.Height < dragBounds.Top) + { + return false; + } + } + else if (dragBounds.Top + dragBounds.Height < bounds.Top) + { + return false; + } + } + else + { + if (bounds.Left < dragBounds.Left) + { + if (bounds.Left + bounds.Width < dragBounds.Left) + { + return false; + } + } + else if (dragBounds.Left + dragBounds.Width < bounds.Left) + { + return false; + } + } + //valid overlapping margin line + return true; + } + + internal Point OnMouseMove(Rectangle dragBounds, SnapLine[] snapLines) + { + bool didSnap = false; + return OnMouseMove(dragBounds, snapLines, ref didSnap, true); + } + + /// + /// Called by the DragBehavior on every mouse move. We first offset all of our drag-control's snap lines by the amount of the mouse move then follow our 2-pass heuristic to determine which SnapLines to render. + /// + internal Point OnMouseMove(Rectangle dragBounds, SnapLine[] snapLines, ref bool didSnap, bool shouldSnapHorizontally) + { + if (snapLines == null || snapLines.Length == 0) + { + return Point.Empty; + } + _targetHorizontalSnapLines.Clear(); + _targetVerticalSnapLines.Clear(); + //manually add our snaplines as targets + foreach (SnapLine snapline in snapLines) + { + if (snapline.IsHorizontal) + { + _targetHorizontalSnapLines.Add(snapline); + } + else + { + _targetVerticalSnapLines.Add(snapline); + } + } + return OnMouseMove(dragBounds, false, ref didSnap, shouldSnapHorizontally); + } + + /// + /// Called by the DragBehavior on every mouse move. We first offset all of our drag-control's snap lines by the amount of the mouse move then follow our 2-pass heuristic to determine which SnapLines to render. + /// + internal Point OnMouseMove(Rectangle dragBounds) + { + bool didSnap = false; + return OnMouseMove(dragBounds, true, ref didSnap, true); + } + + /// + /// Called by the resizebehavior. It needs to know whether we really snapped or not. The snapPoint could be (0,0) even though we snapped. + /// + internal Point OnMouseMove(Control targetControl, SnapLine[] snapLines, ref bool didSnap, bool shouldSnapHorizontally) + { + Rectangle dragBounds = new Rectangle(_behaviorService.ControlToAdornerWindow(targetControl), targetControl.Size); + didSnap = false; + return OnMouseMove(dragBounds, snapLines, ref didSnap, shouldSnapHorizontally); + } + + /// + /// Called by the DragBehavior on every mouse move. We first offset all of our drag-control's snap lines by the amount of the mouse move then follow our 2-pass heuristic to determine which SnapLines to render. + /// + private Point OnMouseMove(Rectangle dragBounds, bool offsetSnapLines, ref bool didSnap, bool shouldSnapHorizontally) + { + _tempVertLines.Clear(); + _tempHorzLines.Clear(); + _dragOffset = new Point(dragBounds.X - _dragOffset.X, dragBounds.Y - _dragOffset.Y); + if (offsetSnapLines) + { + //offset our targetSnapLines by the amount we have dragged it + for (int i = 0; i < _targetHorizontalSnapLines.Count; i++) + { + ((SnapLine)_targetHorizontalSnapLines[i]).AdjustOffset(_dragOffset.Y); + } + for (int i = 0; i < _targetVerticalSnapLines.Count; i++) + { + ((SnapLine)_targetVerticalSnapLines[i]).AdjustOffset(_dragOffset.X); + } + } + + //First pass - build up a distance array of all same-type-alignment pts to theclosest point on our targetControl. Also, keep track of the smallestdistance overall + int smallestDistanceVert = BuildDistanceArray(_verticalSnapLines, _targetVerticalSnapLines, _verticalDistances, dragBounds); + int smallestDistanceHorz = INVALID_VALUE; + if (shouldSnapHorizontally) + { + smallestDistanceHorz = BuildDistanceArray(_horizontalSnapLines, _targetHorizontalSnapLines, _horizontalDistances, dragBounds); + } + //Second Pass! We only need to do a second pass if the smallest delta is <= SnapDistance. If this is the case - then we draw snap lines for every line equal to the smallest distance available in the distance array + _snapPointX = (Math.Abs(smallestDistanceVert) <= SnapDistance) ? -smallestDistanceVert : INVALID_VALUE; + _snapPointY = (Math.Abs(smallestDistanceHorz) <= SnapDistance) ? -smallestDistanceHorz : INVALID_VALUE; + // certain behaviors (like resize) might want to know whether we really snapped or not. They can't check the returned snapPoint for (0,0) since that is a valid snapPoint. + didSnap = false; + if (_snapPointX != INVALID_VALUE) + { + IdentifyAndStoreValidLines(_verticalSnapLines, _verticalDistances, dragBounds, smallestDistanceVert); + didSnap = true; + } + + if (_snapPointY != INVALID_VALUE) + { + IdentifyAndStoreValidLines(_horizontalSnapLines, _horizontalDistances, dragBounds, smallestDistanceHorz); + didSnap = true; + } + + Point snapPoint = new Point(_snapPointX != INVALID_VALUE ? _snapPointX : 0, _snapPointY != INVALID_VALUE ? _snapPointY : 0); + Rectangle tempDragRect = new Rectangle(dragBounds.Left + snapPoint.X, dragBounds.Top + snapPoint.Y, dragBounds.Width, dragBounds.Height); + //out with the old... + _vertLines = EraseOldSnapLines(_vertLines, _tempVertLines); + _horzLines = EraseOldSnapLines(_horzLines, _tempHorzLines); + //store this drag rect - we'll use it when we are (eventually) called back on to actually render our lines + + //NOTE NOTE NOTE: If OnMouseMove is called during a resize operation, then cachedDragRect is not guaranteed to work. That is why I introduced RenderSnapLinesInternal(dragRect) + _cachedDragRect = tempDragRect; + //reset the dragoffset to this last location + _dragOffset = dragBounds.Location; + //this 'snapPoint' will be the amount we want the dragBehavior to shift the dragging control by ('cause we snapped somewhere) + return snapPoint; + } + + //NOTE NOTE NOTE: If OnMouseMove is called during a resize operation, then cachedDragRect is not guaranteed to work. That is why I introduced RenderSnapLinesInternal(dragRect) + /// + /// Called by the ResizeBehavior after it has finished drawing + /// + internal void RenderSnapLinesInternal(Rectangle dragRect) + { + _cachedDragRect = dragRect; + RenderSnapLinesInternal(); + } + + /// + /// Called by the DropSourceBehavior after it finished drawing its' draging images so that we can draw our lines on top of everything. + /// + internal void RenderSnapLinesInternal() + { + RenderSnapLines(_vertLines, _cachedDragRect); + RenderSnapLines(_horzLines, _cachedDragRect); + _recentLines = new Line[_vertLines.Length + _horzLines.Length]; + _vertLines.CopyTo(_recentLines, 0); + _horzLines.CopyTo(_recentLines, _vertLines.Length); + } + + /// + /// Clean up all of our references. + /// + internal void OnMouseUp() + { + // Here, we store off our recent snapline info to the behavior service - this is used for testing purposes + if (_behaviorService != null) + { + Line[] recent = GetRecentLines(); + string[] lines = new string[recent.Length]; + for (int i = 0; i < recent.Length; i++) + { + lines[i] = recent[i].ToString(); + } + _behaviorService.RecentSnapLines = lines; + } + EraseSnapLines(); + _graphics.Dispose(); + if (_disposeEdgePen && _edgePen != null) + { + _edgePen.Dispose(); + } + + if (_baselinePen != null) + { + _baselinePen.Dispose(); + } + + if (_backgroundImage != null) + { + _backgroundImage.Dispose(); + } + } + + /// + /// Our 'line' class - used to manage two points and calculate the difference between any two lines. + /// + internal class Line + { + public int x1, y1, x2, y2; + private LineType _lineType; + private PaddingLineType _paddingLineType; + private Rectangle _originalBounds; + + public LineType LineType + { + get => _lineType; + set => _lineType = value; + } + + + public Rectangle OriginalBounds + { + get => _originalBounds; + set => _originalBounds = value; + } + + public PaddingLineType PaddingLineType + { + get => _paddingLineType; + set => _paddingLineType = value; + } + + + public Line(int x1, int y1, int x2, int y2) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + _lineType = LineType.Standard; + } + + private Line(int x1, int y1, int x2, int y2, LineType type) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + _lineType = type; + } + + public static Line[] GetDiffs(Line l1, Line l2) + { + //x's align + if (l1.x1 == l1.x2 && l1.x1 == l2.x1) + { + return new Line[2] {new Line(l1.x1, Math.Min(l1.y1, l2.y1), l1.x1, Math.Max(l1.y1, l2.y1)), + new Line(l1.x1, Math.Min(l1.y2, l2.y2), l1.x1, Math.Max(l1.y2, l2.y2))}; + } + + //y's align + if (l1.y1 == l1.y2 && l1.y1 == l2.y1) + { + return new Line[2] {new Line(Math.Min(l1.x1, l2.x1), l1.y1, Math.Max(l1.x1, l2.x1), l1.y1), + new Line(Math.Min(l1.x2, l2.x2), l1.y1, Math.Max(l1.x2, l2.x2), l1.y1)}; + } + return null; + } + + public static Line Overlap(Line l1, Line l2) + { + // Need to be the same type + if (l1.LineType != l2.LineType) + { + return null; + } + + // only makes sense to do this for Standard and Baseline + if ((l1.LineType != LineType.Standard) && (l1.LineType != LineType.Baseline)) + { + return null; + } + + // 2 overlapping vertical lines + if ((l1.x1 == l1.x2) && (l2.x1 == l2.x2) && (l1.x1 == l2.x1)) + { + return new Line(l1.x1, Math.Min(l1.y1, l2.y1), l1.x2, Math.Max(l1.y2, l2.y2), l1.LineType); + } + + // 2 overlapping horizontal lines + if ((l1.y1 == l1.y2) && (l2.y1 == l2.y2) && (l1.y1 == l2.y2)) + { + return new Line(Math.Min(l1.x1, l2.x1), l1.y1, Math.Max(l1.x2, l2.x2), l1.y2, l1.LineType); + } + return null; + } + + public override string ToString() + { + return "Line, type = " + _lineType + ", dims =(" + x1 + ", " + y1 + ")->(" + x2 + ", " + y2 + ")"; + } + } + + /// + /// Describes different types of lines (used for margins, etc..) + /// + internal enum LineType + { + Standard, Margin, Padding, Baseline + } + + /// + /// Describes what kind of padding line we have + /// + internal enum PaddingLineType + { + None, PaddingRight, PaddingLeft, PaddingTop, PaddingBottom + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DropSourceBehavior.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DropSourceBehavior.cs new file mode 100644 index 00000000000..7ccc19a5d71 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/DropSourceBehavior.cs @@ -0,0 +1,1218 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The DropSourceBehavior is created by ControlDesigner when it detects that a drag operation has started. This object is passed to the BehaviorService and is used to route GiveFeedback and QueryContinueDrag drag/drop messages. In response to GiveFeedback messages, this class will render the dragging controls in real-time with the help of the DragAssistanceManager (Snaplines) object or by simply snapping to grid dots. + /// + internal sealed class DropSourceBehavior : Behavior, IComparer + { + private struct DragComponent + { + public object dragComponent; //the dragComponent + public int zorderIndex; //the dragComponent's z-order index + public Point originalControlLocation; //the original control of the control in AdornerWindow coordinates + public Point draggedLocation; //the location of the component after each drag - in AdornerWindow coordinates + public Image dragImage; //bitblt'd image of control + public Point positionOffset; //control position offset from primary selection + }; + + private DragComponent[] dragComponents; + private ArrayList dragObjects; // used to initialize the DragAssistanceManager + private BehaviorDataObject data;//drag data that represents the controls we're dragging & the effect/action + private DragDropEffects allowedEffects;//initial allowed effects for the drag operation + private DragDropEffects lastEffect;//the last effect we saw (used for determining a valid drop) + + private bool targetAllowsSnapLines;//indicates if the drop target allows snaplines (flowpanels don't for ex) + private IComponent lastDropTarget;//indicates the drop target on the last 'give feedback' event + private Point lastSnapOffset;//the last snapoffset we used. + // These 2 could be different (e.g. if dropping between forms) + private BehaviorService behaviorServiceSource;//ptr back to the BehaviorService in the drop source + private BehaviorService behaviorServiceTarget;//ptr back to the BehaviorService in the drop target + + //this object will integrate SnapLines into the drag + private DragAssistanceManager dragAssistanceManager; + + private Graphics graphicsTarget;//graphics object of the adornerwindows (via BehaviorService) in drop target + + private IServiceProvider serviceProviderSource; + private IServiceProvider serviceProviderTarget; + + private Point initialMouseLoc;//original mouse location in screen coordinates + + private Image dragImage;//A single image of the controls we are actually dragging around + private Rectangle dragImageRect;//Rectangle of the dragImage -- in SOURCE AdornerWindow coordinates + private Rectangle clearDragImageRect; //Rectangle used to remember the last dragimage rect we cleared + private Point originalDragImageLocation; //original location of the drag image + private Region dragImageRegion; + + private Point lastFeedbackLocation; // the last position we got feedback at + private Control suspendedParent;//pointer to the parent that we suspended @ the beginning of the drag + private Size parentGridSize; //used to snap around to grid dots if layoutmode == SnapToGrid + private Point parentLocation;//location of parent on AdornerWindow - used for grid snap calculations + private bool shareParent = true;//do dragged components share the parent + private bool cleanedUpDrag = false; + private StatusCommandUI statusCommandUITarget;// UI for setting the StatusBar Information in the drop target + + private IDesignerHost srcHost; + private IDesignerHost destHost; + + private bool currentShowState = true; // Initially the controls are showing + + private int primaryComponentIndex = -1; // Index of the primary component (control) in dragComponents + + /// + /// Constuctor that caches all needed vars for perf reasons. + /// + internal DropSourceBehavior(ICollection dragComponents, Control source, Point initialMouseLocation) + { + + serviceProviderSource = source.Site as IServiceProvider; + if (serviceProviderSource == null) + { + Debug.Fail("DragBehavior could not be created because the source ServiceProvider was not found"); + return; + } + + behaviorServiceSource = (BehaviorService)serviceProviderSource.GetService(typeof(BehaviorService)); + if (behaviorServiceSource == null) + { + Debug.Fail("DragBehavior could not be created because the BehaviorService was not found"); + return; + } + + if (dragComponents == null || dragComponents.Count <= 0) + { + Debug.Fail("There are no component to drag!"); + return; + } + + srcHost = (IDesignerHost)serviceProviderSource.GetService(typeof(IDesignerHost)); + if (srcHost == null) + { + Debug.Fail("DragBehavior could not be created because the srcHost could not be found"); + return; + } + + data = new BehaviorDataObject(dragComponents, source, this); + allowedEffects = DragDropEffects.Copy | DragDropEffects.None | DragDropEffects.Move; + this.dragComponents = new DragComponent[dragComponents.Count]; + parentGridSize = Size.Empty; + + lastEffect = DragDropEffects.None; + lastFeedbackLocation = new Point(-1, -1); + lastSnapOffset = Point.Empty; + dragImageRect = Rectangle.Empty; + clearDragImageRect = Rectangle.Empty; + InitiateDrag(initialMouseLocation, dragComponents); + } + + /// + /// This is the initial allowed Effect to start the drag operation with. + /// + internal DragDropEffects AllowedEffects + { + get => allowedEffects; + } + + /// + /// This is the DataObject this DropSourceBehavior represents. + /// + internal DataObject DataObject + { + get => data; + } + + /// + /// Here, during our drag operation, we need to determine the offset from the dragging control's position 'dragLoc' and the parent's grid. We'll return an offset for the image to 'snap to'. + /// + private Point AdjustToGrid(Point dragLoc) + { + //location of the drag with respect to the parent + Point controlLocation = new Point(dragLoc.X - parentLocation.X, dragLoc.Y - parentLocation.Y); + Point offset = Point.Empty; + //determine which way we need to snap + int xDelta = controlLocation.X % parentGridSize.Width; + int yDelta = controlLocation.Y % parentGridSize.Height; + // if we're more than half way to the next grid - then snap that way, otherwise snap back + if (xDelta > parentGridSize.Width / 2) + { + offset.X = parentGridSize.Width - xDelta; + } + else + { + offset.X = -xDelta; + } + + if (yDelta > parentGridSize.Height / 2) + { + offset.Y = parentGridSize.Height - yDelta; + } + else + { + offset.Y = -yDelta; + } + + return offset; + } + + private Point MapPointFromSourceToTarget(Point pt) + { + if (srcHost != destHost && destHost != null) + { + pt = behaviorServiceSource.AdornerWindowPointToScreen(pt); + return behaviorServiceTarget.MapAdornerWindowPoint(IntPtr.Zero, pt); + } + else + { + return pt; + } + } + + private Point MapPointFromTargetToSource(Point pt) + { + if (srcHost != destHost && destHost != null) + { + pt = behaviorServiceTarget.AdornerWindowPointToScreen(pt); + return behaviorServiceSource.MapAdornerWindowPoint(IntPtr.Zero, pt); + } + else + { + return pt; + } + } + + /// + /// This is used to clear the drag images. + /// + private void ClearAllDragImages() + { + if (dragImageRect != Rectangle.Empty) + { + + Rectangle rect = dragImageRect; + rect.Location = MapPointFromSourceToTarget(rect.Location); + + if (graphicsTarget != null) + { + graphicsTarget.SetClip(rect); + } + + if (behaviorServiceTarget != null) + { + behaviorServiceTarget.Invalidate(rect); + } + + if (graphicsTarget != null) + { + graphicsTarget.ResetClip(); + } + } + } + + // Yeah this is recursive, but we also need to resite all + // the children of this control, and their children, and their children... + private void SetDesignerHost(Control c) + { + foreach (Control control in c.Controls) + { + SetDesignerHost(control); + } + if (c.Site != null && !(c.Site is INestedSite) && destHost != null) + { + destHost.Container.Add(c); + } + } + + private void DropControl(int dragComponentIndex, Control dragTarget, Control dragSource, bool localDrag) + { + Control currentControl = dragComponents[dragComponentIndex].dragComponent as Control; + if (lastEffect == DragDropEffects.Copy || (srcHost != destHost && destHost != null)) + { + //between forms or copy + currentControl.Visible = true; + bool visibleState = true; + PropertyDescriptor propLoc = TypeDescriptor.GetProperties(currentControl)["Visible"]; + if (propLoc != null) + { + // store off the visible state. When adding the control to the new designer host, a new control designer will be created for the control. Since currentControl.Visible is currently FALSE (See InitiateDrag), the shadowed Visible property will be FALSE as well. This is not what we want. + visibleState = (bool)propLoc.GetValue(currentControl); + } + + // Hook the control to its new designerHost + SetDesignerHost(currentControl); + currentControl.Parent = dragTarget; + if (propLoc != null) + { + //Make sure and set the Visible property to the correct value + propLoc.SetValue(currentControl, visibleState); + } + } + else if (!localDrag && currentControl.Parent.Equals(dragSource)) + { + //between containers + dragSource.Controls.Remove(currentControl); + currentControl.Visible = true; + dragTarget.Controls.Add(currentControl); + } + } + + private void SetLocationPropertyAndChildIndex(int dragComponentIndex, Control dragTarget, Point dropPoint, int newIndex, bool allowSetChildIndexOnDrop) + { + PropertyDescriptor propLoc = TypeDescriptor.GetProperties(dragComponents[dragComponentIndex].dragComponent)["Location"]; + if ((propLoc != null) && (dragComponents[dragComponentIndex].dragComponent is Control currentControl)) + { + // ControlDesigner shadows the Location property. If the control is parented and the parent is a scrollable control, then it expects the Location to be in displayrectangle coordinates. At this point bounds are in clientrectangle coordinates, so we need to check if we need to adjust the coordinates. + Point pt = new Point(dropPoint.X, dropPoint.Y); + if (currentControl.Parent is ScrollableControl p) + { + Point ptScroll = p.AutoScrollPosition; + pt.Offset(-ptScroll.X, -ptScroll.Y); //always want to add the control below/right of the AutoScrollPosition + } + + propLoc.SetValue(currentControl, pt); + // In some cases the target designer wants to maintain its own ZOrder, in that case we shouldn't try and set the childindex. FlowLayoutPanelDesigner is one such case. + if (allowSetChildIndexOnDrop) + { + dragTarget.Controls.SetChildIndex(currentControl, newIndex); + } + } + } + + /// + /// This is where we end the drag and commit the new control locations. To do this correctly, we loop through every control and find its propertyDescriptor for the Location. Then call SetValue(). After this we re-enable the adorners. Finally, we pop ourselves from the BehaviorStack. + /// + private void EndDragDrop(bool allowSetChildIndexOnDrop) + { + if (!(data.Target is Control dragTarget)) + { + return; //can't deal with a non-control drop target yet + } + + // If for some reason we couldn't get these guys, let's try and get them here + if (serviceProviderTarget == null) + { + Debug.Fail("EndDragDrop - how can serviceProviderTarget be null?"); + serviceProviderTarget = dragTarget.Site as IServiceProvider; + if (serviceProviderTarget == null) + { + Debug.Fail("EndDragDrop - how can serviceProviderTarget be null?"); + return; + } + } + + if (destHost == null) + { + Debug.Fail("EndDragDrop - how can destHost be null?"); + destHost = (IDesignerHost)serviceProviderTarget.GetService(typeof(IDesignerHost)); + if (destHost == null) + { + Debug.Fail("EndDragDrop - how can destHost be null?"); + return; + } + } + + if (behaviorServiceTarget == null) + { + Debug.Fail("EndDragDrop - how can behaviorServiceTarget be null?"); + behaviorServiceTarget = (BehaviorService)serviceProviderTarget.GetService(typeof(BehaviorService)); + if (behaviorServiceTarget == null) + { + Debug.Fail("EndDragDrop - how can behaviorServiceTarget be null?"); + return; + } + } + + // We use this list when doing a Drag-Copy, so that we can correctly restore state when we are done. See Copy code below. + ArrayList originalControls = null; + bool performCopy = (lastEffect == DragDropEffects.Copy); + + Control dragSource = data.Source; + bool localDrag = dragSource.Equals(dragTarget); + PropertyDescriptor targetProp = TypeDescriptor.GetProperties(dragTarget)["Controls"]; + PropertyDescriptor sourceProp = TypeDescriptor.GetProperties(dragSource)["Controls"]; + IComponentChangeService componentChangeSvcSource = (IComponentChangeService)serviceProviderSource.GetService(typeof(IComponentChangeService)); + IComponentChangeService componentChangeSvcTarget = (IComponentChangeService)serviceProviderTarget.GetService(typeof(IComponentChangeService)); + + if (dragAssistanceManager != null) + { + dragAssistanceManager.OnMouseUp(); + } + + // If we are dropping between hosts, we want to set the selection in the new host to be the components that we are dropping. ... or if we are copying + ISelectionService selSvc = null; + if (performCopy || (srcHost != destHost && destHost != null)) + { + selSvc = (ISelectionService)serviceProviderTarget.GetService(typeof(ISelectionService)); + } + + try + { + if (dragComponents != null && dragComponents.Length > 0) + { + DesignerTransaction transSource = null; + DesignerTransaction transTarget = null; + string transDesc; + if (dragComponents.Length == 1) + { + string name = TypeDescriptor.GetComponentName(dragComponents[0].dragComponent); + if (name == null || name.Length == 0) + { + name = dragComponents[0].dragComponent.GetType().Name; + } + transDesc = string.Format(performCopy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name); + } + else + { + transDesc = string.Format(performCopy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, dragComponents.Length); + } + + // We don't want to create a transaction in the source, if we are doing a cross-form copy + if (srcHost != null && !(srcHost != destHost && destHost != null && performCopy)) + { + transSource = srcHost.CreateTransaction(transDesc); + } + + if (srcHost != destHost && destHost != null) + { + transTarget = destHost.CreateTransaction(transDesc); + } + + try + { + ComponentTray tray = null; + int numberOfOriginalTrayControls = 0; + // If we are copying the controls, then, well, let's make a copy of'em... We then stuff the copy into the dragComponents array, since that keeps the rest of this code the same... No special casing needed. + if (performCopy) + { + // As part of a Ctrl-Drag, components might have been added to the component tray, make sure that their location gets updated as well (think ToolStrips). Get the current number of controls in the Component Tray in the target + tray = serviceProviderTarget.GetService(typeof(ComponentTray)) as ComponentTray; + numberOfOriginalTrayControls = tray != null ? tray.Controls.Count : 0; + + // Get the objects to copy + ArrayList temp = new ArrayList(); + for (int i = 0; i < dragComponents.Length; i++) + { + temp.Add(dragComponents[i].dragComponent); + } + + // Create a copy of them + temp = DesignerUtils.CopyDragObjects(temp, serviceProviderTarget) as ArrayList; + if (temp == null) + { + Debug.Fail("Couldn't create copies of the controls we are dragging."); + return; + } + + originalControls = new ArrayList(); + // And stick the copied controls back into the dragComponents array + for (int j = 0; j < temp.Count; j++) + { + // ... but save off the old controls first + originalControls.Add(dragComponents[j].dragComponent); + dragComponents[j].dragComponent = temp[j]; + } + } + + if ((!localDrag || performCopy) && componentChangeSvcSource != null && componentChangeSvcTarget != null) + { + componentChangeSvcTarget.OnComponentChanging(dragTarget, targetProp); + // If we are performing a copy, then the dragSource will not change + if (!performCopy) + { + componentChangeSvcSource.OnComponentChanging(dragSource, sourceProp); + } + } + + // We need to calculate initialDropPoint first to be able to calculate the new drop point for all controls Need to drop it first to make sure that the Parent gets set correctly. + DropControl(primaryComponentIndex, dragTarget, dragSource, localDrag); + Point initialDropPoint = behaviorServiceSource.AdornerWindowPointToScreen(dragComponents[primaryComponentIndex].draggedLocation); + + // Tricky... initialDropPoint is the dropPoint in the source adornerwindow, which could be different than the target adornerwindow. But since we first convert it to screen coordinates, and then to client coordinates using the new parent, we end up dropping in the right spot. Cool, huh! + initialDropPoint = ((Control)dragComponents[primaryComponentIndex].dragComponent).Parent.PointToClient(initialDropPoint); + + // Correct (only) the drop point for when Parent is mirrored, then use the offsets for the other controls, which were already corrected for mirroring in InitDrag + if (((Control)(dragComponents[primaryComponentIndex].dragComponent)).Parent.IsMirrored) + { + initialDropPoint.Offset(-((Control)(dragComponents[primaryComponentIndex].dragComponent)).Width, 0); + } + + // check permission to do that + Control primaryComponent = dragComponents[primaryComponentIndex].dragComponent as Control; + PropertyDescriptor propLoc = TypeDescriptor.GetProperties(primaryComponent)["Location"]; + if (primaryComponent != null && propLoc != null) + { + try + { + componentChangeSvcTarget.OnComponentChanging(primaryComponent, propLoc); + } + + catch (CheckoutException coEx) + { + if (coEx == CheckoutException.Canceled) + { + return; + } + throw; + } + } + // everything is fine, carry on... + SetLocationPropertyAndChildIndex(primaryComponentIndex, dragTarget, initialDropPoint, + shareParent ? dragComponents[primaryComponentIndex].zorderIndex : 0, allowSetChildIndexOnDrop); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { dragComponents[primaryComponentIndex].dragComponent }, SelectionTypes.Primary | SelectionTypes.Replace); + } + + for (int i = 0; i < dragComponents.Length; i++) + { + if (i == primaryComponentIndex) + { + // did this one above + continue; + } + + DropControl(i, dragTarget, dragSource, localDrag); + Point dropPoint = new Point(initialDropPoint.X + dragComponents[i].positionOffset.X, + initialDropPoint.Y + dragComponents[i].positionOffset.Y); + SetLocationPropertyAndChildIndex(i, dragTarget, dropPoint, + shareParent ? dragComponents[i].zorderIndex : 0, allowSetChildIndexOnDrop); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { dragComponents[i].dragComponent }, SelectionTypes.Add); + } + + } + + if ((!localDrag || performCopy) && componentChangeSvcSource != null && componentChangeSvcTarget != null) + { + componentChangeSvcTarget.OnComponentChanged(dragTarget, targetProp, dragTarget.Controls, dragTarget.Controls); + if (!performCopy) + { + componentChangeSvcSource.OnComponentChanged(dragSource, sourceProp, dragSource.Controls, dragSource.Controls); + } + } + + // If we did a Copy, then restore the old controls to make sure we set state correctly + if (originalControls != null) + { + for (int i = 0; i < originalControls.Count; i++) + { + dragComponents[i].dragComponent = originalControls[i]; + } + originalControls = null; + } + + // Rearrange the Component Tray - if we have to + if (performCopy) + { + if (tray == null) + { + // the target did not have a tray already, so let's go get it - if there is one + tray = serviceProviderTarget.GetService(typeof(ComponentTray)) as ComponentTray; + } + + if (tray != null) + { + int numberOfTrayControlsAdded = tray.Controls.Count - numberOfOriginalTrayControls; + + if (numberOfTrayControlsAdded > 0) + { + ArrayList listOfTrayControls = new ArrayList(); + for (int i = 0; i < numberOfTrayControlsAdded; i++) + { + listOfTrayControls.Add(tray.Controls[numberOfOriginalTrayControls + i]); + } + tray.UpdatePastePositions(listOfTrayControls); + } + } + } + + // We need to CleanupDrag BEFORE we commit the transaction. The reason is that cleaning up can potentially cause a layout, and then any changes that happen due to the layout would be in a separate UndoUnit. We want the D&D to be undoable in one step. + CleanupDrag(false); + if (transSource != null) + { + transSource.Commit(); + transSource = null; + } + if (transTarget != null) + { + transTarget.Commit(); + transTarget = null; + } + } + + finally + { + if (transSource != null) + { + transSource.Cancel(); + } + + if (transTarget != null) + { + transTarget.Cancel(); + } + } + } + } + finally + { + // If we did a Copy, then restore the old controls to make sure we set state correctly + if (originalControls != null) + { + for (int i = 0; i < originalControls.Count; i++) + { + dragComponents[i].dragComponent = originalControls[i]; + } + } + + // Even though we call CleanupDrag(false) twice (see above), this method guards against doing the wrong thing. + CleanupDrag(false); + if (statusCommandUITarget != null) + { + // if selSvs is not null, then we either did a copy, or moved between forms, so use it to set the right info + statusCommandUITarget.SetStatusInformation(selSvc == null ? dragComponents[primaryComponentIndex].dragComponent as Component : + selSvc.PrimarySelection as Component); + } + } + + // clear the last feedback loc + lastFeedbackLocation = new Point(-1, -1); + } + + /// + /// Called by the BehaviorService when the GiveFeedback event is fired. Here, we attempt to render all of our dragging control snapshots. *After, of course, we let the DragAssistanceManager adjust the position due to any SnapLine activity. + /// + internal void GiveFeedback(object sender, GiveFeedbackEventArgs e) + { + // cache off this last effect so in QueryContinueDrag we can identify (if dropped) a valid drop operation + lastEffect = e.Effect; + //if our target is null, we can't drop anywhere, so don't even draw images + if (data.Target == null || e.Effect == DragDropEffects.None) + { + if (clearDragImageRect != dragImageRect) + { + // To avoid flashing, we only want to clear the drag images if the the dragimagerect is different than the last time we got here. I.e. if we keep dragging over an area where we are not allowed to drop, then we only have to clear the dragimages once. + ClearAllDragImages(); + clearDragImageRect = dragImageRect; + } + if (dragAssistanceManager != null) + { + dragAssistanceManager.EraseSnapLines(); + } + return; + } + + bool createNewDragAssistance = false; + Point mouseLoc = Control.MousePosition; + bool altKeyPressed = Control.ModifierKeys == Keys.Alt; + if (altKeyPressed && dragAssistanceManager != null) + { + //erase any snaplines (if we had any) + dragAssistanceManager.EraseSnapLines(); + } + + // I can't get rid of the ole-drag/drop default cursor that show's the cross-parent drag indication + if (data.Target.Equals(data.Source) && lastEffect != DragDropEffects.Copy) + { + e.UseDefaultCursors = false; + Cursor.Current = Cursors.Default; + } + else + { + e.UseDefaultCursors = true; + } + + // only do this drawing when the mouse pointer has actually moved so we don't continuously redraw and flicker like mad. + Control target = data.Target as Control; + if ((mouseLoc != lastFeedbackLocation) || (altKeyPressed && dragAssistanceManager != null)) + { + if (!data.Target.Equals(lastDropTarget)) + { + serviceProviderTarget = target.Site as IServiceProvider; + if (serviceProviderTarget == null) + { + return; + } + + IDesignerHost newDestHost = (IDesignerHost)serviceProviderTarget.GetService(typeof(IDesignerHost)); + if (newDestHost == null) + { + return; + } + + targetAllowsSnapLines = true; + //check to see if the current designer participate with SnapLines + if (newDestHost.GetDesigner(target) is ControlDesigner designer && !designer.ParticipatesWithSnapLines) + { + targetAllowsSnapLines = false; + } + + statusCommandUITarget = new StatusCommandUI(serviceProviderTarget); + // Spin up new stuff if the host changes, or if this is the first time through (lastDropTarget will be null in this case) + if ((lastDropTarget == null) || (newDestHost != destHost)) + { + if (destHost != null && destHost != srcHost) + { + // re-enable all glyphs in the old host... need to do this before we get the new behaviorservice + behaviorServiceTarget.EnableAllAdorners(true); + } + + behaviorServiceTarget = (BehaviorService)serviceProviderTarget.GetService(typeof(BehaviorService)); + if (behaviorServiceTarget == null) + { + return; + } + + GetParentSnapInfo(target, behaviorServiceTarget); + + // Disable the adorners in the new host, but only if this is not the source host, since that will already have been done + if (newDestHost != srcHost) + { + DisableAdorners(serviceProviderTarget, behaviorServiceTarget, true); + } + + // clear the old drag images in the old graphicsTarget + ClearAllDragImages(); + + // Build a new dragImageRegion -- but only if we are changing hosts + if (lastDropTarget != null) + { + for (int i = 0; i < dragObjects.Count; i++) + { + Control dragControl = (Control)dragObjects[i]; + Rectangle controlRect = behaviorServiceSource.ControlRectInAdornerWindow(dragControl); + // Can't call MapPointFromSourceToTarget since we always want to do this + controlRect.Location = behaviorServiceSource.AdornerWindowPointToScreen(controlRect.Location); + controlRect.Location = behaviorServiceTarget.MapAdornerWindowPoint(IntPtr.Zero, controlRect.Location); + if (i == 0) + { + if (dragImageRegion != null) + { + dragImageRegion.Dispose(); + } + dragImageRegion = new Region(controlRect); + } + else + { + dragImageRegion.Union(controlRect); + } + } + } + + if (graphicsTarget != null) + { + graphicsTarget.Dispose(); + } + graphicsTarget = behaviorServiceTarget.AdornerWindowGraphics; + + // Always force the dragassistance manager to be created in this case. + createNewDragAssistance = true; + destHost = newDestHost; + } + lastDropTarget = data.Target; + } + + if (ShowHideDragControls(lastEffect == DragDropEffects.Copy) && !createNewDragAssistance) + { + createNewDragAssistance = true; + } + + // Create new dragassistancemanager if needed + if (createNewDragAssistance && behaviorServiceTarget.UseSnapLines) + { + if (dragAssistanceManager != null) + { + //erase any snaplines (if we had any) + dragAssistanceManager.EraseSnapLines(); + } + dragAssistanceManager = new DragAssistanceManager(serviceProviderTarget, graphicsTarget, dragObjects, null, lastEffect == DragDropEffects.Copy); + } + + //The new position of the primary control, i.e. where did we just drag it to + Point newPosition = new Point(mouseLoc.X - initialMouseLoc.X + dragComponents[primaryComponentIndex].originalControlLocation.X, + mouseLoc.Y - initialMouseLoc.Y + dragComponents[primaryComponentIndex].originalControlLocation.Y); + // Map it to the target's adorner window so that we can snap correctly + newPosition = MapPointFromSourceToTarget(newPosition); + //The new rectangle + Rectangle newRect = new Rectangle(newPosition.X, newPosition.Y, + dragComponents[primaryComponentIndex].dragImage.Width, + dragComponents[primaryComponentIndex].dragImage.Height); + //if we have a valid snapline engine - ask it to offset our drag + if (dragAssistanceManager != null) + { + if (targetAllowsSnapLines && !altKeyPressed) + { + // Remembering the last snapoffset allows us to correctly erase snaplines, if the user subsequently holds down the Alt-Key. Remember that we don't physically move the mouse, we move the control (or rather the image of the control). So if we didn't remember the last snapoffset and the user then hit the Alt-Key, we would actually redraw the control at the actual mouse location, which would make the control "jump" which is not what the user would expect. Why does the control "jump"? Because when a control is snapped, we have offset the control relative to where the mouse is, but we have not update the physical mouse position. When the user hits the Alt-Key they expect the control to be where it was (whether snapped or not). + lastSnapOffset = dragAssistanceManager.OnMouseMove(newRect); + } + else + { + dragAssistanceManager.OnMouseMove(new Rectangle(-100, -100, 0, 0));/*just an invalid rect - so we won't snap*///); + } + } + //if we know our parent is forcing grid sizes + else if (!parentGridSize.IsEmpty) + { + lastSnapOffset = AdjustToGrid(newPosition); + } + + // Set the new location after the drag (only need to do this for the primary control) adjusted for a snap offset + newPosition.X += lastSnapOffset.X; + newPosition.Y += lastSnapOffset.Y; + + // draggedLocation is the coordinates in the source AdornerWindow. Need to do this since our original location is in those coordinates + dragComponents[primaryComponentIndex].draggedLocation = MapPointFromTargetToSource(newPosition); + + // Now draw the dragImage in the correct location + // FIRST, INVALIDATE THE REGION THAT IS OUTSIDE OF THE DRAGIMAGERECT + // First remember the old rect so that we can invalidate the right thing + Rectangle previousImageRect = dragImageRect; + // This is in Source adorner window coordinates + newPosition = new Point(mouseLoc.X - initialMouseLoc.X + originalDragImageLocation.X, + mouseLoc.Y - initialMouseLoc.Y + originalDragImageLocation.Y); + newPosition.X += lastSnapOffset.X; + newPosition.Y += lastSnapOffset.Y; + // Store this off in Source adornerwindow coordinates + dragImageRect.Location = newPosition; + + previousImageRect.Location = MapPointFromSourceToTarget(previousImageRect.Location); + Rectangle newImageRect = dragImageRect; + newImageRect.Location = MapPointFromSourceToTarget(newImageRect.Location); + + Rectangle unionRectangle = Rectangle.Union(newImageRect, previousImageRect); + Region invalidRegion = new Region(unionRectangle); + invalidRegion.Exclude(newImageRect); + + // SECOND, INVALIDATE THE TRANSPARENT REGION OF THE DRAGIMAGERECT + using (Region invalidDragRegion = dragImageRegion.Clone()) + { + invalidDragRegion.Translate(mouseLoc.X - initialMouseLoc.X + lastSnapOffset.X, mouseLoc.Y - initialMouseLoc.Y + lastSnapOffset.Y); + invalidDragRegion.Complement(newImageRect); + invalidDragRegion.Union(invalidRegion); + behaviorServiceTarget.Invalidate(invalidDragRegion); + } + invalidRegion.Dispose(); + if (graphicsTarget != null) + { + graphicsTarget.SetClip(newImageRect); + graphicsTarget.DrawImage(dragImage, newImageRect.X, newImageRect.Y); + graphicsTarget.ResetClip(); + } + + if (dragComponents[primaryComponentIndex].dragComponent is Control c) + { + // update drag position on the status bar + Point dropPoint = behaviorServiceSource.AdornerWindowPointToScreen(dragComponents[primaryComponentIndex].draggedLocation); + dropPoint = target.PointToClient(dropPoint); + // must adjust offsets for the flipped X axis when our container and control are mirrored + if (target.IsMirrored && c.IsMirrored) + { + dropPoint.Offset(-c.Width, 0); + } + if (statusCommandUITarget != null) + { + statusCommandUITarget.SetStatusInformation(c as Component, dropPoint); + } + } + + // allow any snaplines to be drawn above our drag images as long as the alt key is not pressed and the mouse is over the root comp + if (dragAssistanceManager != null && !altKeyPressed && targetAllowsSnapLines) + { + dragAssistanceManager.RenderSnapLinesInternal(); + } + + // save off the current mouse position + lastFeedbackLocation = mouseLoc; + } + data.Target = null; + } + + /// + /// We want to sort the dragComponents in descending z-order. We want to make sure that we draw the control lowest in the z-order first, and drawing the control at the top of the z-order last. Remember that z-order indices are in reverse order. I.e. the control that is at the top of the z-order list has the lowest z-order index. + /// + int IComparer.Compare(object x, object y) + { + DragComponent dc1 = (DragComponent)x; + DragComponent dc2 = (DragComponent)y; + if (dc1.zorderIndex > dc2.zorderIndex) + { + return -1; + } + else if (dc1.zorderIndex < dc2.zorderIndex) + { + return 1; + } + else + { + return 0; + } + } + + private void GetParentSnapInfo(Control parentControl, BehaviorService bhvSvc) + { + // Clear out whatever value we might have had stored off + parentGridSize = Size.Empty; + if (bhvSvc != null && !bhvSvc.UseSnapLines) + { + PropertyDescriptor snapProp = TypeDescriptor.GetProperties(parentControl)["SnapToGrid"]; + if (snapProp != null && (bool)snapProp.GetValue(parentControl)) + { + PropertyDescriptor gridProp = TypeDescriptor.GetProperties(parentControl)["GridSize"]; + if (gridProp != null) + { + //cache of the gridsize and the location of the parent on the adornerwindow + if (dragComponents[primaryComponentIndex].dragComponent is Control) + { + parentGridSize = (Size)gridProp.GetValue(parentControl); + parentLocation = bhvSvc.MapAdornerWindowPoint(parentControl.Handle, Point.Empty); + if (parentControl.Parent != null && parentControl.Parent.IsMirrored) + { + parentLocation.Offset(-parentControl.Width, 0); + } + } + } + } + } + } + + private void DisableAdorners(IServiceProvider serviceProvider, BehaviorService behaviorService, bool hostChange) + { + // find our bodyglyph adorner offered by the behavior service we don't want to disable the transparent body glyphs + Adorner bodyGlyphAdorner = null; + SelectionManager selMgr = (SelectionManager)serviceProvider.GetService(typeof(SelectionManager)); + if (selMgr != null) + { + bodyGlyphAdorner = selMgr.BodyGlyphAdorner; + } + + //disable all adorners except for bodyglyph adorner + foreach (Adorner a in behaviorService.Adorners) + { + if (bodyGlyphAdorner != null && a.Equals(bodyGlyphAdorner)) + { + continue; + } + a.EnabledInternal = false; + } + behaviorService.Invalidate(); + + if (hostChange) + { + selMgr.OnBeginDrag(new BehaviorDragDropEventArgs(dragObjects)); + } + } + + /// + /// Called when the ContolDesigner starts a drag operation. Here, all adorners are disabled, screen shots of all related controls are taken, and the DragAssistanceManager (for SnapLines) is created. + /// + private void InitiateDrag(Point initialMouseLocation, ICollection dragComps) + { + dragObjects = new ArrayList(dragComps); + DisableAdorners(serviceProviderSource, behaviorServiceSource, false); + Control primaryControl = dragObjects[0] as Control; + Control primaryParent = primaryControl?.Parent; + Color backColor = primaryParent != null ? primaryParent.BackColor : Color.Empty; + dragImageRect = Rectangle.Empty; + clearDragImageRect = Rectangle.Empty; + initialMouseLoc = initialMouseLocation; + + //loop through every control we need to drag, calculate the offsets and get a snapshot + for (int i = 0; i < dragObjects.Count; i++) + { + Control dragControl = (Control)dragObjects[i]; + + dragComponents[i].dragComponent = dragObjects[i]; + dragComponents[i].positionOffset = new Point(dragControl.Location.X - primaryControl.Location.X, + dragControl.Location.Y - primaryControl.Location.Y); + Rectangle controlRect = behaviorServiceSource.ControlRectInAdornerWindow(dragControl); + if (dragImageRect.IsEmpty) + { + dragImageRect = controlRect; + dragImageRegion = new Region(controlRect); + } + else + { + dragImageRect = Rectangle.Union(dragImageRect, controlRect); + dragImageRegion.Union(controlRect); + } + + //Initialize the dragged location to be the current position of the control + dragComponents[i].draggedLocation = controlRect.Location; + dragComponents[i].originalControlLocation = dragComponents[i].draggedLocation; + //take snapshot of each control + DesignerUtils.GenerateSnapShot(dragControl, ref dragComponents[i].dragImage, i == 0 ? 2 : 1, 1, backColor); + + // The dragged components are not in any specific order. If they all share the same parent, we will sort them by their index in that parent's control's collection to preserve correct Z-order + if (primaryParent != null && shareParent) + { + dragComponents[i].zorderIndex = primaryParent.Controls.GetChildIndex(dragControl, false /*throwException*/); + if (dragComponents[i].zorderIndex == -1) + { + shareParent = false; + } + } + } + if (shareParent) + { + Array.Sort(dragComponents, this); + } + + // Now that we are sorted, set the primaryComponentIndex... + for (int i = 0; i < dragComponents.Length; i++) + { + if (primaryControl.Equals(dragComponents[i].dragComponent as Control)) + { + primaryComponentIndex = i; + break; + } + } + + Debug.Assert(primaryComponentIndex != -1, "primaryComponentIndex was not set!"); + //suspend layout of the parent + if (primaryParent != null) + { + suspendedParent = primaryParent; + suspendedParent.SuspendLayout(); + // Get the parent's grid settings here + GetParentSnapInfo(suspendedParent, behaviorServiceSource); + } + + // If the thing that's being dragged is of 0 size, make the image a little bigger so that the user can see where they're dragging it. + int imageWidth = dragImageRect.Width; + if (imageWidth == 0) + { + imageWidth = 1; + } + + int imageHeight = dragImageRect.Height; + if (imageHeight == 0) + { + imageHeight = 1; + } + + dragImage = new Bitmap(imageWidth, imageHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); + using (Graphics g = Graphics.FromImage(dragImage)) + { + g.Clear(Color.Chartreuse); + } + ((Bitmap)dragImage).MakeTransparent(Color.Chartreuse); + // Gotta use 2 using's here... Too bad. + // Draw each control into the dragimage + using (Graphics g = Graphics.FromImage(dragImage)) + { + using (SolidBrush brush = new SolidBrush(primaryControl.BackColor)) + { + for (int i = 0; i < dragComponents.Length; i++) + { + Rectangle controlRect = new Rectangle(dragComponents[i].draggedLocation.X - dragImageRect.X, + dragComponents[i].draggedLocation.Y - dragImageRect.Y, + dragComponents[i].dragImage.Width, dragComponents[i].dragImage.Height); + // The background + g.FillRectangle(brush, controlRect); + // The foreground + g.DrawImage(dragComponents[i].dragImage, controlRect, + new Rectangle(0, 0, dragComponents[i].dragImage.Width, dragComponents[i].dragImage.Height), + GraphicsUnit.Pixel); + } + } + + } + + originalDragImageLocation = new Point(dragImageRect.X, dragImageRect.Y); + //hide actual controls - this might cause a brief flicker, we are okay with that. + ShowHideDragControls(false); + cleanedUpDrag = false; + } + + internal ArrayList GetSortedDragControls(ref int primaryControlIndex) + { + //create our list of controls-to-drag + ArrayList dragControls = new ArrayList(); + primaryControlIndex = -1; + if ((dragComponents != null) && (dragComponents.Length > 0)) + { + primaryControlIndex = primaryComponentIndex; + for (int i = 0; i < dragComponents.Length; i++) + { + dragControls.Add(dragComponents[i].dragComponent); + } + } + return dragControls; + } + + /// + /// Called by the BehaviorService in response to QueryContinueDrag notifications. + /// + internal void QueryContinueDrag(object sender, QueryContinueDragEventArgs e) + { + //Clean up if the action was cancelled, or we had no effect when dropped. Otherwise EndDragDrop() will do this after the locations have been properly changed. + if (behaviorServiceSource != null && behaviorServiceSource.CancelDrag) + { + e.Action = DragAction.Cancel; + CleanupDrag(true); + return; + } + + if (e.Action == DragAction.Continue) + { + return; + } + + //Clean up if the action was cancelled, or we had no effect when dropped. Otherwise EndDragDrop() will do this after the locations have been properly changed. + if (e.Action == DragAction.Cancel || lastEffect == DragDropEffects.None) + { + CleanupDrag(true); + // QueryContinueDrag can be called before GiveFeedback in which case we will end up here because lastEffect == DragDropEffects.None. If we don't set e.Action, the drag will continue, and GiveFeedback will be called. But since we have cleaned up the drag, weird things happens (e.g. dragImageRegion has been disposed already, so we throw). So if we get here, let's make sure and cancel the drag. + e.Action = DragAction.Cancel; + } + } + + /// + /// Changes the Visible state of the controls we are dragging. Returns whether we change state or not. + /// + internal bool ShowHideDragControls(bool show) + { + if (currentShowState == show) + { + return false; + } + + currentShowState = show; + if (dragComponents != null) + { + for (int i = 0; i < dragComponents.Length; i++) + { + if (dragComponents[i].dragComponent is Control c) + { + c.Visible = show; + } + } + } + return true; + } + + internal void CleanupDrag() + { + CleanupDrag(true); + } + + internal void CleanupDrag(bool clearImages) + { + if (!cleanedUpDrag) + { + if (clearImages) + { + ClearAllDragImages(); + } + + ShowHideDragControls(true); + try + { + if (suspendedParent != null) + { + suspendedParent.ResumeLayout(); + } + } + + finally + { + suspendedParent = null; + //re-enable all glyphs in all adorners + behaviorServiceSource.EnableAllAdorners(true); + if (destHost != srcHost && destHost != null) + { + behaviorServiceTarget.EnableAllAdorners(true); + behaviorServiceTarget.SyncSelection(); + } + + // Layout may have caused controls to resize, which would mean their BodyGlyphs are wrong. We need to sync these. + if (behaviorServiceSource != null) + { + behaviorServiceSource.SyncSelection(); + } + + if (dragImageRegion != null) + { + dragImageRegion.Dispose(); + dragImageRegion = null; + } + + if (dragImage != null) + { + dragImage.Dispose(); + dragImage = null; + } + + if (dragComponents != null) + { + for (int i = 0; i < dragComponents.Length; i++) + { + if (dragComponents[i].dragImage != null) + { + dragComponents[i].dragImage.Dispose(); + dragComponents[i].dragImage = null; + } + } + } + if (graphicsTarget != null) + { + graphicsTarget.Dispose(); + graphicsTarget = null; + } + cleanedUpDrag = true; + } + } + } + + /// + /// This class extends from DataObject and carries additional information such as: the list of Controls currently being dragged and the drag 'Source'. + /// + internal class BehaviorDataObject : DataObject + { + private readonly ICollection _dragComponents; + private readonly Control _source; + private IComponent _target; + private readonly DropSourceBehavior _sourceBehavior; + + public BehaviorDataObject(ICollection dragComponents, Control source, DropSourceBehavior sourceBehavior) : base() + { + _dragComponents = dragComponents; + _source = source; + _sourceBehavior = sourceBehavior; + _target = null; + } + + public Control Source + { + get => _source; + } + + public ICollection DragComponents + { + get => _dragComponents; + } + + public IComponent Target + { + get => _target; + set => _target = value; + } + + internal void EndDragDrop(bool allowSetChildIndexOnDrop) => _sourceBehavior.EndDragDrop(allowSetChildIndexOnDrop); + + internal void CleanupDrag() => _sourceBehavior.CleanupDrag(); + + internal ArrayList GetSortedDragControls(ref int primaryControlIndex) => _sourceBehavior.GetSortedDragControls(ref primaryControlIndex); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/GrabHandleGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/GrabHandleGlyph.cs new file mode 100644 index 00000000000..888a8b97a4b --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/GrabHandleGlyph.cs @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The GrabHandleGlyph represents the 8 handles of our new seleciton model. Note that the pen and brush are created once per instance of this class and re-used in our painting logic for perf. reasonse. + /// + internal class GrabHandleGlyph : SelectionGlyphBase + { + private readonly bool _isPrimary = false; + + /// + /// GrabHandleGlyph's constructor takes additional parameters: 'type' and 'primary selection'. Also, we create/cache our pen & brush here to avoid this action with every paint message. + /// + internal GrabHandleGlyph(Rectangle controlBounds, GrabHandleGlyphType type, Behavior behavior, bool primarySelection) : base(behavior) + { + _isPrimary = primarySelection; + hitTestCursor = Cursors.Default; + rules = SelectionRules.None; + + // We +/- DesignerUtils.HANDLEOVERLAP because we want each GrabHandle to overlap the control by DesignerUtils.HANDLEOVERLAP pixels + switch (type) + { + case GrabHandleGlyphType.UpperLeft: + bounds = new Rectangle((controlBounds.X + DesignerUtils.HANDLEOVERLAP) - DesignerUtils.HANDLESIZE, (controlBounds.Y + DesignerUtils.HANDLEOVERLAP) - DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeNWSE; + rules = SelectionRules.TopSizeable | SelectionRules.LeftSizeable; + break; + case GrabHandleGlyphType.UpperRight: + bounds = new Rectangle(controlBounds.Right - DesignerUtils.HANDLEOVERLAP, (controlBounds.Y + DesignerUtils.HANDLEOVERLAP) - DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeNESW; + rules = SelectionRules.TopSizeable | SelectionRules.RightSizeable; + break; + case GrabHandleGlyphType.LowerRight: + bounds = new Rectangle(controlBounds.Right - DesignerUtils.HANDLEOVERLAP, controlBounds.Bottom - DesignerUtils.HANDLEOVERLAP, DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeNWSE; + rules = SelectionRules.BottomSizeable | SelectionRules.RightSizeable; + break; + case GrabHandleGlyphType.LowerLeft: + bounds = new Rectangle((controlBounds.X + DesignerUtils.HANDLEOVERLAP) - DesignerUtils.HANDLESIZE, controlBounds.Bottom - DesignerUtils.HANDLEOVERLAP, DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeNESW; + rules = SelectionRules.BottomSizeable | SelectionRules.LeftSizeable; + break; + case GrabHandleGlyphType.MiddleTop: + // Only add this one if there's room enough. Room is enough is as follows: 2*HANDLEOVERLAP for UpperLeft and UpperRight handles, 1 HANDLESIZE for the MiddleTop handle, 1 HANDLESIZE for padding + if (controlBounds.Width >= (2 * DesignerUtils.HANDLEOVERLAP) + (2 * DesignerUtils.HANDLESIZE)) + { + bounds = new Rectangle(controlBounds.X + (controlBounds.Width / 2) - (DesignerUtils.HANDLESIZE / 2), (controlBounds.Y + DesignerUtils.HANDLEOVERLAP) - DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeNS; + rules = SelectionRules.TopSizeable; + } + break; + case GrabHandleGlyphType.MiddleBottom: + // Only add this one if there's room enough. Room is enough is as follows: 2*HANDLEOVERLAP for LowerLeft and LowerRight handles, 1 HANDLESIZE for the MiddleBottom handle, 1 HANDLESIZE for padding + if (controlBounds.Width >= (2 * DesignerUtils.HANDLEOVERLAP) + (2 * DesignerUtils.HANDLESIZE)) + { + bounds = new Rectangle(controlBounds.X + (controlBounds.Width / 2) - (DesignerUtils.HANDLESIZE / 2), controlBounds.Bottom - DesignerUtils.HANDLEOVERLAP, DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeNS; + rules = SelectionRules.BottomSizeable; + } + break; + case GrabHandleGlyphType.MiddleLeft: + // Only add this one if there's room enough. Room is enough is as follows: 2*HANDLEOVERLAP for UpperLeft and LowerLeft handles, 1 HANDLESIZE for the MiddleLeft handle, 1 HANDLESIZE for padding + if (controlBounds.Height >= (2 * DesignerUtils.HANDLEOVERLAP) + (2 * DesignerUtils.HANDLESIZE)) + { + bounds = new Rectangle((controlBounds.X + DesignerUtils.HANDLEOVERLAP) - DesignerUtils.HANDLESIZE, controlBounds.Y + (controlBounds.Height / 2) - (DesignerUtils.HANDLESIZE / 2), DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeWE; + rules = SelectionRules.LeftSizeable; + } + break; + case GrabHandleGlyphType.MiddleRight: + // Only add this one if there's room enough. Room is enough is as follows: 2*HANDLEOVERLAP for UpperRight and LowerRight handles, 1 HANDLESIZE for the MiddleRight handle, 1 HANDLESIZE for padding + if (controlBounds.Height >= (2 * DesignerUtils.HANDLEOVERLAP) + (2 * DesignerUtils.HANDLESIZE)) + { + bounds = new Rectangle(controlBounds.Right - DesignerUtils.HANDLEOVERLAP, controlBounds.Y + (controlBounds.Height / 2) - (DesignerUtils.HANDLESIZE / 2), DesignerUtils.HANDLESIZE, DesignerUtils.HANDLESIZE); + hitTestCursor = Cursors.SizeWE; + rules = SelectionRules.RightSizeable; + } + break; + default: + Debug.Assert(false, "GrabHandleGlyph was called with a bad GrapHandleGlyphType."); + break; + } + + hitBounds = bounds; + } + + /// + /// Very simple paint logic. + /// + public override void Paint(PaintEventArgs pe) + { + DesignerUtils.DrawGrabHandle(pe.Graphics, bounds, _isPrimary, this); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/GrabHandleGlyphType.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/GrabHandleGlyphType.cs new file mode 100644 index 00000000000..0999a86dacd --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/GrabHandleGlyphType.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// Describes the type of GrabHandle the GrabHandleGlyph represents. + /// + internal enum GrabHandleGlyphType + { + UpperLeft, + UpperRight, + LowerLeft, + LowerRight, + MiddleTop, + MiddleBottom, + MiddleLeft, + MiddleRight + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/LockedBorderGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/LockedBorderGlyph.cs new file mode 100644 index 00000000000..6f5d06bfc02 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/LockedBorderGlyph.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The LockedBorderGlyph draws one side (depending on type) of a SelectionBorder in the 'Locked' mode The constructor will initialize and cache the pen and brush objects to avoid uneccessary recreations. + /// + internal class LockedBorderGlyph : SelectionGlyphBase + { + /// + /// This constructor extends from the standard SelectionGlyphBase constructor. Note that a primarySelection flag is passed in - this will be used when determining the colors of the borders. + /// + internal LockedBorderGlyph(Rectangle controlBounds, SelectionBorderGlyphType type) : base(null) + { + InitializeGlyph(controlBounds, type); + } + + /// + /// Helper function that initializes the Glyph based on bounds, type, primary sel, and bordersize. + /// + private void InitializeGlyph(Rectangle controlBounds, SelectionBorderGlyphType type) + { + + hitTestCursor = Cursors.Default; // always default cursor for locked + rules = SelectionRules.None; // never change sel rules for locked + + // this will return the rect representing the bounds of the glyph + bounds = DesignerUtils.GetBoundsForSelectionType(controlBounds, type); + hitBounds = bounds; + } + + /// + /// Simple painting logic for locked Glyphs. + /// + public override void Paint(PaintEventArgs pe) + { + DesignerUtils.DrawSelectionBorder(pe.Graphics, bounds); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/LockedHandleGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/LockedHandleGlyph.cs new file mode 100644 index 00000000000..c2111519b10 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/LockedHandleGlyph.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The LockedHandleGlyph represents the handle for a non-resizeable control in our new seleciton model. Note that the pen and brush are created once per instance of this class and re-used in our painting logic for perf. reasonse. + /// + internal class LockedHandleGlyph : SelectionGlyphBase + { + private bool _isPrimary = false; + + /// + /// LockedHandleGlyph's constructor takes additional parameters: 'type' and 'primary selection'. Also, we create/cache our pen & brush here to avoid this action with every paint message. + /// + internal LockedHandleGlyph(Rectangle controlBounds, bool primarySelection) : base(null) + { + _isPrimary = primarySelection; + hitTestCursor = Cursors.Default; + rules = SelectionRules.None; + bounds = new Rectangle((controlBounds.X + DesignerUtils.LOCKHANDLEOVERLAP) - DesignerUtils.LOCKHANDLEWIDTH, + (controlBounds.Y + DesignerUtils.LOCKHANDLEOVERLAP) - DesignerUtils.LOCKHANDLEHEIGHT, + DesignerUtils.LOCKHANDLEWIDTH, DesignerUtils.LOCKHANDLEHEIGHT); + hitBounds = bounds; + } + + /// + /// Very simple paint logic. + /// + public override void Paint(PaintEventArgs pe) + { + DesignerUtils.DrawLockedHandle(pe.Graphics, bounds, _isPrimary, this); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/MiniLockedBorderGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/MiniLockedBorderGlyph.cs new file mode 100644 index 00000000000..8b0c6d41790 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/MiniLockedBorderGlyph.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The LockedBorderGlyph draws one side (depending on type) of a SelectionBorder in the 'Locked' mode. The constructor will initialize and cache the pen and brush objects to avoid uneccessary recreations. + /// + internal class MiniLockedBorderGlyph : SelectionGlyphBase + { + private SelectionBorderGlyphType _type; + + internal SelectionBorderGlyphType Type { get => _type; set => _type = value; } + + /// + /// This constructor extends from the standard SelectionGlyphBase constructor. Note that a primarySelection flag is passed in - this will be used when determining the colors of the borders. + /// + internal MiniLockedBorderGlyph(Rectangle controlBounds, SelectionBorderGlyphType type, Behavior behavior, bool primarySelection) : base(behavior) + { + InitializeGlyph(controlBounds, type); + } + + /// + /// Helper function that initializes the Glyph based on bounds, type, primary sel, and bordersize. + /// + private void InitializeGlyph(Rectangle controlBounds, SelectionBorderGlyphType type) + { + hitTestCursor = Cursors.Default; // always default cursor for locked + rules = SelectionRules.None; // never change sel rules for locked + int borderSize = 1; + Type = type; + // this will return the rect representing the bounds of the glyph + bounds = DesignerUtils.GetBoundsForSelectionType(controlBounds, type, borderSize); + hitBounds = bounds; + } + + /// + /// Simple painting logic for locked Glyphs. + /// + public override void Paint(PaintEventArgs pe) + { + pe.Graphics.FillRectangle(new SolidBrush(SystemColors.ControlText), bounds); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/NoResizeHandleGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/NoResizeHandleGlyph.cs new file mode 100644 index 00000000000..4b6c6d9cf24 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/NoResizeHandleGlyph.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The NoResizeHandleGlyph represents the handle for a non-resizeable control in our new seleciton model. Note that the pen and brush are created once per instance of this class and re-used in our painting logic for perf. reasonse. + /// + internal class NoResizeHandleGlyph : SelectionGlyphBase + { + private bool _isPrimary = false; + + /// + /// NoResizeHandleGlyph's constructor takes additional parameters: 'type' and 'primary selection'. Also, we create/cache our pen & brush here to avoid this action with every paint message. + /// + internal NoResizeHandleGlyph(Rectangle controlBounds, SelectionRules selRules, bool primarySelection, Behavior behavior) : base(behavior) + { + _isPrimary = primarySelection; + hitTestCursor = Cursors.Default; + rules = SelectionRules.None; + if ((selRules & SelectionRules.Moveable) != 0) + { + rules = SelectionRules.Moveable; + hitTestCursor = Cursors.SizeAll; + } + // The handle is always upperleft + bounds = new Rectangle(controlBounds.X - DesignerUtils.NORESIZEHANDLESIZE, controlBounds.Y - DesignerUtils.NORESIZEHANDLESIZE, DesignerUtils.NORESIZEHANDLESIZE, DesignerUtils.NORESIZEHANDLESIZE); + hitBounds = bounds; + + } + + /// + /// Very simple paint logic. + /// + public override void Paint(PaintEventArgs pe) + { + DesignerUtils.DrawNoResizeHandle(pe.Graphics, bounds, _isPrimary, this); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/NoResizeSelectionBorderGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/NoResizeSelectionBorderGlyph.cs new file mode 100644 index 00000000000..03cd2fe226e --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/NoResizeSelectionBorderGlyph.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The NoResizeSelectionBorderGlyph draws one side (depending on type) of a SelectionBorder. + /// + internal class NoResizeSelectionBorderGlyph : SelectionGlyphBase + { + /// + /// This constructor extends from the standard SelectionGlyphBase constructor. + /// + internal NoResizeSelectionBorderGlyph(Rectangle controlBounds, SelectionRules rules, SelectionBorderGlyphType type, Behavior behavior) : base(behavior) + { + InitializeGlyph(controlBounds, rules, type); + } + + /// + /// Helper function that initializes the Glyph based on bounds, type, and bordersize. + /// + private void InitializeGlyph(Rectangle controlBounds, SelectionRules selRules, SelectionBorderGlyphType type) + { + + rules = SelectionRules.None; + hitTestCursor = Cursors.Default; + if ((selRules & SelectionRules.Moveable) != 0) + { + rules = SelectionRules.Moveable; + hitTestCursor = Cursors.SizeAll; + } + + //this will return the rect representing the bounds of the glyph + bounds = DesignerUtils.GetBoundsForNoResizeSelectionType(controlBounds, type); + hitBounds = bounds; + + // The hitbounds for the border is actually a bit bigger than the glyph bounds + + switch (type) + { + case SelectionBorderGlyphType.Top: + goto case SelectionBorderGlyphType.Bottom; + case SelectionBorderGlyphType.Bottom: + // We want to apply the SELECTIONBORDERHITAREA to the top and the bottom of the selection border glyph + hitBounds.Y -= (DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE) / 2; + hitBounds.Height += DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE; + break; + case SelectionBorderGlyphType.Left: + goto case SelectionBorderGlyphType.Right; + case SelectionBorderGlyphType.Right: + // We want to apply the SELECTIONBORDERHITAREA to the left and the right of the selection border glyph + hitBounds.X -= (DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE) / 2; + hitBounds.Width += DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE; + break; + } + } + + /// + /// Simple painting logic for selection Glyphs. + /// + public override void Paint(PaintEventArgs pe) + { + DesignerUtils.DrawSelectionBorder(pe.Graphics, bounds); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ResizeBehavior.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ResizeBehavior.cs new file mode 100644 index 00000000000..273b977aabc --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/ResizeBehavior.cs @@ -0,0 +1,899 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The ResizeBehavior is pushed onto the BehaviorStack in response to a positively hit tested SelectionGlyph. The ResizeBehavior simply tracks the MouseMove messages and updates the bounds of the relatd control based on the new mouse location and the resize Rules. + /// + internal class ResizeBehavior : Behavior + { + private struct ResizeComponent + { + public object resizeControl; + public Rectangle resizeBounds; + public SelectionRules resizeRules; + }; + + private ResizeComponent[] _resizeComponents; + private readonly IServiceProvider _serviceProvider; + private BehaviorService _behaviorService; + private SelectionRules _targetResizeRules; //rules dictating which sizes we can change + private Point _initialPoint; //the initial point of the mouse down + private bool _dragging; //indicates that the behavior is currently 'dragging' + private bool _pushedBehavior; + private bool _initialResize; //true for the first resize of the control, false after that. + private DesignerTransaction _resizeTransaction; //the transaction we create for the resize + private const int MINSIZE = 10; + private const int BorderSize = 2; + private DragAssistanceManager _dragManager; //this object will integrate SnapLines into the resize + private Point _lastMouseLoc; //helps us avoid re-entering code if the mouse hasn't moved + private Point _parentLocation; //used to snap resize ops to the grid + private Size _parentGridSize; //used to snap resize ops to the grid + private NativeMethods.POINT _lastMouseAbs; // last absolute mouse position + private Point _lastSnapOffset; //the last snapoffset we used. + private bool _didSnap; //did we actually snap. + private Control _primaryControl; //the primary control the status bar will queue off of + + private Cursor _cursor = Cursors.Default; //used to set the correct cursor during resizing + private readonly StatusCommandUI _statusCommandUI; // used to update the StatusBar Information. + + private Region _lastResizeRegion; + private bool _captureLost; + + /// + /// Constructor that caches all values for perf. reasons. + /// + internal ResizeBehavior(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + _dragging = false; + _pushedBehavior = false; + _lastSnapOffset = Point.Empty; + _didSnap = false; + _statusCommandUI = new StatusCommandUI(serviceProvider); + } + + /// + /// Demand creates the BehaviorService. + /// + private BehaviorService BehaviorService + { + get + { + if (_behaviorService == null) + { + _behaviorService = (BehaviorService)_serviceProvider.GetService(typeof(BehaviorService)); + } + return _behaviorService; + } + } + + public override Cursor Cursor + { + get + { + return _cursor; + } + } + + /// + /// Called during the resize operation, we'll try to determine an offset so that the controls snap to the grid settings of the parent. + /// + private Rectangle AdjustToGrid(Rectangle controlBounds, SelectionRules rules) + { + + Rectangle rect = controlBounds; + + if ((rules & SelectionRules.RightSizeable) != 0) + { + int xDelta = controlBounds.Right % _parentGridSize.Width; + if (xDelta > _parentGridSize.Width / 2) + { + rect.Width += _parentGridSize.Width - xDelta; + } + else + { + rect.Width -= xDelta; + } + } + else if ((rules & SelectionRules.LeftSizeable) != 0) + { + int xDelta = controlBounds.Left % _parentGridSize.Width; + if (xDelta > _parentGridSize.Width / 2) + { + rect.X += _parentGridSize.Width - xDelta; + rect.Width -= _parentGridSize.Width - xDelta; + } + else + { + rect.X -= xDelta; + rect.Width += xDelta; + } + } + + if ((rules & SelectionRules.BottomSizeable) != 0) + { + int yDelta = controlBounds.Bottom % _parentGridSize.Height; + if (yDelta > _parentGridSize.Height / 2) + { + rect.Height += _parentGridSize.Height - yDelta; + } + else + { + rect.Height -= yDelta; + } + } + else if ((rules & SelectionRules.TopSizeable) != 0) + { + int yDelta = controlBounds.Top % _parentGridSize.Height; + if (yDelta > _parentGridSize.Height / 2) + { + rect.Y += _parentGridSize.Height - yDelta; + rect.Height -= _parentGridSize.Height - yDelta; + } + else + { + rect.Y -= yDelta; + rect.Height += yDelta; + } + } + + //validate our dimensions + rect.Width = Math.Max(rect.Width, _parentGridSize.Width); + rect.Height = Math.Max(rect.Height, _parentGridSize.Height); + + return rect; + } + + /// + /// Builds up an array of snaplines used during resize to adjust/snap the controls bounds. + /// + private SnapLine[] GenerateSnapLines(SelectionRules rules, Point loc) + { + ArrayList lines = new ArrayList(2); + //the four margins and edges of our control + if ((rules & SelectionRules.BottomSizeable) != 0) + { + lines.Add(new SnapLine(SnapLineType.Bottom, loc.Y - 1)); + if (_primaryControl != null) + { + lines.Add(new SnapLine(SnapLineType.Horizontal, loc.Y + _primaryControl.Margin.Bottom, SnapLine.MarginBottom, SnapLinePriority.Always)); + } + } + else if ((rules & SelectionRules.TopSizeable) != 0) + { + lines.Add(new SnapLine(SnapLineType.Top, loc.Y)); + if (_primaryControl != null) + { + lines.Add(new SnapLine(SnapLineType.Horizontal, loc.Y - _primaryControl.Margin.Top, SnapLine.MarginTop, SnapLinePriority.Always)); + } + } + + if ((rules & SelectionRules.RightSizeable) != 0) + { + lines.Add(new SnapLine(SnapLineType.Right, loc.X - 1)); + if (_primaryControl != null) + { + lines.Add(new SnapLine(SnapLineType.Vertical, loc.X + _primaryControl.Margin.Right, SnapLine.MarginRight, SnapLinePriority.Always)); + } + } + else if ((rules & SelectionRules.LeftSizeable) != 0) + { + lines.Add(new SnapLine(SnapLineType.Left, loc.X)); + if (_primaryControl != null) + { + lines.Add(new SnapLine(SnapLineType.Vertical, loc.X - _primaryControl.Margin.Left, SnapLine.MarginLeft, SnapLinePriority.Always)); + } + } + + SnapLine[] l = new SnapLine[lines.Count]; + lines.CopyTo(l); + + return l; + } + + /// + /// This is called in response to the mouse moving far enough away from its initial point. Basically, we calculate the bounds for each control we're resizing and disable any adorners. + /// + private void InitiateResize() + { + bool useSnapLines = BehaviorService.UseSnapLines; + ArrayList components = new ArrayList(); + //check to see if the current designer participate with SnapLines cache the control bounds + for (int i = 0; i < _resizeComponents.Length; i++) + { + _resizeComponents[i].resizeBounds = ((Control)(_resizeComponents[i].resizeControl)).Bounds; + if (useSnapLines) + { + components.Add(_resizeComponents[i].resizeControl); + } + if (_serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost designerHost) + { + if (designerHost.GetDesigner(_resizeComponents[i].resizeControl as Component) is ControlDesigner designer) + { + _resizeComponents[i].resizeRules = designer.SelectionRules; + } + else + { + Debug.Fail("Initiating resize. Could not get the designer for " + _resizeComponents[i].resizeControl.ToString()); + _resizeComponents[i].resizeRules = SelectionRules.None; + } + } + } + + //disable all glyphs in all adorners + BehaviorService.EnableAllAdorners(false); + //build up our resize transaction + IDesignerHost host = (IDesignerHost)_serviceProvider.GetService(typeof(IDesignerHost)); + if (host != null) + { + string locString; + if (_resizeComponents.Length == 1) + { + string name = TypeDescriptor.GetComponentName(_resizeComponents[0].resizeControl); + if (name == null || name.Length == 0) + { + name = _resizeComponents[0].resizeControl.GetType().Name; + } + locString = string.Format(SR.BehaviorServiceResizeControl, name); + } + else + { + locString = string.Format(SR.BehaviorServiceResizeControls, _resizeComponents.Length); + } + _resizeTransaction = host.CreateTransaction(locString); + } + + _initialResize = true; + if (useSnapLines) + { + //instantiate our class to manage snap/margin lines... + _dragManager = new DragAssistanceManager(_serviceProvider, components, true); + } + else if (_resizeComponents.Length > 0) + { + //try to get the parents grid and snap settings + if (_resizeComponents[0].resizeControl is Control control && control.Parent != null) + { + PropertyDescriptor snapProp = TypeDescriptor.GetProperties(control.Parent)["SnapToGrid"]; + if (snapProp != null && (bool)snapProp.GetValue(control.Parent)) + { + PropertyDescriptor gridProp = TypeDescriptor.GetProperties(control.Parent)["GridSize"]; + if (gridProp != null) + { + //cache of the gridsize and the location of the parent on the adornerwindow + _parentGridSize = (Size)gridProp.GetValue(control.Parent); + _parentLocation = _behaviorService.ControlToAdornerWindow(control); + _parentLocation.X -= control.Location.X; + _parentLocation.Y -= control.Location.Y; + } + } + } + } + _captureLost = false; + } + + /// + /// In response to a MouseDown, the SelectionBehavior will push (initiate) a dragBehavior by alerting the SelectionMananger that a new control has been selected and the mouse is down. Note that this is only if we find the related control's Dock property == none. + /// + public override bool OnMouseDown(Glyph g, MouseButtons button, Point mouseLoc) + { + //we only care about the right mouse button for resizing + if (button != MouseButtons.Left) + { + //pass any other mouse click along - unless we've already started our resize in which case we'll ignore it + return _pushedBehavior; + } + //start with no selection rules and try to obtain this info from the glyph + _targetResizeRules = SelectionRules.None; + if (g is SelectionGlyphBase sgb) + { + _targetResizeRules = sgb.SelectionRules; + _cursor = sgb.HitTestCursor; + } + + if (_targetResizeRules == SelectionRules.None) + { + return false; + } + + ISelectionService selSvc = (ISelectionService)_serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc == null) + { + return false; + } + + _initialPoint = mouseLoc; + _lastMouseLoc = mouseLoc; + //build up a list of our selected controls + _primaryControl = selSvc.PrimarySelection as Control; + + // Since we don't know exactly how many valid objects we are going to have we use this temp + ArrayList components = new ArrayList(); + foreach (object o in selSvc.GetSelectedComponents()) + { + if (o is Control) + { + //don't drag locked controls + PropertyDescriptor prop = TypeDescriptor.GetProperties(o)["Locked"]; + if (prop != null) + { + if ((bool)prop.GetValue(o)) + continue; + } + components.Add(o); + } + } + + if (components.Count == 0) + { + return false; + } + + _resizeComponents = new ResizeComponent[components.Count]; + for (int i = 0; i < components.Count; i++) + { + _resizeComponents[i].resizeControl = components[i]; + } + + //push this resizebehavior + _pushedBehavior = true; + BehaviorService.PushCaptureBehavior(this); + return false; + } + + /// + /// This method is called when we lose capture, which can occur when another window requests capture or the user presses ESC during a drag. We check to see if we are currently dragging, and if we are we abort the transaction. We pop our behavior off the stack at this time. + /// + public override void OnLoseCapture(Glyph g, EventArgs e) + { + _captureLost = true; + if (_pushedBehavior) + { + _pushedBehavior = false; + Debug.Assert(BehaviorService != null, "We should have a behavior service."); + if (BehaviorService != null) + { + if (_dragging) + { + _dragging = false; + //make sure we get rid of the selection rectangle + for (int i = 0; !_captureLost && i < _resizeComponents.Length; i++) + { + Control control = _resizeComponents[i].resizeControl as Control; + Rectangle borderRect = BehaviorService.ControlRectInAdornerWindow(control); + if (!borderRect.IsEmpty) + { + using (Graphics graphics = BehaviorService.AdornerWindowGraphics) + { + graphics.SetClip(borderRect); + using (Region newRegion = new Region(borderRect)) + { + newRegion.Exclude(Rectangle.Inflate(borderRect, -BorderSize, -BorderSize)); + BehaviorService.Invalidate(newRegion); + } + graphics.ResetClip(); + } + } + } + //re-enable all glyphs in all adorners + BehaviorService.EnableAllAdorners(true); + } + BehaviorService.PopBehavior(this); + + if (_lastResizeRegion != null) + { + BehaviorService.Invalidate(_lastResizeRegion); //might be the same, might not. + _lastResizeRegion.Dispose(); + _lastResizeRegion = null; + } + } + } + + Debug.Assert(!_dragging, "How can we be dragging without pushing a behavior?"); + // If we still have a transaction, roll it back. + if (_resizeTransaction != null) + { + DesignerTransaction t = _resizeTransaction; + _resizeTransaction = null; + using (t) + { + t.Cancel(); + } + } + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] + internal static int AdjustPixelsForIntegralHeight(Control control, int pixelsMoved) + { + PropertyDescriptor propIntegralHeight = TypeDescriptor.GetProperties(control)["IntegralHeight"]; + if (propIntegralHeight != null) + { + object value = propIntegralHeight.GetValue(control); + if (value is bool && (bool)value == true) + { + PropertyDescriptor propItemHeight = TypeDescriptor.GetProperties(control)["ItemHeight"]; + if (propItemHeight != null) + { + if (pixelsMoved >= 0) + { + return pixelsMoved - (pixelsMoved % (int)propItemHeight.GetValue(control)); + } + else + { + int integralHeight = (int)propItemHeight.GetValue(control); + return pixelsMoved - (integralHeight - (Math.Abs(pixelsMoved) % integralHeight)); + } + } + } + } + //if the control does not have the IntegralHeight property, then the pixels moved are fine + return pixelsMoved; + } + + /// + /// This method will either initiate a new resize operation or continue with an existing one. If we're currently dragging (i.e. resizing) then we look at the resize rules and set the bounds of each control to the new location of the mouse pointer. + /// + public override bool OnMouseMove(Glyph g, MouseButtons button, Point mouseLoc) + { + if (!_pushedBehavior) + { + return false; + } + + bool altKeyPressed = Control.ModifierKeys == Keys.Alt; + if (altKeyPressed && _dragManager != null) + { + //erase any snaplines (if we had any) + _dragManager.EraseSnapLines(); + } + + if (!altKeyPressed && mouseLoc.Equals(_lastMouseLoc)) + { + return true; + } + + // When DesignerWindowPane has scrollbars and we resize, shrinking the the DesignerWindowPane makes it look like the mouse has moved to the BS. To compensate for that we keep track of the mouse's previous position in screen coordinates, and use that to compare if the mouse has really moved. + if (_lastMouseAbs != null) + { + NativeMethods.POINT mouseLocAbs = new NativeMethods.POINT(mouseLoc.X, mouseLoc.Y); + UnsafeNativeMethods.ClientToScreen(new HandleRef(this, _behaviorService.AdornerWindowControl.Handle), mouseLocAbs); + if (mouseLocAbs.x == _lastMouseAbs.x && mouseLocAbs.y == _lastMouseAbs.y) + { + return true; + } + } + + + if (!_dragging) + { + if (Math.Abs(_initialPoint.X - mouseLoc.X) > DesignerUtils.MinDragSize.Width / 2 || Math.Abs(_initialPoint.Y - mouseLoc.Y) > DesignerUtils.MinDragSize.Height / 2) + { + InitiateResize(); + _dragging = true; + } + else + { + return false; + } + } + + if (_resizeComponents == null || _resizeComponents.Length == 0) + { + return false; + } + // we do these separately so as not to disturb the cached sizes for values we're not actually changing. For example, if a control is docked top and we modify the height, the width shouldn't be modified. + PropertyDescriptor propWidth = null; + PropertyDescriptor propHeight = null; + PropertyDescriptor propTop = null; + PropertyDescriptor propLeft = null; + + // We do this to make sure that Undo works correctly. + if (_initialResize) + { + propWidth = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Width"]; + propHeight = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Height"]; + propTop = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Top"]; + propLeft = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Left"]; + + // validate each of the property descriptors. + if (propWidth != null && !typeof(int).IsAssignableFrom(propWidth.PropertyType)) + { + propWidth = null; + } + + if (propHeight != null && !typeof(int).IsAssignableFrom(propHeight.PropertyType)) + { + propHeight = null; + } + + if (propTop != null && !typeof(int).IsAssignableFrom(propTop.PropertyType)) + { + propTop = null; + } + + if (propLeft != null && !typeof(int).IsAssignableFrom(propLeft.PropertyType)) + { + propLeft = null; + } + } + + Control targetControl = _resizeComponents[0].resizeControl as Control; + _lastMouseLoc = mouseLoc; + _lastMouseAbs = new NativeMethods.POINT(mouseLoc.X, mouseLoc.Y); + UnsafeNativeMethods.ClientToScreen(new HandleRef(this, _behaviorService.AdornerWindowControl.Handle), _lastMouseAbs); + int minHeight = Math.Max(targetControl.MinimumSize.Height, MINSIZE); + int minWidth = Math.Max(targetControl.MinimumSize.Width, MINSIZE); + if (_dragManager != null) + { + bool shouldSnap = true; + bool shouldSnapHorizontally = true; + //if the targetcontrol is at min-size then we do not want to offer up snaplines + if ((((_targetResizeRules & SelectionRules.BottomSizeable) != 0) || ((_targetResizeRules & SelectionRules.TopSizeable) != 0)) && + (targetControl.Height == minHeight)) + { + shouldSnap = false; + } + else if ((((_targetResizeRules & SelectionRules.RightSizeable) != 0) || ((_targetResizeRules & SelectionRules.LeftSizeable) != 0)) && + (targetControl.Width == minWidth)) + { + shouldSnap = false; + } + + //if the targetControl has IntegralHeight turned on, then don't snap if the control can be resized vertically + PropertyDescriptor propIntegralHeight = TypeDescriptor.GetProperties(targetControl)["IntegralHeight"]; + if (propIntegralHeight != null) + { + object value = propIntegralHeight.GetValue(targetControl); + if (value is bool && (bool)value == true) + { + shouldSnapHorizontally = false; + } + } + + if (!altKeyPressed && shouldSnap) + { + //here, ask the snapline engine to suggest an offset during our resize + // Remembering the last snapoffset allows us to correctly erase snaplines, if the user subsequently holds down the Alt-Key. Remember that we don't physically move the mouse, we move the control. So if we didn't remember the last snapoffset and the user then hit the Alt-Key, we would actually redraw the control at the actual mouse location, which would make the control "jump" which is not what the user would expect. Why does the control "jump"? Because when a control is snapped, we have offset the control relative to where the mouse is, but we have not update the physical mouse position. + // When the user hits the Alt-Key they expect the control to be where it was (whether snapped or not). we can't rely on lastSnapOffset to check whether we snapped. We used to check if it was empty, but it can be empty and we still snapped (say the control was snapped, as you continue to move the mouse, it will stay snapped for a while. During that while the snapoffset will got from x to -x (or vice versa) and a one point hit 0. + // Since we have to calculate the new size/location differently based on whether we snapped or not, we have to know for sure if we snapped. We do different math because of bug 264996: + // - if you snap, we want to move the control edge. + // - otherwise, we just want to change the size by the number of pixels moved. + _lastSnapOffset = _dragManager.OnMouseMove(targetControl, GenerateSnapLines(_targetResizeRules, mouseLoc), ref _didSnap, shouldSnapHorizontally); + } + else + { + _dragManager.OnMouseMove(new Rectangle(-100, -100, 0, 0));/*just an invalid rect - so we won't snap*///); + } + + // If there's a line to snap to, the offset will come back non-zero. In that case we should adjust the mouse position with the offset such that the size calculation below takes that offset into account. If there's no line, then the offset is 0, and there's no harm in adding the offset. + mouseLoc.X += _lastSnapOffset.X; + mouseLoc.Y += _lastSnapOffset.Y; + } + + // IF WE ARE SNAPPING TO A CONTROL, then we also need to adjust for the offset between the initialPoint (where the MouseDown happened) and the edge of the control otherwise we would be those pixels off when resizing the control. Remember that snaplines are based on the targetControl, so we need to use the targetControl to figure out the offset. + Rectangle controlBounds = new Rectangle(_resizeComponents[0].resizeBounds.X, _resizeComponents[0].resizeBounds.Y, + _resizeComponents[0].resizeBounds.Width, _resizeComponents[0].resizeBounds.Height); + if ((_didSnap) && (targetControl.Parent != null)) + { + controlBounds.Location = _behaviorService.MapAdornerWindowPoint(targetControl.Parent.Handle, controlBounds.Location); + if (targetControl.Parent.IsMirrored) + { + controlBounds.Offset(-controlBounds.Width, 0); + } + } + + Rectangle newBorderRect = Rectangle.Empty; + Rectangle targetBorderRect = Rectangle.Empty; + bool drawSnapline = true; + Color backColor = targetControl.Parent != null ? targetControl.Parent.BackColor : Color.Empty; + for (int i = 0; i < _resizeComponents.Length; i++) + { + Control control = _resizeComponents[i].resizeControl as Control; + Rectangle bounds = control.Bounds; + Rectangle oldBounds = bounds; + // We need to compute the offset beased on the original cached Bounds ... ListBox doesnt allow drag on the top boundary if this is not done when it is "IntegralHeight" + Rectangle baseBounds = _resizeComponents[i].resizeBounds; + Rectangle oldBorderRect = BehaviorService.ControlRectInAdornerWindow(control); + bool needToUpdate = true; + // The ResizeBehavior can easily get into a situation where we are fighting with a layout engine. E.g., We resize control to 50px, LayoutEngine lays out and finds 50px was too small and resized back to 100px. This is what should happen, but it looks bad in the designer. To avoid the flicker we temporarily turn off painting while we do the resize. + UnsafeNativeMethods.SendMessage(control.Handle, Interop.WindowMessages.WM_SETREDRAW, false, /* unused = */ 0); + try + { + bool fRTL = false; + // If the container is mirrored the control origin is in upper-right, so we need to adjust our math for that. Remember that mouse coords have origin in upper left. + if (control.Parent != null && control.Parent.IsMirrored) + { + fRTL = true; + } + // figure out which ones we're actually changing so we don't blow away the controls cached sizing state. This is important if things are docked we don't want to destroy their "pre-dock" size. + BoundsSpecified specified = BoundsSpecified.None; + // When we check if we should change height, width, location, we first have to check if the targetControl allows resizing, and then if the control we are currently resizing allows it as well. + SelectionRules resizeRules = _resizeComponents[i].resizeRules; + if (((_targetResizeRules & SelectionRules.BottomSizeable) != 0) && + ((resizeRules & SelectionRules.BottomSizeable) != 0)) + { + int pixelHeight; + if (_didSnap) + { + pixelHeight = mouseLoc.Y - controlBounds.Bottom; + } + else + { + pixelHeight = AdjustPixelsForIntegralHeight(control, mouseLoc.Y - _initialPoint.Y); + } + + bounds.Height = Math.Max(minHeight, baseBounds.Height + pixelHeight); + specified |= BoundsSpecified.Height; + } + + if (((_targetResizeRules & SelectionRules.TopSizeable) != 0) && + ((resizeRules & SelectionRules.TopSizeable) != 0)) + { + int yOffset; + if (_didSnap) + { + yOffset = controlBounds.Y - mouseLoc.Y; + } + else + { + yOffset = AdjustPixelsForIntegralHeight(control, _initialPoint.Y - mouseLoc.Y); + } + + specified |= BoundsSpecified.Height; + bounds.Height = Math.Max(minHeight, baseBounds.Height + yOffset); + if ((bounds.Height != minHeight) || + ((bounds.Height == minHeight) && (oldBounds.Height != minHeight))) + { + specified |= BoundsSpecified.Y; + //if you do it fast enough, we actually could end up placing the control off the parent (say off the form), so enforce a "minimum" location + bounds.Y = Math.Min(baseBounds.Bottom - minHeight, baseBounds.Y - yOffset); + } + } + + if (((((_targetResizeRules & SelectionRules.RightSizeable) != 0) && ((resizeRules & SelectionRules.RightSizeable) != 0)) && (!fRTL)) || + ((((_targetResizeRules & SelectionRules.LeftSizeable) != 0) && ((resizeRules & SelectionRules.LeftSizeable) != 0)) && (fRTL))) + { + specified |= BoundsSpecified.Width; + int xOffset = _initialPoint.X; + if (_didSnap) + { + xOffset = !fRTL ? controlBounds.Right : controlBounds.Left; + } + bounds.Width = Math.Max(minWidth, baseBounds.Width + (!fRTL ? (mouseLoc.X - xOffset) : (xOffset - mouseLoc.X))); + } + + if (((((_targetResizeRules & SelectionRules.RightSizeable) != 0) && ((resizeRules & SelectionRules.RightSizeable) != 0)) && (fRTL)) || + ((((_targetResizeRules & SelectionRules.LeftSizeable) != 0) && ((resizeRules & SelectionRules.LeftSizeable) != 0)) && (!fRTL))) + { + specified |= BoundsSpecified.Width; + int xPos = _initialPoint.X; + if (_didSnap) + { + xPos = !fRTL ? controlBounds.Left : controlBounds.Right; + } + + int xOffset = !fRTL ? (xPos - mouseLoc.X) : (mouseLoc.X - xPos); + bounds.Width = Math.Max(minWidth, baseBounds.Width + xOffset); + if ((bounds.Width != minWidth) || + ((bounds.Width == minWidth) && (oldBounds.Width != minWidth))) + { + specified |= BoundsSpecified.X; + //if you do it fast enough, we actually could end up placing the control off the parent (say off the form), so enforce a "minimum" location + bounds.X = Math.Min(baseBounds.Right - minWidth, baseBounds.X - xOffset); + } + } + + if (!_parentGridSize.IsEmpty) + { + bounds = AdjustToGrid(bounds, _targetResizeRules); + } + + // Checking specified (check the diff) rather than bounds. != resizeBounds[i]. also handles the following corner cases: + // 1. Create a form and add 2 buttons. Make sure that they are snapped to the left edge. Now grab the left edge of button 1, and start resizing to the left, past the snapline you will initially get, and then back to the right. What you would expect is to get the left edge snapline again. But without the specified check you wouldn't. This is because the bounds. != resizeBounds[i]. checks would fail, since the new size would now be the original size. We could probably live with that, except that we draw the snapline below, since we correctly identified one. We could hack it so that we didn't draw the snapline, but that would confuse the user even more. + // 2. Create a form and add a single button. Place it at 100,100. Now start resizing it to the left and then back to the right. Note that with the original check (see diff), you would never be able to resize it back to position 100,100. You would get to 99,100 and then to 101,100. + if (((specified & BoundsSpecified.Width) == BoundsSpecified.Width) && + _dragging && _initialResize && propWidth != null) + { + propWidth.SetValue(_resizeComponents[i].resizeControl, bounds.Width); + } + + if (((specified & BoundsSpecified.Height) == BoundsSpecified.Height) && + _dragging && _initialResize && propHeight != null) + { + propHeight.SetValue(_resizeComponents[i].resizeControl, bounds.Height); + } + + if (((specified & BoundsSpecified.X) == BoundsSpecified.X) && + _dragging && _initialResize && propLeft != null) + { + propLeft.SetValue(_resizeComponents[i].resizeControl, bounds.X); + } + + if (((specified & BoundsSpecified.Y) == BoundsSpecified.Y) && + _dragging && _initialResize && propTop != null) + { + propTop.SetValue(_resizeComponents[i].resizeControl, bounds.Y); + } + + // We check the dragging bit here at every turn, because if there was a popup we may have lost capture and we are terminated. At that point we shouldn't make any changes. + if (_dragging) + { + control.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height, specified); + //Get the new resize border + newBorderRect = BehaviorService.ControlRectInAdornerWindow(control); + if (control.Equals(targetControl)) + { + Debug.Assert(i == 0, "The first control in the Selection should be the target control"); + targetBorderRect = newBorderRect; + } + + //Check that the control really did resize itself. Some controls (like ListBox, MonthCalendar) might adjust to a slightly different size than the one we pass in SetBounds. If if didn't size, then there's no need to invalidate anything + if (control.Bounds == oldBounds) + { + needToUpdate = false; + } + // We would expect the bounds now to be what we set it to above, but this might not be the case. If the control is hosted with e.g. a FLP, then setting the bounds above actually might force a re-layout, and the control will get moved to another spot. In this case, we don't really want to draw a snapline. Even if we snapped to a snapline, if the control got moved, the snapline would be in the wrong place. + if (control.Bounds != bounds) + { + drawSnapline = false; + } + } + + if (control == _primaryControl && _statusCommandUI != null) + { + _statusCommandUI.SetStatusInformation(control as Component); + } + } + finally + { + // While we were resizing we discarded painting messages to reduce flicker. We now turn painting back on and manually refresh the controls. + UnsafeNativeMethods.SendMessage(control.Handle, Interop.WindowMessages.WM_SETREDRAW, true, /* unused = */ 0); + //update the control + if (needToUpdate) + { + Control parent = control.Parent; + if (parent != null) + { + control.Invalidate(/* invalidateChildren = */ true); + parent.Invalidate(oldBounds, /* invalidateChildren = */ true); + parent.Update(); + } + else + { + control.Refresh(); + } + } + + //render the resize border + if (!newBorderRect.IsEmpty) + { + using (Region newRegion = new Region(newBorderRect)) + { + newRegion.Exclude(Rectangle.Inflate(newBorderRect, -BorderSize, -BorderSize)); + //No reason to get smart about only invalidating part of the border. Thought we could be but no.The reason is the order: ... the new border is drawn (last resize) On next mousemove, the control is resized which redraws the control AND ERASES THE BORDER Then we draw the new border - flash baby. Thus this will always flicker. + if (needToUpdate) + { + using (Region oldRegion = new Region(oldBorderRect)) + { + oldRegion.Exclude(Rectangle.Inflate(oldBorderRect, -BorderSize, -BorderSize)); + BehaviorService.Invalidate(oldRegion); + } + } + + //draw the new border captureLost could be true if a popup came up and caused a lose focus + if (!_captureLost) + { + using (Graphics graphics = BehaviorService.AdornerWindowGraphics) + { + if (_lastResizeRegion != null) + { + if (!_lastResizeRegion.Equals(newRegion, graphics)) + { + _lastResizeRegion.Exclude(newRegion); //we don't want to invalidate this region. + BehaviorService.Invalidate(_lastResizeRegion); //might be the same, might not. + _lastResizeRegion.Dispose(); + _lastResizeRegion = null; + } + } + DesignerUtils.DrawResizeBorder(graphics, newRegion, backColor); + } + if (_lastResizeRegion == null) + { + _lastResizeRegion = newRegion.Clone(); //we will need to dispose it later. + } + } + } + } + } + } + + if ((drawSnapline) && (!altKeyPressed) && (_dragManager != null)) + { + _dragManager.RenderSnapLinesInternal(targetBorderRect); + } + + _initialResize = false; + return true; + } + + /// + /// This ends the Behavior by popping itself from the BehaviorStack. Also, all Adorners are re-enabled at the end of a successful drag. + /// + public override bool OnMouseUp(Glyph g, MouseButtons button) + { + try + { + if (_dragging) + { + if (_dragManager != null) + { + _dragManager.OnMouseUp(); + _dragManager = null; + _lastSnapOffset = Point.Empty; + _didSnap = false; + } + + if (_resizeComponents != null && _resizeComponents.Length > 0) + { + // we do these separately so as not to disturb the cached sizes for values we're not actually changing. For example, if a control is docked top and we modify the height, the width shouldn't be modified. + PropertyDescriptor propWidth = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Width"]; + PropertyDescriptor propHeight = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Height"]; + PropertyDescriptor propTop = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Top"]; + PropertyDescriptor propLeft = TypeDescriptor.GetProperties(_resizeComponents[0].resizeControl)["Left"]; + for (int i = 0; i < _resizeComponents.Length; i++) + { + if (propWidth != null && ((Control)_resizeComponents[i].resizeControl).Width != _resizeComponents[i].resizeBounds.Width) + { + propWidth.SetValue(_resizeComponents[i].resizeControl, ((Control)_resizeComponents[i].resizeControl).Width); + } + if (propHeight != null && ((Control)_resizeComponents[i].resizeControl).Height != _resizeComponents[i].resizeBounds.Height) + { + propHeight.SetValue(_resizeComponents[i].resizeControl, ((Control)_resizeComponents[i].resizeControl).Height); + } + + if (propTop != null && ((Control)_resizeComponents[i].resizeControl).Top != _resizeComponents[i].resizeBounds.Y) + { + propTop.SetValue(_resizeComponents[i].resizeControl, ((Control)_resizeComponents[i].resizeControl).Top); + } + if (propLeft != null && ((Control)_resizeComponents[i].resizeControl).Left != _resizeComponents[i].resizeBounds.X) + { + propLeft.SetValue(_resizeComponents[i].resizeControl, ((Control)_resizeComponents[i].resizeControl).Left); + } + + if (_resizeComponents[i].resizeControl == _primaryControl && _statusCommandUI != null) + { + _statusCommandUI.SetStatusInformation(_primaryControl as Component); + } + } + } + } + + if (_resizeTransaction != null) + { + DesignerTransaction t = _resizeTransaction; + _resizeTransaction = null; + using (t) + { + t.Commit(); + } + } + } + finally + { + // This pops us off the stack, re-enables adorners and clears the "dragging" flag. + OnLoseCapture(g, EventArgs.Empty); + } + return false; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionBorderGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionBorderGlyph.cs new file mode 100644 index 00000000000..d8a8289e141 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionBorderGlyph.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The SelectionBorderGlyph draws one side (depending on type) of a SelectionBorder. + /// + internal class SelectionBorderGlyph : SelectionGlyphBase + { + /// + /// This constructor extends from the standard SelectionGlyphBase constructor. + /// + internal SelectionBorderGlyph(Rectangle controlBounds, SelectionRules rules, SelectionBorderGlyphType type, Behavior behavior) : base(behavior) + { + InitializeGlyph(controlBounds, rules, type); + } + + /// + /// Helper function that initializes the Glyph based on bounds, type, and bordersize. + /// + private void InitializeGlyph(Rectangle controlBounds, SelectionRules selRules, SelectionBorderGlyphType type) + { + rules = SelectionRules.None; + hitTestCursor = Cursors.Default; + + //this will return the rect representing the bounds of the glyph + bounds = DesignerUtils.GetBoundsForSelectionType(controlBounds, type); + hitBounds = bounds; + + // The hitbounds for the border is actually a bit bigger than the glyph bounds + switch (type) + { + case SelectionBorderGlyphType.Top: + if ((selRules & SelectionRules.TopSizeable) != 0) + { + hitTestCursor = Cursors.SizeNS; + rules = SelectionRules.TopSizeable; + } + // We want to apply the SELECTIONBORDERHITAREA to the top and the bottom of the selection border glyph + hitBounds.Y -= (DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE) / 2; + hitBounds.Height += DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE; + break; + case SelectionBorderGlyphType.Bottom: + if ((selRules & SelectionRules.BottomSizeable) != 0) + { + hitTestCursor = Cursors.SizeNS; + rules = SelectionRules.BottomSizeable; + } + // We want to apply the SELECTIONBORDERHITAREA to the top and the bottom of the selection border glyph + hitBounds.Y -= (DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE) / 2; + hitBounds.Height += DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE; + break; + case SelectionBorderGlyphType.Left: + if ((selRules & SelectionRules.LeftSizeable) != 0) + { + hitTestCursor = Cursors.SizeWE; + rules = SelectionRules.LeftSizeable; + } + // We want to apply the SELECTIONBORDERHITAREA to the left and the right of the selection border glyph + hitBounds.X -= (DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE) / 2; + hitBounds.Width += DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE; + break; + case SelectionBorderGlyphType.Right: + if ((selRules & SelectionRules.RightSizeable) != 0) + { + hitTestCursor = Cursors.SizeWE; + rules = SelectionRules.RightSizeable; + } + // We want to apply the SELECTIONBORDERHITAREA to the left and the right of the selection border glyph + hitBounds.X -= (DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE) / 2; + hitBounds.Width += DesignerUtils.SELECTIONBORDERHITAREA - DesignerUtils.SELECTIONBORDERSIZE; + break; + } + } + + /// + /// Simple painting logic for selection Glyphs. + /// + public override void Paint(PaintEventArgs pe) + { + DesignerUtils.DrawSelectionBorder(pe.Graphics, bounds); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionBorderGlyphType.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionBorderGlyphType.cs new file mode 100644 index 00000000000..bfb30c1be2a --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionBorderGlyphType.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// Describes the type of SelectionBorder the SelectionBorderGlyph represents. + /// + internal enum SelectionBorderGlyphType + { + Top, Bottom, Left, Right, Body + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionGlyphBase.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionGlyphBase.cs new file mode 100644 index 00000000000..766efd2c361 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionGlyphBase.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// This is the base class for all the selection Glyphs: GrabHandle, Hidden, Locked, Selection, and Tray Glyphs. This class includes all like-operations for the Selection glyphs. + /// + internal abstract class SelectionGlyphBase : Glyph + { + protected Rectangle bounds; // defines the bounds of the selection glyph + protected Rectangle hitBounds; // defines the bounds used for hittest - it could be different than the bounds of the glyph itself + protected Cursor hitTestCursor; // the cursor returned if hit test is positive + protected SelectionRules rules; // the selection rules - defining how the control can change + + /// + /// Standard constructor. + /// + internal SelectionGlyphBase(Behavior behavior) : base(behavior) + { + } + + /// + /// Read-only property describing the SelecitonRules for these Glyphs. + /// + public SelectionRules SelectionRules + { + get => rules; + } + + /// + /// Simple hit test rule: if the point is contained within the bounds - then it is a positive hit test. + /// + public override Cursor GetHitTest(Point p) + { + if (hitBounds.Contains(p)) + { + return hitTestCursor; + } + return null; + } + + /// + /// Returns the HitTestCursor for this glyph. + /// + public Cursor HitTestCursor + { + get => hitTestCursor; + } + + /// + /// The Bounds of this glyph. + /// + public override Rectangle Bounds + { + get => bounds; + } + + /// + /// There's no paint logic on this base class. + /// + public override void Paint(PaintEventArgs pe) + { + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionManager.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionManager.cs new file mode 100644 index 00000000000..057be900027 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SelectionManager.cs @@ -0,0 +1,470 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace System.Windows.Forms.Design.Behavior +{ + /// + /// The SelectionBehavior is pushed onto the BehaviorStack in response to a positively hit tested SelectionGlyph. The SelectionBehavior performs two main tasks: 1) forward messages to the related ControlDesigner, and 2) calls upon the SelectionManager to push a potention DragBehavior. + /// + internal sealed class SelectionManager : IDisposable + { + private Adorner selectionAdorner;//used to provide all selection glyphs + private Adorner bodyAdorner;//used to track all body glyphs for each control + private BehaviorService behaviorService;//ptr back to our BehaviorService + private IServiceProvider serviceProvider;//standard service provider + private Hashtable componentToDesigner;//used for quick look up of designers related to comps + private Control rootComponent;//root component being designed + private ISelectionService selSvc;//we cache the selection service for perf. + private IDesignerHost designerHost;//we cache the designerhost for perf. + private bool needRefresh; // do we need to refresh? + private Rectangle[] prevSelectionBounds;//used to only repaint the changing part of the selection + private object prevPrimarySelection; //used to check if the primary selection changed + private Rectangle[] curSelectionBounds; + private int curCompIndex; + private DesignerActionUI designerActionUI = null; // the "container" for all things related to the designer action (smartags) UI + private bool selectionChanging; //we dont want the OnSelectionChanged to be recursively called. + + /// + /// Constructor. Here we query for necessary services and cache them for perf. reasons. We also hook to Component Added/Removed/Changed notifications so we can keep in sync when the designers' components change. Also, we create our custom Adorner and add it to the BehaviorService. + /// + public SelectionManager(IServiceProvider serviceProvider, BehaviorService behaviorService) + { + prevSelectionBounds = null; + prevPrimarySelection = null; + this.behaviorService = behaviorService; + this.serviceProvider = serviceProvider; + + selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + + if (designerHost == null || selSvc == null) + { + Debug.Fail("SelectionManager - Host or SelSvc is null, can't continue"); + } + + //sync the BehaviorService's begindrag event + behaviorService.BeginDrag += new BehaviorDragDropEventHandler(OnBeginDrag); + //sync the BehaviorService's Synchronize event + behaviorService.Synchronize += new EventHandler(OnSynchronize); + selSvc.SelectionChanged += new EventHandler(OnSelectionChanged); + rootComponent = (Control)designerHost.RootComponent; + + // create and add both of our adorners, one for selection, one for bodies + selectionAdorner = new Adorner(); + bodyAdorner = new Adorner(); + behaviorService.Adorners.Add(bodyAdorner); + behaviorService.Adorners.Add(selectionAdorner); //adding this will cause the adorner to get setup with a ptr to the beh.svc. + + componentToDesigner = new Hashtable(); + designerHost.TransactionClosed += new DesignerTransactionCloseEventHandler(OnTransactionClosed); + // designeraction UI + if (designerHost.GetService(typeof(DesignerOptionService)) is DesignerOptionService options) + { + PropertyDescriptor p = options.Options.Properties["UseSmartTags"]; + if (p != null && p.PropertyType == typeof(bool) && (bool)p.GetValue(null)) + { + designerActionUI = new DesignerActionUI(serviceProvider, selectionAdorner); + behaviorService.DesignerActionUI = designerActionUI; + } + } + } + + /// + /// Returns the Adorner that contains all the BodyGlyphs for the current selection state. + /// + internal Adorner BodyGlyphAdorner + { + get => bodyAdorner; + } + + /// + /// There are certain cases like Adding Item to ToolStrips through InSitu Editor, where there is ParentTransaction that has to be cancelled depending upon the user action When this parent transaction is cancelled, there may be no reason to REFRESH the selectionManager which actually clears all the glyphs and readds them This REFRESH causes a lot of flicker and can be avoided by setting this property to false. Since this property is checked in the TransactionClosed, the SelectionManager won't REFRESH and hence just eat up the refresh thus avoiding unnecessary flicker. + /// + internal bool NeedRefresh + { + get => needRefresh; + set => needRefresh = value; + } + + /// + /// Returns the Adorner that contains all the BodyGlyphs for the current selection state. + /// + internal Adorner SelectionGlyphAdorner + { + get => selectionAdorner; + } + + /// + /// This method fist calls the recursive AddControlGlyphs() method. When finished, we add the final glyph(s) to the root comp. + /// + private void AddAllControlGlyphs(Control parent, ArrayList selComps, object primarySelection) + { + foreach (Control control in parent.Controls) + { + AddAllControlGlyphs(control, selComps, primarySelection); + } + + GlyphSelectionType selType = GlyphSelectionType.NotSelected; + if (selComps.Contains(parent)) + { + if (parent.Equals(primarySelection)) + { + selType = GlyphSelectionType.SelectedPrimary; + } + else + { + selType = GlyphSelectionType.Selected; + } + } + AddControlGlyphs(parent, selType); + } + + /// + /// Recursive method that goes through and adds all the glyphs of every child to our global Adorner. + /// + private void AddControlGlyphs(Control c, GlyphSelectionType selType) + { + + ControlDesigner cd = (ControlDesigner)componentToDesigner[c]; + if (cd != null) + { + ControlBodyGlyph bodyGlyph = cd.GetControlGlyphInternal(selType); + if (bodyGlyph != null) + { + bodyAdorner.Glyphs.Add(bodyGlyph); + if (selType == GlyphSelectionType.SelectedPrimary || + selType == GlyphSelectionType.Selected) + { + if (curSelectionBounds[curCompIndex] == Rectangle.Empty) + { + curSelectionBounds[curCompIndex] = bodyGlyph.Bounds; + } + else + { + curSelectionBounds[curCompIndex] = Rectangle.Union(curSelectionBounds[curCompIndex], bodyGlyph.Bounds); + } + } + } + GlyphCollection glyphs = cd.GetGlyphs(selType); + if (glyphs != null) + { + selectionAdorner.Glyphs.AddRange(glyphs); + if (selType == GlyphSelectionType.SelectedPrimary || + selType == GlyphSelectionType.Selected) + { + foreach (Glyph glyph in glyphs) + { + curSelectionBounds[curCompIndex] = Rectangle.Union(curSelectionBounds[curCompIndex], glyph.Bounds); + } + } + } + } + + if (selType == GlyphSelectionType.SelectedPrimary || selType == GlyphSelectionType.Selected) + { + curCompIndex++; + } + + } + + /// + /// Unhook all of our event notifications, clear our adorner and remove it from the Beh.Svc. + /// + // We don't need to Dispose rootComponent. + [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public void Dispose() + { + if (designerHost != null) + { + designerHost.TransactionClosed -= new DesignerTransactionCloseEventHandler(OnTransactionClosed); + designerHost = null; + } + + if (serviceProvider != null) + { + if (selSvc != null) + { + selSvc.SelectionChanged -= new EventHandler(OnSelectionChanged); + selSvc = null; + } + serviceProvider = null; + } + + if (behaviorService != null) + { + behaviorService.Adorners.Remove(bodyAdorner); + behaviorService.Adorners.Remove(selectionAdorner); + behaviorService.BeginDrag -= new BehaviorDragDropEventHandler(OnBeginDrag); + behaviorService.Synchronize -= new EventHandler(OnSynchronize); + behaviorService = null; + } + + if (selectionAdorner != null) + { + selectionAdorner.Glyphs.Clear(); + selectionAdorner = null; + } + + if (bodyAdorner != null) + { + bodyAdorner.Glyphs.Clear(); + bodyAdorner = null; + } + + if (designerActionUI != null) + { + designerActionUI.Dispose(); + designerActionUI = null; + } + } + + /// + /// Refreshes all selection Glyphs. + /// + public void Refresh() + { + NeedRefresh = false; + OnSelectionChanged(this, null); + } + + /// + /// When a component is added, we get the designer and add it to our hashtable for quick lookup. + /// + private void OnComponentAdded(object source, ComponentEventArgs ce) + { + IComponent component = ce.Component; + IDesigner designer = designerHost.GetDesigner(component); + if (designer is ControlDesigner) + { + componentToDesigner.Add(component, designer); + } + } + + /// + /// Before a drag, remove all glyphs that are involved in the drag operation and any that don't allow drops. + /// + private void OnBeginDrag(object source, BehaviorDragDropEventArgs e) + { + ArrayList dragComps = new ArrayList(e.DragComponents); + ArrayList glyphsToRemove = new ArrayList(); + foreach (ControlBodyGlyph g in bodyAdorner.Glyphs) + { + if (g.RelatedComponent is Control) + { + if (dragComps.Contains(g.RelatedComponent) || + !((Control)g.RelatedComponent).AllowDrop) + { + glyphsToRemove.Add(g); + } + } + } + foreach (Glyph g in glyphsToRemove) + { + bodyAdorner.Glyphs.Remove(g); + } + } + + // Called by the DropSourceBehavior when dragging into a new host + internal void OnBeginDrag(BehaviorDragDropEventArgs e) + { + OnBeginDrag(null, e); + } + + /// + /// When a component is changed - we need to refresh the selection. + /// + private void OnComponentChanged(object source, ComponentChangedEventArgs ce) + { + if (selSvc.GetComponentSelected(ce.Component)) + { + if (!designerHost.InTransaction) + { + Refresh(); + } + else + { + NeedRefresh = true; + } + } + } + + /// + /// When a component is removed - we remove the key & value from our hashtable. + /// + private void OnComponentRemoved(object source, ComponentEventArgs ce) + { + if (componentToDesigner.Contains(ce.Component)) + { + componentToDesigner.Remove(ce.Component); + } + //remove the associated designeractionpanel + if (designerActionUI != null) + { + designerActionUI.RemoveActionGlyph(ce.Component); + } + } + /// + /// Computes the region representing the difference between the old selection and the new selection. + /// + private Region DetermineRegionToRefresh(object primarySelection) + { + Region toRefresh = new Region(Rectangle.Empty); + Rectangle[] larger; + Rectangle[] smaller; + if (curSelectionBounds.Length >= prevSelectionBounds.Length) + { + larger = curSelectionBounds; + smaller = prevSelectionBounds; + } + else + { + larger = prevSelectionBounds; + smaller = curSelectionBounds; + } + + // we need to make sure all of the rects in the smaller array are accounted for. Any that don't intersect a rect in the larger array need to be included in the region to repaint. + bool[] intersected = new bool[smaller.Length]; + for (int i = 0; i < smaller.Length; i++) + { + intersected[i] = false; + } + + // determine which rects in the larger array need to be included in the region to invalidate by intersecting with rects in the smaller array. + for (int l = 0; l < larger.Length; l++) + { + bool largeIntersected = false; + Rectangle large = larger[l]; + for (int s = 0; s < smaller.Length; s++) + { + if (large.IntersectsWith(smaller[s])) + { + Rectangle small = smaller[s]; + largeIntersected = true; + if (large != small) + { + toRefresh.Union(large); + toRefresh.Union(small); + } + intersected[s] = true; + break; + } + } + if (!largeIntersected) + { + toRefresh.Union(large); + } + } + // now add any rects from the smaller array that weren't accounted for + for (int k = 0; k < intersected.Length; k++) + { + if (!intersected[k]) + { + toRefresh.Union(smaller[k]); + } + } + + using (Graphics g = behaviorService.AdornerWindowGraphics) + { + //If all that changed was the primary selection, then the refresh region was empty, but we do need to update the 2 controls. + if (toRefresh.IsEmpty(g) && primarySelection != null && !primarySelection.Equals(prevPrimarySelection)) + { + for (int i = 0; i < curSelectionBounds.Length; i++) + { + toRefresh.Union(curSelectionBounds[i]); + } + } + } + return toRefresh; + } + + /// + /// Event handler for the behaviorService's Synchronize event + /// + private void OnSynchronize(object sender, EventArgs e) + { + Refresh(); + } + + /// + /// On every selectionchange, we remove all glyphs, get the newly selected components, and re-add all glyphs back to the Adorner. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + // Note: selectionChanging would guard against a re-entrant code... Since we dont want to be in messed up state when adding new Glyphs. + if (!selectionChanging) + { + selectionChanging = true; + selectionAdorner.Glyphs.Clear(); + bodyAdorner.Glyphs.Clear(); + ArrayList selComps = new ArrayList(selSvc.GetSelectedComponents()); + object primarySelection = selSvc.PrimarySelection; + //add all control glyphs to all controls on rootComp + curCompIndex = 0; + curSelectionBounds = new Rectangle[selComps.Count]; + AddAllControlGlyphs(rootComponent, selComps, primarySelection); + if (prevSelectionBounds != null) + { + Region toUpdate = DetermineRegionToRefresh(primarySelection); + using (Graphics g = behaviorService.AdornerWindowGraphics) + { + if (!toUpdate.IsEmpty(g)) + { + selectionAdorner.Invalidate(toUpdate); + } + } + } + else + { + // There was no previous selection, so just invalidate the current selection + if (curSelectionBounds.Length > 0) + { + Rectangle toUpdate = curSelectionBounds[0]; + for (int i = 1; i < curSelectionBounds.Length; i++) + { + toUpdate = Rectangle.Union(toUpdate, curSelectionBounds[i]); + } + if (toUpdate != Rectangle.Empty) + { + selectionAdorner.Invalidate(toUpdate); + } + } + else + { + selectionAdorner.Invalidate(); + } + } + + prevPrimarySelection = primarySelection; + if (curSelectionBounds.Length > 0) + { + prevSelectionBounds = new Rectangle[curSelectionBounds.Length]; + Array.Copy(curSelectionBounds, prevSelectionBounds, curSelectionBounds.Length); + } + else + { + prevSelectionBounds = null; + } + selectionChanging = false; + } + } + + /// + /// When a transaction that involves one of our components closes, refresh to reflect any changes. + /// + private void OnTransactionClosed(object sender, DesignerTransactionCloseEventArgs e) + { + if (e.LastTransaction && NeedRefresh) + { + Refresh(); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SnapLine.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SnapLine.cs index a9f1d2e944a..9a635338181 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SnapLine.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/Behavior/SnapLine.cs @@ -18,6 +18,20 @@ namespace System.Windows.Forms.Design.Behavior /// public sealed class SnapLine { + // These are used in the SnapLine filter to define custom margin/padding SnapLines. + // Margins will have special rules of equality, basically opposites will attract one another + // (ex: margin right == margin left) and paddings will be attracted to like-margins. + internal const string Margin = "Margin"; + internal const string MarginRight = Margin + ".Right"; + internal const string MarginLeft = Margin + ".Left"; + internal const string MarginBottom = Margin + ".Bottom"; + internal const string MarginTop = Margin + ".Top"; + internal const string Padding = "Padding"; + internal const string PaddingRight = Padding + ".Right"; + internal const string PaddingLeft = Padding + ".Left"; + internal const string PaddingBottom = Padding + ".Bottom"; + internal const string PaddingTop = Padding + ".Top"; + /// /// SnapLine constructor that takes the type and offset of SnapLine. /// diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ChangeToolStripParentVerb.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ChangeToolStripParentVerb.cs new file mode 100644 index 00000000000..f1e6b3d0857 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ChangeToolStripParentVerb.cs @@ -0,0 +1,156 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// Internal class to provide 'Embed in ToolStripContainer" verb for ToolStrips & MenuStrips. + /// + internal class ChangeToolStripParentVerb + { + private readonly ToolStripDesigner _designer; + private readonly IDesignerHost _host; + private readonly IComponentChangeService _componentChangeSvc; + private readonly IServiceProvider _provider; + + /// + /// Create one of these things... + /// + internal ChangeToolStripParentVerb(string text, ToolStripDesigner designer) + { + Debug.Assert(designer != null, "Can't have a StandardMenuStripVerb without an associated designer"); + _designer = designer; + _provider = designer.Component.Site; + _host = (IDesignerHost)_provider.GetService(typeof(IDesignerHost)); + _componentChangeSvc = (IComponentChangeService)_provider.GetService(typeof(IComponentChangeService)); + } + + /// + /// When the verb is invoked, change the parent of the ToolStrip. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + // This is actually called... + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public void ChangeParent() + { + Cursor current = Cursor.Current; + // create a transaction so this happens as an atomic unit. + DesignerTransaction changeParent = _host.CreateTransaction("Add ToolStripContainer Transaction"); + try + { + Cursor.Current = Cursors.WaitCursor; + //Add a New ToolStripContainer to the RootComponent ... + Control root = _host.RootComponent as Control; + if (_host.GetDesigner(root) is ParentControlDesigner rootDesigner) + { + // close the DAP first - this is so that the autoshown panel on drag drop here is not conflicting with the currently opened panel + // if the verb was called from the panel + ToolStrip toolStrip = _designer.Component as ToolStrip; + if (toolStrip != null && _designer != null && _designer.Component != null && _provider != null) + { + DesignerActionUIService dapuisvc = _provider.GetService(typeof(DesignerActionUIService)) as DesignerActionUIService; + dapuisvc.HideUI(toolStrip); + } + + // Get OleDragHandler ... + ToolboxItem tbi = new ToolboxItem(typeof(System.Windows.Forms.ToolStripContainer)); + OleDragDropHandler ddh = rootDesigner.GetOleDragHandler(); + if (ddh != null) + { + IComponent[] newComp = ddh.CreateTool(tbi, root, 0, 0, 0, 0, false, false); + if (newComp[0] is ToolStripContainer tsc) + { + if (toolStrip != null) + { + IComponentChangeService changeSvc = _provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService; + Control newParent = GetParent(tsc, toolStrip); + PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(newParent)["Controls"]; + Control oldParent = toolStrip.Parent; + if (oldParent != null) + { + changeSvc.OnComponentChanging(oldParent, controlsProp); + //remove control from the old parent + oldParent.Controls.Remove(toolStrip); + } + + if (newParent != null) + { + changeSvc.OnComponentChanging(newParent, controlsProp); + //finally add & relocate the control with the new parent + newParent.Controls.Add(toolStrip); + } + + //fire our comp changed events + if (changeSvc != null && oldParent != null && newParent != null) + { + changeSvc.OnComponentChanged(oldParent, controlsProp, null, null); + changeSvc.OnComponentChanged(newParent, controlsProp, null, null); + } + + //Set the Selection on the new Parent ... so that the selection is restored to the new item, + if (_provider.GetService(typeof(ISelectionService)) is ISelectionService selSvc) + { + selSvc.SetSelectedComponents(new IComponent[] { tsc }); + } + } + } + } + } + } + catch (Exception e) + { + if (e is System.InvalidOperationException) + { + IUIService uiService = (IUIService)_provider.GetService(typeof(IUIService)); + uiService.ShowError(e.Message); + } + + if (changeParent != null) + { + changeParent.Cancel(); + changeParent = null; + } + + } + finally + { + if (changeParent != null) + { + changeParent.Commit(); + changeParent = null; + } + Cursor.Current = current; + } + } + + private Control GetParent(ToolStripContainer container, Control c) + { + Control newParent = container.ContentPanel; + DockStyle dock = c.Dock; + if (c.Parent is ToolStripPanel) + { + dock = c.Parent.Dock; + } + foreach (Control panel in container.Controls) + { + if (panel is ToolStripPanel) + { + if (panel.Dock == dock) + { + newParent = panel; + break; + } + } + } + return newParent; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CollectionEditVerbManager.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CollectionEditVerbManager.cs new file mode 100644 index 00000000000..30c3e1a4133 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CollectionEditVerbManager.cs @@ -0,0 +1,202 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// Class for sharing code for launching the ToolStripItemsCollectionEditor from a verb. This class implments the IWindowsFormsEditorService and ITypeDescriptorContext to display the dialog. + /// + internal class CollectionEditVerbManager : IWindowsFormsEditorService, ITypeDescriptorContext + { + private readonly ComponentDesigner _designer; + private IComponentChangeService _componentChangeSvc; + private readonly PropertyDescriptor _targetProperty; + private readonly DesignerVerb _editItemsVerb; + + /// + /// Create one of these things... + /// + internal CollectionEditVerbManager(string text, ComponentDesigner designer, PropertyDescriptor prop, bool addToDesignerVerbs) + { + Debug.Assert(designer != null, "Can't have a CollectionEditVerbManager without an associated designer"); + _designer = designer; + _targetProperty = prop; + if (prop == null) + { + prop = TypeDescriptor.GetDefaultProperty(designer.Component); + if (prop != null && typeof(ICollection).IsAssignableFrom(prop.PropertyType)) + { + _targetProperty = prop; + } + } + Debug.Assert(_targetProperty != null, "Need PropertyDescriptor for ICollection property to associate collectoin edtior with."); + if (text == null) + { + text = SR.ToolStripItemCollectionEditorVerb; + } + _editItemsVerb = new DesignerVerb(text, new EventHandler(OnEditItems)); + + if (addToDesignerVerbs) + { + _designer.Verbs.Add(_editItemsVerb); + } + } + + /// + /// Our caching property for the IComponentChangeService + /// + private IComponentChangeService ChangeService + { + get + { + if (_componentChangeSvc == null) + { + _componentChangeSvc = (IComponentChangeService)((IServiceProvider)this).GetService(typeof(IComponentChangeService)); + } + return _componentChangeSvc; + } + } + + /// + /// Self-explanitory interface impl. + /// + IContainer ITypeDescriptorContext.Container + { + get + { + if (_designer.Component.Site != null) + { + return _designer.Component.Site.Container; + } + return null; + } + } + + public DesignerVerb EditItemsVerb + { + get => _editItemsVerb; + } + + /// + /// Self-explanitory interface impl. + /// + void ITypeDescriptorContext.OnComponentChanged() => ChangeService.OnComponentChanged(_designer.Component, _targetProperty, null, null); + + /// + /// Self-explanitory interface impl. + /// + bool ITypeDescriptorContext.OnComponentChanging() + { + try + { + ChangeService.OnComponentChanging(_designer.Component, _targetProperty); + } + catch (CheckoutException checkoutException) + { + if (checkoutException == CheckoutException.Canceled) + { + return false; + } + throw; + } + return true; + } + + /// + /// Self-explanitory interface impl. + /// + object ITypeDescriptorContext.Instance + { + get => _designer.Component; + } + + /// + /// Self-explanitory interface impl. + /// + PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor + { + get => _targetProperty; + } + + /// + /// Self-explanitory interface impl. + /// + object IServiceProvider.GetService(Type serviceType) + { + if (serviceType == typeof(ITypeDescriptorContext) || serviceType == typeof(IWindowsFormsEditorService)) + { + return this; + } + if (_designer.Component.Site != null) + { + return _designer.Component.Site.GetService(serviceType); + } + return null; + } + + /// + /// Self-explanitory interface impl. + /// + void IWindowsFormsEditorService.CloseDropDown() + { + // we'll never be called to do this. + Debug.Fail("NOTIMPL"); + return; + } + + /// + /// Self-explanitory interface impl. + /// + void IWindowsFormsEditorService.DropDownControl(Control control) + { + Debug.Fail("NOTIMPL"); + return; + } + + /// + /// Self-explanitory interface impl. + /// + DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog) + { + IUIService uiSvc = (IUIService)((IServiceProvider)this).GetService(typeof(IUIService)); + if (uiSvc != null) + { + return uiSvc.ShowDialog(dialog); + } + else + { + return dialog.ShowDialog(_designer.Component as IWin32Window); + } + } + + /// + /// When the verb is invoked, use all the stuff above to show the dialog, etc. + /// + private void OnEditItems(object sender, EventArgs e) + { + DesignerActionUIService actionUIService = (DesignerActionUIService)((IServiceProvider)this).GetService(typeof(DesignerActionUIService)); + if (actionUIService != null) + { + actionUIService.HideUI(_designer.Component); + } + object propertyValue = _targetProperty.GetValue(_designer.Component); + if (propertyValue == null) + { + return; + } + CollectionEditor itemsEditor = TypeDescriptor.GetEditor(propertyValue, typeof(UITypeEditor)) as CollectionEditor; + Debug.Assert(itemsEditor != null, "Didn't get a collection editor for type '" + _targetProperty.PropertyType.FullName + "'"); + if (itemsEditor != null) + { + itemsEditor.EditValue(this, this, propertyValue); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CommandSet.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CommandSet.cs new file mode 100644 index 00000000000..d943df5ab9c --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CommandSet.cs @@ -0,0 +1,3540 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Design; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// This class implements the standard set of menu commands for the form designer. This set of command is shared between the form designer (and other UI-based form packages), and composition designer, which doesn't manipulate controls. Therefore, this set of command should only contain commands that are common to both functions. + /// + internal class CommandSet : IDisposable + { + protected ISite site; + private readonly CommandSetItem[] _commandSet; + private IMenuCommandService _menuService; + private IEventHandlerService _eventService; + // Selection service fields. We keep some state about the currently selected components so we can determine proper command enabling quickly. + private ISelectionService _selectionService; + protected int selCount; // the current selection count + protected IComponent primarySelection; // the primary selection, or null + private bool _selectionInherited; // the selection contains inherited components + protected bool controlsOnlySelection; // is the selection containing only controls or are there components in it? + private int _selectionVersion = 1; // the counter of selection changes. + // Selection sort constants + private const int SORT_HORIZONTAL = 0; + private const int SORT_VERTICAL = 1; + private const int SORT_ZORDER = 2; + private const string CF_DESIGNER = "CF_DESIGNERCOMPONENTS_V2"; + //these are used for snapping control via keyboard movement + protected DragAssistanceManager dragManager = null;//point to the snapline engine (only valid between keydown and timer expiration) + private Timer _snapLineTimer;//used to track the time from when a snapline is rendered until it should expire + private BehaviorService _behaviorService;//demand created pointer to the behaviorservice + private StatusCommandUI _statusCommandUI; //Used to update the statusBar Information. + + /// + /// Creates a new CommandSet object. This object implements the set of commands that the UI.Win32 form designer offers. + /// + public CommandSet(ISite site) + { + this.site = site; + _eventService = (IEventHandlerService)site.GetService(typeof(IEventHandlerService)); + Debug.Assert(_eventService != null, "Command set must have the event service. Is command set being initialized too early?"); + _eventService.EventHandlerChanged += new EventHandler(OnEventHandlerChanged); + IDesignerHost host = (IDesignerHost)site.GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (host != null) + { + host.Activated += new EventHandler(UpdateClipboardItems); + } + _statusCommandUI = new StatusCommandUI(site); + IUIService uiService = site.GetService(typeof(IUIService)) as IUIService; + // Establish our set of commands + _commandSet = new CommandSetItem[] + { + // Editing commands + new CommandSetItem( this, new EventHandler(OnStatusDelete), new EventHandler(OnMenuDelete), MenuCommands.Delete, uiService), + new CommandSetItem( this, new EventHandler(OnStatusCopy), new EventHandler(OnMenuCopy), MenuCommands.Copy, uiService), + new CommandSetItem( this, new EventHandler(OnStatusCut), new EventHandler(OnMenuCut), MenuCommands.Cut, uiService), + new ImmediateCommandSetItem( this, new EventHandler(OnStatusPaste), new EventHandler(OnMenuPaste), MenuCommands.Paste, uiService), + // Miscellaneous commands + new CommandSetItem( this, new EventHandler(OnStatusSelectAll), new EventHandler(OnMenuSelectAll), MenuCommands.SelectAll, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAlways), new EventHandler(OnMenuDesignerProperties), MenuCommands.DesignerProperties, uiService), + // Keyboard commands + new CommandSetItem( this, new EventHandler(OnStatusAlways), new EventHandler(OnKeyCancel), MenuCommands.KeyCancel, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAlways), new EventHandler(OnKeyCancel), MenuCommands.KeyReverseCancel, uiService), + new CommandSetItem( this, new EventHandler(OnStatusPrimarySelection), new EventHandler(OnKeyDefault), MenuCommands.KeyDefaultAction, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyMoveUp, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyMoveDown, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyMoveLeft, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyMoveRight, true), + new CommandSetItem(this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyNudgeUp, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyNudgeDown, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyNudgeLeft, true, uiService), + new CommandSetItem( this, new EventHandler(OnStatusAnySelection), new EventHandler(OnKeyMove), MenuCommands.KeyNudgeRight, true, uiService), + }; + + _selectionService = (ISelectionService)site.GetService(typeof(ISelectionService)); + Debug.Assert(_selectionService != null, "CommandSet relies on the selection service, which is unavailable."); + if (_selectionService != null) + { + _selectionService.SelectionChanged += new EventHandler(OnSelectionChanged); + } + + _menuService = (IMenuCommandService)site.GetService(typeof(IMenuCommandService)); + if (_menuService != null) + { + for (int i = 0; i < _commandSet.Length; i++) + { + _menuService.AddCommand(_commandSet[i]); + } + } + + // Now setup the default command GUID for this designer. This GUID is also used in our toolbar definition file to identify toolbars we own. We store the GUID in a command ID here in the dictionary of the root component. Our host may pull this GUID out and use it. + IDictionaryService ds = site.GetService(typeof(IDictionaryService)) as IDictionaryService; + Debug.Assert(ds != null, "No dictionary service"); + if (ds != null) + { + ds.SetValue(typeof(CommandID), new CommandID(new Guid("BA09E2AF-9DF2-4068-B2F0-4C7E5CC19E2F"), 0)); + } + } + + /// + /// Demand creates a pointer to the BehaviorService + /// + protected BehaviorService BehaviorService + { + get + { + if (_behaviorService == null) + { + _behaviorService = GetService(typeof(BehaviorService)) as BehaviorService; + } + return _behaviorService; + } + } + + /// + /// Retrieves the menu command service, which the command set typically uses quite a bit. + /// + protected IMenuCommandService MenuService + { + get + { + if (_menuService == null) + { + _menuService = (IMenuCommandService)GetService(typeof(IMenuCommandService)); + } + return _menuService; + } + } + + /// + /// Retrieves the selection service, which the command set typically uses quite a bit. + /// + protected ISelectionService SelectionService + { + get => _selectionService; + } + + protected int SelectionVersion + { + get => _selectionVersion; + } + + /// + /// This property demand creates our snaplinetimer used to track how long we'll leave snaplines on the screen before erasing them + /// + protected Timer SnapLineTimer + { + get + { + if (_snapLineTimer == null) + { + //instantiate our snapline timer + _snapLineTimer = new Timer + { + Interval = DesignerUtils.SNAPELINEDELAY + }; + _snapLineTimer.Tick += new EventHandler(OnSnapLineTimerExpire); + } + return _snapLineTimer; + } + } + + /// + /// Checks if an object supports ComponentEditors, and optionally launches the editor. + /// + private bool CheckComponentEditor(object obj, bool launchEditor) + { + if (obj is IComponent) + { + try + { + if (!launchEditor) + { + return true; + } + ComponentEditor editor = (ComponentEditor)TypeDescriptor.GetEditor(obj, typeof(ComponentEditor)); + if (editor == null) + { + return false; + } + + bool success = false; + IComponentChangeService changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (changeService != null) + { + try + { + changeService.OnComponentChanging(obj, null); + } + catch (CheckoutException coEx) + { + if (coEx == CheckoutException.Canceled) + { + return false; + } + throw coEx; + } + catch + { + Debug.Fail("non-CLS compliant exception"); + throw; + } + } + + if (editor is WindowsFormsComponentEditor winEditor) + { + IWin32Window parent = null; + if (obj is IWin32Window) + { +#pragma warning disable 1717 // assignment to self + parent = (IWin32Window)parent; +#pragma warning restore 1717 + } + success = winEditor.EditComponent(obj, parent); + } + else + { + success = editor.EditComponent(obj); + } + + if (success && changeService != null) + { + // Now notify the change service that the change was successful. + changeService.OnComponentChanged(obj, null, null, null); + } + return true; + } + catch (Exception ex) + { + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + } + return false; + } + + /// + /// Disposes of this object, removing all commands from the menu service. + /// + // We don't need to Dispose snapLineTimer + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public virtual void Dispose() + { + if (_menuService != null) + { + for (int i = 0; i < _commandSet.Length; i++) + { + _menuService.RemoveCommand(_commandSet[i]); + _commandSet[i].Dispose(); + } + _menuService = null; + } + + if (_selectionService != null) + { + _selectionService.SelectionChanged -= new EventHandler(OnSelectionChanged); + _selectionService = null; + } + + if (_eventService != null) + { + _eventService.EventHandlerChanged -= new EventHandler(OnEventHandlerChanged); + _eventService = null; + } + + IDesignerHost host = (IDesignerHost)site.GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (host != null) + { + host.Activated -= new EventHandler(UpdateClipboardItems); + } + + if (_snapLineTimer != null) + { + _snapLineTimer.Stop(); + _snapLineTimer.Tick -= new EventHandler(OnSnapLineTimerExpire); + _snapLineTimer = null; + } + + EndDragManager(); + _statusCommandUI = null; + site = null; + } + + /// + /// Properly cleans up our drag engine. + /// + protected void EndDragManager() + { + if (dragManager != null) + { + if (_snapLineTimer != null) + { + _snapLineTimer.Stop(); + } + dragManager.EraseSnapLines(); + dragManager.OnMouseUp(); + dragManager = null; + } + } + + /// + /// Filters the set of selected components. The selection service will retrieve all components that are currently selected. This method allows you to filter this set down to components that match your criteria. The selectionRules parameter must contain one or more flags from the SelectionRules class. These flags allow you to constrain the set of selected objects to visible, movable, sizeable or all objects. + /// + private object[] FilterSelection(object[] components, SelectionRules selectionRules) + { + object[] selection = null; + if (components == null) + return new object[0]; + // Mask off any selection object that doesn't adhere to the given ruleset. We can ignore this if the ruleset is zero, as all components would be accepted. + if (selectionRules != SelectionRules.None) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + ArrayList list = new ArrayList(); + foreach (IComponent comp in components) + { + if (host.GetDesigner(comp) is ControlDesigner des && (des.SelectionRules & selectionRules) == selectionRules) + { + list.Add(comp); + } + } + selection = list.ToArray(); + } + } + return selection ?? (new object[0]); + } + + /// + /// Used to retrieve the selection for a copy. The default implementation retrieves the current selection. + /// + protected virtual ICollection GetCopySelection() + { + ICollection selectedComponents = SelectionService.GetSelectedComponents(); + bool sort = false; + object[] comps = new object[selectedComponents.Count]; + selectedComponents.CopyTo(comps, 0); + foreach (object comp in comps) + { + if (comp is Control) + { + sort = true; + break; + } + } + if (sort) + { + SortSelection(comps, SORT_ZORDER); + } + selectedComponents = comps; + IDesignerHost host = (IDesignerHost)site.GetService(typeof(IDesignerHost)); + if (host != null) + { + ArrayList copySelection = new ArrayList(); + foreach (IComponent comp in selectedComponents) + { + copySelection.Add(comp); + GetAssociatedComponents(comp, host, copySelection); + } + selectedComponents = copySelection; + } + return selectedComponents; + } + + private void GetAssociatedComponents(IComponent component, IDesignerHost host, ArrayList list) + { + if (!(host.GetDesigner(component) is ComponentDesigner designer)) + { + return; + } + foreach (IComponent childComp in designer.AssociatedComponents) + { + if (childComp.Site != null) + { + list.Add(childComp); + GetAssociatedComponents(childComp, host, list); + } + } + } + + /// + /// Used to retrieve the current location of the given component. + /// + private Point GetLocation(IComponent comp) + { + PropertyDescriptor prop = GetProperty(comp, "Location"); + if (prop != null) + { + try + { + return (Point)prop.GetValue(comp); + } + catch (Exception e) + { + Debug.Fail("Commands may be disabled, the location property was not accessible", e.ToString()); + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + } + return Point.Empty; + } + + /// + /// Retrieves the given property on the given component. + /// + protected PropertyDescriptor GetProperty(object comp, string propName) + { + return TypeDescriptor.GetProperties(comp)[propName]; + } + + /// + /// Retrieves the requested service. + /// + protected virtual object GetService(Type serviceType) + { + if (site != null) + { + return site.GetService(serviceType); + } + return null; + } + + /// + /// Used to retrieve the current size of the given component. + /// + private Size GetSize(IComponent comp) + { + PropertyDescriptor prop = GetProperty(comp, "Size"); + if (prop != null) + { + return (Size)prop.GetValue(comp); + } + return Size.Empty; + } + + /// + /// Retrieves the snap information for the given component. + /// + protected virtual void GetSnapInformation(IDesignerHost host, IComponent component, out Size snapSize, out IComponent snapComponent, out PropertyDescriptor snapProperty) + { + // This implementation is shared by all. It just looks for snap properties on the base component. + IComponent currentSnapComponent; + PropertyDescriptor gridSizeProp; + PropertyDescriptor currentSnapProp; + PropertyDescriptorCollection props; + + currentSnapComponent = host.RootComponent; + props = TypeDescriptor.GetProperties(currentSnapComponent); + currentSnapProp = props["SnapToGrid"]; + if (currentSnapProp != null && currentSnapProp.PropertyType != typeof(bool)) + { + currentSnapProp = null; + } + gridSizeProp = props["GridSize"]; + if (gridSizeProp != null && gridSizeProp.PropertyType != typeof(Size)) + { + gridSizeProp = null; + } + // Finally, now that we've got the various properties and components, dole out the values. + snapComponent = currentSnapComponent; + snapProperty = currentSnapProp; + if (gridSizeProp != null) + { + snapSize = (Size)gridSizeProp.GetValue(snapComponent); + } + else + { + snapSize = Size.Empty; + } + } + + /// + /// Called before doing any change to multiple controls to check if we have the right to make any change otherwise we would get a checkout message for each control we call setvalue on + /// + protected bool CanCheckout(IComponent comp) + { + // look if it's ok to change + IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + // is it ok to change? + if (changeSvc != null) + { + try + { + changeSvc.OnComponentChanging(comp, null); + } + catch (CheckoutException chkex) + { + if (chkex == CheckoutException.Canceled) + return false; + throw chkex; + } + } + return true; + } + + /// + /// Called by the event handler service when the current event handler has changed. Here we invalidate all of our menu items so that they can pick up the new event handler. + /// + private void OnEventHandlerChanged(object sender, EventArgs e) + { + OnUpdateCommandStatus(); + } + + /// + /// Called for the two cancel commands we support. + /// + private void OnKeyCancel(object sender, EventArgs e) + { + OnKeyCancel(sender); + } + + /// + /// Called for the two cancel commands we support. Returns true If we did anything with the cancel, or false if not. + /// + protected virtual bool OnKeyCancel(object sender) + { + bool handled = false; + // The base implementation here just checks to see if we are dragging. If we are, then we abort the drag. + if (BehaviorService != null && BehaviorService.HasCapture) + { + BehaviorService.OnLoseCapture(); + handled = true; + } + else + { + IToolboxService tbx = (IToolboxService)GetService(typeof(IToolboxService)); + if (tbx != null && tbx.GetSelectedToolboxItem((IDesignerHost)GetService(typeof(IDesignerHost))) != null) + { + tbx.SelectedToolboxItemUsed(); + NativeMethods.POINT p = new NativeMethods.POINT(); + NativeMethods.GetCursorPos(p); + IntPtr hwnd = NativeMethods.WindowFromPoint(p.x, p.y); + if (hwnd != IntPtr.Zero) + { + NativeMethods.SendMessage(hwnd, Interop.WindowMessages.WM_SETCURSOR, hwnd, (IntPtr)NativeMethods.HTCLIENT); + } + else + { + Cursor.Current = Cursors.Default; + } + handled = true; + } + } + return handled; + } + + /// + /// Called for the "default" command, typically the Enter key. + /// + protected void OnKeyDefault(object sender, EventArgs e) + { + // Return key. Handle it like a double-click on the primary selection + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (selSvc.PrimarySelection is IComponent pri) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + IDesigner designer = host.GetDesigner(pri); + + if (designer != null) + { + designer.DoDefaultAction(); + } + } + } + } + } + + /// + /// Called for all cursor movement commands. + /// + protected virtual void OnKeyMove(object sender, EventArgs e) + { + // Arrow keys. Begin a drag if the selection isn't locked. + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (selSvc.PrimarySelection is IComponent comp) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + PropertyDescriptor lockedProp = TypeDescriptor.GetProperties(comp)["Locked"]; + if (lockedProp == null || (lockedProp.PropertyType == typeof(bool) && ((bool)lockedProp.GetValue(comp))) == false) + { + CommandID cmd = ((MenuCommand)sender).CommandID; + bool invertSnap = false; + int moveOffsetX = 0; + int moveOffsetY = 0; + + if (cmd.Equals(MenuCommands.KeyMoveUp)) + { + moveOffsetY = -1; + } + else if (cmd.Equals(MenuCommands.KeyMoveDown)) + { + moveOffsetY = 1; + } + else if (cmd.Equals(MenuCommands.KeyMoveLeft)) + { + moveOffsetX = -1; + } + else if (cmd.Equals(MenuCommands.KeyMoveRight)) + { + moveOffsetX = 1; + } + else if (cmd.Equals(MenuCommands.KeyNudgeUp)) + { + moveOffsetY = -1; + invertSnap = true; + } + else if (cmd.Equals(MenuCommands.KeyNudgeDown)) + { + moveOffsetY = 1; + invertSnap = true; + } + else if (cmd.Equals(MenuCommands.KeyNudgeLeft)) + { + moveOffsetX = -1; + invertSnap = true; + } + else if (cmd.Equals(MenuCommands.KeyNudgeRight)) + { + moveOffsetX = 1; + invertSnap = true; + } + else + { + Debug.Fail("Unknown command mapped to OnKeyMove: " + cmd.ToString()); + } + + DesignerTransaction trans; + if (selSvc.SelectionCount > 1) + { + trans = host.CreateTransaction(string.Format(SR.DragDropMoveComponents, selSvc.SelectionCount)); + } + else + { + trans = host.CreateTransaction(string.Format(SR.DragDropMoveComponent, comp.Site.Name)); + } + try + { + //if we can find the behaviorservice, then we can use it and the SnapLineEngine to help us move these controls... + if (BehaviorService != null) + { + Control primaryControl = comp as Control; //this can be null (when we are moving a component in the ComponenTray) + bool useSnapLines = BehaviorService.UseSnapLines; + // If we have previous snaplines, we always want to erase them, no matter what. VS Whidbey #397709 + if (dragManager != null) + { + EndDragManager(); + } + + //If we CTRL+Arrow and we're using SnapLines - snap to the next location. Don't snap if we are moving a component in the ComponentTray + if (invertSnap && useSnapLines && primaryControl != null) + { + ArrayList selComps = new ArrayList(selSvc.GetSelectedComponents()); + //create our snapline engine + dragManager = new DragAssistanceManager(comp.Site, selComps); + //ask our snapline engine to find the nearest snap position with the given direction + Point snappedOffset = dragManager.OffsetToNearestSnapLocation(primaryControl, new Point(moveOffsetX, moveOffsetY)); + //update the offset according to the snapline engine + // This is the offset assuming origin is in the upper-left. + moveOffsetX = snappedOffset.X; + moveOffsetY = snappedOffset.Y; + // If the parent is mirrored then we need to negate moveOffsetX. This is because moveOffsetX assumes that the origin is upper left. That is, when moveOffsetX is positive, we are moving right, negative when moving left. The parent container's origin depends on its mirroring property. Thus when we call propLoc.setValue below, we need to make sure that our moveOffset.X correctly reflects the placement of the parent container's origin. We need to do this AFTER we calculate the snappedOffset. This is because the dragManager calculations are all based on an origin in the upper-left. + if (primaryControl.Parent.IsMirrored) + { + moveOffsetX *= -1; + } + } + //if we used a regular arrow key and we're in SnapToGrid mode... + else if (!invertSnap && !useSnapLines) + { + bool snapOn = false; + Size snapSize = Size.Empty; + GetSnapInformation(host, comp, out snapSize, out IComponent snapComponent, out PropertyDescriptor snapProperty); + if (snapProperty != null) + { + snapOn = (bool)snapProperty.GetValue(snapComponent); + } + if (snapOn && !snapSize.IsEmpty) + { + moveOffsetX *= snapSize.Width; + moveOffsetY *= snapSize.Height; + if (primaryControl != null) + { + //ask the parent to adjust our wanna-be snapped position + if (host.GetDesigner(primaryControl.Parent) is ParentControlDesigner parentDesigner) + { + Point loc = primaryControl.Location; + // If the parent is mirrored then we need to negate moveOffsetX. This is because moveOffsetX assumes that the origin is upper left. That is, when moveOffsetX is positive, we are moving right, negative when moving left. The parent container's origin depends on its mirroring property. Thus when we call propLoc.setValue below, we need to make sure that our moveOffset.X correctly reflects the placement of the parent container's origin. Should do this BEFORE we get the snapped point. + if (primaryControl.Parent.IsMirrored) + { + moveOffsetX *= -1; + } + loc.Offset(moveOffsetX, moveOffsetY); + loc = parentDesigner.GetSnappedPoint(loc); + //reset our offsets now that we've snapped correctly + if (moveOffsetX != 0) + { + moveOffsetX = loc.X - primaryControl.Location.X; + } + if (moveOffsetY != 0) + { + moveOffsetY = loc.Y - primaryControl.Location.Y; + } + } + } + } + else + { + // In this case we are just going to move 1 pixel, so let's adjust for Mirroring + if (primaryControl != null && primaryControl.Parent.IsMirrored) + { + moveOffsetX *= -1; + } + } + } + else + { + if (primaryControl != null && primaryControl.Parent.IsMirrored) + { + moveOffsetX *= -1; + } + } + + SelectionRules rules = SelectionRules.Moveable | SelectionRules.Visible; + foreach (IComponent component in selSvc.GetSelectedComponents()) + { + if (host.GetDesigner(component) is ControlDesigner des && ((des.SelectionRules & rules) != rules)) + { + //the control must match the rules, if not, then we don't move it + continue; + } + // Components are always moveable and visible + PropertyDescriptor propLoc = TypeDescriptor.GetProperties(component)["Location"]; + if (propLoc != null) + { + Point loc = (Point)propLoc.GetValue(component); + loc.Offset(moveOffsetX, moveOffsetY); + propLoc.SetValue(component, loc); + } + //change the Status information .... + if (component == selSvc.PrimarySelection && _statusCommandUI != null) + { + _statusCommandUI.SetStatusInformation(component as Component); + } + } + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + + if (dragManager != null) + { + //start our timer for the snaplines + SnapLineTimer.Start(); + + //render any lines + dragManager.RenderSnapLinesInternal(); + } + } + } + } + } + } + } + + /// + /// Called for all alignment operations that key off of a primary selection. + /// + protected void OnMenuAlignByPrimary(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + CommandID id = cmd.CommandID; + + //Need to get the location for the primary control, we do this here (instead of onselectionchange) because the control could be dragged around once it is selected and might have a new location + Point primaryLocation = GetLocation(primarySelection); + Size primarySize = GetSize(primarySelection); + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + // Now loop through each of the components. + ICollection comps = SelectionService.GetSelectedComponents(); + // Inform the designer that we are about to monkey with a ton of properties. + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + DesignerTransaction trans = null; + try + { + if (host != null) + { + trans = host.CreateTransaction(string.Format(SR.CommandSetAlignByPrimary, comps.Count)); + } + + bool firstTry = true; + Point loc = Point.Empty; + foreach (object obj in comps) + { + if (obj == primarySelection) + { + continue; + } + IComponent comp = obj as IComponent; + if (comp != null && host != null) + { + if (!(host.GetDesigner(comp) is ControlDesigner des)) + { + continue; + } + } + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(comp); + PropertyDescriptor locProp = props["Location"]; + PropertyDescriptor sizeProp = props["Size"]; + PropertyDescriptor lockProp = props["Locked"]; + // Skip all components that are locked + // + if (lockProp != null) + { + if ((bool)lockProp.GetValue(comp)) + continue; + } + + // Skip all components that don't have a location property + // + if (locProp == null || locProp.IsReadOnly) + { + continue; + } + + // Skip all components that don't have size if we're doing a size operation. + if (id.Equals(MenuCommands.AlignBottom) || + id.Equals(MenuCommands.AlignHorizontalCenters) || + id.Equals(MenuCommands.AlignVerticalCenters) || + id.Equals(MenuCommands.AlignRight)) + { + if (sizeProp == null || sizeProp.IsReadOnly) + { + continue; + } + } + + // Align bottom + if (id.Equals(MenuCommands.AlignBottom)) + { + loc = (Point)locProp.GetValue(comp); + Size size = (Size)sizeProp.GetValue(comp); + loc.Y = primaryLocation.Y + primarySize.Height - size.Height; + } + // Align horizontal centers + else if (id.Equals(MenuCommands.AlignHorizontalCenters)) + { + loc = (Point)locProp.GetValue(comp); + Size size = (Size)sizeProp.GetValue(comp); + loc.Y = primarySize.Height / 2 + primaryLocation.Y - size.Height / 2; + } + // Align left + else if (id.Equals(MenuCommands.AlignLeft)) + { + loc = (Point)locProp.GetValue(comp); + loc.X = primaryLocation.X; + } + // Align right + else if (id.Equals(MenuCommands.AlignRight)) + { + loc = (Point)locProp.GetValue(comp); + Size size = (Size)sizeProp.GetValue(comp); + loc.X = primaryLocation.X + primarySize.Width - size.Width; + } + // Align top + else if (id.Equals(MenuCommands.AlignTop)) + { + loc = (Point)locProp.GetValue(comp); + loc.Y = primaryLocation.Y; + } + // Align vertical centers + else if (id.Equals(MenuCommands.AlignVerticalCenters)) + { + loc = (Point)locProp.GetValue(comp); + Size size = (Size)sizeProp.GetValue(comp); + loc.X = primarySize.Width / 2 + primaryLocation.X - size.Width / 2; + } + else + { + Debug.Fail("Unrecognized command: " + id.ToString()); + } + + if (firstTry && !CanCheckout(comp)) + { + return; + } + firstTry = false; + locProp.SetValue(comp, loc); + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the align->to grid menu item is selected. + /// + protected void OnMenuAlignToGrid(object sender, EventArgs e) + { + Size gridSize = Size.Empty; + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + ICollection selectedComponents = SelectionService.GetSelectedComponents(); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + DesignerTransaction trans = null; + try + { + if (host != null) + { + trans = host.CreateTransaction(string.Format(SR.CommandSetAlignToGrid, selectedComponents.Count)); + if (host.RootComponent is Control baseComponent) + { + PropertyDescriptor prop = GetProperty(baseComponent, "GridSize"); + if (prop != null) + { + gridSize = (Size)prop.GetValue(baseComponent); + } + if (prop == null || gridSize.IsEmpty) + { + //bail silently here + return; + } + } + + } + bool firstTry = true; + // for each component, we round to the nearest snap offset for x and y + foreach (object comp in selectedComponents) + { + // first check to see if the component is locked, if so - don't move it... + PropertyDescriptor lockedProp = GetProperty(comp, "Locked"); + if (lockedProp != null && ((bool)lockedProp.GetValue(comp)) == true) + { + continue; + } + // if the designer for this component isn't a ControlDesigner (maybe it's something in the component tray) then don't try to align it to grid. + IComponent component = comp as IComponent; + if (component != null && host != null) + { + if (!(host.GetDesigner(component) is ControlDesigner des)) + { + continue; + } + } + + // get the location property + PropertyDescriptor locProp = GetProperty(comp, "Location"); + + // get the current value + if (locProp == null || locProp.IsReadOnly) + { + continue; + } + Point loc = (Point)locProp.GetValue(comp); + + // round the x to the snap size + int delta = loc.X % gridSize.Width; + if (delta < (gridSize.Width / 2)) + { + loc.X -= delta; + } + else + { + loc.X += (gridSize.Width - delta); + } + + // round the y to the gridsize + delta = loc.Y % gridSize.Height; + if (delta < (gridSize.Height / 2)) + { + loc.Y -= delta; + } + else + { + loc.Y += (gridSize.Height - delta); + } + + // look if it's ok to change + if (firstTry && !CanCheckout(component)) + { + return; + } + firstTry = false; + + // set the value + locProp.SetValue(comp, loc); + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the center horizontally or center vertically menu item is selected. + /// + protected void OnMenuCenterSelection(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + CommandID cmdID = cmd.CommandID; + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + // NOTE: this only works on Control types + ICollection selectedComponents = SelectionService.GetSelectedComponents(); + Control viewParent = null; + Size size = Size.Empty; + Point loc = Point.Empty; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + DesignerTransaction trans = null; + try + { + if (host != null) + { + string batchString; + + if (cmdID == MenuCommands.CenterHorizontally) + { + batchString = string.Format(SR.WindowsFormsCommandCenterX, selectedComponents.Count); + } + else + { + batchString = string.Format(SR.WindowsFormsCommandCenterY, selectedComponents.Count); + } + trans = host.CreateTransaction(batchString); + } + //subhag calculate the union REctangle + int top = int.MaxValue; + int left = int.MaxValue; + int right = int.MinValue; + int bottom = int.MinValue; + + foreach (object obj in selectedComponents) + { + if (obj is Control) + { + IComponent comp = (IComponent)obj; + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(comp); + PropertyDescriptor locProp = props["Location"]; + PropertyDescriptor sizeProp = props["Size"]; + // Skip all components that don't have location and size properties + if (locProp == null || sizeProp == null || locProp.IsReadOnly || sizeProp.IsReadOnly) + { + continue; + } + + // Also, skip all locked componenents... + PropertyDescriptor lockProp = props["Locked"]; + if (lockProp != null && (bool)lockProp.GetValue(comp) == true) + { + continue; + } + + size = (Size)sizeProp.GetValue(comp); + loc = (Point)locProp.GetValue(comp); + + //cache the first parent we see - if there's a mix of different parents - we'll just center based on the first one + if (viewParent == null) + { + viewParent = ((Control)comp).Parent; + } + + if (loc.X < left) + left = loc.X; + if (loc.Y < top) + top = loc.Y; + if (loc.X + size.Width > right) + right = loc.X + size.Width; + if (loc.Y + size.Height > bottom) + bottom = loc.Y + size.Height; + } + } + + //if we never found a viewParent (some read-only inherited scenarios then simply bail + if (viewParent == null) + { + return; + } + + int centerOfUnionRectX = (left + right) / 2; + int centerOfUnionRectY = (top + bottom) / 2; + int centerOfParentX = (viewParent.ClientSize.Width) / 2; + int centerOfParentY = (viewParent.ClientSize.Height) / 2; + int deltaX = 0; + int deltaY = 0; + bool shiftRight = false; + bool shiftBottom = false; + if (centerOfParentX >= centerOfUnionRectX) + { + deltaX = centerOfParentX - centerOfUnionRectX; + shiftRight = true; + } + else + deltaX = centerOfUnionRectX - centerOfParentX; + + if (centerOfParentY >= centerOfUnionRectY) + { + deltaY = centerOfParentY - centerOfUnionRectY; + shiftBottom = true; + } + else + deltaY = centerOfUnionRectY - centerOfParentY; + + bool firstTry = true; + foreach (object obj in selectedComponents) + { + if (obj is Control) + { + IComponent comp = (IComponent)obj; + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(comp); + PropertyDescriptor locProp = props["Location"]; + if (locProp.IsReadOnly) + { + continue; + } + + loc = (Point)locProp.GetValue(comp); + + if (cmdID == MenuCommands.CenterHorizontally) + { + if (shiftRight) + loc.X += deltaX; + else + loc.X -= deltaX; + } + else if (cmdID == MenuCommands.CenterVertically) + { + if (shiftBottom) + loc.Y += deltaY; + else + loc.Y -= deltaY; + } + // look if it's ok to change the first time + if (firstTry && !CanCheckout(comp)) + { + return; + } + firstTry = false; + // do the change + locProp.SetValue(comp, loc); + } + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the copy menu item is selected. + /// + protected void OnMenuCopy(object sender, EventArgs e) + { + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + ICollection selectedComponents = GetCopySelection(); + selectedComponents = PrependComponentNames(selectedComponents); + IDesignerSerializationService ds = (IDesignerSerializationService)GetService(typeof(IDesignerSerializationService)); + Debug.Assert(ds != null, "No designer serialization service -- we cannot copy to clipboard"); + if (ds != null) + { + object serializationData = ds.Serialize(selectedComponents); + MemoryStream stream = new MemoryStream(); + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(stream, serializationData); + stream.Seek(0, SeekOrigin.Begin); + byte[] bytes = stream.GetBuffer(); + IDataObject dataObj = new DataObject(CF_DESIGNER, bytes); + Clipboard.SetDataObject(dataObj); + } + UpdateClipboardItems(null, null); + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the cut menu item is selected. + /// + protected void OnMenuCut(object sender, EventArgs e) + { + if (SelectionService == null) + { + return; + } + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + ICollection selectedComponents = GetCopySelection(); + int cutCount = selectedComponents.Count; + selectedComponents = PrependComponentNames(selectedComponents); + IDesignerSerializationService ds = (IDesignerSerializationService)GetService(typeof(IDesignerSerializationService)); + Debug.Assert(ds != null, "No designer serialization service -- we cannot copy to clipboard"); + if (ds != null) + { + object serializationData = ds.Serialize(selectedComponents); + MemoryStream stream = new MemoryStream(); + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(stream, serializationData); + stream.Seek(0, SeekOrigin.Begin); + byte[] bytes = stream.GetBuffer(); + IDataObject dataObj = new DataObject(CF_DESIGNER, bytes); + Clipboard.SetDataObject(dataObj); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Control commonParent = null; + if (host != null) + { + IComponentChangeService changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + DesignerTransaction trans = null; + + ArrayList designerList = new ArrayList(); + try + { + trans = host.CreateTransaction(string.Format(SR.CommandSetCutMultiple, cutCount)); + // clear the selected components so we aren't browsing them + SelectionService.SetSelectedComponents(new object[0], SelectionTypes.Replace); + object[] selComps = new object[selectedComponents.Count]; + selectedComponents.CopyTo(selComps, 0); + for (int i = 0; i < selComps.Length; i++) + { + object obj = selComps[i]; + // We should never delete the base component. + // + if (obj == host.RootComponent || !(obj is IComponent component)) + { + continue; + } + //Perf: We suspend Component Changing Events on parent for bulk changes to avoid unnecessary serialization\deserialization for undo + if (obj is Control c) + { + Control parent = c.Parent; + if (parent != null) + { + if (host.GetDesigner(parent) is ParentControlDesigner designer && !designerList.Contains(designer)) + { + designer.SuspendChangingEvents(); + designerList.Add(designer); + designer.ForceComponentChanging(); + } + } + } + } + // go backward so we destroy parents before children + + for (int i = 0; i < selComps.Length; i++) + { + object obj = selComps[i]; + // We should never delete the base component. + // + if (obj == host.RootComponent || !(obj is IComponent component)) + { + continue; + } + + Control c = obj as Control; + //Cannot use idx = 1 to check (see diff) due to the call to PrependComponentNames, which adds non IComponent objects to the beginning of selectedComponents. Thus when we finally get here idx would be > 1. + if (commonParent == null && c != null) + { + commonParent = c.Parent; + } + else if (commonParent != null && c != null) + { + Control selectedControl = c; + + if (selectedControl.Parent != commonParent && !commonParent.Contains(selectedControl)) + { + // look for internal parenting + if (selectedControl == commonParent || selectedControl.Contains(commonParent)) + { + commonParent = selectedControl.Parent; + } + else + { + commonParent = null; + } + } + } + if (component != null) + { + ArrayList al = new ArrayList(); + GetAssociatedComponents(component, host, al); + foreach (IComponent comp in al) + { + changeService.OnComponentChanging(comp, null); + } + + host.DestroyComponent(component); + } + } + } + finally + { + if (trans != null) + trans.Commit(); + foreach (ParentControlDesigner des in designerList) + { + if (des != null) + { + des.ResumeChangingEvents(); + } + } + } + if (commonParent != null) + { + SelectionService.SetSelectedComponents(new object[] { commonParent }, SelectionTypes.Replace); + } + else if (SelectionService.PrimarySelection == null) + { + SelectionService.SetSelectedComponents(new object[] { host.RootComponent }, SelectionTypes.Replace); + } + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the delete menu item is selected. + /// + protected void OnMenuDelete(object sender, EventArgs e) + { + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + if (site != null) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (SelectionService == null) + { + return; + } + + if (host != null) + { + IComponentChangeService changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + ICollection comps = SelectionService.GetSelectedComponents(); + string desc = string.Format(SR.CommandSetDelete, comps.Count); + DesignerTransaction trans = null; + IComponent commonParent = null; + bool commonParentSet = false; + ArrayList designerList = new ArrayList(); + try + { + trans = host.CreateTransaction(desc); + SelectionService.SetSelectedComponents(new object[0], SelectionTypes.Replace); + foreach (object obj in comps) + { + if (!(obj is IComponent comp) || comp.Site == null) + { + continue; + } + //Perf: We suspend Component Changing Events on parent for bulk changes to avoid unnecessary serialization\deserialization for undo + if (obj is Control c) + { + Control parent = c.Parent; + if (parent != null) + { + if (host.GetDesigner(parent) is ParentControlDesigner designer && !designerList.Contains(designer)) + { + designer.SuspendChangingEvents(); + designerList.Add(designer); + designer.ForceComponentChanging(); + } + } + } + } + foreach (object obj in comps) + { + // If it's not a component, we can't delete it. It also may have already been deleted as part of a parent operation, so we skip it. + if (!(obj is IComponent c) || c.Site == null) + { + continue; + } + // We should never delete the base component. + if (obj == host.RootComponent) + { + continue; + } + Control control = obj as Control; + if (!commonParentSet) + { + if (control != null) + { + commonParent = control.Parent; + } + else + { + // if this is not a Control, see if we can get an ITreeDesigner from it, and figure out the Component from that. + if (host.GetDesigner((IComponent)obj) is ITreeDesigner designer) + { + IDesigner parentDesigner = designer.Parent; + if (parentDesigner != null) + { + commonParent = parentDesigner.Component; + } + } + } + commonParentSet = (commonParent != null); + } + else if (commonParent != null) + { + if (control != null && commonParent is Control) + { + Control selectedControl = control; + Control controlCommonParent = (Control)commonParent; + if (selectedControl.Parent != controlCommonParent && !controlCommonParent.Contains(selectedControl)) + { + // look for internal parenting + if (selectedControl == controlCommonParent || selectedControl.Contains(controlCommonParent)) + { + commonParent = selectedControl.Parent; + } + else + { + // start walking up until we find a common parent + while (controlCommonParent != null && !controlCommonParent.Contains(selectedControl)) + { + controlCommonParent = controlCommonParent.Parent; + } + commonParent = controlCommonParent; + } + } + } + else + { + // for these we aren't as thorough as we are with the Control-based ones. we just walk up the chain until we find that parent or the root component. + if (host.GetDesigner((IComponent)obj) is ITreeDesigner designer && host.GetDesigner(commonParent) is ITreeDesigner commonParentDesigner && designer.Parent != commonParentDesigner) + { + ArrayList designerChain = new ArrayList(); + ArrayList parentDesignerChain = new ArrayList(); + // walk the chain of designers from the current parent designer up to the root component, and for the current component designer. + for (designer = designer.Parent as ITreeDesigner; + designer != null; + designer = designer.Parent as ITreeDesigner) + { + designerChain.Add(designer); + } + + for (commonParentDesigner = commonParentDesigner.Parent as ITreeDesigner; commonParentDesigner != null; commonParentDesigner = commonParentDesigner.Parent as ITreeDesigner) + { + parentDesignerChain.Add(commonParentDesigner); + } + + // now that we've got the trees built up, start comparing them from the ends to see where they diverge. + ArrayList shorterList = designerChain.Count < parentDesignerChain.Count ? designerChain : parentDesignerChain; + ArrayList longerList = (shorterList == designerChain ? parentDesignerChain : designerChain); + commonParentDesigner = null; + if (shorterList.Count > 0 && longerList.Count > 0) + { + int shortIndex = Math.Max(0, shorterList.Count - 1); + int longIndex = Math.Max(0, longerList.Count - 1); + while (shortIndex >= 0 && longIndex >= 0) + { + if (shorterList[shortIndex] != longerList[longIndex]) + { + break; + } + commonParentDesigner = (ITreeDesigner)shorterList[shortIndex]; + shortIndex--; + longIndex--; + } + } + // alright, what have we got? + if (commonParentDesigner != null) + { + commonParent = commonParentDesigner.Component; + } + else + { + commonParent = null; + } + } + } + } + ArrayList al = new ArrayList(); + GetAssociatedComponents((IComponent)obj, host, al); + foreach (IComponent comp in al) + { + changeService.OnComponentChanging(comp, null); + } + host.DestroyComponent((IComponent)obj); + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + + foreach (ParentControlDesigner des in designerList) + { + if (des != null) + { + des.ResumeChangingEvents(); + } + } + } + + if (commonParent != null && SelectionService.PrimarySelection == null) + { + if (host.GetDesigner(commonParent) is ITreeDesigner commonParentDesigner && commonParentDesigner.Children != null) + { + // choose the first child of the common parent if it has any. + foreach (IDesigner designer in commonParentDesigner.Children) + { + IComponent component = designer.Component; + if (component.Site != null) + { + commonParent = component; + break; + } + } + } + else if (commonParent is Control controlCommonParent) + { + // if we have a common parent, select it's first child + if (controlCommonParent.Controls.Count > 0) + { + controlCommonParent = controlCommonParent.Controls[0]; + while (controlCommonParent != null && controlCommonParent.Site == null) + { + controlCommonParent = controlCommonParent.Parent; + } + commonParent = controlCommonParent; + } + } + if (commonParent != null) + { + SelectionService.SetSelectedComponents(new object[] { commonParent }, SelectionTypes.Replace); + } + else + { + SelectionService.SetSelectedComponents(new object[] { host.RootComponent }, SelectionTypes.Replace); + } + } + else + { + if (SelectionService.PrimarySelection == null) + { + SelectionService.SetSelectedComponents(new object[] { host.RootComponent }, SelectionTypes.Replace); + } + } + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the paste menu item is selected. + /// + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1809:AvoidExcessiveLocals")] + protected void OnMenuPaste(object sender, EventArgs e) + { + Cursor oldCursor = Cursor.Current; + ArrayList designerList = new ArrayList(); + try + { + Cursor.Current = Cursors.WaitCursor; + // If a control fails to get pasted; then we should remember its associatedComponents so that they are not pasted. + ICollection associatedCompsOfFailedContol = null; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (host == null) + return; // nothing we can do here! + IDataObject dataObj = Clipboard.GetDataObject(); + ICollection components = null; + bool createdItems = false; + ComponentTray tray = null; + int numberOfOriginalTrayControls = 0; + // Get the current number of controls in the Component Tray in the target + tray = GetService(typeof(ComponentTray)) as ComponentTray; + numberOfOriginalTrayControls = tray != null ? tray.Controls.Count : 0; + // We understand two things: CF_DESIGNER, and toolbox items. + object data = dataObj.GetData(CF_DESIGNER); + using (DesignerTransaction trans = host.CreateTransaction(SR.CommandSetPaste)) + { + if (data is byte[] bytes) + { + MemoryStream s = new MemoryStream(bytes); + if (s != null) + { + // CF_DESIGNER was put on the clipboard by us using the designer serialization service. + IDesignerSerializationService ds = (IDesignerSerializationService)GetService(typeof(IDesignerSerializationService)); + if (ds != null) + { + BinaryFormatter formatter = new BinaryFormatter(); + s.Seek(0, SeekOrigin.Begin); + object serializationData = formatter.Deserialize(s); + components = ds.Deserialize(serializationData); + } + } + } + else + { + // Now check for a toolbox item. + IToolboxService ts = (IToolboxService)GetService(typeof(IToolboxService)); + if (ts != null && ts.IsSupported(dataObj, host)) + { + ToolboxItem ti = ts.DeserializeToolboxItem(dataObj, host); + if (ti != null) + { + components = ti.CreateComponents(host); + createdItems = true; + } + } + } + + // Now, if we got some components, hook 'em up! + if (components != null && components.Count > 0) + { + IComponent curComp; + string name; + //Make copy of Items in Array.. + object[] allComponents = new object[components.Count]; + components.CopyTo(allComponents, 0); + ArrayList selectComps = new ArrayList(); + ArrayList controls = new ArrayList(); + string[] componentNames = null; + int idx = 0; + // if the selected item is a frame designer, add to that, otherwise add to the form + IComponent selectedComponent = null; + IDesigner designer = null; + bool dragClient = false; + + IComponent baseComponent = host.RootComponent; + selectedComponent = (IComponent)SelectionService.PrimarySelection; + if (selectedComponent == null) + { + selectedComponent = baseComponent; + } + + dragClient = false; + ITreeDesigner tree = host.GetDesigner(selectedComponent) as ITreeDesigner; + while (!dragClient && tree != null) + { + if (tree is IOleDragClient) + { + designer = tree; + dragClient = true; + } + else + { + if (tree == tree.Parent) + break; + tree = tree.Parent as ITreeDesigner; + } + } + + foreach (object obj in components) + { + + name = null; + curComp = obj as IComponent; + // see if we can fish out the original name. When we serialized, we serialized an array of names at the head of the list. This array matches the components that were created. + if (obj is IComponent) + { + if (componentNames != null && idx < componentNames.Length) + { + name = componentNames[idx++]; + } + } + else + { + if (componentNames == null && obj is string[] sa) + { + componentNames = sa; + idx = 0; + continue; + } + } + + if (GetService(typeof(IEventBindingService)) is IEventBindingService evs) + { + PropertyDescriptorCollection eventProps = evs.GetEventProperties(TypeDescriptor.GetEvents(curComp)); + foreach (PropertyDescriptor pd in eventProps) + { + // If we couldn't find a property for this event, or of the property is read only, then abort. + if (pd == null || pd.IsReadOnly) + { + continue; + } + + if (pd.GetValue(curComp) is string handler) + { + pd.SetValue(curComp, null); + } + } + } + + if (dragClient) + { + bool foundAssociatedControl = false; + // If we have failed to add a control in this Paste operation ... + if (associatedCompsOfFailedContol != null) + { + // then dont add its children controls. + foreach (Component comp in associatedCompsOfFailedContol) + { + if (comp == obj as Component) + { + foundAssociatedControl = true; + break; + } + } + } + + if (foundAssociatedControl) + { + continue; //continue from here so that we dont add the associted compoenet of a control that failed paste operation. + } + + ICollection designerComps = null; + // DGV has columns which are sited IComponents that don't have designers. in this case, ignore them. + if (!(host.GetDesigner(curComp) is ComponentDesigner cDesigner)) + { + continue; + } + //store associatedComponents. + designerComps = cDesigner.AssociatedComponents; + ComponentDesigner parentCompDesigner = ((ITreeDesigner)cDesigner).Parent as ComponentDesigner; + Component parentComp = null; + if (parentCompDesigner != null) + { + parentComp = parentCompDesigner.Component as Component; + } + + ArrayList associatedComps = new ArrayList(); + if (parentComp != null) + { + if (parentCompDesigner != null) + { + foreach (IComponent childComp in parentCompDesigner.AssociatedComponents) + { + associatedComps.Add(childComp as Component); + } + } + } + + if (parentComp == null || !(associatedComps.Contains(curComp))) + { + if (parentComp != null) + { + if (host.GetDesigner(parentComp) is ParentControlDesigner parentDesigner && !designerList.Contains(parentDesigner)) + { + parentDesigner.SuspendChangingEvents(); + designerList.Add(parentDesigner); + parentDesigner.ForceComponentChanging(); + } + } + + if (!((IOleDragClient)designer).AddComponent(curComp, name, createdItems)) + { + //cache the associatedComponents only for FAILED control. + associatedCompsOfFailedContol = designerComps; + // now we will jump out of the using block and call trans.Dispose() which in turn calls trans.Cancel for an uncommited transaction, We want to cancel the transaction because otherwise we'll have un-parented controls + return; + } + + Control designerControl = ((IOleDragClient)designer).GetControlForComponent(curComp); + if (designerControl != null) + { + controls.Add(designerControl); + } + // Select the newly Added top level component + if ((TypeDescriptor.GetAttributes(curComp).Contains(DesignTimeVisibleAttribute.Yes)) || curComp is ToolStripItem) + { + selectComps.Add(curComp); + } + } + // if Parent is not selected... select the curcomp. + else if (associatedComps.Contains(curComp) && Array.IndexOf(allComponents, parentComp) == -1) + { + selectComps.Add(curComp); + } + bool changeName = false; + if (curComp is Control c) + { + // if the text is the same as the name, remember it. After we add the control, we'll update the text with the new name. + if (name != null && name.Equals(c.Text)) + { + changeName = true; + } + } + if (changeName) + { + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(curComp); + PropertyDescriptor nameProp = props["Name"]; + if (nameProp != null && nameProp.PropertyType == typeof(string)) + { + string newName = (string)nameProp.GetValue(curComp); + if (!newName.Equals(name)) + { + PropertyDescriptor textProp = props["Text"]; + if (textProp != null && textProp.PropertyType == nameProp.PropertyType) + { + textProp.SetValue(curComp, nameProp.GetValue(curComp)); + } + } + } + } + } + } + // Find those controls that have ControlDesigners and center them on the designer surface + ArrayList compsWithControlDesigners = new ArrayList(); + foreach (Control c in controls) + { + IDesigner des = host.GetDesigner((IComponent)c); + if (des is ControlDesigner) + { + compsWithControlDesigners.Add(c); + } + } + + if (compsWithControlDesigners.Count > 0) + { + // Update the control positions. We want to keep the entire block of controls relative to each other, but relocate them within the container. + UpdatePastePositions(compsWithControlDesigners); + } + + // Figure out if we added components to the component tray, and have the tray adjust their position. MartinTh - removed the old check, since ToolStrips breaks the scenario. ToolStrips have a ControlDesigner, but also add a component to the tray. The old code wouldn't detect that, so the tray location wouldn't get adjusted. Rather than fixing this up in ToolStripKeyboardHandlingService.OnCommandPaste, we do it here, since doing it in the service, wouldn't handle cross-form paste. + if (tray == null) + { + // the paste target did not have a tray already, so let's go get it - if there is one + tray = GetService(typeof(ComponentTray)) as ComponentTray; + } + if (tray != null) + { + int numberOfTrayControlsAdded = tray.Controls.Count - numberOfOriginalTrayControls; + if (numberOfTrayControlsAdded > 0) + { + ArrayList listOfTrayControls = new ArrayList(); + for (int i = 0; i < numberOfTrayControlsAdded; i++) + { + listOfTrayControls.Add(tray.Controls[numberOfOriginalTrayControls + i]); + } + tray.UpdatePastePositions(listOfTrayControls); + } + } + + // Update the tab indices of all the components. We must first sort the components by their existing tab indices or else we will not preserve their original intent. + controls.Sort(new TabIndexCompare()); + foreach (Control c in controls) + { + UpdatePasteTabIndex(c, c.Parent); + } + + // finally select all the components we added + SelectionService.SetSelectedComponents((object[])selectComps.ToArray(), SelectionTypes.Replace); + // and bring them to the front - but only if we can mess with the Z-order. + if (designer is ParentControlDesigner parentControlDesigner && parentControlDesigner.AllowSetChildIndexOnDrop) + { + MenuCommand btf = MenuService.FindCommand(MenuCommands.BringToFront); + if (btf != null) + { + btf.Invoke(); + } + } + trans.Commit(); + } + } + } + finally + { + Cursor.Current = oldCursor; + foreach (ParentControlDesigner des in designerList) + { + if (des != null) + { + des.ResumeChangingEvents(); + } + } + } + } + + /// + /// Called when the select all menu item is selected. + /// + protected void OnMenuSelectAll(object sender, EventArgs e) + { + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + if (site != null) + { + Debug.Assert(SelectionService != null, "We need the SelectionService, but we can't find it!"); + if (SelectionService == null) + { + return; + } + + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (host != null) + { + ComponentCollection components = host.Container.Components; + object[] selComps; + if (components == null || components.Count == 0) + { + selComps = new IComponent[0]; + } + else + { + selComps = new object[components.Count - 1]; + object baseComp = host.RootComponent; + + int j = 0; + foreach (IComponent comp in components) + { + if (baseComp == comp) + continue; + selComps[j++] = comp; + } + } + SelectionService.SetSelectedComponents(selComps, SelectionTypes.Replace); + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the show grid menu item is selected. + /// + protected void OnMenuShowGrid(object sender, EventArgs e) + { + if (site != null) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (host != null) + { + DesignerTransaction trans = null; + + try + { + trans = host.CreateTransaction(); + IComponent baseComponent = host.RootComponent; + if (baseComponent != null && baseComponent is Control) + { + PropertyDescriptor prop = GetProperty(baseComponent, "DrawGrid"); + if (prop != null) + { + bool drawGrid = (bool)prop.GetValue(baseComponent); + prop.SetValue(baseComponent, !drawGrid); + ((MenuCommand)sender).Checked = !drawGrid; + } + } + } + finally + { + if (trans != null) + trans.Commit(); + } + } + } + } + + /// + /// Handles the various size to commands. + /// + protected void OnMenuSizingCommand(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + CommandID cmdID = cmd.CommandID; + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + ICollection sel = SelectionService.GetSelectedComponents(); + object[] selectedObjects = new object[sel.Count]; + sel.CopyTo(selectedObjects, 0); + selectedObjects = FilterSelection(selectedObjects, SelectionRules.Visible); + object selPrimary = SelectionService.PrimarySelection; + Size primarySize = Size.Empty; + Size itemSize = Size.Empty; + PropertyDescriptor sizeProp; + if (selPrimary is IComponent component) + { + sizeProp = GetProperty(component, "Size"); + if (sizeProp == null) + { + //if we couldn't get a valid size for our primary selection, we'll fail silently + return; + } + primarySize = (Size)sizeProp.GetValue(component); + } + if (selPrimary == null) + { + return; + } + + Debug.Assert(null != selectedObjects, "queryStatus should have disabled this"); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + DesignerTransaction trans = null; + try + { + if (host != null) + { + trans = host.CreateTransaction(string.Format(SR.CommandSetSize, selectedObjects.Length)); + } + + foreach (object obj in selectedObjects) + { + if (obj.Equals(selPrimary)) + continue; + if (!(obj is IComponent comp)) + { + continue; + } + //if the component is locked, no sizing is allowed... + PropertyDescriptor lockedDesc = GetProperty(obj, "Locked"); + if (lockedDesc != null && (bool)lockedDesc.GetValue(obj)) + { + continue; + } + sizeProp = GetProperty(comp, "Size"); + // Skip all components that don't have a size property + if (sizeProp == null || sizeProp.IsReadOnly) + { + continue; + } + itemSize = (Size)sizeProp.GetValue(comp); + if (cmdID == MenuCommands.SizeToControlHeight || cmdID == MenuCommands.SizeToControl) + { + itemSize.Height = primarySize.Height; + } + + if (cmdID == MenuCommands.SizeToControlWidth || cmdID == MenuCommands.SizeToControl) + { + itemSize.Width = primarySize.Width; + } + sizeProp.SetValue(comp, itemSize); + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + } + } + finally + { + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the size->to grid menu item is selected. + /// + protected void OnMenuSizeToGrid(object sender, EventArgs e) + { + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + DesignerTransaction trans = null; + try + { + Cursor.Current = Cursors.WaitCursor; + ICollection sel = SelectionService.GetSelectedComponents(); + object[] selectedObjects = new object[sel.Count]; + sel.CopyTo(selectedObjects, 0); + selectedObjects = FilterSelection(selectedObjects, SelectionRules.Visible); + Size size = Size.Empty; + Point loc = Point.Empty; + Debug.Assert(null != selectedObjects, "queryStatus should have disabled this"); + Size grid = Size.Empty; + PropertyDescriptor sizeProp = null; + PropertyDescriptor locProp = null; + if (host != null) + { + trans = host.CreateTransaction(string.Format(SR.CommandSetSizeToGrid, selectedObjects.Length)); + IComponent baseComponent = host.RootComponent; + if (baseComponent != null && baseComponent is Control) + { + PropertyDescriptor prop = GetProperty(baseComponent, "CurrentGridSize"); + if (prop != null) + { + grid = (Size)prop.GetValue(baseComponent); + } + } + } + + if (!grid.IsEmpty) + { + foreach (object obj in selectedObjects) + { + IComponent comp = obj as IComponent; + if (obj == null) + { + continue; + } + + sizeProp = GetProperty(comp, "Size"); + locProp = GetProperty(comp, "Location"); + Debug.Assert(sizeProp != null, "No size property on component"); + Debug.Assert(locProp != null, "No location property on component"); + if (sizeProp == null || locProp == null || sizeProp.IsReadOnly || locProp.IsReadOnly) + { + continue; + } + + size = (Size)sizeProp.GetValue(comp); + loc = (Point)locProp.GetValue(comp); + size.Width = ((size.Width + (grid.Width / 2)) / grid.Width) * grid.Width; + size.Height = ((size.Height + (grid.Height / 2)) / grid.Height) * grid.Height; + loc.X = (loc.X / grid.Width) * grid.Width; + loc.Y = (loc.Y / grid.Height) * grid.Height; + sizeProp.SetValue(comp, size); + locProp.SetValue(comp, loc); + } + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the properties menu item is selected on the Context menu + /// + protected void OnMenuDesignerProperties(object sender, EventArgs e) + { + // first, look if the currently selected object has a component editor... + object obj = SelectionService.PrimarySelection; + if (CheckComponentEditor(obj, true)) + { + return; + } + + IMenuCommandService menuSvc = (IMenuCommandService)GetService(typeof(IMenuCommandService)); + if (menuSvc != null) + { + if (menuSvc.GlobalInvoke(MenuCommands.PropertiesWindow)) + { + return; + } + } + Debug.Assert(false, "Invoking pbrs command failed"); + } + + /// + /// Called when the snap to grid menu item is selected. + /// + protected void OnMenuSnapToGrid(object sender, EventArgs e) + { + if (site != null) + { + IDesignerHost host = (IDesignerHost)site.GetService(typeof(IDesignerHost)); + if (host != null) + { + DesignerTransaction trans = null; + try + { + trans = host.CreateTransaction(string.Format(SR.CommandSetPaste, 0)); + IComponent baseComponent = host.RootComponent; + if (baseComponent != null && baseComponent is Control) + { + PropertyDescriptor prop = GetProperty(baseComponent, "SnapToGrid"); + if (prop != null) + { + bool snapToGrid = (bool)prop.GetValue(baseComponent); + prop.SetValue(baseComponent, !snapToGrid); + ((MenuCommand)sender).Checked = !snapToGrid; + } + } + } + finally + { + if (trans != null) + trans.Commit(); + } + } + } + + } + + /// + /// Called when a spacing command is selected + /// + protected void OnMenuSpacingCommand(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + CommandID cmdID = cmd.CommandID; + DesignerTransaction trans = null; + if (SelectionService == null) + { + return; + } + + Cursor oldCursor = Cursor.Current; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + try + { + Cursor.Current = Cursors.WaitCursor; + // Inform the designer that we are about to monkey with a ton of properties. + Size grid = Size.Empty; + ICollection sel = SelectionService.GetSelectedComponents(); + object[] selectedObjects = new object[sel.Count]; + sel.CopyTo(selectedObjects, 0); + if (host != null) + { + trans = host.CreateTransaction(string.Format(SR.CommandSetFormatSpacing, selectedObjects.Length)); + IComponent baseComponent = host.RootComponent; + if (baseComponent != null && baseComponent is Control) + { + PropertyDescriptor prop = GetProperty(baseComponent, "CurrentGridSize"); + if (prop != null) + { + grid = (Size)prop.GetValue(baseComponent); + } + } + } + + selectedObjects = FilterSelection(selectedObjects, SelectionRules.Visible); + int nEqualDelta = 0; + Debug.Assert(null != selectedObjects, "queryStatus should have disabled this"); + PropertyDescriptor curSizeDesc = null, lastSizeDesc = null; + PropertyDescriptor curLocDesc = null, lastLocDesc = null; + Size curSize = Size.Empty, lastSize = Size.Empty; + Point curLoc = Point.Empty, lastLoc = Point.Empty; + Point primaryLoc = Point.Empty; + IComponent curComp = null, lastComp = null; + int sort = -1; + // Must sort differently if we're horizontal or vertical... + if (cmdID == MenuCommands.HorizSpaceConcatenate || cmdID == MenuCommands.HorizSpaceDecrease || cmdID == MenuCommands.HorizSpaceIncrease || cmdID == MenuCommands.HorizSpaceMakeEqual) + { + sort = SORT_HORIZONTAL; + } + else if (cmdID == MenuCommands.VertSpaceConcatenate || cmdID == MenuCommands.VertSpaceDecrease || cmdID == MenuCommands.VertSpaceIncrease || cmdID == MenuCommands.VertSpaceMakeEqual) + { + sort = SORT_VERTICAL; + } + else + { + throw new ArgumentException(SR.CommandSetUnknownSpacingCommand); + } + + SortSelection(selectedObjects, sort); + //now that we're sorted, lets get our primary selection and it's index + object primary = SelectionService.PrimarySelection; + int primaryIndex = 0; + if (primary != null) + primaryIndex = Array.IndexOf(selectedObjects, primary); + + // And compute delta values for Make Equal + if (cmdID == MenuCommands.HorizSpaceMakeEqual || + cmdID == MenuCommands.VertSpaceMakeEqual) + { + int total, n; + total = 0; + for (n = 0; n < selectedObjects.Length; n++) + { + curSize = Size.Empty; + if (selectedObjects[n] is IComponent component) + { + curComp = component; + curSizeDesc = GetProperty(curComp, "Size"); + if (curSizeDesc != null) + { + curSize = (Size)curSizeDesc.GetValue(curComp); + } + } + + if (sort == SORT_HORIZONTAL) + { + total += curSize.Width; + } + else + { + total += curSize.Height; + } + } + + lastComp = curComp = null; + curSize = Size.Empty; + curLoc = Point.Empty; + for (n = 0; n < selectedObjects.Length; n++) + { + curComp = selectedObjects[n] as IComponent; + if (curComp != null) + { + // only get the descriptors if we've changed component types + if (lastComp == null || curComp.GetType() != lastComp.GetType()) + { + curSizeDesc = GetProperty(curComp, "Size"); + curLocDesc = GetProperty(curComp, "Location"); + } + lastComp = curComp; + + if (curLocDesc != null) + { + curLoc = (Point)curLocDesc.GetValue(curComp); + } + else + { + continue; + } + + if (curSizeDesc != null) + { + curSize = (Size)curSizeDesc.GetValue(curComp); + } + else + { + continue; + } + + if (!curSize.IsEmpty && !curLoc.IsEmpty) + { + break; + } + } + } + + for (n = selectedObjects.Length - 1; n >= 0; n--) + { + curComp = selectedObjects[n] as IComponent; + if (curComp != null) + { + // only get the descriptors if we've changed component types + if (lastComp == null || curComp.GetType() != lastComp.GetType()) + { + curSizeDesc = GetProperty(curComp, "Size"); + curLocDesc = GetProperty(curComp, "Location"); + } + lastComp = curComp; + + if (curLocDesc != null) + { + lastLoc = (Point)curLocDesc.GetValue(curComp); + } + else + { + continue; + } + + if (curSizeDesc != null) + { + lastSize = (Size)curSizeDesc.GetValue(curComp); + } + else + { + continue; + } + + if (curSizeDesc != null && curLocDesc != null) + { + break; + } + } + } + + if (curSizeDesc != null && curLocDesc != null) + { + if (sort == SORT_HORIZONTAL) + { + nEqualDelta = (lastSize.Width + lastLoc.X - curLoc.X - total) / (selectedObjects.Length - 1); + } + else + { + nEqualDelta = (lastSize.Height + lastLoc.Y - curLoc.Y - total) / (selectedObjects.Length - 1); + } + if (nEqualDelta < 0) + nEqualDelta = 0; + } + } + curComp = lastComp = null; + if (primary != null) + { + PropertyDescriptor primaryLocDesc = GetProperty(primary, "Location"); + if (primaryLocDesc != null) + { + primaryLoc = (Point)primaryLocDesc.GetValue(primary); + } + } + + // Finally move the components + for (int n = 0; n < selectedObjects.Length; n++) + { + curComp = (IComponent)selectedObjects[n]; + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(curComp); + //Check to see if the component we are about to move is locked... + PropertyDescriptor lockedDesc = props["Locked"]; + if (lockedDesc != null && (bool)lockedDesc.GetValue(curComp)) + { + continue; // locked property of our component is true, so don't move it + } + + if (lastComp == null || lastComp.GetType() != curComp.GetType()) + { + curSizeDesc = props["Size"]; + curLocDesc = props["Location"]; + } + else + { + curSizeDesc = lastSizeDesc; + curLocDesc = lastLocDesc; + } + + if (curLocDesc != null) + { + curLoc = (Point)curLocDesc.GetValue(curComp); + } + else + { + continue; + } + + if (curSizeDesc != null) + { + curSize = (Size)curSizeDesc.GetValue(curComp); + } + else + { + continue; + } + + int lastIndex = Math.Max(0, n - 1); + lastComp = (IComponent)selectedObjects[lastIndex]; + if (lastComp.GetType() != curComp.GetType()) + { + lastSizeDesc = GetProperty(lastComp, "Size"); + lastLocDesc = GetProperty(lastComp, "Location"); + } + else + { + lastSizeDesc = curSizeDesc; + lastLocDesc = curLocDesc; + } + + if (lastLocDesc != null) + { + lastLoc = (Point)lastLocDesc.GetValue(lastComp); + } + else + { + continue; + } + + if (lastSizeDesc != null) + { + lastSize = (Size)lastSizeDesc.GetValue(lastComp); + } + else + { + continue; + } + + if (cmdID == MenuCommands.HorizSpaceConcatenate && n > 0) + { + curLoc.X = lastLoc.X + lastSize.Width; + } + else if (cmdID == MenuCommands.HorizSpaceDecrease) + { + if (primaryIndex < n) + { + curLoc.X -= grid.Width * (n - primaryIndex); + if (curLoc.X < primaryLoc.X) + curLoc.X = primaryLoc.X; + } + else if (primaryIndex > n) + { + curLoc.X += grid.Width * (primaryIndex - n); + if (curLoc.X > primaryLoc.X) + curLoc.X = primaryLoc.X; + } + } + else if (cmdID == MenuCommands.HorizSpaceIncrease) + { + if (primaryIndex < n) + { + curLoc.X += grid.Width * (n - primaryIndex); + } + else if (primaryIndex > n) + { + curLoc.X -= grid.Width * (primaryIndex - n); + } + + } + else if (cmdID == MenuCommands.HorizSpaceMakeEqual && n > 0) + { + curLoc.X = lastLoc.X + lastSize.Width + nEqualDelta; + } + else if (cmdID == MenuCommands.VertSpaceConcatenate && n > 0) + { + curLoc.Y = lastLoc.Y + lastSize.Height; + } + else if (cmdID == MenuCommands.VertSpaceDecrease) + { + if (primaryIndex < n) + { + curLoc.Y -= grid.Height * (n - primaryIndex); + if (curLoc.Y < primaryLoc.Y) + curLoc.Y = primaryLoc.Y; + } + else if (primaryIndex > n) + { + curLoc.Y += grid.Height * (primaryIndex - n); + if (curLoc.Y > primaryLoc.Y) + curLoc.Y = primaryLoc.Y; + } + } + else if (cmdID == MenuCommands.VertSpaceIncrease) + { + if (primaryIndex < n) + { + curLoc.Y += grid.Height * (n - primaryIndex); + } + else if (primaryIndex > n) + { + curLoc.Y -= grid.Height * (primaryIndex - n); + } + } + else if (cmdID == MenuCommands.VertSpaceMakeEqual && n > 0) + { + curLoc.Y = lastLoc.Y + lastSize.Height + nEqualDelta; + } + + if (!curLocDesc.IsReadOnly) + { + curLocDesc.SetValue(curComp, curLoc); + } + lastComp = curComp; + } + } + finally + { + if (trans != null) + { + trans.Commit(); + } + Cursor.Current = oldCursor; + } + } + + /// + /// Called when the current selection changes. Here we determine what commands can and can't be enabled. + /// + protected void OnSelectionChanged(object sender, EventArgs e) + { + if (SelectionService == null) + { + return; + } + _selectionVersion++; + // Update our cached selection counts. + selCount = SelectionService.SelectionCount; + IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Failed to get designer host"); + // if the base component is selected, we'll say that nothing's selected so we don't get wierd behavior + if (selCount > 0 && designerHost != null) + { + object baseComponent = designerHost.RootComponent; + if (baseComponent != null && SelectionService.GetComponentSelected(baseComponent)) + { + selCount = 0; + } + } + + primarySelection = SelectionService.PrimarySelection as IComponent; + _selectionInherited = false; + controlsOnlySelection = true; + if (selCount > 0) + { + ICollection selection = SelectionService.GetSelectedComponents(); + foreach (object obj in selection) + { + if (!(obj is Control)) + { + controlsOnlySelection = false; + } + + if (!TypeDescriptor.GetAttributes(obj)[typeof(InheritanceAttribute)].Equals(InheritanceAttribute.NotInherited)) + { + _selectionInherited = true; + break; + } + } + } + OnUpdateCommandStatus(); + } + + /// + /// When this timer expires, this tells us that we need to erase any snaplines we have drawn. First, we need to marshal this back to the correct thread. + /// + private void OnSnapLineTimerExpire(object sender, EventArgs e) + { + Control marshalControl = BehaviorService.AdornerWindowControl; + if (marshalControl != null && marshalControl.IsHandleCreated) + { + marshalControl.BeginInvoke(new EventHandler(OnSnapLineTimerExpireMarshalled), new object[] { sender, e }); + } + } + + /// + /// Called when our snapline timer expires - this method has been call has been properly marshalled back to the correct thread. + /// + private void OnSnapLineTimerExpireMarshalled(object sender, EventArgs e) + { + _snapLineTimer.Stop(); + EndDragManager(); + } + + /// + /// Determines the status of a menu command. Commands with this event handler are always enabled. + /// + protected void OnStatusAlways(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + cmd.Enabled = true; + } + + /// + /// Determines the status of a menu command. Commands with this event handler are enabled when one or more objects are selected. + /// + protected void OnStatusAnySelection(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + cmd.Enabled = selCount > 0; + } + + /// + /// Status for the copy command. This is enabled when there is something juicy selected. + /// + protected void OnStatusCopy(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + bool enable = false; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (!_selectionInherited && host != null && !host.Loading) + { + ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || selSvc != null, "ISelectionService not found"); + if (selSvc != null) + { + // There must also be a component in the mix, and not the base component + ICollection selectedComponents = selSvc.GetSelectedComponents(); + object baseComp = host.RootComponent; + if (!selSvc.GetComponentSelected(baseComp)) + { + foreach (object obj in selectedComponents) + { + // if the object is not sited to the same thing as the host container then don't allow copy. + if (obj is IComponent comp && comp.Site != null && comp.Site.Container == host.Container) + { + enable = true; + break; + } + } + } + } + } + cmd.Enabled = enable; + } + + /// + /// Status for the cut command. This is enabled when there is something juicy selected and that something does not contain any inherited components. + /// + protected void OnStatusCut(object sender, EventArgs e) + { + OnStatusDelete(sender, e); + if (((MenuCommand)sender).Enabled) + { + OnStatusCopy(sender, e); + } + } + + /// + /// Status for the delete command. This is enabled when there is something selected and that something does not contain inherited components. + /// + protected void OnStatusDelete(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + if (_selectionInherited) + { + cmd.Enabled = false; + } + else + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + if (selSvc != null) + { + ICollection selectedComponents = selSvc.GetSelectedComponents(); + foreach (object obj in selectedComponents) + { + // if the object is not sited to the same thing as the host container then don't allow delete. VSWhidbey# 275790 + if (obj is IComponent comp && (comp.Site == null || (comp.Site != null && comp.Site.Container != host.Container))) + { + cmd.Enabled = false; + return; + } + } + } + } + OnStatusAnySelection(sender, e); + } + } + + /// + /// Determines the status of a menu command. Commands with this event are enabled when there is something yummy on the clipboard. + /// + protected void OnStatusPaste(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + // Before we even look at the data format, check to see if the thing we're going to paste into is privately inherited. If it is, then we definitely cannot paste. + if (primarySelection != null) + { + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || host != null, "IDesignerHost not found"); + if (host != null && host.GetDesigner(primarySelection) is ParentControlDesigner) + { + // This component is a target for our paste operation. We must ensure that it is not privately inherited. + InheritanceAttribute attr = (InheritanceAttribute)TypeDescriptor.GetAttributes(primarySelection)[typeof(InheritanceAttribute)]; + Debug.Assert(attr != null, "Type descriptor gave us a null attribute -- problem in type descriptor"); + if (attr.InheritanceLevel == InheritanceLevel.InheritedReadOnly) + { + cmd.Enabled = false; + return; + } + } + } + + // Not being inherited. Now look at the contents of the data + IDataObject dataObj = Clipboard.GetDataObject(); + bool enable = false; + if (dataObj != null) + { + if (dataObj.GetDataPresent(CF_DESIGNER)) + { + enable = true; + } + else + { + // Not ours, check to see if the toolbox service understands this + IToolboxService ts = (IToolboxService)GetService(typeof(IToolboxService)); + if (ts != null) + { + enable = (host != null ? ts.IsSupported(dataObj, host) : ts.IsToolboxItem(dataObj)); + } + } + } + cmd.Enabled = enable; + } + + private void OnStatusPrimarySelection(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + cmd.Enabled = primarySelection != null; + } + + protected virtual void OnStatusSelectAll(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + cmd.Enabled = host.Container.Components.Count > 1; + } + + /// + /// This is called when the selection has changed. Anyone using CommandSetItems that need to update their status based on selection changes should override this and update their own commands at this time. The base implementaion runs through all base commands and calls UpdateStatus on them. + /// + protected virtual void OnUpdateCommandStatus() + { + // Now whip through all of the commands and ask them to update. + for (int i = 0; i < _commandSet.Length; i++) + { + _commandSet[i].UpdateStatus(); + } + } + + /// + /// This method grows the objects collection by one. It prepends the collection with a string[] which contains the component names in order for each component in the list. + /// + private ICollection PrependComponentNames(ICollection objects) + { + object[] newObjects = new object[objects.Count + 1]; + int idx = 1; + ArrayList names = new ArrayList(objects.Count); + foreach (object o in objects) + { + if (o is IComponent comp) + { + string name = null; + if (comp.Site != null) + { + name = comp.Site.Name; + } + names.Add(name); + } + newObjects[idx++] = o; + } + string[] nameArray = new string[names.Count]; + names.CopyTo(nameArray, 0); + newObjects[0] = nameArray; + return newObjects; + } + + /// + /// called by the formatting commands when we need a given selection array sorted. Sorting the array sorts by x from left to right, and by Y from top to bottom. + /// + private void SortSelection(object[] selectedObjects, int nSortBy) + { + IComparer comp; + switch (nSortBy) + { + case SORT_HORIZONTAL: + comp = new ComponentLeftCompare(); + break; + case SORT_VERTICAL: + comp = new ComponentTopCompare(); + break; + case SORT_ZORDER: + comp = new ControlZOrderCompare(); + break; + default: + return; + } + Array.Sort(selectedObjects, comp); + } + + /// + /// Common function that updates the status of clipboard menu items only + /// + private void UpdateClipboardItems(object s, EventArgs e) + { + int itemCount = 0; + CommandSetItem curItem; + for (int i = 0; itemCount < 3 && i < _commandSet.Length; i++) + { + curItem = _commandSet[i]; + if (curItem.CommandID == MenuCommands.Paste || + curItem.CommandID == MenuCommands.Copy || + curItem.CommandID == MenuCommands.Cut) + { + itemCount++; + curItem.UpdateStatus(); + } + } + } + + private void UpdatePastePositions(ArrayList controls) + { + if (controls.Count == 0) + { + return; + } + + // Find the offset to apply to these controls. The offset is the location needed to center the controls in the parent. If there is no parent, we relocate to 0, 0. + Control parentControl = ((Control)controls[0]).Parent; + Point min = ((Control)controls[0]).Location; + Point max = min; + foreach (Control c in controls) + { + Point loc = c.Location; + Size size = c.Size; + if (min.X > loc.X) + { + min.X = loc.X; + } + if (min.Y > loc.Y) + { + min.Y = loc.Y; + } + if (max.X < loc.X + size.Width) + { + max.X = loc.X + size.Width; + } + if (max.Y < loc.Y + size.Height) + { + max.Y = loc.Y + size.Height; + } + } + // We have the bounding rect for the controls. Next, offset this rect so that we center it in the parent. If we have no parent, the offset will position the control at 0, 0, to whatever parent we eventually get. + Point offset = new Point(-min.X, -min.Y); + // Look to ensure that we're not going to paste this control over the top of another control. We only do this for the first control because preserving the relationship between controls is more important than obscuring a control. + if (parentControl != null) + { + bool bumpIt; + bool wrapped = false; + Size parentSize = parentControl.ClientSize; + Size gridSize = Size.Empty; + Point parentOffset = new Point(parentSize.Width / 2, parentSize.Height / 2); + parentOffset.X -= (max.X - min.X) / 2; + parentOffset.Y -= (max.Y - min.Y) / 2; + do + { + bumpIt = false; + // Cycle through the controls on the parent. We're interested in controls that (a) are not in our set of controls and (b) have a location == to our current bumpOffset OR (c) are the same size as our parent. If we find such a control, we increment the bump offset by one grid size. + foreach (Control child in parentControl.Controls) + { + Rectangle childBounds = child.Bounds; + if (controls.Contains(child)) + { + // We still want to bump if the child is the same size as the parent. Otherwise the child would overlay exactly on top of the parent. + if (!child.Size.Equals(parentSize)) + { + continue; + } + + // We're dealing with our own pasted control, so offset its bounds. We don't use parent offset here because, well, we're comparing against the parent! + childBounds.Offset(offset); + } + + // We need only compare against one of our pasted controls, so pick the first one. + Control pasteControl = (Control)controls[0]; + Rectangle pasteControlBounds = pasteControl.Bounds; + pasteControlBounds.Offset(offset); + pasteControlBounds.Offset(parentOffset); + if (pasteControlBounds.Equals(childBounds)) + { + bumpIt = true; + if (gridSize.IsEmpty) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + IComponent baseComponent = host.RootComponent; + if (baseComponent != null && baseComponent is Control) + { + PropertyDescriptor gs = GetProperty(baseComponent, "GridSize"); + if (gs != null) + { + gridSize = (Size)gs.GetValue(baseComponent); + } + } + if (gridSize.IsEmpty) + { + gridSize.Width = 8; + gridSize.Height = 8; + } + } + + parentOffset += gridSize; + // Extra check: If the end of our control group is > the parent size, bump back to zero. We still allow further bumps after this so we can continue to offset, but if we cycle again then we quit so we won't loop indefinitely. We only do this if we're a group. If we're a single control we use the beginning of the control + a grid size. + int groupEndX; + int groupEndY; + if (controls.Count > 1) + { + groupEndX = parentOffset.X + max.X - min.X; + groupEndY = parentOffset.Y + max.Y - min.Y; + } + else + { + groupEndX = parentOffset.X + gridSize.Width; + groupEndY = parentOffset.Y + gridSize.Height; + } + + if (groupEndX > parentSize.Width || groupEndY > parentSize.Height) + { + parentOffset.X = 0; + parentOffset.Y = 0; + if (wrapped) + { + bumpIt = false; + } + else + { + wrapped = true; + } + } + break; + } + } + } while (bumpIt); + offset.Offset(parentOffset.X, parentOffset.Y); + } + + // Now, for each control, update the offset. + if (parentControl != null) + { + parentControl.SuspendLayout(); + } + try + { + foreach (Control c in controls) + { + Point newLoc = c.Location; + newLoc.Offset(offset.X, offset.Y); + c.Location = newLoc; + } + } + finally + { + if (parentControl != null) + { + parentControl.ResumeLayout(); + } + } + } + + private void UpdatePasteTabIndex(Control componentControl, object parentComponent) + { + if (!(parentComponent is Control parentControl) || componentControl == null) + { + return; + } + bool tabIndexCollision = false; + int tabIndexOriginal = componentControl.TabIndex; + // Find the next highest tab index + int nextTabIndex = 0; + foreach (Control c in parentControl.Controls) + { + int t = c.TabIndex; + if (nextTabIndex <= t) + { + nextTabIndex = t + 1; + } + + if (t == tabIndexOriginal) + { + tabIndexCollision = true; + } + } + + if (tabIndexCollision) + { + componentControl.TabIndex = nextTabIndex; + } + } + + /// + /// We extend MenuCommand for our command set items. A command set item is a menu command with an added delegate that is used to determine the flags for the menu item. We have different classes of delegates here. For example, many menu items may be enabled when there is at least one object selected, while others are only enabled if there is more than one object or if there is a primary selection. + /// + protected class CommandSetItem : MenuCommand + { + private readonly EventHandler _statusHandler; + private readonly IEventHandlerService _eventService; + private readonly IUIService _uiService; + private readonly CommandSet _commandSet; + private static Hashtable s_commandStatusHash; // list of the command statuses we are tracking. + private bool _updatingCommand = false; // flag we set when we're updating the command so we don't call back on the status handler. + + public CommandSetItem(CommandSet commandSet, EventHandler statusHandler, EventHandler invokeHandler, CommandID id, IUIService uiService) : this(commandSet, statusHandler, invokeHandler, id, false, uiService) + { + } + + public CommandSetItem(CommandSet commandSet, EventHandler statusHandler, EventHandler invokeHandler, CommandID id) : this(commandSet, statusHandler, invokeHandler, id, false, null) + { + } + + public CommandSetItem(CommandSet commandSet, EventHandler statusHandler, EventHandler invokeHandler, CommandID id, bool optimizeStatus) : this(commandSet, statusHandler, invokeHandler, id, optimizeStatus, null) + { + } + + /// + /// Creates a new CommandSetItem. + /// + [SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")] + public CommandSetItem(CommandSet commandSet, EventHandler statusHandler, EventHandler invokeHandler, CommandID id, bool optimizeStatus, IUIService uiService) + : base(invokeHandler, id) + { + _uiService = uiService; + _eventService = commandSet._eventService; + _statusHandler = statusHandler; + // when we optimize, it's because status is fully based on selection. so what we do is only call the status handler once per selection change to prevent doing the same work over and over again. we do this by hashing up the command statuses and then filling in the results we get, so we can easily retrieve them when the selection hasn't changed. + if (optimizeStatus && statusHandler != null) + { + // we use this as our sentinel of when we're doing this. + _commandSet = commandSet; + // create the hash if needed. + lock (typeof(CommandSetItem)) + { + if (s_commandStatusHash == null) + { + s_commandStatusHash = new Hashtable(); + } + } + + // UNDONE:CommandSetItem is put in a static hashtable, and CommandSetItem references CommandSet, CommandSet reference FormDesigner. If we don't remove the CommandSetItem from the static hashtable, FormDesigner is leaked. This demonstrates a bad design. We should not keep a static hashtable for all the items, instead, we should keep a hashtable per Designer. When designer is disposed, all command items got disposed automatically. However, at this time, we would pick a simple way with low risks to fix this. + // if this handler isn't already in there, add it. + if (!(s_commandStatusHash[statusHandler] is StatusState state)) + { + state = new StatusState(); + s_commandStatusHash.Add(statusHandler, state); + } + state.refCount++; + } + } + + /// + /// Checks if the status for this command is valid, meaning we don't need to call the status handler. + /// + private bool CommandStatusValid + { + get + { + // check to see if this is a command we have hashed up and if it's version stamp is the same as our current selection version. + if (_commandSet != null && s_commandStatusHash.Contains(_statusHandler)) + { + if (s_commandStatusHash[_statusHandler] is StatusState state && state.SelectionVersion == _commandSet.SelectionVersion) + { + return true; + } + } + return false; + } + } + + /// + /// Applys the cached status to this item. + /// + private void ApplyCachedStatus() + { + if (_commandSet != null && s_commandStatusHash.Contains(_statusHandler)) + { + try + { + // set our our updating flag so it doesn't call the status handler again. + _updatingCommand = true; + // and push the state into this command. + StatusState state = s_commandStatusHash[_statusHandler] as StatusState; + state.ApplyState(this); + } + finally + { + _updatingCommand = false; + } + } + } + + /// + /// This may be called to invoke the menu item. + /// + public override void Invoke() + { + // We allow outside parties to override the availability of particular menu commands. + try + { + if (_eventService != null) + { + IMenuStatusHandler msh = (IMenuStatusHandler)_eventService.GetHandler(typeof(IMenuStatusHandler)); + if (msh != null && msh.OverrideInvoke(this)) + { + return; + } + } + base.Invoke(); + } + catch (Exception e) + { + if (_uiService != null) + { + _uiService.ShowError(e, string.Format(SR.CommandSetError, e.Message)); + } + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + } + + /// + /// Only pass this down to the base when we're not doing the cached update. + /// + protected override void OnCommandChanged(EventArgs e) + { + if (!_updatingCommand) + { + base.OnCommandChanged(e); + } + } + + /// + /// Saves the status for this command to the statusstate that's stored in the hashtable based on our status handler delegate. + /// + private void SaveCommandStatus() + { + if (_commandSet != null) + { + StatusState state; + // see if we need to create one of these StatusState dudes. + if (s_commandStatusHash.Contains(_statusHandler)) + { + state = s_commandStatusHash[_statusHandler] as StatusState; + } + else + { + state = new StatusState(); + } + // and save the enabled, visible, checked, and supported state. + state.SaveState(this, _commandSet.SelectionVersion); + } + } + + /// + /// Called when the status of this command should be re-queried. + /// + public void UpdateStatus() + { + // We allow outside parties to override the availability of particular menu commands. + if (_eventService != null) + { + IMenuStatusHandler msh = (IMenuStatusHandler)_eventService.GetHandler(typeof(IMenuStatusHandler)); + if (msh != null && msh.OverrideStatus(this)) + { + return; + } + } + if (_statusHandler != null) + { + // if we need to update our status, call the status handler. otherwise, get the cached status and push it into this command. + if (!CommandStatusValid) + { + try + { + _statusHandler(this, EventArgs.Empty); + SaveCommandStatus(); + } + catch + { + } + } + else + { + ApplyCachedStatus(); + } + } + } + + /// + /// Remove this command item from the static hashtable to avoid leaking this object. + /// + public virtual void Dispose() + { + if (s_commandStatusHash[_statusHandler] is StatusState state) + { + state.refCount--; + if (state.refCount == 0) + { + s_commandStatusHash.Remove(_statusHandler); + } + } + } + + /// + /// This class saves the state for a given command. It keeps track of the results of the last status handler invocation and what "selection version" that happened on. + /// + private class StatusState + { + // these are the command's possible values. + private const int Enabled = 0x01; + private const int Visible = 0x02; + private const int Checked = 0x04; + private const int Supported = 0x08; + private const int NeedsUpdate = 0x10; + private int _selectionVersion = 0; // the version of the selection that this was initialized with. + private int _statusFlags = NeedsUpdate; // our flags. + // Multiple CommandSetItem instances can share a same status handler within a designer host. We use a simple ref count to make sure the CommandSetItem can be properly removed. + internal int refCount = 0; + + /// + /// Just what it says... + /// + public int SelectionVersion + { + get => _selectionVersion; + } + + /// + /// Pushes the state stored in this object into the given command item. + /// + internal void ApplyState(CommandSetItem item) + { + Debug.Assert((_statusFlags & NeedsUpdate) != NeedsUpdate, "Updating item when StatusState is not valid."); + item.Enabled = ((_statusFlags & Enabled) == Enabled); + item.Visible = ((_statusFlags & Visible) == Visible); + item.Checked = ((_statusFlags & Checked) == Checked); + item.Supported = ((_statusFlags & Supported) == Supported); + } + + /// + /// Updates this status object with the state from the given item, and saves teh seletion version. + /// + internal void SaveState(CommandSetItem item, int version) + { + _selectionVersion = version; + _statusFlags = 0; + if (item.Enabled) + { + _statusFlags |= Enabled; + } + if (item.Visible) + { + _statusFlags |= Visible; + } + if (item.Checked) + { + _statusFlags |= Checked; + } + if (item.Supported) + { + _statusFlags |= Supported; + } + } + } + } + + /// + /// The immediate command set item is used for commands that cannot be cached. Commands such as Paste that get outside stimulus cannot be cached by our menu system, so they get an ImmediateCommandSetItem instead of a CommandSetItem. + /// + protected class ImmediateCommandSetItem : CommandSetItem + { + /// + /// Creates a new ImmediateCommandSetItem. + /// + public ImmediateCommandSetItem(CommandSet commandSet, EventHandler statusHandler, EventHandler invokeHandler, CommandID id, IUIService uiService) : base(commandSet, statusHandler, invokeHandler, id, uiService) + { + } + + /// + /// Overrides OleStatus in MenuCommand to invoke our status handler first. + /// + public override int OleStatus + { + get + { + UpdateStatus(); + return base.OleStatus; + } + } + } + + /// + /// Component comparer that compares the left property of a component. + /// + private class ComponentLeftCompare : IComparer + { + public int Compare(object p, object q) + { + PropertyDescriptor pProp = TypeDescriptor.GetProperties(p)["Location"]; + PropertyDescriptor qProp = TypeDescriptor.GetProperties(q)["Location"]; + Point pLoc = (Point)pProp.GetValue(p); + Point qLoc = (Point)qProp.GetValue(q); + //if our lefts are equal, then compare tops + if (pLoc.X == qLoc.X) + { + return pLoc.Y - qLoc.Y; + } + return pLoc.X - qLoc.X; + } + } + + /// + /// Component comparer that compares the top property of a component. + /// + private class ComponentTopCompare : IComparer + { + public int Compare(object p, object q) + { + PropertyDescriptor pProp = TypeDescriptor.GetProperties(p)["Location"]; + PropertyDescriptor qProp = TypeDescriptor.GetProperties(q)["Location"]; + Point pLoc = (Point)pProp.GetValue(p); + Point qLoc = (Point)qProp.GetValue(q); + //if our tops are equal, then compare lefts + if (pLoc.Y == qLoc.Y) + { + return pLoc.X - qLoc.X; + } + return pLoc.Y - qLoc.Y; + } + } + + private class ControlZOrderCompare : IComparer + { + public int Compare(object p, object q) + { + if (p == null) + { + return -1; + } + else if (q == null) + { + return 1; + } + else if (p == q) + { + return 0; + } + if (!(p is Control c1) || !(q is Control c2)) + { + return 1; + } + + if (c1.Parent == c2.Parent && c1.Parent != null) + { + return c1.Parent.Controls.GetChildIndex(c1) - c1.Parent.Controls.GetChildIndex(c2); + } + return 1; + } + } + + private class TabIndexCompare : IComparer + { + public int Compare(object p, object q) + { + Control c1 = p as Control; + Control c2 = q as Control; + if (c1 == c2) + { + return 0; + } + + if (c1 == null) + { + return -1; + } + + if (c2 == null) + { + return 1; + } + return c1.TabIndex - c2.TabIndex; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentActionsType.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentActionsType.cs new file mode 100644 index 00000000000..f97c068f51f --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentActionsType.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + public enum ComponentActionsType + { + All, Component, Service + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentTray.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentTray.cs index 891824abe8d..2e430be0a48 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentTray.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ComponentTray.cs @@ -2,18 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections; using System.ComponentModel; using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Drawing.Design; +using System.Drawing.Drawing2D; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms.Design.Behavior; +using Microsoft.Win32; namespace System.Windows.Forms.Design { /// - /// - /// Provides the component tray UI for the form designer. - /// + /// Provides the component tray UI for the form designer. /// [ToolboxItem(false)] [DesignTimeVisible(false)] @@ -21,202 +27,917 @@ namespace System.Windows.Forms.Design [ProvideProperty("TrayLocation", typeof(IComponent))] public class ComponentTray : ScrollableControl, IExtenderProvider, ISelectionUIHandler, IOleDragClient { + private static readonly Point InvalidPoint = new Point(int.MinValue, int.MinValue); + private IServiceProvider serviceProvider; // Where services come from. + private Point whiteSpace = Point.Empty; // space to leave between components. + private Size grabHandle = Size.Empty; // Size of the grab handles. + + private ArrayList controls; // List of items in the tray in the order of their layout. + private SelectionUIHandler dragHandler; // the thing responsible for handling mouse drags + private ISelectionUIService selectionUISvc; // selectiuon UI; we use this a lot + private IToolboxService toolboxService; // cached for drag/drop + + /// + /// Provides drag and drop functionality through OLE. + /// + internal OleDragDropHandler oleDragDropHandler; // handler class for ole drag drop operations. + + private IDesigner mainDesigner; // the designer that is associated with this tray + private IEventHandlerService eventHandlerService = null; // Event Handler service to handle keyboard and focus. + private bool queriedTabOrder; + private MenuCommand tabOrderCommand; + private ICollection selectedObjects; + + // Services that we use on a high enough frequency to merit caching. + private IMenuCommandService menuCommandService; + private CommandSet privateCommandSet = null; + private InheritanceUI inheritanceUI; + + private Point mouseDragStart = InvalidPoint; // the starting location of a drag + private Point mouseDragEnd = InvalidPoint; // the ending location of a drag + private Rectangle mouseDragWorkspace = Rectangle.Empty; // a temp work rectangle we cache for perf + private ToolboxItem mouseDragTool; // the tool that's being dragged; only for drag/drop + private Point mouseDropLocation = InvalidPoint; // where the tool was dropped + private bool showLargeIcons = false;// Show Large icons or not. + private bool autoArrange = false; // allows for auto arranging icons. + private Point autoScrollPosBeforeDragging = Point.Empty;//Used to return the correct scroll pos. after a drag + + // Component Tray Context menu items... + private MenuCommand menucmdArrangeIcons = null; + private MenuCommand menucmdLineupIcons = null; + private MenuCommand menucmdLargeIcons = null; + private bool fResetAmbient = false; + private bool fSelectionChanged = false; + private ComponentTrayGlyphManager glyphManager;//used to manage any glyphs added to the tray + // Empty class for build time dependancy /// - /// Creates a new component tray. The component tray - /// will monitor component additions and removals and create - /// appropriate UI objects in its space. + /// Creates a new component tray. The component tray + /// will monitor component additions and removals and create + /// appropriate UI objects in its space. /// [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] public ComponentTray(IDesigner mainDesigner, IServiceProvider serviceProvider) { - throw new NotImplementedException(SR.NotImplementedByDesign); + AutoScroll = true; + this.mainDesigner = mainDesigner; + this.serviceProvider = serviceProvider; + AllowDrop = true; + Text = "ComponentTray"; // makes debugging easier + SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true); + controls = new ArrayList(); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + IExtenderProviderService es = (IExtenderProviderService)GetService(typeof(IExtenderProviderService)); + Debug.Assert(es != null, "Component tray wants an extender provider service, but there isn't one."); + if (es != null) + { + es.AddExtenderProvider(this); + } + + if (GetService(typeof(IEventHandlerService)) == null) + { + if (host != null) + { + eventHandlerService = new EventHandlerService(this); + host.AddService(typeof(IEventHandlerService), eventHandlerService); + } + } + + IMenuCommandService mcs = MenuService; + if (mcs != null) + { + Debug.Assert(menucmdArrangeIcons == null, "Non-Null Menu Command for ArrangeIcons"); + Debug.Assert(menucmdLineupIcons == null, "Non-Null Menu Command for LineupIcons"); + Debug.Assert(menucmdLargeIcons == null, "Non-Null Menu Command for LargeIcons"); + menucmdArrangeIcons = new MenuCommand(new EventHandler(OnMenuArrangeIcons), StandardCommands.ArrangeIcons); + menucmdLineupIcons = new MenuCommand(new EventHandler(OnMenuLineupIcons), StandardCommands.LineupIcons); + menucmdLargeIcons = new MenuCommand(new EventHandler(OnMenuShowLargeIcons), StandardCommands.ShowLargeIcons); + menucmdArrangeIcons.Checked = AutoArrange; + menucmdLargeIcons.Checked = ShowLargeIcons; + mcs.AddCommand(menucmdArrangeIcons); + mcs.AddCommand(menucmdLineupIcons); + mcs.AddCommand(menucmdLargeIcons); + } + + IComponentChangeService componentChangeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (componentChangeService != null) + { + componentChangeService.ComponentRemoved += new ComponentEventHandler(OnComponentRemoved); + } + + if (GetService(typeof(IUIService)) is IUIService uiService) + { + Color styleColor; + if (uiService.Styles["ArtboardBackground"] is Color) + { + styleColor = (Color)uiService.Styles["ArtboardBackground"]; + } + //Can't use 'as' here since Color is a value type + else if (uiService.Styles["VsColorDesignerTray"] is Color) + { + styleColor = (Color)uiService.Styles["VsColorDesignerTray"]; + } + else if (uiService.Styles["HighlightColor"] is Color) + { + // Since v1, we have had code here that checks for HighlightColor, so some hosts (like WinRes) have been setting it. If VsColorDesignerTray isn't present, we look for HighlightColor for backward compat. + styleColor = (Color)uiService.Styles["HighlightColor"]; + } + else + { + //No style color provided? Let's pick a default. + styleColor = SystemColors.Info; + } + + if (uiService.Styles["ArtboardBackgroundText"] is Color) + { + ForeColor = (Color)uiService.Styles["ArtboardBackgroundText"]; + } + else if (uiService.Styles["VsColorPanelText"] is Color) + { + ForeColor = (Color)uiService.Styles["VsColorPanelText"]; + } + + BackColor = styleColor; + Font = (Font)uiService.Styles["DialogFont"]; + } + + ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SelectionChanged += new EventHandler(OnSelectionChanged); + } + + // Listen to the SystemEvents so that we can resync selection based on display settings etc. + SystemEvents.DisplaySettingsChanged += new EventHandler(OnSystemSettingChanged); + SystemEvents.InstalledFontsChanged += new EventHandler(OnSystemSettingChanged); + SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(OnUserPreferenceChanged); + + if (GetService(typeof(BehaviorService)) is BehaviorService behSvc) + { + //this object will manage any glyphs that get added to our tray + glyphManager = new ComponentTrayGlyphManager(selSvc, behSvc); + } } - public bool AutoArrange + private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) { - get => throw new NotImplementedException(SR.NotImplementedByDesign); + if (IsHandleCreated) + { + fResetAmbient = true; + ResetTrayControls(); + BeginInvoke(new AsyncInvokeHandler(Invalidate), new object[] { true }); + } + } - set => throw new NotImplementedException(SR.NotImplementedByDesign); + private void OnComponentRefresh(RefreshEventArgs e) + { + if (e.ComponentChanged is IComponent component) + { + TrayControl control = TrayControl.FromComponent(component); + if (control != null) + { + bool shouldDisplay = CanDisplayComponent(component); + if (shouldDisplay != control.Visible || !shouldDisplay) + { + control.Visible = shouldDisplay; + Rectangle bounds = control.Bounds; + bounds.Inflate(grabHandle); + bounds.Inflate(grabHandle); + Invalidate(bounds); + PerformLayout(); + } + } + } } - /// - /// - /// Gets the number of compnents contained within this tray. - /// - /// - public int ComponentCount => throw new NotImplementedException(SR.NotImplementedByDesign); + private void OnSystemSettingChanged(object sender, EventArgs e) + { + if (IsHandleCreated) + { + fResetAmbient = true; + ResetTrayControls(); + BeginInvoke(new AsyncInvokeHandler(Invalidate), new object[] { true }); + } + } - /// - /// Determines whether the tray will show large icon view or not. - /// - public bool ShowLargeIcons + private void ResetTrayControls() { - get => throw new NotImplementedException(SR.NotImplementedByDesign); + ControlCollection children = (ControlCollection)Controls; + if (children == null) + return; - set => throw new NotImplementedException(SR.NotImplementedByDesign); + for (int i = 0; i < children.Count; ++i) + { + if (children[i] is TrayControl tc) + { + tc._fRecompute = true; + } + } } - bool IExtenderProvider.CanExtend(object extendee) + private delegate void AsyncInvokeHandler(bool children); + + private void OnSelectionChanged(object sender, EventArgs e) { - throw new NotImplementedException(); + selectedObjects = ((ISelectionService)sender).GetSelectedComponents(); + object primary = ((ISelectionService)sender).PrimarySelection; + Invalidate(); + fSelectionChanged = true; + // Accessibility information + foreach (object selObj in selectedObjects) + { + if (selObj is IComponent component) + { + Control c = TrayControl.FromComponent(component); + if (c != null) + { + Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "MSAA: SelectionAdd, traycontrol = " + c.ToString()); + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.SelectionAdd, new HandleRef(c, c.Handle), NativeMethods.OBJID_CLIENT, 0); + } + } + } + + if (primary is IComponent comp) + { + Control c = TrayControl.FromComponent(comp); + if (c != null && IsHandleCreated) + { + ScrollControlIntoView(c); + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.Focus, new HandleRef(c, c.Handle), NativeMethods.OBJID_CLIENT, 0); + } + if (glyphManager != null) + { + glyphManager.SelectionGlyphs.Clear(); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + foreach (object selObj in selectedObjects) + { + if (selObj is IComponent selectedComponent && !(host.GetDesigner(selectedComponent) is ControlDesigner)) + { // don't want to do it for controls that are also in the tray + GlyphCollection glyphs = glyphManager.GetGlyphsForComponent(selectedComponent); + if (glyphs != null && glyphs.Count > 0) + { + SelectionGlyphs.AddRange(glyphs); + } + } + } + } + } } - IComponent IOleDragClient.Component => throw new NotImplementedException(); + private void OnComponentRemoved(object sender, ComponentEventArgs cevent) + { + RemoveComponent(cevent.Component); + } - bool IOleDragClient.CanModifyComponents => throw new NotImplementedException(); + private void OnMenuShowLargeIcons(object sender, EventArgs e) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + DesignerTransaction t = null; + try + { + t = host.CreateTransaction(SR.TrayShowLargeIcons); + PropertyDescriptor trayIconProp = TypeDescriptor.GetProperties(mainDesigner.Component)["TrayLargeIcon"]; + if (trayIconProp != null) + { + trayIconProp.SetValue(mainDesigner.Component, !ShowLargeIcons); + } + } + finally + { + if (t != null) + t.Commit(); + } + } - bool IOleDragClient.AddComponent(IComponent component, string name, bool firstAdd) + private void OnMenuLineupIcons(object sender, EventArgs e) { - throw new NotImplementedException(); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + DesignerTransaction t = null; + try + { + t = host.CreateTransaction(SR.TrayLineUpIcons); + DoLineupIcons(); + } + finally + { + if (t != null) + t.Commit(); + } } - bool IOleDragClient.IsDropOk(IComponent component) + private void DoLineupIcons() { - throw new NotImplementedException(); + if (autoArrange) + return; + bool oldValue = autoArrange; + autoArrange = true; + try + { + DoAutoArrange(true); + } + finally + { + autoArrange = oldValue; + } } - Control IOleDragClient.GetDesignerControl() + private void DoAutoArrange(bool dirtyDesigner) { - throw new NotImplementedException(); + if (controls == null || controls.Count <= 0) + { + return; + } + + controls.Sort(new AutoArrangeComparer()); + + SuspendLayout(); + + //Reset the autoscroll position before auto arranging. + //This way, when OnLayout gets fired after this, we won't + //have to move every component again. Note that sync'ing + //the selection will automatically select & scroll into view + //the right components + AutoScrollPosition = new Point(0, 0); + + try + { + Control prevCtl = null; + bool positionedGlobal = true; + foreach (Control ctl in controls) + { + if (!ctl.Visible) + continue; + // If we're auto arranging, always move the control. If not, move the control only if it was never given a position. This auto arranges it until the user messes with it, or until its position is saved into the resx. (if one control is no longer positioned, move all the other one as we don't want them to go under one another) + if (autoArrange) + { + PositionInNextAutoSlot(ctl as TrayControl, prevCtl, dirtyDesigner); + } + else if (!((TrayControl)ctl).Positioned || !positionedGlobal) + { + PositionInNextAutoSlot(ctl as TrayControl, prevCtl, false); + positionedGlobal = false; + } + prevCtl = ctl; + } + if (selectionUISvc != null) + { + selectionUISvc.SyncSelection(); + } + } + finally + { + ResumeLayout(); + } } - Control IOleDragClient.GetControlForComponent(object component) + private void OnMenuArrangeIcons(object sender, EventArgs e) { - throw new NotImplementedException(); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + DesignerTransaction t = null; + + try + { + t = host.CreateTransaction(SR.TrayAutoArrange); + + PropertyDescriptor trayAAProp = TypeDescriptor.GetProperties(mainDesigner.Component)["TrayAutoArrange"]; + if (trayAAProp != null) + { + trayAAProp.SetValue(mainDesigner.Component, !AutoArrange); + } + } + finally + { + if (t != null) + t.Commit(); + } } - bool ISelectionUIHandler.BeginDrag(object[] components, SelectionRules rules, int initialX, int initialY) + public bool AutoArrange { - throw new NotImplementedException(); + get => autoArrange; + set + { + if (autoArrange != value) + { + autoArrange = value; + menucmdArrangeIcons.Checked = value; + + if (autoArrange) + { + DoAutoArrange(true); + } + } + } } - void ISelectionUIHandler.DragMoved(object[] components, Rectangle offset) + /// + /// Gets the number of compnents contained within this tray. + /// + public int ComponentCount { - throw new NotImplementedException(); + get => Controls.Count; } - void ISelectionUIHandler.EndDrag(object[] components, bool cancel) + internal GlyphCollection SelectionGlyphs { - throw new NotImplementedException(); + get + { + if (glyphManager != null) + { + return glyphManager.SelectionGlyphs; + } + else + { + return null; + } + } } - Rectangle ISelectionUIHandler.GetComponentBounds(object component) + /// + /// Determines whether the tray will show large icon view or not. + /// + public bool ShowLargeIcons { - throw new NotImplementedException(); + get => showLargeIcons; + set + { + if (showLargeIcons != value) + { + showLargeIcons = value; + menucmdLargeIcons.Checked = ShowLargeIcons; + + ResetTrayControls(); + Invalidate(true); + } + } } - SelectionRules ISelectionUIHandler.GetComponentRules(object component) + bool IExtenderProvider.CanExtend(object extendee) { - throw new NotImplementedException(); + return (extendee is IComponent comp) && (TrayControl.FromComponent(comp) != null); } - Rectangle ISelectionUIHandler.GetSelectionClipRect(object component) + IComponent IOleDragClient.Component { - throw new NotImplementedException(); + get => mainDesigner.Component; } - void ISelectionUIHandler.OnSelectionDoubleClick(IComponent component) + bool IOleDragClient.CanModifyComponents { - throw new NotImplementedException(); + get => true; } - bool ISelectionUIHandler.QueryBeginDrag(object[] components, SelectionRules rules, int initialX, int initialY) + bool IOleDragClient.AddComponent(IComponent component, string name, bool firstAdd) { - throw new NotImplementedException(); + // the designer for controls decides what to do here + if (mainDesigner is IOleDragClient oleDragClient) + { + try + { + oleDragClient.AddComponent(component, name, firstAdd); + PositionControl(TrayControl.FromComponent(component)); + mouseDropLocation = InvalidPoint; + return true; + } + catch + { + } + } + else + { + // for webforms (98109) just add the component directly to the host + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + try + { + if (host != null && host.Container != null) + { + if (host.Container.Components[name] != null) + { + name = null; + } + host.Container.Add(component, name); + return true; + } + } + catch + { + } + } + Debug.Fail("Don't know how to add component!"); + return false; } - void ISelectionUIHandler.ShowContextMenu(IComponent component) + bool IOleDragClient.IsDropOk(IComponent component) => true; + + Control IOleDragClient.GetDesignerControl() => this; + + Control IOleDragClient.GetControlForComponent(object component) { - throw new NotImplementedException(); + if (component is IComponent comp) + { + return TrayControl.FromComponent(comp); + } + Debug.Fail("component is not IComponent"); + return null; } - void ISelectionUIHandler.OleDragEnter(DragEventArgs de) + bool ISelectionUIHandler.BeginDrag(object[] components, SelectionRules rules, int initialX, int initialY) { - throw new NotImplementedException(); + if (TabOrderActive) + { + return false; + } + bool result = DragHandler.BeginDrag(components, rules, initialX, initialY); + if (result) + { + if (!GetOleDragHandler().DoBeginDrag(components, rules, initialX, initialY)) + { + return false; + } + } + return result; } - void ISelectionUIHandler.OleDragDrop(DragEventArgs de) + internal virtual OleDragDropHandler GetOleDragHandler() { - throw new NotImplementedException(); + if (oleDragDropHandler == null) + { + oleDragDropHandler = new TrayOleDragDropHandler(DragHandler, serviceProvider, this); + } + return oleDragDropHandler; } - void ISelectionUIHandler.OleDragOver(DragEventArgs de) + internal virtual SelectionUIHandler DragHandler { - throw new NotImplementedException(); + get + { + if (dragHandler == null) + { + dragHandler = new TraySelectionUIHandler(this); + } + return dragHandler; + } } - void ISelectionUIHandler.OleDragLeave() + void ISelectionUIHandler.DragMoved(object[] components, Rectangle offset) => DragHandler.DragMoved(components, offset); + + void ISelectionUIHandler.EndDrag(object[] components, bool cancel) { - throw new NotImplementedException(); + DragHandler.EndDrag(components, cancel); + GetOleDragHandler().DoEndDrag(components, cancel); + // Here, after the drag is finished and after we have resumed layout, adjust the location of the components we dragged by the scroll offset + if (!autoScrollPosBeforeDragging.IsEmpty) + { + foreach (IComponent comp in components) + { + TrayControl tc = TrayControl.FromComponent(comp); + if (tc != null) + { + SetTrayLocation(comp, new Point(tc.Location.X - autoScrollPosBeforeDragging.X, tc.Location.Y - autoScrollPosBeforeDragging.Y)); + } + } + AutoScrollPosition = new Point(-autoScrollPosBeforeDragging.X, -autoScrollPosBeforeDragging.Y); + } } + // We render the selection UI glyph ourselves. + Rectangle ISelectionUIHandler.GetComponentBounds(object component) => Rectangle.Empty; + + SelectionRules ISelectionUIHandler.GetComponentRules(object component) => SelectionRules.Visible | SelectionRules.Moveable; + + Rectangle ISelectionUIHandler.GetSelectionClipRect(object component) + { + if (IsHandleCreated) + { + return RectangleToScreen(ClientRectangle); + } + return Rectangle.Empty; + } + + void ISelectionUIHandler.OnSelectionDoubleClick(IComponent component) + { + if (!TabOrderActive) + { + if (((IOleDragClient)this).GetControlForComponent(component) is TrayControl tc) + { + tc.ViewDefaultEvent(component); + } + } + } + + bool ISelectionUIHandler.QueryBeginDrag(object[] components, SelectionRules rules, int initialX, int initialY) => DragHandler.QueryBeginDrag(components, rules, initialX, initialY); + + void ISelectionUIHandler.ShowContextMenu(IComponent component) + { + Point cur = Control.MousePosition; + OnContextMenu(cur.X, cur.Y, true); + } + + private void OnContextMenu(int x, int y, bool useSelection) + { + if (!TabOrderActive) + { + Capture = false; + IMenuCommandService mcs = MenuService; + if (mcs != null) + { + Capture = false; + Cursor.Clip = Rectangle.Empty; + ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService)); + if (useSelection && s != null && !(1 == s.SelectionCount && s.PrimarySelection == mainDesigner.Component)) + { + mcs.ShowContextMenu(MenuCommands.TraySelectionMenu, x, y); + } + else + { + mcs.ShowContextMenu(MenuCommands.ComponentTrayMenu, x, y); + } + } + } + } + + void ISelectionUIHandler.OleDragEnter(DragEventArgs de) => GetOleDragHandler().DoOleDragEnter(de); + + void ISelectionUIHandler.OleDragDrop(DragEventArgs de) => GetOleDragHandler().DoOleDragDrop(de); + + void ISelectionUIHandler.OleDragOver(DragEventArgs de) => GetOleDragHandler().DoOleDragOver(de); + + void ISelectionUIHandler.OleDragLeave() => GetOleDragHandler().DoOleDragLeave(); + /// - /// Adds a component to the tray. + /// Adds a component to the tray. /// public virtual void AddComponent(IComponent component) { - throw new NotImplementedException(SR.NotImplementedByDesign); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + // Ignore components that cannot be added to the tray + if (!CanDisplayComponent(component)) + { + return; + } + // And designate us as the selection UI handler for the control. + if (selectionUISvc == null) + { + selectionUISvc = (ISelectionUIService)GetService(typeof(ISelectionUIService)); + + // If there is no selection service, then we will provide our own. + if (selectionUISvc == null) + { + selectionUISvc = new SelectionUIService(host); + host.AddService(typeof(ISelectionUIService), selectionUISvc); + } + grabHandle = selectionUISvc.GetAdornmentDimensions(AdornmentType.GrabHandle); + } + + // Create a new instance of a tray control. + TrayControl trayctl = new TrayControl(this, component); + SuspendLayout(); + try + { + // Add it to us. + Controls.Add(trayctl); + controls.Add(trayctl); + // CanExtend can actually be called BEFORE the component is added to the ComponentTray. ToolStrip is such as scenario: + // 1. Add a timer to the Tray. + // 2. Add a ToolStrip. + // 3. ToolStripDesigner.Initialize will be called before ComponentTray.AddComponent, so the ToolStrip is not yet added to the tray. + // 4. TooStripDesigner.Initialize calls GetProperties, which causes our CanExtend to be called. + // 5. CanExtend will return false, since the component has not yet been added. + // 6. This causes all sorts of badness + // Fix is to refresh. + TypeDescriptor.Refresh(component); + if (host != null && !host.Loading) + { + PositionControl(trayctl); + } + if (selectionUISvc != null) + { + selectionUISvc.AssignSelectionUIHandler(component, this); + } + InheritanceAttribute attr = trayctl.InheritanceAttribute; + if (attr.InheritanceLevel != InheritanceLevel.NotInherited) + { + InheritanceUI iui = InheritanceUI; + if (iui != null) + { + iui.AddInheritedControl(trayctl, attr.InheritanceLevel); + } + } + } + finally + { + ResumeLayout(); + } + if (host != null && !host.Loading) + { + ScrollControlIntoView(trayctl); + } } [CLSCompliant(false)] protected virtual bool CanCreateComponentFromTool(ToolboxItem tool) { - throw new NotImplementedException(SR.NotImplementedByDesign); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(host != null, "Service object could not provide us with a designer host."); + // Disallow controls to be added to the component tray. + Type compType = host.GetType(tool.TypeName); + if (compType == null) + return true; + if (!compType.IsSubclassOf(typeof(Control))) + { + return true; + } + Type designerType = GetDesignerType(compType, typeof(IDesigner)); + return ! (typeof(ControlDesigner).IsAssignableFrom(designerType)); + } + + private Type GetDesignerType(Type t, Type designerBaseType) + { + Type designerType = null; + // Get the set of attributes for this type + AttributeCollection attributes = TypeDescriptor.GetAttributes(t); + for (int i = 0; i < attributes.Count; i++) + { + if (attributes[i] is DesignerAttribute da) + { + Type attributeBaseType = Type.GetType(da.DesignerBaseTypeName); + if (attributeBaseType != null && attributeBaseType == designerBaseType) + { + bool foundService = false; + ITypeResolutionService tr = (ITypeResolutionService)GetService(typeof(ITypeResolutionService)); + if (tr != null) + { + foundService = true; + designerType = tr.GetType(da.DesignerTypeName); + } + + if (!foundService) + { + designerType = Type.GetType(da.DesignerTypeName); + } + + if (designerType != null) + { + break; + } + } + } + } + return designerType; } /// - /// This method determines if a UI representation for the given component should be provided. - /// If it returns true, then the component will get a glyph in the tray area. If it returns - /// false, then the component will not actually be added to the tray. The default - /// implementation looks for DesignTimeVisibleAttribute.Yes on the component's class. + /// This method determines if a UI representation for the given component should be provided. + /// If it returns true, then the component will get a glyph in the tray area. If it returns + /// false, then the component will not actually be added to the tray. The default + /// implementation looks for DesignTimeVisibleAttribute.Yes on the component's class. /// protected virtual bool CanDisplayComponent(IComponent component) { - throw new NotImplementedException(SR.NotImplementedByDesign); + return TypeDescriptor.GetAttributes(component).Contains(DesignTimeVisibleAttribute.Yes); } [CLSCompliant(false)] public void CreateComponentFromTool(ToolboxItem tool) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (!CanCreateComponentFromTool(tool)) + { + return; + } + // We invoke the drag drop handler for this. This implementation is shared between all designers that create components. + GetOleDragHandler().CreateTool(tool, null, 0, 0, 0, 0, false, false); } /// - /// Displays the given exception to the user. + /// Displays the given exception to the user. /// protected void DisplayError(Exception e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + IUIService uis = (IUIService)GetService(typeof(IUIService)); + if (uis != null) + { + uis.ShowError(e); + } + else + { + string message = e.Message; + if (message == null || message.Length == 0) + { + message = e.ToString(); + } + RTLAwareMessageBox.Show(null, message, null, MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, 0); + } } - // - /// - /// - /// Disposes of the resources (other than memory) used by the component tray object. - /// + /// Disposes of the resources (other than memory) used by the component tray object. /// protected override void Dispose(bool disposing) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (disposing && controls != null) + { + IExtenderProviderService es = (IExtenderProviderService)GetService(typeof(IExtenderProviderService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (es != null), "IExtenderProviderService not found"); + if (es != null) + { + es.RemoveExtenderProvider(this); + } + + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (eventHandlerService != null) + { + if (host != null) + { + host.RemoveService(typeof(IEventHandlerService)); + eventHandlerService = null; + } + } + + IComponentChangeService componentChangeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (componentChangeService != null) + { + componentChangeService.ComponentRemoved -= new ComponentEventHandler(OnComponentRemoved); + } + + SystemEvents.DisplaySettingsChanged -= new EventHandler(OnSystemSettingChanged); + SystemEvents.InstalledFontsChanged -= new EventHandler(OnSystemSettingChanged); + SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(OnUserPreferenceChanged); + IMenuCommandService mcs = MenuService; + if (mcs != null) + { + Debug.Assert(menucmdArrangeIcons != null, "Null Menu Command for ArrangeIcons"); + Debug.Assert(menucmdLineupIcons != null, "Null Menu Command for LineupIcons"); + Debug.Assert(menucmdLargeIcons != null, "Null Menu Command for LargeIcons"); + mcs.RemoveCommand(menucmdArrangeIcons); + mcs.RemoveCommand(menucmdLineupIcons); + mcs.RemoveCommand(menucmdLargeIcons); + } + + if (privateCommandSet != null) + { + privateCommandSet.Dispose(); + // If we created a private command set, we also added a selection ui service to the host + if (host != null) + { + host.RemoveService(typeof(ISelectionUIService)); + } + } + selectionUISvc = null; + + if (inheritanceUI != null) + { + inheritanceUI.Dispose(); + inheritanceUI = null; + } + + serviceProvider = null; + controls.Clear(); + controls = null; + + if (glyphManager != null) + { + glyphManager.Dispose(); + glyphManager = null; + } + } + base.Dispose(disposing); } /// - /// Similar to GetNextControl on Control, this method returns the next - /// component in the tray, given a starting component. It will return - /// null if the end (or beginning, if forward is false) of the list - /// is encountered. + /// Similar to GetNextControl on Control, this method returns the next + /// component in the tray, given a starting component. It will return + /// null if the end (or beginning, if forward is false) of the list + /// is encountered. /// public IComponent GetNextComponent(IComponent component, bool forward) { - throw new NotImplementedException(SR.NotImplementedByDesign); + for (int i = 0; i < controls.Count; i++) + { + TrayControl control = (TrayControl)controls[i]; + if (control.Component == component) + { + int targetIndex = (forward ? i + 1 : i - 1); + if (targetIndex >= 0 && targetIndex < controls.Count) + { + return ((TrayControl)controls[targetIndex]).Component; + } + // Reached the end of the road. + return null; + } + } + // If we got here then the component isn't in our list. Prime the caller with either the first or the last. + if (controls.Count > 0) + { + int targetIndex = (forward ? 0 : controls.Count - 1); + return ((TrayControl)controls[targetIndex]).Component; + } + return null; } /// - /// Accessor method for the location extender property. We offer this extender - /// to all non-visual components. + /// Accessor method for the location extender property. We offer this extender + /// to all non-visual components. /// [Category("Layout")] [Localizable(false)] @@ -227,12 +948,22 @@ public IComponent GetNextComponent(IComponent component, bool forward) [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] public Point GetLocation(IComponent receiver) { - throw new NotImplementedException(SR.NotImplementedByDesign); + PropertyDescriptor loc = TypeDescriptor.GetProperties(receiver.GetType())["Location"]; + if (loc != null) + { + // In this case the component already had a Location property, and what the caller wants is the underlying components Location, not the tray location. Why? Because we now use TrayLocation. + return (Point)(loc.GetValue(receiver)); + } + else + { + // If the component didn't already have a Location property, then the caller really wants the tray location. Could be a 3rd party vendor. + return GetTrayLocation(receiver); + } } /// - /// Accessor method for the location extender property. We offer this extender - /// to all non-visual components. + /// Accessor method for the location extender property. We offer this extender + /// to all non-visual components. /// [Category("Layout")] [Localizable(false)] @@ -241,166 +972,1979 @@ public Point GetLocation(IComponent receiver) [DesignOnly(true)] public Point GetTrayLocation(IComponent receiver) { - throw new NotImplementedException(SR.NotImplementedByDesign); + Control c = TrayControl.FromComponent(receiver); + if (c == null) + { + Debug.Fail("Anything we're extending should have a component view."); + return new Point(); + } + Point loc = c.Location; + Point autoScrollLoc = AutoScrollPosition; + return new Point(loc.X - autoScrollLoc.X, loc.Y - autoScrollLoc.Y); } /// - /// - /// Gets the requsted service type. - /// + /// Gets the requsted service type. /// protected override object GetService(Type serviceType) { - throw new NotImplementedException(SR.NotImplementedByDesign); + object service = null; + Debug.Assert(serviceProvider != null, "Trying to access services too late or too early."); + if (serviceProvider != null) + { + service = serviceProvider.GetService(serviceType); + } + return service; } /// - /// Returns true if the given componenent is being shown on the tray. + /// Returns true if the given componenent is being shown on the tray. /// public bool IsTrayComponent(IComponent comp) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (TrayControl.FromComponent(comp) == null) + { + return false; + } + foreach (Control control in Controls) + { + if (control is TrayControl tc && tc.Component == comp) + { + return true; + } + } + return false; } protected override void OnMouseDoubleClick(MouseEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + //give our glyphs first chance at this + if (glyphManager != null && glyphManager.OnMouseDoubleClick(e)) + { + //handled by a glyph - so don't send to the comp tray + return; + } + base.OnDoubleClick(e); + if (!TabOrderActive) + { + OnLostCapture(); + IEventBindingService eps = (IEventBindingService)GetService(typeof(IEventBindingService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (eps != null), "IEventBindingService not found"); + if (eps != null) + { + eps.ShowCode(); + } + } } /// - /// Inheriting classes should override this method to handle this event. - /// Call base.onGiveFeedback to send this event to any registered event listeners. + /// Inheriting classes should override this method to handle this event. + /// Call base.onGiveFeedback to send this event to any registered event listeners. /// protected override void OnGiveFeedback(GiveFeedbackEventArgs gfevent) { - throw new NotImplementedException(SR.NotImplementedByDesign); + base.OnGiveFeedback(gfevent); + GetOleDragHandler().DoOleGiveFeedback(gfevent); } /// - /// Called in response to a drag drop for OLE drag and drop. Here we - /// drop a toolbox component on our parent control. + /// Called in response to a drag drop for OLE drag and drop. Here we + /// drop a toolbox component on our parent control. /// protected override void OnDragDrop(DragEventArgs de) { - throw new NotImplementedException(SR.NotImplementedByDesign); + // This will be used once during PositionComponent to place the component at the drop point. It is automatically set to null afterwards, so further components appear after the first one dropped. + mouseDropLocation = PointToClient(new Point(de.X, de.Y)); + autoScrollPosBeforeDragging = AutoScrollPosition; // save the scroll position + if (mouseDragTool != null) + { + ToolboxItem tool = mouseDragTool; + mouseDragTool = null; + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (GetService(typeof(IDesignerHost)) != null), "IDesignerHost not found"); + try + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + IDesigner designer = host.GetDesigner(host.RootComponent); + if (designer is IToolboxUser itu) + { + itu.ToolPicked(tool); + } + else + { + CreateComponentFromTool(tool); + } + } + catch (Exception e) + { + DisplayError(e); + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + de.Effect = DragDropEffects.Copy; + } + else + { + GetOleDragHandler().DoOleDragDrop(de); + } + mouseDropLocation = InvalidPoint; + ResumeLayout(); } /// - /// Called in response to a drag enter for OLE drag and drop. + /// Called in response to a drag enter for OLE drag and drop. /// protected override void OnDragEnter(DragEventArgs de) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (!TabOrderActive) + { + SuspendLayout(); + if (toolboxService == null) + { + toolboxService = (IToolboxService)GetService(typeof(IToolboxService)); + } + OleDragDropHandler dragDropHandler = GetOleDragHandler(); + object[] dragComps = dragDropHandler.GetDraggingObjects(de); + // Only assume the items came from the ToolBox if dragComps == null + if (toolboxService != null && dragComps == null) + { + mouseDragTool = toolboxService.DeserializeToolboxItem(de.Data, (IDesignerHost)GetService(typeof(IDesignerHost))); + } + if (mouseDragTool != null) + { + Debug.Assert(0 != (int)(de.AllowedEffect & (DragDropEffects.Move | DragDropEffects.Copy)), "DragDropEffect.Move | .Copy isn't allowed?"); + if ((int)(de.AllowedEffect & DragDropEffects.Move) != 0) + { + de.Effect = DragDropEffects.Move; + } + else + { + de.Effect = DragDropEffects.Copy; + } + } + else + { + dragDropHandler.DoOleDragEnter(de); + } + } } /// - /// Called when a drag-drop operation leaves the control designer view + /// Called when a drag-drop operation leaves the control designer view /// protected override void OnDragLeave(EventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + mouseDragTool = null; + GetOleDragHandler().DoOleDragLeave(); + ResumeLayout(); } /// - /// Called when a drag drop object is dragged over the control designer view + /// Called when a drag drop object is dragged over the control designer view /// protected override void OnDragOver(DragEventArgs de) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (mouseDragTool != null) + { + Debug.Assert(0 != (int)(de.AllowedEffect & DragDropEffects.Copy), "DragDropEffect.Move isn't allowed?"); + de.Effect = DragDropEffects.Copy; + } + else + { + GetOleDragHandler().DoOleDragOver(de); + } } /// /// - /// Forces the layout of any docked or anchored child controls. + /// Forces the layout of any docked or anchored child controls. /// protected override void OnLayout(LayoutEventArgs levent) { - throw new NotImplementedException(SR.NotImplementedByDesign); + DoAutoArrange(false); + // make sure selection service redraws + Invalidate(true); + base.OnLayout(levent); } /// - /// This is called when we lose capture. Here we get rid of any - /// rubber band we were drawing. You should put any cleanup - /// code in here. + /// This is called when we lose capture. Here we get rid of any + /// rubber band we were drawing. You should put any cleanup + /// code in here. /// protected virtual void OnLostCapture() { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (mouseDragStart != InvalidPoint) + { + Cursor.Clip = Rectangle.Empty; + if (mouseDragEnd != InvalidPoint) + { + DrawRubber(mouseDragStart, mouseDragEnd); + mouseDragEnd = InvalidPoint; + } + mouseDragStart = InvalidPoint; + } + } + + private void DrawRubber(Point start, Point end) + { + mouseDragWorkspace.X = Math.Min(start.X, end.X); + mouseDragWorkspace.Y = Math.Min(start.Y, end.Y); + mouseDragWorkspace.Width = Math.Abs(end.X - start.X); + mouseDragWorkspace.Height = Math.Abs(end.Y - start.Y); + mouseDragWorkspace = RectangleToScreen(mouseDragWorkspace); + ControlPaint.DrawReversibleFrame(mouseDragWorkspace, BackColor, FrameStyle.Dashed); } /// - /// Inheriting classes should override this method to handle this event. - /// Call base.onMouseDown to send this event to any registered event listeners. + /// Inheriting classes should override this method to handle this event. + /// Call base.onMouseDown to send this event to any registered event listeners. /// protected override void OnMouseDown(MouseEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + //give our glyphs first chance at this + if (glyphManager != null && glyphManager.OnMouseDown(e)) + { + //handled by a glyph - so don't send to the comp tray + return; + } + + base.OnMouseDown(e); + if (!TabOrderActive) + { + if (toolboxService == null) + { + toolboxService = (IToolboxService)GetService(typeof(IToolboxService)); + } + FocusDesigner(); + if (e.Button == MouseButtons.Left && toolboxService != null) + { + ToolboxItem tool = toolboxService.GetSelectedToolboxItem((IDesignerHost)GetService(typeof(IDesignerHost))); + if (tool != null) + { + // mouseDropLocation is checked in PositionControl, which should get called as a result of adding a new component. This allows us to set the position without flickering, while still providing support for auto layout if the control was double clicked or added through extensibility. + mouseDropLocation = new Point(e.X, e.Y); + try + { + CreateComponentFromTool(tool); + toolboxService.SelectedToolboxItemUsed(); + } + catch (Exception ex) + { + DisplayError(ex); + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + mouseDropLocation = InvalidPoint; + return; + } + } + + // If it is the left button, start a rubber band drag to laso controls. + if (e.Button == MouseButtons.Left) + { + mouseDragStart = new Point(e.X, e.Y); + Capture = true; + Cursor.Clip = RectangleToScreen(ClientRectangle); + } + else + { + try + { + ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (ss != null), "ISelectionService not found"); + if (ss != null) + { + ss.SetSelectedComponents(new object[] { mainDesigner.Component }); + } + } + catch (Exception ex) + { + // nothing we can really do here; just eat it. + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + + } + } } /// - /// Inheriting classes should override this method to handle this event. - /// Call base.onMouseMove to send this event to any registered event listeners. + /// Inheriting classes should override this method to handle this event. + /// Call base.onMouseMove to send this event to any registered event listeners. /// protected override void OnMouseMove(MouseEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + //give our glyphs first chance at this + if (glyphManager != null && glyphManager.OnMouseMove(e)) + { + //handled by a glyph - so don't send to the comp tray + return; + } + base.OnMouseMove(e); + + // If we are dragging, then draw our little rubber band. + if (mouseDragStart != InvalidPoint) + { + if (mouseDragEnd != InvalidPoint) + { + DrawRubber(mouseDragStart, mouseDragEnd); + } + else + { + mouseDragEnd = new Point(0, 0); + } + mouseDragEnd.X = e.X; + mouseDragEnd.Y = e.Y; + DrawRubber(mouseDragStart, mouseDragEnd); + } } /// - /// Inheriting classes should override this method to handle this event. - /// Call base.onMouseUp to send this event to any registered event listeners. + /// Inheriting classes should override this method to handle this event. + /// Call base.onMouseUp to send this event to any registered event listeners. /// protected override void OnMouseUp(MouseEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + //give our glyphs first chance at this + if (glyphManager != null && glyphManager.OnMouseUp(e)) + { + //handled by a glyph - so don't send to the comp tray + return; + } + + if (mouseDragStart != InvalidPoint && e.Button == MouseButtons.Left) + { + object[] comps; + Capture = false; + Cursor.Clip = Rectangle.Empty; + if (mouseDragEnd != InvalidPoint) + { + DrawRubber(mouseDragStart, mouseDragEnd); + Rectangle rect = new Rectangle + { + X = Math.Min(mouseDragStart.X, e.X), + Y = Math.Min(mouseDragStart.Y, e.Y), + Width = Math.Abs(e.X - mouseDragStart.X), + Height = Math.Abs(e.Y - mouseDragStart.Y) + }; + comps = GetComponentsInRect(rect); + mouseDragEnd = InvalidPoint; + } + else + { + comps = new object[0]; + } + + if (comps.Length == 0) + { + comps = new object[] { mainDesigner.Component }; + } + try + { + ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (ss != null), "ISelectionService not found"); + if (ss != null) + { + ss.SetSelectedComponents(comps); + } + } + catch (Exception ex) + { + // nothing we can really do here; just eat it. + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + mouseDragStart = InvalidPoint; + } + base.OnMouseUp(e); + } + + private object[] GetComponentsInRect(Rectangle rect) + { + ArrayList list = new ArrayList(); + int controlCount = Controls.Count; + for (int i = 0; i < controlCount; i++) + { + Control child = Controls[i]; + Rectangle bounds = child.Bounds; + if (child is TrayControl tc && bounds.IntersectsWith(rect)) + { + list.Add(tc.Component); + } + } + return list.ToArray(); } protected override void OnPaint(PaintEventArgs pe) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (fResetAmbient || fSelectionChanged) + { + fResetAmbient = false; + fSelectionChanged = false; + IUIService uiService = (IUIService)GetService(typeof(IUIService)); + if (uiService != null) + { + Color styleColor; + if (uiService.Styles["ArtboardBackground"] is Color) + { + styleColor = (Color)uiService.Styles["ArtboardBackground"]; + } + //Can't use 'as' here since Color is a value type + else if (uiService.Styles["VsColorDesignerTray"] is Color) + { + styleColor = (Color)uiService.Styles["VsColorDesignerTray"]; + } + else if (uiService.Styles["HighlightColor"] is Color) + { + // Since v1, we have had code here that checks for HighlightColor, so some hosts (like WinRes) have been setting it. If VsColorDesignerTray isn't present, we look for HighlightColor for backward compat. + styleColor = (Color)uiService.Styles["HighlightColor"]; + } + else + { + //No style color provided? Let's pick a default. + styleColor = SystemColors.Info; + } + + BackColor = styleColor; + Font = (Font)uiService.Styles["DialogFont"]; + foreach (Control ctl in controls) + { + ctl.BackColor = styleColor; + ctl.ForeColor = ForeColor; + } + } + } + + base.OnPaint(pe); + Graphics gr = pe.Graphics; + // Now, if we have a selection, paint it + if (selectedObjects != null) + { + bool first = true;//indicates the first iteration of our foreach loop + HatchBrush selectionBorderBrush; + if (SystemInformation.HighContrast) + { + selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.HighlightText, Color.Transparent); + } + else + { + selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.ControlDarkDark, Color.Transparent); + } + + try + { + foreach (object o in selectedObjects) + { + Control c = ((IOleDragClient)this).GetControlForComponent(o); + if (c != null && c.Visible) + { + Rectangle innerRect = c.Bounds; + if (SystemInformation.HighContrast) + { + c.ForeColor = SystemColors.HighlightText; + c.BackColor = SystemColors.Highlight; + } + NoResizeHandleGlyph glyph = new NoResizeHandleGlyph(innerRect, SelectionRules.None, first, null); + gr.FillRectangle(selectionBorderBrush, DesignerUtils.GetBoundsForNoResizeSelectionType(innerRect, SelectionBorderGlyphType.Top)); + gr.FillRectangle(selectionBorderBrush, DesignerUtils.GetBoundsForNoResizeSelectionType(innerRect, SelectionBorderGlyphType.Bottom)); + gr.FillRectangle(selectionBorderBrush, DesignerUtils.GetBoundsForNoResizeSelectionType(innerRect, SelectionBorderGlyphType.Left)); + gr.FillRectangle(selectionBorderBrush, DesignerUtils.GetBoundsForNoResizeSelectionType(innerRect, SelectionBorderGlyphType.Right)); + // Need to draw this one last + DesignerUtils.DrawNoResizeHandle(gr, glyph.Bounds, first, glyph); + } + first = false; + } + } + finally + { + if (selectionBorderBrush != null) + { + selectionBorderBrush.Dispose(); + } + } + } + //paint any glyphs + if (glyphManager != null) + { + glyphManager.OnPaintGlyphs(pe); + } } /// - /// Sets the cursor. You may override this to set your own - /// cursor. + /// Sets the cursor. You may override this to set your own + /// cursor. /// protected virtual void OnSetCursor() { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (toolboxService == null) + { + toolboxService = (IToolboxService)GetService(typeof(IToolboxService)); + } + if (toolboxService == null || !toolboxService.SetCursor()) + { + Cursor.Current = Cursors.Default; + } } /// - /// Removes a component from the tray. + /// Removes a component from the tray. /// public virtual void RemoveComponent(IComponent component) { - throw new NotImplementedException(SR.NotImplementedByDesign); + TrayControl c = TrayControl.FromComponent(component); + if (c != null) + { + try + { + InheritanceAttribute attr = c.InheritanceAttribute; + if (attr.InheritanceLevel != InheritanceLevel.NotInherited && inheritanceUI != null) + { + inheritanceUI.RemoveInheritedControl(c); + } + if (controls != null) + { + int index = controls.IndexOf(c); + if (index != -1) + controls.RemoveAt(index); + } + } + finally + { + c.Dispose(); + } + } } /// - /// Accessor method for the location extender property. We offer this extender - /// to all non-visual components. + /// Accessor method for the location extender property. We offer this extender + /// to all non-visual components. /// public void SetLocation(IComponent receiver, Point location) { - throw new NotImplementedException(SR.NotImplementedByDesign); + // This really should only be called when we are loading. + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && host.Loading) + { + // If we are loading, and we get called here, that's because we have provided the extended Location property. In this case we are loading an old project, and what we are really setting is the tray location. + SetTrayLocation(receiver, location); + } + else + { + // we are not loading + PropertyDescriptor loc = TypeDescriptor.GetProperties(receiver.GetType())["Location"]; + if (loc != null) + { + // so if the component already had the Location property, what the caller wants is really the underlying component's Location property. + loc.SetValue(receiver, location); + } + else + { + // if the component didn't have a Location property, then the caller really wanted the tray location. + SetTrayLocation(receiver, location); + } + } } /// - /// Accessor method for the location extender property. We offer this extender - /// to all non-visual components. + /// Accessor method for the location extender property. We offer this extender + /// to all non-visual components. /// public void SetTrayLocation(IComponent receiver, Point location) { - throw new NotImplementedException(SR.NotImplementedByDesign); + TrayControl c = TrayControl.FromComponent(receiver); + if (c == null) + { + Debug.Fail("Anything we're extending should have a component view."); + return; + } + if (c.Parent == this) + { + Point autoScrollLoc = AutoScrollPosition; + location = new Point(location.X + autoScrollLoc.X, location.Y + autoScrollLoc.Y); + if (c.Visible) + { + RearrangeInAutoSlots(c, location); + } + } + else if (!c.Location.Equals(location)) + { + c.Location = location; + c.Positioned = true; + } } /// - /// We override our base class's WndProc to monitor certain messages. + /// We override our base class's WndProc to monitor certain messages. /// protected override void WndProc(ref Message m) { - throw new NotImplementedException(SR.NotImplementedByDesign); + switch (m.Msg) + { + case Interop.WindowMessages.WM_CANCELMODE: + // When we get cancelmode (i.e. you tabbed away to another window) then we want to cancel any pending drag operation! + OnLostCapture(); + break; + case Interop.WindowMessages.WM_SETCURSOR: + OnSetCursor(); + return; + case Interop.WindowMessages.WM_HSCROLL: + case Interop.WindowMessages.WM_VSCROLL: + // When we scroll, we reposition a control without causing a property change event. Therefore, we must tell the selection UI service to sync itself. + base.WndProc(ref m); + if (selectionUISvc != null) + { + selectionUISvc.SyncSelection(); + } + return; + case Interop.WindowMessages.WM_STYLECHANGED: + // When the scroll bars first appear, we need to invalidate so we properly paint our grid. + Invalidate(); + break; + case Interop.WindowMessages.WM_CONTEXTMENU: + // Pop a context menu for the composition designer. + int x = NativeMethods.Util.SignedLOWORD(unchecked((int)(long)m.LParam)); + int y = NativeMethods.Util.SignedHIWORD(unchecked((int)(long)m.LParam)); + if (x == -1 && y == -1) + { + // for shift-F10 + Point mouse = Control.MousePosition; + x = mouse.X; + y = mouse.Y; + } + OnContextMenu(x, y, true); + break; + case Interop.WindowMessages.WM_NCHITTEST: + if (glyphManager != null) + { + // Get a hit test on any glyhs that we are managing this way - we know where to route appropriate messages + Point pt = new Point((short)NativeMethods.Util.LOWORD(unchecked((int)(long)m.LParam)), (short)NativeMethods.Util.HIWORD(unchecked((int)(long)m.LParam))); + NativeMethods.POINT pt1 = new NativeMethods.POINT + { + x = 0, + y = 0 + }; + NativeMethods.MapWindowPoints(IntPtr.Zero, Handle, pt1, 1); + pt.Offset(pt1.x, pt1.y); + glyphManager.GetHitTest(pt); + } + base.WndProc(ref m); + break; + default: + base.WndProc(ref m); + break; + } + } + + internal TrayControl GetTrayControlFromComponent(IComponent comp) + { + return TrayControl.FromComponent(comp); + } + + private bool TabOrderActive + { + get + { + if (!queriedTabOrder) + { + queriedTabOrder = true; + IMenuCommandService mcs = MenuService; + if (mcs != null) + { + tabOrderCommand = mcs.FindCommand(MenuCommands.TabOrder); + } + } + if (tabOrderCommand != null) + { + return tabOrderCommand.Checked; + } + return false; + } + } + + private InheritanceUI InheritanceUI + { + get + { + if (inheritanceUI == null) + { + inheritanceUI = new InheritanceUI(); + } + return inheritanceUI; + } + } + + private IMenuCommandService MenuService + { + get + { + if (menuCommandService == null) + { + menuCommandService = (IMenuCommandService)GetService(typeof(IMenuCommandService)); + } + return menuCommandService; + } + } + + internal void FocusDesigner() + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && host.RootComponent != null) + { + if (host.GetDesigner(host.RootComponent) is IRootDesigner rd) + { + ViewTechnology[] techs = rd.SupportedTechnologies; + if (techs.Length > 0) + { + if (rd.GetView(techs[0]) is Control view) + { + view.Focus(); + } + } + } + } + } + + internal Size ParentGridSize + { + get + { + if (mainDesigner is ParentControlDesigner designer) + { + return designer.ParentGridSize; + } + + return new Size(8, 8); + } + } + + internal void UpdatePastePositions(ArrayList components) + { + foreach (TrayControl c in components) + { + if (!CanDisplayComponent(c.Component)) + { + return; + } + + if (mouseDropLocation == InvalidPoint) + { + Control prevCtl = null; + if (controls.Count > 1) + { + prevCtl = (Control)controls[controls.Count - 1]; + } + PositionInNextAutoSlot(c, prevCtl, true); + } + else + { + PositionControl(c); + } + c.BringToFront(); + } + } + + private void PositionControl(TrayControl c) + { + Debug.Assert(c.Visible, "TrayControl for " + c.Component + " should not be positioned"); + if (!autoArrange) + { + if (mouseDropLocation != InvalidPoint) + { + if (!c.Location.Equals(mouseDropLocation)) + c.Location = mouseDropLocation; + } + else + { + Control prevCtl = null; + if (controls.Count > 1) + { + // PositionControl can be called when all the controls have been added (from IOleDragClient.AddComponent), so we can't use the old way of looking up the previous control (prevCtl = controls[controls.Count - 2] + int index = controls.IndexOf(c); + Debug.Assert(index >= 1, "Got the wrong index, how could that be?"); + if (index >= 1) + { + prevCtl = (Control)controls[index - 1]; + } + } + PositionInNextAutoSlot(c, prevCtl, true); + } + } + else + { + if (mouseDropLocation != InvalidPoint) + { + RearrangeInAutoSlots(c, mouseDropLocation); + } + else + { + Control prevCtl = null; + if (controls.Count > 1) + { + int index = controls.IndexOf(c); + Debug.Assert(index >= 1, "Got the wrong index, how could that be?"); + if (index >= 1) + { + prevCtl = (Control)controls[index - 1]; + } + } + PositionInNextAutoSlot(c, prevCtl, true); + } + } + } + + internal void RearrangeInAutoSlots(Control c, Point pos) + { +#if DEBUG + int index = controls.IndexOf(c); + Debug.Assert(index != -1, "Add control to the list of controls before autoarranging.!!!"); + Debug.Assert(Visible == c.Visible, "TrayControl for " + ((TrayControl)c).Component + " should not be positioned"); +#endif + TrayControl tc = (TrayControl)c; + tc.Positioned = true; + tc.Location = pos; + } + + private bool PositionInNextAutoSlot(TrayControl c, Control prevCtl, bool dirtyDesigner) + { + Debug.Assert(c.Visible, "TrayControl for " + c.Component + " should not be positioned"); + if (whiteSpace.IsEmpty) + { + Debug.Assert(selectionUISvc != null, "No SelectionUIService available for tray."); + whiteSpace = new Point(selectionUISvc.GetAdornmentDimensions(AdornmentType.GrabHandle)); + whiteSpace.X = whiteSpace.X * 2 + 3; + whiteSpace.Y = whiteSpace.Y * 2 + 3; + } + + if (prevCtl == null) + { + Rectangle display = DisplayRectangle; + Point newLoc = new Point(display.X + whiteSpace.X, display.Y + whiteSpace.Y); + if (!c.Location.Equals(newLoc)) + { + c.Location = newLoc; + if (dirtyDesigner) + { + IComponent comp = c.Component; + Debug.Assert(comp != null, "Component for the TrayControl is null"); + PropertyDescriptor ctlLocation = TypeDescriptor.GetProperties(comp)["TrayLocation"]; + if (ctlLocation != null) + { + Point autoScrollLoc = AutoScrollPosition; + newLoc = new Point(newLoc.X - autoScrollLoc.X, newLoc.Y - autoScrollLoc.Y); + ctlLocation.SetValue(comp, newLoc); + } + } + else + { + c.Location = newLoc; + } + return true; + } + } + else + { + // Calcuate the next location for this control. + Rectangle bounds = prevCtl.Bounds; + Point newLoc = new Point(bounds.X + bounds.Width + whiteSpace.X, bounds.Y); + + // Check to see if it goes over the edge of our window. If it does, then wrap it. + if (newLoc.X + c.Size.Width > Size.Width) + { + newLoc.X = whiteSpace.X; + newLoc.Y += bounds.Height + whiteSpace.Y; + } + + if (!c.Location.Equals(newLoc)) + { + if (dirtyDesigner) + { + IComponent comp = c.Component; + Debug.Assert(comp != null, "Component for the TrayControl is null"); + PropertyDescriptor ctlLocation = TypeDescriptor.GetProperties(comp)["TrayLocation"]; + if (ctlLocation != null) + { + Point autoScrollLoc = AutoScrollPosition; + newLoc = new Point(newLoc.X - autoScrollLoc.X, newLoc.Y - autoScrollLoc.Y); + ctlLocation.SetValue(comp, newLoc); + } + } + else + { + c.Location = newLoc; + } + return true; + } + } + return false; + } + + internal class TrayControl : Control + { + // Values that define this tray control + private readonly IComponent _component; // the component this control is representing + private Image _toolboxBitmap; // the bitmap used to represent the component + private int _cxIcon; // the dimensions of the bitmap + private int _cyIcon; // the dimensions of the bitmap + private readonly InheritanceAttribute _inheritanceAttribute; + + // Services that we use often enough to cache. + private readonly ComponentTray _tray; + // transient values that are used during mouse drags + private Point _mouseDragLast = InvalidPoint; // the last position of the mouse during a drag. + private bool _mouseDragMoved; // has the mouse been moved during this drag? + private bool _ctrlSelect = false; // was the ctrl key down on the mouse down? + private bool _positioned = false; // Have we given this control an explicit location yet? + private const int WhiteSpace = 5; + private readonly int _borderWidth; + internal bool _fRecompute = false; // This flag tells the TrayControl that it needs to retrieve the font and the background color before painting. + + /// + /// Creates a new TrayControl based on the component. + /// + public TrayControl(ComponentTray tray, IComponent component) + { + _tray = tray; + _component = component; + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + SetStyle(ControlStyles.Selectable, false); + _borderWidth = SystemInformation.BorderSize.Width; + UpdateIconInfo(); + + IComponentChangeService cs = (IComponentChangeService)tray.GetService(typeof(IComponentChangeService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (cs != null), "IComponentChangeService not found"); + if (cs != null) + { + cs.ComponentRename += new ComponentRenameEventHandler(OnComponentRename); + } + + ISite site = component.Site; + string name = null; + + if (site != null) + { + name = site.Name; + IDictionaryService ds = (IDictionaryService)site.GetService(typeof(IDictionaryService)); + Debug.Assert(ds != null, "ComponentTray relies on IDictionaryService, which is not available."); + if (ds != null) + { + ds.SetValue(GetType(), this); + } + } + + if (name == null) + { + // We always want name to have something in it, so we default to the class name. This way the design instance contains something semi-intuitive if we don't have a site. + name = component.GetType().Name; + } + Text = name; + _inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(component)[typeof(InheritanceAttribute)]; + TabStop = false; + + + } + + /// + /// Retrieves the compnent this control is representing. + /// + public IComponent Component + { + get => _component; + } + + public override Font Font + { + get => _tray.Font; + } + + public InheritanceAttribute InheritanceAttribute + { + get => _inheritanceAttribute; + } + + public bool Positioned + { + get => _positioned; + set => _positioned = value; + } + + /// + /// Adjusts the size of the control based on the contents. + /// + // CONSIDER: this method gets called three or four times per component, and is even reentrant (CreateGraphics can force handle creation, and OnCreateHandle calls this method). There's probably a better way to do this, but since this doesn't seem to be on the critical path, I'm not going to lose sleep over it. + private void AdjustSize() + { + // CONSIDER: this forces handle creation. Can we delay this calculation? + Graphics gr = CreateGraphics(); + try + { + Size sz = Size.Ceiling(gr.MeasureString(Text, Font)); + + Rectangle rc = Bounds; + + if (_tray.ShowLargeIcons) + { + rc.Width = Math.Max(_cxIcon, sz.Width) + 4 * _borderWidth + 2 * WhiteSpace; + rc.Height = _cyIcon + 2 * WhiteSpace + sz.Height + 4 * _borderWidth; + } + else + { + rc.Width = _cxIcon + sz.Width + 4 * _borderWidth + 2 * WhiteSpace; + rc.Height = Math.Max(_cyIcon, sz.Height) + 4 * _borderWidth; + } + + Bounds = rc; + Invalidate(); + } + + finally + { + if (gr != null) + { + gr.Dispose(); + } + } + + if (_tray.glyphManager != null) + { + _tray.glyphManager.UpdateLocation(this); + } + } + + protected override AccessibleObject CreateAccessibilityInstance() => new TrayControlAccessibleObject(this, _tray); + + /// + /// Destroys this control. Views automatically destroy themselves when they are removed from the design container. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + ISite site = _component.Site; + if (site != null) + { + IComponentChangeService cs = (IComponentChangeService)site.GetService(typeof(IComponentChangeService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (cs != null), "IComponentChangeService not found"); + if (cs != null) + { + cs.ComponentRename -= new ComponentRenameEventHandler(OnComponentRename); + } + + IDictionaryService ds = (IDictionaryService)site.GetService(typeof(IDictionaryService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (ds != null), "IDictionaryService not found"); + if (ds != null) + { + ds.SetValue(typeof(TrayControl), null); + } + } + } + base.Dispose(disposing); + } + + /// + /// Retrieves the tray control object for the given component. + /// + public static TrayControl FromComponent(IComponent component) + { + TrayControl c = null; + if (component == null) + { + return null; + } + + ISite site = component.Site; + if (site != null) + { + IDictionaryService ds = (IDictionaryService)site.GetService(typeof(IDictionaryService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (ds != null), "IDictionaryService not found"); + if (ds != null) + { + c = (TrayControl)ds.GetValue(typeof(TrayControl)); + } + } + return c; + } + + /// + /// Delegate that is called in response to a name change. Here we update our own stashed version of the name, recalcuate our size and repaint. + /// + private void OnComponentRename(object sender, ComponentRenameEventArgs e) + { + if (e.Component == _component) + { + Text = e.NewName; + AdjustSize(); + } + } + + /// + /// Overrides handle creation notification for a control. Here we just ensure that we're the proper size. + /// + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + AdjustSize(); + } + + /// + /// Called in response to a double-click of the left mouse button. The default behavior here calls onDoubleClick on IMouseHandler + /// + protected override void OnDoubleClick(EventArgs e) + { + base.OnDoubleClick(e); + if (!_tray.TabOrderActive) + { + IDesignerHost host = (IDesignerHost)_tray.GetService(typeof(IDesignerHost)); + Debug.Assert(host != null, "Component tray does not have access to designer host."); + if (host != null) + { + _mouseDragLast = InvalidPoint; + Capture = false; + // We try to get a designer for the component and let it view the event. If this fails, then we'll try to do it ourselves. + IDesigner designer = host.GetDesigner(_component); + if (designer == null) + { + ViewDefaultEvent(_component); + } + else + { + designer.DoDefaultAction(); + } + } + } + } + + /// + /// Terminates our drag operation. + /// + private void OnEndDrag(bool cancel) + { + _mouseDragLast = InvalidPoint; + if (!_mouseDragMoved) + { + if (_ctrlSelect) + { + ISelectionService sel = (ISelectionService)_tray.GetService(typeof(ISelectionService)); + if (sel != null) + { + sel.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary); + } + _ctrlSelect = false; + } + return; + } + _mouseDragMoved = false; + _ctrlSelect = false; + Capture = false; + OnSetCursor(); + + // And now finish the drag. + Debug.Assert(_tray.selectionUISvc != null, "We shouldn't be able to begin a drag without this"); + if (_tray.selectionUISvc != null && _tray.selectionUISvc.Dragging) + { + _tray.selectionUISvc.EndDrag(cancel); + } + } + + /// + /// Called when the mouse button is pressed down. Here, we provide drag support for the component. + /// + protected override void OnMouseDown(MouseEventArgs me) + { + base.OnMouseDown(me); + if (!_tray.TabOrderActive) + { + _tray.FocusDesigner(); + // If this is the left mouse button, then begin a drag. + if (me.Button == MouseButtons.Left) + { + Capture = true; + _mouseDragLast = PointToScreen(new Point(me.X, me.Y)); + // If the CTRL key isn't down, select this component, otherwise, we wait until the mouse up. Make sure the component is selected + _ctrlSelect = NativeMethods.GetKeyState((int)Keys.ControlKey) != 0; + if (!_ctrlSelect) + { + ISelectionService sel = (ISelectionService)_tray.GetService(typeof(ISelectionService)); + // Make sure the component is selected + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (sel != null), "ISelectionService not found"); + if (sel != null) + { + sel.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary); + } + } + } + } + } + + /// + /// Called when the mouse is moved over the component. We update our drag information here if we're dragging the component around. + /// + protected override void OnMouseMove(MouseEventArgs me) + { + base.OnMouseMove(me); + if (_mouseDragLast == InvalidPoint) + { + return; + } + + if (!_mouseDragMoved) + { + Size minDrag = SystemInformation.DragSize; + Size minDblClick = SystemInformation.DoubleClickSize; + minDrag.Width = Math.Max(minDrag.Width, minDblClick.Width); + minDrag.Height = Math.Max(minDrag.Height, minDblClick.Height); + // we have to make sure the mouse moved farther than the minimum drag distance before we actually start the drag + Point newPt = PointToScreen(new Point(me.X, me.Y)); + if (_mouseDragLast == InvalidPoint || + (Math.Abs(_mouseDragLast.X - newPt.X) < minDrag.Width && + Math.Abs(_mouseDragLast.Y - newPt.Y) < minDrag.Height)) + { + return; + } + else + { + _mouseDragMoved = true; + // we're on the move, so we're not in a ctrlSelect + _ctrlSelect = false; + } + } + + try + { + // Make sure the component is selected + ISelectionService sel = (ISelectionService)_tray.GetService(typeof(ISelectionService)); + if (sel != null) + { + sel.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary); + } + + // Notify the selection service that all the components are in the "mouse down" mode. + if (_tray.selectionUISvc != null && _tray.selectionUISvc.BeginDrag(SelectionRules.Visible | SelectionRules.Moveable, _mouseDragLast.X, _mouseDragLast.Y)) + { + OnSetCursor(); + } + } + finally + { + _mouseDragMoved = false; + _mouseDragLast = InvalidPoint; + } + } + + /// + /// Called when the mouse button is released. Here, we finish our drag if one was started. + /// + protected override void OnMouseUp(MouseEventArgs me) + { + base.OnMouseUp(me); + OnEndDrag(false); + } + + /// + /// Called when we are to display our context menu for this component. + /// + private void OnContextMenu(int x, int y) + { + if (!_tray.TabOrderActive) + { + Capture = false; + // Ensure that this component is selected. + ISelectionService s = (ISelectionService)_tray.GetService(typeof(ISelectionService)); + if (s != null && !s.GetComponentSelected(_component)) + { + s.SetSelectedComponents(new object[] { _component }, SelectionTypes.Replace); + } + IMenuCommandService mcs = _tray.MenuService; + if (mcs != null) + { + Capture = false; + Cursor.Clip = Rectangle.Empty; + mcs.ShowContextMenu(MenuCommands.TraySelectionMenu, x, y); + } + } + } + + /// + /// Painting for our control. + /// + protected override void OnPaint(PaintEventArgs e) + { + if (_fRecompute) + { + _fRecompute = false; + UpdateIconInfo(); + } + base.OnPaint(e); + Rectangle rc = ClientRectangle; + rc.X += WhiteSpace + _borderWidth; + rc.Y += _borderWidth; + rc.Width -= (2 * _borderWidth + WhiteSpace); + rc.Height -= 2 * _borderWidth; + StringFormat format = new StringFormat(); + Brush foreBrush = new SolidBrush(ForeColor); + try + { + format.Alignment = StringAlignment.Center; + if (_tray.ShowLargeIcons) + { + if (null != _toolboxBitmap) + { + int x = rc.X + (rc.Width - _cxIcon) / 2; + int y = rc.Y + WhiteSpace; + e.Graphics.DrawImage(_toolboxBitmap, new Rectangle(x, y, _cxIcon, _cyIcon)); + } + + rc.Y += (_cyIcon + WhiteSpace); + rc.Height -= _cyIcon; + e.Graphics.DrawString(Text, Font, foreBrush, rc, format); + } + else + { + if (null != _toolboxBitmap) + { + int y = rc.Y + (rc.Height - _cyIcon) / 2; + e.Graphics.DrawImage(_toolboxBitmap, new Rectangle(rc.X, y, _cxIcon, _cyIcon)); + } + rc.X += (_cxIcon + _borderWidth); + rc.Width -= _cxIcon; + rc.Y += 3; + e.Graphics.DrawString(Text, Font, foreBrush, rc); + } + } + + finally + { + if (format != null) + { + format.Dispose(); + } + if (foreBrush != null) + { + foreBrush.Dispose(); + } + } + + // If this component is being inherited, paint it as such + if (!InheritanceAttribute.NotInherited.Equals(_inheritanceAttribute)) + { + InheritanceUI iui = _tray.InheritanceUI; + if (iui != null) + { + e.Graphics.DrawImage(iui.InheritanceGlyph, 0, 0); + } + } + } + + /// + /// Overrides control's FontChanged. Here we re-adjust our size if the font changes. + /// + protected override void OnFontChanged(EventArgs e) + { + AdjustSize(); + base.OnFontChanged(e); + } + + /// + /// Overrides control's LocationChanged. Here, we make sure that any glyphs associated with us are also relocated. + /// + protected override void OnLocationChanged(EventArgs e) + { + if (_tray.glyphManager != null) + { + _tray.glyphManager.UpdateLocation(this); + } + } + + /// + /// Overrides control's TextChanged. Here we re-adjust our size if the font changes. + /// + protected override void OnTextChanged(EventArgs e) + { + AdjustSize(); + base.OnTextChanged(e); + } + + /// + /// Called each time the cursor needs to be set. The ControlDesigner behavior here will set the cursor to one of three things: + /// 1. If the selection UI service shows a locked selection, or if there is no location property on the control, then the default arrow will be set. + /// 2. Otherwise, the four headed arrow will be set to indicate that the component can be clicked and moved. + /// 3. If the user is currently dragging a component, the crosshair cursor will be used instead of the four headed arrow. + /// + private void OnSetCursor() + { + // Check that the component is not locked. + PropertyDescriptor prop; + try + { + prop = TypeDescriptor.GetProperties(_component)["Locked"]; + } + catch (FileNotFoundException e) + { + // In case an unhandled exception was encountered, we don't want to leave the cursor with some strange shape Currently we have watson logs with FileNotFoundException only, so we are scoping the catch only to that type. + Cursor.Current = Cursors.Default; + Debug.Fail(e.Message); + return; + } + + if (prop != null && ((bool)prop.GetValue(_component)) == true) + { + Cursor.Current = Cursors.Default; + return; + } + + // Ask the tray to see if the tab order UI is not running. + if (_tray.TabOrderActive) + { + Cursor.Current = Cursors.Default; + return; + } + + if (_mouseDragMoved) + { + Cursor.Current = Cursors.Default; + } + else if (_mouseDragLast != InvalidPoint) + { + Cursor.Current = Cursors.Cross; + } + else + { + Cursor.Current = Cursors.SizeAll; + } + } + + protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) + { + if (!_tray.AutoArrange || + (specified & BoundsSpecified.Width) == BoundsSpecified.Width || + (specified & BoundsSpecified.Height) == BoundsSpecified.Height) + { + + base.SetBoundsCore(x, y, width, height, specified); + } + Rectangle bounds = Bounds; + Size parentGridSize = _tray.ParentGridSize; + if (Math.Abs(bounds.X - x) > parentGridSize.Width || Math.Abs(bounds.Y - y) > parentGridSize.Height) + { + base.SetBoundsCore(x, y, width, height, specified); + } + + } + + protected override void SetVisibleCore(bool value) + { + if (value && !_tray.CanDisplayComponent(_component)) + return; + base.SetVisibleCore(value); + } + + public override string ToString() => "ComponentTray: " + _component.ToString(); + + internal void UpdateIconInfo() + { + ToolboxBitmapAttribute attr = (ToolboxBitmapAttribute)TypeDescriptor.GetAttributes(_component)[typeof(ToolboxBitmapAttribute)]; + if (attr != null) + { + _toolboxBitmap = attr.GetImage(_component, _tray.ShowLargeIcons); + } + + // Get the size of the bitmap so we can size our component correctly. + if (null == _toolboxBitmap) + { + _cxIcon = 0; + _cyIcon = SystemInformation.IconSize.Height; + } + else + { + Size sz = _toolboxBitmap.Size; + _cxIcon = sz.Width; + _cyIcon = sz.Height; + } + AdjustSize(); + } + + /// + /// This creates a method signature in the source code file for the default event on the component and navigates the user's cursor to that location. + /// + public virtual void ViewDefaultEvent(IComponent component) + { + EventDescriptor defaultEvent = TypeDescriptor.GetDefaultEvent(component); + PropertyDescriptor defaultPropEvent = null; + bool eventChanged = false; + IEventBindingService eps = (IEventBindingService)GetService(typeof(IEventBindingService)); + Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || (eps != null), "IEventBindingService not found"); + if (eps != null) + { + defaultPropEvent = eps.GetEventProperty(defaultEvent); + } + + // If we couldn't find a property for this event, or if the property is read only, then abort and just show the code. + if (defaultPropEvent == null || defaultPropEvent.IsReadOnly) + { + if (eps != null) + { + eps.ShowCode(); + } + return; + } + + string handler = (string)defaultPropEvent.GetValue(component); + + // If there is no handler set, set one now. + if (handler == null) + { + eventChanged = true; + handler = eps.CreateUniqueMethodName(component, defaultEvent); + } + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + DesignerTransaction trans = null; + + try + { + if (host != null) + { + trans = host.CreateTransaction(string.Format(SR.WindowsFormsAddEvent, defaultEvent.Name)); + } + // Save the new value... BEFORE navigating to it! + if (eventChanged && defaultPropEvent != null) + { + defaultPropEvent.SetValue(component, handler); + } + eps.ShowCode(component, defaultEvent); + } + finally + { + if (trans != null) + { + trans.Commit(); + } + } + } + + /// + /// This method should be called by the extending designer for each message the control would normally receive. This allows the designer to pre-process messages before allowing them to be routed to the control. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_SETCURSOR: + // We always handle setting the cursor ourselves. + OnSetCursor(); + break; + case Interop.WindowMessages.WM_CONTEXTMENU: + // We must handle this ourselves. Control only allows regular Windows Forms context menus, which doesn't do us much good. Also, control's button up processing calls DefwndProc first, which causes a right mouse up to be routed as a WM_CONTEXTMENU. If we don't respond to it here, this message will be bubbled up to our parent, which would pop up a container context menu instead of our own. + int x = NativeMethods.Util.SignedLOWORD(unchecked((int)(long)m.LParam)); + int y = NativeMethods.Util.SignedHIWORD(unchecked((int)(long)m.LParam)); + if (x == -1 && y == -1) + { + // for shift-F10 + Point mouse = Control.MousePosition; + x = mouse.X; + y = mouse.Y; + } + OnContextMenu(x, y); + break; + case Interop.WindowMessages.WM_NCHITTEST: + if (_tray.glyphManager != null) + { + // Make sure tha we send our glyphs hit test messages over the TrayControls too + Point pt = new Point((short)NativeMethods.Util.LOWORD(unchecked((int)(long)m.LParam)), (short)NativeMethods.Util.HIWORD(unchecked((int)(long)m.LParam))); + NativeMethods.POINT pt1 = new NativeMethods.POINT + { + x = 0, + y = 0 + }; + NativeMethods.MapWindowPoints(IntPtr.Zero, Handle, pt1, 1); + pt.Offset(pt1.x, pt1.y); + pt.Offset(Location.X, Location.Y);//offset the loc of the traycontrol -so now we're in comptray coords + _tray.glyphManager.GetHitTest(pt); + } + base.WndProc(ref m); + break; + default: + base.WndProc(ref m); + break; + } + } + + private class TrayControlAccessibleObject : ControlAccessibleObject + { + readonly ComponentTray _tray; + public TrayControlAccessibleObject(TrayControl owner, ComponentTray tray) : base(owner) + { + _tray = tray; + } + + private IComponent Component + { + get => ((TrayControl)Owner).Component; + } + + public override AccessibleStates State + { + get + { + AccessibleStates state = base.State; + ISelectionService s = (ISelectionService)_tray.GetService(typeof(ISelectionService)); + if (s != null) + { + if (s.GetComponentSelected(Component)) + { + state |= AccessibleStates.Selected; + } + if (s.PrimarySelection == Component) + { + state |= AccessibleStates.Focused; + } + } + return state; + } + } + } + } + + private class ComponentTrayGlyphManager + { + private Adorner _traySelectionAdorner; //we'll use a single adorner to manage the glyphs + private Glyph _hitTestedGlyph; //the last glyph we hit tested (can be null) + private readonly ISelectionService _selSvc; //we need the selection service fo r the hover behavior + private readonly BehaviorService _behaviorSvc; + + /// + /// Constructor that simply creates an empty adorner. + /// + public ComponentTrayGlyphManager(ISelectionService selSvc, BehaviorService behaviorSvc) + { + _selSvc = selSvc; + _behaviorSvc = behaviorSvc; + _traySelectionAdorner = new Adorner(); + } + + /// + /// This is how we publically expose our glyph collection so that other designer services can 'add value'. + /// + public GlyphCollection SelectionGlyphs + { + get => _traySelectionAdorner.Glyphs; + } + + /// + /// Clears teh adorner of glyphs. + /// + public void Dispose() + { + if (_traySelectionAdorner != null) + { + _traySelectionAdorner.Glyphs.Clear(); + _traySelectionAdorner = null; + } + } + + /// + /// Retrieves a list of glyphs associated with the component. + /// + public GlyphCollection GetGlyphsForComponent(IComponent comp) + { + GlyphCollection glyphs = new GlyphCollection(); + if (_behaviorSvc != null && comp != null) + { + if (_behaviorSvc.DesignerActionUI != null) + { + Glyph g = _behaviorSvc.DesignerActionUI.GetDesignerActionGlyph(comp); + if (g != null) + { + glyphs.Add(g); + } + } + } + return glyphs; + } + + /// + /// Called from the tray's NCHITTEST message in the WndProc. We use this to loop through our glyphs and identify which one is successfully hit tested. From here, we know where to send our messages. + /// + public Cursor GetHitTest(Point p) + { + for (int i = 0; i < _traySelectionAdorner.Glyphs.Count; i++) + { + Cursor hitTestCursor = _traySelectionAdorner.Glyphs[i].GetHitTest(p); + if (hitTestCursor != null) + { + _hitTestedGlyph = _traySelectionAdorner.Glyphs[i]; + return hitTestCursor; + } + } + _hitTestedGlyph = null; + return null; + } + + + /// + /// Called when the tray receives this mouse message. Here, we'll give our glyphs the first chance to repsond to the message before the tray even sees it. + /// + public bool OnMouseDoubleClick(MouseEventArgs e) + { + if (_hitTestedGlyph != null && _hitTestedGlyph.Behavior != null) + { + return _hitTestedGlyph.Behavior.OnMouseDoubleClick(_hitTestedGlyph, e.Button, new Point(e.X, e.Y)); + } + return false; + } + + /// + /// Called when the tray receives this mouse message. Here, we'll give our glyphs the first chance to repsond to the message before the tray even sees it. + /// + public bool OnMouseDown(MouseEventArgs e) + { + if (_hitTestedGlyph != null && _hitTestedGlyph.Behavior != null) + { + return _hitTestedGlyph.Behavior.OnMouseDown(_hitTestedGlyph, e.Button, new Point(e.X, e.Y)); + } + return false; + } + + + /// + /// Called when the tray receives this mouse message. Here, we'll give our glyphs the first chance to repsond to the message before the tray even sees it. + /// + public bool OnMouseMove(MouseEventArgs e) + { + if (_hitTestedGlyph != null && _hitTestedGlyph.Behavior != null) + { + return _hitTestedGlyph.Behavior.OnMouseMove(_hitTestedGlyph, e.Button, new Point(e.X, e.Y)); + } + return false; + } + + /// + /// Called when the tray receives this mouse message. Here, we'll give our glyphs the first chance to repsond to the message before the tray even sees it. + /// + public bool OnMouseUp(MouseEventArgs e) + { + if (_hitTestedGlyph != null && _hitTestedGlyph.Behavior != null) + { + return _hitTestedGlyph.Behavior.OnMouseUp(_hitTestedGlyph, e.Button); + } + return false; + } + + /// + /// Called when the comp tray or any tray control paints. This will simply enumerate through the glyphs in our Adorner and ask them to paint + /// + public void OnPaintGlyphs(PaintEventArgs pe) + { + //Paint any glyphs our tray adorner has + foreach (Glyph g in _traySelectionAdorner.Glyphs) + { + g.Paint(pe); + } + } + + /// + /// Called when a tray control's location has changed. We'll loop through our glyphs and invalidate any that are associated with the component. + /// + public void UpdateLocation(TrayControl trayControl) + { + foreach (Glyph g in _traySelectionAdorner.Glyphs) + { + //only look at glyphs that derive from designerglyph base (actions) + if (g is DesignerActionGlyph desGlyph && ((DesignerActionBehavior)(desGlyph.Behavior)).RelatedComponent.Equals(trayControl.Component)) + { + desGlyph.UpdateAlternativeBounds(trayControl.Bounds); + } + } + } + } + + internal class AutoArrangeComparer : IComparer + { + int IComparer.Compare(object o1, object o2) + { + Debug.Assert(o1 != null && o2 != null, "Null objects sent for comparison!!!"); + Point tcLoc1 = ((Control)o1).Location; + Point tcLoc2 = ((Control)o2).Location; + int height = ((Control)o1).Height / 2; + // If they are at the same location, they are equal. + if (tcLoc1.X == tcLoc2.X && tcLoc1.Y == tcLoc2.Y) + return 0; + // Is the first control lower than the 2nd... + if (tcLoc1.Y + height <= tcLoc2.Y) + return -1; + // Is the 2nd control lower than the first... + if (tcLoc2.Y + height <= tcLoc1.Y) + return 1; + // Which control is left of the other... + return ((tcLoc1.X <= tcLoc2.X) ? -1 : 1); + } + } + + private class TraySelectionUIHandler : SelectionUIHandler + { + private readonly ComponentTray _tray; + private Size _snapSize = Size.Empty; + + /// + /// Creates a new selection UI handler for the given component tray. + /// + public TraySelectionUIHandler(ComponentTray tray) + { + _tray = tray; + _snapSize = new Size(); + } + + /// + /// Called when the user has started the drag. + /// + public override bool BeginDrag(object[] components, SelectionRules rules, int initialX, int initialY) + { + bool value = base.BeginDrag(components, rules, initialX, initialY); + _tray.SuspendLayout(); + return value; + } + + /// + /// Called when the user has completed the drag. The designer should remove any UI feedback it may be providing. + /// + public override void EndDrag(object[] components, bool cancel) + { + base.EndDrag(components, cancel); + _tray.ResumeLayout(); + } + + /// + /// Retrieves the base component for the selection handler. + /// + protected override IComponent GetComponent() + { + return _tray; + } + + /// + /// Retrieves the base component's UI control for the selection handler. + /// + protected override Control GetControl() + { + return _tray; + } + + /// + /// Retrieves the UI control for the given component. + /// + protected override Control GetControl(IComponent component) + { + return TrayControl.FromComponent(component); + } + + /// + /// Retrieves the current grid snap size we should snap objects to. + /// + protected override Size GetCurrentSnapSize() + { + return _snapSize; + } + + /// + /// We use this to request often-used services. + /// + protected override object GetService(Type serviceType) + { + return _tray.GetService(serviceType); + } + + /// + /// Determines if the selection UI handler should attempt to snap objects to a grid. + /// + protected override bool GetShouldSnapToGrid() + { + return false; + } + + /// + /// Given a rectangle, this updates the dimensions of it with any grid snaps and returns a new rectangle. If no changes to the rectangle's size were needed, this may return the same rectangle. + /// + public override Rectangle GetUpdatedRect(Rectangle originalRect, Rectangle dragRect, bool updateSize) + { + return dragRect; + } + + /// + /// Asks the handler to set the appropriate cursor + /// + public override void SetCursor() + { + _tray.OnSetCursor(); + } + } + + private class TrayOleDragDropHandler : OleDragDropHandler + { + public TrayOleDragDropHandler(SelectionUIHandler selectionHandler, IServiceProvider serviceProvider, IOleDragClient client) : base(selectionHandler, serviceProvider, client) + { + } + + protected override bool CanDropDataObject(IDataObject dataObj) + { + ICollection comps = null; + if (dataObj != null) + { + if (dataObj is ComponentDataObjectWrapper cdow) + { + ComponentDataObject cdo = (ComponentDataObject)cdow.InnerData; + comps = cdo.Components; + } + else + { + try + { + object serializationData = dataObj.GetData(OleDragDropHandler.DataFormat, true); + if (serializationData == null) + { + return false; + } + + IDesignerSerializationService ds = (IDesignerSerializationService)GetService(typeof(IDesignerSerializationService)); + if (ds == null) + { + return false; + } + comps = ds.Deserialize(serializationData); + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + // we return false on any exception + } + } + } + + if (comps != null && comps.Count > 0) + { + foreach (object comp in comps) + { + if (comp is Point) + { + continue; + } + if (comp is Control || !(comp is IComponent)) + { + return false; + } + } + return true; + } + return false; + } } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventArgs.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventArgs.cs new file mode 100644 index 00000000000..7c1af36b0b2 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventArgs.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// Provides data for the event. + /// + internal class ContainerSelectorActiveEventArgs : EventArgs + { + private readonly object _component; + private readonly ContainerSelectorActiveEventArgsType _eventType; + + /// + /// Initializes a new instance of the 'ContainerSelectorActiveEventArgs' class. + /// + public ContainerSelectorActiveEventArgs(object component) : this(component, ContainerSelectorActiveEventArgsType.Mouse) + { + } + + /// + /// Initializes a new instance of the 'ContainerSelectorActiveEventArgs' class. + /// + public ContainerSelectorActiveEventArgs(object component, ContainerSelectorActiveEventArgsType eventType) + { + _component = component; + _eventType = eventType; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventArgsType.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventArgsType.cs new file mode 100644 index 00000000000..ad86ebeb6c0 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventArgsType.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// Specifies IDs for containers of certain event types. + /// + internal enum ContainerSelectorActiveEventArgsType + { + /// + /// Indicates the container of the active event was the contextmenu. + /// + Contextmenu = 1, + /// + /// Indicates the container of the active event was the mouse. + /// + Mouse = 2, + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventHandler.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventHandler.cs new file mode 100644 index 00000000000..39d645db344 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContainerSelectorActiveEventHandler.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Windows.Forms.Design.ContainerSelectorActiveEventHandler..ctor(System.Object,System.IntPtr)")] +namespace System.Windows.Forms.Design +{ + /// + /// Represents the method that will handle a ContainerSelectorActive event. + /// + internal delegate void ContainerSelectorActiveEventHandler(object sender, ContainerSelectorActiveEventArgs e); +} + diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripActionList.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripActionList.cs new file mode 100644 index 00000000000..49468c2c5ae --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripActionList.cs @@ -0,0 +1,110 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; + +namespace System.Windows.Forms.Design +{ + internal class ContextMenuStripActionList : DesignerActionList + { + private readonly ToolStripDropDown _toolStripDropDown; + private bool _autoShow = false; + + public ContextMenuStripActionList(ToolStripDropDownDesigner designer) : base(designer.Component) + { + _toolStripDropDown = (ToolStripDropDown)designer.Component; + } + + //helper function to get the property on the actual Control + private object GetProperty(string propertyName) + { + PropertyDescriptor getProperty = TypeDescriptor.GetProperties(_toolStripDropDown)[propertyName]; + Debug.Assert(getProperty != null, "Could not find given property in control."); + if (getProperty != null) + { + return getProperty.GetValue(_toolStripDropDown); + } + return null; + } + + //helper function to change the property on the actual Control + private void ChangeProperty(string propertyName, object value) + { + PropertyDescriptor changingProperty = TypeDescriptor.GetProperties(_toolStripDropDown)[propertyName]; + Debug.Assert(changingProperty != null, "Could not find given property in control."); + if (changingProperty != null) + { + changingProperty.SetValue(_toolStripDropDown, value); + } + } + + /// + /// Controls whether the Chrome is Automatically shown on selection + /// + public override bool AutoShow + { + get => _autoShow; + set + { + if (_autoShow != value) + { + _autoShow = value; + } + } + } + + public bool ShowImageMargin + { + get => (bool)GetProperty("ShowImageMargin"); + set + { + if (value != ShowImageMargin) + { + ChangeProperty("ShowImageMargin", (object)value); + } + } + } + + public bool ShowCheckMargin + { + get => (bool)GetProperty("ShowCheckMargin"); + set + { + if (value != ShowCheckMargin) + { + ChangeProperty("ShowCheckMargin", (object)value); + } + } + } + + public ToolStripRenderMode RenderMode + { + get => (ToolStripRenderMode)GetProperty("RenderMode"); + set + { + if (value != RenderMode) + { + ChangeProperty("RenderMode", (object)value); + } + } + } + + /// + /// The Main method to group the ActionItems and pass it to the Panel. + /// + public override DesignerActionItemCollection GetSortedActionItems() + { + DesignerActionItemCollection items = new DesignerActionItemCollection(); + items.Add(new DesignerActionPropertyItem("RenderMode", SR.ToolStripActionList_RenderMode, SR.ToolStripActionList_Layout, SR.ToolStripActionList_RenderModeDesc)); + if (_toolStripDropDown is ToolStripDropDownMenu) + { + items.Add(new DesignerActionPropertyItem("ShowImageMargin", SR.ContextMenuStripActionList_ShowImageMargin, SR.ToolStripActionList_Layout, SR.ContextMenuStripActionList_ShowImageMarginDesc)); + items.Add(new DesignerActionPropertyItem("ShowCheckMargin", SR.ContextMenuStripActionList_ShowCheckMargin, SR.ToolStripActionList_Layout, SR.ContextMenuStripActionList_ShowCheckMarginDesc)); + } + return items; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripGroup.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripGroup.cs new file mode 100644 index 00000000000..ae2f8ce3fc2 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripGroup.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +namespace System.Windows.Forms.Design +{ + internal class ContextMenuStripGroup + { + private List _items; + private readonly string _name; + + public ContextMenuStripGroup(string name) => _name = name; + + public List Items + { + get + { + if (_items == null) + { + _items = new List(); + } + return _items; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripGroupCollection.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripGroupCollection.cs new file mode 100644 index 00000000000..6c5871432ea --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ContextMenuStripGroupCollection.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; + +namespace System.Windows.Forms.Design +{ + internal class ContextMenuStripGroupCollection : DictionaryBase + { + public ContextMenuStripGroupCollection() + { + + } + + public ContextMenuStripGroup this[string key] + { + get + { + if (!InnerHashtable.ContainsKey(key)) + { + InnerHashtable[key] = new ContextMenuStripGroup(key); + } + return InnerHashtable[key] as ContextMenuStripGroup; + } + } + + public bool ContainsKey(string key) + { + return InnerHashtable.ContainsKey(key); + } + protected override void OnInsert(object key, object value) + { + if (!(value is ContextMenuStripGroup)) + { + throw new NotSupportedException(); + } + base.OnInsert(key, value); + } + + protected override void OnSet(object key, object oldValue, object newValue) + { + if (!(newValue is ContextMenuStripGroup)) + { + throw new NotSupportedException(); + } + base.OnSet(key, oldValue, newValue); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ControlDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ControlDesigner.cs index 1b025ee64be..eb074f38e7e 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ControlDesigner.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ControlDesigner.cs @@ -2,585 +2,3152 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.CodeDom; using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Drawing; +using System.Drawing.Design; +using System.Globalization; using System.Runtime.InteropServices; using System.Windows.Forms.Design.Behavior; +using Accessibility; namespace System.Windows.Forms.Design { /// - /// - /// Provides a designer that can design components - /// that extend Control. - /// + /// Provides a designer that can design components that extend Control. /// public class ControlDesigner : ComponentDesigner { - protected AccessibleObject accessibilityObj = null; - - protected BehaviorService BehaviorService => throw new NotImplementedException(SR.NotImplementedByDesign); - + protected static readonly Point InvalidPoint = new Point(int.MinValue, int.MinValue); + private static int s_currentProcessId; + private IDesignerHost _host; // the host for our designer + private IDesignerTarget _designerTarget; // the target window proc for the control. + + private bool _liveRegion; // is the mouse is over a live region of the control? + private bool _inHitTest; // A popular way to implement GetHitTest is by WM_NCHITTEST...which would cause a cycle. + private bool _hasLocation; // Do we have a location property? + private bool _locationChecked; // And did we check it + private bool _locked; // signifies if this control is locked or not + private bool _enabledchangerecursionguard; + + //Behavior work + private BehaviorService _behaviorService; //we cache this 'cause we use it so often + private ResizeBehavior _resizeBehavior; //the standard behavior for our selection glyphs - demand created + private ContainerSelectorBehavior _moveBehavior; //the behavior for non-resize glyphs - demand created + // Services that we use enough to cache + private ISelectionUIService _selectionUISvc; + private IEventHandlerService _eventSvc; + private IToolboxService _toolboxSvc; + private InheritanceUI _inheritanceUI; + private IOverlayService _overlayService; + // transient values that are used during mouse drags + private Point _mouseDragLast = InvalidPoint; // the last position of the mouse during a drag. + private bool _mouseDragMoved; // has the mouse been moved during this drag? + private int _lastMoveScreenX; + private int _lastMoveScreenY; + // Values used to simulate double clicks for controls that don't support them. + private int _lastClickMessageTime; + private int _lastClickMessagePositionX; + private int _lastClickMessagePositionY; + + private Point _downPos = Point.Empty; // point used to track first down of a double click + private event EventHandler DisposingHandler; + private CollectionChangeEventHandler _dataBindingsCollectionChanged; + private Exception _thrownException; + + private bool _ctrlSelect; // if the CTRL key was down at the mouse down + private bool _toolPassThrough; // a tool is selected, allow the parent to draw a rect for it. + private bool _removalNotificationHooked = false; + private bool _revokeDragDrop = true; + private bool _hadDragDrop; + private static bool s_inContextMenu = false; + private DockingActionList _dockingAction; + private StatusCommandUI _statusCommandUI; // UI for setting the StatusBar Information.. + + private bool _forceVisible = true; + private bool _autoResizeHandles = false; // used for disabling AutoSize effect on resize modes. Needed for compat. + private Dictionary _subclassedChildren; + + protected BehaviorService BehaviorService + { + get + { + if (_behaviorService == null) + { + _behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + } + return _behaviorService; + } + } internal bool ForceVisible { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - - set => throw new NotImplementedException(SR.NotImplementedByDesign); + get => _forceVisible; + set => _forceVisible = value; } /// - /// - /// Retrieves a list of associated components. These are components that should be incluced in a cut or copy - /// operation on this component. - /// + /// Retrieves a list of associated components. These are components that should be incluced in a cut or copy operation on this component. /// - public override ICollection AssociatedComponents => - throw new NotImplementedException(SR.NotImplementedByDesign); - - public virtual AccessibleObject AccessibilityObject => - throw new NotImplementedException(SR.NotImplementedByDesign); - - /// - /// Retrieves the control we're designing. - /// - public virtual Control Control => throw new NotImplementedException(SR.NotImplementedByDesign); + public override ICollection AssociatedComponents + { + get + { + ArrayList sitedChildren = null; + foreach (Control c in Control.Controls) + { + if (c.Site != null) + { + if (sitedChildren == null) + { + sitedChildren = new ArrayList(); + } + sitedChildren.Add(c); + } + } + + if (sitedChildren != null) + { + return sitedChildren; + } + return base.AssociatedComponents; + } + } - /// - /// Determines whether drag rects can be drawn on this designer. - /// - protected virtual bool EnableDragRect => throw new NotImplementedException(SR.NotImplementedByDesign); + protected AccessibleObject accessibilityObj = null; - /// - /// Returns the parent component for this control designer. - /// The default implementation just checks to see if the - /// component being designed is a control, and if it is it - /// returns its parent. This property can return null if there - /// is no parent component. - /// - protected override IComponent ParentComponent => throw new NotImplementedException(SR.NotImplementedByDesign); + public virtual AccessibleObject AccessibilityObject + { + get + { + if (accessibilityObj == null) + { + accessibilityObj = new ControlDesignerAccessibleObject(this, Control); + } + return accessibilityObj; + } + } /// - /// Determines whether or not the ControlDesigner will allow SnapLine alignment during a - /// drag operation when the primary drag control is over this designer, or when a control - /// is being dragged from the toolbox, or when a control is being drawn through click-drag. + /// Retrieves the control we're designing. /// - public virtual bool ParticipatesWithSnapLines => throw new NotImplementedException(SR.NotImplementedByDesign); + public virtual Control Control + { + get => (Control)Component; + } /// + /// Determines whether drag rects can be drawn on this designer. /// - public bool AutoResizeHandles + protected virtual bool EnableDragRect { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); + get => false; } /// - /// Retrieves a set of rules concerning the movement capabilities of a component. - /// This should be one or more flags from the SelectionRules class. If no designer - /// provides rules for a component, the component will not get any UI services. + /// Returns the parent component for this control designer. The default implementation just checks to see if the component being designed is a control, and if it is it returns its parent. This property can return null if there is no parent component. /// - public virtual SelectionRules SelectionRules => throw new NotImplementedException(SR.NotImplementedByDesign); + protected override IComponent ParentComponent + { + get + { + if (Component is Control c && c.Parent != null) + { + return c.Parent; + } + return base.ParentComponent; + } + } /// - /// Returns a list of SnapLine objects representing interesting - /// alignment points for this control. These SnapLines are used - /// to assist in the positioning of the control on a parent's - /// surface. + /// Determines whether or not the ControlDesigner will allow SnapLine alignment during a drag operation when the primary drag control is over this designer, or when a control is being dragged from the toolbox, or when a control is being drawn through click-drag. /// - public virtual IList SnapLines => throw new NotImplementedException(SR.NotImplementedByDesign); + public virtual bool ParticipatesWithSnapLines + { + get => true; + } - protected override InheritanceAttribute InheritanceAttribute => - throw new NotImplementedException(SR.NotImplementedByDesign); + public bool AutoResizeHandles + { + get => _autoResizeHandles; + set => _autoResizeHandles = value; + } - /// - /// Returns the number of internal control designers in the ControlDesigner. An internal control - /// is a control that is not in the IDesignerHost.Container.Components collection. - /// SplitterPanel is an example of one such control. We use this to get SnapLines for the internal - /// control designers. - /// - public virtual int NumberOfInternalControlDesigners() + private IDesignerTarget DesignerTarget { - throw new NotImplementedException(SR.NotImplementedByDesign); + get => _designerTarget; + set => _designerTarget = value; } - /// - /// Returns the internal control designer with the specified index in the ControlDesigner. An internal control - /// is a control that is not in the IDesignerHost.Container.Components collection. - /// SplitterPanel is an example of one such control. - /// internalControlIndex is zero-based. - /// - public virtual ControlDesigner InternalControlDesigner(int internalControlIndex) + private Dictionary SubclassedChildWindows { - throw new NotImplementedException(SR.NotImplementedByDesign); + get + { + if (_subclassedChildren == null) + { + _subclassedChildren = new Dictionary(); + } + return _subclassedChildren; + } } /// - /// Default processing for messages. This method causes the message to - /// get processed by windows, skipping the control. This is useful if - /// you want to block this message from getting to the control, but - /// you do not want to block it from getting to Windows itself because - /// it causes other messages to be generated. + /// Retrieves a set of rules concerning the movement capabilities of a component. This should be one or more flags from the SelectionRules class. If no designer provides rules for a component, the component will not get any UI services. /// - protected void BaseWndProc(ref Message m) + public virtual SelectionRules SelectionRules { - throw new NotImplementedException(SR.NotImplementedByDesign); + get + { + object component = Component; + SelectionRules rules = SelectionRules.Visible; + PropertyDescriptor prop; + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(component); + PropertyDescriptor autoSizeProp = props["AutoSize"]; + PropertyDescriptor autoSizeModeProp = props["AutoSizeMode"]; + if ((prop = props["Location"]) != null && + !prop.IsReadOnly) + { + rules |= SelectionRules.Moveable; + } + + if ((prop = props["Size"]) != null && !prop.IsReadOnly) + { + if (AutoResizeHandles && Component != _host.RootComponent) + { + rules = IsResizableConsiderAutoSize(autoSizeProp, autoSizeModeProp) ? rules | SelectionRules.AllSizeable : rules; + } + else + { + rules |= SelectionRules.AllSizeable; + } + } + + PropertyDescriptor propDock = props["Dock"]; + if (propDock != null) + { + DockStyle dock = (DockStyle)(int)propDock.GetValue(component); + //gotta adjust if the control's parent is mirrored... this is just such that we add the right resize handles. We need to do it this way, since resize glyphs are added in AdornerWindow coords, and the AdornerWindow is never mirrored. + if (Control.Parent != null && Control.Parent.IsMirrored) + { + if (dock == DockStyle.Left) + { + dock = DockStyle.Right; + } + else if (dock == DockStyle.Right) + { + dock = DockStyle.Left; + } + } + switch (dock) + { + case DockStyle.Top: + rules &= ~(SelectionRules.Moveable | SelectionRules.TopSizeable | SelectionRules.LeftSizeable | SelectionRules.RightSizeable); + break; + case DockStyle.Left: + rules &= ~(SelectionRules.Moveable | SelectionRules.TopSizeable | SelectionRules.LeftSizeable | SelectionRules.BottomSizeable); + break; + case DockStyle.Right: + rules &= ~(SelectionRules.Moveable | SelectionRules.TopSizeable | SelectionRules.BottomSizeable | SelectionRules.RightSizeable); + break; + case DockStyle.Bottom: + rules &= ~(SelectionRules.Moveable | SelectionRules.LeftSizeable | SelectionRules.BottomSizeable | SelectionRules.RightSizeable); + break; + case DockStyle.Fill: + rules &= ~(SelectionRules.Moveable | SelectionRules.TopSizeable | SelectionRules.LeftSizeable | SelectionRules.RightSizeable | SelectionRules.BottomSizeable); + break; + } + } + + PropertyDescriptor pd = props["Locked"]; + if (pd != null) + { + object value = pd.GetValue(component); + // make sure that value is a boolean, in case someone else added this property + if (value is bool && (bool)value == true) + { + rules = SelectionRules.Locked | SelectionRules.Visible; + } + } + return rules; + } } - /// - /// Determines if the this designer can be parented to the specified desinger -- - /// generally this means if the control for this designer can be parented into the - /// given ParentControlDesigner's designer. - /// - public virtual bool CanBeParentedTo(IDesigner parentDesigner) + internal virtual bool ControlSupportsSnaplines { - ParentControlDesigner p = parentDesigner as ParentControlDesigner; - return p != null && !Control.Contains(p.Control); + get => true; } - /// - /// Default processing for messages. This method causes the message to - /// get processed by the control, rather than the designer. - /// - protected void DefWndProc(ref Message m) + internal Point GetOffsetToClientArea() { - throw new NotImplementedException(SR.NotImplementedByDesign); + NativeMethods.POINT nativeOffset = new NativeMethods.POINT(0, 0); + NativeMethods.MapWindowPoints(Control.Handle, Control.Parent.Handle, nativeOffset, 1); + Point offset = Control.Location; + // If the 2 controls do not have the same orientation, then force one to make sure we calculate the correct offset + if (Control.IsMirrored != Control.Parent.IsMirrored) + { + offset.Offset(Control.Width, 0); + } + return (new Point(Math.Abs(nativeOffset.x - offset.X), nativeOffset.y - offset.Y)); } - /// - /// Displays the given exception to the user. - /// - protected void DisplayError(Exception e) + private bool IsResizableConsiderAutoSize(PropertyDescriptor autoSizeProp, PropertyDescriptor autoSizeModeProp) { - throw new NotImplementedException(SR.NotImplementedByDesign); + object component = Component; + bool resizable = true; + bool autoSize = false; + bool growOnly = false; + if (autoSizeProp != null && + !(autoSizeProp.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden) || + autoSizeProp.Attributes.Contains(BrowsableAttribute.No))) + { + autoSize = (bool)autoSizeProp.GetValue(component); + } + + if (autoSizeModeProp != null) + { + AutoSizeMode mode = (AutoSizeMode)autoSizeModeProp.GetValue(component); + growOnly = mode == AutoSizeMode.GrowOnly; + } + + if (autoSize) + { + resizable = growOnly; + } + return resizable; } /// - /// Disposes of this object. + /// Returns a list of SnapLine objects representing interesting alignment points for this control. These SnapLines are used to assist in the positioning of the control on a parent's surface. /// - protected override void Dispose(bool disposing) + public virtual IList SnapLines { - throw new NotImplementedException(SR.NotImplementedByDesign); + get => SnapLinesInternal(); } - /// - /// Enables design time functionality for a child control. The child control is a child - /// of this control designer's control. The child does not directly participate in - /// persistence, but it will if it is exposed as a property of the main control. Consider - /// a control like the SplitContainer: it has two panels, Panel1 and Panel2. These panels - /// are exposed through read only Panel1 and Panel2 properties on the SplitContainer class. - /// SplitContainer's designer calls EnableDesignTime for each panel, which allows other - /// components to be dropped on them. But, in order for the contents of Panel1 and Panel2 - /// to be saved, SplitContainer itself needed to expose the panels as public properties. - /// The child paramter is the control to enable. The name paramter is the name of this - /// control as exposed to the end user. Names need to be unique within a control designer, - /// but do not have to be unique to other control designer's children. - /// This method returns true if the child control could be enabled for design time, or - /// false if the hosting infrastructure does not support it. To support this feature, the - /// hosting infrastructure must expose the INestedContainer class as a service off of the site. - /// - protected bool EnableDesignMode(Control child, string name) + internal IList SnapLinesInternal() { - throw new NotImplementedException(SR.NotImplementedByDesign); + return SnapLinesInternal(Control.Margin); } - /// - /// Enables or disables drag/drop support. This - /// hooks drag event handlers to the control. - /// - protected void EnableDragDrop(bool value) + internal IList SnapLinesInternal(Padding margin) { - throw new NotImplementedException(SR.NotImplementedByDesign); + ArrayList snapLines = new ArrayList(4); + int width = Control.Width; // better perf + int height = Control.Height; // better perf + //the four edges of our control + snapLines.Add(new SnapLine(SnapLineType.Top, 0, SnapLinePriority.Low)); + snapLines.Add(new SnapLine(SnapLineType.Bottom, height - 1, SnapLinePriority.Low)); + snapLines.Add(new SnapLine(SnapLineType.Left, 0, SnapLinePriority.Low)); + snapLines.Add(new SnapLine(SnapLineType.Right, width - 1, SnapLinePriority.Low)); + //the four margins of our control + // Even if a control does not have margins, we still want to add Margin snaplines. + // This is because we only try to match to matching snaplines. Makes the code a little easier... + snapLines.Add(new SnapLine(SnapLineType.Horizontal, -margin.Top, SnapLine.MarginTop, SnapLinePriority.Always)); + snapLines.Add(new SnapLine(SnapLineType.Horizontal, margin.Bottom + height, SnapLine.MarginBottom, SnapLinePriority.Always)); + snapLines.Add(new SnapLine(SnapLineType.Vertical, -margin.Left, SnapLine.MarginLeft, SnapLinePriority.Always)); + snapLines.Add(new SnapLine(SnapLineType.Vertical, margin.Right + width, SnapLine.MarginRight, SnapLinePriority.Always)); + return snapLines; } - /// - /// Returns a 'BodyGlyph' representing the bounds of this control. - /// The BodyGlyph is responsible for hit testing the related CtrlDes - /// and forwarding messages directly to the designer. - /// - protected virtual ControlBodyGlyph GetControlGlyph(GlyphSelectionType selectionType) + protected override InheritanceAttribute InheritanceAttribute { - throw new NotImplementedException(SR.NotImplementedByDesign); + get + { + if (IsRootDesigner) + { + return InheritanceAttribute.Inherited; + } + return base.InheritanceAttribute; + } } - /// - /// Returns a collection of Glyph objects representing the selection - /// borders and grab handles for a standard control. Note that - /// based on 'selectionType' the Glyphs returned will either: represent - /// a fully resizeable selection border with grab handles, a locked - /// selection border, or a single 'hidden' selection Glyph. - /// - public virtual GlyphCollection GetGlyphs(GlyphSelectionType selectionType) + internal new bool IsRootDesigner { - throw new NotImplementedException(SR.NotImplementedByDesign); + get + { + Debug.Assert(Component != null, "this.component needs to be set before this method is valid."); + bool isRoot = false; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && Component == host.RootComponent) + { + isRoot = true; + } + return isRoot; + } } /// - /// Allows your component to support a design time user interface. A TabStrip - /// control, for example, has a design time user interface that allows the user - /// to click the tabs to change tabs. To implement this, TabStrip returns - /// true whenever the given point is within its tabs. + /// Returns the number of internal control designers in the ControlDesigner. An internal control is a control that is not in the IDesignerHost.Container.Components collection. SplitterPanel is an example of one such control. We use this to get SnapLines for the internal control designers. /// - protected virtual bool GetHitTest(Point point) - { - return false; - } + public virtual int NumberOfInternalControlDesigners() => 0; /// - /// Hooks the children of the given control. We need to do this for - /// child controls that are not in design mode, which is the case - /// for composite controls. + /// Returns the internal control designer with the specified index in the ControlDesigner. An internal control is a control that is not in the IDesignerHost.Container.Components collection. SplitterPanel is an example of one such control. internalControlIndex is zero-based. /// - protected void HookChildControls(Control firstChild) - { - throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual ControlDesigner InternalControlDesigner(int internalControlIndex) => null; /// - /// Called by the host when we're first initialized. + /// Default processing for messages. This method causes the message to get processed by windows, skipping the control. This is useful if you want to block this message from getting to the control, but you do not want to block it from getting to Windows itself because it causes other messages to be generated. /// - public override void Initialize(IComponent component) - { - throw new NotImplementedException(SR.NotImplementedByDesign); - } + protected void BaseWndProc(ref Message m) => m.Result = UnsafeNativeMethods.DefWindowProc(m.HWnd, m.Msg, m.WParam, m.LParam); /// - /// ControlDesigner overrides this method to handle after-drop cases. + /// Determines if the this designer can be parented to the specified desinger -- generally this means if the control for this designer can be parented into the given ParentControlDesigner's designer. /// - public override void InitializeExistingComponent(IDictionary defaultValues) - { - throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool CanBeParentedTo(IDesigner parentDesigner) => parentDesigner is ParentControlDesigner p && !Control.Contains(p.Control); /// - /// ControlDesigner overrides this method. It will look at the default property for the control and, - /// if it is of type string, it will set this property's value to the name of the component. It only - /// does this if the designer has been configured with this option in the options service. This method - /// also connects the control to its parent and positions it. If you override this method, you should - /// always call base. + /// Default processing for messages. This method causes the message to get processed by the control, rather than the designer. /// - public override void InitializeNewComponent(IDictionary defaultValues) + protected void DefWndProc(ref Message m) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _designerTarget.DefWndProc(ref m); } /// - /// Called when the designer is intialized. This allows the designer to provide some - /// meaningful default values in the component. The default implementation of this - /// sets the components's default property to it's name, if that property is a string. + /// Displays the given exception to the user. /// - [Obsolete( - "This method has been deprecated. Use InitializeNewComponent instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public override void OnSetComponentDefaults() + protected void DisplayError(Exception e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + IUIService uis = (IUIService)GetService(typeof(IUIService)); + if (uis != null) + { + uis.ShowError(e); + } + else + { + string message = e.Message; + if (message == null || message.Length == 0) + { + message = e.ToString(); + } + RTLAwareMessageBox.Show(Control, message, null, MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, 0); + } } /// - /// Called when the context menu should be displayed + /// Disposes of this object. /// - protected virtual void OnContextMenu(int x, int y) + protected override void Dispose(bool disposing) { - ShowContextMenu(x, y); + if (disposing) + { + if (Control != null) + { + if (_dataBindingsCollectionChanged != null) + { + Control.DataBindings.CollectionChanged -= _dataBindingsCollectionChanged; + } + + if (Inherited && _inheritanceUI != null) + { + _inheritanceUI.RemoveInheritedControl(Control); + } + + if (_removalNotificationHooked) + { + IComponentChangeService csc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (csc != null) + { + csc.ComponentRemoved -= new ComponentEventHandler(DataSource_ComponentRemoved); + } + _removalNotificationHooked = false; + } + DisposingHandler?.Invoke(this, EventArgs.Empty); + UnhookChildControls(Control); + } + + if (ContextMenu != null) + { + ContextMenu.Disposed -= new EventHandler(DetachContextMenu); + } + + if (_designerTarget != null) + { + _designerTarget.Dispose(); + } + _downPos = Point.Empty; + Control.ControlAdded -= new ControlEventHandler(OnControlAdded); + Control.ControlRemoved -= new ControlEventHandler(OnControlRemoved); + Control.ParentChanged -= new EventHandler(OnParentChanged); + Control.SizeChanged -= new EventHandler(OnSizeChanged); + Control.LocationChanged -= new EventHandler(OnLocationChanged); + Control.EnabledChanged -= new EventHandler(OnEnabledChanged); + } + base.Dispose(disposing); } - /// - /// This is called immediately after the control handle has been created. - /// - protected virtual void OnCreateHandle() + private void OnControlAdded(object sender, ControlEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (e.Control != null && _host != null) + { + if (!(_host.GetDesigner(e.Control) is ControlDesigner)) + { + // No, no designer means we must replace the window target in this control. + IWindowTarget oldTarget = e.Control.WindowTarget; + if (!(oldTarget is ChildWindowTarget)) + { + e.Control.WindowTarget = new ChildWindowTarget(this, e.Control, oldTarget); + // Controls added in UserControl.OnLoad() do not setup sniffing WndProc properly. + e.Control.ControlAdded += new ControlEventHandler(OnControlAdded); + } + + // Some controls (primarily RichEdit) will register themselves as drag-drop source/targets when they are instantiated. We have to RevokeDragDrop() for them so that the ParentControlDesigner()'s drag-drop support can work correctly. Normally, the hwnd for the child control is not created at this time, and we will use the WM_CREATE message in ChildWindowTarget's WndProc() to revoke drag-drop. But, if the handle was already created for some reason, we will need to revoke drag-drop right away. + if (e.Control.IsHandleCreated) + { + Application.OleRequired(); + UnsafeNativeMethods.RevokeDragDrop(e.Control.Handle); + // We only hook the control's children if there was no designer. We leave it up to the designer to hook its own children. + HookChildControls(e.Control); + } + } + } } - /// - /// Called when a drag-drop operation enters the control designer view - /// - protected virtual void OnDragEnter(DragEventArgs de) + private interface IDesignerTarget : IDisposable { - throw new NotImplementedException(SR.NotImplementedByDesign); + void DefWndProc(ref Message m); } - /// - /// Called to cleanup a D&D operation - /// - protected virtual void OnDragComplete(DragEventArgs de) + private void DetachContextMenu(object sender, EventArgs e) { - // default implementation - does nothing. + ContextMenu = null; } - /// - /// Called when a drag drop object is dropped onto the control designer view - /// - protected virtual void OnDragDrop(DragEventArgs de) + private ContextMenu ContextMenu { - throw new NotImplementedException(SR.NotImplementedByDesign); + get => (ContextMenu)ShadowProperties["ContextMenu"]; + set + { + ContextMenu oldValue = (ContextMenu)ShadowProperties["ContextMenu"]; + + if (oldValue != value) + { + EventHandler disposedHandler = new EventHandler(DetachContextMenu); + + if (oldValue != null) + { + oldValue.Disposed -= disposedHandler; + } + + ShadowProperties["ContextMenu"] = value; + + if (value != null) + { + value.Disposed += disposedHandler; + } + } + + } } - /// - /// Called when a drag-drop operation leaves the control designer view - /// - protected virtual void OnDragLeave(EventArgs e) + private void DataSource_ComponentRemoved(object sender, ComponentEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + // It is possible to use the control designer with NON CONTROl types. + if (Component is Control ctl) + { + Debug.Assert(ctl.DataBindings.Count > 0, "we should not be notified if the control has no dataBindings"); + ctl.DataBindings.CollectionChanged -= _dataBindingsCollectionChanged; + for (int i = 0; i < ctl.DataBindings.Count; i++) + { + Binding binding = ctl.DataBindings[i]; + if (binding.DataSource == e.Component) + { + // remove the binding from the control's collection. this will also remove the binding from the bindingManagerBase's bindingscollection + // NOTE: we can't remove the bindingManager from the bindingContext, cause there may be some complex bound controls ( such as the dataGrid, or the ComboBox, or the ListBox ) that still use that bindingManager + ctl.DataBindings.Remove(binding); + } + } + // if after removing those bindings the collection is empty, then unhook the changeNotificationService + if (ctl.DataBindings.Count == 0) + { + IComponentChangeService csc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (csc != null) + { + csc.ComponentRemoved -= new ComponentEventHandler(DataSource_ComponentRemoved); + } + _removalNotificationHooked = false; + } + ctl.DataBindings.CollectionChanged += _dataBindingsCollectionChanged; + } } /// - /// Called when a drag drop object is dragged over the control designer view + /// Enables design time functionality for a child control. The child control is a child of this control designer's control. The child does not directly participate in persistence, but it will if it is exposed as a property of the main control. Consider a control like the SplitContainer: it has two panels, Panel1 and Panel2. These panels are exposed through read only Panel1 and Panel2 properties on the SplitContainer class. SplitContainer's designer calls EnableDesignTime for each panel, which allows other components to be dropped on them. But, in order for the contents of Panel1 and Panel2 to be saved, SplitContainer itself needed to expose the panels as public properties. The child paramter is the control to enable. The name paramter is the name of this control as exposed to the end user. Names need to be unique within a control designer, but do not have to be unique to other control designer's children. This method returns true if the child control could be enabled for design time, or false if the hosting infrastructure does not support it. To support this feature, the hosting infrastructure must expose the INestedContainer class as a service off of the site. /// - protected virtual void OnDragOver(DragEventArgs de) + protected bool EnableDesignMode(Control child, string name) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (child == null) + { + throw new ArgumentNullException("child"); + } + + if (name == null) + { + throw new ArgumentNullException("name"); + } + + if (!(GetService(typeof(INestedContainer)) is INestedContainer nc)) + { + return false; + } + + // Only add the child if it doesn't already exist. VSWhidbey #408041. + for (int i = 0; i < nc.Components.Count; i++) + { + if (nc.Components[i].Equals(child)) + { + return true; + } + } + nc.Add(child, name); + return true; } /// - /// Event handler for our GiveFeedback event, which is called when a drag operation - /// is in progress. The host will call us with - /// this when an OLE drag event happens. + /// Enables or disables drag/drop support. This hooks drag event handlers to the control. /// - protected virtual void OnGiveFeedback(GiveFeedbackEventArgs e) + protected void EnableDragDrop(bool value) { - throw new NotImplementedException(SR.NotImplementedByDesign); + Control rc = Control; + if (rc == null) + { + return; + } + + if (value) + { + rc.DragDrop += new DragEventHandler(OnDragDrop); + rc.DragOver += new DragEventHandler(OnDragOver); + rc.DragEnter += new DragEventHandler(OnDragEnter); + rc.DragLeave += new EventHandler(OnDragLeave); + rc.GiveFeedback += new GiveFeedbackEventHandler(OnGiveFeedback); + _hadDragDrop = rc.AllowDrop; + if (!_hadDragDrop) + { + rc.AllowDrop = true; + } + _revokeDragDrop = false; + } + else + { + rc.DragDrop -= new DragEventHandler(OnDragDrop); + rc.DragOver -= new DragEventHandler(OnDragOver); + rc.DragEnter -= new DragEventHandler(OnDragEnter); + rc.DragLeave -= new EventHandler(OnDragLeave); + rc.GiveFeedback -= new GiveFeedbackEventHandler(OnGiveFeedback); + if (!_hadDragDrop) + { + rc.AllowDrop = false; + } + _revokeDragDrop = true; + } } - /// - /// Called in response to the left mouse button being pressed on a - /// component. It ensures that the component is selected. - /// - protected virtual void OnMouseDragBegin(int x, int y) + private void OnGiveFeedback(object s, GiveFeedbackEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + OnGiveFeedback(e); } - /// - /// Called at the end of a drag operation. This either commits or rolls back the - /// drag. - /// - protected virtual void OnMouseDragEnd(bool cancel) + private void OnDragLeave(object s, EventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + OnDragLeave(e); } - /// - /// Called for each movement of the mouse. This will check to see if a drag operation - /// is in progress. If so, it will pass the updated drag dimensions on to the selection - /// UI service. - /// - protected virtual void OnMouseDragMove(int x, int y) + private void OnDragEnter(object s, DragEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (BehaviorService != null) + { + //Tell the BehaviorService to monitor mouse messages so it can send appropriate drag notifications. + BehaviorService.StartDragNotification(); + } + OnDragEnter(e); } - /// - /// Called when the mouse first enters the control. This is forwarded to the parent - /// designer to enable the container selector. - /// - protected virtual void OnMouseEnter() + private void OnDragOver(object s, DragEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + OnDragOver(e); } - /// - /// Called after the mouse hovers over the control. This is forwarded to the parent - /// designer to enabled the container selector. - /// - protected virtual void OnMouseHover() + private void OnDragDrop(object s, DragEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (BehaviorService != null) + { + //this will cause the BehSvc to return from 'drag mode' + BehaviorService.EndDragNotification(); + } + OnDragDrop(e); } - /// - /// Called when the mouse first enters the control. This is forwarded to the parent - /// designer to enable the container selector. - /// - protected virtual void OnMouseLeave() + internal System.Windows.Forms.Design.Behavior.Behavior MoveBehavior { - throw new NotImplementedException(SR.NotImplementedByDesign); + get + { + if (_moveBehavior == null) + { + _moveBehavior = new ContainerSelectorBehavior(Control, Component.Site); + } + return _moveBehavior; + } } /// - /// Called when the control we're designing has finished painting. This method - /// gives the designer a chance to paint any additional adornments on top of the - /// control. + /// Returns a 'BodyGlyph' representing the bounds of this control. The BodyGlyph is responsible for hit testing the related CtrlDes and forwarding messages directly to the designer. /// - protected virtual void OnPaintAdornments(PaintEventArgs pe) + protected virtual ControlBodyGlyph GetControlGlyph(GlyphSelectionType selectionType) { - throw new NotImplementedException(SR.NotImplementedByDesign); + //get the right cursor for this component + OnSetCursor(); + Cursor cursor = Cursor.Current; + //get the correctly translated bounds + Rectangle translatedBounds = BehaviorService.ControlRectInAdornerWindow(Control); + //create our glyph, and set its cursor appropriately + ControlBodyGlyph g = null; + Control parent = Control.Parent; + if (parent != null && _host != null && _host.RootComponent != Component) + { + Rectangle parentRect = parent.RectangleToScreen(parent.ClientRectangle); + Rectangle controlRect = Control.RectangleToScreen(Control.ClientRectangle); + if (!parentRect.Contains(controlRect) && !parentRect.IntersectsWith(controlRect)) + { + //since the parent is completely clipping the control, the control cannot be a drop target, and it will not get mouse messages. So we don't have to give the glyph a transparentbehavior (default for ControlBodyGlyph). But we still would like to be able to move the control, so push a MoveBehavior. If we didn't we wouldn't be able to move the control, since it won't get any mouse messages. + + ISelectionService sel = (ISelectionService)GetService(typeof(ISelectionService)); + if (sel != null && sel.GetComponentSelected(Control)) + { + g = new ControlBodyGlyph(translatedBounds, cursor, Control, MoveBehavior); + } + else if (cursor == Cursors.SizeAll) + { + //If we get here, OnSetCursor could have set the cursor to SizeAll. But if we fall into this category, we don't have a MoveBehavior, so we don't want to show the SizeAll cursor. Let's make sure the cursor is set to the default cursor. + cursor = Cursors.Default; + } + } + } + + if (g == null) + { + //we are not totally clipped by the parent + g = new ControlBodyGlyph(translatedBounds, cursor, Control, this); + } + return g; } + internal ControlBodyGlyph GetControlGlyphInternal(GlyphSelectionType selectionType) => GetControlGlyph(selectionType); + /// - /// Called each time the cursor needs to be set. The ControlDesigner behavior here - /// will set the cursor to one of three things: - /// 1. If the toolbox service has a tool selected, it will allow the toolbox service to - /// set the cursor. - /// 2. If the selection UI service shows a locked selection, or if there is no location - /// property on the control, then the default arrow will be set. - /// 3. Otherwise, the four headed arrow will be set to indicate that the component can - /// be clicked and moved. - /// 4. If the user is currently dragging a component, the crosshair cursor will be used - /// instead of the four headed arrow. + /// Returns a collection of Glyph objects representing the selection borders and grab handles for a standard control. Note that based on 'selectionType' the Glyphs returned will either: represent a fully resizeable selection border with grab handles, a locked selection border, or a single 'hidden' selection Glyph. /// - protected virtual void OnSetCursor() + public virtual GlyphCollection GetGlyphs(GlyphSelectionType selectionType) { - throw new NotImplementedException(SR.NotImplementedByDesign); + GlyphCollection glyphs = new GlyphCollection(); + if (selectionType != GlyphSelectionType.NotSelected) + { + Rectangle translatedBounds = BehaviorService.ControlRectInAdornerWindow(Control); + bool primarySelection = (selectionType == GlyphSelectionType.SelectedPrimary); + SelectionRules rules = SelectionRules; + if ((Locked) || (InheritanceAttribute == InheritanceAttribute.InheritedReadOnly)) + { + // the lock glyph + glyphs.Add(new LockedHandleGlyph(translatedBounds, primarySelection)); + //the four locked border glyphs + glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Top)); + glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Bottom)); + glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Left)); + glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Right)); + } + else if ((rules & SelectionRules.AllSizeable) == SelectionRules.None) + { + //the non-resizeable grab handle + glyphs.Add(new NoResizeHandleGlyph(translatedBounds, rules, primarySelection, MoveBehavior)); + //the four resizeable border glyphs + glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Top, MoveBehavior)); + glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Bottom, MoveBehavior)); + glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Left, MoveBehavior)); + glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Right, MoveBehavior)); + // enable the designeractionpanel for this control if it needs one + if (TypeDescriptor.GetAttributes(Component).Contains(DesignTimeVisibleAttribute.Yes) && _behaviorService.DesignerActionUI != null) + { + Glyph dapGlyph = _behaviorService.DesignerActionUI.GetDesignerActionGlyph(Component); + if (dapGlyph != null) + { + glyphs.Insert(0, dapGlyph); //we WANT to be in front of the other UI + } + } + } + else + { + //grab handles + if ((rules & SelectionRules.TopSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.MiddleTop, StandardBehavior, primarySelection)); + if ((rules & SelectionRules.LeftSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.UpperLeft, StandardBehavior, primarySelection)); + } + if ((rules & SelectionRules.RightSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.UpperRight, StandardBehavior, primarySelection)); + } + } + + if ((rules & SelectionRules.BottomSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.MiddleBottom, StandardBehavior, primarySelection)); + if ((rules & SelectionRules.LeftSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.LowerLeft, StandardBehavior, primarySelection)); + } + if ((rules & SelectionRules.RightSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.LowerRight, StandardBehavior, primarySelection)); + } + } + + if ((rules & SelectionRules.LeftSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.MiddleLeft, StandardBehavior, primarySelection)); + } + + if ((rules & SelectionRules.RightSizeable) != 0) + { + glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.MiddleRight, StandardBehavior, primarySelection)); + } + + //the four resizeable border glyphs + glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Top, StandardBehavior)); + glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Bottom, StandardBehavior)); + glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Left, StandardBehavior)); + glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Right, StandardBehavior)); + // enable the designeractionpanel for this control if it needs one + if (TypeDescriptor.GetAttributes(Component).Contains(DesignTimeVisibleAttribute.Yes) && _behaviorService.DesignerActionUI != null) + { + Glyph dapGlyph = _behaviorService.DesignerActionUI.GetDesignerActionGlyph(Component); + if (dapGlyph != null) + { + glyphs.Insert(0, dapGlyph); //we WANT to be in front of the other UI + } + } + } + } + return glyphs; } - /// - /// Allows a designer to filter the set of properties - /// the component it is designing will expose through the - /// TypeDescriptor object. This method is called - /// immediately before its corresponding "Post" method. - /// If you are overriding this method you should call - /// the base implementation before you perform your own - /// filtering. - /// - protected override void PreFilterProperties(IDictionary properties) + internal virtual Behavior.Behavior StandardBehavior { - throw new NotImplementedException(SR.NotImplementedByDesign); + get + { + if (_resizeBehavior == null) + { + _resizeBehavior = new ResizeBehavior(Component.Site); + } + return _resizeBehavior; + } } - /// - /// Hooks the children of the given control. We need to do this for - /// child controls that are not in design mode, which is the case - /// for composite controls. - /// - protected void UnhookChildControls(Control firstChild) + internal virtual bool SerializePerformLayout { - throw new NotImplementedException(SR.NotImplementedByDesign); + get => false; } /// - /// This method should be called by the extending designer for each message - /// the control would normally receive. This allows the designer to pre-process - /// messages before allowing them to be routed to the control. + /// Allows your component to support a design time user interface. A TabStrip control, for example, has a design time user interface that allows the user to click the tabs to change tabs. To implement this, TabStrip returns true whenever the given point is within its tabs. /// - protected virtual void WndProc(ref Message m) + protected virtual bool GetHitTest(Point point) { - throw new NotImplementedException(SR.NotImplementedByDesign); + return false; } - [ComVisible(true)] - public class ControlDesignerAccessibleObject : AccessibleObject + /// + /// Hooks the children of the given control. We need to do this for child controls that are not in design mode, which is the case for composite controls. + /// + protected void HookChildControls(Control firstChild) { - public ControlDesignerAccessibleObject(ControlDesigner designer, Control control) + foreach (Control child in firstChild.Controls) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (child != null && _host != null) + { + if (!(_host.GetDesigner(child) is ControlDesigner)) + { + // No, no designer means we must replace the window target in this control. + IWindowTarget oldTarget = child.WindowTarget; + if (!(oldTarget is ChildWindowTarget)) + { + child.WindowTarget = new ChildWindowTarget(this, child, oldTarget); + child.ControlAdded += new ControlEventHandler(OnControlAdded); + } + if (child.IsHandleCreated) + { + Application.OleRequired(); + UnsafeNativeMethods.RevokeDragDrop(child.Handle); + HookChildHandles(child.Handle); + } + else + { + child.HandleCreated += new EventHandler(OnChildHandleCreated); + } + // We only hook the children's children if there was no designer. We leave it up to the designer to hook its own children. + HookChildControls(child); + } + } } + } - public override Rectangle Bounds => throw new NotImplementedException(SR.NotImplementedByDesign); + private void OnChildHandleCreated(object sender, EventArgs e) + { + Control child = sender as Control; - public override string Description => throw new NotImplementedException(SR.NotImplementedByDesign); + Debug.Assert(child != null); - public override string DefaultAction => throw new NotImplementedException(SR.NotImplementedByDesign); + if (child != null) + { + Debug.Assert(child.IsHandleCreated); + HookChildHandles(child.Handle); + } + } - public override string Name => throw new NotImplementedException(SR.NotImplementedByDesign); + /// + /// Called by the host when we're first initialized. + /// + public override void Initialize(IComponent component) + { + // Visibility works as follows: If the control's property is not actually set, then set our shadow to true. Otherwise, grab the shadow value from the control directly and then set the control to be visible if it is not the root component. Root components will be set to visible = true in their own time by the view. + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(component.GetType()); + PropertyDescriptor visibleProp = props["Visible"]; + if (visibleProp == null || visibleProp.PropertyType != typeof(bool) || !visibleProp.ShouldSerializeValue(component)) + { + Visible = true; + } + else + { + Visible = (bool)visibleProp.GetValue(component); + } - public override AccessibleObject Parent => throw new NotImplementedException(SR.NotImplementedByDesign); + PropertyDescriptor enabledProp = props["Enabled"]; + if (enabledProp == null || enabledProp.PropertyType != typeof(bool) || !enabledProp.ShouldSerializeValue(component)) + { + Enabled = true; + } + else + { + Enabled = (bool)enabledProp.GetValue(component); + } + base.Initialize(component); + // And get other commonly used services. + _host = (IDesignerHost)GetService(typeof(IDesignerHost)); + + // this is to create the action in the DAP for this component if it requires docking/undocking logic + AttributeCollection attributes = TypeDescriptor.GetAttributes(Component); + DockingAttribute dockingAttribute = (DockingAttribute)attributes[typeof(DockingAttribute)]; + if (dockingAttribute != null && dockingAttribute.DockingBehavior != DockingBehavior.Never) + { + // create the action for this control + _dockingAction = new DockingActionList(this); + //add our 'dock in parent' or 'undock in parent' action + if (GetService(typeof(DesignerActionService)) is DesignerActionService das) + { + das.Add(Component, _dockingAction); + } + } + // Hook up the property change notifications we need to track. One for data binding. More for control add / remove notifications + _dataBindingsCollectionChanged = new CollectionChangeEventHandler(DataBindingsCollectionChanged); + Control.DataBindings.CollectionChanged += _dataBindingsCollectionChanged; - public override AccessibleRole Role => throw new NotImplementedException(SR.NotImplementedByDesign); + Control.ControlAdded += new ControlEventHandler(OnControlAdded); + Control.ControlRemoved += new ControlEventHandler(OnControlRemoved); + Control.ParentChanged += new EventHandler(OnParentChanged); - public override AccessibleStates State => throw new NotImplementedException(SR.NotImplementedByDesign); + Control.SizeChanged += new EventHandler(OnSizeChanged); + Control.LocationChanged += new EventHandler(OnLocationChanged); - public override string Value => throw new NotImplementedException(SR.NotImplementedByDesign); + // Replace the control's window target with our own. This allows us to hook messages. + DesignerTarget = new DesignerWindowTarget(this); - public override AccessibleObject GetChild(int index) + // If the handle has already been created for this control, invoke OnCreateHandle so we can hookup our child control subclass. + if (Control.IsHandleCreated) { - throw new NotImplementedException(SR.NotImplementedByDesign); + OnCreateHandle(); } - public override int GetChildCount() + // If we are an inherited control, notify our inheritance UI + if (Inherited && _host != null && _host.RootComponent != component) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _inheritanceUI = (InheritanceUI)GetService(typeof(InheritanceUI)); + if (_inheritanceUI != null) + { + _inheritanceUI.AddInheritedControl(Control, InheritanceAttribute.InheritanceLevel); + } } - public override AccessibleObject GetFocused() + // When we drag one control from one form to another, we will end up here. In this case we do not want to set the control to visible, so check ForceVisible. + if ((_host == null || _host.RootComponent != component) && ForceVisible) { - throw new NotImplementedException(SR.NotImplementedByDesign); + Control.Visible = true; } - public override AccessibleObject GetSelected() + // Always make controls enabled, event inherited ones. Otherwise we won't be able to select them. + Control.Enabled = true; + // we move enabledchanged below the set to avoid any possible stack overflows. this can occur if the parent is not enabled when we set enabled to true. + Control.EnabledChanged += new EventHandler(OnEnabledChanged); + // And force some shadow properties that we change in the course of initializing the form. + AllowDrop = Control.AllowDrop; + // update the Status Command + _statusCommandUI = new StatusCommandUI(component.Site); + } + + // This is a workaround to some problems with the ComponentCache that we should fix. When this is removed remember to change ComponentCache's RemoveEntry method back to private (from internal). + private void OnSizeChanged(object sender, EventArgs e) + { + System.ComponentModel.Design.Serialization.ComponentCache cache = + (System.ComponentModel.Design.Serialization.ComponentCache)GetService(typeof(System.ComponentModel.Design.Serialization.ComponentCache)); + object component = Component; + if (cache != null && component != null) { - throw new NotImplementedException(SR.NotImplementedByDesign); + cache.RemoveEntry(component); } + } - public override AccessibleObject HitTest(int x, int y) + private void OnLocationChanged(object sender, EventArgs e) + { + System.ComponentModel.Design.Serialization.ComponentCache cache = + (System.ComponentModel.Design.Serialization.ComponentCache)GetService(typeof(System.ComponentModel.Design.Serialization.ComponentCache)); + object component = Component; + if (cache != null && component != null) { - throw new NotImplementedException(SR.NotImplementedByDesign); + cache.RemoveEntry(component); } } - /// - /// This TransparentBehavior is associated with the BodyGlyph for - /// this ControlDesigner. When the BehaviorService hittests a glyph - /// w/a TransparentBehavior, all messages will be passed through - /// the BehaviorService directly to the ControlDesigner. - /// During a Drag operation, when the BehaviorService hittests - /// - internal class TransparentBehavior : Behavior.Behavior + private void OnParentChanged(object sender, EventArgs e) { - /// - /// Constructor that accepts the related ControlDesigner. - /// - internal TransparentBehavior(ControlDesigner designer) + if (Control.IsHandleCreated) { - throw new NotImplementedException(SR.NotImplementedByDesign); + OnHandleChange(); } + } - /// - /// This property performs a hit test on the ControlDesigner - /// to determine if the BodyGlyph should return '-1' for - /// hit testing (letting all messages pass directly to the - /// the control). - /// - internal bool IsTransparent(Point p) + private void OnControlRemoved(object sender, ControlEventArgs e) + { + if (e.Control != null) { - throw new NotImplementedException(SR.NotImplementedByDesign); + // No, no designer means we must replace the window target in this control. + if (e.Control.WindowTarget is ChildWindowTarget oldTarget) + { + e.Control.WindowTarget = oldTarget.OldWindowTarget; + } + UnhookChildControls(e.Control); } + } - /// - /// Forwards DragDrop notification from the BehaviorService to - /// the related ControlDesigner. - /// - public override void OnDragDrop(Glyph g, DragEventArgs e) + private void DataBindingsCollectionChanged(object sender, CollectionChangeEventArgs e) + { + // It is possible to use the control designer with NON CONTROl types. + if (Component is Control ctl) { - throw new NotImplementedException(SR.NotImplementedByDesign); + if (ctl.DataBindings.Count == 0 && _removalNotificationHooked) + { + // remove the notification for the ComponentRemoved event + IComponentChangeService csc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (csc != null) + { + csc.ComponentRemoved -= new ComponentEventHandler(DataSource_ComponentRemoved); + } + _removalNotificationHooked = false; + } + else if (ctl.DataBindings.Count > 0 && !_removalNotificationHooked) + { + // add he notification for the ComponentRemoved event + IComponentChangeService csc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (csc != null) + { + csc.ComponentRemoved += new ComponentEventHandler(DataSource_ComponentRemoved); + } + _removalNotificationHooked = true; + } } + } - /// - /// Forwards DragDrop notification from the BehaviorService to - /// the related ControlDesigner. - /// - public override void OnDragEnter(Glyph g, DragEventArgs e) + private void OnEnabledChanged(object sender, EventArgs e) + { + if (!_enabledchangerecursionguard) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _enabledchangerecursionguard = true; + try + { + Control.Enabled = true; + } + finally + { + _enabledchangerecursionguard = false; + } + } + } + + private bool AllowDrop + { + get => (bool)ShadowProperties["AllowDrop"]; + set => ShadowProperties["AllowDrop"] = value; + } + + private bool Enabled + { + get => (bool)ShadowProperties["Enabled"]; + set => ShadowProperties["Enabled"] = value; + } + + private bool Visible + { + get => (bool)ShadowProperties["Visible"]; + set => ShadowProperties["Visible"] = value; + } + + /// + /// ControlDesigner overrides this method to handle after-drop cases. + /// + public override void InitializeExistingComponent(IDictionary defaultValues) + { + base.InitializeExistingComponent(defaultValues); + // unhook any sited children that got ChildWindowTargets + foreach (Control c in Control.Controls) + { + if (c != null) + { + ISite site = c.Site; + if (site != null && c.WindowTarget is ChildWindowTarget target) + { + c.WindowTarget = target.OldWindowTarget; + } + } + } + } + + /// + /// ControlDesigner overrides this method. It will look at the default property for the control and, if it is of type string, it will set this property's value to the name of the component. It only does this if the designer has been configured with this option in the options service. This method also connects the control to its parent and positions it. If you override this method, you should always call base. + /// + public override void InitializeNewComponent(IDictionary defaultValues) + { + ISite site = Component.Site; + if (site != null) + { + PropertyDescriptor textProp = TypeDescriptor.GetProperties(Component)["Text"]; + if (textProp != null && textProp.PropertyType == typeof(string) && !textProp.IsReadOnly && textProp.IsBrowsable) + { + textProp.SetValue(Component, site.Name); + } + } + + if (defaultValues != null) + { + if (defaultValues["Parent"] is IComponent parent && GetService(typeof(IDesignerHost)) is IDesignerHost host) + { + if (host.GetDesigner(parent) is ParentControlDesigner parentDesigner) + { + parentDesigner.AddControl(Control, defaultValues); + } + + if (parent is Control parentControl) + { + // Some containers are docked differently (instead of DockStyle.None) when they are added through the designer + AttributeCollection attributes = TypeDescriptor.GetAttributes(Component); + DockingAttribute dockingAttribute = (DockingAttribute)attributes[typeof(DockingAttribute)]; + if (dockingAttribute != null && dockingAttribute.DockingBehavior != DockingBehavior.Never) + { + if (dockingAttribute.DockingBehavior == DockingBehavior.AutoDock) + { + bool onlyNonDockedChild = true; + foreach (Control c in parentControl.Controls) + { + if (c != Control && c.Dock == DockStyle.None) + { + onlyNonDockedChild = false; + break; + } + } + + if (onlyNonDockedChild) + { + PropertyDescriptor dockProp = TypeDescriptor.GetProperties(Component)["Dock"]; + if (dockProp != null && dockProp.IsBrowsable) + { + dockProp.SetValue(Component, DockStyle.Fill); + } + } + } + } + } + } + } + base.InitializeNewComponent(defaultValues); + } + + /// + /// Called when the designer is intialized. This allows the designer to provide some meaningful default values in the component. The default implementation of this sets the components's default property to it's name, if that property is a string. + /// + [Obsolete("This method has been deprecated. Use InitializeNewComponent instead. http://go.microsoft.com/fwlink/?linkid=14202")] + public override void OnSetComponentDefaults() + { + ISite site = Component.Site; + if (site != null) + { + PropertyDescriptor textProp = TypeDescriptor.GetProperties(Component)["Text"]; + if (textProp != null && textProp.IsBrowsable) + { + textProp.SetValue(Component, site.Name); + } + } + } + + /// + /// Called when the context menu should be displayed + /// + protected virtual void OnContextMenu(int x, int y) + { + ShowContextMenu(x, y); + } + + /// + /// This is called immediately after the control handle has been created. + /// + protected virtual void OnCreateHandle() + { + OnHandleChange(); + if (_revokeDragDrop) + { + UnsafeNativeMethods.RevokeDragDrop(Control.Handle); + } + } + + /// + /// Called when a drag-drop operation enters the control designer view + /// + protected virtual void OnDragEnter(DragEventArgs de) + { + // unhook our events - we don't want to create an infinite loop. + Control control = Control; + DragEventHandler handler = new DragEventHandler(OnDragEnter); + control.DragEnter -= handler; + ((IDropTarget)Control).OnDragEnter(de); + control.DragEnter += handler; + } + + /// + /// Called to cleanup a D&D operation + /// + protected virtual void OnDragComplete(DragEventArgs de) + { + // default implementation - does nothing. + } + + /// + /// Called when a drag drop object is dropped onto the control designer view + /// + protected virtual void OnDragDrop(DragEventArgs de) + { + // unhook our events - we don't want to create an infinite loop. + Control control = Control; + DragEventHandler handler = new DragEventHandler(OnDragDrop); + control.DragDrop -= handler; + ((IDropTarget)Control).OnDragDrop(de); + control.DragDrop += handler; + OnDragComplete(de); + } + + /// + /// Called when a drag-drop operation leaves the control designer view + /// + protected virtual void OnDragLeave(EventArgs e) + { + // unhook our events - we don't want to create an infinite loop. + Control control = Control; + EventHandler handler = new EventHandler(OnDragLeave); + control.DragLeave -= handler; + ((IDropTarget)Control).OnDragLeave(e); + control.DragLeave += handler; + } + + /// + /// Called when a drag drop object is dragged over the control designer view + /// + protected virtual void OnDragOver(DragEventArgs de) + { + // unhook our events - we don't want to create an infinite loop. + Control control = Control; + DragEventHandler handler = new DragEventHandler(OnDragOver); + control.DragOver -= handler; + ((IDropTarget)Control).OnDragOver(de); + control.DragOver += handler; + } + + /// + /// Event handler for our GiveFeedback event, which is called when a drag operation is in progress. The host will call us with this when an OLE drag event happens. + /// + protected virtual void OnGiveFeedback(GiveFeedbackEventArgs e) + { + } + + /// + /// Called in response to the left mouse button being pressed on a component. It ensures that the component is selected. + /// + protected virtual void OnMouseDragBegin(int x, int y) + { + // Ignore another mouse down if we are already in a drag. + if (BehaviorService == null && _mouseDragLast != InvalidPoint) + { + return; + } + _mouseDragLast = new Point(x, y); + _ctrlSelect = (Control.ModifierKeys & Keys.Control) != 0; + ISelectionService sel = (ISelectionService)GetService(typeof(ISelectionService)); + // If the CTRL key isn't down, select this component, otherwise, we wait until the mouse up. Make sure the component is selected + if (!_ctrlSelect && sel != null) + { + sel.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary); + } + Control.Capture = true; + } + + /// + /// Called at the end of a drag operation. This either commits or rolls back the drag. + /// + protected virtual void OnMouseDragEnd(bool cancel) + { + _mouseDragLast = InvalidPoint; + Control.Capture = false; + if (!_mouseDragMoved) + { + // ParentControlDesigner.Dispose depends on cancel having this behavior. + if (!cancel) + { + ISelectionService sel = (ISelectionService)GetService(typeof(ISelectionService)); + bool shiftSelect = (Control.ModifierKeys & Keys.Shift) != 0; + if (!shiftSelect && (_ctrlSelect || (sel != null && !sel.GetComponentSelected(Component)))) + { + if (sel != null) + { + sel.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary); + } + _ctrlSelect = false; + } + } + return; + } + _mouseDragMoved = false; + _ctrlSelect = false; + // And now finish the drag. + if (BehaviorService != null && BehaviorService.Dragging && cancel) + { + BehaviorService.CancelDrag = true; + } + // Leave this here in case we are doing a ComponentTray drag + if (_selectionUISvc == null) + { + _selectionUISvc = (ISelectionUIService)GetService(typeof(ISelectionUIService)); + } + + if (_selectionUISvc == null) + { + return; + } + + // We must check to ensure that UI service is still in drag mode. It is possible that the user hit escape, which will cancel drag mode. + if (_selectionUISvc.Dragging) + { + _selectionUISvc.EndDrag(cancel); + } + } + + /// + /// Called for each movement of the mouse. This will check to see if a drag operation is in progress. If so, it will pass the updated drag dimensions on to the selection UI service. + /// + protected virtual void OnMouseDragMove(int x, int y) + { + if (!_mouseDragMoved) + { + Size minDrag = SystemInformation.DragSize; + Size minDblClick = SystemInformation.DoubleClickSize; + minDrag.Width = Math.Max(minDrag.Width, minDblClick.Width); + minDrag.Height = Math.Max(minDrag.Height, minDblClick.Height); + // we have to make sure the mouse moved farther than the minimum drag distance before we actually start the drag + if (_mouseDragLast == InvalidPoint || + (Math.Abs(_mouseDragLast.X - x) < minDrag.Width && + Math.Abs(_mouseDragLast.Y - y) < minDrag.Height)) + { + return; + } + else + { + _mouseDragMoved = true; + // we're on the move, so we're not in a ctrlSelect + _ctrlSelect = false; + } + } + + // Make sure the component is selected + // But only select it if it is not already the primary selection, and we want to toggle the current primary selection. + ISelectionService sel = (ISelectionService)GetService(typeof(ISelectionService)); + if (sel != null && !Component.Equals(sel.PrimarySelection)) + { + sel.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary | SelectionTypes.Toggle); + } + + if (BehaviorService != null && sel != null) + { + //create our list of controls-to-drag + ArrayList dragControls = new ArrayList(); + ICollection selComps = sel.GetSelectedComponents(); + //must identify a required parent to avoid dragging mixes of children + Control requiredParent = null; + foreach (IComponent comp in selComps) + { + if (comp is Control control) + { + if (requiredParent == null) + { + requiredParent = control.Parent; + } + else if (!requiredParent.Equals(control.Parent)) + { + continue;//mixed selection of different parents - don't add this + } + + if (_host.GetDesigner(comp) is ControlDesigner des && (des.SelectionRules & SelectionRules.Moveable) != 0) + { + dragControls.Add(comp); + } + } + } + + //if we have controls-to-drag, create our new behavior and start the drag/drop operation + if (dragControls.Count > 0) + { + using (Graphics adornerGraphics = BehaviorService.AdornerWindowGraphics) + { + DropSourceBehavior dsb = new DropSourceBehavior(dragControls, Control.Parent, _mouseDragLast); + BehaviorService.DoDragDrop(dsb); + } + } + } + + _mouseDragLast = InvalidPoint; + _mouseDragMoved = false; + } + + /// + /// Called when the mouse first enters the control. This is forwarded to the parent designer to enable the container selector. + /// + protected virtual void OnMouseEnter() + { + Control ctl = Control; + Control parent = ctl; + object parentDesigner = null; + while (parentDesigner == null && parent != null) + { + parent = parent.Parent; + if (parent != null) + { + object d = _host.GetDesigner(parent); + if (d != this) + { + parentDesigner = d; + } + } + } + + if (parentDesigner is ControlDesigner cd) + { + cd.OnMouseEnter(); + } + } + + /// + /// Called after the mouse hovers over the control. This is forwarded to the parent designer to enabled the container selector. + /// Called after the mouse hovers over the control. This is forwarded to the parent + /// designer to enabled the container selector. + /// + protected virtual void OnMouseHover() + { + Control ctl = Control; + Control parent = ctl; + object parentDesigner = null; + while (parentDesigner == null && parent != null) + { + parent = parent.Parent; + if (parent != null) + { + object d = _host.GetDesigner(parent); + if (d != this) + { + parentDesigner = d; + } + } + } + + if (parentDesigner is ControlDesigner cd) + { + cd.OnMouseHover(); + } + } + + /// + /// Called when the mouse first enters the control. This is forwarded to the parent designer to enable the container selector. + /// + protected virtual void OnMouseLeave() + { + Control ctl = Control; + Control parent = ctl; + object parentDesigner = null; + while (parentDesigner == null && parent != null) + { + parent = parent.Parent; + if (parent != null) + { + object d = _host.GetDesigner(parent); + if (d != this) + { + parentDesigner = d; + } + } + } + + if (parentDesigner is ControlDesigner cd) + { + cd.OnMouseLeave(); + } + } + + /// + /// Called when the control we're designing has finished painting. This method gives the designer a chance to paint any additional adornments on top of the control. + /// + protected virtual void OnPaintAdornments(PaintEventArgs pe) + { + + // If this control is being inherited, paint it + if (_inheritanceUI != null && pe.ClipRectangle.IntersectsWith(_inheritanceUI.InheritanceGlyphRectangle)) + { + pe.Graphics.DrawImage(_inheritanceUI.InheritanceGlyph, 0, 0); + } + } + + /// + /// Called each time the cursor needs to be set. The ControlDesigner behavior here will set the cursor to one of three things: + /// 1. If the toolbox service has a tool selected, it will allow the toolbox service to set the cursor. + /// 2. If the selection UI service shows a locked selection, or if there is no location property on the control, then the default arrow will be set. + /// 3. Otherwise, the four headed arrow will be set to indicate that the component can be clicked and moved. + /// 4. If the user is currently dragging a component, the crosshair cursor will be used instead of the four headed arrow. + /// + protected virtual void OnSetCursor() + { + if (Control.Dock != DockStyle.None) + { + Cursor.Current = Cursors.Default; + } + else + { + if (_toolboxSvc == null) + { + _toolboxSvc = (IToolboxService)GetService(typeof(IToolboxService)); + } + + if (_toolboxSvc != null && _toolboxSvc.SetCursor()) + { + return; + } + + if (!_locationChecked) + { + _locationChecked = true; + try + { + _hasLocation = TypeDescriptor.GetProperties(Component)["Location"] != null; + } + catch + { + } + } + + if (!_hasLocation) + { + Cursor.Current = Cursors.Default; + return; + } + + if (Locked) + { + Cursor.Current = Cursors.Default; + return; + } + Cursor.Current = Cursors.SizeAll; + } + } + + private bool Locked + { + get => _locked; + set => _locked = value; + } + + /// + /// Allows a designer to filter the set of properties the component it is designing will expose through the TypeDescriptor object. This method is called immediately before its corresponding "Post" method. If you are overriding this method you should call the base implementation before you perform your own filtering. + /// + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + PropertyDescriptor prop; + // Handle shadowed properties + string[] shadowProps = new string[] { "Visible", "Enabled", "ContextMenu", "AllowDrop", "Location", "Name" }; + + Attribute[] empty = new Attribute[0]; + for (int i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ControlDesigner), prop, empty); + } + } + + // replace this one seperately because it is of a different type (DesignerControlCollection) than the original property (ControlCollection) + PropertyDescriptor controlsProp = (PropertyDescriptor)properties["Controls"]; + + if (controlsProp != null) + { + Attribute[] attrs = new Attribute[controlsProp.Attributes.Count]; + controlsProp.Attributes.CopyTo(attrs, 0); + properties["Controls"] = TypeDescriptor.CreateProperty(typeof(ControlDesigner), "Controls", typeof(DesignerControlCollection), attrs); + } + + PropertyDescriptor sizeProp = (PropertyDescriptor)properties["Size"]; + if (sizeProp != null) + { + properties["Size"] = new CanResetSizePropertyDescriptor(sizeProp); + } + + // Now we add our own design time properties. + properties["Locked"] = TypeDescriptor .CreateProperty(typeof(ControlDesigner), "Locked", typeof(bool), new DefaultValueAttribute(false), BrowsableAttribute.Yes, CategoryAttribute.Design, DesignOnlyAttribute.Yes, new SRDescriptionAttribute(SR.lockedDescr)); + } + + /// + /// Hooks the children of the given control. We need to do this for child controls that are not in design mode, which is the case for composite controls. + /// + protected void UnhookChildControls(Control firstChild) + { + if (_host == null) + { + _host = (IDesignerHost)GetService(typeof(IDesignerHost)); + } + + foreach (Control child in firstChild.Controls) + { + IWindowTarget oldTarget = null; + if (child != null) + { + // No, no designer means we must replace the window target in this control. + oldTarget = child.WindowTarget; + if (oldTarget is ChildWindowTarget target) + { + child.WindowTarget = target.OldWindowTarget; + } + } + if (!(oldTarget is DesignerWindowTarget)) + { + UnhookChildControls(child); + } + } + } + + /// + /// This method should be called by the extending designer for each message the control would normally receive. This allows the designer to pre-process messages before allowing them to be routed to the control. + /// + protected virtual void WndProc(ref Message m) + { + IMouseHandler mouseHandler = null; + // We look at WM_NCHITTEST to determine if the mouse is in a live region of the control + if (m.Msg == Interop.WindowMessages.WM_NCHITTEST) + { + if (!_inHitTest) + { + _inHitTest = true; + Point pt = new Point((short)NativeMethods.Util.LOWORD(unchecked((int)(long)m.LParam)), (short)NativeMethods.Util.HIWORD(unchecked((int)(long)m.LParam))); + try + { + _liveRegion = GetHitTest(pt); + } + catch (Exception e) + { + _liveRegion = false; + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + _inHitTest = false; + } + } + + // Check to see if the mouse is in a live region of the control and that the context key is not being fired + bool isContextKey = (m.Msg == Interop.WindowMessages.WM_CONTEXTMENU); + if (_liveRegion && (IsMouseMessage(m.Msg) || isContextKey)) + { + // The ActiveX DataGrid control brings up a context menu on right mouse down when it is in edit mode. + // And, when we generate a WM_CONTEXTMENU message later, it calls DefWndProc() which by default calls the parent (formdesigner). The FormDesigner then brings up the AxHost context menu. This code causes recursive WM_CONTEXTMENU messages to be ignored till we return from the live region message. + if (m.Msg == Interop.WindowMessages.WM_CONTEXTMENU) + { + Debug.Assert(!s_inContextMenu, "Recursively hitting live region for context menu!!!"); + s_inContextMenu = true; + } + + try + { + DefWndProc(ref m); + } + finally + { + if (m.Msg == Interop.WindowMessages.WM_CONTEXTMENU) + { + s_inContextMenu = false; + } + if (m.Msg == Interop.WindowMessages.WM_LBUTTONUP) + { + // terminate the drag. TabControl loses shortcut menu options after adding ActiveX control. + OnMouseDragEnd(true); + } + + } + return; + } + + // Get the x and y coordniates of the mouse message + int x = 0, y = 0; + + // Look for a mouse handler. + // CONSIDER - I really don't like this one bit. We need a + // : centralized handler so we can do a global override for the tab order + // : UI, but the designer is a natural fit for an object oriented UI. + if (m.Msg >= Interop.WindowMessages.WM_MOUSEFIRST && m.Msg <= Interop.WindowMessages.WM_MOUSELAST + || m.Msg >= Interop.WindowMessages.WM_NCMOUSEMOVE && m.Msg <= Interop.WindowMessages.WM_NCMBUTTONDBLCLK + || m.Msg == Interop.WindowMessages.WM_SETCURSOR) + { + if (_eventSvc == null) + { + _eventSvc = (IEventHandlerService)GetService(typeof(IEventHandlerService)); + } + if (_eventSvc != null) + { + mouseHandler = (IMouseHandler)_eventSvc.GetHandler(typeof(IMouseHandler)); + } + } + + if (m.Msg >= Interop.WindowMessages.WM_MOUSEFIRST && m.Msg <= Interop.WindowMessages.WM_MOUSELAST) + { + NativeMethods.POINT pt = new NativeMethods.POINT + { + x = NativeMethods.Util.SignedLOWORD(unchecked((int)(long)m.LParam)), + y = NativeMethods.Util.SignedHIWORD(unchecked((int)(long)m.LParam)) + }; + NativeMethods.MapWindowPoints(m.HWnd, IntPtr.Zero, pt, 1); + x = pt.x; + y = pt.y; + } + else if (m.Msg >= Interop.WindowMessages.WM_NCMOUSEMOVE && m.Msg <= Interop.WindowMessages.WM_NCMBUTTONDBLCLK) + { + x = NativeMethods.Util.SignedLOWORD(unchecked((int)(long)m.LParam)); + y = NativeMethods.Util.SignedHIWORD(unchecked((int)(long)m.LParam)); + } + + // This is implemented on the base designer for UI activation support. We call it so that we can support UI activation. + MouseButtons button = MouseButtons.None; + switch (m.Msg) + { + case Interop.WindowMessages.WM_CREATE: + DefWndProc(ref m); + // Only call OnCreateHandle if this is our OWN window handle -- the designer window procs are re-entered for child controls. + if (m.HWnd == Control.Handle) + { + OnCreateHandle(); + } + break; + + case Interop.WindowMessages.WM_GETOBJECT: + // See "How to Handle WM_GETOBJECT" in MSDN + if (NativeMethods.OBJID_CLIENT == unchecked((int)(long)m.LParam)) + { + Guid IID_IAccessible = new Guid(NativeMethods.uuid_IAccessible); + // Get an Lresult for the accessibility Object for this control + IntPtr punkAcc; + try + { + IAccessible iacc = (IAccessible)AccessibilityObject; + if (iacc == null) + { + // Accessibility is not supported on this control + m.Result = (IntPtr)0; + } + else + { + // Obtain the Lresult + punkAcc = Marshal.GetIUnknownForObject(iacc); + try + { + m.Result = UnsafeNativeMethods.LresultFromObject(ref IID_IAccessible, m.WParam, punkAcc); + } + finally + { + Marshal.Release(punkAcc); + } + } + } + catch (Exception e) + { + throw e; + } + } + else + { // m.lparam != OBJID_CLIENT, so do default message processing + DefWndProc(ref m); + } + break; + + case Interop.WindowMessages.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_NCMOUSEHOVER: + case Interop.WindowMessages.WM_NCMOUSELEAVE: + case Interop.WindowMessages.WM_MOUSEWHEEL: + case Interop.WindowMessages.WM_NCMBUTTONDOWN: + case Interop.WindowMessages.WM_NCMBUTTONUP: + case Interop.WindowMessages.WM_NCMBUTTONDBLCLK: + // We intentionally eat these messages. + break; + case Interop.WindowMessages.WM_MOUSEHOVER: + if (mouseHandler != null) + { + mouseHandler.OnMouseHover(Component); + } + else + { + OnMouseHover(); + } + break; + case Interop.WindowMessages.WM_MOUSELEAVE: + OnMouseLeave(); + BaseWndProc(ref m); + break; + case Interop.WindowMessages.WM_NCLBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_NCRBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: + if ((m.Msg == Interop.WindowMessages.WM_NCRBUTTONDBLCLK || m.Msg == Interop.WindowMessages.WM_RBUTTONDBLCLK)) + { + button = MouseButtons.Right; + } + else + { + button = MouseButtons.Left; + } + if (button == MouseButtons.Left) + { + // We handle doubleclick messages, and we also process our own simulated double clicks for controls that don't specify CS_WANTDBLCLKS. + if (mouseHandler != null) + { + mouseHandler.OnMouseDoubleClick(Component); + } + else + { + OnMouseDoubleClick(); + } + } + break; + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: + if ((m.Msg == Interop.WindowMessages.WM_NCRBUTTONDOWN || m.Msg == Interop.WindowMessages.WM_RBUTTONDOWN)) + { + button = MouseButtons.Right; + } + else + { + button = MouseButtons.Left; + } + // We don't really want the focus, but we want to focus the designer. Below we handle WM_SETFOCUS and do the right thing. + NativeMethods.SendMessage(Control.Handle, Interop.WindowMessages.WM_SETFOCUS, 0, 0); + // We simulate doubleclick for things that don't... + if (button == MouseButtons.Left && IsDoubleClick(x, y)) + { + if (mouseHandler != null) + { + mouseHandler.OnMouseDoubleClick(Component); + } + else + { + OnMouseDoubleClick(); + } + } + else + { + _toolPassThrough = false; + if (!EnableDragRect && button == MouseButtons.Left) + { + if (_toolboxSvc == null) + { + _toolboxSvc = (IToolboxService)GetService(typeof(IToolboxService)); + } + + if (_toolboxSvc != null && _toolboxSvc.GetSelectedToolboxItem((IDesignerHost)GetService(typeof(IDesignerHost))) != null) + { + // there is a tool to be dragged, so set passthrough and pass to the parent. + _toolPassThrough = true; + } + } + else + { + _toolPassThrough = false; + } + + + if (_toolPassThrough) + { + NativeMethods.SendMessage(Control.Parent.Handle, m.Msg, m.WParam, (IntPtr)GetParentPointFromLparam(m.LParam)); + return; + } + + if (mouseHandler != null) + { + mouseHandler.OnMouseDown(Component, button, x, y); + } + else if (button == MouseButtons.Left) + { + OnMouseDragBegin(x, y); + + } + else if (button == MouseButtons.Right) + { + ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { Component }, SelectionTypes.Primary); + } + } + _lastMoveScreenX = x; + _lastMoveScreenY = y; + } + break; + + case Interop.WindowMessages.WM_NCMOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: + if ((unchecked((int)(long)m.WParam) & NativeMethods.MK_LBUTTON) != 0) + { + button = MouseButtons.Left; + } + else if ((unchecked((int)(long)m.WParam) & NativeMethods.MK_RBUTTON) != 0) + { + button = MouseButtons.Right; + _toolPassThrough = false; + } + else + { + _toolPassThrough = false; + } + + if (_lastMoveScreenX != x || _lastMoveScreenY != y) + { + if (_toolPassThrough) + { + NativeMethods.SendMessage(Control.Parent.Handle, m.Msg, m.WParam, (IntPtr)GetParentPointFromLparam(m.LParam)); + return; + } + + if (mouseHandler != null) + { + mouseHandler.OnMouseMove(Component, x, y); + } + else if (button == MouseButtons.Left) + { + OnMouseDragMove(x, y); + } + } + _lastMoveScreenX = x; + _lastMoveScreenY = y; + + // We eat WM_NCMOUSEMOVE messages, since we don't want the non-client area/ of design time controls to repaint on mouse move. + if (m.Msg == Interop.WindowMessages.WM_MOUSEMOVE) + { + BaseWndProc(ref m); + } + break; + case Interop.WindowMessages.WM_NCLBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_NCRBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: + // This is implemented on the base designer for UI activation support. + if ((m.Msg == Interop.WindowMessages.WM_NCRBUTTONUP || m.Msg == Interop.WindowMessages.WM_RBUTTONUP)) + { + button = MouseButtons.Right; + } + else + { + button = MouseButtons.Left; + } + + // And terminate the drag. + if (mouseHandler != null) + { + mouseHandler.OnMouseUp(Component, button); + } + else + { + if (_toolPassThrough) + { + NativeMethods.SendMessage(Control.Parent.Handle, m.Msg, m.WParam, (IntPtr)GetParentPointFromLparam(m.LParam)); + _toolPassThrough = false; + return; + } + + if (button == MouseButtons.Left) + { + OnMouseDragEnd(false); + } + } + // clear any pass through. + _toolPassThrough = false; + BaseWndProc(ref m); + break; + case Interop.WindowMessages.WM_PRINTCLIENT: + { + using (Graphics g = Graphics.FromHdc(m.WParam)) + { + using (PaintEventArgs e = new PaintEventArgs(g, Control.ClientRectangle)) + { + DefWndProc(ref m); + OnPaintAdornments(e); + } + } + } + break; + case Interop.WindowMessages.WM_PAINT: + // First, save off the update region and call our base class. + if (OleDragDropHandler.FreezePainting) + { + SafeNativeMethods.ValidateRect(m.HWnd, IntPtr.Zero); + break; + } + if (Control == null) + { + break; + } + NativeMethods.RECT clip = new NativeMethods.RECT(); + IntPtr hrgn = NativeMethods.CreateRectRgn(0, 0, 0, 0); + NativeMethods.GetUpdateRgn(m.HWnd, hrgn, false); + NativeMethods.GetUpdateRect(m.HWnd, ref clip, false); + Region r = Region.FromHrgn(hrgn); + Rectangle paintRect = Rectangle.Empty; + try + { + // Call the base class to do its own painting. + if (_thrownException == null) + { + DefWndProc(ref m); + } + + // Now do our own painting. + Graphics gr = Graphics.FromHwnd(m.HWnd); + try + { + if (m.HWnd != Control.Handle) + { + // Re-map the clip rect we pass to the paint event args to our child coordinates. + NativeMethods.POINT pt = new NativeMethods.POINT + { + x = 0, + y = 0 + }; + NativeMethods.MapWindowPoints(m.HWnd, Control.Handle, pt, 1); + gr.TranslateTransform(-pt.x, -pt.y); + NativeMethods.MapWindowPoints(m.HWnd, Control.Handle, ref clip, 2); + } + paintRect = new Rectangle(clip.left, clip.top, clip.right - clip.left, clip.bottom - clip.top); + PaintEventArgs pevent = new PaintEventArgs(gr, paintRect); + + try + { + gr.Clip = r; + if (_thrownException == null) + { + OnPaintAdornments(pevent); + } + else + { + NativeMethods.PAINTSTRUCT ps = new NativeMethods.PAINTSTRUCT(); + UnsafeNativeMethods.BeginPaint(m.HWnd, ref ps); + PaintException(pevent, _thrownException); + UnsafeNativeMethods.EndPaint(m.HWnd, ref ps); + } + } + finally + { + pevent.Dispose(); + } + } + finally + { + gr.Dispose(); + } + } + finally + { + r.Dispose(); + NativeMethods.DeleteObject(hrgn); + } + + if (OverlayService != null) + { + // this will allow any Glyphs to re-paint after this control and its designer has painted + paintRect.Location = Control.PointToScreen(paintRect.Location); + OverlayService.InvalidateOverlays(paintRect); + } + break; + case Interop.WindowMessages.WM_NCPAINT: + case Interop.WindowMessages.WM_NCACTIVATE: + if (m.Msg == Interop.WindowMessages.WM_NCACTIVATE) + { + DefWndProc(ref m); + } + else if (_thrownException == null) + { + DefWndProc(ref m); + } + + // For some reason we dont always get an NCPAINT with the WM_NCACTIVATE usually this repros with themes on.... this can happen when someone calls RedrawWindow without the flags to send an NCPAINT. So that we dont double process this event, our calls to redraw window should not have RDW_ERASENOW | RDW_UPDATENOW. + if (OverlayService != null) + { + if (Control != null && Control.Size != Control.ClientSize && Control.Parent != null) + { + // we have a non-client region to invalidate + Rectangle controlScreenBounds = new Rectangle(Control.Parent.PointToScreen(Control.Location), Control.Size); + Rectangle clientAreaScreenBounds = new Rectangle(Control.PointToScreen(Point.Empty), Control.ClientSize); + + using (Region nonClient = new Region(controlScreenBounds)) + { + nonClient.Exclude(clientAreaScreenBounds); + OverlayService.InvalidateOverlays(nonClient); + } + } + } + break; + + case Interop.WindowMessages.WM_SETCURSOR: + // We always handle setting the cursor ourselves. + // + + if (_liveRegion) + { + DefWndProc(ref m); + break; + } + + if (mouseHandler != null) + { + mouseHandler.OnSetCursor(Component); + } + else + { + OnSetCursor(); + } + break; + case Interop.WindowMessages.WM_SIZE: + if (_thrownException != null) + { + Control.Invalidate(); + } + DefWndProc(ref m); + break; + case Interop.WindowMessages.WM_CANCELMODE: + // When we get cancelmode (i.e. you tabbed away to another window) then we want to cancel any pending drag operation! + OnMouseDragEnd(true); + DefWndProc(ref m); + break; + case Interop.WindowMessages.WM_SETFOCUS: + // We eat the focus unless the target is a ToolStrip edit node (TransparentToolStrip). If we eat the focus in that case, the Windows Narrator won't follow navigation via the keyboard. + // NB: "ToolStrip" is a bit of a misnomer here, because the ToolStripTemplateNode is also used for MenuStrip, StatusStrip, etc... + //if (Control.FromHandle(m.HWnd) is ToolStripTemplateNode.TransparentToolStrip) + //{ + // DefWndProc(ref m); + //} + //else + if (_host != null && _host.RootComponent != null) + { + if (_host.GetDesigner(_host.RootComponent) is IRootDesigner rd) + { + ViewTechnology[] techs = rd.SupportedTechnologies; + if (techs.Length > 0) + { + if (rd.GetView(techs[0]) is Control view) + { + view.Focus(); + } + } + } + } + break; + case Interop.WindowMessages.WM_CONTEXTMENU: + if (s_inContextMenu) + { + break; + } + + // We handle this in addition to a right mouse button. Why? Because we often eat the right mouse button, so it may never generate a WM_CONTEXTMENU. However, the system may generate one in response to an F-10. + x = NativeMethods.Util.SignedLOWORD(unchecked((int)(long)m.LParam)); + y = NativeMethods.Util.SignedHIWORD(unchecked((int)(long)m.LParam)); + + ToolStripKeyboardHandlingService keySvc = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + bool handled = false; + if (keySvc != null) + { + handled = keySvc.OnContextMenu(x, y); + } + + if (!handled) + { + if (x == -1 && y == -1) + { + // for shift-F10 + Point p = Cursor.Position; + x = p.X; + y = p.Y; + } + OnContextMenu(x, y); + } + break; + default: + if (m.Msg == NativeMethods.WM_MOUSEENTER) + { + OnMouseEnter(); + BaseWndProc(ref m); + } + // We eat all key handling to the control. Controls generally should not be getting focus anyway, so this shouldn't happen. However, we want to prevent this as much as possible. + else if (m.Msg < Interop.WindowMessages.WM_KEYFIRST || m.Msg > Interop.WindowMessages.WM_KEYLAST) + { + DefWndProc(ref m); + } + break; + } + } + + private void PaintException(PaintEventArgs e, Exception ex) + { + StringFormat stringFormat = new StringFormat + { + Alignment = StringAlignment.Near, + LineAlignment = StringAlignment.Near + }; + string exceptionText = ex.ToString(); + stringFormat.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, exceptionText.Length) }); + + // rendering calculations... + int penThickness = 2; + Size glyphSize = SystemInformation.IconSize; + int marginX = penThickness * 2; + int marginY = penThickness * 2; + + Rectangle clientRectangle = Control.ClientRectangle; + Rectangle borderRectangle = clientRectangle; + borderRectangle.X++; + borderRectangle.Y++; + borderRectangle.Width -= 2; + borderRectangle.Height -= 2; + + Rectangle imageRect = new Rectangle(marginX, marginY, glyphSize.Width, glyphSize.Height); + Rectangle textRect = clientRectangle; + textRect.X = imageRect.X + imageRect.Width + 2 * marginX; + textRect.Y = imageRect.Y; + textRect.Width -= (textRect.X + marginX + penThickness); + textRect.Height -= (textRect.Y + marginY + penThickness); + + using (Font errorFont = new Font(Control.Font.FontFamily, Math.Max(SystemInformation.ToolWindowCaptionHeight - SystemInformation.BorderSize.Height - 2, Control.Font.Height), GraphicsUnit.Pixel)) + { + using (Region textRegion = e.Graphics.MeasureCharacterRanges(exceptionText, errorFont, textRect, stringFormat)[0]) + { + // paint contents... clipping optimizations for less flicker... + Region originalClip = e.Graphics.Clip; + e.Graphics.ExcludeClip(textRegion); + e.Graphics.ExcludeClip(imageRect); + try + { + e.Graphics.FillRectangle(Brushes.White, clientRectangle); + } + finally + { + e.Graphics.Clip = originalClip; + } + + using (Pen pen = new Pen(Color.Red, penThickness)) + { + e.Graphics.DrawRectangle(pen, borderRectangle); + } + + Icon err = SystemIcons.Error; + e.Graphics.FillRectangle(Brushes.White, imageRect); + e.Graphics.DrawIcon(err, imageRect.X, imageRect.Y); + textRect.X++; + e.Graphics.IntersectClip(textRegion); + try + { + e.Graphics.FillRectangle(Brushes.White, textRect); + e.Graphics.DrawString(exceptionText, errorFont, new SolidBrush(Control.ForeColor), textRect, stringFormat); + } + finally + { + e.Graphics.Clip = originalClip; + } + } + } + stringFormat.Dispose(); + } + + private IOverlayService OverlayService + { + get + { + if (_overlayService == null) + { + _overlayService = (IOverlayService)GetService(typeof(IOverlayService)); + } + return _overlayService; + } + } + + private bool IsMouseMessage(int msg) + { + if (msg >= Interop.WindowMessages.WM_MOUSEFIRST && msg <= Interop.WindowMessages.WM_MOUSELAST) + { + return true; + } + + switch (msg) + { + // WM messages not covered by the above block + case Interop.WindowMessages.WM_MOUSEHOVER: + case Interop.WindowMessages.WM_MOUSELEAVE: + // WM_NC messages + case Interop.WindowMessages.WM_NCMOUSEMOVE: + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + case Interop.WindowMessages.WM_NCLBUTTONUP: + case Interop.WindowMessages.WM_NCLBUTTONDBLCLK: + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + case Interop.WindowMessages.WM_NCRBUTTONUP: + case Interop.WindowMessages.WM_NCRBUTTONDBLCLK: + case Interop.WindowMessages.WM_NCMBUTTONDOWN: + case Interop.WindowMessages.WM_NCMBUTTONUP: + case Interop.WindowMessages.WM_NCMBUTTONDBLCLK: + case Interop.WindowMessages.WM_NCMOUSEHOVER: + case Interop.WindowMessages.WM_NCMOUSELEAVE: + case Interop.WindowMessages.WM_NCXBUTTONDOWN: + case Interop.WindowMessages.WM_NCXBUTTONUP: + case Interop.WindowMessages.WM_NCXBUTTONDBLCLK: + return true; + default: + return false; + } + } + + private bool IsDoubleClick(int x, int y) + { + bool doubleClick = false; + int wait = SystemInformation.DoubleClickTime; + int elapsed = SafeNativeMethods.GetTickCount() - _lastClickMessageTime; + if (elapsed <= wait) + { + Size dblClick = SystemInformation.DoubleClickSize; + if (x >= _lastClickMessagePositionX - dblClick.Width + && x <= _lastClickMessagePositionX + dblClick.Width + && y >= _lastClickMessagePositionY - dblClick.Height + && y <= _lastClickMessagePositionY + dblClick.Height) + { + doubleClick = true; + } + } + + if (!doubleClick) + { + _lastClickMessagePositionX = x; + _lastClickMessagePositionY = y; + _lastClickMessageTime = SafeNativeMethods.GetTickCount(); + } + else + { + _lastClickMessagePositionX = _lastClickMessagePositionY = 0; + _lastClickMessageTime = 0; + } + return doubleClick; + } + + private void OnMouseDoubleClick() + { + try + { + DoDefaultAction(); + } + catch (Exception e) + { + DisplayError(e); + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + } + + private int GetParentPointFromLparam(IntPtr lParam) + { + Point pt = new Point(NativeMethods.Util.SignedLOWORD(unchecked((int)(long)lParam)), NativeMethods.Util.SignedHIWORD(unchecked((int)(long)lParam))); + pt = Control.PointToScreen(pt); + pt = Control.Parent.PointToClient(pt); + return NativeMethods.Util.MAKELONG(pt.X, pt.Y); + } + + [ComVisible(true)] + public class ControlDesignerAccessibleObject : AccessibleObject + { + private readonly ControlDesigner _designer = null; + private readonly Control _control = null; + private IDesignerHost _host = null; + private ISelectionService _selSvc = null; + + public ControlDesignerAccessibleObject(ControlDesigner designer, Control control) + { + _designer = designer; + _control = control; + } + + public override Rectangle Bounds + { + get => _control.AccessibilityObject.Bounds; + } + + public override string Description + { + get => _control.AccessibilityObject.Description; + } + + private IDesignerHost DesignerHost + { + get + { + if (_host == null) + { + _host = (IDesignerHost)_designer.GetService(typeof(IDesignerHost)); + } + return _host; + } + } + + public override string DefaultAction + { + get => ""; + } + + public override string Name + { + get => _control.Name; + } + + public override AccessibleObject Parent + { + get => _control.AccessibilityObject.Parent; + } + + public override AccessibleRole Role + { + get => _control.AccessibilityObject.Role; + } + + private ISelectionService SelectionService + { + get + { + if (_selSvc == null) + { + _selSvc = (ISelectionService)_designer.GetService(typeof(ISelectionService)); + } + return _selSvc; + } + } + + public override AccessibleStates State + { + get + { + AccessibleStates state = _control.AccessibilityObject.State; + ISelectionService s = SelectionService; + if (s != null) + { + if (s.GetComponentSelected(_control)) + { + state |= AccessibleStates.Selected; + } + if (s.PrimarySelection == _control) + { + state |= AccessibleStates.Focused; + } + } + return state; + } + } + + public override string Value + { + get => _control.AccessibilityObject.Value; + } + + public override AccessibleObject GetChild(int index) + { + Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "ControlDesignerAccessibleObject.GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ")"); + if (_control.AccessibilityObject.GetChild(index) is Control.ControlAccessibleObject childAccObj) + { + AccessibleObject cao = GetDesignerAccessibleObject(childAccObj); + if (cao != null) + { + return cao; + } + } + return _control.AccessibilityObject.GetChild(index); + } + + public override int GetChildCount() => _control.AccessibilityObject.GetChildCount(); + + private AccessibleObject GetDesignerAccessibleObject(Control.ControlAccessibleObject cao) + { + if (cao == null) + { + return null; + } + if (DesignerHost.GetDesigner(cao.Owner) is ControlDesigner ctlDesigner) + { + return ctlDesigner.AccessibilityObject; + } + return null; + } + + public override AccessibleObject GetFocused() + { + if ((State & AccessibleStates.Focused) != 0) + { + return this; + } + return base.GetFocused(); + } + + public override AccessibleObject GetSelected() + { + if ((State & AccessibleStates.Selected) != 0) + { + return this; + } + return base.GetFocused(); + } + + public override AccessibleObject HitTest(int x, int y) => _control.AccessibilityObject.HitTest(x, y); + } + + /// + /// This TransparentBehavior is associated with the BodyGlyph for this ControlDesigner. When the BehaviorService hittests a glyph w/a TransparentBehavior, all messages will be passed through the BehaviorService directly to the ControlDesigner. During a Drag operation, when the BehaviorService hittests + /// + internal class TransparentBehavior : Behavior.Behavior + { + readonly ControlDesigner _designer; + Rectangle _controlRect = Rectangle.Empty; + + /// + /// Constructor that accepts the related ControlDesigner. + /// + internal TransparentBehavior(ControlDesigner designer) + { + _designer = designer; + } + + /// + /// This property performs a hit test on the ControlDesigner to determine if the BodyGlyph should return '-1' for hit testing (letting all messages pass directly to the the control). + /// + internal bool IsTransparent(Point p) => _designer.GetHitTest(p); + + /// + /// Forwards DragDrop notification from the BehaviorService to the related ControlDesigner. + /// + public override void OnDragDrop(Glyph g, DragEventArgs e) + { + _controlRect = Rectangle.Empty; + _designer.OnDragDrop(e); + } + + /// + /// Forwards DragDrop notification from the BehaviorService to the related ControlDesigner. + /// + public override void OnDragEnter(Glyph g, DragEventArgs e) + { + if (_designer != null && _designer.Control != null) + { + _controlRect = _designer.Control.RectangleToScreen(_designer.Control.ClientRectangle); + } + _designer.OnDragEnter(e); } /// - /// Forwards DragDrop notification from the BehaviorService to - /// the related ControlDesigner. + /// Forwards DragDrop notification from the BehaviorService to the related ControlDesigner. /// public override void OnDragLeave(Glyph g, EventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _controlRect = Rectangle.Empty; + _designer.OnDragLeave(e); } /// - /// Forwards DragDrop notification from the BehaviorService to - /// the related ControlDesigner. + /// Forwards DragDrop notification from the BehaviorService to the related ControlDesigner. /// public override void OnDragOver(Glyph g, DragEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + // If we are not over a valid drop area, then do not allow the drag/drop. Now that all dragging/dropping is done via the behavior service and adorner window, we have to do our own validation, and cannot rely on the OS to do it for us. + if (e != null && _controlRect != Rectangle.Empty && !_controlRect.Contains(new Point(e.X, e.Y))) + { + e.Effect = DragDropEffects.None; + return; + } + _designer.OnDragOver(e); } /// - /// Forwards DragDrop notification from the BehaviorService to - /// the related ControlDesigner. + /// Forwards DragDrop notification from the BehaviorService to the related ControlDesigner. /// public override void OnGiveFeedback(Glyph g, GiveFeedbackEventArgs e) { - throw new NotImplementedException(SR.NotImplementedByDesign); + _designer.OnGiveFeedback(e); + } + } + + [SuppressMessage("Microsoft.Performance", "CA1806:DoNotIgnoreMethodResults")] + internal void HookChildHandles(IntPtr firstChild) + { + IntPtr hwndChild = firstChild; + while (hwndChild != IntPtr.Zero) + { + if (!IsWindowInCurrentProcess(hwndChild)) + { + break; + } + + // Is it a control? + Control child = Control.FromHandle(hwndChild); + if (child == null) + { + // No control. We must subclass this control. + if (!SubclassedChildWindows.ContainsKey(hwndChild)) + { + // Some controls (primarily RichEdit) will register themselves as + // drag-drop source/targets when they are instantiated. Since these hwnds do not + // have a Windows Forms control associated with them, we have to RevokeDragDrop() + // for them so that the ParentControlDesigner()'s drag-drop support can work + // correctly. + UnsafeNativeMethods.RevokeDragDrop(hwndChild); + new ChildSubClass(this, hwndChild); + SubclassedChildWindows[hwndChild] = true; + } + } + + // UserControl is a special ContainerControl which should "hook to all the WindowHandles" + // Since it doesnt allow the Mouse to pass through any of its contained controls. + // Please refer to VsWhidbey : 293117 + if (child == null || Control is UserControl) + { + // Now do the children of this window. + HookChildHandles(UnsafeNativeMethods.GetWindow(hwndChild, NativeMethods.GW_CHILD)); + } + hwndChild = UnsafeNativeMethods.GetWindow(hwndChild, NativeMethods.GW_HWNDNEXT); + } + } + + private bool IsWindowInCurrentProcess(IntPtr hwnd) + { + SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(null, hwnd), out int pid); + return pid == CurrentProcessId; + } + + private int CurrentProcessId + { + get + { + if (s_currentProcessId == 0) + { + s_currentProcessId = SafeNativeMethods.GetCurrentProcessId(); + } + return s_currentProcessId; + } + } + + private void OnHandleChange() + { + // We must now traverse child handles for this control. There are three types of child handles and we are interested in two of them: + // 1. Child handles that do not have a Control associated with them. We must subclass these and prevent them from getting design-time events. + // 2. Child handles that do have a Control associated with them, but the control does not have a designer. We must hook the WindowTarget on these controls and prevent them from getting design-time events. + // 3. Child handles that do have a Control associated with them, and the control has a designer. We ignore these and let the designer handle their messages. + HookChildHandles(UnsafeNativeMethods.GetWindow(Control.Handle, NativeMethods.GW_CHILD)); + HookChildControls(Control); + } + + private class ChildSubClass : NativeWindow, IDesignerTarget + { + private ControlDesigner _designer; + + // AssignHandle calls NativeWindow::OnHandleChanged, but we do not override it so we should be okay + [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] + public ChildSubClass(ControlDesigner designer, IntPtr hwnd) + { + _designer = designer; + if (designer != null) + { + designer.DisposingHandler += new EventHandler(OnDesignerDisposing); + } + AssignHandle(hwnd); + } + + void IDesignerTarget.DefWndProc(ref Message m) => base.DefWndProc(ref m); + + public void Dispose() => _designer = null; + + private void OnDesignerDisposing(object sender, EventArgs e) => Dispose(); + + protected override void WndProc(ref Message m) + { + if (_designer == null) + { + DefWndProc(ref m); + return; + } + + if (m.Msg == Interop.WindowMessages.WM_DESTROY) + { + _designer.RemoveSubclassedWindow(m.HWnd); + } + if (m.Msg == Interop.WindowMessages.WM_PARENTNOTIFY && NativeMethods.Util.LOWORD(unchecked((int)(long)m.WParam)) == (short)Interop.WindowMessages.WM_CREATE) + { + _designer.HookChildHandles(m.LParam); // they will get removed from the collection just above + } + + // We want these messages to go through the designer's WndProc method, and we want people to be able to do default processing with the designer's DefWndProc. So, we stuff ourselves into the designers window target and call their WndProc. + IDesignerTarget designerTarget = _designer.DesignerTarget; + _designer.DesignerTarget = this; + Debug.Assert(m.HWnd == Handle, "Message handle differs from target handle"); + try + { + _designer.WndProc(ref m); + } + catch (Exception ex) + { + _designer.SetUnhandledException(Control.FromChildHandle(m.HWnd), ex); + } + finally + { + // make sure the designer wasn't destroyed + if (_designer != null && _designer.Component != null) + { + _designer.DesignerTarget = designerTarget; + } + } + } + } + + internal void RemoveSubclassedWindow(IntPtr hwnd) + { + if (SubclassedChildWindows.ContainsKey(hwnd)) + { + SubclassedChildWindows.Remove(hwnd); + } + } + + private class DesignerWindowTarget : IWindowTarget, IDesignerTarget, IDisposable + { + internal ControlDesigner _designer; + internal IWindowTarget _oldTarget; + + public DesignerWindowTarget(ControlDesigner designer) + { + Control control = designer.Control; + _designer = designer; + _oldTarget = control.WindowTarget; + control.WindowTarget = this; + } + + public void DefWndProc(ref Message m) + { + _oldTarget.OnMessage(ref m); + } + + public void Dispose() + { + if (_designer != null) + { + _designer.Control.WindowTarget = _oldTarget; + _designer = null; + } + } + + public void OnHandleChange(IntPtr newHandle) + { + _oldTarget.OnHandleChange(newHandle); + if (newHandle != IntPtr.Zero) + { + _designer.OnHandleChange(); + } + } + + public void OnMessage(ref Message m) + { + // We want these messages to go through the designer's WndProc method, and we want people to be able to do default processing with the designer's DefWndProc. So, we stuff ourselves into the designers window target and call their WndProc. + ControlDesigner currentDesigner = _designer; + if (currentDesigner != null) + { + IDesignerTarget designerTarget = currentDesigner.DesignerTarget; + currentDesigner.DesignerTarget = this; + try + { + currentDesigner.WndProc(ref m); + } + catch (Exception ex) + { + currentDesigner.SetUnhandledException(currentDesigner.Control, ex); + } + finally + { + currentDesigner.DesignerTarget = designerTarget; + } + } + else + { + DefWndProc(ref m); + } + } + } + + private class ChildWindowTarget : IWindowTarget, IDesignerTarget + { + private readonly ControlDesigner _designer; + private readonly Control _childControl; + private readonly IWindowTarget _oldWindowTarget; + private IntPtr _handle = IntPtr.Zero; + + public ChildWindowTarget(ControlDesigner designer, Control childControl, IWindowTarget oldWindowTarget) + { + _designer = designer; + _childControl = childControl; + _oldWindowTarget = oldWindowTarget; + } + + public IWindowTarget OldWindowTarget + { + get => _oldWindowTarget; + } + + public void DefWndProc(ref Message m) => _oldWindowTarget.OnMessage(ref m); + + [SuppressMessage("Microsoft.Usage", "CA2216:DisposableTypesShouldDeclareFinalizer")] + public void Dispose() + { + // Do nothing. We will pick this up through a null DesignerTarget property when we come out of the message loop. + } + + public void OnHandleChange(IntPtr newHandle) + { + _handle = newHandle; + _oldWindowTarget.OnHandleChange(newHandle); + } + + public void OnMessage(ref Message m) + { + // If the designer has jumped ship, the continue partying on messages, but send them back to the original control. + if (_designer.Component == null) + { + _oldWindowTarget.OnMessage(ref m); + return; + } + + // We want these messages to go through the designer's WndProc method, and we want people to be able to do default processing with the designer's DefWndProc. So, we stuff the old window target into the designer's target and then call their WndProc. + IDesignerTarget designerTarget = _designer.DesignerTarget; + _designer.DesignerTarget = this; + + try + { + _designer.WndProc(ref m); + } + catch (Exception ex) + { + _designer.SetUnhandledException(_childControl, ex); + } + finally + { + // If the designer disposed us, then we should follow suit. + if (_designer.DesignerTarget == null) + { + designerTarget.Dispose(); + } + else + { + _designer.DesignerTarget = designerTarget; + } + + // Controls (primarily RichEdit) will register themselves as drag-drop source/targets when they are instantiated. Normally, when they are being designed, we will RevokeDragDrop() in their designers. The problem occurs when these controls are inside a UserControl. At that time, we do not have a designer for these controls, and they prevent the ParentControlDesigner's drag-drop from working. What we do is to loop through all child controls that do not have a designer (in HookChildControls()), and RevokeDragDrop() after their handles have been created. + if (m.Msg == Interop.WindowMessages.WM_CREATE) + { + Debug.Assert(_handle != IntPtr.Zero, "Handle for control not created"); + UnsafeNativeMethods.RevokeDragDrop(_handle); + } + } + } + } + + internal void SetUnhandledException(Control owner, Exception exception) + { + if (_thrownException == null) + { + _thrownException = exception; + if (owner == null) + { + owner = Control; + } + string stack = string.Empty; + string[] exceptionLines = exception.StackTrace.Split('\r', '\n'); + string typeName = owner.GetType().FullName; + foreach (string line in exceptionLines) + { + if (line.IndexOf(typeName) != -1) + { + stack = string.Format(CultureInfo.CurrentCulture, "{0}\r\n{1}", stack, line); + } + } + + Exception wrapper = new Exception(string.Format(SR.ControlDesigner_WndProcException, typeName, exception.Message, stack), exception); + DisplayError(wrapper); + // hide all the child controls. + foreach (Control c in Control.Controls) + { + c.Visible = false; + } + Control.Invalidate(true); + } + } + + [ListBindable(false)] + [DesignerSerializer(typeof(DesignerControlCollectionCodeDomSerializer), typeof(CodeDomSerializer))] + internal class DesignerControlCollection : Control.ControlCollection, IList + { + readonly Control.ControlCollection _realCollection; + public DesignerControlCollection(Control owner) : base(owner) + { + _realCollection = owner.Controls; + } + + public override int Count + { + get => _realCollection.Count; + } + + object ICollection.SyncRoot + { + get => this; + } + + bool ICollection.IsSynchronized + { + get => false; + } + + bool IList.IsFixedSize + { + get => false; + } + + public new bool IsReadOnly + { + get => _realCollection.IsReadOnly; + } + + int IList.Add(object control) => ((IList)_realCollection).Add(control); + + public override void Add(Control c) => _realCollection.Add(c); + + public override void AddRange(Control[] controls) => _realCollection.AddRange(controls); + + bool IList.Contains(object control) => ((IList)_realCollection).Contains(control); + + public new void CopyTo(Array dest, int index) => _realCollection.CopyTo(dest, index); + + public override bool Equals(object other) => _realCollection.Equals(other); + + public new IEnumerator GetEnumerator() => _realCollection.GetEnumerator(); + + public override int GetHashCode() => _realCollection.GetHashCode(); + + int IList.IndexOf(object control) => ((IList)_realCollection).IndexOf(control); + + void IList.Insert(int index, object value) => ((IList)_realCollection).Insert(index, value); + + void IList.Remove(object control) => ((IList)_realCollection).Remove(control); + + void IList.RemoveAt(int index) => ((IList)_realCollection).RemoveAt(index); + + object IList.this[int index] + { + get => ((IList)_realCollection)[index]; + set => throw new NotSupportedException(); + } + + public override int GetChildIndex(Control child, bool throwException) => _realCollection.GetChildIndex(child, throwException); + + // we also need to redirect this guy + public override void SetChildIndex(Control child, int newIndex) => _realCollection.SetChildIndex(child, newIndex); + + public override void Clear() + { + for (int i = _realCollection.Count - 1; i >= 0; i--) + { + if (_realCollection[i] != null && + _realCollection[i].Site != null && + TypeDescriptor.GetAttributes(_realCollection[i]).Contains(InheritanceAttribute.NotInherited)) + { + _realCollection.RemoveAt(i); + } + } + } + } + + // Custom code dom serializer for the DesignerControlCollection. We need this so we can filter out controls + // that aren't sited in the host's container. + internal class DesignerControlCollectionCodeDomSerializer : CollectionCodeDomSerializer + { + protected override object SerializeCollection(IDesignerSerializationManager manager, CodeExpression targetExpression, Type targetType, ICollection originalCollection, ICollection valuesToSerialize) + { + ArrayList subset = new ArrayList(); + if (valuesToSerialize != null && valuesToSerialize.Count > 0) + { + foreach (object val in valuesToSerialize) + { + if (val is IComponent comp && comp.Site != null && !(comp.Site is INestedSite)) + { + subset.Add(comp); + } + } + } + return base.SerializeCollection(manager, targetExpression, targetType, originalCollection, subset); + } + } + + private class DockingActionList : DesignerActionList + { + private readonly ControlDesigner _designer; + private readonly IDesignerHost _host; + + public DockingActionList(ControlDesigner owner) : base(owner.Component) + { + _designer = owner; + _host = GetService(typeof(IDesignerHost)) as IDesignerHost; + } + + private string GetActionName() + { + PropertyDescriptor dockProp = TypeDescriptor.GetProperties(Component)["Dock"]; + if (dockProp != null) + { + DockStyle dockStyle = (DockStyle)dockProp.GetValue(Component); + if (dockStyle == DockStyle.Fill) + { + return SR.DesignerShortcutUndockInParent; + } + else + { + return SR.DesignerShortcutDockInParent; + } + } + return null; + } + + public override DesignerActionItemCollection GetSortedActionItems() + { + DesignerActionItemCollection items = new DesignerActionItemCollection(); + string actionName = GetActionName(); + if (actionName != null) + { + items.Add(new DesignerActionVerbItem(new DesignerVerb(GetActionName(), OnDockActionClick))); + } + return items; + } + + private void OnDockActionClick(object sender, EventArgs e) + { + if (sender is DesignerVerb designerVerb && _host != null) + { + using (DesignerTransaction t = _host.CreateTransaction(designerVerb.Text)) + { + //set the dock prop to DockStyle.Fill + PropertyDescriptor dockProp = TypeDescriptor.GetProperties(Component)["Dock"]; + DockStyle dockStyle = (DockStyle)dockProp.GetValue(Component); + if (dockStyle == DockStyle.Fill) + { + dockProp.SetValue(Component, DockStyle.None); + } + else + { + dockProp.SetValue(Component, DockStyle.Fill); + } + t.Commit(); + } + } + } + } + + private class CanResetSizePropertyDescriptor : PropertyDescriptor + { + private readonly PropertyDescriptor _basePropDesc; + + public CanResetSizePropertyDescriptor(PropertyDescriptor pd) : base(pd) + { + _basePropDesc = pd; + } + + public override Type ComponentType + { + get => _basePropDesc.ComponentType; } + + public override string DisplayName + { + get => _basePropDesc.DisplayName; + } + + public override bool IsReadOnly + { + get => _basePropDesc.IsReadOnly; + } + + public override Type PropertyType + { + get => _basePropDesc.PropertyType; + } + + + // since we can't get to the DefaultSize property, we use the existing ShouldSerialize logic. + public override bool CanResetValue(object component) => _basePropDesc.ShouldSerializeValue(component); + + public override object GetValue(object component) => _basePropDesc.GetValue(component); + + public override void ResetValue(object component) => _basePropDesc.ResetValue(component); + + + public override void SetValue(object component, object value) => _basePropDesc.SetValue(component, value); + + // we always want to serialize values. + public override bool ShouldSerializeValue(object component) => true; } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CustomMenuItemCollection.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CustomMenuItemCollection.cs new file mode 100644 index 00000000000..97217060bf2 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/CustomMenuItemCollection.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; + +namespace System.Windows.Forms.Design +{ + /// + /// A strongly-typed collection that stores ToolStripMenuItem objects for DesignerContextMenu + /// + internal class CustomMenuItemCollection : CollectionBase + { + /// + /// Constructor + /// + public CustomMenuItemCollection() + { + } + + /// + /// Add value to the collection + /// + public int Add(ToolStripItem value) + { + return List.Add(value); + } + + /// + /// Add range of values to the collection + /// + public void AddRange(ToolStripItem[] value) + { + for (int i = 0; (i < value.Length); i = (i + 1)) + { + Add(value[i]); + } + } + + /// + /// Abstract base class version for refreshing the items + /// + public virtual void RefreshItems() + { + + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedEventArgs.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedEventArgs.cs new file mode 100644 index 00000000000..9b1162ab9c9 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedEventArgs.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + /// + /// This EventArgs class is used by the DesignerActionService to signify that there has been a change in DesignerActionLists (added or removed) on the related object. + /// + public class DesignerActionListsChangedEventArgs : EventArgs + { + /// + /// Constructor that requires the object in question, the type of change and the remaining actionlists left for the object. on the related object. + /// + public DesignerActionListsChangedEventArgs(object relatedObject, DesignerActionListsChangedType changeType, DesignerActionListCollection actionLists) + { + RelatedObject = relatedObject; + ChangeType = changeType; + ActionLists = actionLists; + } + + /// + /// The object this change is related to. + /// + public object RelatedObject { get; } + + /// + /// The type of changed that caused the related event to be thrown. + /// + public DesignerActionListsChangedType ChangeType { get; } + + /// + /// The remaining actionlists left for the related object. + /// + public DesignerActionListCollection ActionLists { get; } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedEventHandler.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedEventHandler.cs new file mode 100644 index 00000000000..ac8057309e4 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedEventHandler.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +namespace System.ComponentModel.Design +{ + [ComVisible(true)] + public delegate void DesignerActionListsChangedEventHandler(object sender, DesignerActionListsChangedEventArgs e); +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedType.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedType.cs new file mode 100644 index 00000000000..6e939eeb40d --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionListsChangedType.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +namespace System.ComponentModel.Design +{ + /// + /// An enum that defines what time of action happend to the related object's DesignerActionLists collection. + /// + [ComVisible(true)] + public enum DesignerActionListsChangedType + { + /// + /// Signifies that one or more DesignerActionList was added. + /// + ActionListsAdded, + + /// + /// Signifies that one or more DesignerActionList was removed. + /// + ActionListsRemoved + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionMethodItem.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionMethodItem.cs index bfcc3c1f36a..4a541b92421 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionMethodItem.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionMethodItem.cs @@ -8,8 +8,6 @@ namespace System.ComponentModel.Design { public class DesignerActionMethodItem : DesignerActionItem { - private readonly string _memberName; - private readonly bool _includeAsDesignerVerb; private readonly DesignerActionList _actionList; private MethodInfo _methodInfo; @@ -17,8 +15,8 @@ public DesignerActionMethodItem(DesignerActionList actionList, string memberName : base(displayName, category, description) { _actionList = actionList; - _memberName = memberName; - _includeAsDesignerVerb = includeAsDesignerVerb; + MemberName = memberName; + IncludeAsDesignerVerb = includeAsDesignerVerb; } public DesignerActionMethodItem(DesignerActionList actionList, string memberName, string displayName) : this(actionList, memberName, displayName, null, null, false) @@ -41,45 +39,25 @@ public DesignerActionMethodItem(DesignerActionList actionList, string memberName { } - internal DesignerActionMethodItem() - { - } - - public virtual string MemberName - { - get => _memberName; - } + public virtual string MemberName { get; } public IComponent RelatedComponent { get; set; } - public virtual bool IncludeAsDesignerVerb - { - get => _includeAsDesignerVerb; - } - - // this is only use for verbs so that a designer action method item can be converted to a verb. - // Verbs use an EventHandler to call their invoke so we need a way to translate the EventHandler Invoke into ou own Invoke - internal void Invoke(object sender, EventArgs args) - { - Invoke(); - } + public virtual bool IncludeAsDesignerVerb { get; } public virtual void Invoke() { if (_methodInfo == null) { - // we look public AND private or protected methods - _methodInfo = _actionList.GetType().GetMethod(_memberName, BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + _methodInfo = _actionList?.GetType()?.GetMethod(MemberName, BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } - if (_methodInfo != null) - { - _methodInfo.Invoke(_actionList, null); - } - else + if (_methodInfo == null) { throw new InvalidOperationException(string.Format(SR.DesignerActionPanel_CouldNotFindMethod, MemberName)); } + + _methodInfo.Invoke(_actionList, null); } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionPropertyItem.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionPropertyItem.cs index 706ab1a6dc1..c2efd9b22f2 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionPropertyItem.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionPropertyItem.cs @@ -6,12 +6,9 @@ namespace System.ComponentModel.Design { public sealed class DesignerActionPropertyItem : DesignerActionItem { - private readonly string _memberName; - private IComponent _relatedComponent; - public DesignerActionPropertyItem(string memberName, string displayName, string category, string description) : base(displayName, category, description) { - _memberName = memberName; + MemberName = memberName; } public DesignerActionPropertyItem(string memberName, string displayName) : this(memberName, displayName, null, null) @@ -22,16 +19,8 @@ public DesignerActionPropertyItem(string memberName, string displayName, string { } - public string MemberName - { - get => _memberName; - } - - public IComponent RelatedComponent - { - get => _relatedComponent; - set => _relatedComponent = value; - } + public string MemberName { get; } + public IComponent RelatedComponent { get; set; } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionService.cs new file mode 100644 index 00000000000..99dab6ee00c --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionService.cs @@ -0,0 +1,445 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Diagnostics; +using System.Windows.Forms.Design; + +namespace System.ComponentModel.Design +{ + /// + /// The DesignerActionService manages DesignerActions. All DesignerActions are associated with an object. DesignerActions can be added or removed at any given time. The DesignerActionService controls the expiration of DesignerActions by monitoring three basic events: selection change, component change, and timer expiration. Designer implementing this service will need to monitor the DesignerActionsChanged event on this class. This event will fire every time a change is made to any object's DesignerActions. + /// + public class DesignerActionService : IDisposable + { + private readonly Hashtable _designerActionLists; // this is how we store 'em. Syntax: key = object, value = DesignerActionListCollection + private DesignerActionListsChangedEventHandler _designerActionListsChanged; + private readonly IServiceProvider _serviceProvider; // standard service provider + private readonly ISelectionService _selSvc; // selection service + private readonly Hashtable _componentToVerbsEventHookedUp; //table component true/false + // Gaurd against ReEntrant Code. The Infragistics TabControlDesigner, Sets the Commands Status when the Verbs property is accesssed. This property is used in the OnVerbStatusChanged code here and hence causes recursion leading to Stack Overflow Exception. + private bool _reEntrantCode = false; + + /// + /// Standard constructor. A Service Provider is necessary for monitoring selection and component changes. + /// + public DesignerActionService(IServiceProvider serviceProvider) + { + if (serviceProvider != null) + { + _serviceProvider = serviceProvider; + IDesignerHost host = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + host.AddService(typeof(DesignerActionService), this); + IComponentChangeService cs = (IComponentChangeService)serviceProvider.GetService(typeof(IComponentChangeService)); + if (cs != null) + { + cs.ComponentRemoved += new ComponentEventHandler(OnComponentRemoved); + } + _selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + if (_selSvc == null) + { + Debug.Fail("Either BehaviorService or ISelectionService is null, cannot continue."); + } + } + _designerActionLists = new Hashtable(); + _componentToVerbsEventHookedUp = new Hashtable(); + } + + /// + /// This event is thrown whenever a DesignerActionList is removed or added for any object. + /// + public event DesignerActionListsChangedEventHandler DesignerActionListsChanged + { + add => _designerActionListsChanged += value; + remove => _designerActionListsChanged -= value; + } + + /// + /// Adds a new collection of DesignerActions to be monitored with the related comp object. + /// + public void Add(IComponent comp, DesignerActionListCollection designerActionListCollection) + { + if (comp == null) + { + throw new ArgumentNullException(nameof(comp)); + } + if (designerActionListCollection == null) + { + throw new ArgumentNullException(nameof(designerActionListCollection)); + } + + DesignerActionListCollection dhlc = (DesignerActionListCollection)_designerActionLists[comp]; + if (dhlc != null) + { + dhlc.AddRange(designerActionListCollection); + } + else + { + _designerActionLists.Add(comp, designerActionListCollection); + } + + //fire event + OnDesignerActionListsChanged(new DesignerActionListsChangedEventArgs(comp, DesignerActionListsChangedType.ActionListsAdded, GetComponentActions(comp))); + } + + /// + /// Adds a new DesignerActionList to be monitored with the related comp object + /// + public void Add(IComponent comp, DesignerActionList actionList) + { + Add(comp, new DesignerActionListCollection( new[] { actionList } )); + } + + /// + /// Clears all objects and DesignerActions from the DesignerActionService. + /// + public void Clear() + { + if (_designerActionLists.Count == 0) + { + return; + } + + //this will represent the list of componets we just cleared + ArrayList compsRemoved = new ArrayList(_designerActionLists.Count); + foreach (DictionaryEntry entry in _designerActionLists) + { + compsRemoved.Add(entry.Key); + } + + //actually clear our hashtable + _designerActionLists.Clear(); + //fire our DesignerActionsChanged event for each comp we just removed + foreach (Component comp in compsRemoved) + { + OnDesignerActionListsChanged(new DesignerActionListsChangedEventArgs(comp, DesignerActionListsChangedType.ActionListsRemoved, GetComponentActions(comp))); + } + + } + + /// + /// Returns true if the DesignerActionService is currently managing the comp object. + /// + public bool Contains(IComponent comp) + { + if (comp == null) + { + throw new ArgumentNullException(nameof(comp)); + } + return _designerActionLists.Contains(comp); + } + + /// + /// Disposes all resources and unhooks all events. + /// + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && _serviceProvider != null) + { + IDesignerHost host = (IDesignerHost)_serviceProvider.GetService(typeof(IDesignerHost)); + if (host != null) + { + host.RemoveService(typeof(DesignerActionService)); + } + + IComponentChangeService cs = (IComponentChangeService)_serviceProvider.GetService(typeof(IComponentChangeService)); + if (cs != null) + { + cs.ComponentRemoved -= new ComponentEventHandler(OnComponentRemoved); + } + } + } + + public DesignerActionListCollection GetComponentActions(IComponent component) + { + return GetComponentActions(component, ComponentActionsType.All); + } + + public virtual DesignerActionListCollection GetComponentActions(IComponent component, ComponentActionsType type) + { + if (component == null) + { + throw new ArgumentNullException(nameof(component)); + } + DesignerActionListCollection result = new DesignerActionListCollection(); + switch (type) + { + case ComponentActionsType.All: + GetComponentDesignerActions(component, result); + GetComponentServiceActions(component, result); + break; + case ComponentActionsType.Component: + GetComponentDesignerActions(component, result); + break; + case ComponentActionsType.Service: + GetComponentServiceActions(component, result); + break; + } + return result; + } + + protected virtual void GetComponentDesignerActions(IComponent component, DesignerActionListCollection actionLists) + { + if (component == null) + { + throw new ArgumentNullException(nameof(component)); + } + + if (actionLists == null) + { + throw new ArgumentNullException(nameof(actionLists)); + } + + if (component.Site is IServiceContainer sc) + { + DesignerCommandSet dcs = (DesignerCommandSet)sc.GetService(typeof(DesignerCommandSet)); + if (dcs != null) + { + DesignerActionListCollection pullCollection = dcs.ActionLists; + if (pullCollection != null) + { + actionLists.AddRange(pullCollection); + } + + // if we don't find any, add the verbs for this component there... + if (actionLists.Count == 0) + { + DesignerVerbCollection verbs = dcs.Verbs; + if (verbs != null && verbs.Count != 0) + { + ArrayList verbsArray = new ArrayList(); + bool hookupEvents = _componentToVerbsEventHookedUp[component] == null; + if (hookupEvents) + { + _componentToVerbsEventHookedUp[component] = true; + } + foreach (DesignerVerb verb in verbs) + { + if (hookupEvents) + { + verb.CommandChanged += new EventHandler(OnVerbStatusChanged); + } + if (verb.Enabled && verb.Visible) + { + verbsArray.Add(verb); + } + } + if (verbsArray.Count != 0) + { + DesignerActionVerbList davl = new DesignerActionVerbList((DesignerVerb[])verbsArray.ToArray(typeof(DesignerVerb))); + actionLists.Add(davl); + } + } + } + + // remove all the ones that are empty... ie GetSortedActionList returns nothing. we might waste some time doing this twice but don't have much of a choice here... the panel is not yet displayed and we want to know if a non empty panel is present... + // NOTE: We do this AFTER the verb check that way to disable auto verb upgrading you can just return an empty actionlist collection + if (pullCollection != null) + { + foreach (DesignerActionList actionList in pullCollection) + { + DesignerActionItemCollection collection = actionList.GetSortedActionItems(); + if (collection == null || collection.Count == 0) + { + actionLists.Remove(actionList); + } + } + } + } + } + } + + private void OnVerbStatusChanged(object sender, EventArgs args) + { + if (!_reEntrantCode) + { + try + { + _reEntrantCode = true; + if (_selSvc.PrimarySelection is IComponent comp) + { + if (comp.Site is IServiceContainer sc) + { + DesignerCommandSet dcs = (DesignerCommandSet)sc.GetService(typeof(DesignerCommandSet)); + foreach (DesignerVerb verb in dcs.Verbs) + { + if (verb == sender) + { + DesignerActionUIService dapUISvc = (DesignerActionUIService)sc.GetService(typeof(DesignerActionUIService)); + if (dapUISvc != null) + { + dapUISvc.Refresh(comp); // we need to refresh, a verb on the current panel has changed its state + } + } + } + } + } + } + finally + { + _reEntrantCode = false; + } + } + } + + protected virtual void GetComponentServiceActions(IComponent component, DesignerActionListCollection actionLists) + { + if (component == null) + { + throw new ArgumentNullException(nameof(component)); + } + + if (actionLists == null) + { + throw new ArgumentNullException(nameof(actionLists)); + } + + DesignerActionListCollection pushCollection = (DesignerActionListCollection)_designerActionLists[component]; + if (pushCollection != null) + { + actionLists.AddRange(pushCollection); + // remove all the ones that are empty... ie GetSortedActionList returns nothing. we might waste some time doing this twice but don't have much of a choice here... the panel is not yet displayed and we want to know if a non empty panel is present... + foreach (DesignerActionList actionList in pushCollection) + { + DesignerActionItemCollection collection = actionList.GetSortedActionItems(); + if (collection == null || collection.Count == 0) + { + actionLists.Remove(actionList); + } + } + } + } + + /// + /// We hook the OnComponentRemoved event so we can clean up all associated actions. + /// + private void OnComponentRemoved(object source, ComponentEventArgs ce) + { + Remove(ce.Component); + } + + /// + /// This fires our DesignerActionsChanged event. + /// + private void OnDesignerActionListsChanged(DesignerActionListsChangedEventArgs e) + { + _designerActionListsChanged?.Invoke(this, e); + } + + /// + /// This will remove all DesignerActions associated with the 'comp' object. All alarms will be unhooked and the DesignerActionsChagned event will be fired. + /// + public void Remove(IComponent comp) + { + if (comp == null) + { + throw new ArgumentNullException(nameof(comp)); + } + + if (!_designerActionLists.Contains(comp)) + { + return; + } + + _designerActionLists.Remove(comp); + OnDesignerActionListsChanged(new DesignerActionListsChangedEventArgs(comp, DesignerActionListsChangedType.ActionListsRemoved, GetComponentActions(comp))); + } + + /// + /// This will remove the specified Designeraction from the DesignerActionService. All alarms will be unhooked and the DesignerActionsChagned event will be fired. + /// + public void Remove(DesignerActionList actionList) + { + if (actionList == null) + { + throw new ArgumentNullException(nameof(actionList)); + } + + //find the associated component + foreach (IComponent comp in _designerActionLists.Keys) + { + if (((DesignerActionListCollection)_designerActionLists[comp]).Contains(actionList)) + { + Remove(comp, actionList); + break; + } + } + } + + /// + /// This will remove the all instances of the DesignerAction from the 'comp' object. If an alarm was set, it will be unhooked. This will also fire the DesignerActionChanged event. + /// + public void Remove(IComponent comp, DesignerActionList actionList) + { + if (comp == null) + { + throw new ArgumentNullException(nameof(comp)); + } + if (actionList == null) + { + throw new ArgumentNullException(nameof(actionList)); + } + if (!_designerActionLists.Contains(comp)) + { + return; + } + + DesignerActionListCollection actionLists = (DesignerActionListCollection)_designerActionLists[comp]; + if (!actionLists.Contains(actionList)) + { + return; + } + + if (actionLists.Count == 1) + { + //this is the last action for this object, remove the entire thing + Remove(comp); + } + else + { + //remove each instance of this action + ArrayList actionListsToRemove = new ArrayList(1); + foreach (DesignerActionList t in actionLists) + { + if (actionList.Equals(t)) + { + //found one to remove + actionListsToRemove.Add(t); + } + } + + foreach (DesignerActionList t in actionListsToRemove) + { + actionLists.Remove(t); + } + OnDesignerActionListsChanged(new DesignerActionListsChangedEventArgs(comp, DesignerActionListsChangedType.ActionListsRemoved, GetComponentActions(comp))); + } + } + + internal event DesignerActionUIStateChangeEventHandler DesignerActionUIStateChange + { + add + { + DesignerActionUIService dapUISvc = (DesignerActionUIService)_serviceProvider.GetService(typeof(DesignerActionUIService)); + if (dapUISvc != null) + { + dapUISvc.DesignerActionUIStateChange += value; + } + } + remove + { + DesignerActionUIService dapUISvc = (DesignerActionUIService)_serviceProvider.GetService(typeof(DesignerActionUIService)); + if (dapUISvc != null) + { + dapUISvc.DesignerActionUIStateChange -= value; + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionUI.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionUI.cs new file mode 100644 index 00000000000..54db7208a55 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionUI.cs @@ -0,0 +1,1080 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Diagnostics; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using System.Windows.Forms.Design; +using System.Windows.Forms.Design.Behavior; + +namespace System.ComponentModel.Design +{ + /// + /// The DesignerActionUI is the designer/UI-specific implementation of the DesignerActions feature. This class instantiates the DesignerActionService and hooks to its DesignerActionsChanged event. Responding to this single event will enable the DesignerActionUI to perform all neceessary UI-related operations. Note that the DesignerActionUI uses the BehaviorService to manage all UI interaction. For every component containing a DesignerAction (determined by the DesignerActionsChagned event) there will be an associated DesignerActionGlyph and DesignerActionBehavior. Finally, the DesignerActionUI is also responsible for showing and managing the Action's context menus. Note that every DesignerAction context menu has an item that will bring up the DesignerActions option pane in the options dialog. + /// + internal class DesignerActionUI : IDisposable + { + private static readonly TraceSwitch s_designeActionPanelTraceSwitch = new TraceSwitch("DesigneActionPanelTrace", "DesignerActionPanel tracing"); + + private Adorner _designerActionAdorner; //used to add designeraction-related glyphs + private IServiceProvider _serviceProvider; //standard service provider + private ISelectionService _selSvc; //used to determine if comps have selection or not + private DesignerActionService _designerActionService; //this is how all designeractions will be managed + private DesignerActionUIService _designerActionUIService; //this is how all designeractions UI elements will be managed + private BehaviorService _behaviorService; //this is how all of our UI is implemented (glyphs, behaviors, etc...) + private readonly IMenuCommandService _menuCommandService; + private DesignerActionKeyboardBehavior _dapkb; //out keyboard behavior + private readonly Hashtable _componentToGlyph; //used for quick reference between compoments and our glyphs + private Control _marshalingControl; //used to invoke events on our main gui thread + private IComponent _lastPanelComponent; + + private readonly IUIService _uiService; + private readonly IWin32Window _mainParentWindow; + internal DesignerActionToolStripDropDown designerActionHost; + + private readonly MenuCommand _cmdShowDesignerActions; //used to respond to the Alt+Shft+F10 command + private bool _inTransaction = false; + private IComponent _relatedComponentTransaction; + private DesignerActionGlyph _relatedGlyphTransaction; + private readonly bool _disposeActionService; + private readonly bool _disposeActionUIService; + + private delegate void ActionChangedEventHandler(object sender, DesignerActionListsChangedEventArgs e); +#if DEBUG + internal static readonly TraceSwitch DropDownVisibilityDebug = new TraceSwitch("DropDownVisibilityDebug", "Debug ToolStrip Selection code"); +#else + internal static readonly TraceSwitch DropDownVisibilityDebug; +#endif + /// + /// Constructor that takes a service provider. This is needed to establish references to the BehaviorService and SelecteionService, as well as spin-up the DesignerActionService. + /// + public DesignerActionUI(IServiceProvider serviceProvider, Adorner containerAdorner) + { + _serviceProvider = serviceProvider; + _designerActionAdorner = containerAdorner; + _behaviorService = (BehaviorService)serviceProvider.GetService(typeof(BehaviorService)); + _menuCommandService = (IMenuCommandService)serviceProvider.GetService(typeof(IMenuCommandService)); + _selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + if (_behaviorService == null || _selSvc == null) + { + Debug.Fail("Either BehaviorService or ISelectionService is null, cannot continue."); + return; + } + + //query for our DesignerActionService + _designerActionService = (DesignerActionService)serviceProvider.GetService(typeof(DesignerActionService)); + if (_designerActionService == null) + { + //start the service + _designerActionService = new DesignerActionService(serviceProvider); + _disposeActionService = true; + } + _designerActionUIService = (DesignerActionUIService)serviceProvider.GetService(typeof(DesignerActionUIService)); + if (_designerActionUIService == null) + { + _designerActionUIService = new DesignerActionUIService(serviceProvider); + _disposeActionUIService = true; + } + _designerActionUIService.DesignerActionUIStateChange += new DesignerActionUIStateChangeEventHandler(OnDesignerActionUIStateChange); + _designerActionService.DesignerActionListsChanged += new DesignerActionListsChangedEventHandler(OnDesignerActionsChanged); + _lastPanelComponent = null; + + IComponentChangeService cs = (IComponentChangeService)serviceProvider.GetService(typeof(IComponentChangeService)); + if (cs != null) + { + cs.ComponentChanged += new ComponentChangedEventHandler(OnComponentChanged); + } + + if (_menuCommandService != null) + { + _cmdShowDesignerActions = new MenuCommand(new EventHandler(OnKeyShowDesignerActions), MenuCommands.KeyInvokeSmartTag); + _menuCommandService.AddCommand(_cmdShowDesignerActions); + } + + _uiService = (IUIService)serviceProvider.GetService(typeof(IUIService)); + if (_uiService != null) + _mainParentWindow = _uiService.GetDialogOwnerWindow(); + _componentToGlyph = new Hashtable(); + _marshalingControl = new Control(); + _marshalingControl.CreateControl(); + } + + /// + /// Disposes all UI-related objects and unhooks services. + /// + // Don't need to dispose of designerActionUIService. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public void Dispose() + { + if (_marshalingControl != null) + { + _marshalingControl.Dispose(); + _marshalingControl = null; + } + if (_serviceProvider != null) + { + IComponentChangeService cs = (IComponentChangeService)_serviceProvider.GetService(typeof(IComponentChangeService)); + if (cs != null) + { + cs.ComponentChanged -= new ComponentChangedEventHandler(OnComponentChanged); + } + + if (_cmdShowDesignerActions != null) + { + IMenuCommandService mcs = (IMenuCommandService)_serviceProvider.GetService(typeof(IMenuCommandService)); + if (mcs != null) + { + mcs.RemoveCommand(_cmdShowDesignerActions); + } + } + } + + _serviceProvider = null; + _behaviorService = null; + _selSvc = null; + if (_designerActionService != null) + { + _designerActionService.DesignerActionListsChanged -= new DesignerActionListsChangedEventHandler(OnDesignerActionsChanged); + if (_disposeActionService) + { + _designerActionService.Dispose(); + } + } + _designerActionService = null; + + if (_designerActionUIService != null) + { + _designerActionUIService.DesignerActionUIStateChange -= new DesignerActionUIStateChangeEventHandler(OnDesignerActionUIStateChange); + if (_disposeActionUIService) + { + _designerActionUIService.Dispose(); + } + } + _designerActionUIService = null; + _designerActionAdorner = null; + } + + public DesignerActionGlyph GetDesignerActionGlyph(IComponent comp) + { + return GetDesignerActionGlyph(comp, null); + } + + internal DesignerActionGlyph GetDesignerActionGlyph(IComponent comp, DesignerActionListCollection dalColl) + { + // check this component origin, this class or is it readyonly because inherited... + InheritanceAttribute attribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(comp)[typeof(InheritanceAttribute)]; + if (attribute == InheritanceAttribute.InheritedReadOnly) + { // only do it if we can change the control... + return null; + } + + // we didnt get on, fetch it + if (dalColl == null) + { + dalColl = _designerActionService.GetComponentActions(comp); + } + + if (dalColl != null && dalColl.Count > 0) + { + DesignerActionGlyph dag = null; + if (_componentToGlyph[comp] == null) + { + DesignerActionBehavior dab = new DesignerActionBehavior(_serviceProvider, comp, dalColl, this); + + //if comp is a component then try to find a traycontrol associated with it... this should really be in ComponentTray but there is no behaviorService for the CT + if (!(comp is Control) || comp is ToolStripDropDown) + { + //Here, we'll try to get the traycontrol associated with the comp and supply the glyph with an alternative bounds + if (_serviceProvider.GetService(typeof(ComponentTray)) is ComponentTray compTray) + { + ComponentTray.TrayControl trayControl = compTray.GetTrayControlFromComponent(comp); + if (trayControl != null) + { + Rectangle trayBounds = trayControl.Bounds; + dag = new DesignerActionGlyph(dab, trayBounds, compTray); + } + } + } + + //either comp is a control or we failed to find a traycontrol (which could be the case for toolstripitem components) - in this case just create a standard glyoh. + if (dag == null) + { + //if the related comp is a control, then this shortcut will just hang off its bounds + dag = new DesignerActionGlyph(dab, _designerActionAdorner); + } + + if (dag != null) + { + //store off this relationship + _componentToGlyph.Add(comp, dag); + } + } + else + { + dag = _componentToGlyph[comp] as DesignerActionGlyph; + if (dag != null) + { + if (dag.Behavior is DesignerActionBehavior behavior) + { + behavior.ActionLists = dalColl; + } + dag.Invalidate(); // need to invalidate here too, someone could have called refresh too soon, causing the glyph to get created in the wrong place + } + } + return dag; + } + else + { + // the list is now empty... remove the panel and glyph for this control + RemoveActionGlyph(comp); + return null; + } + } + + /// + /// We monitor this event so we can update smart tag locations when controls move. + /// + private void OnComponentChanged(object source, ComponentChangedEventArgs ce) + { + //validate event args + if (ce.Component == null || ce.Member == null || !IsDesignerActionPanelVisible) + { + return; + } + + // If the smart tag is showing, we only move the smart tag if the changing component is the component for the currently showing smart tag. + if (_lastPanelComponent != null && !_lastPanelComponent.Equals(ce.Component)) + { + return; + } + + //if something changed on a component we have actions associated with then invalidate all (repaint & reposition) + if (_componentToGlyph[ce.Component] is DesignerActionGlyph glyph) + { + glyph.Invalidate(); + + if (ce.Member.Name.Equals("Dock")) + { // this is the only case were we don't require an explicit refresh + RecreatePanel(ce.Component as IComponent); // because 99% of the time the action is name "dock in parent container" and get replaced by "undock" + } + + if (ce.Member.Name.Equals("Location") || + ce.Member.Name.Equals("Width") || + ce.Member.Name.Equals("Height")) + { + // we don't need to regen, we just need to update location calculate the position of the form hosting the panel + UpdateDAPLocation(ce.Component as IComponent, glyph); + } + } + } + + private void RecreatePanel(IComponent comp) + { + if (_inTransaction || comp != _selSvc.PrimarySelection) + { // we only ever need to do that when the comp is the primary selection + return; + } + // we check wether or not we're in a transaction, if we are, we only the refresh at the end of the transaction to avoid flicker. + if (_serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host) + { + bool hostIsClosingTransaction = false; + if (host is IDesignerHostTransactionState hostTransactionState) + { + hostIsClosingTransaction = hostTransactionState.IsClosingTransaction; + } + if (host.InTransaction && !hostIsClosingTransaction) + { + host.TransactionClosed += new DesignerTransactionCloseEventHandler(DesignerTransactionClosed); + _inTransaction = true; + _relatedComponentTransaction = comp; + return; + } + } + RecreateInternal(comp); + } + + private void DesignerTransactionClosed(object sender, DesignerTransactionCloseEventArgs e) + { + if (e.LastTransaction && _relatedComponentTransaction != null) + { + // surprise surprise we can get multiple even with e.LastTransaction set to true, even though we unhook here this is because the list on which we enumerate (the event handler list) is copied before it's enumerated on which means that if the undo engine for example creates and commit a transaction during the OnCancel of another completed transaction we will get this twice. So we have to check also for relatedComponentTransaction != null + _inTransaction = false; + IDesignerHost host = _serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; + host.TransactionClosed -= new DesignerTransactionCloseEventHandler(DesignerTransactionClosed); + RecreateInternal(_relatedComponentTransaction); + _relatedComponentTransaction = null; + } + } + + private void RecreateInternal(IComponent comp) + { + DesignerActionGlyph glyph = GetDesignerActionGlyph(comp); + if (glyph != null) + { + VerifyGlyphIsInAdorner(glyph); + // this could happen when a verb change state or suddendly a control gets a new action in the panel and we are the primary selection in that case there would not be a glyph active in the adorner to be shown because we update that on selection change. We have to do that here too. Sad really... + RecreatePanel(glyph); // recreate the DAP itself + UpdateDAPLocation(comp, glyph); // reposition the thing + } + } + private void RecreatePanel(Glyph glyphWithPanelToRegen) + { + // we don't want to do anything if the panel is not visible + if (!IsDesignerActionPanelVisible) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI.RecreatePanel] panel is not visible, bail"); + return; + } + //recreate a designeraction panel + if (glyphWithPanelToRegen != null) + { + if (glyphWithPanelToRegen.Behavior is DesignerActionBehavior behaviorWithPanelToRegen) + { + Debug.Assert(behaviorWithPanelToRegen.RelatedComponent != null, "could not find related component for this refresh"); + DesignerActionPanel dap = designerActionHost.CurrentPanel; // WE DO NOT RECREATE THE WHOLE THING / WE UPDATE THE TASKS - should flicker less + dap.UpdateTasks(behaviorWithPanelToRegen.ActionLists, new DesignerActionListCollection(), string.Format(SR.DesignerActionPanel_DefaultPanelTitle, + behaviorWithPanelToRegen.RelatedComponent.GetType().Name), null); + designerActionHost.UpdateContainerSize(); + } + } + } + + private void VerifyGlyphIsInAdorner(DesignerActionGlyph glyph) + { + if (glyph.IsInComponentTray) + { + ComponentTray compTray = _serviceProvider.GetService(typeof(ComponentTray)) as ComponentTray; + if (compTray.SelectionGlyphs != null && !compTray.SelectionGlyphs.Contains(glyph)) + { + compTray.SelectionGlyphs.Insert(0, glyph); + } + } + else + { + if (_designerActionAdorner != null && _designerActionAdorner.Glyphs != null && !_designerActionAdorner.Glyphs.Contains(glyph)) + { + _designerActionAdorner.Glyphs.Insert(0, glyph); + } + } + glyph.InvalidateOwnerLocation(); + } + + /// + /// This event is fired by the DesignerActionService in response to a DesignerActionCollection changing. The event args contains information about the related object, the type of change (added or removed) and the remaining DesignerActionCollection for the object. Note that when new DesignerActions are added, if the related control/ is not yet parented - we add these actions to a "delay" list and they are later created when the control is finally parented. + /// + private void OnDesignerActionsChanged(object sender, DesignerActionListsChangedEventArgs e) + { + // We need to invoke this async because the designer action service will raise this event from the thread pool. + if (_marshalingControl != null && _marshalingControl.IsHandleCreated) + { + _marshalingControl.BeginInvoke(new ActionChangedEventHandler(OnInvokedDesignerActionChanged), new object[] { sender, e }); + } + } + + private void OnDesignerActionUIStateChange(object sender, DesignerActionUIStateChangeEventArgs e) + { + IComponent comp = e.RelatedObject as IComponent; + Debug.Assert(comp != null || e.ChangeType == DesignerActionUIStateChangeType.Hide, "related object is not an IComponent, something is wrong here..."); + if (comp != null) + { + DesignerActionGlyph relatedGlyph = GetDesignerActionGlyph(comp); + if (relatedGlyph != null) + { + if (e.ChangeType == DesignerActionUIStateChangeType.Show) + { + if (relatedGlyph.Behavior is DesignerActionBehavior behavior) + { + behavior.ShowUI(relatedGlyph); + } + } + else if (e.ChangeType == DesignerActionUIStateChangeType.Hide) + { + if (relatedGlyph.Behavior is DesignerActionBehavior behavior) + { + behavior.HideUI(); + } + } + else if (e.ChangeType == DesignerActionUIStateChangeType.Refresh) + { + relatedGlyph.Invalidate(); + RecreatePanel((IComponent)e.RelatedObject); + } + } + } + else + { + if (e.ChangeType == DesignerActionUIStateChangeType.Hide) + { + HideDesignerActionPanel(); + } + } + } + + /// + /// This is the same as DesignerActionChanged, but it is invoked on our control's thread + /// + private void OnInvokedDesignerActionChanged(object sender, DesignerActionListsChangedEventArgs e) + { + IComponent relatedComponent = e.RelatedObject as IComponent; + DesignerActionGlyph g = null; + if (e.ChangeType == DesignerActionListsChangedType.ActionListsAdded) + { + if (relatedComponent == null) + { + Debug.Fail("How can we add a DesignerAction glyphs when it's related object is not an IComponent?"); + return; + } + IComponent primSel = _selSvc.PrimarySelection as IComponent; + if (primSel == e.RelatedObject) + { + g = GetDesignerActionGlyph(relatedComponent, e.ActionLists); + if (g != null) + { + VerifyGlyphIsInAdorner(g); + } + else + { + RemoveActionGlyph(e.RelatedObject); + } + } + } + if (e.ChangeType == DesignerActionListsChangedType.ActionListsRemoved && e.ActionLists.Count == 0) + { + //only remove our glyph if there are no more DesignerActions associated with it. + RemoveActionGlyph(e.RelatedObject); + } + else if (g != null) + { + // we need to recreate the panel here, since it's content has changed... + RecreatePanel(relatedComponent); + } + } + + /// + /// Called when our KeyShowDesignerActions menu command is fired (a.k.a. Alt+Shift+F10) - we will find the primary selection, see if it has designer actions, and if so - show the menu. + /// + private void OnKeyShowDesignerActions(object sender, EventArgs e) + { + ShowDesignerActionPanelForPrimarySelection(); + } + + // we cannot attach several menu command to the same command id, we need a single entry point, we put it in designershortcutui. but we need a way to call the show ui on the related behavior hence this internal function to hack it together. we return false if we have nothing to display, we hide it and return true if we're already displaying + internal bool ShowDesignerActionPanelForPrimarySelection() + { + //can't do anythign w/o selection service + if (_selSvc == null) + { + return false; + } + + object primarySelection = _selSvc.PrimarySelection; + //verfiy that we have obtained a valid component with designer actions + if (primarySelection == null || !_componentToGlyph.Contains(primarySelection)) + { + return false; + } + + DesignerActionGlyph glyph = (DesignerActionGlyph)_componentToGlyph[primarySelection]; + if (glyph != null && glyph.Behavior is DesignerActionBehavior) + { + // show the menu + if (glyph.Behavior is DesignerActionBehavior behavior) + { + if (!IsDesignerActionPanelVisible) + { + behavior.ShowUI(glyph); + return true; + } + else + { + behavior.HideUI(); + return false; + } + } + } + return false; + } + + /// + /// When all the DesignerActions have been removed for a particular object, we remove any UI (glyphs) that we may have been managing. + /// + internal void RemoveActionGlyph(object relatedObject) + { + if (relatedObject == null) + { + return; + } + if (IsDesignerActionPanelVisible && relatedObject == _lastPanelComponent) + { + HideDesignerActionPanel(); + } + + DesignerActionGlyph glyph = (DesignerActionGlyph)_componentToGlyph[relatedObject]; + if (glyph != null) + { + // Check ComponentTray first + if (_serviceProvider.GetService(typeof(ComponentTray)) is ComponentTray compTray && compTray.SelectionGlyphs != null) + { + if (compTray != null && compTray.SelectionGlyphs.Contains(glyph)) + { + compTray.SelectionGlyphs.Remove(glyph); + } + } + + if (_designerActionAdorner.Glyphs.Contains(glyph)) + { + _designerActionAdorner.Glyphs.Remove(glyph); + } + _componentToGlyph.Remove(relatedObject); + + // we only do this when we're in a transaction, see bug VSWHIDBEY 418709. This is for compat reason - infragistic. if we're not in a transaction, too bad, we don't update the screen + if (_serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host && host.InTransaction) + { + host.TransactionClosed += new DesignerTransactionCloseEventHandler(InvalidateGlyphOnLastTransaction); + _relatedGlyphTransaction = glyph; + } + } + } + + private void InvalidateGlyphOnLastTransaction(object sender, DesignerTransactionCloseEventArgs e) + { + if (e.LastTransaction) + { + IDesignerHost host = (_serviceProvider != null) ? _serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost : null; + if (host != null) + { + host.TransactionClosed -= new DesignerTransactionCloseEventHandler(InvalidateGlyphOnLastTransaction); + } + if (_relatedGlyphTransaction != null) + { + _relatedGlyphTransaction.InvalidateOwnerLocation(); + } + _relatedGlyphTransaction = null; + } + } + + internal void HideDesignerActionPanel() + { + if (IsDesignerActionPanelVisible) + { + designerActionHost.Close(); + } + } + + internal bool IsDesignerActionPanelVisible + { + get => (designerActionHost != null && designerActionHost.Visible); + } + + internal IComponent LastPanelComponent + { + get => (IsDesignerActionPanelVisible ? _lastPanelComponent : null); + } + + private void ToolStripDropDown_Closing(object sender, ToolStripDropDownClosingEventArgs e) + { + if (_cancelClose || e.Cancel) + { + e.Cancel = true; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI.toolStripDropDown_Closing] cancelClose true, bail"); + return; + } + if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked) + { + e.Cancel = true; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI.toolStripDropDown_Closing] ItemClicked: e.Cancel set to: " + e.Cancel.ToString()); + } + if (e.CloseReason == ToolStripDropDownCloseReason.Keyboard) + { + e.Cancel = false; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI.toolStripDropDown_Closing] Keyboard: e.Cancel set to: " + e.Cancel.ToString()); + } + + if (e.Cancel == false) + { // we WILL disappear + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI.toolStripDropDown_Closing] Closing..."); + Debug.Assert(_lastPanelComponent != null, "last panel component should not be null here... " + + "(except if you're currently debugging VS where deactivation messages in the middle of the pump can mess up everything...)"); + if (_lastPanelComponent == null) + return; + // if we're actually closing get the coordinate of the last message, the one causing us to close, is it within the glyph coordinate. if it is that mean that someone just clicked back from the panel, on VS, but ON THE GLYPH, that means that he actually wants to close it. The activation change is going to do that for us but we should NOT reopen right away because he clicked on the glyph... this code is here to prevent this... + Point point = DesignerUtils.LastCursorPoint; + if (_componentToGlyph[_lastPanelComponent] is DesignerActionGlyph currentGlyph) + { + Point glyphCoord = GetGlyphLocationScreenCoord(_lastPanelComponent, currentGlyph); + if ((new Rectangle(glyphCoord, new Size(currentGlyph.Bounds.Width, currentGlyph.Bounds.Height))).Contains(point)) + { + DesignerActionBehavior behavior = currentGlyph.Behavior as DesignerActionBehavior; + behavior.IgnoreNextMouseUp = true; + } + currentGlyph.InvalidateOwnerLocation(); + } + _lastPanelComponent = null; + // panel is going away, pop the behavior that's on the stack... + Debug.Assert(_dapkb != null, "why is dapkb null?"); + System.Windows.Forms.Design.Behavior.Behavior popBehavior = _behaviorService.PopBehavior(_dapkb); + Debug.Assert(popBehavior is DesignerActionKeyboardBehavior, "behavior returned is of the wrong kind?"); + } + } + + internal Point UpdateDAPLocation(IComponent component, DesignerActionGlyph glyph) + { + if (component == null) + { // in case of a resize... + component = _lastPanelComponent; + } + + if (designerActionHost == null) + { + return Point.Empty; + } + + if (component == null || glyph == null) + { + return designerActionHost.Location; + } + + // check that the glyph is still visible in the adorner window + if (_behaviorService != null && + !_behaviorService.AdornerWindowControl.DisplayRectangle.IntersectsWith(glyph.Bounds)) + { + HideDesignerActionPanel(); + return designerActionHost.Location; + } + + Point glyphLocationScreenCoord = GetGlyphLocationScreenCoord(component, glyph); + Rectangle rectGlyph = new Rectangle(glyphLocationScreenCoord, glyph.Bounds.Size); + Point pt = DesignerActionPanel.ComputePreferredDesktopLocation(rectGlyph, designerActionHost.Size, out DockStyle edgeToDock); + glyph.DockEdge = edgeToDock; + designerActionHost.Location = pt; + return pt; + } + + private Point GetGlyphLocationScreenCoord(IComponent relatedComponent, Glyph glyph) + { + Point glyphLocationScreenCoord = new Point(0, 0); + if (relatedComponent is Control && !(relatedComponent is ToolStripDropDown)) + { + glyphLocationScreenCoord = _behaviorService.AdornerWindowPointToScreen(glyph.Bounds.Location); + } + //ISSUE: we can't have this special cased here - we should find a more generic approach to solving this problem + else if (relatedComponent is ToolStripItem) + { + if (relatedComponent is ToolStripItem item && item.Owner != null) + { + glyphLocationScreenCoord = _behaviorService.AdornerWindowPointToScreen(glyph.Bounds.Location); + } + } + else if (relatedComponent is IComponent) + { + if (_serviceProvider.GetService(typeof(ComponentTray)) is ComponentTray compTray) + { + glyphLocationScreenCoord = compTray.PointToScreen(glyph.Bounds.Location); + } + } + return glyphLocationScreenCoord; + } + + bool _cancelClose = false; + /// + /// This shows the actual chrome paenl that is created by the DesignerActionBehavior object. + /// + internal void ShowDesignerActionPanel(IComponent relatedComponent, DesignerActionPanel panel, DesignerActionGlyph glyph) + { + if (designerActionHost == null) + { + designerActionHost = new DesignerActionToolStripDropDown(this, _mainParentWindow) + { + AutoSize = false, + Padding = Padding.Empty, + Renderer = new NoBorderRenderer(), + Text = "DesignerActionTopLevelForm" + }; + designerActionHost.Closing += new ToolStripDropDownClosingEventHandler(ToolStripDropDown_Closing); + } + // set the accessible name of the panel to the same title as the panel header. do that every time + designerActionHost.AccessibleName = string.Format(SR.DesignerActionPanel_DefaultPanelTitle, relatedComponent.GetType().Name); + panel.AccessibleName = string.Format(SR.DesignerActionPanel_DefaultPanelTitle, relatedComponent.GetType().Name); + + designerActionHost.SetDesignerActionPanel(panel, glyph); + Point location = UpdateDAPLocation(relatedComponent, glyph); + + // check that the panel will have at least it's parent glyph visible on the adorner window + if (_behaviorService != null && + _behaviorService.AdornerWindowControl.DisplayRectangle.IntersectsWith(glyph.Bounds)) + { + if (_mainParentWindow != null && _mainParentWindow.Handle != IntPtr.Zero) + { + Debug.WriteLineIf(s_designeActionPanelTraceSwitch.TraceVerbose, "Assigning owner to mainParentWindow"); + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "Assigning owner to mainParentWindow"); + UnsafeNativeMethods.SetWindowLong(new HandleRef(designerActionHost, designerActionHost.Handle), NativeMethods.GWL_HWNDPARENT, new HandleRef(_mainParentWindow, _mainParentWindow.Handle)); + } + + _cancelClose = true; + designerActionHost.Show(location); + designerActionHost.Focus(); + // when a control is drag and dropped and authoshow is set to true the vs designer is going to get activated as soon as the control is dropped we don't want to close the panel then, so we post a message (using the trick to call begin invoke) and once everything is settled re-activate the autoclose logic + designerActionHost.BeginInvoke(new EventHandler(OnShowComplete)); + // invalidate the glyph to have it point the other way + glyph.InvalidateOwnerLocation(); + _lastPanelComponent = relatedComponent; + // push new behavior for keyboard handling on the behavior stack + _dapkb = new DesignerActionKeyboardBehavior(designerActionHost.CurrentPanel, _serviceProvider, _behaviorService); + _behaviorService.PushBehavior(_dapkb); + } + } + + private void OnShowComplete(object sender, EventArgs e) + { + _cancelClose = false; + // force the panel to be the active window - for some reason someone else could have forced VS to become active for real while we were ignoring close. This might be bad cause we'd be in a bad state. + if (designerActionHost != null && designerActionHost.Handle != IntPtr.Zero && designerActionHost.Visible) + { + UnsafeNativeMethods.SetActiveWindow(new HandleRef(this, designerActionHost.Handle)); + designerActionHost.CheckFocusIsRight(); + } + } + } + + internal class DesignerActionToolStripDropDown : ToolStripDropDown + { + private readonly IWin32Window _mainParentWindow; + private ToolStripControlHost _panel; + private readonly DesignerActionUI _designerActionUI; + private bool _cancelClose = false; + private Glyph _relatedGlyph; + + public DesignerActionToolStripDropDown(DesignerActionUI designerActionUI, IWin32Window mainParentWindow) + { + _mainParentWindow = mainParentWindow; + _designerActionUI = designerActionUI; + } + + public DesignerActionPanel CurrentPanel + { + get + { + if (_panel != null) + { + return _panel.Control as DesignerActionPanel; + } + else + { + return null; + } + } + } + + // we're not topmost because we can show modal editors above us. + protected override bool TopMost + { + get => false; + } + + public void UpdateContainerSize() + { + if (CurrentPanel != null) + { + Size panelSize = CurrentPanel.GetPreferredSize(new Size(150, int.MaxValue)); + if (CurrentPanel.Size == panelSize) + { + // If the panel size didn't actually change, we still have to force a call to PerformLayout to make sure that controls get repositioned properly within the panel. The issue arises because we did a measure-only Layout that determined some sizes, and then we end up painting with those values even though there wasn't an actual Layout performed. + CurrentPanel.PerformLayout(); + } + else + { + CurrentPanel.Size = panelSize; + } + ClientSize = panelSize; + } + } + + public void CheckFocusIsRight() + { // fix to get the focus to NOT stay on ContainerControl + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "Checking focus..."); + IntPtr focusedControl = UnsafeNativeMethods.GetFocus(); + if (focusedControl == Handle) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, " putting focus on the panel..."); + _panel.Focus(); + } + focusedControl = UnsafeNativeMethods.GetFocus(); + if (CurrentPanel != null && CurrentPanel.Handle == focusedControl) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, " selecting next available control on the panel..."); + CurrentPanel.SelectNextControl(null, true, true, true, true); + } + UnsafeNativeMethods.GetFocus(); + } + + protected override void OnLayout(LayoutEventArgs levent) + { + base.OnLayout(levent); + + UpdateContainerSize(); + } + + protected override void OnClosing(ToolStripDropDownClosingEventArgs e) + { + + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "_____________________________Begin OnClose " + e.CloseReason.ToString()); + Debug.Indent(); + if (e.CloseReason == ToolStripDropDownCloseReason.AppFocusChange && _cancelClose) + { + _cancelClose = false; + e.Cancel = true; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "cancel close prepopulated"); + } + // when we get closing event as a result of an activation change, pre-populate e.Cancel based on why we're exiting. + // - if it's a modal window that's owned by VS dont exit + // - if it's a window that's owned by the toolstrip dropdown dont exit + else if (e.CloseReason == ToolStripDropDownCloseReason.AppFocusChange || e.CloseReason == ToolStripDropDownCloseReason.AppClicked) + { + IntPtr hwndActivating = UnsafeNativeMethods.GetActiveWindow(); + if (Handle == hwndActivating && e.CloseReason == ToolStripDropDownCloseReason.AppClicked) + { + e.Cancel = false; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] activation hasnt changed, but we've certainly clicked somewhere else."); + } + else if (WindowOwnsWindow(Handle, hwndActivating)) + { + // we're being de-activated for someone owned by the panel + e.Cancel = true; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] Cancel close - the window activating is owned by this window"); + } + else if (_mainParentWindow != null && !WindowOwnsWindow(_mainParentWindow.Handle, hwndActivating)) + { + if (IsWindowEnabled(_mainParentWindow.Handle)) + { + // the activated windows is not a child/owned windows of the main top level windows let toolstripdropdown handle this + e.Cancel = false; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] Call close: the activated windows is not a child/owned windows of the main top level windows "); + } + else + { + e.Cancel = true; + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] we're being deactivated by a foreign window, but the main window is not enabled - we should stay up"); + } + base.OnClosing(e); + Debug.Unindent(); + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "_____________________________End OnClose e.Cancel: " + e.Cancel.ToString()); + return; + } + else + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] since the designer action panel dropdown doesnt own the activating window " + hwndActivating.ToString("x") + ", calling close. "); + } + + // what's the owner of the windows being activated? + IntPtr parent = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, hwndActivating), NativeMethods.GWL_HWNDPARENT); + // is it currently disabled (ie, the activating windows is in modal mode) + if (!IsWindowEnabled(parent)) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] modal window activated - cancelling close"); + // we are in a modal case + e.Cancel = true; + } + } + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.OnClosing] calling base.OnClosing with e.Cancel: " + e.Cancel.ToString()); + base.OnClosing(e); + Debug.Unindent(); + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "_____________________________End OnClose e.Cancel: " + e.Cancel.ToString()); + } + + public void SetDesignerActionPanel(DesignerActionPanel panel, Glyph relatedGlyph) + { + if (_panel != null && panel == (DesignerActionPanel)_panel.Control) + return; + Debug.Assert(relatedGlyph != null, "related glyph cannot be null"); + _relatedGlyph = relatedGlyph; + panel.SizeChanged += new EventHandler(PanelResized); + // hook up the event + if (_panel != null) + { + Items.Remove(_panel); + _panel.Dispose(); + _panel = null; + } + _panel = new ToolStripControlHost(panel) + { + // we don't want no margin + Margin = Padding.Empty, + Size = panel.Size + }; + + SuspendLayout(); + Size = panel.Size; + Items.Add(_panel); + ResumeLayout(); + if (Visible) + { + CheckFocusIsRight(); + } + + } + + private void PanelResized(object sender, System.EventArgs e) + { + Control ctrl = sender as Control; + if (Size.Width != ctrl.Size.Width || Size.Height != ctrl.Size.Height) + { + SuspendLayout(); + Size = ctrl.Size; + if (_panel != null) + { + _panel.Size = ctrl.Size; + } + _designerActionUI.UpdateDAPLocation(null, _relatedGlyph as DesignerActionGlyph); + ResumeLayout(); + } + } + + protected override void SetVisibleCore(bool visible) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionToolStripDropDown.SetVisibleCore] setting dropdown visible=" + visible.ToString()); + base.SetVisibleCore(visible); + if (visible) + { + CheckFocusIsRight(); + } + } + + /// + /// General purpose method, based on Control.Contains()... + /// Determines whether a given window (specified using native window handle) is a descendant of this control. This catches both contained descendants and 'owned' windows such as modal dialogs. Using window handles rather than Control objects allows it to catch un-managed windows as well. + /// + private static bool WindowOwnsWindow(IntPtr hWndOwner, IntPtr hWndDescendant) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[WindowOwnsWindow] Testing if " + hWndOwner.ToString("x") + " is a owned by " + hWndDescendant.ToString("x") + "... "); +#if DEBUG + if (DesignerActionUI.DropDownVisibilityDebug.TraceVerbose) { + Debug.WriteLine("\t\tOWNER: " + GetControlInformation(hWndOwner)); + Debug.WriteLine("\t\tOWNEE: " + GetControlInformation(hWndDescendant)); + IntPtr claimedOwnerHwnd = UnsafeNativeMethods.GetWindowLong(new HandleRef(null, hWndDescendant), NativeMethods.GWL_HWNDPARENT); + Debug.WriteLine("OWNEE's CLAIMED OWNER: "+ GetControlInformation(claimedOwnerHwnd)); + } +#endif + if (hWndDescendant == hWndOwner) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "they match, YES."); + return true; + } + + while (hWndDescendant != IntPtr.Zero) + { + hWndDescendant = UnsafeNativeMethods.GetWindowLong(new HandleRef(null, hWndDescendant), NativeMethods.GWL_HWNDPARENT); + if (hWndDescendant == IntPtr.Zero) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "NOPE."); + return false; + } + if (hWndDescendant == hWndOwner) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "YES."); + return true; + } + } + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "NO."); + return false; + } + // helper function for generating infomation about a particular control use AssertControlInformation if sticking in an assert - then the work to figure out the control info will only be done when the assertion is false. + internal static string GetControlInformation(IntPtr hwnd) + { + if (hwnd == IntPtr.Zero) + { + return "Handle is IntPtr.Zero"; + } +#if DEBUG + if (!DesignerActionUI.DropDownVisibilityDebug.TraceVerbose) { + return string.Empty; + } + int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(null, hwnd)); + StringBuilder sb = new StringBuilder(textLen+1); + UnsafeNativeMethods.GetWindowText(new HandleRef(null, hwnd), sb, sb.Capacity); + string typeOfControl = "Unknown"; + string nameOfControl = ""; + Control c = Control.FromHandle(hwnd); + if (c != null) { + typeOfControl = c.GetType().Name; + if (!string.IsNullOrEmpty(c.Name)) { + nameOfControl += c.Name; + } + else { + nameOfControl += "Unknown"; + // some extra debug info for toolstripdropdowns... + if (c is ToolStripDropDown dd) + { + if (dd.OwnerItem != null) + { + nameOfControl += "OwnerItem: [" + dd.OwnerItem.ToString() + "]"; + } + } + } + } + return sb.ToString() + "\r\n\t\t\tType: [" + typeOfControl + "] Name: [" + nameOfControl + "]"; +#else + return string.Empty; +#endif + + } + private bool IsWindowEnabled(IntPtr handle) + { + int style = (int)UnsafeNativeMethods.GetWindowLong(new HandleRef(this, handle), NativeMethods.GWL_STYLE); + return (style & NativeMethods.WS_DISABLED) == 0; + } + + private void WmActivate(ref Message m) + { + if (unchecked((int)(long)m.WParam) == NativeMethods.WA_INACTIVE) + { + IntPtr hwndActivating = m.LParam; + if (WindowOwnsWindow(Handle, hwndActivating)) + { + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI WmActivate] setting cancel close true because WindowsOwnWindow"); + Debug.WriteLineIf(DesignerActionUI.DropDownVisibilityDebug.TraceVerbose, "[DesignerActionUI WmActivate] checking the focus... " + GetControlInformation(UnsafeNativeMethods.GetFocus())); + _cancelClose = true; + } + else + { + _cancelClose = false; + } + } + else + { + _cancelClose = false; + } + base.WndProc(ref m); + } + + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_ACTIVATE: + WmActivate(ref m); + return; + } + base.WndProc(ref m); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + // since we're not hosted in a form we need to do the same logic as Form.cs. If we get an enter key we need to find the current focused control. if it's a button, we click it and return that we handled the message + if (keyData == Keys.Enter) + { + IntPtr focusedControlPtr = UnsafeNativeMethods.GetFocus(); + Control focusedControl = Control.FromChildHandle(focusedControlPtr); + if (focusedControl is IButtonControl button && button is Control) + { + button.PerformClick(); + return true; + } + } + return base.ProcessDialogKey(keyData); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionUIService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionUIService.cs new file mode 100644 index 00000000000..5ab88d536e6 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionUIService.cs @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Windows.Forms.Design +{ + public sealed class DesignerActionUIService : IDisposable + { + private DesignerActionUIStateChangeEventHandler _designerActionUIStateChangedEventHandler; + private readonly IServiceProvider _serviceProvider; //standard service provider + private readonly DesignerActionService _designerActionService; + + internal DesignerActionUIService(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + + if (serviceProvider != null) + { + _serviceProvider = serviceProvider; + + IDesignerHost host = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + host.AddService(typeof(DesignerActionUIService), this); + + _designerActionService = serviceProvider.GetService(typeof(DesignerActionService)) as DesignerActionService; + Debug.Assert(_designerActionService != null, "we should have created and registered the DAService first"); + } + } + + /// + /// Disposes all resources and unhooks all events. + /// + [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public void Dispose() + { + if (_serviceProvider != null) + { + IDesignerHost host = (IDesignerHost)_serviceProvider.GetService(typeof(IDesignerHost)); + if (host != null) + { + host.RemoveService(typeof(DesignerActionUIService)); + } + } + } + + /// + /// This event is thrown whenever a request is made to show/hide the ui + /// + public event DesignerActionUIStateChangeEventHandler DesignerActionUIStateChange + { + add + { + _designerActionUIStateChangedEventHandler += value; + } + remove + { + _designerActionUIStateChangedEventHandler -= value; + } + } + + + public void HideUI(IComponent component) + { + OnDesignerActionUIStateChange(new DesignerActionUIStateChangeEventArgs(component, DesignerActionUIStateChangeType.Hide)); + } + + public void ShowUI(IComponent component) + { + OnDesignerActionUIStateChange(new DesignerActionUIStateChangeEventArgs(component, DesignerActionUIStateChangeType.Show)); + } + + /// + /// This is a new Helper Method that the service provides to refresh the DesignerActionGlyph as well as DesignerActionPanels. + /// + public void Refresh(IComponent component) + { + OnDesignerActionUIStateChange(new DesignerActionUIStateChangeEventArgs(component, DesignerActionUIStateChangeType.Refresh)); + } + + /// + /// This fires our DesignerActionsChanged event. + /// + private void OnDesignerActionUIStateChange(DesignerActionUIStateChangeEventArgs e) + { + _designerActionUIStateChangedEventHandler?.Invoke(this, e); + } + + public bool ShouldAutoShow(IComponent component) + { + if (_serviceProvider != null) + { + if (_serviceProvider.GetService(typeof(DesignerOptionService)) is DesignerOptionService opts) + { + PropertyDescriptor p = opts.Options.Properties["ObjectBoundSmartTagAutoShow"]; + if (p != null && p.PropertyType == typeof(bool) && !(bool)p.GetValue(null)) + { + return false; + } + } + } + + if (_designerActionService != null) + { + DesignerActionListCollection coll = _designerActionService.GetComponentActions(component); + if (coll != null && coll.Count > 0) + { + for (int i = 0; i < coll.Count; i++) + { + if (coll[i].AutoShow) + { + return true; + } + } + } + } + return false; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionVerbItem.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionVerbItem.cs new file mode 100644 index 00000000000..9ae7300020c --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionVerbItem.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + internal class DesignerActionVerbItem : DesignerActionMethodItem + { + private readonly DesignerVerb _targetVerb; + + public DesignerActionVerbItem(DesignerVerb verb) : base(null, null, null) + { + _targetVerb = verb ?? throw new ArgumentNullException(nameof(verb)); + } + + public override string Category => "Verbs"; + + public override string DisplayName => _targetVerb.Text; + + public override void Invoke() => _targetVerb.Invoke(); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionVerbList.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionVerbList.cs new file mode 100644 index 00000000000..2837b836b23 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerActionVerbList.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ComponentModel.Design +{ + internal class DesignerActionVerbList : DesignerActionList + { + private readonly DesignerVerb[] _verbs; + + public DesignerActionVerbList(DesignerVerb[] verbs) : base(null) + { + _verbs = verbs; + } + + public override bool AutoShow => false; + + public override DesignerActionItemCollection GetSortedActionItems() + { + DesignerActionItemCollection items = new DesignerActionItemCollection(); + for (int i = 0; i < _verbs.Length; i++) + { + if (_verbs[i].Visible && _verbs[i].Enabled && _verbs[i].Supported) + { + items.Add(new DesignerActionVerbItem(_verbs[i])); + } + } + return items; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerCommandSet.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerCommandSet.cs new file mode 100644 index 00000000000..3358d4358c8 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerCommandSet.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel.Design; + +namespace System.Windows.Forms.Design +{ + public class DesignerCommandSet + { + public virtual ICollection GetCommands(string name) + { + return null; + } + + public DesignerVerbCollection Verbs + { + get => (DesignerVerbCollection)GetCommands("Verbs"); + } + + public DesignerActionListCollection ActionLists + { + get => (DesignerActionListCollection)GetCommands("ActionLists"); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerFrame.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerFrame.cs new file mode 100644 index 00000000000..6c02c83c783 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerFrame.cs @@ -0,0 +1,610 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms.Design.Behavior; +using Microsoft.Win32; + +namespace System.Windows.Forms.Design +{ + /// + /// This class implements our design time document. This is the outer window that encompases a designer. It maintains a control hierarchy that looks like this: + /// DesignerFrame + /// ScrollableControl + /// Designer + /// Splitter + /// ScrollableControl + /// Component Tray + /// The splitter and second scrollable control are created on demand when a tray is added. + /// + internal class DesignerFrame : Control, IOverlayService, ISplitWindowService, IContainsThemedScrollbarWindows + { + private readonly ISite _designerSite; + private readonly OverlayControl _designerRegion; + private Splitter _splitter; + private Control _designer; + private BehaviorService _behaviorService; + private readonly IUIService _uiService; + + /// + /// Initializes a new instance of the class. + /// + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + public DesignerFrame(ISite site) + { + Text = "DesignerFrame"; + _designerSite = site; + _designerRegion = new OverlayControl(site); + _uiService = _designerSite.GetService(typeof(IUIService)) as IUIService; + if (_uiService != null) + { + if (_uiService.Styles["ArtboardBackground"] is Color) + { + BackColor = (Color)_uiService.Styles["ArtboardBackground"]; + } + } + Controls.Add(_designerRegion); + // Now we must configure our designer to be at the correct location, and setup the autoscrolling for its container. + _designerRegion.AutoScroll = true; + _designerRegion.Dock = DockStyle.Fill; + } + + /// + /// Returns the scroll offset for the scrollable control that manages all overlays. This is needed by the BehaviorService so we can correctly invalidate our AdornerWindow based on scrollposition. + /// + internal Point AutoScrollPosition + { + get => _designerRegion.AutoScrollPosition; + } + + /// + /// Demand creates a ptr to the BehaviorService - we do this so we can route keyboard message to it. + /// + private BehaviorService BehaviorService + { + get + { + if (_behaviorService == null) + { + _behaviorService = _designerSite.GetService(typeof(BehaviorService)) as BehaviorService; + } + return _behaviorService; + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_designer != null) + { + Control designerHolder = _designer; + _designer = null; + designerHolder.Visible = false; + designerHolder.Parent = null; + } + if (_splitter != null) + { + _splitter.SplitterMoved -= new SplitterEventHandler(OnSplitterMoved); + } + } + base.Dispose(disposing); + } + + private void ForceDesignerRedraw(bool focus) + { + if (_designer != null && _designer.IsHandleCreated) + { + NativeMethods.SendMessage(_designer.Handle, Interop.WindowMessages.WM_NCACTIVATE, focus ? 1 : 0, 0); + SafeNativeMethods.RedrawWindow(_designer.Handle, null, IntPtr.Zero, NativeMethods.RDW_FRAME); + } + } + + /// + /// Initializes this frame with the given designer view. + /// + public void Initialize(Control view) + { + _designer = view; + if (_designer is Form form) + { + form.TopLevel = false; + } + _designerRegion.Controls.Add(_designer); + SyncDesignerUI(); + _designer.Visible = true; + _designer.Enabled = true; + } + + /// + /// When we get an lose focus, we need to make sure the form designer knows about it so it'll paint it's caption right. + /// + protected override void OnGotFocus(EventArgs e) + { + ForceDesignerRedraw(true); + ISelectionService selSvc = (ISelectionService)_designerSite.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + if (selSvc.PrimarySelection is Control ctrl && !ctrl.IsDisposed) + { + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.Focus, new HandleRef(ctrl, ctrl.Handle), NativeMethods.OBJID_CLIENT, 0); + } + } + } + + /// + /// When we get an lose focus, we need to make sure the form designer knows about it so it'll paint it's caption right. + /// + protected override void OnLostFocus(EventArgs e) + { + ForceDesignerRedraw(false); + } + + void OnSplitterMoved(object sender, SplitterEventArgs e) + { + // Dirty the designer. + if (_designerSite.GetService(typeof(IComponentChangeService)) is IComponentChangeService cs) + { + try + { + cs.OnComponentChanging(_designerSite.Component, null); + cs.OnComponentChanged(_designerSite.Component, null, null, null); + } + catch + { + } + } + } + + void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) + { + if (e.Category == UserPreferenceCategory.Window && _designer != null) + { + SyncDesignerUI(); + } + } + + /// + /// We override this to do nothing. Otherwise, all the nice keyboard messages we want would get run through the Form's keyboard handling procedure. + /// + protected override bool ProcessDialogKey(Keys keyData) + { + return false; + } + + void SyncDesignerUI() + { + Size selectionSize = DesignerUtils.GetAdornmentDimensions(AdornmentType.Maximum); + _designerRegion.AutoScrollMargin = selectionSize; + _designer.Location = new Point(selectionSize.Width, selectionSize.Height); + if (BehaviorService != null) + { + BehaviorService.SyncSelection(); + } + } + + /// + /// Base wndProc. All messages are sent to wndProc after getting filtered through the preProcessMessage function. Inheriting controls should call base.wndProc for any messages that they don't handle. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + // Provide MouseWheel access for scrolling + case Interop.WindowMessages.WM_MOUSEWHEEL: + // Send a message to ourselves to scroll + if (!_designerRegion._messageMouseWheelProcessed) + { + _designerRegion._messageMouseWheelProcessed = true; + NativeMethods.SendMessage(_designerRegion.Handle, Interop.WindowMessages.WM_MOUSEWHEEL, m.WParam, m.LParam); + return; + } + break; + // Provide keyboard access for scrolling + case Interop.WindowMessages.WM_KEYDOWN: + int wScrollNotify = 0; + int msg = 0; + int keycode = unchecked((int)(long)m.WParam) & 0xFFFF; + switch ((Keys)keycode) + { + case Keys.Up: + wScrollNotify = NativeMethods.SB_LINEUP; + msg = Interop.WindowMessages.WM_VSCROLL; + break; + case Keys.Down: + wScrollNotify = NativeMethods.SB_LINEDOWN; + msg = Interop.WindowMessages.WM_VSCROLL; + break; + case Keys.PageUp: + wScrollNotify = NativeMethods.SB_PAGEUP; + msg = Interop.WindowMessages.WM_VSCROLL; + break; + case Keys.PageDown: + wScrollNotify = NativeMethods.SB_PAGEDOWN; + msg = Interop.WindowMessages.WM_VSCROLL; + break; + case Keys.Home: + wScrollNotify = NativeMethods.SB_TOP; + msg = Interop.WindowMessages.WM_VSCROLL; + break; + case Keys.End: + wScrollNotify = NativeMethods.SB_BOTTOM; + msg = Interop.WindowMessages.WM_VSCROLL; + break; + case Keys.Left: + wScrollNotify = NativeMethods.SB_LINEUP; + msg = Interop.WindowMessages.WM_HSCROLL; + break; + case Keys.Right: + wScrollNotify = NativeMethods.SB_LINEDOWN; + msg = Interop.WindowMessages.WM_HSCROLL; + break; + } + if ((msg == Interop.WindowMessages.WM_VSCROLL) + || (msg == Interop.WindowMessages.WM_HSCROLL)) + { + // Send a message to ourselves to scroll + NativeMethods.SendMessage(_designerRegion.Handle, msg, NativeMethods.Util.MAKELONG(wScrollNotify, 0), 0); + return; + } + break; + case Interop.WindowMessages.WM_CONTEXTMENU: + NativeMethods.SendMessage(_designer.Handle, m.Msg, m.WParam, m.LParam); + return; + } + base.WndProc(ref m); + } + + /// + /// Pushes the given control on top of the overlay list. This is a "push" operation, meaning that it forces this control to the top of the existing overlay list. + /// + int IOverlayService.PushOverlay(Control control) => _designerRegion.PushOverlay(control); + + /// + /// Removes the given control from the overlay list. Unlike pushOverlay, this can remove a control from the middle of the overlay list. + /// + void IOverlayService.RemoveOverlay(Control control) + { + _designerRegion.RemoveOverlay(control); + } + + /// + /// Inserts the overlay. + /// + void IOverlayService.InsertOverlay(Control control, int index) + { + _designerRegion.InsertOverlay(control, index); + } + + /// + /// Invalidate child overlays + /// + void IOverlayService.InvalidateOverlays(Rectangle screenRectangle) + { + _designerRegion.InvalidateOverlays(screenRectangle); + } + + /// + /// Invalidate child overlays + /// + void IOverlayService.InvalidateOverlays(Region screenRegion) + { + _designerRegion.InvalidateOverlays(screenRegion); + } + + /// + /// Requests the service to add a window 'pane'. + /// + void ISplitWindowService.AddSplitWindow(Control window) + { + if (_splitter == null) + { + _splitter = new Splitter(); + if (_uiService != null && _uiService.Styles["HorizontalResizeGrip"] is Color) + { + _splitter.BackColor = (Color)_uiService.Styles["HorizontalResizeGrip"]; + } + else + { + _splitter.BackColor = SystemColors.Control; + } + _splitter.BorderStyle = BorderStyle.Fixed3D; + _splitter.Height = 7; + _splitter.Dock = DockStyle.Bottom; + _splitter.SplitterMoved += new SplitterEventHandler(OnSplitterMoved); + } + SuspendLayout(); + window.Dock = DockStyle.Bottom; + // Compute a minimum height for this window. + int minHeight = 80; + if (window.Height < minHeight) + { + window.Height = minHeight; + } + Controls.Add(_splitter); + Controls.Add(window); + ResumeLayout(); + } + + /// + /// Requests the service to remove a window 'pane'. + /// + void ISplitWindowService.RemoveSplitWindow(Control window) + { + SuspendLayout(); + Controls.Remove(window); + Controls.Remove(_splitter); + ResumeLayout(); + } + + /// + /// Returns IEnumerable of all windows which need to be themed when running inside VS We don't know how to do theming here but we know which windows need to be themed. The two ScrollableControls that hold the designer and the tray need to be themed, all of the children of the designed form should not be themed. The tray contains only conrols which are not visible in the user app but are visible inside VS. As a result, we want to theme all windows within the tray but only the top window for the designer pane. + /// + IEnumerable IContainsThemedScrollbarWindows.ThemedScrollbarWindows() + { + ArrayList windows = new ArrayList(); + foreach (Control c in Controls) + { + ThemedScrollbarWindow windowInfo = new ThemedScrollbarWindow { Handle = c.Handle }; + if (c is OverlayControl) + { + windowInfo.Mode = ThemedScrollbarMode.OnlyTopLevel; + } + else + { + windowInfo.Mode = ThemedScrollbarMode.All; + } + windows.Add(windowInfo); + } + return windows; + } + + /// + /// This is a scrollable control that supports additional floating overlay controls. + /// + private class OverlayControl : ScrollableControl + { + private readonly ArrayList _overlayList; + private readonly IServiceProvider _provider; + internal bool _messageMouseWheelProcessed; + private BehaviorService _behaviorService; + + /// + /// Creates a new overlay control. + /// + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + public OverlayControl(IServiceProvider provider) + { + _provider = provider; + _overlayList = new ArrayList(); + AutoScroll = true; + Text = "OverlayControl"; + } + + protected override AccessibleObject CreateAccessibilityInstance() + { + return new OverlayControlAccessibleObject(this); + } + + /// + /// Demand creates a ptr to the BehaviorService + /// + private BehaviorService BehaviorService + { + get + { + if (_behaviorService == null) + { + _behaviorService = _provider.GetService(typeof(BehaviorService)) as BehaviorService; + } + return _behaviorService; + } + } + + /// + /// At handle creation time we request the designer's handle and parent it. + /// + protected override void OnCreateControl() + { + base.OnCreateControl(); + // Loop through all of the overlays, create them, and hook them up + if (_overlayList != null) + { + foreach (Control c in _overlayList) + { + ParentOverlay(c); + } + } + + // We've reparented everything, which means that our selection UI is probably out of sync. Ask it to sync. + if (BehaviorService != null) + { + BehaviorService.SyncSelection(); + } + } + + /// + /// We override onLayout to provide our own custom layout functionality. This just overlaps all of the controls. + /// + protected override void OnLayout(LayoutEventArgs e) + { + base.OnLayout(e); + Rectangle client = DisplayRectangle; + + // Loop through all of the overlays and size them. Also make sure that they are still on top of the zorder, because a handle recreate could have changed this. + if (_overlayList != null) + { + foreach (Control c in _overlayList) + { + c.Bounds = client; + } + } + } + + /// + /// Called to parent an overlay window into our document. This assumes that we call in reverse stack order, as it always pushes to the top of the z-order. + /// + private void ParentOverlay(Control control) + { + NativeMethods.SetParent(control.Handle, Handle); + SafeNativeMethods.SetWindowPos(control.Handle, (IntPtr)NativeMethods.HWND_TOP, 0, 0, 0, 0, NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOMOVE); + } + + /// + /// Pushes the given control on top of the overlay list. This is a "push" operation, meaning that it forces this control to the top of the existing overlay list. + /// + public int PushOverlay(Control control) + { + Debug.Assert(_overlayList.IndexOf(control) == -1, "Duplicate overlay in overlay service :" + control.GetType().FullName); + _overlayList.Add(control); + // We need to have these components parented, but we don't want them to effect our layout. + if (IsHandleCreated) + { + ParentOverlay(control); + control.Bounds = DisplayRectangle; + } + return _overlayList.IndexOf(control); + } + + /// + /// Removes the given control from the overlay list. Unlike pushOverlay, this can remove a control from the middle of the overlay list. + /// + public void RemoveOverlay(Control control) + { + Debug.Assert(_overlayList.IndexOf(control) != -1, "Control is not in overlay service :" + control.GetType().FullName); + _overlayList.Remove(control); + control.Visible = false; + control.Parent = null; + } + + /// + /// Inserts Overlay. + /// + public void InsertOverlay(Control control, int index) + { + Debug.Assert(_overlayList.IndexOf(control) == -1, "Duplicate overlay in overlay service :" + control.GetType().FullName); + Control c = (Control)_overlayList[index]; + RemoveOverlay(c); + PushOverlay(control); + PushOverlay(c); + c.Visible = true; + } + + /// + /// Invalidates overlays that intersect with the given section of the screen; + /// + public void InvalidateOverlays(Rectangle screenRectangle) + { + // paint in inverse order so that things at the front paint last. + for (int i = _overlayList.Count - 1; i >= 0; i--) + { + if (_overlayList[i] is Control overlayControl) + { + Rectangle invalidateRect = new Rectangle(overlayControl.PointToClient(screenRectangle.Location), screenRectangle.Size); + if (overlayControl.ClientRectangle.IntersectsWith(invalidateRect)) + { + overlayControl.Invalidate(invalidateRect); + } + } + } + } + + /// + /// Invalidates overlays that intersect with the given section of the screen; + /// + public void InvalidateOverlays(Region screenRegion) + { + // paint in inverse order so that things at the front paint last. + for (int i = _overlayList.Count - 1; i >= 0; i--) + { + if (_overlayList[i] is Control overlayControl) + { + Rectangle overlayControlScreenBounds = overlayControl.Bounds; + overlayControlScreenBounds.Location = overlayControl.PointToScreen(overlayControl.Location); + using (Region intersectionRegion = screenRegion.Clone()) + { + // get the intersection of everything on the screen that's invalidating and the overlaycontrol + intersectionRegion.Intersect(overlayControlScreenBounds); + // translate this down to overlay control coordinates. + intersectionRegion.Translate(-overlayControlScreenBounds.X, -overlayControlScreenBounds.Y); + overlayControl.Invalidate(intersectionRegion); + } + } + } + } + /// + /// Need to know when child windows are created so we can properly set the Z-order + /// + protected override void WndProc(ref Message m) + { + base.WndProc(ref m); + if (m.Msg == Interop.WindowMessages.WM_PARENTNOTIFY && NativeMethods.Util.LOWORD(unchecked((int)(long)m.WParam)) == (short)Interop.WindowMessages.WM_CREATE) + { + if (_overlayList != null) + { + bool ourWindow = false; + foreach (Control c in _overlayList) + { + if (c.IsHandleCreated && m.LParam == c.Handle) + { + ourWindow = true; + break; + } + } + + if (!ourWindow) + { + foreach (Control c in _overlayList) + { + SafeNativeMethods.SetWindowPos(c.Handle, (IntPtr)NativeMethods.HWND_TOP, 0, 0, 0, 0, NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOMOVE); + } + } + } + } + else if ((m.Msg == Interop.WindowMessages.WM_VSCROLL || m.Msg == Interop.WindowMessages.WM_HSCROLL) && BehaviorService != null) + { + BehaviorService.SyncSelection(); + } + else if ((m.Msg == Interop.WindowMessages.WM_MOUSEWHEEL)) + { + _messageMouseWheelProcessed = false; + if (BehaviorService != null) + { + BehaviorService.SyncSelection(); + } + } + } + + public class OverlayControlAccessibleObject : Control.ControlAccessibleObject + { + public OverlayControlAccessibleObject(OverlayControl owner) : base(owner) + { + } + + public override AccessibleObject HitTest(int x, int y) + { + // Since the SelectionUIOverlay in first in the z-order, it normally gets + // returned from accHitTest. But we'd rather expose the form that is being + // designed. + // + foreach (Control c in Owner.Controls) + { + AccessibleObject cao = c.AccessibilityObject; + if (cao.Bounds.Contains(x, y)) + { + return cao; + } + } + return base.HitTest(x, y); + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs index 645b6e9fa01..30e06031529 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs @@ -9,104 +9,101 @@ namespace System.Windows.Forms.Design { /// - /// Provides access to get and set option values for a designer. + /// Provides access to get and set option values for a designer. /// [ComVisible(true)] public class DesignerOptions { + private const int MinGridSize = 2; + private const int MaxGridSize = 200; + private Size _gridSize = new Size(8, 8); + /// - /// Public GridSize property. + /// Public GridSize property. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDisplayName(nameof(SR.DesignerOptions_GridSizeDisplayName))] [SRDescription(nameof(SR.DesignerOptions_GridSizeDesc))] public virtual Size GridSize { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); + get => _gridSize; + set + { + //do some validation checking here + if (value.Width < MinGridSize) + { + value.Width = MinGridSize; + } + if (value.Height < MinGridSize) + { + value.Height = MinGridSize; + } + if (value.Width > MaxGridSize) + { + value.Width = MaxGridSize; + } + if (value.Height > MaxGridSize) + { + value.Height = MaxGridSize; + } + + _gridSize = value; + } } /// - /// Public ShowGrid property. + /// Public ShowGrid property. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDisplayName(nameof(SR.DesignerOptions_ShowGridDisplayName))] [SRDescription(nameof(SR.DesignerOptions_ShowGridDesc))] - public virtual bool ShowGrid - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool ShowGrid { get; set; } = true; /// - /// Public SnapToGrid property. + /// Public SnapToGrid property. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDisplayName(nameof(SR.DesignerOptions_SnapToGridDisplayName))] [SRDescription(nameof(SR.DesignerOptions_SnapToGridDesc))] - public virtual bool SnapToGrid - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool SnapToGrid { get; set; } = true; /// - /// This property enables or disables snaplines in the designer. + /// This property enables or disables snaplines in the designer. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDescription(nameof(SR.DesignerOptions_UseSnapLines))] - public virtual bool UseSnapLines - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool UseSnapLines { get; set; } /// - /// This property enables or disables smart tags in the designer. + /// This property enables or disables smart tags in the designer. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDescription(nameof(SR.DesignerOptions_UseSmartTags))] - public virtual bool UseSmartTags - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool UseSmartTags { get; set; } /// - /// This property enables or disables smart tags in the designer. + /// This property enables or disables smart tags in the designer. /// [SRDisplayName(nameof(SR.DesignerOptions_ObjectBoundSmartTagAutoShowDisplayName))] [SRCategory(nameof(SR.DesignerOptions_ObjectBoundSmartTagSettings))] [SRDescription(nameof(SR.DesignerOptions_ObjectBoundSmartTagAutoShow))] - public virtual bool ObjectBoundSmartTagAutoShow - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool ObjectBoundSmartTagAutoShow { get; set; } = true; /// - /// This property enables or disables the component cache + /// This property enables or disables the component cache /// [SRDisplayName(nameof(SR.DesignerOptions_CodeGenDisplay))] [SRCategory(nameof(SR.DesignerOptions_CodeGenSettings))] [SRDescription(nameof(SR.DesignerOptions_OptimizedCodeGen))] - public virtual bool UseOptimizedCodeGeneration - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool UseOptimizedCodeGeneration { get; set; } /// - /// This property enables or disables the InSitu Editing for ToolStrips + /// This property enables or disables the InSitu Editing for ToolStrips /// [SRDisplayName(nameof(SR.DesignerOptions_EnableInSituEditingDisplay))] [SRCategory(nameof(SR.DesignerOptions_EnableInSituEditingCat))] [SRDescription(nameof(SR.DesignerOptions_EnableInSituEditingDesc))] [Browsable(false)] - public virtual bool EnableInSituEditing - { - get => throw new NotImplementedException(SR.NotImplementedByDesign); - set => throw new NotImplementedException(SR.NotImplementedByDesign); - } + public virtual bool EnableInSituEditing { get; set; } = true; } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerToolStripControlHost.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerToolStripControlHost.cs new file mode 100644 index 00000000000..8e5edf60a6d --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerToolStripControlHost.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// This internal class is used by the new ToolStripDesigner to add a dummy node to the end. This class inherits from ToolStripControlHost and overrides the CanSelect property so that the dummy Node when shown in the designer doesnt show selection on Mouse movements. The image is set to theDummyNodeImage embedded into the resources. + /// + + internal class DesignerToolStripControlHost : ToolStripControlHost, IComponent + { + private BehaviorService _behaviorService; + // disable csharp compiler warning #0414: field assigned unused value +#pragma warning disable 0414 + internal ToolStrip _parent = null; +#pragma warning restore 0414 + + public DesignerToolStripControlHost(Control c) : base(c) + { + // this ToolStripItem should not have defaultPadding. + Margin = Padding.Empty; + } + + /// + /// We need to return Default size for Editor ToolStrip (92, 22). + /// + protected override Size DefaultSize + { + get => new Size(92, 22); + } + + internal GlyphCollection GetGlyphs(ToolStrip parent, GlyphCollection glyphs, System.Windows.Forms.Design.Behavior.Behavior standardBehavior) + { + if (_behaviorService == null) + { + _behaviorService = (BehaviorService)parent.Site.GetService(typeof(BehaviorService)); + } + Point loc = _behaviorService.ControlToAdornerWindow(Parent); + Rectangle r = Bounds; + r.Offset(loc); + r.Inflate(-2, -2); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Top, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Bottom, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Left, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Right, standardBehavior, true)); + return glyphs; + } + + internal void RefreshSelectionGlyph() + { + if (Control is ToolStrip miniToolStrip) + { + if (miniToolStrip.Renderer is ToolStripTemplateNode.MiniToolStripRenderer renderer) + { + renderer.State = (int)TemplateNodeSelectionState.None; + miniToolStrip.Invalidate(); + } + } + } + + internal void SelectControl() + { + if (Control is ToolStrip miniToolStrip) + { + if (miniToolStrip.Renderer is ToolStripTemplateNode.MiniToolStripRenderer renderer) + { + renderer.State = (int)TemplateNodeSelectionState.TemplateNodeSelected; + miniToolStrip.Focus(); + miniToolStrip.Invalidate(); + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerUtils.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerUtils.cs new file mode 100644 index 00000000000..28fcb917d0a --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerUtils.cs @@ -0,0 +1,962 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// Contains designer utilities. + /// + internal static class DesignerUtils + { + private static Size s_minDragSize = Size.Empty; + //brush used to draw a 'hover' state over a designer action glyph + private static SolidBrush s_hoverBrush = new SolidBrush(Color.FromArgb(50, SystemColors.Highlight)); + //brush used to draw the resizeable selection borders around controls/components + private static HatchBrush s_selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.ControlDarkDark, Color.Transparent); + //Pens and Brushes used via GDI to render our grabhandles + private static IntPtr s_grabHandleFillBrushPrimary = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.Window)); + private static IntPtr s_grabHandleFillBrush = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.ControlText)); + private static IntPtr s_grabHandlePenPrimary = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, ColorTranslator.ToWin32(SystemColors.ControlText)); + private static IntPtr s_grabHandlePen = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, ColorTranslator.ToWin32(SystemColors.Window)); + + //The box-like image used as the user is dragging comps from the toolbox + private static Bitmap s_boxImage = null; + public static int BOXIMAGESIZE = 16; + + // selection border size + public static int SELECTIONBORDERSIZE = 1; + // Although the selection border is only 1, we actually want a 3 pixel hittestarea + public static int SELECTIONBORDERHITAREA = 3; + + // We want to make sure that the 1 pixel selectionborder is centered on the handles. The fact that the border is actually 3 pixels wide works like magic. If you draw a picture, then you will see why. + //grabhandle size (diameter) + public static int HANDLESIZE = 7; + //how much should the grabhandle overlap the control + public static int HANDLEOVERLAP = 2; + //we want the selection border to be centered on a grabhandle, so how much do. we need to offset the border from the control to make that happen + public static int SELECTIONBORDEROFFSET = ((HANDLESIZE - SELECTIONBORDERSIZE) / 2) - HANDLEOVERLAP; + + //no-resize handle size (diameter) + public static int NORESIZEHANDLESIZE = 5; + //we want the selection border to be centered on a grabhandle, so how much do + //we need to offset the border from the control to make that happen + public static int NORESIZEBORDEROFFSET = ((NORESIZEHANDLESIZE - SELECTIONBORDERSIZE) / 2); + + //lock handle height + public static int LOCKHANDLEHEIGHT = 9; + //total lock handle width + public static int LOCKHANDLEWIDTH = 7; + //how much should the lockhandle overlap the control + public static int LOCKHANDLEOVERLAP = 2; + //we want the selection border to be centered on the no-resize handle, so calculate how many pixels we need + //to offset the selection border from the control -- since the handle is not square, we need one in each direction + public static int LOCKEDSELECTIONBORDEROFFSET_Y = ((LOCKHANDLEHEIGHT - SELECTIONBORDERSIZE) / 2) - LOCKHANDLEOVERLAP; + public static int LOCKEDSELECTIONBORDEROFFSET_X = ((LOCKHANDLEWIDTH - SELECTIONBORDERSIZE) / 2) - LOCKHANDLEOVERLAP; + + // upper rectangle size (diameter) + public static int LOCKHANDLESIZE_UPPER = 5; + // lower rectangle size + public static int LOCKHANDLEHEIGHT_LOWER = 6; + public static int LOCKHANDLEWIDTH_LOWER = 7; + + //Offset used when drawing the upper rect of a lock handle + public static int LOCKHANDLEUPPER_OFFSET = (LOCKHANDLEWIDTH_LOWER - LOCKHANDLESIZE_UPPER) / 2; + //Offset used when drawing the lower rect of a lock handle + public static int LOCKHANDLELOWER_OFFSET = (LOCKHANDLEHEIGHT - LOCKHANDLEHEIGHT_LOWER); + + public static int CONTAINERGRABHANDLESIZE = 15; + //delay for showing snaplines on keyboard movements + public static int SNAPELINEDELAY = 1000; + + //min new row/col style size for the table layout panel + public static int MINIMUMSTYLESIZE = 20; + public static int MINIMUMSTYLEPERCENT = 50; + + //min width/height used to create bitmap to paint control into. + public static int MINCONTROLBITMAPSIZE = 1; + //min size for row/col style during a resize drag operation + public static int MINUMUMSTYLESIZEDRAG = 8; + //min # of rows/cols for the tablelayoutpanel when it is newly created + public static int DEFAULTROWCOUNT = 2; + public static int DEFAULTCOLUMNCOUNT = 2; + + //size of the col/row grab handle glyphs for teh table layout panel + public static int RESIZEGLYPHSIZE = 4; + + //default value for Form padding if it has not been set in the designer (usability study request) + public static int DEFAULTFORMPADDING = 9; + + //use these value to signify ANY of the right, top, left, center, or bottom alignments with the ContentAlignment enum. + public static readonly ContentAlignment anyTopAlignment = ContentAlignment.TopLeft | ContentAlignment.TopCenter | ContentAlignment.TopRight; + /* UNUSED: private static readonly ContentAlignment anyBottom = ContentAlignment.BottomLeft | ContentAlignment.BottomCenter | ContentAlignment.BottomRight;*/ + public static readonly ContentAlignment anyMiddleAlignment = ContentAlignment.MiddleLeft | ContentAlignment.MiddleCenter | ContentAlignment.MiddleRight; + + /// + /// Scale all hardcoded sizes if needed + /// + static DesignerUtils() + { + if (!DpiHelper.IsScalingRequired) + { + return; + } + + BOXIMAGESIZE = DpiHelper.LogicalToDeviceUnitsX(BOXIMAGESIZE); + SELECTIONBORDERSIZE = DpiHelper.LogicalToDeviceUnitsX(SELECTIONBORDERSIZE); + SELECTIONBORDERHITAREA = DpiHelper.LogicalToDeviceUnitsX(SELECTIONBORDERHITAREA); + HANDLESIZE = DpiHelper.LogicalToDeviceUnitsX(HANDLESIZE); + HANDLEOVERLAP = DpiHelper.LogicalToDeviceUnitsX(HANDLEOVERLAP); + NORESIZEHANDLESIZE = DpiHelper.LogicalToDeviceUnitsX(NORESIZEHANDLESIZE); + LOCKHANDLEHEIGHT = DpiHelper.LogicalToDeviceUnitsX(LOCKHANDLEHEIGHT); + LOCKHANDLEWIDTH = DpiHelper.LogicalToDeviceUnitsX(LOCKHANDLEWIDTH); + LOCKHANDLEOVERLAP = DpiHelper.LogicalToDeviceUnitsX(LOCKHANDLEOVERLAP); + LOCKHANDLESIZE_UPPER = DpiHelper.LogicalToDeviceUnitsX(LOCKHANDLESIZE_UPPER); + LOCKHANDLEHEIGHT_LOWER = DpiHelper.LogicalToDeviceUnitsX(LOCKHANDLEHEIGHT_LOWER); + LOCKHANDLEWIDTH_LOWER = DpiHelper.LogicalToDeviceUnitsX(LOCKHANDLEWIDTH_LOWER); + CONTAINERGRABHANDLESIZE = DpiHelper.LogicalToDeviceUnitsX(CONTAINERGRABHANDLESIZE); + RESIZEGLYPHSIZE = DpiHelper.LogicalToDeviceUnitsX(RESIZEGLYPHSIZE); + + SELECTIONBORDEROFFSET = ((HANDLESIZE - SELECTIONBORDERSIZE) / 2) - HANDLEOVERLAP; + NORESIZEBORDEROFFSET = ((NORESIZEHANDLESIZE - SELECTIONBORDERSIZE) / 2); + LOCKEDSELECTIONBORDEROFFSET_Y = ((LOCKHANDLEHEIGHT - SELECTIONBORDERSIZE) / 2) - LOCKHANDLEOVERLAP; + LOCKEDSELECTIONBORDEROFFSET_X = ((LOCKHANDLEWIDTH - SELECTIONBORDERSIZE) / 2) - LOCKHANDLEOVERLAP; + LOCKHANDLEUPPER_OFFSET = (LOCKHANDLEWIDTH_LOWER - LOCKHANDLESIZE_UPPER) / 2; + LOCKHANDLELOWER_OFFSET = (LOCKHANDLEHEIGHT - LOCKHANDLEHEIGHT_LOWER); + } + + /// + /// Used when the user clicks and drags a toolbox item onto the documentdesigner - this is the small box that is painted beneath the mouse pointer. + /// + public static Image BoxImage + { + get + { + if (s_boxImage == null) + { + s_boxImage = new Bitmap(BOXIMAGESIZE, BOXIMAGESIZE, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); + using (Graphics g = Graphics.FromImage(s_boxImage)) + { + g.FillRectangle(new SolidBrush(SystemColors.InactiveBorder), 0, 0, BOXIMAGESIZE, BOXIMAGESIZE); + g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), 0, 0, BOXIMAGESIZE - 1, BOXIMAGESIZE - 1); + } + } + return s_boxImage; + } + } + + /// + /// Used by Designer action glyphs to render a 'mouse hover' state. + /// + public static Brush HoverBrush + { + get => s_hoverBrush; + } + + /// + /// Demand created size used to determine how far the user needs to drag the mouse before a drag operation starts. + /// + public static Size MinDragSize + { + get + { + if (s_minDragSize == Size.Empty) + { + Size minDrag = SystemInformation.DragSize; + Size minDblClick = SystemInformation.DoubleClickSize; + s_minDragSize.Width = Math.Max(minDrag.Width, minDblClick.Width); + s_minDragSize.Height = Math.Max(minDrag.Height, minDblClick.Height); + } + return s_minDragSize; + } + } + + public static Point LastCursorPoint + { + get + { + int lastXY = SafeNativeMethods.GetMessagePos(); + return new Point(NativeMethods.Util.SignedLOWORD(lastXY), NativeMethods.Util.SignedHIWORD(lastXY)); + } + } + + // Recreate the brushes - behaviorservice calls this when the user preferences changes + public static void SyncBrushes() + { + s_hoverBrush.Dispose(); + s_hoverBrush = new SolidBrush(Color.FromArgb(50, SystemColors.Highlight)); + + s_selectionBorderBrush.Dispose(); + s_selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.ControlDarkDark, Color.Transparent); + + SafeNativeMethods.DeleteObject(new HandleRef(null, s_grabHandleFillBrushPrimary)); + s_grabHandleFillBrushPrimary = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.Window)); + + SafeNativeMethods.DeleteObject(new HandleRef(null, s_grabHandleFillBrush)); + s_grabHandleFillBrush = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.ControlText)); + + SafeNativeMethods.DeleteObject(new HandleRef(null, s_grabHandlePenPrimary)); + s_grabHandlePenPrimary = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, ColorTranslator.ToWin32(SystemColors.ControlText)); + + SafeNativeMethods.DeleteObject(new HandleRef(null, s_grabHandlePen)); + s_grabHandlePen = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, ColorTranslator.ToWin32(SystemColors.Window)); + } + + /// + /// Draws a ControlDarkDark border around the given image. + /// + private static void DrawDragBorder(Graphics g, Size imageSize, int borderSize, Color backColor) + { + Pen pen = SystemPens.ControlDarkDark; + if (backColor != Color.Empty && backColor.GetBrightness() < .5) + { + pen = SystemPens.ControlLight; + } + + //draw a border w/o the corners connecting + g.DrawLine(pen, 1, 0, imageSize.Width - 2, 0); + g.DrawLine(pen, 1, imageSize.Height - 1, imageSize.Width - 2, imageSize.Height - 1); + g.DrawLine(pen, 0, 1, 0, imageSize.Height - 2); + g.DrawLine(pen, imageSize.Width - 1, 1, imageSize.Width - 1, imageSize.Height - 2); + + //loop through drawing inner-rects until we get the proper thickness + for (int i = 1; i < borderSize; i++) + { + g.DrawRectangle(pen, i, i, imageSize.Width - (2 + i), imageSize.Height - (2 + i)); + } + } + + /// + /// Used for drawing the borders around controls that are being resized + /// + public static void DrawResizeBorder(Graphics g, Region resizeBorder, Color backColor) + { + Brush brush = SystemBrushes.ControlDarkDark; + if (backColor != Color.Empty && backColor.GetBrightness() < .5) + { + brush = SystemBrushes.ControlLight; + } + + g.FillRegion(brush, resizeBorder); + } + + /// + /// Used for drawing the frame when doing a mouse drag + /// + public static void DrawFrame(Graphics g, Region resizeBorder, FrameStyle style, Color backColor) + { + Brush brush; + Color color = SystemColors.ControlDarkDark; + if (backColor != Color.Empty && backColor.GetBrightness() < .5) + { + color = SystemColors.ControlLight; + } + switch (style) + { + case FrameStyle.Dashed: + brush = new HatchBrush(HatchStyle.Percent50, color, Color.Transparent); + break; + case FrameStyle.Thick: + default: + brush = new SolidBrush(color); + break; + } + g.FillRegion(brush, resizeBorder); + brush.Dispose(); + } + + /// + /// Used for drawing the grabhandles around sizeable selected controls and components. + /// + public static void DrawGrabHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph) + { + IntPtr hDC = graphics.GetHdc(); + try + { + //set our pen and brush based on primary selection + IntPtr oldBrush = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush)); + IntPtr oldPen = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? s_grabHandlePenPrimary : s_grabHandlePen)); + + //draw our rounded rect grabhandle + SafeNativeMethods.RoundRect(new HandleRef(glyph, hDC), bounds.Left, bounds.Top, bounds.Right, bounds.Bottom, 2, 2); + //restore old pen and brush + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldBrush)); + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldPen)); + } + + finally + { + graphics.ReleaseHdcInternal(hDC); + } + } + + /// + /// Used for drawing the no-resize handle for non-resizeable selected controls and components. + /// + public static void DrawNoResizeHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph) + { + IntPtr hDC = graphics.GetHdc(); + try + { + //set our pen and brush based on primary selection + IntPtr oldBrush = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush)); + IntPtr oldPen = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, s_grabHandlePenPrimary)); + + //draw our rect no-resize handle + SafeNativeMethods.Rectangle(new HandleRef(glyph, hDC), bounds.Left, bounds.Top, bounds.Right, bounds.Bottom); + //restore old pen and brush + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldBrush)); + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldPen)); + } + finally + { + graphics.ReleaseHdcInternal(hDC); + } + } + + /// + /// Used for drawing the lock handle for locked selected controls and components. + /// + public static void DrawLockedHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph) + { + IntPtr hDC = graphics.GetHdc(); + try + { + IntPtr oldPen = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, s_grabHandlePenPrimary)); + // Upper rect - upper rect is always filled with the primary brush + IntPtr oldBrush = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, s_grabHandleFillBrushPrimary)); + SafeNativeMethods.RoundRect(new HandleRef(glyph, hDC), bounds.Left + LOCKHANDLEUPPER_OFFSET, bounds.Top, + bounds.Left + LOCKHANDLEUPPER_OFFSET + LOCKHANDLESIZE_UPPER, bounds.Top + LOCKHANDLESIZE_UPPER, 2, 2); + // Lower rect - its fillbrush depends on the primary selection + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush)); + SafeNativeMethods.Rectangle(new HandleRef(glyph, hDC), bounds.Left, bounds.Top + LOCKHANDLELOWER_OFFSET, bounds.Right, bounds.Bottom); + + //restore old pen and brush + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldBrush)); + SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldPen)); + } + finally + { + graphics.ReleaseHdcInternal(hDC); + } + } + + /// + /// Uses the lockedBorderBrush to draw a 'locked' border on the given Graphics at the specified bounds. + /// + public static void DrawSelectionBorder(Graphics graphics, Rectangle bounds) + { + graphics.FillRectangle(s_selectionBorderBrush, bounds); + } + + /// + /// Used to generate an image that represents the given control. First, this method will call the 'GenerateSnapShotWithWM_PRINT' method on the control. If we believe that this method did not return us a valid image (caused by some comctl/ax controls not properly responding to a wm_print) then we will attempt to do a bitblt of the control instead. + /// + public static void GenerateSnapShot(Control control, ref Image image, int borderSize, double opacity, Color backColor) + { + //GenerateSnapShot will return a boolean value indicating if the control returned an image or not... + if (!GenerateSnapShotWithWM_PRINT(control, ref image)) + { + //here, we failed to get the image on wmprint - so try bitblt + GenerateSnapShotWithBitBlt(control, ref image); + //if we still failed - we'll just fall though, put up a border around an empty area and call it good enough + } + //set the opacity + if (opacity < 1.0 && opacity > 0.0) + { + // make this semi-transparent + SetImageAlpha((Bitmap)image, opacity); + } + + // draw a drag border around this thing + if (borderSize > 0) + { + using (Graphics g = Graphics.FromImage(image)) + { + DrawDragBorder(g, image.Size, borderSize, backColor); + } + } + } + + /// + /// Retrieves the width and height of a selection border grab handle. Designers may need this to properly position their user interfaces. + /// + public static Size GetAdornmentDimensions(AdornmentType adornmentType) + { + switch (adornmentType) + { + case AdornmentType.GrabHandle: + return new Size(HANDLESIZE, HANDLESIZE); + case AdornmentType.ContainerSelector: + case AdornmentType.Maximum: + return new Size(CONTAINERGRABHANDLESIZE, CONTAINERGRABHANDLESIZE); + } + return new Size(0, 0); + } + + public static bool UseSnapLines(IServiceProvider provider) + { + bool useSnapLines = true; + object optionValue = null; + if (provider.GetService(typeof(DesignerOptionService)) is DesignerOptionService options) + { + PropertyDescriptor snaplinesProp = options.Options.Properties["UseSnapLines"]; + if (snaplinesProp != null) + { + optionValue = snaplinesProp.GetValue(null); + } + } + + if (optionValue != null && optionValue is bool) + { + useSnapLines = (bool)optionValue; + } + return useSnapLines; + } + + public static object GetOptionValue(IServiceProvider provider, string name) + { + object optionValue = null; + if (provider != null) + { + if (provider.GetService(typeof(DesignerOptionService)) is DesignerOptionService desOpts) + { + PropertyDescriptor prop = desOpts.Options.Properties[name]; + if (prop != null) + { + optionValue = prop.GetValue(null); + } + } + else + { + if (provider.GetService(typeof(IDesignerOptionService)) is IDesignerOptionService optSvc) + { + optionValue = optSvc.GetOptionValue("WindowsFormsDesigner\\General", name); + } + } + } + return optionValue; + } + + /// + /// Uses BitBlt to geta snapshot of the control + /// + public static void GenerateSnapShotWithBitBlt(Control control, ref Image image) + { + //get the DC's and create our image + HandleRef hWnd = new HandleRef(control, control.Handle); + IntPtr controlDC = UnsafeNativeMethods.GetDC(hWnd); + image = new Bitmap(Math.Max(control.Width, MINCONTROLBITMAPSIZE), Math.Max(control.Height, MINCONTROLBITMAPSIZE), System.Drawing.Imaging.PixelFormat.Format32bppPArgb); + + using (Graphics gDest = Graphics.FromImage(image)) + { + if (control.BackColor == Color.Transparent) + { + gDest.Clear(SystemColors.Control); + } + IntPtr destDC = gDest.GetHdc(); + //perform our bitblit operation to push the image into the dest bitmap + SafeNativeMethods.BitBlt(destDC, 0, 0, image.Width, image.Height, controlDC, 0, 0, 0xcc0020/*RasterOp.SOURCE*/); + //clean up all our handles and what not + gDest.ReleaseHdc(destDC); + } + } + + /// + /// Uses WM_PRINT to get a snapshot of the control. This method will return true if the control properly responded to the wm_print message. + /// + public static bool GenerateSnapShotWithWM_PRINT(Control control, ref Image image) + { + IntPtr hWnd = control.Handle; + image = new Bitmap(Math.Max(control.Width, MINCONTROLBITMAPSIZE), Math.Max(control.Height, MINCONTROLBITMAPSIZE), System.Drawing.Imaging.PixelFormat.Format32bppPArgb); + + //Have to do this BEFORE we set the testcolor. + if (control.BackColor == Color.Transparent) + { + using (Graphics g = Graphics.FromImage(image)) + { + g.Clear(SystemColors.Control); + } + } + + // To validate that the control responded to the wm_print message, we pre-populate the bitmap with a colored center pixel. We assume that the control _did not_ respond to wm_print if these center pixel is still this value + Color testColor = Color.FromArgb(255, 252, 186, 238); + ((Bitmap)image).SetPixel(image.Width / 2, image.Height / 2, testColor); + using (Graphics g = Graphics.FromImage(image)) + { + IntPtr hDc = g.GetHdc(); + //send the actual wm_print message + NativeMethods.SendMessage(hWnd, Interop.WindowMessages.WM_PRINT, hDc, (IntPtr)(NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT)); + g.ReleaseHdc(hDc); + } + + //now check to see if our center pixel was cleared, if not then our wm_print failed + if (((Bitmap)image).GetPixel(image.Width / 2, image.Height / 2).Equals(testColor)) + { + //wm_print failed + return false; + } + return true; + } + + /// + /// Used by the Glyphs and ComponentTray to determine the Top, Left, Right, Bottom and Body bound rects related to their original bounds and bordersize. + /// + public static Rectangle GetBoundsForSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type, int borderSize) + { + Rectangle bounds = Rectangle.Empty; + switch (type) + { + case SelectionBorderGlyphType.Top: + bounds = new Rectangle(originalBounds.Left - borderSize, originalBounds.Top - borderSize, originalBounds.Width + 2 * borderSize, borderSize); + break; + case SelectionBorderGlyphType.Bottom: + bounds = new Rectangle(originalBounds.Left - borderSize, originalBounds.Bottom, originalBounds.Width + 2 * borderSize, borderSize); + break; + case SelectionBorderGlyphType.Left: + bounds = new Rectangle(originalBounds.Left - borderSize, originalBounds.Top - borderSize, borderSize, originalBounds.Height + 2 * borderSize); + break; + case SelectionBorderGlyphType.Right: + bounds = new Rectangle(originalBounds.Right, originalBounds.Top - borderSize, borderSize, originalBounds.Height + 2 * borderSize); + break; + case SelectionBorderGlyphType.Body: + bounds = originalBounds; + break; + } + return bounds; + } + + /// + /// Used by the Glyphs and ComponentTray to determine the Top, Left, Right, Bottom and Body bound rects related to their original bounds and bordersize. + /// Offset - how many pixels between the border glyph and the control + /// + private static Rectangle GetBoundsForSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type, int bordersize, int offset) + { + Rectangle bounds = GetBoundsForSelectionType(originalBounds, type, bordersize); + if (offset != 0) + { + switch (type) + { + case SelectionBorderGlyphType.Top: + bounds.Offset(-offset, -offset); + bounds.Width += 2 * offset; + break; + case SelectionBorderGlyphType.Bottom: + bounds.Offset(-offset, offset); + bounds.Width += 2 * offset; + break; + case SelectionBorderGlyphType.Left: + bounds.Offset(-offset, -offset); + bounds.Height += 2 * offset; + break; + case SelectionBorderGlyphType.Right: + bounds.Offset(offset, -offset); + bounds.Height += 2 * offset; + break; + case SelectionBorderGlyphType.Body: + bounds = originalBounds; + break; + } + } + return bounds; + } + + /// + /// Used by the Glyphs and ComponentTray to determine the Top, Left, Right, Bottom and Body bound rects related to their original bounds and bordersize. + /// + public static Rectangle GetBoundsForSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type) + { + return GetBoundsForSelectionType(originalBounds, type, DesignerUtils.SELECTIONBORDERSIZE, SELECTIONBORDEROFFSET); + } + + public static Rectangle GetBoundsForNoResizeSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type) + { + return GetBoundsForSelectionType(originalBounds, type, DesignerUtils.SELECTIONBORDERSIZE, NORESIZEBORDEROFFSET); + } + + /// + /// Identifes where the text baseline for our control which should be based on bounds, padding, font, and textalignment. + /// + public static int GetTextBaseline(Control ctrl, ContentAlignment alignment) + { + //determine the actual client area we are working in (w/padding) + Rectangle face = ctrl.ClientRectangle; + + //get the font metrics via gdi + int fontAscent = 0; + int fontHeight = 0; + using (Graphics g = ctrl.CreateGraphics()) + { + IntPtr dc = g.GetHdc(); + IntPtr hFont = ctrl.Font.ToHfont(); + IntPtr hFontOld; + try + { + hFontOld = SafeNativeMethods.SelectObject(new HandleRef(ctrl, dc), new HandleRef(ctrl, hFont)); + NativeMethods.TEXTMETRIC metrics = new NativeMethods.TEXTMETRIC(); + UnsafeNativeMethods.GetTextMetrics(new HandleRef(ctrl, dc), metrics); + //add the font ascent to the baseline + fontAscent = metrics.tmAscent + 1; + fontHeight = metrics.tmHeight; + SafeNativeMethods.SelectObject(new HandleRef(ctrl, dc), new HandleRef(ctrl, hFontOld)); + } + finally + { + SafeNativeMethods.DeleteObject(new HandleRef(ctrl.Font, hFont)); + g.ReleaseHdc(dc); + } + } + + //now add it all up + if ((alignment & anyTopAlignment) != 0) + { + return face.Top + fontAscent; + } + else if ((alignment & anyMiddleAlignment) != 0) + { + return face.Top + (face.Height / 2) - (fontHeight / 2) + fontAscent; + } + else + { + return face.Bottom - fontHeight + fontAscent; + } + } + + /// + /// Called by the ParentControlDesigner when creating a new + /// control - this will update the new control's bounds with the + /// proper toolbox/snapline information that has been stored + /// off + // + /// isMirrored - Is the ParentControlDesigner mirrored? If so, we need + /// to offset for that. This is because all snapline stuff is done + /// using a LTR coordinate system + /// + public static Rectangle GetBoundsFromToolboxSnapDragDropInfo(ToolboxSnapDragDropEventArgs e, Rectangle originalBounds, bool isMirrored) + { + Rectangle newBounds = originalBounds; + + //this should always be the case 'cause we don't + //create 'e' unless we have an offset + if (e.Offset != Point.Empty) + { + //snap either up or down depending on offset + if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Top) != 0) + { + newBounds.Y += e.Offset.Y;//snap to top - so move up our bounds + } + else if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Bottom) != 0) + { + newBounds.Y = originalBounds.Y - originalBounds.Height + e.Offset.Y; + } + + //snap either left or right depending on offset + if (!isMirrored) + { + if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Left) != 0) + { + newBounds.X += e.Offset.X;//snap to left- + } + else if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Right) != 0) + { + newBounds.X = originalBounds.X - originalBounds.Width + e.Offset.X; + } + } + else + { + // ParentControlDesigner is RTL, that means that the origin is upper-right, not upper-left + if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Left) != 0) + { + // e.Offset.X is negative when we snap to left + newBounds.X = originalBounds.X - originalBounds.Width - e.Offset.X; + } + else if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Right) != 0) + { + // e.Offset.X is positive when we snao to right + newBounds.X -= e.Offset.X; + } + } + } + + return newBounds; + } + + /// + /// Determine a unique site name for a component, starting from a base name. Return value should be passed into the Container.Add() method. If null is returned, this just means "let container generate a default name based on component type". + /// + public static string GetUniqueSiteName(IDesignerHost host, string name) + { + // Item has no explicit name, so let host generate a type-based name instead + if (string.IsNullOrEmpty(name)) + { + return null; + } + + // Get the name creation service from the designer host + INameCreationService nameCreationService = (INameCreationService)host.GetService(typeof(INameCreationService)); + if (nameCreationService == null) + { + return null; + } + + // See if desired name is already in use + object existingComponent = host.Container.Components[name]; + if (existingComponent == null) + { + // Name is not in use - but make sure that it contains valid characters before using it! + return nameCreationService.IsValidName(name) ? name : null; + } + else + { + // Name is in use (and therefore basically valid), so start appending numbers + string nameN = name; + for (int i = 1; !nameCreationService.IsValidName(nameN); ++i) + { + nameN = name + i.ToString(CultureInfo.InvariantCulture); + } + return nameN; + } + } + + /// + /// Applies the given opacity to the image + /// + private static unsafe void SetImageAlpha(Bitmap b, double opacity) + { + if (opacity == 1.0) + { + return; + } + + byte[] alphaValues = new byte[256]; + // precompute all the possible alpha values into an array so we don't do multiplications in the loop + for (int i = 0; i < alphaValues.Length; i++) + { + alphaValues[i] = (byte)(i * opacity); + } + + // lock the data in ARGB format. + // + BitmapData data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); + try + { + // compute the number of pixels that we're modifying. + int pixels = data.Height * data.Width; + int* pPixels = (int*)data.Scan0; + + // have the compiler figure out where to stop for us + // by doing the pointer math + byte* maxAddr = (byte*)(pPixels + pixels); + + // now run through the pixels only modifyng the A byte + for (byte* addr = (byte*)(pPixels) + 3; addr < maxAddr; addr += 4) + { + // the new value is just an index into our precomputed value array from above. + *addr = alphaValues[*addr]; + } + } + finally + { + // now, apply the data back to the bitmap. + b.UnlockBits(data); + } + } + + /// + /// This method removes types that are generics from the input collection + /// + public static ICollection FilterGenericTypes(ICollection types) + { + if (types == null || types.Count == 0) + return types; + + //now we get each Type and add it to the destination collection if its not a generic + ArrayList final = new ArrayList(types.Count); + foreach (Type t in types) + { + if (!t.ContainsGenericParameters) + { + final.Add(t); + } + } + return final; + } + + /// + /// Checks the given container, substituting any nested container with its owning container. Ensures that a SplitterPanel in a SplitContainer returns the same container as other form components, since SplitContainer sites its two SplitterPanels inside a nested container. + /// + public static IContainer CheckForNestedContainer(IContainer container) + { + if (container is NestedContainer nestedContainer) + { + return nestedContainer.Owner.Site.Container; + } + else + { + return container; + } + } + + /// + /// Used to create copies of the objects that we are dragging in a drag operation + /// + public static ICollection CopyDragObjects(ICollection objects, IServiceProvider svcProvider) + { + if (objects == null || svcProvider == null) + { + Debug.Fail("Invalid parameter passed to DesignerUtils.CopyObjects."); + return null; + } + + Cursor oldCursor = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + ComponentSerializationService css = svcProvider.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService; + IDesignerHost host = svcProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; + Debug.Assert(css != null, "No component serialization service -- we cannot copy the objects"); + Debug.Assert(host != null, "No host -- we cannot copy the objects"); + if (css != null && host != null) + { + SerializationStore store = null; + store = css.CreateStore(); + // Get all the objects, meaning we want the children too + ICollection copyObjects = GetCopySelection(objects, host); + + // The serialization service does not (yet) handle serializing collections + foreach (IComponent comp in copyObjects) + { + css.Serialize(store, comp); + } + store.Close(); + copyObjects = css.Deserialize(store); + + // Now, copyObjects contains a flattened list of all the controls contained in the original drag objects, that's not what we want to return. We only want to return the root drag objects, so that the caller gets an identical copy - identical in terms of objects.Count + ArrayList newObjects = new ArrayList(objects.Count); + foreach (IComponent comp in copyObjects) + { + Control c = comp as Control; + if (c != null && c.Parent == null) + { + newObjects.Add(comp); + } + else if (c == null) + { // this happens when we are dragging a toolstripitem + if (comp is ToolStripItem item && item.GetCurrentParent() == null) + { + newObjects.Add(comp); + } + } + } + Debug.Assert(newObjects.Count == objects.Count, "Why is the count of the copied objects not the same?"); + return newObjects; + } + } + finally + { + Cursor.Current = oldCursor; + } + return null; + } + + private static ICollection GetCopySelection(ICollection objects, IDesignerHost host) + { + if (objects == null || host == null) + { + return null; + } + + ArrayList copySelection = new ArrayList(); + foreach (IComponent comp in objects) + { + copySelection.Add(comp); + GetAssociatedComponents(comp, host, copySelection); + } + return copySelection; + } + + internal static void GetAssociatedComponents(IComponent component, IDesignerHost host, ArrayList list) + { + if (host == null) + { + return; + } + + if (!(host.GetDesigner(component) is ComponentDesigner designer)) + { + return; + } + + foreach (IComponent childComp in designer.AssociatedComponents) + { + if (childComp.Site != null) + { + list.Add(childComp); + GetAssociatedComponents(childComp, host, list); + } + } + } + + private static int TreeView_GetExtendedStyle(IntPtr handle) + { + IntPtr ptr = NativeMethods.SendMessage(handle, NativeMethods.TVM_GETEXTENDEDSTYLE, IntPtr.Zero, IntPtr.Zero); + return ptr.ToInt32(); + } + + private static void TreeView_SetExtendedStyle(IntPtr handle, int extendedStyle, int mask) + { + NativeMethods.SendMessage(handle, NativeMethods.TVM_SETEXTENDEDSTYLE, new IntPtr(mask), new IntPtr(extendedStyle)); + } + + /// + /// Modify a WinForms TreeView control to use the new Explorer style theme + /// + /// The tree view control to modify + public static void ApplyTreeViewThemeStyles(TreeView treeView) + { + if (treeView == null) + { + throw new ArgumentNullException(nameof(treeView)); + } + treeView.HotTracking = true; + treeView.ShowLines = false; + IntPtr hwnd = treeView.Handle; + SafeNativeMethods.SetWindowTheme(hwnd, "Explorer", null); + int exstyle = TreeView_GetExtendedStyle(hwnd); + exstyle |= NativeMethods.TVS_EX_DOUBLEBUFFER | NativeMethods.TVS_EX_FADEINOUTEXPANDOS; + TreeView_SetExtendedStyle(hwnd, exstyle, 0); + } + + private static void ListView_SetExtendedListViewStyleEx(IntPtr handle, int mask, int extendedStyle) + { + NativeMethods.SendMessage(handle, NativeMethods.LVM_SETEXTENDEDLISTVIEWSTYLE, new IntPtr(mask), new IntPtr(extendedStyle)); + } + + /// + /// Modify a WinForms ListView control to use the new Explorer style theme + /// + /// The list view control to modify + public static void ApplyListViewThemeStyles(ListView listView) + { + if (listView == null) + { + throw new ArgumentNullException(nameof(listView)); + } + IntPtr hwnd = listView.Handle; + SafeNativeMethods.SetWindowTheme(hwnd, "Explorer", null); + ListView_SetExtendedListViewStyleEx(hwnd, NativeMethods.LVS_EX_DOUBLEBUFFER, NativeMethods.LVS_EX_DOUBLEBUFFER); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerVerbToolStripMenuItem.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerVerbToolStripMenuItem.cs new file mode 100644 index 00000000000..308325e89e0 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerVerbToolStripMenuItem.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// Associates DesignerVerb with ToolStripMenuItem. + /// + internal class DesignerVerbToolStripMenuItem : ToolStripMenuItem + { + readonly DesignerVerb _verb; + + // Text is a virtual method on the base class, but since we don't override it we should be okay. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] + public DesignerVerbToolStripMenuItem(DesignerVerb verb) + { + _verb = verb; + Text = verb.Text; + RefreshItem(); + } + + public void RefreshItem() + { + if (_verb != null) + { + Visible = _verb.Visible; + Enabled = _verb.Enabled; + Checked = _verb.Checked; + } + } + + protected override void OnClick(System.EventArgs e) + { + if (_verb != null) + { + _verb.Invoke(); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DocumentDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DocumentDesigner.cs index bfd83510e58..6d6e677e78c 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DocumentDesigner.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DocumentDesigner.cs @@ -108,6 +108,43 @@ protected override void OnCreateHandle() throw new NotImplementedException(SR.NotImplementedByDesign); } + internal virtual void DoProperMenuSelection(ICollection selComponents) + { + foreach (object obj in selComponents) + { + if (obj is ContextMenu cm) + { + menuEditorService.SetMenu((Menu)obj); + } + else + { + if (obj is MenuItem item) + { + //before we set the selection, we need to check if the item belongs the current menu, if not, we need to set the menu editor to the appropiate menu, then set selection + MenuItem parent = item; + while (parent.Parent is MenuItem) + { + parent = (MenuItem)parent.Parent; + } + + if (menuEditorService.GetMenu() != parent.Parent) + { + menuEditorService.SetMenu(parent.Parent); + } + + //ok, here we have the correct editor selected for this item. Now, if there's only one item selected, then let the editor service know, if there is more than one - then the selection was done through themenu editor and we don't need to tell it + if (selComponents.Count == 1) + { + menuEditorService.SetSelection(item); + } + } + //Here, something is selected, but the menuservice isn't interested so, we'll collapse our active menu accordingly + else + menuEditorService.SetMenu(null); + } + } + } + /// /// Determines if a MenuEditorService has already been started. If not, /// this method will create a new instance of the service. diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/EditorServiceContext.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/EditorServiceContext.cs new file mode 100644 index 00000000000..9a7d8a0c80b --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/EditorServiceContext.cs @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// Provides an implementation of IWindowsFormsEditorService and ITypeDescriptorContext. Also provides a static method to invoke a UITypeEditor given a designer, an object and a property name. + /// + internal class EditorServiceContext : IWindowsFormsEditorService, ITypeDescriptorContext + { + private readonly ComponentDesigner _designer; + private IComponentChangeService _componentChangeSvc; + private readonly PropertyDescriptor _targetProperty; + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EditorServiceContext(ComponentDesigner designer) + { + _designer = designer; + } + + internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor prop) + { + _designer = designer; + _targetProperty = prop; + if (prop == null) + { + prop = TypeDescriptor.GetDefaultProperty(designer.Component); + if (prop != null && typeof(ICollection).IsAssignableFrom(prop.PropertyType)) + { + _targetProperty = prop; + } + } + Debug.Assert(_targetProperty != null, "Need PropertyDescriptor for ICollection property to associate collectoin edtior with."); + } + + internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor prop, string newVerbText) : this(designer, prop) + { + Debug.Assert(!string.IsNullOrEmpty(newVerbText), "newVerbText cannot be null or empty"); + _designer.Verbs.Add(new DesignerVerb(newVerbText, new EventHandler(OnEditItems))); + } + + public static object EditValue(ComponentDesigner designer, object objectToChange, string propName) + { + // Get PropertyDescriptor + PropertyDescriptor descriptor = TypeDescriptor.GetProperties(objectToChange)[propName]; + // Create a Context + EditorServiceContext context = new EditorServiceContext(designer, descriptor); + // Get Editor + UITypeEditor editor = descriptor.GetEditor(typeof(UITypeEditor)) as UITypeEditor; + // Get value to edit + object value = descriptor.GetValue(objectToChange); + // Edit value + object newValue = editor.EditValue(context, context, value); + + if (newValue != value) + { + try + { + descriptor.SetValue(objectToChange, newValue); + } + catch (CheckoutException) + { + + } + } + return newValue; + } + + /// + /// Our caching property for the IComponentChangeService + /// + private IComponentChangeService ChangeService + { + get + { + if (_componentChangeSvc == null) + { + _componentChangeSvc = (IComponentChangeService)((IServiceProvider)this).GetService(typeof(IComponentChangeService)); + } + return _componentChangeSvc; + } + } + + /// + /// Self-explanitory interface impl. + /// + IContainer ITypeDescriptorContext.Container + { + get + { + if (_designer.Component.Site != null) + { + return _designer.Component.Site.Container; + } + return null; + } + } + + /// + /// Self-explanitory interface impl. + /// + void ITypeDescriptorContext.OnComponentChanged() + { + ChangeService.OnComponentChanged(_designer.Component, _targetProperty, null, null); + } + + /// + /// Self-explanitory interface impl. + /// + bool ITypeDescriptorContext.OnComponentChanging() + { + try + { + ChangeService.OnComponentChanging(_designer.Component, _targetProperty); + } + catch (CheckoutException checkoutException) + { + if (checkoutException == CheckoutException.Canceled) + { + return false; + } + throw; + } + return true; + } + + object ITypeDescriptorContext.Instance + { + get => _designer.Component; + } + + PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor + { + get => _targetProperty; + } + + object IServiceProvider.GetService(Type serviceType) + { + if (serviceType == typeof(ITypeDescriptorContext) || serviceType == typeof(IWindowsFormsEditorService)) + { + return this; + } + if (_designer.Component != null && _designer.Component.Site != null) + { + return _designer.Component.Site.GetService(serviceType); + } + return null; + } + + void IWindowsFormsEditorService.CloseDropDown() + { + // we'll never be called to do this. + Debug.Fail("NOTIMPL"); + return; + } + + void IWindowsFormsEditorService.DropDownControl(Control control) + { + Debug.Fail("NOTIMPL"); + return; + } + + System.Windows.Forms.DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog) + { + IUIService uiSvc = (IUIService)((IServiceProvider)this).GetService(typeof(IUIService)); + if (uiSvc != null) + { + return uiSvc.ShowDialog(dialog); + } + else + { + return dialog.ShowDialog(_designer.Component as IWin32Window); + } + } + + /// + /// When the verb is invoked, use all the stuff above to show the dialog, etc. + /// + private void OnEditItems(object sender, EventArgs e) + { + object propertyValue = _targetProperty.GetValue(_designer.Component); + if (propertyValue == null) + { + return; + } + CollectionEditor itemsEditor = TypeDescriptor.GetEditor(propertyValue, typeof(UITypeEditor)) as CollectionEditor; + + Debug.Assert(itemsEditor != null, "Didn't get a collection editor for type '" + _targetProperty.PropertyType.FullName + "'"); + if (itemsEditor != null) + { + itemsEditor.EditValue(this, this, propertyValue); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/FormDocumentDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/FormDocumentDesigner.cs new file mode 100644 index 00000000000..2170708f263 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/FormDocumentDesigner.cs @@ -0,0 +1,703 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// The FormDocumentDesigner class builds on the DocumentDesigner. It adds shadowing for form properties that need to be shadowed and it also adds logic to properly paint the form's title bar to match the active document window. + /// + internal class FormDocumentDesigner : DocumentDesigner + { + private Size _autoScaleBaseSize = Size.Empty; + private bool _inAutoscale = false; + private int _heightDelta = 0; + private bool _isMenuInherited; //indicates if the 'active menu' is inherited + private bool _hasMenu = false; + private InheritanceAttribute _inheritanceAttribute; + private bool _initializing = false; + private bool _autoSize = false; + private ToolStripAdornerWindowService _toolStripAdornerWindowService = null; + + /// + /// Shadow the AcceptButton property at design-time so that we can preserve it when the form is rebuilt. Otherwise, form.Controls.Clear() will clear it out when we don't want it to. + /// + private IButtonControl AcceptButton + { + get => ShadowProperties["AcceptButton"] as IButtonControl; + set + { + ((Form)Component).AcceptButton = value; + ShadowProperties["AcceptButton"] = value; + } + } + + /// + /// Shadow the CancelButton property at design-time so that we can preserve it when the form is rebuilt. Otherwise, form.Controls.Clear() will clear it out when we don't want it to. + /// + private IButtonControl CancelButton + { + get => ShadowProperties["CancelButton"] as IButtonControl; + set + { + ((Form)Component).CancelButton = value; + ShadowProperties["CancelButton"] = value; + } + } + + /// + /// Shadowed version of the AutoScaleBaseSize property. We shadow this so that it always persists. Normally only properties that differ from the default values at instantiation are persisted, but this should always be written. So, we shadow it and add our own ShouldSerialize method. + /// + private Size AutoScaleBaseSize + { + get + { + // we don't want to get inherited value from a base form that might have been designed in a different DPI so we recalculate the thing instead of getting AutoScaleBaseSize (QFE 2280) +#pragma warning disable 618 + SizeF real = Form.GetAutoScaleSize(((Form)Component).Font); +#pragma warning restore 618 + return new Size((int)Math.Round(real.Width), (int)Math.Round(real.Height)); + } + set + { + // We do nothing at design time for this property; we always want to use the calculated value from the component. + _autoScaleBaseSize = value; + ShadowProperties["AutoScaleBaseSize"] = value; + } + } + + /// + /// We shadow the AutoSize property at design-time so that the form doesn't grow and shrink as users fiddle with autosize related properties. + /// + private bool AutoSize + { + get => _autoSize; + set => _autoSize = value; + } + + private bool ShouldSerializeAutoScaleBaseSize() + { + // Never serialize this unless AutoScale is turned on +#pragma warning disable 618 + return _initializing ? false + : ((Form)Component).AutoScale && ShadowProperties.Contains("AutoScaleBaseSize"); +#pragma warning restore 618 + } + + /// + /// Shadow property for the ClientSize property -- this allows us to intercept client size changes and apply the new menu height if necessary + /// + private Size ClientSize + { + get + { + if (_initializing) + { + return new Size(-1, -1); + } + else + { + Size size = new Size(-1, -1); + if (Component is Form form) + { + size = form.ClientSize; + // don't report the size decremented by the scroll bars, otherwise, we'll just lose that size when we run because the form doesn't take that into consideration (it's too early, it hasn't layed out and doesn't know it needs scrollbars) when sizing. + if (form.HorizontalScroll.Visible) + { + size.Height += SystemInformation.HorizontalScrollBarHeight; + } + if (form.VerticalScroll.Visible) + { + size.Width += SystemInformation.VerticalScrollBarWidth; + } + } + return size; + } + } + set + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + if (host.Loading) + { + _heightDelta = GetMenuHeight(); + } + } + ((Form)Component).ClientSize = value; + } + } + + /// + /// Shadow property for the IsMDIContainer property on a form. + /// + private bool IsMdiContainer + { + get => ((Form)Control).IsMdiContainer; + set + { + if (!value) + { + UnhookChildControls(Control); + } + ((Form)Control).IsMdiContainer = value; + if (value) + { + HookChildControls(Control); + } + } + } + + /// + /// Returns true if the active menu is an inherited component. We use this to determine if we need to resize the base control or not. + /// + private bool IsMenuInherited + { + get + { + if (_inheritanceAttribute == null && Menu != null) + { + _inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(Menu)[typeof(InheritanceAttribute)]; + if (_inheritanceAttribute.Equals(InheritanceAttribute.NotInherited)) + { + _isMenuInherited = false; + } + else + { + _isMenuInherited = true; + } + } + return _isMenuInherited; + } + } + + /// + /// Accessor method for the menu property on control. We shadow this property at design time. + /// + internal MainMenu Menu + { + get => (MainMenu)ShadowProperties["Menu"]; + set + { + if (value == ShadowProperties["Menu"]) + { + return; + } + ShadowProperties["Menu"] = value; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && !host.Loading) + { + EnsureMenuEditorService(value); + if (menuEditorService != null) + menuEditorService.SetMenu(value); + } + + if (_heightDelta == 0) + { + _heightDelta = GetMenuHeight(); + } + } + } + + /// + /// Opacity property on control. We shadow this property at design time. + /// + private double Opacity + { + get => (double)ShadowProperties["Opacity"]; + set + { + if (value < 0.0f || value > 1.0f) + { + throw new ArgumentException(string.Format(SR.InvalidBoundArgument, "value", value.ToString(CultureInfo.CurrentCulture), + (0.0f).ToString(CultureInfo.CurrentCulture), (1.0f).ToString(CultureInfo.CurrentCulture)), "value"); + } + ShadowProperties["Opacity"] = value; + } + } + + /// + /// Overrides the default implementation of ParentControlDesigner SnapLines. Note that if the Padding property is not set on our Form - we'll special case this and add default Padding values to our SnapLines. This was a usability request specific to the Form itself. Note that a Form only has Padding SnapLines. + /// + public override IList SnapLines + { + get + { + ArrayList snapLines = null; + base.AddPaddingSnapLines(ref snapLines); + if (snapLines == null) + { + Debug.Fail("why did base.AddPaddingSnapLines return null?"); + snapLines = new ArrayList(4); + } + + // if the padding has not been set - then we'll auto-add padding to form - this is a Usability request + if (Control.Padding == Padding.Empty && snapLines != null) + { + int paddingsFound = 0; // used to short-circuit once we find 4 paddings + for (int i = 0; i < snapLines.Count; i++) + { + // remove previous padding snaplines + if (snapLines[i] is SnapLine snapLine && snapLine.Filter != null && snapLine.Filter.StartsWith(SnapLine.Padding)) + { + if (snapLine.Filter.Equals(SnapLine.PaddingLeft) || snapLine.Filter.Equals(SnapLine.PaddingTop)) + { + snapLine.AdjustOffset(DesignerUtils.DEFAULTFORMPADDING); + paddingsFound++; + } + + if (snapLine.Filter.Equals(SnapLine.PaddingRight) || snapLine.Filter.Equals(SnapLine.PaddingBottom)) + { + snapLine.AdjustOffset(-DesignerUtils.DEFAULTFORMPADDING); + paddingsFound++; + } + + if (paddingsFound == 4) + { + break;//we adjusted all of our paddings + } + } + } + } + return snapLines; + } + } + + private Size Size + { + get => Control.Size; + set + { + IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(Component); + if (cs != null) + { + cs.OnComponentChanging(Component, props["ClientSize"]); + } + + Control.Size = value; + if (cs != null) + { + cs.OnComponentChanged(Component, props["ClientSize"], null, null); + } + } + } + + /// + /// Accessor method for the showInTaskbar property on control. We shadow this property at design time. + /// + private bool ShowInTaskbar + { + get => (bool)ShadowProperties["ShowInTaskbar"]; + set => ShadowProperties["ShowInTaskbar"] = value; + } + + /// + /// Accessor method for the windowState property on control. We shadow this property at design time. + /// + private FormWindowState WindowState + { + get => (FormWindowState)ShadowProperties["WindowState"]; + set => ShadowProperties["WindowState"] = value; + } + + private void ApplyAutoScaling(SizeF baseVar, Form form) + { + // We also don't do this if the property is empty. Otherwise we will perform two GetAutoScaleBaseSize calls only to find that they returned the same value. + if (!baseVar.IsEmpty) + { +#pragma warning disable 618 + SizeF newVarF = Form.GetAutoScaleSize(form.Font); +#pragma warning restore 618 + Size newVar = new Size((int)Math.Round(newVarF.Width), (int)Math.Round(newVarF.Height)); + // We save a significant amount of time by bailing early if there's no work to be done + if (baseVar.Equals(newVar)) + return; + float percY = ((float)newVar.Height) / ((float)baseVar.Height); + float percX = ((float)newVar.Width) / ((float)baseVar.Width); + try + { + _inAutoscale = true; +#pragma warning disable 618 + form.Scale(percX, percY); +#pragma warning restore 618 + } + finally + { + _inAutoscale = false; + } + } + } + + /// + /// Disposes of this designer. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + Debug.Assert(host != null, "Must have a designer host on dispose"); + } + base.Dispose(disposing); + } + + internal override void DoProperMenuSelection(ICollection selComponents) + { + foreach (object obj in selComponents) + { + //first check to see if our selection is any kind of menu: main, context, item AND the designer for the component is this one + if (obj is Menu menu) + { + //if it's a menu item, set the selection + if (menu is MenuItem item) + { + Menu currentMenu = menuEditorService.GetMenu(); + // before we set the selection, we need to check if the item belongs the current menu, if not, we need to set the menu editor to the appropiate menu, then set selection + MenuItem parent = item; + while (parent.Parent is MenuItem) + { + parent = (MenuItem)parent.Parent; + } + + if (!(currentMenu == parent.Parent)) + { + menuEditorService.SetMenu(parent.Parent); + } + + // ok, here we have the correct editor selected for this item. Now, if there's only one item selected, then let the editor service know, if there is more than one - then the selection was done through the menu editor and we don't need to tell it + if (selComponents.Count == 1) + { + menuEditorService.SetSelection(item); + } + } + // here, either it's a main or context menu, even if the menu is the current one, we still want to call this "SetMenu" method, 'cause that'll collapse it and remove the focus + else + { + menuEditorService.SetMenu(menu); + } + return; + } + // Here, something is selected, but it is in no way, shape, or form a menu so, we'll collapse our active menu accordingly + else + { + if (Menu != null && Menu.MenuItems.Count == 0) + { + menuEditorService.SetMenu(null); + } + else + { + menuEditorService.SetMenu(Menu); + } + NativeMethods.SendMessage(Control.Handle, Interop.WindowMessages.WM_NCACTIVATE, 1, 0); + } + } + } + + /// + /// Determines if a MenuEditorService has already been started. If not, this method will create a new instance of the service. We override this because we want to allow any kind of menu to start the service, not just ContextMenus. + /// + protected override void EnsureMenuEditorService(IComponent c) + { + if (menuEditorService == null && c is Menu) + { + menuEditorService = (IMenuEditorService)GetService(typeof(IMenuEditorService)); + } + } + + private void EnsureToolStripWindowAdornerService() + { + if (_toolStripAdornerWindowService == null) + { + _toolStripAdornerWindowService = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService)); + } + } + + /// + /// Gets the current menu height so we know how much to increment the form size by + /// + private int GetMenuHeight() + { + if (Menu == null || (IsMenuInherited && _initializing)) + { + return 0; + } + + if (menuEditorService != null) + { + // there is a magic property on teh menueditorservice that gives us this information. Unfortuantely, we can't compute it ourselves -- the menu shown in the designer isn't a windows one so we can't ask windows. + PropertyDescriptor heightProp = TypeDescriptor.GetProperties(menuEditorService)["MenuHeight"]; + if (heightProp != null) + { + int height = (int)heightProp.GetValue(menuEditorService); + return height; + } + } + return SystemInformation.MenuHeight; + } + + /// + /// Initializes the designer with the given component. The designer can get the component's site and request services from it in this call. + /// + public override void Initialize(IComponent component) + { + // We have to shadow the WindowState before we call base.Initialize + PropertyDescriptor windowStateProp = TypeDescriptor.GetProperties(component.GetType())["WindowState"]; + if (windowStateProp != null && windowStateProp.PropertyType == typeof(FormWindowState)) + { + WindowState = (FormWindowState)windowStateProp.GetValue(component); + } + + _initializing = true; + base.Initialize(component); + _initializing = false; + AutoResizeHandles = true; + Debug.Assert(component is Form, "FormDocumentDesigner expects its component to be a form."); + + Form form = (Form)Control; + form.WindowState = FormWindowState.Normal; + ShadowProperties["AcceptButton"] = form.AcceptButton; + ShadowProperties["CancelButton"] = form.CancelButton; + } + + /// + /// Called when a component is added to the design container. If the component isn't a control, this will demand create the component tray and add the component to it. + /// + private void OnComponentAdded(object source, ComponentEventArgs ce) + { + if (ce.Component is Menu) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && !host.Loading) + { + //if it's a MainMenu & we don't have one set for the form yet, then do it... + if (ce.Component is MainMenu && !_hasMenu) + { + PropertyDescriptor menuProp = TypeDescriptor.GetProperties(Component)["Menu"]; + Debug.Assert(menuProp != null, "What the happened to the Menu property"); + menuProp.SetValue(Component, ce.Component); + _hasMenu = true; + } + } + } + if (ce.Component is ToolStrip && _toolStripAdornerWindowService == null) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + EnsureToolStripWindowAdornerService(); + } + } + } + + /// + /// Called when a component is removed from the design container. Here, we check if a menu is being removed and handle removing the Form's mainmenu vs. other menus properly. + /// + private void OnComponentRemoved(object source, ComponentEventArgs ce) + { + if (ce.Component is Menu) + { + //if we deleted the form's mainmenu, set it null... + if (ce.Component == Menu) + { + PropertyDescriptor menuProp = TypeDescriptor.GetProperties(Component)["Menu"]; + Debug.Assert(menuProp != null, "What the happened to the Menu property"); + menuProp.SetValue(Component, null); + _hasMenu = false; + } + else if (menuEditorService != null && ce.Component == menuEditorService.GetMenu()) + { + menuEditorService.SetMenu(Menu); + } + } + if (ce.Component is ToolStrip && _toolStripAdornerWindowService != null) + { + _toolStripAdornerWindowService = null; + } + if (ce.Component is IButtonControl) + { + if (ce.Component == ShadowProperties["AcceptButton"]) + { + AcceptButton = null; + } + if (ce.Component == ShadowProperties["CancelButton"]) + { + CancelButton = null; + } + } + } + + /// + /// We're watching the handle creation in case we have a menu editor. If we do, the menu editor will have to be torn down and recreated. + /// + protected override void OnCreateHandle() + { + if (Menu != null && menuEditorService != null) + { + menuEditorService.SetMenu(null); + menuEditorService.SetMenu(Menu); + } + + if (_heightDelta != 0) + { + ((Form)Component).Height += _heightDelta; + _heightDelta = 0; + } + } + + // Called when our document becomes active. We paint our form's border the appropriate color here. + private void OnDesignerActivate(object source, EventArgs evevent) + { + // Paint the form's title bar UI-active + Control control = Control; + if (control != null && control.IsHandleCreated) + { + NativeMethods.SendMessage(control.Handle, Interop.WindowMessages.WM_NCACTIVATE, 1, 0); + SafeNativeMethods.RedrawWindow(control.Handle, null, IntPtr.Zero, NativeMethods.RDW_FRAME); + } + } + + /// + /// Called by the host when we become inactive. Here we update the title bar of our form so it's the inactive color. + /// + private void OnDesignerDeactivate(object sender, EventArgs e) + { + Control control = Control; + if (control != null && control.IsHandleCreated) + { + NativeMethods.SendMessage(control.Handle, Interop.WindowMessages.WM_NCACTIVATE, 0, 0); + SafeNativeMethods.RedrawWindow(control.Handle, null, IntPtr.Zero, NativeMethods.RDW_FRAME); + } + } + + /// + /// Called when our code loads. Here we connect us as the selection UI handler for ourselves. This is a special case because for the top level document, we are our own selection UI handler. + /// + private void OnLoadComplete(object source, EventArgs evevent) + { + if (Control is Form form) + { + // The form's ClientSize is reported including the ScrollBar's height. We need to account for this in order to display the form with scrollbars correctly. + int clientWidth = form.ClientSize.Width; + int clientHeight = form.ClientSize.Height; + if (form.HorizontalScroll.Visible && form.AutoScroll) + { + clientHeight += SystemInformation.HorizontalScrollBarHeight; + } + if (form.VerticalScroll.Visible && form.AutoScroll) + { + clientWidth += SystemInformation.VerticalScrollBarWidth; + } + + // ApplyAutoScaling causes WmWindowPosChanging to be called and there we calculate if we need to compensate for a menu being visible we were causing that calculation to fail if we set ClientSize too early. we now do the right thing AND check again if we need to compensate for the menu. + ApplyAutoScaling(_autoScaleBaseSize, form); + ClientSize = new Size(clientWidth, clientHeight); + BehaviorService svc = (BehaviorService)GetService(typeof(BehaviorService)); + if (svc != null) + { + svc.SyncSelection(); + } + + // if there is a menu and we need to update our height because of it, do it now. + if (_heightDelta == 0) + { + _heightDelta = GetMenuHeight(); + } + + if (_heightDelta != 0) + { + form.Height += _heightDelta; + _heightDelta = 0; + } + + // After loading the form if the ControlBox and ShowInTaskbar properties are false, the form will be sized incorrectly. This is due to the text property being set after the ControlBox and ShowInTaskbar properties, which causes windows to recalculate our client area wrong. The reason it does this is because after setting the ShowInTaskbar and ControlBox it assumes we have no titlebar, and bases the clientSize we pass it on that. In reality our ClientSize DOES depend on having a titlebar, so windows gets confused. This only happens at designtime, because at runtime our special DesignTime only MainMenu is not around to mess things up. Because of this, I'm adding this nasty workaround to correctly update the height at design time. + if (!form.ControlBox && !form.ShowInTaskbar && !string.IsNullOrEmpty(form.Text) && Menu != null && !IsMenuInherited) + { + form.Height += SystemInformation.CaptionHeight + 1; + } + form.PerformLayout(); + } + + } + + /// + /// Allows a designer to filter the set of properties the component it is designing will expose through the TypeDescriptor object. This method is called immediately before its corresponding "Post" method. If you are overriding this method you should call the base implementation before you perform your own filtering. + /// + protected override void PreFilterProperties(IDictionary properties) + { + PropertyDescriptor prop; + base.PreFilterProperties(properties); + // Handle shadowed properties + string[] shadowProps = new string[] { "Opacity", "Menu", "IsMdiContainer", "Size", "ShowInTaskBar", "WindowState", "AutoSize", "AcceptButton", "CancelButton" }; + Attribute[] empty = new Attribute[0]; + for (int i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(FormDocumentDesigner), prop, empty); + } + } + + // Mark auto scale base size as serializable again so we can monitor it for backwards compat. + prop = (PropertyDescriptor)properties["AutoScaleBaseSize"]; + if (prop != null) + { + properties["AutoScaleBaseSize"] = TypeDescriptor.CreateProperty(typeof(FormDocumentDesigner), prop, DesignerSerializationVisibilityAttribute.Visible); + } + + // And set the new default value attribute for client base size, and shadow it as well. + prop = (PropertyDescriptor)properties["ClientSize"]; + if (prop != null) + { + properties["ClientSize"] = TypeDescriptor.CreateProperty(typeof(FormDocumentDesigner), prop, new DefaultValueAttribute(new Size(-1, -1))); + } + } + + /// + /// Handles the WM_WINDOWPOSCHANGING message + /// + private unsafe void WmWindowPosChanging(ref Message m) + { + NativeMethods.WINDOWPOS* wp = (NativeMethods.WINDOWPOS*)m.LParam; + bool updateSize = _inAutoscale; + if (!updateSize) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + updateSize = host.Loading; + } + } + // we want to update the size if we have a menu and... + // 1) we're doing an autoscale + // 2) we're loading a form without an inherited menu (inherited forms will already have the right size) + if (updateSize && Menu != null && (wp->flags & NativeMethods.SWP_NOSIZE) == 0 && (IsMenuInherited || _inAutoscale)) + { + _heightDelta = GetMenuHeight(); + } + } + + /// + /// Overrides our base class WndProc to provide support for the menu editor service. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_WINDOWPOSCHANGING: + WmWindowPosChanging(ref m); + break; + } + base.WndProc(ref m); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/GroupedContextMenuStrip.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/GroupedContextMenuStrip.cs new file mode 100644 index 00000000000..34e0403dc5e --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/GroupedContextMenuStrip.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; + +namespace System.Windows.Forms.Design +{ + internal class GroupedContextMenuStrip : ContextMenuStrip + { + private StringCollection _groupOrdering; + private ContextMenuStripGroupCollection _groups; + private bool _populated = false; + + public bool Populated + { + set => _populated = value; + } + + public GroupedContextMenuStrip() + { + } + + public ContextMenuStripGroupCollection Groups + { + get + { + if (_groups == null) + { + _groups = new ContextMenuStripGroupCollection(); + } + return _groups; + } + } + public StringCollection GroupOrdering + { + get + { + if (_groupOrdering == null) + { + _groupOrdering = new StringCollection(); + } + return _groupOrdering; + } + } + + // merges all the items which are currently in the groups into the items collection. + public void Populate() + { + Items.Clear(); + foreach (string groupName in GroupOrdering) + { + if (_groups.ContainsKey(groupName)) + { + List items = _groups[groupName].Items; + + if (Items.Count > 0 && items.Count > 0) + { + Items.Add(new ToolStripSeparator()); + } + foreach (ToolStripItem item in items) + { + Items.Add(item); + } + } + } + _populated = true; + } + + protected override void OnOpening(CancelEventArgs e) + { + SuspendLayout(); + if (!_populated) + { + Populate(); + } + RefreshItems(); + ResumeLayout(true); + PerformLayout(); + e.Cancel = (Items.Count == 0); + base.OnOpening(e); + } + + public virtual void RefreshItems() + { + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IContainsThemedScrollbarWindows.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IContainsThemedScrollbarWindows.cs new file mode 100644 index 00000000000..584804cc75c --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IContainsThemedScrollbarWindows.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; + +namespace System.Windows.Forms.Design +{ + /// + /// Returns an enumeration of windows and flags of how their scrollbars need to be themed when the designer is running inside Visual Studio. + /// + public interface IContainsThemedScrollbarWindows + { + IEnumerable ThemedScrollbarWindows(); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IMenuStatusHandler.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IMenuStatusHandler.cs new file mode 100644 index 00000000000..b472ec881a1 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IMenuStatusHandler.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// We plug this interface into the designer event service for overriding menu commands. + /// + internal interface IMenuStatusHandler + { + /// + /// CommandSet will check with this handler on each status update to see if the handler wants to override the availability of this command. + /// + bool OverrideInvoke(MenuCommand cmd); + + /// + /// CommandSet will check with this handler on each status update to see if the handler wants to override the availability of this command. + /// + bool OverrideStatus(MenuCommand cmd); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IMouseHandler.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IMouseHandler.cs new file mode 100644 index 00000000000..720af4fb184 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IMouseHandler.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; + +namespace System.Windows.Forms.Design +{ + internal interface IMouseHandler + { + /// + /// This is called when the user double clicks on a component. The typical behavior is to create an event handler for the component's default event and navigate to the handler. + /// + void OnMouseDoubleClick(IComponent component); + + /// + /// This is called when a mouse button is depressed. This will perform the default drag action for the selected components, which is to move those components around by the mouse. + /// + void OnMouseDown(IComponent component, MouseButtons button, int x, int y); + + /// + /// This is called when the mouse momentarially hovers over the view for the given component. + /// + void OnMouseHover(IComponent component); + + /// + /// This is called for each movement of the mouse. + /// + void OnMouseMove(IComponent component, int x, int y); + /// + /// This is called when the user releases the mouse from a component. This will update the UI to reflect the release of the mouse. + /// + void OnMouseUp(IComponent component, MouseButtons button); + + /// + /// This is called when the cursor for the given component should be updated. The mouse is always over the given component's view when this is called. + /// + void OnSetCursor(IComponent component); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IOverlayService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IOverlayService.cs new file mode 100644 index 00000000000..0bc202dca49 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/IOverlayService.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// IOverlayService is a service that supports adding simple overlay windows to a design surface. Overlay windows can be used to paint extra glyphs on top of existing controls. Once an overlay is added, it will be forced on top of the Z-order for the other controls and overlays. If you want the overlay to be transparent, then you must do this work yourself. A typical way to make an overlay control transparent is to use the method setRegion on the control class to define the non-transparent portion of the control. + /// + internal interface IOverlayService + { + /// + /// Pushes the given control on top of the overlay list. This is a "push" operation, meaning that it forces this control to the top of the existing overlay list. + /// + int PushOverlay(Control control); + + /// + /// Removes the given control from the overlay list. Unlike pushOverlay, this can remove a control from the middle of the overlay list. + /// + void RemoveOverlay(Control control); + + /// + /// Inserts the given control from the overlay list. You need to pass the index of the overlay. + /// + void InsertOverlay(Control control, int index); + + /// + /// Invalidates the overlays + /// + void InvalidateOverlays(Rectangle screenRectangle); + + /// + /// Invalidates the overlays + /// + void InvalidateOverlays(Region screenRegion); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISelectionUIService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISelectionUIService.cs new file mode 100644 index 00000000000..a07bb34a64c --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISelectionUIService.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// The selection UI service is used to provide a standard user interface for selection across designers. Using this service is optional, but is recommended to provide a standard UI component selection. + /// + internal interface ISelectionUIService + { + /// + /// Determines if the selection UI is shown or not. + /// + bool Visible { get; set; } + + /// + /// Adds an event handler to the ContainerSelectorActive event. This event is fired whenever the user interacts with the container selector in a manor that would indicate that the selector should continued to be displayed. Since the container selector normally will vanish after a timeout, designers should listen to this event and reset the timeout when this event occurs. + /// + event ContainerSelectorActiveEventHandler ContainerSelectorActive; + + /// + /// Assigns a selection UI handler to a given component. The handler will be called when the UI service needs information about the component. A single selection UI handler can be assigned to multiple components. When multiple components are dragged, only a single handler may control the drag. Because of this, only components that are assigned the same handler as the primary selection are included in drag operations. A selection UI handler is automatically unassigned when the component is removed from the container or disposed. + /// + void AssignSelectionUIHandler(object component, ISelectionUIHandler handler); + + void ClearSelectionUIHandler(object component, ISelectionUIHandler handler); + + /// + /// This can be called by an outside party to begin a drag of the currently selected set of components. At least one designer must have added a UI handler or else this method will always return false. + /// + bool BeginDrag(SelectionRules rules, int initialX, int initialY); + + /// + /// This can be used to determine if the user is in the middle of a drag operation. + /// + bool Dragging { get; } + + /// + /// Called by an outside party to update drag information. This can only be called after a successful call to beginDrag. + /// + void DragMoved(Rectangle offset); + + /// + /// Called by an outside party to finish a drag operation. This can only be called after a successful call to beginDrag. + /// + void EndDrag(bool cancel); + + /// + /// Filters the set of selected components. The selection service will retrieve all components that are currently selected. This method allows you to filter this set down to components that match your criteria. The selectionRules parameter must contain one or more flags from the SelectionRules class. These flags allow you to constrain the set of selected objects to visible, movable, sizeable or all objects. + /// + object[] FilterSelection(object[] components, SelectionRules selectionRules); + + /// + /// Retrieves the width and height of a selection border grab handle. Designers may need this to properly position their user interfaces. + /// + Size GetAdornmentDimensions(AdornmentType adornmentType); + + /// + /// Tests to determine if the given screen coordinate is over an adornment for the specified component. This will only return true if the adornment, and selection UI, is visible. + /// + bool GetAdornmentHitTest(object component, Point pt); + + /// + /// Gets a value indicating whether the specified component is the currently selected container. + /// + bool GetContainerSelected(object component); + + /// + /// Retrieves a set of flags that define rules for the selection. Selection rules indicate if the given component can be moved or sized, for example. + /// + SelectionRules GetSelectionRules(object component); + + /// + /// Allows you to configure the style of the selection frame that a component uses. This is useful if your component supports different modes of operation (such as an in-place editing mode and a static design mode). Where possible, you should leave the selection style as is and use the design-time hit testing feature of the IDesigner interface to provide features at design time. The value of style must be one of the SelectionStyle enum values. The selection style is only valid for the duration that the component is selected. + /// + SelectionStyles GetSelectionStyle(object component); + + /// + /// Changes the container selection status of the specified component. + /// + void SetContainerSelected(object component, bool selected); + + /// + /// Allows you to configure the style of the selection frame that a component uses. This is useful if your component supports different modes of operation (such as an in-place editing mode and a static design mode). Where possible, you should leave the selection style as is and use the design-time hit testing feature of the IDesigner interface to provide features at design time. The value of style must be one of the SelectionStyle enum values. The selection style is only valid for the duration that the component is selected. + /// + void SetSelectionStyle(object component, SelectionStyles style); + + /// + /// This should be called when a component has been moved, sized or re-parented, but the change was not the result of a property change. All property changes are monitored by the selection UI service, so this is automatic most of the time. There are times, however, when a component may be moved without a property change notification occurring. Scrolling an auto scroll Win32 form is an example of this. This method simply re-queries all currently selected components for their bounds and udpates the selection handles for any that have changed. + /// + void SyncSelection(); + + /// + /// This should be called when a component's property changed, that the designer thinks should result in a selection UI change. This method simply re-queries all currently selected components for their bounds and udpates the selection handles for any that have changed. + /// + void SyncComponent(object component); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISplitWindowService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISplitWindowService.cs new file mode 100644 index 00000000000..5a072d29527 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISplitWindowService.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// Supports the hosting of several 'pane' windows separated by splitter bars. + /// + internal interface ISplitWindowService + { + /// + /// Requests the service to add a window 'pane'. + /// + void AddSplitWindow(Control window); + + /// + /// Requests the service to remove a window 'pane'. + /// + void RemoveSplitWindow(Control window); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISupportInSituService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISupportInSituService.cs new file mode 100644 index 00000000000..687f296de27 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ISupportInSituService.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// Provides an interface for a designer to support Insitu editing for selected components. + /// + [Runtime.InteropServices.ComVisible(true)] + internal interface ISupportInSituService + { + /// + /// Returns if the service is interested in InSitu Edit on Key Messages.. + /// + bool IgnoreMessages { get; } + + /// + /// This method allows the service to handle the first WM_CHAR message. The implementer for this service can perform any tasks that it wants when it gets this message. + /// e.g : ToolStripInSituService shows the Editor for each ToolStripItem in HandleKeyChar() + /// + void HandleKeyChar(); + + /// + /// Returns the Window Handle that gets all the Keyboarf messages once in InSitu. + /// + IntPtr GetEditWindow(); + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/InheritanceUI.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/InheritanceUI.cs new file mode 100644 index 00000000000..e1ccf59be38 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/InheritanceUI.cs @@ -0,0 +1,119 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// This class handles the user interface for inherited components. + /// + internal class InheritanceUI + { + private static Bitmap s_inheritanceGlyph; + private static Rectangle s_inheritanceGlyphRect; + private ToolTip _tooltip; + + /// + /// The bitmap we use to show inheritance. + /// + public Bitmap InheritanceGlyph + { + get + { + if (s_inheritanceGlyph == null) + { + s_inheritanceGlyph = new Bitmap(typeof(InheritanceUI), "InheritedGlyph.bmp"); + s_inheritanceGlyph.MakeTransparent(); + if (DpiHelper.IsScalingRequired) + { + DpiHelper.ScaleBitmapLogicalToDevice(ref s_inheritanceGlyph); + } + } + return s_inheritanceGlyph; + } + } + + /// + /// The rectangle surrounding the glyph. + /// + public Rectangle InheritanceGlyphRectangle + { + get + { + if (s_inheritanceGlyphRect == Rectangle.Empty) + { + Size size = InheritanceGlyph.Size; + s_inheritanceGlyphRect = new Rectangle(0, 0, size.Width, size.Height); + } + return s_inheritanceGlyphRect; + } + } + + /// + /// Adds an inherited control to our list. This creates a tool tip for that control. + /// + public void AddInheritedControl(Control c, InheritanceLevel level) + { + if (_tooltip == null) + { + _tooltip = new ToolTip + { + ShowAlways = true + }; + } + + Debug.Assert(level != InheritanceLevel.NotInherited, "This should only be called for inherited components."); + string text; + if (level == InheritanceLevel.InheritedReadOnly) + { + text = SR.DesignerInheritedReadOnly; + } + else + { + text = SR.DesignerInherited; + } + + _tooltip.SetToolTip(c, text); + + // Also, set all of its non-sited children + foreach (Control child in c.Controls) + { + if (child.Site == null) + { + _tooltip.SetToolTip(child, text); + } + } + } + + public void Dispose() + { + if (_tooltip != null) + { + _tooltip.Dispose(); + } + } + + /// + /// Removes a previously added inherited control. + /// + public void RemoveInheritedControl(Control c) + { + if (_tooltip != null && _tooltip.GetToolTip(c).Length > 0) + { + _tooltip.SetToolTip(c, null); + // Also, set all of its non-sited children + foreach (Control child in c.Controls) + { + if (child.Site == null) + { + _tooltip.SetToolTip(child, null); + } + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ItemTypeToolStripMenuItem.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ItemTypeToolStripMenuItem.cs new file mode 100644 index 00000000000..46bc91ee3f0 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ItemTypeToolStripMenuItem.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Drawing.Design; + +namespace System.Windows.Forms.Design +{ + /// + /// Associates Type with ToolStripMenuItem. + /// + internal class ItemTypeToolStripMenuItem : ToolStripMenuItem + { + private static readonly string s_systemWindowsFormsNamespace = typeof(ToolStripItem).Namespace; + private static readonly ToolboxItem s_invalidToolboxItem = new ToolboxItem(); + private readonly Type _itemType; + private bool _convertTo = false; + private ToolboxItem _tbxItem = s_invalidToolboxItem; + private Image _image = null; + + public ItemTypeToolStripMenuItem(Type t) => _itemType = t; + + public static string SystemWindowsFormsNamespace => s_systemWindowsFormsNamespace; + + public Type ItemType + { + get => _itemType; + } + + public bool ConvertTo + { + get => _convertTo; + set => _convertTo = value; + } + + public override Image Image + { + get + { + if (_image == null) + { + _image = ToolStripDesignerUtils.GetToolboxBitmap(ItemType); + } + return _image; + } + set + { + } + } + + public override string Text + { + get => ToolStripDesignerUtils.GetToolboxDescription(ItemType); + set + { + } + } + + public ToolboxItem TbxItem { get => _tbxItem; set => _tbxItem = value; } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + TbxItem = null; + } + base.Dispose(disposing); + } + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs index 42667652b5a..cb14f082788 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs @@ -7,27 +7,20 @@ namespace System.Windows.Forms.Design { /// - /// - /// This class contains command ID's and GUIDS that - /// correspond - /// to the host Command Bar menu layout. - /// + /// This class contains command ID's and GUIDS that correspond to the host Command Bar menu layout. /// public sealed class MenuCommands : StandardCommands { // Windows Forms specific popup menus - // private const int mnuidSelection = 0x0500; private const int mnuidContainer = 0x0501; private const int mnuidTraySelection = 0x0503; private const int mnuidComponentTray = 0x0506; // Windows Forms specific menu items - // private const int cmdidDesignerProperties = 0x1001; // Windows Forms specific keyboard commands - // private const int cmdidReverseCancel = 0x4001; private const int cmdidSetStatusText = 0x4003; private const int cmdidSetStatusRectangle = 0x4004; @@ -65,26 +58,26 @@ public sealed class MenuCommands : StandardCommands private const int ECMD_END_EXT = 18; /// - /// This guid corresponds to the standard set of commands for the shell and office. - /// This new giud is added so that the ToolStripDesigner now respond to the F2 command - /// and go into InSitu Edit mode. + /// This guid corresponds to the standard set of commands for the shell and office. + /// This new giud is added so that the ToolStripDesigner now respond to the F2 command + /// and go into InSitu Edit mode. /// private static readonly Guid VSStandardCommandSet97 = new Guid("{5efc7975-14bc-11cf-9b2b-00aa00573819}"); /// - /// This guid corresponds to the menu grouping Windows Forms will use for its menus. This is - /// defined in the Windows Forms menu CTC file, but we need it here so we can define what - /// context menus to use. + /// This guid corresponds to the menu grouping Windows Forms will use for its menus. This is + /// defined in the Windows Forms menu CTC file, but we need it here so we can define what + /// context menus to use. /// private static readonly Guid wfMenuGroup = new Guid("{74D21312-2AEE-11d1-8BFB-00A0C90F26F7}"); /// - /// This guid corresponds to the Windows Forms command set. + /// This guid corresponds to the Windows Forms command set. /// private static readonly Guid wfCommandSet = new Guid("{74D21313-2AEE-11d1-8BFB-00A0C90F26F7}"); /// - /// This guid is the standard vs 2k commands for key bindings + /// This guid is the standard vs 2k commands for key bindings /// private static readonly Guid guidVSStd2K = new Guid("{1496A755-94DE-11D0-8C3F-00C04FC2AAE2}"); @@ -97,11 +90,9 @@ public sealed class MenuCommands : StandardCommands public static readonly CommandID ComponentTrayMenu = new CommandID(wfMenuGroup, mnuidComponentTray); // Windows Forms commands - public static readonly CommandID DesignerProperties = new CommandID(wfCommandSet, cmdidDesignerProperties); - // Windows Forms Key commands - + // Windows Forms Key commands public static readonly CommandID KeyCancel = new CommandID(guidVSStd2K, ECMD_CANCEL); public static readonly CommandID KeyReverseCancel = new CommandID(wfCommandSet, cmdidReverseCancel); diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/NewItemsContextMenuStrip.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/NewItemsContextMenuStrip.cs new file mode 100644 index 00000000000..7a16472c30d --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/NewItemsContextMenuStrip.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; + +namespace System.Windows.Forms.Design +{ + internal class NewItemsContextMenuStrip : GroupedContextMenuStrip + { + private readonly IComponent _component = null; + private readonly EventHandler _onClick = null; + private readonly bool _convertTo = false; + private readonly IServiceProvider _serviceProvider = null; + private readonly ToolStripItem _currentItem; + + public NewItemsContextMenuStrip(IComponent component, ToolStripItem currentItem, EventHandler onClick, bool convertTo, IServiceProvider serviceProvider) + { + _component = component; + _onClick = onClick; + _convertTo = convertTo; + _serviceProvider = serviceProvider; + _currentItem = currentItem; + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]; + } + } + protected override void OnOpening(CancelEventArgs e) + { + Groups["StandardList"].Items.Clear(); + Groups["CustomList"].Items.Clear(); + Populated = false; + + // plumb through the standard and custom items. + foreach (ToolStripItem item in ToolStripDesignerUtils.GetStandardItemMenuItems(_component, _onClick, _convertTo)) + { + Groups["StandardList"].Items.Add(item); + if (_convertTo) + { + if (item is ItemTypeToolStripMenuItem toolItem && _currentItem != null && toolItem.ItemType == _currentItem.GetType()) + { + toolItem.Enabled = false; + } + } + + } + foreach (ToolStripItem item in ToolStripDesignerUtils.GetCustomItemMenuItems(_component, _onClick, _convertTo, _serviceProvider)) + { + Groups["CustomList"].Items.Add(item); + if (_convertTo) + { + if (item is ItemTypeToolStripMenuItem toolItem && _currentItem != null && toolItem.ItemType == _currentItem.GetType()) + { + toolItem.Enabled = false; + } + } + } + base.OnOpening(e); + } + + // We dont want the runtime behavior for this Design Time only DropDown and hence we overide the ProcessDialogKey and just close the DropDown instead of running through the runtime implementation for RIGHT/LEFT Keys which ends up setting ModalMenuFilter. + protected override bool ProcessDialogKey(Keys keyData) + { + Keys keyCode = (Keys)keyData & Keys.KeyCode; + switch (keyCode) + { + case Keys.Left: + case Keys.Right: + Close(); + return true; + } + return base.ProcessDialogKey(keyData); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/ComboBoxTests.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/NoBorderRenderer.cs similarity index 53% rename from src/System.Windows.Forms/tests/UnitTests/ComboBoxTests.cs rename to src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/NoBorderRenderer.cs index 7649a44b55e..a0bba770d6e 100644 --- a/src/System.Windows.Forms/tests/UnitTests/ComboBoxTests.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/NoBorderRenderer.cs @@ -2,18 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Xunit; - -namespace System.Windows.Forms.Tests +namespace System.Windows.Forms.Design { - public class ComboBoxTests + internal class NoBorderRenderer : ToolStripProfessionalRenderer { - [Fact] - public void ComboBox_Constructor() + protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - var box = new ComboBox(); - - Assert.NotNull(box); } } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ParentControlDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ParentControlDesigner.cs index f26fa746e54..55c676db641 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ParentControlDesigner.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ParentControlDesigner.cs @@ -4,6 +4,8 @@ using System.Collections; using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Drawing.Design; @@ -18,6 +20,14 @@ namespace System.Windows.Forms.Design /// public class ParentControlDesigner : ControlDesigner, IOleDragClient { + private Control pendingRemoveControl; // we've gotten an OnComponentRemoving, and are waiting for OnComponentRemove + + private OleDragDropHandler oleDragDropHandler; // handler for ole drag drop operations + private IComponentChangeService componentChangeSvc; + private StatusCommandUI statusCommandUI; // UI for setting the StatusBar Information.. + + private int suspendChanging = 0; + /// /// This is called after the user selects a toolbox item (that has a ParentControlDesigner /// associated with it) and draws a reversible rectangle on a designer's surface. If @@ -92,6 +102,256 @@ protected Size GridSize /// public override IList SnapLines => throw new NotImplementedException(SR.NotImplementedByDesign); + internal Size ParentGridSize + { + get => GridSize; + } + + internal OleDragDropHandler GetOleDragHandler() + { + if (oleDragDropHandler == null) + { + oleDragDropHandler = new OleDragDropHandler(null, (IServiceProvider)GetService(typeof(IDesignerHost)), this); + } + return oleDragDropHandler; + } + + internal void AddControl(Control newChild, IDictionary defaultValues) + { + Point location = Point.Empty; + Size size = Size.Empty; + Size offset = new Size(0, 0); + bool hasLocation = (defaultValues != null && defaultValues.Contains("Location")); + bool hasSize = (defaultValues != null && defaultValues.Contains("Size")); + + if (hasLocation) + location = (Point)defaultValues["Location"]; + if (hasSize) + size = (Size)defaultValues["Size"]; + if (defaultValues != null && defaultValues.Contains("Offset")) + { + offset = (Size)defaultValues["Offset"]; + } + + // If this component doesn't have a control designer, or if this control is top level, then ignore it. We have the reverse logic in OnComponentAdded in the document designer so that we will add those guys to the tray. Also, if the child-control has already been parented, we assume it's also been located and return immediately. Otherwise, proceed with the parenting and locating. + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null && newChild != null && !Control.Contains(newChild) && (host.GetDesigner(newChild) as ControlDesigner) != null && !(newChild is Form && ((Form)newChild).TopLevel)) + { + Rectangle bounds = new Rectangle(); + // If we were provided with a location, convert it to parent control coordinates. Otherwise, get the control's size and put the location in the middle of it + if (hasLocation) + { + location = Control.PointToClient(location); + bounds.X = location.X; + bounds.Y = location.Y; + } + else + { + // is the currently selected control this container? + ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + object primarySelection = selSvc.PrimarySelection; + Control selectedControl = null; + if (primarySelection != null) + { + selectedControl = ((IOleDragClient)this).GetControlForComponent(primarySelection); + } + + // If the resulting control that came back isn't sited, it's not part of the design surface and should not be used as a marker. + if (selectedControl != null && selectedControl.Site == null) + { + selectedControl = null; + } + + // if the currently selected container is this parent control, default to 0,0 + if (primarySelection == Component || selectedControl == null) + { + bounds.X = DefaultControlLocation.X; + bounds.Y = DefaultControlLocation.Y; + } + else + { + // otherwise offset from selected control. + bounds.X = selectedControl.Location.X + GridSize.Width; + bounds.Y = selectedControl.Location.Y + GridSize.Height; + } + + } + // If we were not given a size, ask the control for its default. We also update the location here so the control is in the middle of the user's point, rather than at the edge. + if (hasSize) + { + bounds.Width = size.Width; + bounds.Height = size.Height; + } + else + { + bounds.Size = GetDefaultSize(newChild); + } + + // If we were given neither, center the control + if (!hasSize && !hasLocation) + { + // get the adjusted location, then inflate the rect so we can find a nice spot for this control to live. + Rectangle tempBounds = GetAdjustedSnapLocation(Rectangle.Empty, bounds); + // compute the stacking location + tempBounds = GetControlStackLocation(tempBounds); + bounds = tempBounds; + } + else + { + // Finally, convert the bounds to the appropriate grid snaps + bounds = GetAdjustedSnapLocation(Rectangle.Empty, bounds); + } + + // Adjust for the offset, if any + bounds.X += offset.Width; + bounds.Y += offset.Height; + // check to see if we have additional information for bounds from the behaviorservice dragdrop logic + if (defaultValues != null && defaultValues.Contains("ToolboxSnapDragDropEventArgs")) + { + ToolboxSnapDragDropEventArgs e = defaultValues["ToolboxSnapDragDropEventArgs"] as ToolboxSnapDragDropEventArgs; + Debug.Assert(e != null, "Why can't we get a ToolboxSnapDragDropEventArgs object out of our default values?"); + Rectangle snappedBounds = DesignerUtils.GetBoundsFromToolboxSnapDragDropInfo(e, bounds, Control.IsMirrored); + //Make sure the snapped bounds intersects with the bounds of the root control before we go adjusting the drag offset. A race condition exists where the user can drag a tbx item so fast that the adorner window will never receive the proper drag/mouse move messages and never properly adjust the snap drag info. This cause the control to be added @ 0,0 w.r.t. the adorner window. + if (host.RootComponent is Control rootControl && snappedBounds.IntersectsWith(rootControl.ClientRectangle)) + { + bounds = snappedBounds; + } + } + // Parent the control to the designer and set it to the front. + PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(Control)["Controls"]; + if (componentChangeSvc != null) + { + componentChangeSvc.OnComponentChanging(Control, controlsProp); + } + AddChildControl(newChild); + // Now see if the control has size and location properties. Update these values if it does. + PropertyDescriptorCollection props = TypeDescriptor.GetProperties(newChild); + if (props != null) + { + PropertyDescriptor prop = props["Size"]; + if (prop != null) + { + prop.SetValue(newChild, new Size(bounds.Width, bounds.Height)); + } + + // ControlDesigner shadows the Location property. If the control is parented and the parent is a scrollable control, then it expects the Location to be in displayrectangle coordinates. At this point bounds are in clientrectangle coordinates, so we need to check if we need to adjust the coordinates. The reason this worked in Everett was that the AddChildControl was done AFTER this. The AddChildControl was moved above a while back. Not sure what will break if AddChildControl is moved down below, so let's just fix up things here. + Point pt = new Point(bounds.X, bounds.Y); + if (newChild.Parent is ScrollableControl p) + { + Point ptScroll = p.AutoScrollPosition; + pt.Offset(-ptScroll.X, -ptScroll.Y); //always want to add the control below/right of the AutoScrollPosition + } + + prop = props["Location"]; + if (prop != null) + { + prop.SetValue(newChild, pt); + } + } + + if (componentChangeSvc != null) + { + componentChangeSvc.OnComponentChanged(Control, controlsProp, Control.Controls, Control.Controls); + } + newChild.Update(); + } + } + + internal virtual void AddChildControl(Control newChild) + { + if (newChild.Left == 0 && newChild.Top == 0 && newChild.Width >= Control.Width && newChild.Height >= Control.Height) + { + // bump the control down one gridsize just so it's selectable... + Point loc = newChild.Location; + loc.Offset(GridSize.Width, GridSize.Height); + newChild.Location = loc; + } + Control.Controls.Add(newChild); + Control.Controls.SetChildIndex(newChild, 0); + } + + private Rectangle GetControlStackLocation(Rectangle centeredLocation) + { + Control parent = Control; + int parentHeight = parent.ClientSize.Height; + int parentWidth = parent.ClientSize.Width; + if (centeredLocation.Bottom >= parentHeight || centeredLocation.Right >= parentWidth) + { + centeredLocation.X = DefaultControlLocation.X; + centeredLocation.Y = DefaultControlLocation.Y; + } + return centeredLocation; + } + + [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] + private Size GetDefaultSize(IComponent component) + { + //Check to see if the control is AutoSized. VSWhidbey #416721 + PropertyDescriptor prop = TypeDescriptor.GetProperties(component)["AutoSize"]; + Size size; + if (prop != null && + !(prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden) || + prop.Attributes.Contains(BrowsableAttribute.No))) + { + bool autoSize = (bool)prop.GetValue(component); + if (autoSize) + { + prop = TypeDescriptor.GetProperties(component)["PreferredSize"]; + if (prop != null) + { + size = (Size)prop.GetValue(component); + if (size != Size.Empty) + { + return size; + } + } + } + } + + // attempt to get the size property of our component + prop = TypeDescriptor.GetProperties(component)["Size"]; + if (prop != null) + { + // first, let's see if we can get a valid size... + size = (Size)prop.GetValue(component); + // ...if not, we'll see if there's a default size attribute... + if (size.Width <= 0 || size.Height <= 0) + { + DefaultValueAttribute sizeAttr = (DefaultValueAttribute)prop.Attributes[typeof(DefaultValueAttribute)]; + if (sizeAttr != null) + { + return ((Size)sizeAttr.Value); + } + } + else + { + return size; + } + } + // Couldn't get the size or a def size attrib, returning 75,23... + return (new Size(75, 23)); + } + + private Rectangle GetAdjustedSnapLocation(Rectangle originalRect, Rectangle dragRect) + { + Rectangle adjustedRect = GetUpdatedRect(originalRect, dragRect, true); + //now, preserve the width and height that was originally passed in + adjustedRect.Width = dragRect.Width; + adjustedRect.Height = dragRect.Height; + // we need to keep in mind that if we adjust to the snap, that we could have possibly moved the control's position outside of the display rect. ex: groupbox's display rect.x = 3, but we might snap to 0. so we need to check with the control's designer to make sure this doesn't happen + Point minimumLocation = DefaultControlLocation; + if (adjustedRect.X < minimumLocation.X) + { + adjustedRect.X = minimumLocation.X; + } + if (adjustedRect.Y < minimumLocation.Y) + { + adjustedRect.Y = minimumLocation.Y; + } + // here's our rect that has been snapped to grid + return adjustedRect; + } + bool IOleDragClient.CanModifyComponents => throw new NotImplementedException(); bool IOleDragClient.AddComponent(IComponent component, string name, bool firstAdd) @@ -246,6 +506,12 @@ public override GlyphCollection GetGlyphs(GlyphSelectionType selectionType) throw new NotImplementedException(SR.NotImplementedByDesign); } + internal Point GetSnappedPoint(Point pt) + { + Rectangle r = GetUpdatedRect(Rectangle.Empty, new Rectangle(pt.X, pt.Y, 0, 0), false); + return new Point(r.X, r.Y); + } + /// /// Updates the given rectangle, adjusting it for grid snaps as /// needed. @@ -261,7 +527,58 @@ protected Rectangle GetUpdatedRect(Rectangle originalRect, Rectangle dragRect, b /// public override void Initialize(IComponent component) { - throw new NotImplementedException(SR.NotImplementedByDesign); + base.Initialize(component); + if (Control is ScrollableControl) + { + ((ScrollableControl)Control).Scroll += new ScrollEventHandler(OnScroll); + } + EnableDragDrop(true); + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + componentChangeSvc = (IComponentChangeService)host.GetService(typeof(IComponentChangeService)); + } + // update the Status Command + statusCommandUI = new StatusCommandUI(component.Site); + } + + private void OnComponentRemoved(object sender, ComponentEventArgs e) + { + if (e.Component == pendingRemoveControl) + { + pendingRemoveControl = null; + componentChangeSvc.OnComponentChanged(Control, TypeDescriptor.GetProperties(Control)["Controls"], null, null); + } + } + + private void OnComponentRemoving(object sender, ComponentEventArgs e) + { + if (e.Component is Control comp && comp.Parent != null && comp.Parent == Control) + { + pendingRemoveControl = (Control)comp; + //We suspend Component Changing Events for bulk operations to avoid unnecessary serialization\deserialization for undo + if (suspendChanging == 0) + { + componentChangeSvc.OnComponentChanging(Control, TypeDescriptor.GetProperties(Control)["Controls"]); + } + } + } + + internal void SuspendChangingEvents() + { + suspendChanging++; + Debug.Assert(suspendChanging > 0, "Unbalanced SuspendChangingEvents\\ResumeChangingEvents"); + } + + internal void ForceComponentChanging() + { + componentChangeSvc.OnComponentChanging(Control, TypeDescriptor.GetProperties(Control)["Controls"]); + } + + internal void ResumeChangingEvents() + { + suspendChanging--; + Debug.Assert(suspendChanging >= 0, "Unbalanced SuspendChangingEvents\\ResumeChangingEvents"); } /// diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionManager.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionManager.cs new file mode 100644 index 00000000000..3b665359cbf --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionManager.cs @@ -0,0 +1,453 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Drawing; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// The SelectionBehavior is pushed onto the BehaviorStack in response to apositively hit tested SelectionGlyph. The SelectionBehavior performs two main tasks: 1) forward messages to the related ControlDesigner, and 2) calls upon the SelectionManager to push a potention DragBehavior. + /// + internal sealed class SelectionManager : IDisposable + { + private Adorner _selectionAdorner;//used to provide all selection glyphs + private Adorner _bodyAdorner;//used to track all body glyphs for each control + private BehaviorService _behaviorService;//ptr back to our BehaviorService + private IServiceProvider _serviceProvider;//standard service provider + private readonly Hashtable _componentToDesigner;//used for quick look up of designers related to comps + private readonly Control _rootComponent;//root component being designed + private ISelectionService _selSvc;//we cache the selection service for perf. + private IDesignerHost _designerHost;//we cache the designerhost for perf. + private bool _needRefresh; // do we need to refresh? + private Rectangle[] _prevSelectionBounds;//used to only repaint the changing part of the selection + private object _prevPrimarySelection; //used to check if the primary selection changed + private Rectangle[] _curSelectionBounds; + private int _curCompIndex; + private DesignerActionUI _designerActionUI = null; // the "container" for all things related to the designer action (smartags) UI + private bool _selectionChanging; //we dont want the OnSelectionChanged to be recursively called. + + /// + /// Constructor. Here we query for necessary services and cache them for perf. reasons. We also hook to Component Added/Removed/Changed notifications so we can keep in sync when the designers' components change. Also, we create our custom Adorner and add it to the BehaviorService. + /// + public SelectionManager(IServiceProvider serviceProvider, BehaviorService behaviorService) + { + _prevSelectionBounds = null; + _prevPrimarySelection = null; + _behaviorService = behaviorService; + _serviceProvider = serviceProvider; + _selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + _designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + if (_designerHost == null || _selSvc == null) + { + Debug.Fail("SelectionManager - Host or SelSvc is null, can't continue"); + } + + _rootComponent = (Control)_designerHost.RootComponent; + //create and add both of our adorners, one for selection, one for bodies + _selectionAdorner = new Adorner(); + _bodyAdorner = new Adorner(); + behaviorService.Adorners.Add(_bodyAdorner); + behaviorService.Adorners.Add(_selectionAdorner);//adding this will cause the adorner to get setup with a ptr to the beh.svc. + _componentToDesigner = new Hashtable(); + // designeraction UI + if (_designerHost.GetService(typeof(DesignerOptionService)) is DesignerOptionService options) + { + PropertyDescriptor p = options.Options.Properties["UseSmartTags"]; + if (p != null && p.PropertyType == typeof(bool) && (bool)p.GetValue(null)) + { + _designerActionUI = new DesignerActionUI(serviceProvider, _selectionAdorner); + behaviorService.DesignerActionUI = _designerActionUI; + } + } + } + + /// + /// Returns the Adorner that contains all the BodyGlyphs for the current selection state. + /// + internal Adorner BodyGlyphAdorner + { + get => _bodyAdorner; + } + + /// + /// There are certain cases like Adding Item to ToolStrips through InSitu Editor, where there is ParentTransaction that has to be cancelled depending upon the user action. When this parent transaction is cancelled, there may be no reason to REFRESH the selectionManager which actually clears all the glyphs and readds them. This REFRESH causes a lot of flicker and can be avoided by setting this property to false. Since this property is checked in the TransactionClosed, the SelectionManager won't REFRESH and hence just eat up the refresh thus avoiding unnecessary flicker. + /// + internal bool NeedRefresh + { + get => _needRefresh; + set => _needRefresh = value; + } + + /// + /// Returns the Adorner that contains all the BodyGlyphs for the current selection state. + /// + internal Adorner SelectionGlyphAdorner + { + get => _selectionAdorner; + } + + /// + /// This method fist calls the recursive AddControlGlyphs() method. When finished, we add the final glyph(s) to the root comp. + /// + private void AddAllControlGlyphs(Control parent, ArrayList selComps, object primarySelection) + { + foreach (Control control in parent.Controls) + { + AddAllControlGlyphs(control, selComps, primarySelection); + } + + GlyphSelectionType selType = GlyphSelectionType.NotSelected; + if (selComps.Contains(parent)) + { + if (parent.Equals(primarySelection)) + { + selType = GlyphSelectionType.SelectedPrimary; + } + else + { + selType = GlyphSelectionType.Selected; + } + } + AddControlGlyphs(parent, selType); + } + + /// + /// Recursive method that goes through and adds all the glyphs of every child to our global Adorner. + /// + private void AddControlGlyphs(Control c, GlyphSelectionType selType) + { + + ControlDesigner cd = (ControlDesigner)_componentToDesigner[c]; + if (cd != null) + { + ControlBodyGlyph bodyGlyph = cd.GetControlGlyphInternal(selType); + if (bodyGlyph != null) + { + _bodyAdorner.Glyphs.Add(bodyGlyph); + if (selType == GlyphSelectionType.SelectedPrimary || + selType == GlyphSelectionType.Selected) + { + + if (_curSelectionBounds[_curCompIndex] == Rectangle.Empty) + { + _curSelectionBounds[_curCompIndex] = bodyGlyph.Bounds; + } + else + { + _curSelectionBounds[_curCompIndex] = Rectangle.Union(_curSelectionBounds[_curCompIndex], bodyGlyph.Bounds); + } + } + } + GlyphCollection glyphs = cd.GetGlyphs(selType); + if (glyphs != null) + { + _selectionAdorner.Glyphs.AddRange(glyphs); + if (selType == GlyphSelectionType.SelectedPrimary || + selType == GlyphSelectionType.Selected) + { + foreach (Glyph glyph in glyphs) + { + _curSelectionBounds[_curCompIndex] = Rectangle.Union(_curSelectionBounds[_curCompIndex], glyph.Bounds); + } + } + } + } + + if (selType == GlyphSelectionType.SelectedPrimary || selType == GlyphSelectionType.Selected) + { + _curCompIndex++; + } + } + + /// + /// Unhook all of our event notifications, clear our adorner and remove it from the Beh.Svc. + /// + // We don't need to Dispose rootComponent. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public void Dispose() + { + if (_designerHost != null) + { + _designerHost = null; + } + if (_serviceProvider != null) + { + if (_selSvc != null) + { + _selSvc = null; + } + _serviceProvider = null; + } + if (_behaviorService != null) + { + _behaviorService.Adorners.Remove(_bodyAdorner); + _behaviorService.Adorners.Remove(_selectionAdorner); + _behaviorService = null; + } + if (_selectionAdorner != null) + { + _selectionAdorner.Glyphs.Clear(); + _selectionAdorner = null; + } + if (_bodyAdorner != null) + { + _bodyAdorner.Glyphs.Clear(); + _bodyAdorner = null; + } + if (_designerActionUI != null) + { + _designerActionUI.Dispose(); + _designerActionUI = null; + } + } + + /// + /// Refreshes all selection Glyphs. + /// + public void Refresh() + { + NeedRefresh = false; + OnSelectionChanged(this, null); + } + + /// + /// When a component is added, we get the designer and add it to our hashtable for quick lookup. + /// + private void OnComponentAdded(object source, ComponentEventArgs ce) + { + IComponent component = ce.Component; + IDesigner designer = _designerHost.GetDesigner(component); + if (designer is ControlDesigner) + { + _componentToDesigner.Add(component, designer); + } + } + + /// + /// Before a drag, remove all glyphs that are involved in the drag operation and any that don't allow drops. + /// + private void OnBeginDrag(object source, BehaviorDragDropEventArgs e) + { + ArrayList dragComps = new ArrayList(e.DragComponents); + ArrayList glyphsToRemove = new ArrayList(); + foreach (ControlBodyGlyph g in _bodyAdorner.Glyphs) + { + if (g.RelatedComponent is Control) + { + if (dragComps.Contains(g.RelatedComponent) || + !((Control)g.RelatedComponent).AllowDrop) + { + glyphsToRemove.Add(g); + } + } + } + foreach (Glyph g in glyphsToRemove) + { + _bodyAdorner.Glyphs.Remove(g); + } + } + + // Called by the DropSourceBehavior when dragging into a new host + internal void OnBeginDrag(BehaviorDragDropEventArgs e) + { + OnBeginDrag(null, e); + } + + /// + /// When a component is changed - we need to refresh the selection. + /// + private void OnComponentChanged(object source, ComponentChangedEventArgs ce) + { + if (_selSvc.GetComponentSelected(ce.Component)) + { + if (!_designerHost.InTransaction) + { + Refresh(); + } + else + { + NeedRefresh = true; + } + } + } + + /// + /// When a component is removed - we remove the key & value from our hashtable. + /// + private void OnComponentRemoved(object source, ComponentEventArgs ce) + { + if (_componentToDesigner.Contains(ce.Component)) + { + _componentToDesigner.Remove(ce.Component); + } + //remove the associated designeractionpanel + if (_designerActionUI != null) + { + _designerActionUI.RemoveActionGlyph(ce.Component); + } + } + /// + /// Computes the region representing the difference between the old selection and the new selection. + /// + private Region DetermineRegionToRefresh(object primarySelection) + { + Region toRefresh = new Region(Rectangle.Empty); + Rectangle[] larger; + Rectangle[] smaller; + if (_curSelectionBounds.Length >= _prevSelectionBounds.Length) + { + larger = _curSelectionBounds; + smaller = _prevSelectionBounds; + } + else + { + larger = _prevSelectionBounds; + smaller = _curSelectionBounds; + } + + // we need to make sure all of the rects in the smaller array are accounted for. Any that don't intersect a rect in the larger array need to be included in the region to repaint. + bool[] intersected = new bool[smaller.Length]; + for (int i = 0; i < smaller.Length; i++) + { + intersected[i] = false; + } + + // determine which rects in the larger array need to be included in the region to invalidate by intersecting with rects in the smaller array. + for (int l = 0; l < larger.Length; l++) + { + bool largeIntersected = false; + Rectangle large = larger[l]; + for (int s = 0; s < smaller.Length; s++) + { + if (large.IntersectsWith(smaller[s])) + { + Rectangle small = smaller[s]; + largeIntersected = true; + if (large != small) + { + toRefresh.Union(large); + toRefresh.Union(small); + } + intersected[s] = true; + break; + } + } + if (!largeIntersected) + { + toRefresh.Union(large); + } + } + + // now add any rects from the smaller array that weren't accounted for + for (int k = 0; k < intersected.Length; k++) + { + if (!intersected[k]) + { + toRefresh.Union(smaller[k]); + } + } + + using (Graphics g = _behaviorService.AdornerWindowGraphics) + { + //If all that changed was the primary selection, then the refresh region was empty, but we do need to update the 2 controls. VSWhidbey #269806 + if (toRefresh.IsEmpty(g) && primarySelection != null && !primarySelection.Equals(_prevPrimarySelection)) + { + for (int i = 0; i < _curSelectionBounds.Length; i++) + { + toRefresh.Union(_curSelectionBounds[i]); + } + } + } + return toRefresh; + } + + /// + /// Event handler for the behaviorService's Synchronize event + /// + private void OnSynchronize(object sender, EventArgs e) + { + Refresh(); + } + + /// + /// On every selectionchange, we remove all glyphs, get the newly selected components, and re-add all glyphs back to the Adorner. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + // Note: selectionChanging would guard against a re-entrant code... Since we dont want to be in messed up state when adding new Glyphs. + if (!_selectionChanging) + { + _selectionChanging = true; + _selectionAdorner.Glyphs.Clear(); + _bodyAdorner.Glyphs.Clear(); + ArrayList selComps = new ArrayList(_selSvc.GetSelectedComponents()); + object primarySelection = _selSvc.PrimarySelection; + + //add all control glyphs to all controls on rootComp + _curCompIndex = 0; + _curSelectionBounds = new Rectangle[selComps.Count]; + AddAllControlGlyphs(_rootComponent, selComps, primarySelection); + if (_prevSelectionBounds != null) + { + Region toUpdate = DetermineRegionToRefresh(primarySelection); + using (Graphics g = _behaviorService.AdornerWindowGraphics) + { + if (!toUpdate.IsEmpty(g)) + { + _selectionAdorner.Invalidate(toUpdate); + } + } + } + else + { + // There was no previous selection, so just invalidate the current selection + if (_curSelectionBounds.Length > 0) + { + Rectangle toUpdate = _curSelectionBounds[0]; + for (int i = 1; i < _curSelectionBounds.Length; i++) + { + toUpdate = Rectangle.Union(toUpdate, _curSelectionBounds[i]); + } + if (toUpdate != Rectangle.Empty) + { + _selectionAdorner.Invalidate(toUpdate); + } + } + else + { + _selectionAdorner.Invalidate(); + } + } + + _prevPrimarySelection = primarySelection; + if (_curSelectionBounds.Length > 0) + { + _prevSelectionBounds = new Rectangle[_curSelectionBounds.Length]; + Array.Copy(_curSelectionBounds, _prevSelectionBounds, _curSelectionBounds.Length); + } + else + { + _prevSelectionBounds = null; + } + _selectionChanging = false; + } + } + + /// + /// When a transaction that involves one of our components closes, refresh to reflect any changes. + /// + private void OnTransactionClosed(object sender, DesignerTransactionCloseEventArgs e) + { + if (e.LastTransaction && NeedRefresh) + { + Refresh(); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionRules.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionRules.cs index 1e7529dc601..c3b904b41ff 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionRules.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionRules.cs @@ -7,10 +7,7 @@ namespace System.Windows.Forms.Design { /// - /// - /// Specifies a set of selection rule identifiers that - /// can be used to indicate attributes for a selected component. - /// + /// Specifies a set of selection rule identifiers that can be used to indicate attributes for a selected component. /// // We need to combine the SelectionRules. [SuppressMessage("Microsoft.Usage", "CA2217:DoNotMarkEnumsWithFlags")] @@ -18,92 +15,47 @@ namespace System.Windows.Forms.Design public enum SelectionRules { /// - /// - /// Indicates - /// no special selection attributes. - /// + /// Indicates no special selection attributes. /// None = 0x00000000, /// - /// - /// Indicates - /// the given component supports a location - /// property that allows it to be moved on the screen, and - /// that the selection service is not currently locked. - /// + /// Indicates the given component supports a location property that allows it to be moved on the screen, and that the selection service is not currently locked. /// Moveable = 0x10000000, /// - /// - /// Indicates - /// the given component has some form of visible user - /// interface and the selection service is drawing a selection border around - /// this user interface. If a selected component has this rule set, you can assume - /// that the component implements - /// and that it - /// is associated with a corresponding design instance. - /// + /// Indicates the given component has some form of visible user interface and the selection service is drawing a selection border around this user interface. If a selected component has this rule set, you can assume that the component implements and that it is associated with a corresponding design instance. /// Visible = 0x40000000, /// - /// - /// Indicates - /// the given component is locked to - /// its container. Overrides the moveable and sizeable - /// properties of this enum. - /// + /// Indicates the given component is locked to its container. Overrides the moveable and sizeable properties of this enum. /// Locked = unchecked((int)0x80000000), /// - /// - /// Indicates - /// the given component supports resize from - /// the top. This bit will be ignored unless the Sizeable - /// bit is also set. - /// + /// Indicates the given component supports resize from the top. This bit will be ignored unless the Sizeable bit is also set. /// TopSizeable = 0x00000001, /// - /// - /// Indicates - /// the given component supports resize from - /// the bottom. This bit will be ignored unless the Sizeable - /// bit is also set. - /// + /// Indicates the given component supports resize from the bottom. This bit will be ignored unless the Sizeable bit is also set. /// BottomSizeable = 0x00000002, /// - /// - /// Indicates - /// the given component supports resize from - /// the left. This bit will be ignored unless the Sizeable - /// bit is also set. - /// + /// Indicates the given component supports resize from the left. This bit will be ignored unless the Sizeable bit is also set. /// LeftSizeable = 0x00000004, /// - /// - /// Indicates - /// the given component supports resize from - /// the right. This bit will be ignored unless the Sizeable - /// bit is also set. - /// + /// Indicates the given component supports resize from the right. This bit will be ignored unless the Sizeable bit is also set. /// RightSizeable = 0x00000008, /// - /// - /// Indicates - /// the given component supports sizing - /// in all directions, and the selection service is not currently locked. - /// + /// Indicates the given component supports sizing in all directions, and the selection service is not currently locked. /// AllSizeable = TopSizeable | BottomSizeable | LeftSizeable | RightSizeable } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionStyles.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionStyles.cs new file mode 100644 index 00000000000..03d66484741 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionStyles.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + /// + /// Specifies identifiers to use to indicate the style of the selection frame of a component. + /// + [Flags] + internal enum SelectionStyles + { + /// + /// The component is not currently selected. + /// + None = 0, + /// + /// A component is selected and may be dragged around + /// + Selected = 0x01, + /// + /// An alternative selection border, indicating that a component is in active editing mode and that clicking and dragging on the component affects the component itself, not its position in the designer. + /// + Active = 0x02, + + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionUIService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionUIService.cs new file mode 100644 index 00000000000..8a8763f2eea --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/SelectionUIService.cs @@ -0,0 +1,1935 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using Microsoft.Win32; + +namespace System.Windows.Forms.Design +{ + /// + /// The selection manager handles selection within a form. There is one selection manager for each form or top level designer. A selection consists of an array of components. One component is designated the "primary" selection and is displayed with different grab handles. An individual selection may or may not have UI associated with it. If the selection manager can find a suitable designer that is representing the selection, it will highlight the designer's border. If the merged property set has a location property, the selection's rules will allow movement. Also, if the property set has a size property, the selection's rules will allow for sizing. Grab handles may be drawn around the designer and user interactions involving the selection frame and grab handles are initiated here, but the actual movement of the objects is done in a designer object that implements the ISelectionHandler interface. + /// + internal sealed class SelectionUIService : Control, ISelectionUIService + { + private static readonly Point s_invalidPoint = new Point(int.MinValue, int.MinValue); + private const int HITTEST_CONTAINER_SELECTOR = 0x0001; + private const int HITTEST_NORMAL_SELECTION = 0x0002; + private const int HITTEST_DEFAULT = HITTEST_CONTAINER_SELECTOR | HITTEST_NORMAL_SELECTION; + + // These are used during a drag operation, either through our own handle drag or through ISelectionUIService + private ISelectionUIHandler _dragHandler; // the current drag handler + private object[] _dragComponents; // the controls being dragged + private SelectionRules _dragRules; // movement constraints for the drag + private bool _dragMoved = false; + private object _containerDrag; // object being dragged during a container drag + // These are used during a drag of a selection grab handle + private bool _ignoreCaptureChanged = false; + private int _mouseDragHitTest; // where the hit occurred that caused the drag + private Point _mouseDragAnchor = s_invalidPoint; // anchor point of the drag + private Rectangle _mouseDragOffset = Rectangle.Empty; // current drag offset + private Point _lastMoveScreenCoord = Point.Empty; + private bool _ctrlSelect = false; // was the CTRL key down when the drag began + private bool _mouseDragging = false; // Are we actually doing a drag? + private ContainerSelectorActiveEventHandler _containerSelectorActive; // the event we fire when user interacts with container selector + private Hashtable _selectionItems; + private readonly Hashtable _selectionHandlers; // Component UI handlers + + private bool _savedVisible; // we stash this when we mess with visibility ourselves. + private bool _batchMode; + private bool _batchChanged; + private bool _batchSync; + private readonly ISelectionService _selSvc; + private readonly IDesignerHost _host; + private DesignerTransaction _dragTransaction; + + /// + /// Creates a new selection manager object. The selection manager manages all selection of all designers under the current form file. + /// + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + public SelectionUIService(IDesignerHost host) : base() + { + SetStyle(ControlStyles.StandardClick | ControlStyles.Opaque | ControlStyles.OptimizedDoubleBuffer, true); + _host = host; + _dragHandler = null; + _dragComponents = null; + _selectionItems = new Hashtable(); + _selectionHandlers = new Hashtable(); + AllowDrop = true; + // Not really any reason for this, except that it can be handy when using Spy++ + Text = "SelectionUIOverlay"; + + _selSvc = (ISelectionService)host.GetService(typeof(ISelectionService)); + if (_selSvc != null) + { + _selSvc.SelectionChanged += new EventHandler(OnSelectionChanged); + } + + // And configure the events we want to listen to. + host.TransactionOpened += new EventHandler(OnTransactionOpened); + host.TransactionClosed += new DesignerTransactionCloseEventHandler(OnTransactionClosed); + if (host.InTransaction) + { + OnTransactionOpened(host, EventArgs.Empty); + } + + // Listen to the SystemEvents so that we can resync selection based on display settings etc. + SystemEvents.DisplaySettingsChanged += new EventHandler(OnSystemSettingChanged); + SystemEvents.InstalledFontsChanged += new EventHandler(OnSystemSettingChanged); + SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(OnUserPreferenceChanged); + } + + /// + /// override of control. + /// + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.Style &= ~(NativeMethods.WS_CLIPSIBLINGS | NativeMethods.WS_CLIPCHILDREN); + return cp; + } + } + + /// + /// Called to initiate a mouse drag on the selection overlay. We cache some state here. + /// + private void BeginMouseDrag(Point anchor, int hitTest) + { + Capture = true; + _ignoreCaptureChanged = false; + _mouseDragAnchor = anchor; + _mouseDragging = true; + _mouseDragHitTest = hitTest; + _mouseDragOffset = new Rectangle(); + _savedVisible = Visible; + } + + /// + /// Displays the given exception to the user. + /// + private void DisplayError(Exception e) + { + IUIService uis = (IUIService)_host.GetService(typeof(IUIService)); + if (uis != null) + { + uis.ShowError(e); + } + else + { + string message = e.Message; + if (message == null || message.Length == 0) + { + message = e.ToString(); + } + RTLAwareMessageBox.Show(null, message, null, MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, 0); + } + } + + /// + /// Disposes the entire selection UI manager. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_selSvc != null) + { + _selSvc.SelectionChanged -= new EventHandler(OnSelectionChanged); + } + + if (_host != null) + { + _host.TransactionOpened -= new EventHandler(OnTransactionOpened); + _host.TransactionClosed -= new DesignerTransactionCloseEventHandler(OnTransactionClosed); + if (_host.InTransaction) + { + OnTransactionClosed(_host, new DesignerTransactionCloseEventArgs(true, true)); + } + } + + foreach (SelectionUIItem s in _selectionItems.Values) + { + s.Dispose(); + } + _selectionHandlers.Clear(); + _selectionItems.Clear(); + // Listen to the SystemEvents so that we can resync selection based on display settings etc. + SystemEvents.DisplaySettingsChanged -= new EventHandler(OnSystemSettingChanged); + SystemEvents.InstalledFontsChanged -= new EventHandler(OnSystemSettingChanged); + SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(OnUserPreferenceChanged); + } + base.Dispose(disposing); + } + + /// + /// Called when we want to finish a mouse drag and clean up our variables. We call this from multiple places, depending on the state of the finish. This does NOT end the drag -- for that must call EndDrag. This just cleans up the state of the mouse. + /// + private void EndMouseDrag(Point position) + { + // it's possible for us to be destroyed in a drag -- e.g. if this is the tray's selectionuiservice and the last item is dragged out, so check diposed first + if (IsDisposed) + { + return; + } + _ignoreCaptureChanged = true; + Capture = false; + _mouseDragAnchor = s_invalidPoint; + _mouseDragOffset = Rectangle.Empty; + _mouseDragHitTest = 0; + _dragMoved = false; + SetSelectionCursor(position); + _mouseDragging = _ctrlSelect = false; + } + + /// + /// Determines the selection hit test at the given point. The point should be in screen coordinates. + /// + private HitTestInfo GetHitTest(Point value, int flags) + { + Point pt = PointToClient(value); + foreach (SelectionUIItem item in _selectionItems.Values) + { + if ((flags & HITTEST_CONTAINER_SELECTOR) != 0) + { + if (item is ContainerSelectionUIItem && (item.GetRules() & SelectionRules.Visible) != SelectionRules.None) + { + int hitTest = item.GetHitTest(pt); + if ((hitTest & SelectionUIItem.CONTAINER_SELECTOR) != 0) + { + return new HitTestInfo(hitTest, item, true); + } + } + } + + if ((flags & HITTEST_NORMAL_SELECTION) != 0) + { + if (!(item is ContainerSelectionUIItem) && (item.GetRules() & SelectionRules.Visible) != SelectionRules.None) + { + int hitTest = item.GetHitTest(pt); + if (hitTest != SelectionUIItem.NOHIT) + { + if (hitTest != 0) + { + return new HitTestInfo(hitTest, item); + } + else + { + return new HitTestInfo(SelectionUIItem.NOHIT, item); + } + } + } + } + } + return new HitTestInfo(SelectionUIItem.NOHIT, null); + } + + private ISelectionUIHandler GetHandler(object component) => (ISelectionUIHandler)_selectionHandlers[component]; + + /// + /// This method returns a well-formed name for a drag transaction based on the rules it is given. + /// + public static string GetTransactionName(SelectionRules rules, object[] objects) + { + // Determine a nice name for the drag operation + string transactionName; + if ((int)(rules & SelectionRules.Moveable) != 0) + { + if (objects.Length > 1) + { + transactionName = string.Format(SR.DragDropMoveComponents, objects.Length); + } + else + { + string name = string.Empty; + if (objects.Length > 0) + { + if (objects[0] is IComponent comp && comp.Site != null) + { + name = comp.Site.Name; + } + else + { + name = objects[0].GetType().Name; + } + } + transactionName = string.Format(SR.DragDropMoveComponent, name); + } + } + else if ((int)(rules & SelectionRules.AllSizeable) != 0) + { + if (objects.Length > 1) + { + transactionName = string.Format(SR.DragDropSizeComponents, objects.Length); + } + else + { + string name = string.Empty; + if (objects.Length > 0) + { + if (objects[0] is IComponent comp && comp.Site != null) + { + name = comp.Site.Name; + } + else + { + name = objects[0].GetType().Name; + } + } + transactionName = string.Format(SR.DragDropSizeComponent, name); + } + } + else + { + transactionName = string.Format(SR.DragDropDragComponents, objects.Length); + } + return transactionName; + } + + /// + /// Called by the designer host when it is entering or leaving a batch operation. Here we queue up selection notification and we turn off our UI. + /// + private void OnTransactionClosed(object sender, DesignerTransactionCloseEventArgs e) + { + if (e.LastTransaction) + { + _batchMode = false; + if (_batchChanged) + { + _batchChanged = false; + ((ISelectionUIService)this).SyncSelection(); + } + if (_batchSync) + { + _batchSync = false; + ((ISelectionUIService)this).SyncComponent(null); + } + } + } + + /// + /// Called by the designer host when it is entering or leaving a batch operation. Here we queue up selection notification and we turn off our UI. + /// + private void OnTransactionOpened(object sender, EventArgs e) + { + _batchMode = true; + } + + /// + /// update our window region on first create. We shouldn't do this before the handle is created or else we will force creation. + /// + protected override void OnHandleCreated(EventArgs e) + { + Debug.Assert(!RecreatingHandle, "Perf hit: we are recreating the docwin handle"); + base.OnHandleCreated(e); + // Default the shape of the control to be empty, so that if nothing is initially selected that our window surface doesn't interfere. + UpdateWindowRegion(); + } + + /// + /// Called whenever a component changes. Here we update our selection information so that the selection rectangles are all up to date. + /// + private void OnComponentChanged(object sender, ComponentChangedEventArgs ccevent) + { + if (!_batchMode) + { + ((ISelectionUIService)this).SyncSelection(); + } + else + { + _batchChanged = true; + } + } + + /// + /// called by the formcore when someone has removed a component. This will remove any selection on the component without disturbing the rest of the selection + /// + private void OnComponentRemove(object sender, ComponentEventArgs ce) + { + _selectionHandlers.Remove(ce.Component); + _selectionItems.Remove(ce.Component); + ((ISelectionUIService)this).SyncComponent(ce.Component); + } + + /// + /// Called to invoke the container active event, if a designer has bound to it. + /// + private void OnContainerSelectorActive(ContainerSelectorActiveEventArgs e) + { + _containerSelectorActive?.Invoke(this, e); + } + + /// + /// Called when the selection changes. We sync up the UI with the selection at this point. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + ICollection selection = _selSvc.GetSelectedComponents(); + Hashtable newSelection = new Hashtable(selection.Count); + bool shapeChanged = false; + foreach (object comp in selection) + { + object existingItem = _selectionItems[comp]; + bool create = true; + if (existingItem != null) + { + if (existingItem is ContainerSelectionUIItem item) + { + item.Dispose(); + shapeChanged = true; + } + else + { + newSelection[comp] = existingItem; + create = false; + } + } + + if (create) + { + shapeChanged = true; + newSelection[comp] = new SelectionUIItem(this, comp); + } + } + + if (!shapeChanged) + { + shapeChanged = _selectionItems.Keys.Count != newSelection.Keys.Count; + } + + _selectionItems = newSelection; + + if (shapeChanged) + { + UpdateWindowRegion(); + } + Invalidate(); + Update(); + } + + /// + /// User setting requires that we repaint. + /// + private void OnSystemSettingChanged(object sender, EventArgs e) => Invalidate(); + + /// + /// User setting requires that we repaint. + /// + private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) => Invalidate(); + + /// + /// Inheriting classes should override this method to handle this event. Call super.onDragEnter to send this event to any registered event listeners. + /// + protected override void OnDragEnter(DragEventArgs devent) + { + base.OnDragEnter(devent); + if (_dragHandler != null) + { + _dragHandler.OleDragEnter(devent); + } + } + + /// + /// Inheriting classes should override this method to handle this event. Call super.onDragOver to send this event to any registered event listeners. + /// + protected override void OnDragOver(DragEventArgs devent) + { + base.OnDragOver(devent); + if (_dragHandler != null) + { + _dragHandler.OleDragOver(devent); + } + } + /// + /// Inheriting classes should override this method to handle this event. Call super.onDragLeave to send this event to any registered event listeners. + /// + protected override void OnDragLeave(EventArgs e) + { + base.OnDragLeave(e); + if (_dragHandler != null) + { + _dragHandler.OleDragLeave(); + } + } + + /// + /// Inheriting classes should override this method to handle this event. Call super.onDragDrop to send this event to any registered event listeners. + /// + protected override void OnDragDrop(DragEventArgs devent) + { + base.OnDragDrop(devent); + if (_dragHandler != null) + { + _dragHandler.OleDragDrop(devent); + } + } + + /// + /// Inheriting classes should override this method to handle this event. Call base.OnDoiubleClick to send this event to any registered event listeners. + /// + protected override void OnDoubleClick(EventArgs devent) + { + base.OnDoubleClick(devent); + if (_selSvc != null) + { + object selComp = _selSvc.PrimarySelection; + Debug.Assert(selComp != null, "Illegal selection on double-click"); + if (selComp != null) + { + ISelectionUIHandler handler = GetHandler(selComp); + if (handler != null) + { + handler.OnSelectionDoubleClick((IComponent)selComp); + } + } + } + } + + /// + /// Overrides Control to handle our selection grab handles. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + protected override void OnMouseDown(MouseEventArgs me) + { + if (_dragHandler == null && _selSvc != null) + { + try + { + // First, did the user step on anything? + Point anchor = PointToScreen(new Point(me.X, me.Y)); + HitTestInfo hti = GetHitTest(anchor, HITTEST_DEFAULT); + int hitTest = hti.hitTest; + if ((hitTest & SelectionUIItem.CONTAINER_SELECTOR) != 0) + { + _selSvc.SetSelectedComponents(new object[] { hti.selectionUIHit._component }, SelectionTypes.Auto); + // Then do a drag... + SelectionRules rules = SelectionRules.Moveable; + if (((ISelectionUIService)this).BeginDrag(rules, anchor.X, anchor.Y)) + { + Visible = false; + _containerDrag = hti.selectionUIHit._component; + BeginMouseDrag(anchor, hitTest); + } + } + else if (hitTest != SelectionUIItem.NOHIT && me.Button == MouseButtons.Left) + { + SelectionRules rules = SelectionRules.None; + // If the CTRL key isn't down, select this component, otherwise, we wait until the mouse up. Make sure the component is selected + _ctrlSelect = (Control.ModifierKeys & Keys.Control) != Keys.None; + if (!_ctrlSelect) + { + _selSvc.SetSelectedComponents(new object[] { hti.selectionUIHit._component }, SelectionTypes.Primary); + } + + if ((hitTest & SelectionUIItem.MOVE_MASK) != 0) + { + rules |= SelectionRules.Moveable; + } + if ((hitTest & SelectionUIItem.SIZE_MASK) != 0) + { + if ((hitTest & (SelectionUIItem.SIZE_X | SelectionUIItem.POS_RIGHT)) == (SelectionUIItem.SIZE_X | SelectionUIItem.POS_RIGHT)) + { + rules |= SelectionRules.RightSizeable; + } + if ((hitTest & (SelectionUIItem.SIZE_X | SelectionUIItem.POS_LEFT)) == (SelectionUIItem.SIZE_X | SelectionUIItem.POS_LEFT)) + { + rules |= SelectionRules.LeftSizeable; + } + if ((hitTest & (SelectionUIItem.SIZE_Y | SelectionUIItem.POS_TOP)) == (SelectionUIItem.SIZE_Y | SelectionUIItem.POS_TOP)) + { + rules |= SelectionRules.TopSizeable; + } + if ((hitTest & (SelectionUIItem.SIZE_Y | SelectionUIItem.POS_BOTTOM)) == (SelectionUIItem.SIZE_Y | SelectionUIItem.POS_BOTTOM)) + { + rules |= SelectionRules.BottomSizeable; + } + + if (((ISelectionUIService)this).BeginDrag(rules, anchor.X, anchor.Y)) + { + BeginMouseDrag(anchor, hitTest); + } + } + else + { + // Our mouse is in drag mode. We defer the actual move until the user moves the mouse. + _dragRules = rules; + BeginMouseDrag(anchor, hitTest); + } + } + else if (hitTest == SelectionUIItem.NOHIT) + { + _dragRules = SelectionRules.None; + _mouseDragAnchor = s_invalidPoint; + return; + } + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + else if (e != CheckoutException.Canceled) + { + DisplayError(e); + } + } + } + } + + /// + /// Overrides Control to handle our selection grab handles. + /// + protected override void OnMouseMove(MouseEventArgs me) + { + base.OnMouseMove(me); + Point screenCoord = PointToScreen(new Point(me.X, me.Y)); + HitTestInfo hti = GetHitTest(screenCoord, HITTEST_CONTAINER_SELECTOR); + int hitTest = hti.hitTest; + if (hitTest != SelectionUIItem.CONTAINER_SELECTOR && hti.selectionUIHit != null) + { + OnContainerSelectorActive(new ContainerSelectorActiveEventArgs(hti.selectionUIHit._component)); + } + + if (_lastMoveScreenCoord == screenCoord) + { + return; + } + // If we're not dragging then set the cursor correctly. + if (!_mouseDragging) + { + SetSelectionCursor(screenCoord); + } + else + { + // we have to make sure the mouse moved farther than the minimum drag distance before we actually start the drag + if (!((ISelectionUIService)this).Dragging && (_mouseDragHitTest & SelectionUIItem.MOVE_MASK) != 0) + { + Size minDragSize = SystemInformation.DragSize; + if ( + Math.Abs(screenCoord.X - _mouseDragAnchor.X) < minDragSize.Width && + Math.Abs(screenCoord.Y - _mouseDragAnchor.Y) < minDragSize.Height) + { + return; + } + else + { + _ignoreCaptureChanged = true; + if (((ISelectionUIService)this).BeginDrag(_dragRules, _mouseDragAnchor.X, _mouseDragAnchor.Y)) + { + // we're moving, so we don't care about the ctrl key any more + _ctrlSelect = false; + } + else + { + EndMouseDrag(MousePosition); + return; + } + } + } + + Rectangle old = _mouseDragOffset; + if ((_mouseDragHitTest & SelectionUIItem.MOVE_X) != 0) + { + _mouseDragOffset.X = screenCoord.X - _mouseDragAnchor.X; + } + if ((_mouseDragHitTest & SelectionUIItem.MOVE_Y) != 0) + { + _mouseDragOffset.Y = screenCoord.Y - _mouseDragAnchor.Y; + } + if ((_mouseDragHitTest & SelectionUIItem.SIZE_X) != 0) + { + if ((_mouseDragHitTest & SelectionUIItem.POS_LEFT) != 0) + { + _mouseDragOffset.X = screenCoord.X - _mouseDragAnchor.X; + _mouseDragOffset.Width = _mouseDragAnchor.X - screenCoord.X; + } + else + { + _mouseDragOffset.Width = screenCoord.X - _mouseDragAnchor.X; + } + } + if ((_mouseDragHitTest & SelectionUIItem.SIZE_Y) != 0) + { + if ((_mouseDragHitTest & SelectionUIItem.POS_TOP) != 0) + { + _mouseDragOffset.Y = screenCoord.Y - _mouseDragAnchor.Y; + _mouseDragOffset.Height = _mouseDragAnchor.Y - screenCoord.Y; + } + else + { + _mouseDragOffset.Height = screenCoord.Y - _mouseDragAnchor.Y; + } + } + + if (!old.Equals(_mouseDragOffset)) + { + Rectangle delta = _mouseDragOffset; + delta.X -= old.X; + delta.Y -= old.Y; + delta.Width -= old.Width; + delta.Height -= old.Height; + if (delta.X != 0 || delta.Y != 0 || delta.Width != 0 || delta.Height != 0) + { + // Go to default cursor for moves... + if ((_mouseDragHitTest & SelectionUIItem.MOVE_X) != 0 || (_mouseDragHitTest & SelectionUIItem.MOVE_Y) != 0) + { + Cursor = Cursors.Default; + } + ((ISelectionUIService)this).DragMoved(delta); + } + } + } + } + + /// + /// Overrides Control to handle our selection grab handles. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + protected override void OnMouseUp(MouseEventArgs me) + { + try + { + Point screenCoord = PointToScreen(new Point(me.X, me.Y)); + if (_ctrlSelect && !_mouseDragging && _selSvc != null) + { + HitTestInfo hti = GetHitTest(screenCoord, HITTEST_DEFAULT); + _selSvc.SetSelectedComponents(new object[] { hti.selectionUIHit._component }, SelectionTypes.Primary); + } + + if (_mouseDragging) + { + object oldContainerDrag = _containerDrag; + bool oldDragMoved = _dragMoved; + EndMouseDrag(screenCoord); + if (((ISelectionUIService)this).Dragging) + { + ((ISelectionUIService)this).EndDrag(false); + } + + if (me.Button == MouseButtons.Right && oldContainerDrag != null && !oldDragMoved) + { + OnContainerSelectorActive(new ContainerSelectorActiveEventArgs(oldContainerDrag, ContainerSelectorActiveEventArgsType.Contextmenu)); + } + } + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + else if (e != CheckoutException.Canceled) + { + DisplayError(e); + } + } + } + + /// + /// If the selection manager move, this indicates that the form has autoscolling enabled and has been scrolled. We have to invalidate here because we may get moved before the rest of the components so we may draw the selection in the wrong spot. + /// + protected override void OnMove(EventArgs e) + { + base.OnMove(e); + Invalidate(); + } + + /// + /// overrides control.onPaint. here we paint the selection handles. The window's region was setup earlier. + /// + protected override void OnPaint(PaintEventArgs e) + { + // Paint the regular selection items first, and then the container selectors last so they draw over the top. + foreach (SelectionUIItem item in _selectionItems.Values) + { + if (item is ContainerSelectionUIItem) + { + continue; + } + item.DoPaint(e.Graphics); + } + + foreach (SelectionUIItem item in _selectionItems.Values) + { + if (item is ContainerSelectionUIItem) + { + item.DoPaint(e.Graphics); + } + } + } + + /// + /// Sets the appropriate selection cursor at the given point. + /// + private void SetSelectionCursor(Point pt) + { + Point clientCoords = PointToClient(pt); + // We render the cursor in the same order we paint. + foreach (SelectionUIItem item in _selectionItems.Values) + { + if (item is ContainerSelectionUIItem) + { + continue; + } + Cursor cursor = item.GetCursorAtPoint(clientCoords); + if (cursor != null) + { + if (cursor == Cursors.Default) + { + Cursor = null; + } + else + { + Cursor = cursor; + } + return; + } + } + + foreach (SelectionUIItem item in _selectionItems.Values) + { + if (item is ContainerSelectionUIItem) + { + Cursor cursor = item.GetCursorAtPoint(clientCoords); + if (cursor != null) + { + if (cursor == Cursors.Default) + { + Cursor = null; + } + else + { + Cursor = cursor; + } + return; + } + } + } + // Don't know what to set; just use the default. + Cursor = null; + } + + /// + /// called when the overlay region is invalid and should be updated + /// + private void UpdateWindowRegion() + { + Region region = new Region(new Rectangle(0, 0, 0, 0)); + foreach (SelectionUIItem item in _selectionItems.Values) + { + region.Union(item.GetRegion()); + } + + Region = region; + } + + /// + /// Override of our control's WNDPROC. We diddle with capture a bit, and it's important to turn this off if the capture changes. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: + if (_mouseDragAnchor != s_invalidPoint) + { + _ignoreCaptureChanged = true; + } + break; + case Interop.WindowMessages.WM_CAPTURECHANGED: + if (!_ignoreCaptureChanged && _mouseDragAnchor != s_invalidPoint) + { + EndMouseDrag(MousePosition); + if (((ISelectionUIService)this).Dragging) + { + ((ISelectionUIService)this).EndDrag(true); + } + } + _ignoreCaptureChanged = false; + break; + } + base.WndProc(ref m); + } + + /// + /// This can be used to determine if the user is in the middle of a drag operation. + /// + bool ISelectionUIService.Dragging + { + get => _dragHandler != null; + } + + /// + /// Determines if the selection UI is shown or not. + /// + bool ISelectionUIService.Visible + { + get => Visible; + set => Visible = value; + } + + /// + /// Adds an event handler to the ContainerSelectorActive event. This event is fired whenever the user interacts with the container selector in a manor that would indicate that the selector should continued to be displayed. Since the container selector normally will vanish after a timeout, designers should listen to this event and reset the timeout when this event occurs. + /// + event ContainerSelectorActiveEventHandler ISelectionUIService.ContainerSelectorActive + { + add => _containerSelectorActive += value; + remove => _containerSelectorActive -= value; + } + + /// + /// Assigns a selection UI handler to a given component. The handler will be called when the UI service needs information about the component. A single selection UI handler can be assigned to multiple components. When multiple components are dragged, only a single handler may control the drag. Because of this, only components that are assigned the same handler as the primary selection are included in drag operations. A selection UI handler is automatically unassigned when the component is removed from the container or disposed. + /// + void ISelectionUIService.AssignSelectionUIHandler(object component, ISelectionUIHandler handler) + { + ISelectionUIHandler oldHandler = (ISelectionUIHandler)_selectionHandlers[component]; + if (oldHandler != null) + { + // The collection editors do not dispose objects from the collection before setting a new collection. This causes items that are common to the old and new collections to come through this code path again, causing the exception to fire. So, we check to see if the SelectionUIHandler is same, and bail out in that case. + if (handler == oldHandler) + { + return; + } + Debug.Fail("A component may have only one selection UI handler."); + throw new InvalidOperationException(); + } + _selectionHandlers[component] = handler; + // If this component is selected, create a new UI handler for it. + if (_selSvc != null && _selSvc.GetComponentSelected(component)) + { + SelectionUIItem item = new SelectionUIItem(this, component); + _selectionItems[component] = item; + UpdateWindowRegion(); + item.Invalidate(); + } + } + + void ISelectionUIService.ClearSelectionUIHandler(object component, ISelectionUIHandler handler) + { + ISelectionUIHandler oldHandler = (ISelectionUIHandler)_selectionHandlers[component]; + if (oldHandler == handler) + { + _selectionHandlers[component] = null; + } + } + + /// + /// This can be called by an outside party to begin a drag of the currently selected set of components. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + bool ISelectionUIService.BeginDrag(SelectionRules rules, int initialX, int initialY) + { + if (_dragHandler != null) + { + Debug.Fail("Caller is starting a drag, but there is already one in progress -- we cannot nest these!"); + return false; + } + + if (rules == SelectionRules.None) + { + Debug.Fail("Caller is starting requesting a drag with no drag rules."); + return false; + } + + if (_selSvc == null) + { + return false; + } + + _savedVisible = Visible; + // First, get the list of controls + ICollection col = _selSvc.GetSelectedComponents(); + object[] objects = new object[col.Count]; + col.CopyTo(objects, 0); + objects = ((ISelectionUIService)this).FilterSelection(objects, rules); + if (objects.Length == 0) + { + return false; // nothing selected + } + + // We allow all components with the same UI handler as the primary selection to participate in the drag. + ISelectionUIHandler primaryHandler = null; + object primary = _selSvc.PrimarySelection; + if (primary != null) + { + primaryHandler = GetHandler(primary); + } + if (primaryHandler == null) + { + return false; // no UI handler for selection + } + + // Now within the given selection, add those items that have the same UI handler and that have the proper rule constraints. + ArrayList list = new ArrayList(); + for (int i = 0; i < objects.Length; i++) + { + if (GetHandler(objects[i]) == primaryHandler) + { + SelectionRules compRules = primaryHandler.GetComponentRules(objects[i]); + if ((compRules & rules) == rules) + { + list.Add(objects[i]); + } + } + } + if (list.Count == 0) + { + return false; // nothing matching the given constraints + } + objects = list.ToArray(); + bool dragging = false; + // We must setup state before calling QueryBeginDrag. It is possible that QueryBeginDrag will cancel a drag (if it places a modal dialog, for example), so we must have the drag data all setup before it cancels. Then, we will check again after QueryBeginDrag to see if a cancel happened. + _dragComponents = objects; + _dragRules = rules; + _dragHandler = primaryHandler; + string transactionName = GetTransactionName(rules, objects); + _dragTransaction = _host.CreateTransaction(transactionName); + try + { + if (primaryHandler.QueryBeginDrag(objects, rules, initialX, initialY)) + { + if (_dragHandler != null) + { + try + { + dragging = primaryHandler.BeginDrag(objects, rules, initialX, initialY); + } + catch (Exception e) + { + Debug.Fail("Drag handler threw during BeginDrag -- bad handler!", e.ToString()); + dragging = false; + } + } + } + } + finally + { + + if (!dragging) + { + _dragComponents = null; + _dragRules = 0; + _dragHandler = null; + + // Always commit this -- BeginDrag returns false for our drags because it is a complete operation. + if (_dragTransaction != null) + { + _dragTransaction.Commit(); + _dragTransaction = null; + } + } + } + return dragging; + } + + /// + /// Called by an outside party to update drag information. This can only be called after a successful call to beginDrag. + /// + void ISelectionUIService.DragMoved(Rectangle offset) + { + Rectangle newOffset = Rectangle.Empty; + if (_dragHandler == null) + { + throw new Exception(SR.DesignerBeginDragNotCalled); + } + + Debug.Assert(_dragComponents != null, "We should have a set of drag controls here"); + if ((_dragRules & SelectionRules.Moveable) == SelectionRules.None && (_dragRules & (SelectionRules.TopSizeable | SelectionRules.LeftSizeable)) == SelectionRules.None) + { + newOffset = new Rectangle(0, 0, offset.Width, offset.Height); + } + if ((_dragRules & SelectionRules.AllSizeable) == SelectionRules.None) + { + if (newOffset.IsEmpty) + { + newOffset = new Rectangle(offset.X, offset.Y, 0, 0); + } + else + { + newOffset.Width = newOffset.Height = 0; + } + } + + if (!newOffset.IsEmpty) + { + offset = newOffset; + } + + Visible = false; + _dragMoved = true; + _dragHandler.DragMoved(_dragComponents, offset); + } + + /// + /// Called by an outside party to finish a drag operation. This can only be called after a successful call to beginDrag. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + void ISelectionUIService.EndDrag(bool cancel) + { + _containerDrag = null; + ISelectionUIHandler handler = _dragHandler; + object[] components = _dragComponents; + // Clean these out so that even if we throw an exception we don't die. + _dragHandler = null; + _dragComponents = null; + _dragRules = SelectionRules.None; + if (handler == null) + { + throw new InvalidOperationException(); + } + + // Typically, the handler will be changing a bunch of component properties here. Optimize this by enclosing it within a batch call. + DesignerTransaction trans = null; + try + { + IComponent comp = components[0] as IComponent; + if (components.Length > 1 || (components.Length == 1 && comp != null && comp.Site == null)) + { + trans = _host.CreateTransaction(string.Format(SR.DragDropMoveComponents, components.Length)); + } + else if (components.Length == 1) + { + if (comp != null) + { + trans = _host.CreateTransaction(string.Format(SR.DragDropMoveComponent, comp.Site.Name)); + } + } + try + { + handler.EndDrag(components, cancel); + } + catch (Exception e) + { + Debug.Fail(e.ToString()); + } + } + finally + { + if (trans != null) + trans.Commit(); + // Reset the selection. This will re-display our selection. + Visible = _savedVisible; + ((ISelectionUIService)this).SyncSelection(); + if (_dragTransaction != null) + { + _dragTransaction.Commit(); + _dragTransaction = null; + } + // In case this drag was initiated by us, ensure that our mouse state is correct + EndMouseDrag(MousePosition); + } + } + + /// + /// Filters the set of selected components. The selection service will retrieve all components that are currently selected. This method allows you to filter this set down to components that match your criteria. The selectionRules parameter must contain one or more flags from the SelectionRules class. These flags allow you to constrain the set of selected objects to visible, movable, sizeable or all objects. + /// + object[] ISelectionUIService.FilterSelection(object[] components, SelectionRules selectionRules) + { + object[] selection = null; + if (components == null) + return new object[0]; + // Mask off any selection object that doesn't adhere to the given ruleset. We can ignore this if the ruleset is zero, as all components would be accepted. + if (selectionRules != SelectionRules.None) + { + ArrayList list = new ArrayList(); + foreach (object comp in components) + { + SelectionUIItem item = (SelectionUIItem)_selectionItems[comp]; + if (item != null && !(item is ContainerSelectionUIItem)) + { + if ((item.GetRules() & selectionRules) == selectionRules) + { + list.Add(comp); + } + } + } + selection = (object[])list.ToArray(); + } + return selection ?? (new object[0]); + } + + /// + /// Retrieves the width and height of a selection border grab handle. Designers may need this to properly position their user interfaces. + /// + Size ISelectionUIService.GetAdornmentDimensions(AdornmentType adornmentType) + { + switch (adornmentType) + { + case AdornmentType.GrabHandle: + return new Size(SelectionUIItem.GRABHANDLE_WIDTH, SelectionUIItem.GRABHANDLE_HEIGHT); + case AdornmentType.ContainerSelector: + case AdornmentType.Maximum: + return new Size(ContainerSelectionUIItem.CONTAINER_WIDTH, ContainerSelectionUIItem.CONTAINER_HEIGHT); + } + return new Size(0, 0); + } + + /// + /// Tests to determine if the given screen coordinate is over an adornment for the specified component. This will only return true if the adornment, and selection UI, is visible. + /// + bool ISelectionUIService.GetAdornmentHitTest(object component, Point value) => GetHitTest(value, HITTEST_DEFAULT).hitTest != SelectionUIItem.NOHIT; + + /// + /// Determines if the component is currently "container" selected. Container selection is a visual aid for selecting containers. It doesn't affect the normal "component" selection. + /// + bool ISelectionUIService.GetContainerSelected(object component) => (component != null && _selectionItems[component] is ContainerSelectionUIItem); + + /// + /// Retrieves a set of flags that define rules for the selection. Selection rules indicate if the given component can be moved or sized, for example. + /// + SelectionRules ISelectionUIService.GetSelectionRules(object component) + { + SelectionUIItem sel = (SelectionUIItem)_selectionItems[component]; + if (sel == null) + { + Debug.Fail("The component is not currently selected."); + throw new InvalidOperationException(); + } + return sel.GetRules(); + } + + /// + /// Allows you to configure the style of the selection frame that a component uses. This is useful if your component supports different modes of operation (such as an in-place editing mode and a static design mode). Where possible, you should leave the selection style as is and use the design-time hit testing feature of the IDesigner interface to provide features at design time. The value of style must be one of the SelectionStyle enum values. The selection style is only valid for the duration that the component is selected. + /// + SelectionStyles ISelectionUIService.GetSelectionStyle(object component) + { + SelectionUIItem s = (SelectionUIItem)_selectionItems[component]; + if (s == null) + { + return SelectionStyles.None; + } + return s.Style; + } + + /// + /// Changes the container selection status of the given component. Container selection is a visual aid for selecting containers. It doesn't affect the normal "component" selection. + /// + void ISelectionUIService.SetContainerSelected(object component, bool selected) + { + if (selected) + { + SelectionUIItem existingItem = (SelectionUIItem)_selectionItems[component]; + if (!(existingItem is ContainerSelectionUIItem)) + { + if (existingItem != null) + { + existingItem.Dispose(); + } + SelectionUIItem item = new ContainerSelectionUIItem(this, component); + _selectionItems[component] = item; + // Now update our region and invalidate + UpdateWindowRegion(); + if (existingItem != null) + { + existingItem.Invalidate(); + } + item.Invalidate(); + } + } + else + { + SelectionUIItem existingItem = (SelectionUIItem)_selectionItems[component]; + if (existingItem == null || existingItem is ContainerSelectionUIItem) + { + _selectionItems.Remove(component); + if (existingItem != null) + { + existingItem.Dispose(); + } + UpdateWindowRegion(); + existingItem.Invalidate(); + } + } + } + + /// + /// Allows you to configure the style of the selection frame that a component uses. This is useful if your component supports different modes of operation (such as an in-place editing mode and a static design mode). Where possible, you should leave the selection style as is and use the design-time hit testing feature of the IDesigner interface to provide features at design time. The value of style must be one of the SelectionStyle enum values. The selection style is only valid for the duration that the component is selected. + /// + void ISelectionUIService.SetSelectionStyle(object component, SelectionStyles style) + { + SelectionUIItem selUI = (SelectionUIItem)_selectionItems[component]; + if (_selSvc != null && _selSvc.GetComponentSelected(component)) + { + selUI = new SelectionUIItem(this, component); + _selectionItems[component] = selUI; + } + + if (selUI != null) + { + selUI.Style = style; + UpdateWindowRegion(); + selUI.Invalidate(); + } + } + + /// + /// This should be called when a component has been moved, sized or re-parented, but the change was not the result of a property change. All property changes are monitored by the selection UI service, so this is automatic most of the time. There are times, however, when a component may be moved without a property change notification occurring. Scrolling an auto scroll Win32 form is an example of this. This method simply re-queries all currently selected components for their bounds and udpates the selection handles for any that have changed. + /// + void ISelectionUIService.SyncSelection() + { + if (_batchMode) + { + _batchChanged = true; + } + else + { + if (IsHandleCreated) + { + bool updateRegion = false; + foreach (SelectionUIItem item in _selectionItems.Values) + { + updateRegion |= item.UpdateSize(); + item.UpdateRules(); + } + if (updateRegion) + { + UpdateWindowRegion(); + Update(); + } + } + } + } + + /// + /// This should be called when a component's property changed, that the designer thinks should result in a selection UI change. This method simply re-queries all currently selected components for their bounds and udpates the selection handles for any that have changed. + /// + void ISelectionUIService.SyncComponent(object component) + { + if (_batchMode) + { + _batchSync = true; + } + else + { + if (IsHandleCreated) + { + foreach (SelectionUIItem item in _selectionItems.Values) + { + item.UpdateRules(); + item.Dispose(); + } + UpdateWindowRegion(); + Invalidate(); + Update(); + } + } + } + + /// + /// This class represents a single selected object. + /// + private class SelectionUIItem + { + // Flags describing how a given selection point may be sized + public const int SIZE_X = 0x0001; + public const int SIZE_Y = 0x0002; + public const int SIZE_MASK = 0x0003; + // Flags describing how a given selection point may be moved + public const int MOVE_X = 0x0004; + public const int MOVE_Y = 0x0008; + public const int MOVE_MASK = 0x000C; + // Flags describing where a given selection point is located on an object + public const int POS_LEFT = 0x0010; + public const int POS_TOP = 0x0020; + public const int POS_RIGHT = 0x0040; + public const int POS_BOTTOM = 0x0080; + public const int POS_MASK = 0x00F0; + // This is returned if the given selection point is not within the selection + public const int NOHIT = 0x0100; + // This is returned if the given selection point on the "container selector" + public const int CONTAINER_SELECTOR = 0x0200; + public const int GRABHANDLE_WIDTH = 7; + public const int GRABHANDLE_HEIGHT = 7; + // tables we use to determine how things can move and size + internal static readonly int[] s_activeSizeArray = new int[] { + SIZE_X | SIZE_Y | POS_LEFT | POS_TOP, SIZE_Y | POS_TOP, SIZE_X | SIZE_Y | POS_TOP | POS_RIGHT, + SIZE_X | POS_LEFT, SIZE_X | POS_RIGHT, + SIZE_X | SIZE_Y | POS_LEFT | POS_BOTTOM, SIZE_Y | POS_BOTTOM, SIZE_X | SIZE_Y | POS_RIGHT | POS_BOTTOM + }; + + internal static readonly Cursor[] s_activeCursorArrays = new Cursor[] { + Cursors.SizeNWSE, Cursors.SizeNS, Cursors.SizeNESW, + Cursors.SizeWE, Cursors.SizeWE, + Cursors.SizeNESW, Cursors.SizeNS, Cursors.SizeNWSE + }; + + internal static readonly int[] s_inactiveSizeArray = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }; + internal static readonly Cursor[] s_inactiveCursorArray = new Cursor[] { + Cursors.Arrow, Cursors.Arrow, Cursors.Arrow, + Cursors.Arrow, Cursors.Arrow, + Cursors.Arrow, Cursors.Arrow, Cursors.Arrow + }; + + internal int[] _sizes; // array of sizing rules for this selection + internal Cursor[] _cursors; // array of cursors for each grab location + internal SelectionUIService _selUIsvc; + internal Rectangle _innerRect = Rectangle.Empty; // inner part of selection (== control bounds) + internal Rectangle _outerRect = Rectangle.Empty; // outer part of selection (inner + border size) + internal Region _region; // region object that defines the shape + internal object _component; // the component we're rendering + private readonly Control _control; + private SelectionStyles _selectionStyle; // how do we draw this thing? + private SelectionRules _selectionRules; + private readonly ISelectionUIHandler _handler; // the components selection UI handler (can be null) + + /// Its ok to call virtual method as this is a private class. + [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] + public SelectionUIItem(SelectionUIService selUIsvc, object component) + { + _selUIsvc = selUIsvc; + _component = component; + _selectionStyle = SelectionStyles.Selected; + // By default, a component isn't visible. We must establish what it can do through it's UI handler. + _handler = selUIsvc.GetHandler(component); + _sizes = s_inactiveSizeArray; + _cursors = s_inactiveCursorArray; + if (component is IComponent comp) + { + if (selUIsvc._host.GetDesigner(comp) is ControlDesigner cd) + { + _control = cd.Control; + } + } + UpdateRules(); + UpdateGrabSettings(); + UpdateSize(); + } + + /// + /// Retrieves the style of the selection frame for this selection. + /// + public virtual SelectionStyles Style + { + get => _selectionStyle; + set + { + if (value != _selectionStyle) + { + _selectionStyle = value; + if (_region != null) + { + _region.Dispose(); + _region = null; + } + } + } + } + + /// + /// paints the selection + /// + public virtual void DoPaint(Graphics gr) + { + // If we're not visible, then there's nothing to do... + // + if ((GetRules() & SelectionRules.Visible) == SelectionRules.None) + return; + bool fActive = false; + if (_selUIsvc._selSvc != null) + { + fActive = _component == _selUIsvc._selSvc.PrimarySelection; + // Office rules: If this is a multi-select, reverse the colors for active / inactive. + fActive = (fActive == (_selUIsvc._selSvc.SelectionCount <= 1)); + } + + Rectangle r = new Rectangle(_outerRect.X, _outerRect.Y, GRABHANDLE_WIDTH, GRABHANDLE_HEIGHT); + Rectangle inner = _innerRect; + Rectangle outer = _outerRect; + Region oldClip = gr.Clip; + Color borderColor = SystemColors.Control; + if (_control != null && _control.Parent != null) + { + Control parent = _control.Parent; + borderColor = parent.BackColor; + } + Brush brush = new SolidBrush(borderColor); + gr.ExcludeClip(inner); + gr.FillRectangle(brush, outer); + brush.Dispose(); + gr.Clip = oldClip; + ControlPaint.DrawSelectionFrame(gr, false, outer, inner, borderColor); + //if it's not locked & it is sizeable... + if (((GetRules() & SelectionRules.Locked) == SelectionRules.None) && (GetRules() & SelectionRules.AllSizeable) != SelectionRules.None) + { + // upper left + ControlPaint.DrawGrabHandle(gr, r, fActive, (_sizes[0] != 0)); + // upper right + r.X = inner.X + inner.Width; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[2] != 0); + // lower right + r.Y = inner.Y + inner.Height; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[7] != 0); + // lower left + r.X = outer.X; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[5] != 0); + // lower middle + r.X += (outer.Width - GRABHANDLE_WIDTH) / 2; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[6] != 0); + // upper middle + r.Y = outer.Y; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[1] != 0); + // left middle + r.X = outer.X; + r.Y = inner.Y + (inner.Height - GRABHANDLE_HEIGHT) / 2; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[3] != 0); + // right middle + r.X = inner.X + inner.Width; + ControlPaint.DrawGrabHandle(gr, r, fActive, _sizes[4] != 0); + } + else + { + ControlPaint.DrawLockedFrame(gr, outer, fActive); + } + } + + /// + /// Retrieves an appropriate cursor at the given point. If there is no appropriate cursor here (ie, the point lies outside the selection rectangle), then this will return null. + /// + public virtual Cursor GetCursorAtPoint(Point pt) + { + Cursor cursor = null; + if (PointWithinSelection(pt)) + { + int nOffset = -1; + if ((GetRules() & SelectionRules.AllSizeable) != SelectionRules.None) + { + nOffset = GetHandleIndexOfPoint(pt); + } + + if (-1 == nOffset) + { + if ((GetRules() & SelectionRules.Moveable) == SelectionRules.None) + { + cursor = Cursors.Default; + } + else + { + cursor = Cursors.SizeAll; + } + } + else + { + cursor = _cursors[nOffset]; + } + } + return cursor; + } + + /// + /// returns the hit test code of the given point. This may be one of: + /// + public virtual int GetHitTest(Point pt) + { + // Is it within our rects? + if (!PointWithinSelection(pt)) + { + return NOHIT; + } + + // Which index in the array is this? + int nOffset = GetHandleIndexOfPoint(pt); + // If no index, the user has picked on the hatch + if (-1 == nOffset || _sizes[nOffset] == 0) + { + return ((GetRules() & SelectionRules.Moveable) == SelectionRules.None ? 0 : MOVE_X | MOVE_Y); + } + return _sizes[nOffset]; + } + + /// + /// gets the array offset of the handle at the given point + /// + private int GetHandleIndexOfPoint(Point pt) + { + if (pt.X >= _outerRect.X && pt.X <= _innerRect.X) + { + // Something on the left side. + if (pt.Y >= _outerRect.Y && pt.Y <= _innerRect.Y) + return 0; // top left + if (pt.Y >= _innerRect.Y + _innerRect.Height && pt.Y <= _outerRect.Y + _outerRect.Height) + return 5; // bottom left + if (pt.Y >= _outerRect.Y + (_outerRect.Height - GRABHANDLE_HEIGHT) / 2 + && pt.Y <= _outerRect.Y + (_outerRect.Height + GRABHANDLE_HEIGHT) / 2) + return 3; // middle left + return -1; // unknown hit + } + + if (pt.Y >= _outerRect.Y && pt.Y <= _innerRect.Y) + { + // something on the top + Debug.Assert(!(pt.X >= _outerRect.X && pt.X <= _innerRect.X), "Should be handled by left top check"); + if (pt.X >= _innerRect.X + _innerRect.Width && pt.X <= _outerRect.X + _outerRect.Width) + return 2; // top right + if (pt.X >= _outerRect.X + (_outerRect.Width - GRABHANDLE_WIDTH) / 2 + && pt.X <= _outerRect.X + (_outerRect.Width + GRABHANDLE_WIDTH) / 2) + return 1; // top middle + return -1; // unknown hit + } + + if (pt.X >= _innerRect.X + _innerRect.Width && pt.X <= _outerRect.X + _outerRect.Width) + { + // something on the right side + Debug.Assert(!(pt.Y >= _outerRect.Y && pt.Y <= _innerRect.Y), "Should be handled by top right check"); + if (pt.Y >= _innerRect.Y + _innerRect.Height && pt.Y <= _outerRect.Y + _outerRect.Height) + return 7; // bottom right + if (pt.Y >= _outerRect.Y + (_outerRect.Height - GRABHANDLE_HEIGHT) / 2 + && pt.Y <= _outerRect.Y + (_outerRect.Height + GRABHANDLE_HEIGHT) / 2) + return 4; // middle right + return -1; // unknown hit + } + + if (pt.Y >= _innerRect.Y + _innerRect.Height && pt.Y <= _outerRect.Y + _outerRect.Height) + { + // something on the bottom + Debug.Assert(!(pt.X >= _outerRect.X && pt.X <= _innerRect.X), "Should be handled by left bottom check"); + + Debug.Assert(!(pt.X >= _innerRect.X + _innerRect.Width && pt.X <= _outerRect.X + _outerRect.Width), "Should be handled by right bottom check"); + + if (pt.X >= _outerRect.X + (_outerRect.Width - GRABHANDLE_WIDTH) / 2 && pt.X <= _outerRect.X + (_outerRect.Width + GRABHANDLE_WIDTH) / 2) + return 6; // bottom middle + return -1; // unknown hit + } + return -1; // unknown hit + } + + /// + /// returns a region handle that defines this selection. This is used to piece together a paint region for the surface that we draw our selection handles on + /// + public virtual Region GetRegion() + { + if (_region == null) + { + if ((GetRules() & SelectionRules.Visible) != SelectionRules.None && !_outerRect.IsEmpty) + { + _region = new Region(_outerRect); + _region.Exclude(_innerRect); + } + else + { + _region = new Region(new Rectangle(0, 0, 0, 0)); + } + + if (_handler != null) + { + Rectangle handlerClip = _handler.GetSelectionClipRect(_component); + if (!handlerClip.IsEmpty) + { + _region.Intersect(_selUIsvc.RectangleToClient(handlerClip)); + } + } + } + return _region; + } + + /// + /// Retrieves the rules associated with this selection. + /// + public SelectionRules GetRules() => _selectionRules; + + public void Dispose() + { + if (_region != null) + { + _region.Dispose(); + _region = null; + } + } + + /// + /// Invalidates the region for this selection glyph. + /// + public void Invalidate() + { + if (!_outerRect.IsEmpty && !_selUIsvc.Disposing) + { + _selUIsvc.Invalidate(_outerRect); + } + } + + /// + /// Part of our hit testing logic; determines if the point is somewhere within our selection. + /// + protected bool PointWithinSelection(Point pt) + { + // This is only supported for visible selections + if ((GetRules() & SelectionRules.Visible) == SelectionRules.None || _outerRect.IsEmpty || _innerRect.IsEmpty) + { + return false; + } + if (pt.X < _outerRect.X || pt.X > _outerRect.X + _outerRect.Width) + { + return false; + } + if (pt.Y < _outerRect.Y || pt.Y > _outerRect.Y + _outerRect.Height) + { + return false; + } + if (pt.X > _innerRect.X + && pt.X < _innerRect.X + _innerRect.Width + && pt.Y > _innerRect.Y + && pt.Y < _innerRect.Y + _innerRect.Height) + { + return false; + } + return true; + } + + /// + /// Updates the available grab handle settings based on the current rules. + /// + private void UpdateGrabSettings() + { + SelectionRules rules = GetRules(); + if ((rules & SelectionRules.AllSizeable) == SelectionRules.None) + { + _sizes = s_inactiveSizeArray; + _cursors = s_inactiveCursorArray; + } + else + { + _sizes = new int[8]; + _cursors = new Cursor[8]; + Array.Copy(s_activeCursorArrays, _cursors, _cursors.Length); + Array.Copy(s_activeSizeArray, _sizes, _sizes.Length); + if ((rules & SelectionRules.TopSizeable) != SelectionRules.TopSizeable) + { + _sizes[0] = 0; + _sizes[1] = 0; + _sizes[2] = 0; + _cursors[0] = Cursors.Arrow; + _cursors[1] = Cursors.Arrow; + _cursors[2] = Cursors.Arrow; + } + if ((rules & SelectionRules.LeftSizeable) != SelectionRules.LeftSizeable) + { + _sizes[0] = 0; + _sizes[3] = 0; + _sizes[5] = 0; + _cursors[0] = Cursors.Arrow; + _cursors[3] = Cursors.Arrow; + _cursors[5] = Cursors.Arrow; + } + if ((rules & SelectionRules.BottomSizeable) != SelectionRules.BottomSizeable) + { + _sizes[5] = 0; + _sizes[6] = 0; + _sizes[7] = 0; + _cursors[5] = Cursors.Arrow; + _cursors[6] = Cursors.Arrow; + _cursors[7] = Cursors.Arrow; + } + if ((rules & SelectionRules.RightSizeable) != SelectionRules.RightSizeable) + { + _sizes[2] = 0; + _sizes[4] = 0; + _sizes[7] = 0; + _cursors[2] = Cursors.Arrow; + _cursors[4] = Cursors.Arrow; + _cursors[7] = Cursors.Arrow; + } + } + } + + /// + /// Updates our cached selection rules based on current handler values. + /// + public void UpdateRules() + { + if (_handler == null) + { + _selectionRules = SelectionRules.None; + } + else + { + SelectionRules oldRules = _selectionRules; + _selectionRules = _handler.GetComponentRules(_component); + if (_selectionRules != oldRules) + { + UpdateGrabSettings(); + Invalidate(); + } + } + } + + /// + /// rebuilds the inner and outer rectangles based on the current selItem.component dimensions. We could calcuate this every time, but that would be expensive for functions like getHitTest that are called a lot (like on every mouse move) + /// + public virtual bool UpdateSize() + { + bool sizeChanged = false; + // Short circuit common cases + if (_handler == null) + return false; + if ((GetRules() & SelectionRules.Visible) == SelectionRules.None) + return false; + _innerRect = _handler.GetComponentBounds(_component); + if (!_innerRect.IsEmpty) + { + _innerRect = _selUIsvc.RectangleToClient(_innerRect); + Rectangle rcOuterNew = new Rectangle( _innerRect.X - GRABHANDLE_WIDTH, _innerRect.Y - GRABHANDLE_HEIGHT, _innerRect.Width + 2 * GRABHANDLE_WIDTH, _innerRect.Height + 2 * GRABHANDLE_HEIGHT); + if (_outerRect.IsEmpty || !_outerRect.Equals(rcOuterNew)) + { + if (!_outerRect.IsEmpty) + Invalidate(); + _outerRect = rcOuterNew; + Invalidate(); + if (_region != null) + { + _region.Dispose(); + _region = null; + } + sizeChanged = true; + } + } + else + { + Rectangle rcNew = new Rectangle(0, 0, 0, 0); + sizeChanged = _outerRect.IsEmpty || !_outerRect.Equals(rcNew); + _innerRect = _outerRect = rcNew; + } + return sizeChanged; + } + } + + private class ContainerSelectionUIItem : SelectionUIItem + { + public const int CONTAINER_WIDTH = 13; + public const int CONTAINER_HEIGHT = 13; + + public ContainerSelectionUIItem(SelectionUIService selUIsvc, object component) : base(selUIsvc, component) + { + } + + public override Cursor GetCursorAtPoint(Point pt) + { + if ((GetHitTest(pt) & CONTAINER_SELECTOR) != 0 && (GetRules() & SelectionRules.Moveable) != SelectionRules.None) + { + return Cursors.SizeAll; + } + else + { + return null; + } + } + + public override int GetHitTest(Point pt) + { + int ht = NOHIT; + if ((GetRules() & SelectionRules.Visible) != SelectionRules.None && !_outerRect.IsEmpty) + { + Rectangle r = new Rectangle(_outerRect.X, _outerRect.Y, CONTAINER_WIDTH, CONTAINER_HEIGHT); + + if (r.Contains(pt)) + { + ht = CONTAINER_SELECTOR; + if ((GetRules() & SelectionRules.Moveable) != SelectionRules.None) + { + ht |= MOVE_X | MOVE_Y; + } + } + } + return ht; + } + + public override void DoPaint(Graphics gr) + { + // If we're not visible, then there's nothing to do... + if ((GetRules() & SelectionRules.Visible) == SelectionRules.None) + return; + Rectangle glyphBounds = new Rectangle(_outerRect.X, _outerRect.Y, CONTAINER_WIDTH, CONTAINER_HEIGHT); + ControlPaint.DrawContainerGrabHandle(gr, glyphBounds); + } + + public override Region GetRegion() + { + if (_region == null) + { + if ((GetRules() & SelectionRules.Visible) != SelectionRules.None && !_outerRect.IsEmpty) + { + Rectangle r = new Rectangle(_outerRect.X, _outerRect.Y, CONTAINER_WIDTH, CONTAINER_HEIGHT); + _region = new Region(r); + } + else + { + _region = new Region(new Rectangle(0, 0, 0, 0)); + } + } + return _region; + } + } + + private struct HitTestInfo + { + public readonly int hitTest; + public readonly SelectionUIItem selectionUIHit; + public readonly bool containerSelector; + + public HitTestInfo(int hitTest, SelectionUIItem selectionUIHit) + { + this.hitTest = hitTest; + this.selectionUIHit = selectionUIHit; + containerSelector = false; + } + + public HitTestInfo(int hitTest, SelectionUIItem selectionUIHit, bool containerSelector) + { + this.hitTest = hitTest; + this.selectionUIHit = selectionUIHit; + this.containerSelector = containerSelector; + } + + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + public override bool Equals(object obj) + { + try + { + HitTestInfo hi = (HitTestInfo)obj; + return hitTest == hi.hitTest && selectionUIHit == hi.selectionUIHit && containerSelector == hi.containerSelector; + } + catch (Exception ex) + { + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + return false; + } + + public static bool operator ==(HitTestInfo left, HitTestInfo right) + { + return (left.hitTest == right.hitTest && left.selectionUIHit == right.selectionUIHit && left.containerSelector == right.containerSelector); + } + + public static bool operator !=(HitTestInfo left, HitTestInfo right) => !(left == right); + + public override int GetHashCode() + { + int hash = hitTest | selectionUIHit.GetHashCode(); + if (containerSelector) + { + hash |= 0x10000; + } + return hash; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardCommandToolStripMenuItem.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardCommandToolStripMenuItem.cs new file mode 100644 index 00000000000..614d2ce5a32 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardCommandToolStripMenuItem.cs @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Design; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// Associates standard command with ToolStripMenuItem. + /// + internal class StandardCommandToolStripMenuItem : ToolStripMenuItem + { + private bool _cachedImage = false; + private Image _image = null; + private readonly CommandID _menuID; + private IMenuCommandService _menuCommandService; + private readonly IServiceProvider _serviceProvider; + private readonly string _name; + private readonly MenuCommand _menuCommand; + + // Ok to call MenuService.FindComand to find the menuCommand mapping to the appropriated menuID. + [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + public StandardCommandToolStripMenuItem(CommandID menuID, string text, string imageName, IServiceProvider serviceProvider) + { + _menuID = menuID; + _serviceProvider = serviceProvider; + // Findcommand can throw; so we need to catch and disable the command. + try + { + _menuCommand = MenuService.FindCommand(menuID); + } + catch + { + Enabled = false; + } + + Text = text; + _name = imageName; + + RefreshItem(); + } + + public void RefreshItem() + { + if (_menuCommand != null) + { + Visible = _menuCommand.Visible; + Enabled = _menuCommand.Enabled; + Checked = _menuCommand.Checked; + } + } + + /// + /// Retrieves the menu editor service, which we cache for speed. + /// + public IMenuCommandService MenuService + { + get + { + if (_menuCommandService == null) + { + _menuCommandService = (IMenuCommandService)_serviceProvider.GetService(typeof(IMenuCommandService)); + } + return _menuCommandService; + } + } + + public override Image Image + { + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + get + { + // Defer loading the image until we're sure we need it + if (!_cachedImage) + { + _cachedImage = true; + try + { + if (_name != null) + { + _image = new Icon(typeof(ToolStripMenuItem), _name + ".bmp").ToBitmap(); + } + ImageTransparentColor = Color.Magenta; + } + catch (Exception ex) + { + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + } + return _image; + } + set + { + _image = value; + _cachedImage = true; + } + } + + protected override void OnClick(System.EventArgs e) + { + if (_menuCommand != null) + { + _menuCommand.Invoke(); + } + else if (MenuService != null) + { + if (MenuService.GlobalInvoke(_menuID)) + { + return; + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs new file mode 100644 index 00000000000..28a32108b81 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + internal static class StandardGroups + { + public const string Code = "Code"; + public const string ZORder = "ZOrder"; + public const string Grid = "Grid"; + public const string Lock = "Lock"; + public const string Verbs = "Verbs"; + public const string Custom = "Custom"; + public const string Selection = "Selection"; + public const string Edit = "Edit"; + public const string Properties = "Properties"; + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardMenuStripVerb.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardMenuStripVerb.cs new file mode 100644 index 00000000000..a46ae2338f7 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardMenuStripVerb.cs @@ -0,0 +1,525 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Globalization; + +namespace System.Windows.Forms.Design +{ + /// + /// Internal class to provide 'Insert Standard Items" verb for ToolStrips & MenuStrips. + /// + internal class StandardMenuStripVerb + { + private readonly ToolStripDesigner _designer; + private readonly IDesignerHost _host; + private readonly IComponentChangeService _componentChangeSvc; + private readonly IServiceProvider _provider; + + /// + /// Create one of these things... + /// + internal StandardMenuStripVerb(ToolStripDesigner designer) + { + Debug.Assert(designer != null, "Can't have a StandardMenuStripVerb without an associated designer"); + _designer = designer; + _provider = designer.Component.Site; + _host = (IDesignerHost)_provider.GetService(typeof(IDesignerHost)); + _componentChangeSvc = (IComponentChangeService)_provider.GetService(typeof(IComponentChangeService)); + } + + /// + /// When the verb is invoked, use all the stuff above to show the dialog, etc. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public void InsertItems() + { + DesignerActionUIService actionUIService = (DesignerActionUIService)_host.GetService(typeof(DesignerActionUIService)); + if (actionUIService != null) + { + actionUIService.HideUI(_designer.Component); + } + Cursor current = Cursor.Current; + try + { + Cursor.Current = Cursors.WaitCursor; + if (_designer.Component is MenuStrip) + { + CreateStandardMenuStrip(_host, (MenuStrip)_designer.Component); + } + else + { + CreateStandardToolStrip(_host, (ToolStrip)_designer.Component); + } + } + finally + { + Cursor.Current = current; + } + } + + /// + /// Here is where all the fun stuff starts. We create the structure and apply the naming here. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void CreateStandardMenuStrip(System.ComponentModel.Design.IDesignerHost host, MenuStrip tool) + { + // build the static menu items structure. + string[][] menuItemNames = new string[][]{ + new string[]{SR.StandardMenuFile, SR.StandardMenuNew, SR.StandardMenuOpen, "-", SR.StandardMenuSave, SR.StandardMenuSaveAs, "-", SR.StandardMenuPrint, SR.StandardMenuPrintPreview, "-", SR.StandardMenuExit}, + new string[]{SR.StandardMenuEdit, SR.StandardMenuUndo, SR.StandardMenuRedo, "-", SR.StandardMenuCut, SR.StandardMenuCopy, SR.StandardMenuPaste, "-", SR.StandardMenuSelectAll}, + new string[]{SR.StandardMenuTools, SR.StandardMenuCustomize, SR.StandardMenuOptions}, + new string[]{SR.StandardMenuHelp, SR.StandardMenuContents, SR.StandardMenuIndex, SR.StandardMenuSearch, "-", SR.StandardMenuAbout } }; + + // build the static menu items image list that maps one-one with above menuItems structure. this is required so that the in LOCALIZED build we dont use the Localized item string. + string[][] menuItemImageNames = new string[][]{ + new string[]{"","new", "open", "-", "save", "", "-", "print", "printPreview", "-", ""}, + new string[]{"", "", "", "-", "cut", "copy", "paste", "-", ""}, + new string[]{"", "", ""}, + new string[]{"", "", "", "", "-", ""}}; + + Keys[][] menuItemShortcuts = new Keys[][]{ + new Keys[]{/*File*/Keys.None, /*New*/Keys.Control | Keys.N, /*Open*/Keys.Control | Keys.O, /*Separator*/ Keys.None, /*Save*/ Keys.Control | Keys.S, /*SaveAs*/Keys.None, Keys.None, /*Print*/ Keys.Control | Keys.P, /*PrintPreview*/ Keys.None, /*Separator*/Keys.None, /*Exit*/ Keys.None}, + new Keys[]{/*Edit*/Keys.None, /*Undo*/Keys.Control | Keys.Z, /*Redo*/Keys.Control | Keys.Y, /*Separator*/Keys.None, /*Cut*/ Keys.Control | Keys.X, /*Copy*/ Keys.Control | Keys.C, /*Paste*/Keys.Control | Keys.V, /*Separator*/ Keys.None, /*SelectAll*/Keys.None}, + new Keys[]{/*Tools*/Keys.None, /*Customize*/Keys.None, /*Options*/Keys.None}, + new Keys[]{/*Help*/Keys.None, /*Contents*/Keys.None, /*Index*/Keys.None, /*Search*/Keys.None,/*Separator*/Keys.None , /*About*/Keys.None}}; + + Debug.Assert(host != null, "can't create standard menu without designer _host."); + if (host == null) + { + return; + } + tool.SuspendLayout(); + ToolStripDesigner.s_autoAddNewItems = false; + // create a transaction so this happens as an atomic unit. + DesignerTransaction createMenu = _host.CreateTransaction(SR.StandardMenuCreateDesc); + try + { + INameCreationService nameCreationService = (INameCreationService)_provider.GetService(typeof(INameCreationService)); + string defaultName = "standardMainMenuStrip"; + string name = defaultName; + int index = 1; + + if (host != null) + { + while (_host.Container.Components[name] != null) + { + name = defaultName + (index++).ToString(CultureInfo.InvariantCulture); + } + } + + // now build the menu items themselves. + for (int j = 0; j < menuItemNames.Length; j++) + { + string[] menuArray = menuItemNames[j]; + ToolStripMenuItem rootItem = null; + for (int i = 0; i < menuArray.Length; i++) + { + name = null; + // for separators, just use the default name. Otherwise, remove any non-characters and get the name from the text. + string itemText = menuArray[i]; + name = NameFromText(itemText, typeof(ToolStripMenuItem), nameCreationService, true); + ToolStripItem item = null; + if (name.Contains("Separator")) + { + // create the componennt. + item = (ToolStripSeparator)_host.CreateComponent(typeof(ToolStripSeparator), name); + IDesigner designer = _host.GetDesigner(item); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + item.Text = itemText; + } + else + { + // create the componennt. + item = (ToolStripMenuItem)_host.CreateComponent(typeof(ToolStripMenuItem), name); + IDesigner designer = _host.GetDesigner(item); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + item.Text = itemText; + Keys shortcut = menuItemShortcuts[j][i]; + if ((item is ToolStripMenuItem) && shortcut != Keys.None) + { + if (!ToolStripManager.IsShortcutDefined(shortcut) && ToolStripManager.IsValidShortcut(shortcut)) + { + ((ToolStripMenuItem)item).ShortcutKeys = shortcut; + } + } + Bitmap image = null; + try + { + image = GetImage(menuItemImageNames[j][i]); + } + catch + { + // eat the exception.. as you may not find image for all MenuItems. + } + if (image != null) + { + PropertyDescriptor imageProperty = TypeDescriptor.GetProperties(item)["Image"]; + Debug.Assert(imageProperty != null, "Could not find 'Image' property in ToolStripItem."); + if (imageProperty != null) + { + imageProperty.SetValue(item, image); + } + item.ImageTransparentColor = Color.Magenta; + } + } + + // the first item in each array is the root item. + if (i == 0) + { + rootItem = (ToolStripMenuItem)item; + rootItem.DropDown.SuspendLayout(); + } + else + { + rootItem.DropDownItems.Add(item); + } + //If Last SubItem Added the Raise the Events + if (i == menuArray.Length - 1) + { + // member is OK to be null... + MemberDescriptor member = TypeDescriptor.GetProperties(rootItem)["DropDownItems"]; + _componentChangeSvc.OnComponentChanging(rootItem, member); + _componentChangeSvc.OnComponentChanged(rootItem, member, null, null); + } + } + + // finally, add it to the MainMenu. + rootItem.DropDown.ResumeLayout(false); + tool.Items.Add(rootItem); + //If Last SubItem Added the Raise the Events + if (j == menuItemNames.Length - 1) + { + // member is OK to be null... + MemberDescriptor topMember = TypeDescriptor.GetProperties(tool)["Items"]; + _componentChangeSvc.OnComponentChanging(tool, topMember); + _componentChangeSvc.OnComponentChanged(tool, topMember, null, null); + } + } + } + catch (Exception e) + { + if (e is InvalidOperationException) + { + IUIService uiService = (IUIService)_provider.GetService(typeof(IUIService)); + uiService.ShowError(e.Message); + } + if (createMenu != null) + { + createMenu.Cancel(); + createMenu = null; + } + } + finally + { + ToolStripDesigner.s_autoAddNewItems = true; + if (createMenu != null) + { + createMenu.Commit(); + createMenu = null; + } + tool.ResumeLayout(); + // Select the Main Menu... + ISelectionService selSvc = (ISelectionService)_provider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { _designer.Component }); + } + //Refresh the Glyph + DesignerActionUIService actionUIService = (DesignerActionUIService)_provider.GetService(typeof(DesignerActionUIService)); + if (actionUIService != null) + { + actionUIService.Refresh(_designer.Component); + } + // this will invalidate the Selection Glyphs. + SelectionManager selMgr = (SelectionManager)_provider.GetService(typeof(SelectionManager)); + selMgr.Refresh(); + } + } + + /// + /// Here is where all the fun stuff starts. We create the structure and apply the naming here. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void CreateStandardToolStrip(IDesignerHost host, ToolStrip tool) + { + + // build the static menu items structure. + // + string[] menuItemNames = new string[] { SR.StandardMenuNew, SR.StandardMenuOpen, SR.StandardMenuSave, SR.StandardMenuPrint, "-", SR.StandardToolCut, SR.StandardMenuCopy, SR.StandardMenuPaste, "-", SR.StandardToolHelp }; + + // build a image list mapping one-one the above menuItems list... this is required so that the in LOCALIZED build we dont use the Localized item string. + string[] menuItemImageNames = new string[] { "new", "open", "save", "print", "-", "cut", "copy", "paste", "-", "help" }; + Debug.Assert(host != null, "can't create standard menu without designer _host."); + + if (host == null) + { + return; + } + + tool.SuspendLayout(); + ToolStripDesigner.s_autoAddNewItems = false; + // create a transaction so this happens as an atomic unit. + DesignerTransaction createMenu = _host.CreateTransaction(SR.StandardMenuCreateDesc); + try + { + INameCreationService nameCreationService = (INameCreationService)_provider.GetService(typeof(INameCreationService)); + string defaultName = "standardMainToolStrip"; + string name = defaultName; + int index = 1; + if (host != null) + { + while (_host.Container.Components[name] != null) + { + name = defaultName + (index++).ToString(CultureInfo.InvariantCulture); + } + } + + //keep an index in the MenuItemImageNames .. so that mapping is maintained. + int menuItemImageNamesCount = 0; + // now build the menu items themselves. + foreach (string itemText in menuItemNames) + { + name = null; + // for separators, just use the default name. Otherwise, remove any non-characters and get the name from the text. + defaultName = "ToolStripButton"; + name = NameFromText(itemText, typeof(ToolStripButton), nameCreationService, true); + ToolStripItem item = null; + if (name.Contains("Separator")) + { + // create the componennt. + item = (ToolStripSeparator)_host.CreateComponent(typeof(ToolStripSeparator), name); + IDesigner designer = _host.GetDesigner(item); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + } + else + { + // create the component. + item = (ToolStripButton)_host.CreateComponent(typeof(ToolStripButton), name); + IDesigner designer = _host.GetDesigner(item); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + + PropertyDescriptor displayStyleProperty = TypeDescriptor.GetProperties(item)["DisplayStyle"]; + Debug.Assert(displayStyleProperty != null, "Could not find 'Text' property in ToolStripItem."); + if (displayStyleProperty != null) + { + displayStyleProperty.SetValue(item, ToolStripItemDisplayStyle.Image); + } + + PropertyDescriptor textProperty = TypeDescriptor.GetProperties(item)["Text"]; + Debug.Assert(textProperty != null, "Could not find 'Text' property in ToolStripItem."); + if (textProperty != null) + { + textProperty.SetValue(item, itemText); + } + + Bitmap image = null; + try + { + image = GetImage(menuItemImageNames[menuItemImageNamesCount]); + } + catch + { + // eat the exception.. as you may not find image for all MenuItems. + } + if (image != null) + { + PropertyDescriptor imageProperty = TypeDescriptor.GetProperties(item)["Image"]; + Debug.Assert(imageProperty != null, "Could not find 'Image' property in ToolStripItem."); + if (imageProperty != null) + { + imageProperty.SetValue(item, image); + } + item.ImageTransparentColor = Color.Magenta; + } + } + tool.Items.Add(item); + //increment the counter... + menuItemImageNamesCount++; + } + // finally, add it to the Main ToolStrip. + MemberDescriptor topMember = TypeDescriptor.GetProperties(tool)["Items"]; + _componentChangeSvc.OnComponentChanging(tool, topMember); + _componentChangeSvc.OnComponentChanged(tool, topMember, null, null); + } + catch (Exception e) + { + if (e is InvalidOperationException) + { + IUIService uiService = (IUIService)_provider.GetService(typeof(IUIService)); + uiService.ShowError(e.Message); + } + if (createMenu != null) + { + createMenu.Cancel(); + createMenu = null; + } + } + finally + { + //Reset the AutoAdd state + ToolStripDesigner.s_autoAddNewItems = true; + if (createMenu != null) + { + createMenu.Commit(); + createMenu = null; + } + tool.ResumeLayout(); + // Select the Main Menu... + ISelectionService selSvc = (ISelectionService)_provider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { _designer.Component }); + } + + //Refresh the Glyph + DesignerActionUIService actionUIService = (DesignerActionUIService)_provider.GetService(typeof(DesignerActionUIService)); + if (actionUIService != null) + { + actionUIService.Refresh(_designer.Component); + } + // this will invalidate the Selection Glyphs. + SelectionManager selMgr = (SelectionManager)_provider.GetService(typeof(SelectionManager)); + selMgr.Refresh(); + } + + } + + /// + /// Helper Function to get Images from types. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private Bitmap GetImage(string name) + { + Bitmap image = null; + if (name.StartsWith("new")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "new.bmp"); + } + else if (name.StartsWith("open")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "open.bmp"); + } + else if (name.StartsWith("save")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "save.bmp"); + } + else if (name.StartsWith("printPreview")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "printPreview.bmp"); + } + else if (name.StartsWith("print")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "print.bmp"); + } + else if (name.StartsWith("cut")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "cut.bmp"); + } + else if (name.StartsWith("copy")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "copy.bmp"); + } + else if (name.StartsWith("paste")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "paste.bmp"); + } + else if (name.StartsWith("help")) + { + image = new Bitmap(typeof(ToolStripMenuItem), "help.bmp"); + } + return image; + } + + /// + /// Computes a name from a text label by removing all spaces and non-alphanumeric characters. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private string NameFromText(string text, Type itemType, INameCreationService nameCreationService, bool adjustCapitalization) + { + string baseName; + // for separators, name them ToolStripSeparator... + if (text == "-") + { + baseName = "toolStripSeparator"; + } + else + { + string nameSuffix = itemType.Name; + // remove all the non letter and number characters. Append length of "MenuItem" + Text.StringBuilder name = new Text.StringBuilder(text.Length + nameSuffix.Length); + bool firstCharSeen = false; + for (int i = 0; i < text.Length; i++) + { + char c = text[i]; + if (char.IsLetterOrDigit(c)) + { + if (!firstCharSeen) + { + c = char.ToLower(c, CultureInfo.CurrentCulture); + firstCharSeen = true; + } + name.Append(c); + } + } + name.Append(nameSuffix); + baseName = name.ToString(); + if (adjustCapitalization) + { + string nameOfRandomItem = ToolStripDesigner.NameFromText(null, typeof(ToolStripMenuItem), _designer.Component.Site); + if (!string.IsNullOrEmpty(nameOfRandomItem) && char.IsUpper(nameOfRandomItem[0])) + { + baseName = char.ToUpper(baseName[0], CultureInfo.InvariantCulture) + baseName.Substring(1); + } + } + } + + // see if this name matches another one in the container.. + object existingComponent = _host.Container.Components[baseName]; + if (existingComponent == null) + { + if (!nameCreationService.IsValidName(baseName)) + { + // we don't have a name collision but this still isn't a valid name...something is wrong and we can't make a valid identifier out of this so bail. + return nameCreationService.CreateName(_host.Container, itemType); + } + else + { + return baseName; + } + } + else + { + // start appending numbers. + string newName = baseName; + for (int indexer = 1; !nameCreationService.IsValidName(newName); indexer++) + { + newName = baseName + indexer.ToString(CultureInfo.InvariantCulture); + } + return newName; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StatusCommandUI.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StatusCommandUI.cs new file mode 100644 index 00000000000..f2811d54a89 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StatusCommandUI.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// This class provides a single entrypoint used by the Behaviors, KeySize and KeyMoves (in CommandSets) and SelectionService to update the StatusBar Information. + /// + internal class StatusCommandUI + { + private MenuCommand _statusRectCommand = null; + private IMenuCommandService _menuService = null; + private readonly IServiceProvider _serviceProvider; + + public StatusCommandUI(IServiceProvider provider) + { + _serviceProvider = provider; + } + + /// + /// Retrieves the menu editor service, which we cache for speed. + /// + private IMenuCommandService MenuService + { + get + { + if (_menuService == null) + { + _menuService = (IMenuCommandService)_serviceProvider.GetService(typeof(IMenuCommandService)); + } + return _menuService; + } + } + + /// + /// Retrieves the actual StatusRectCommand, which we cache for speed. + /// + private MenuCommand StatusRectCommand + { + get + { + if (_statusRectCommand == null) + { + if (MenuService != null) + { + _statusRectCommand = MenuService.FindCommand(MenuCommands.SetStatusRectangle); + } + } + return _statusRectCommand; + } + } + + /// + /// Actual Function which invokes the command. + /// + public void SetStatusInformation(Component selectedComponent, Point location) + { + if (selectedComponent == null) + { + return; + } + Rectangle bounds = Rectangle.Empty; + if (selectedComponent is Control c) + { + bounds = c.Bounds; + } + else + { + PropertyDescriptor BoundsProp = TypeDescriptor.GetProperties(selectedComponent)["Bounds"]; + if (BoundsProp != null && typeof(Rectangle).IsAssignableFrom(BoundsProp.PropertyType)) + { + bounds = (Rectangle)BoundsProp.GetValue(selectedComponent); + } + } + if (location != Point.Empty) + { + bounds.X = location.X; + bounds.Y = location.Y; + } + if (StatusRectCommand != null) + { + StatusRectCommand.Invoke(bounds); + } + } + + /// + /// Actual Function which invokes the command. + /// + public void SetStatusInformation(Component selectedComponent) + { + if (selectedComponent == null) + { + return; + } + Rectangle bounds = Rectangle.Empty; + if (selectedComponent is Control c) + { + bounds = c.Bounds; + } + else + { + PropertyDescriptor BoundsProp = TypeDescriptor.GetProperties(selectedComponent)["Bounds"]; + if (BoundsProp != null && typeof(Rectangle).IsAssignableFrom(BoundsProp.PropertyType)) + { + bounds = (Rectangle)BoundsProp.GetValue(selectedComponent); + } + } + if (StatusRectCommand != null) + { + StatusRectCommand.Invoke(bounds); + } + } + + /// + /// Actual Function which invokes the command. + /// + public void SetStatusInformation(Rectangle bounds) + { + if (StatusRectCommand != null) + { + StatusRectCommand.Invoke(bounds); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/TemplateNodeCustomMenuItemCollection.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/TemplateNodeCustomMenuItemCollection.cs new file mode 100644 index 00000000000..42edc647079 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/TemplateNodeCustomMenuItemCollection.cs @@ -0,0 +1,167 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// Custom ContextMenu section for ToolStripMenuItems. + /// + internal class TemplateNodeCustomMenuItemCollection : CustomMenuItemCollection + { + private readonly ToolStripItem _currentItem; + private readonly IServiceProvider _serviceProvider; + private ToolStripMenuItem _insertToolStripMenuItem; + + public TemplateNodeCustomMenuItemCollection(IServiceProvider provider, Component currentItem) : base() + { + _serviceProvider = provider; + _currentItem = currentItem as ToolStripItem; + PopulateList(); + } + + /// + /// Immediate parent - can be ToolStrip if the Item is on the toplevel + /// + private ToolStrip ParentTool + { + get => _currentItem.Owner; + } + + private void PopulateList() + { + _insertToolStripMenuItem = new ToolStripMenuItem + { + Text = SR.ToolStripItemContextMenuInsert, + DropDown = ToolStripDesignerUtils.GetNewItemDropDown(ParentTool, _currentItem, new EventHandler(AddNewItemClick), false, _serviceProvider, true) + }; + Add(_insertToolStripMenuItem); + } + + private void AddNewItemClick(object sender, EventArgs e) + { + ItemTypeToolStripMenuItem senderItem = (ItemTypeToolStripMenuItem)sender; + Type t = senderItem.ItemType; + // we are inserting a new item.. + InsertItem(t); + } + + private void InsertItem(Type t) + { + InsertToolStripItem(t); + } + + /// + /// Insert Item into ToolStrip. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void InsertToolStripItem(Type t) + { + IDesignerHost designerHost = (IDesignerHost)_serviceProvider.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + ToolStrip parent = ParentTool; + int dummyIndex = parent.Items.IndexOf(_currentItem); + DesignerTransaction newItemTransaction = designerHost.CreateTransaction(SR.ToolStripAddingItem); + try + { + // turn off Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = false; + // the code in ComponentAdded will actually get the add done. + IComponent component = designerHost.CreateComponent(t); + IDesigner designer = designerHost.GetDesigner(component); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + + //Set the Image property and DisplayStyle... + if (component is ToolStripButton || component is ToolStripSplitButton || component is ToolStripDropDownButton) + { + Image image = null; + try + { + image = new Bitmap(typeof(ToolStripButton), "blank.bmp"); + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + + PropertyDescriptor imageProperty = TypeDescriptor.GetProperties(component)["Image"]; + Debug.Assert(imageProperty != null, "Could not find 'Image' property in ToolStripItem."); + if (imageProperty != null && image != null) + { + imageProperty.SetValue(component, image); + } + + PropertyDescriptor dispProperty = TypeDescriptor.GetProperties(component)["DisplayStyle"]; + Debug.Assert(dispProperty != null, "Could not find 'DisplayStyle' property in ToolStripItem."); + if (dispProperty != null) + { + dispProperty.SetValue(component, ToolStripItemDisplayStyle.Image); + } + + PropertyDescriptor imageTransProperty = TypeDescriptor.GetProperties(component)["ImageTransparentColor"]; + Debug.Assert(imageTransProperty != null, "Could not find 'DisplayStyle' property in ToolStripItem."); + if (imageTransProperty != null) + { + imageTransProperty.SetValue(component, Color.Magenta); + } + } + Debug.Assert(dummyIndex != -1, "Why is the index of the Item negative?"); + parent.Items.Insert(dummyIndex, (ToolStripItem)component); + // set the selection to our new item.. since we destroyed Original component.. we have to ask SelectionServive from new Component + ISelectionService selSvc = (ISelectionService)_serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { component }, SelectionTypes.Replace); + } + } + catch (Exception ex) + { + if (newItemTransaction != null) + { + newItemTransaction.Cancel(); + newItemTransaction = null; + } + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + finally + { + if (newItemTransaction != null) + { + newItemTransaction.Commit(); + newItemTransaction = null; + } + // turn off Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = true; + // Add the glyphs if the parent is DropDown. + if (parent is ToolStripDropDown parentDropDown && parentDropDown.Visible) + { + if (parentDropDown.OwnerItem is ToolStripDropDownItem ownerItem) + { + ToolStripMenuItemDesigner itemDesigner = designerHost.GetDesigner(ownerItem) as ToolStripMenuItemDesigner; + if (itemDesigner != null) + { + itemDesigner.ResetGlyphs(ownerItem); + } + } + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/TemplateNodeSelectionState.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/TemplateNodeSelectionState.cs new file mode 100644 index 00000000000..82f5b104805 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/TemplateNodeSelectionState.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + internal enum TemplateNodeSelectionState + { + None = 0, + TemplateNodeSelected = 1, + SplitButtonSelected = 2, + DropDownSelected = 3, + MouseOverLabel = 4, + MouseOverHotRegion = 5, + HotRegionSelected = 6 + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs new file mode 100644 index 00000000000..af40c680ac9 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + public enum ThemedScrollbarMode + { + /// + /// The window and all of its children will have themed scrollbars + /// + All = 1, + + /// + /// The window and all of its children will be un-themed + /// + None = 2, + + /// + /// The window will have themed scrollbars but all of its children will be un-themed + /// + OnlyTopLevel = 3 + }; +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs new file mode 100644 index 00000000000..24a3fcf8ebf --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + public struct ThemedScrollbarWindow + { + public IntPtr Handle; + public ThemedScrollbarMode Mode; + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripActionList.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripActionList.cs new file mode 100644 index 00000000000..ab52e75b0c9 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripActionList.cs @@ -0,0 +1,196 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Windows.Forms.Design +{ + internal class ToolStripActionList : DesignerActionList + { + private readonly ToolStrip _toolStrip; + private bool _autoShow = false; + private readonly ToolStripDesigner _designer; + + private ChangeToolStripParentVerb _changeParentVerb = null; + private StandardMenuStripVerb _standardItemsVerb = null; + + public ToolStripActionList(ToolStripDesigner designer) : base(designer.Component) + { + _toolStrip = (ToolStrip)designer.Component; + this._designer = designer; + + _changeParentVerb = new ChangeToolStripParentVerb(string.Format(SR.ToolStripDesignerEmbedVerb), designer); + if (!(_toolStrip is StatusStrip)) + { + _standardItemsVerb = new StandardMenuStripVerb(designer); + } + } + + /// + /// False if were inherited and can't be modified. + /// + private bool CanAddItems + { + get + { + // Make sure the component is not being inherited -- we can't delete these! + InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(_toolStrip)[typeof(InheritanceAttribute)]; + if (ia == null || ia.InheritanceLevel == InheritanceLevel.NotInherited) + { + return true; + } + return false; + } + } + + private bool IsReadOnly + { + get + { + // Make sure the component is not being inherited -- we can't delete these! + InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(_toolStrip)[typeof(InheritanceAttribute)]; + if (ia == null || ia.InheritanceLevel == InheritanceLevel.InheritedReadOnly) + { + return true; + } + return false; + } + } + + //helper function to get the property on the actual Control + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private object GetProperty(string propertyName) + { + PropertyDescriptor getProperty = TypeDescriptor.GetProperties(_toolStrip)[propertyName]; + Debug.Assert(getProperty != null, "Could not find given property in control."); + if (getProperty != null) + { + return getProperty.GetValue(_toolStrip); + } + return null; + } + + //helper function to change the property on the actual Control + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private void ChangeProperty(string propertyName, object value) + { + PropertyDescriptor changingProperty = TypeDescriptor.GetProperties(_toolStrip)[propertyName]; + Debug.Assert(changingProperty != null, "Could not find given property in control."); + if (changingProperty != null) + { + changingProperty.SetValue(_toolStrip, value); + } + } + + /// + /// Controls whether the Chrome is Automatically shown on selection + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public override bool AutoShow + { + get => _autoShow; + set + { + if (_autoShow != value) + { + _autoShow = value; + } + } + } + + public DockStyle Dock + { + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + get => (DockStyle)GetProperty("Dock"); + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + set + { + if (value != Dock) + { + ChangeProperty("Dock", (object)value); + } + } + } + + public ToolStripRenderMode RenderMode + { + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + get => (ToolStripRenderMode)GetProperty("RenderMode"); + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + set + { + if (value != RenderMode) + { + ChangeProperty("RenderMode", (object)value); + } + } + } + + public ToolStripGripStyle GripStyle + { + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + get => (ToolStripGripStyle)GetProperty("GripStyle"); + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + set + { + if (value != GripStyle) + { + ChangeProperty("GripStyle", (object)value); + } + } + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private void InvokeEmbedVerb() + { + // Hide the Panel... + DesignerActionUIService actionUIService = (DesignerActionUIService)_toolStrip.Site.GetService(typeof(DesignerActionUIService)); + if (actionUIService != null) + { + actionUIService.HideUI(_toolStrip); + } + _changeParentVerb.ChangeParent(); + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + private void InvokeInsertStandardItemsVerb() + { + _standardItemsVerb.InsertItems(); + } + + /// + /// The Main method to group the ActionItems and pass it to the Panel. + /// + public override DesignerActionItemCollection GetSortedActionItems() + { + DesignerActionItemCollection items = new DesignerActionItemCollection(); + if (!IsReadOnly) + { + items.Add(new DesignerActionMethodItem(this, "InvokeEmbedVerb", SR.ToolStripDesignerEmbedVerb, "", SR.ToolStripDesignerEmbedVerbDesc, true)); + } + + if (CanAddItems) + { + if (!(_toolStrip is StatusStrip)) + { + items.Add(new DesignerActionMethodItem(this, "InvokeInsertStandardItemsVerb", SR.ToolStripDesignerStandardItemsVerb, "", SR.ToolStripDesignerStandardItemsVerbDesc, true)); + } + items.Add(new DesignerActionPropertyItem("RenderMode", SR.ToolStripActionList_RenderMode, SR.ToolStripActionList_Layout, SR.ToolStripActionList_RenderModeDesc)); + } + + if (!(_toolStrip.Parent is ToolStripPanel)) + { + items.Add(new DesignerActionPropertyItem("Dock", SR.ToolStripActionList_Dock, SR.ToolStripActionList_Layout, SR.ToolStripActionList_DockDesc)); + } + if (!(_toolStrip is StatusStrip)) + { + items.Add(new DesignerActionPropertyItem("GripStyle", SR.ToolStripActionList_GripStyle, SR.ToolStripActionList_Layout, SR.ToolStripActionList_GripStyleDesc)); + } + return items; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripAdornerWindowService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripAdornerWindowService.cs new file mode 100644 index 00000000000..aba8a8562e6 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripAdornerWindowService.cs @@ -0,0 +1,310 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// Transparent Window to parent the DropDowns. + /// + internal sealed class ToolStripAdornerWindowService : IDisposable + { + private readonly IServiceProvider _serviceProvider; //standard service provider + private readonly ToolStripAdornerWindow _toolStripAdornerWindow; //the transparent window all glyphs are drawn to + private BehaviorService _behaviorService; + private Adorner _dropDownAdorner; + private ArrayList _dropDownCollection; + private readonly IOverlayService _overlayService; + + /// + /// This constructor is called from DocumentDesigner's Initialize method. + /// + internal ToolStripAdornerWindowService(IServiceProvider serviceProvider, Control windowFrame) + { + _serviceProvider = serviceProvider; + //create the AdornerWindow + _toolStripAdornerWindow = new ToolStripAdornerWindow(windowFrame); + _behaviorService = (BehaviorService)serviceProvider.GetService(typeof(BehaviorService)); + int indexToInsert = _behaviorService.AdornerWindowIndex; + + //use the adornerWindow as an overlay + _overlayService = (IOverlayService)serviceProvider.GetService(typeof(IOverlayService)); + if (_overlayService != null) + { + _overlayService.InsertOverlay(_toolStripAdornerWindow, indexToInsert); + } + + _dropDownAdorner = new Adorner(); + int count = _behaviorService.Adorners.Count; + + // Why this is NEEDED ? To Add the Adorner at proper index in the AdornerCollection for the BehaviorService. So that the DesignerActionGlyph always stays on the Top. + if (count > 1) + { + _behaviorService.Adorners.Insert(count - 1, _dropDownAdorner); + } + } + + /// + /// Returns the actual Control that represents the transparent AdornerWindow. + /// + internal Control ToolStripAdornerWindowControl + { + get => _toolStripAdornerWindow; + } + + /// + /// Creates and returns a Graphics object for the AdornerWindow + /// + public Graphics ToolStripAdornerWindowGraphics + { + get => _toolStripAdornerWindow.CreateGraphics(); + } + + internal Adorner DropDownAdorner + { + get => _dropDownAdorner; + } + + /// + /// Disposes the behavior service. + /// + [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] + public void Dispose() + { + if (_overlayService != null) + { + _overlayService.RemoveOverlay(_toolStripAdornerWindow); + } + _toolStripAdornerWindow.Dispose(); + if (_behaviorService != null) + { + _behaviorService.Adorners.Remove(_dropDownAdorner); + _behaviorService = null; + } + if (_dropDownAdorner != null) + { + _dropDownAdorner.Glyphs.Clear(); + _dropDownAdorner = null; + } + } + + /// + /// Translates a point in the AdornerWindow to screen coords. + /// + public Point AdornerWindowPointToScreen(Point p) + { + NativeMethods.POINT offset = new NativeMethods.POINT(p.X, p.Y); + NativeMethods.MapWindowPoints(_toolStripAdornerWindow.Handle, IntPtr.Zero, offset, 1); + return new Point(offset.x, offset.y); + } + + /// + /// Gets the location (upper-left corner) of the AdornerWindow in screen coords. + /// + public Point AdornerWindowToScreen() + { + Point origin = new Point(0, 0); + return AdornerWindowPointToScreen(origin); + } + + /// + /// Returns the location of a Control translated to AdornerWidnow coords. + /// + public Point ControlToAdornerWindow(Control c) + { + if (c.Parent == null) + { + return Point.Empty; + } + NativeMethods.POINT pt = new NativeMethods.POINT + { + x = c.Left, + y = c.Top + }; + NativeMethods.MapWindowPoints(c.Parent.Handle, _toolStripAdornerWindow.Handle, pt, 1); + return new Point(pt.x, pt.y); + } + + /// + /// Invalidates the BehaviorService's AdornerWindow. This will force a refesh of all Adorners and, in turn, all Glyphs. + /// + public void Invalidate() + { + _toolStripAdornerWindow.InvalidateAdornerWindow(); + } + + /// + /// Invalidates the BehaviorService's AdornerWindow. This will force a refesh of all Adorners and, in turn, all Glyphs. + /// + public void Invalidate(Rectangle rect) + { + _toolStripAdornerWindow.InvalidateAdornerWindow(rect); + } + + /// + /// Invalidates the BehaviorService's AdornerWindow. This will force a refesh of all Adorners and, in turn, all Glyphs. + /// + public void Invalidate(Region r) + { + _toolStripAdornerWindow.InvalidateAdornerWindow(r); + } + + internal ArrayList DropDowns + { + get => _dropDownCollection; + set + { + if (_dropDownCollection == null) + { + _dropDownCollection = new ArrayList(); + } + } + + } + + /// + /// ControlDesigner calls this internal method in response to a WmPaint. We need to know when a ControlDesigner paints - 'cause we will need to re-paint any glyphs above of this Control. + /// + internal void ProcessPaintMessage(Rectangle paintRect) + { + // Note, we don't call BehSvc.Invalidate because this will just cause the messages to recurse. Instead, invalidating this adornerWindow will just cause a "propagatePaint" and draw the glyphs. + _toolStripAdornerWindow.Invalidate(paintRect); + } + + /// + /// The AdornerWindow is a transparent window that resides ontop of the Designer's Frame. This window is used by the ToolStripAdornerWindowService to parent the MenuItem DropDowns. + /// + private class ToolStripAdornerWindow : Control + { + private Control _designerFrame; //the designer's frame + + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + internal ToolStripAdornerWindow(Control designerFrame) + { + _designerFrame = designerFrame; + Dock = DockStyle.Fill; + AllowDrop = true; + Text = "ToolStripAdornerWindow"; + SetStyle(ControlStyles.Opaque, true); + } + + /// + /// The key here is to set the appropriate TransparetWindow style. + /// + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.Style &= ~(NativeMethods.WS_CLIPCHILDREN | NativeMethods.WS_CLIPSIBLINGS); + cp.ExStyle |= NativeMethods.WS_EX_TRANSPARENT; + return cp; + } + } + + /// + /// We'll use CreateHandle as our notification for creating our mouse hooker. + /// + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + } + + /// + /// Unhook and null out our mouseHook. + /// + protected override void OnHandleDestroyed(EventArgs e) + { + base.OnHandleDestroyed(e); + } + + /// + /// Null out our mouseHook and unhook any events. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_designerFrame != null) + { + _designerFrame = null; + } + + } + base.Dispose(disposing); + } + + /// + /// Returns true if the DesignerFrame is created & not being disposed. + /// + private bool DesignerFrameValid + { + get + { + if (_designerFrame == null || _designerFrame.IsDisposed || !_designerFrame.IsHandleCreated) + { + return false; + } + return true; + } + } + + /// + /// Invalidates the transparent AdornerWindow by asking the Designer Frame beneath it to invalidate. Note the they use of the .Update() call for perf. purposes. + /// + internal void InvalidateAdornerWindow() + { + if (DesignerFrameValid) + { + _designerFrame.Invalidate(true); + _designerFrame.Update(); + } + } + + /// + /// Invalidates the transparent AdornerWindow by asking the Designer Frame beneath it to invalidate. Note the they use of the .Update() call for perf. purposes. + /// + internal void InvalidateAdornerWindow(Region region) + { + if (DesignerFrameValid) + { + _designerFrame.Invalidate(region, true); + _designerFrame.Update(); + } + } + + /// + /// Invalidates the transparent AdornerWindow by asking the Designer Frame beneath it to invalidate. Note the they use of the .Update() call for perf. purposes. + /// + internal void InvalidateAdornerWindow(Rectangle rectangle) + { + if (DesignerFrameValid) + { + _designerFrame.Invalidate(rectangle, true); + _designerFrame.Update(); + } + } + + /// + /// The AdornerWindow intercepts all designer-related messages and forwards them to the BehaviorService for appropriate actions. Note that Paint and HitTest messages are correctly parsed and translated to AdornerWindow coords. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_NCHITTEST: + m.Result = (IntPtr)(NativeMethods.HTTRANSPARENT); + break; + default: + base.WndProc(ref m); + break; + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDesigner.cs new file mode 100644 index 00000000000..51c57b7a746 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDesigner.cs @@ -0,0 +1,2551 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Design; +using System.Globalization; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// Designer for the ToolStrip class. + /// + internal class ToolStripDesigner : ControlDesigner + { + private const int GLYPHBORDER = 2; + internal static Point s_lastCursorPosition = Point.Empty; //remembers last cursorPosition; + internal static bool s_autoAddNewItems = true; // true to force newly created items to be added to the currently selected strip. + internal static ToolStripItem s_dragItem = null; // this is used in overflow to know current item selected while drag, so that we can get the drop-index. + internal static bool s_shiftState = false; // maintains the shift state used of invalidation. disable csharp compiler warning #0414: field assigned unused value +#pragma warning disable 0414 + internal static bool s_editTemplateNode = false; // this is used in selection changed so that unnecessary redraw is not required. +#pragma warning restore 0414 + private DesignerToolStripControlHost _editorNode = null; //new editorNode + private ToolStripEditorManager _editManager = null; // newly added editor manager ... + private ToolStrip _miniToolStrip = null;// the toolStrip that hosts the "New Template Node" button + private DesignerTransaction _insertMenuItemTransaction = null; //There Should be one and only one Pending insertTransaction. + private Rectangle _dragBoxFromMouseDown = Rectangle.Empty; //Needed to Store the DRAGDROP Rect from the ToolStripItemBehavior. + private int _indexOfItemUnderMouseToDrag = -1; //defaulted to invalid index andwill be set by the behaviour. + private ToolStripTemplateNode _tn = null; //templateNode + private ISelectionService _selectionSvc = null; // cached selection service. + private uint _editingCollection = 0; // non-zero if the collection editor is up for this ToolStrip or a child of it. + private DesignerTransaction _pendingTransaction = null; // our transaction for adding/removing items. + private bool _addingItem = false; // true if we are expecting to be notified of adding a ToolStripItem to the designer. + private Rectangle _boundsToInvalidate = Rectangle.Empty; //Bounds to Invalidate if a DropDownItem is Deleted + private bool _currentVisible = true; // Change Visibility + private ToolStripActionList _actionLists; // Action List on Chrome... + private ToolStripAdornerWindowService _toolStripAdornerWindowService = null; // Add the Adorner Service for OverFlow DropDown... + private IDesignerHost _host = null;//get private copy of the DesignerHost + private IComponentChangeService _componentChangeSvc; + private bool _undoingCalled = false; + private IToolboxService _toolboxService; + private ContextMenuStrip _toolStripContextMenu; + private bool _toolStripSelected = false; + private bool _cacheItems = false; //ToolStripDesigner would cache items for the MenuItem when dropdown is changed. + private ArrayList _items; //cached Items. + private bool _disposed = false; + private DesignerTransaction _newItemTransaction; + private bool _fireSyncSelection = false; //fires SyncSelection when we toggle the items visibility to add the glyphs after the item gets visible. + private ToolStripKeyboardHandlingService _keyboardHandlingService = null; + private bool _parentNotVisible = false; //sync the parent visibility (used for ToolStripPanels) + private bool _dontCloseOverflow = false; //When an item is added to the ToolStrip through the templateNode which is on the Overflow; we should not close the overflow (to avoid flicker) + private bool _addingDummyItem = false; //When the dummyItem is added the toolStrip might resize (as in the Vertival Layouts). In this case we dont want the Resize to cause SyncSelection and Layouts. + + /// + /// Adds designer actions to the ActionLists collection. + /// + public override DesignerActionListCollection ActionLists + { + get + { + DesignerActionListCollection actionLists = new DesignerActionListCollection(); + actionLists.AddRange(base.ActionLists); + if (_actionLists == null) + { + _actionLists = new ToolStripActionList(this); + } + actionLists.Add(_actionLists); + + // First add the verbs for this component there... + DesignerVerbCollection verbs = Verbs; + if (verbs != null && verbs.Count != 0) + { + DesignerVerb[] verbsArray = new DesignerVerb[verbs.Count]; + verbs.CopyTo(verbsArray, 0); + actionLists.Add(new DesignerActionVerbList(verbsArray)); + } + return actionLists; + } + } + + /// + /// Compute the rect for the "Add New Item" button. + /// + private Rectangle AddItemRect + { + get + { + Rectangle rect = new Rectangle(); + if (_miniToolStrip == null) + { + return rect; + } + rect = _miniToolStrip.Bounds; + return rect; + } + } + + /// + /// Accessor for Shadow Property for AllowDrop. + /// + private bool AllowDrop + { + get => (bool)ShadowProperties["AllowDrop"]; + set + { + if (value && AllowItemReorder) + { + throw new ArgumentException(SR.ToolStripAllowItemReorderAndAllowDropCannotBeSetToTrue); + } + ShadowProperties["AllowDrop"] = value; + } + } + + /// + /// Accessor for Shadow Property for AllowItemReorder. + /// + private bool AllowItemReorder + { + get => (bool)ShadowProperties["AllowItemReorder"]; + set + { + if (value && AllowDrop) + { + throw new ArgumentException(SR.ToolStripAllowItemReorderAndAllowDropCannotBeSetToTrue); + } + ShadowProperties["AllowItemReorder"] = value; + } + } + + /// + /// The ToolStripItems are the associated components. We want those to come with in any cut, copy opreations. + /// + public override System.Collections.ICollection AssociatedComponents + { + get + { + ArrayList items = new ArrayList(); + foreach (ToolStripItem item in ToolStrip.Items) + { + if (!(item is DesignerToolStripControlHost addNewItem)) + { + items.Add(item); + } + } + return (ICollection)items; + } + } + + /// + /// CacheItems is set to TRUE by the ToolStripMenuItemDesigner, when the Transaction of setting the DropDown property is undone. In this case the Undo adds the original items to the Main MenustripDesigners Items collection and later are moved to to the appropriate ToolStripMenuItem + /// + public bool CacheItems + { + get => _cacheItems; + set => _cacheItems = value; + } + + /// + /// False if were inherited and can't be modified. + /// + private bool CanAddItems + { + get + { + // Make sure the component is not being inherited -- we can't delete these! + InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(ToolStrip)[typeof(InheritanceAttribute)]; + if (ia == null || ia.InheritanceLevel == InheritanceLevel.NotInherited) + { + return true; + } + return false; + } + } + + /// + // This boolean indicates whether the Control will allow SnapLines to be shown when any other targetControl is dragged on the design surface. This is true by default. + /// + internal override bool ControlSupportsSnaplines + { + get + { + if (!(ToolStrip.Parent is ToolStripPanel)) + { + return true; + } + return false; + } + } + + /// + /// DesignerContextMenu that is shown on the ToolStrip/MenuStrip/StatusStrip. + /// + private ContextMenuStrip DesignerContextMenu + { + get + { + if (_toolStripContextMenu == null) + { + _toolStripContextMenu = new BaseContextMenuStrip(ToolStrip.Site, ToolStrip) + { + Text = "CustomContextMenu" + }; + } + return _toolStripContextMenu; + } + } + + /// + /// Used by ToolStripTemplateNode. When the ToolStrip gains selection the Overflow is closed. But when an item is added through the TemplateNode which itself is on the Overflow, we should not close the Overflow as this caused weird artifacts and flicker. Hence this boolean property. + /// + public bool DontCloseOverflow + { + get => _dontCloseOverflow; + set => _dontCloseOverflow = value; + } + + /// + /// Since the Itemglyphs are recreated on the SelectionChanged, we need to cache in the "MouseDown" while the item Drag-Drop operation. + /// + public Rectangle DragBoxFromMouseDown + { + get => _dragBoxFromMouseDown; + set => _dragBoxFromMouseDown = value; + } + + /// + /// Set by the ToolStripItemCollectionEditor when it's launched for this ToolStrip so we won't pick up it's items when added. We count this so that we can deal with nestings. + /// + internal bool EditingCollection + { + get => _editingCollection != 0; + set + { + if (value) + { + _editingCollection++; + } + else + { + _editingCollection--; + } + + } + } + + /// + /// EditManager for the ToolStrip Designer. This EditorManager controls the Insitu Editing. + /// + public ToolStripEditorManager EditManager + { + get => _editManager; + } + + /// + /// The TemplateNode. This is the object that actually creates miniToolStrip and manages InSitu editing. + /// + internal ToolStripTemplateNode Editor + { + get => _tn; + } + + /// + /// This is the ToolStripControlHost that hosts the ToolStripTemplateNode's miniToolStrip. + /// + public DesignerToolStripControlHost EditorNode + { + get => _editorNode; + } + + /// + /// This is the ToolStripTemplateNode's miniToolStrip. + /// + internal ToolStrip EditorToolStrip + { + get => _miniToolStrip; + set + { + _miniToolStrip = value; + _miniToolStrip.Parent = ToolStrip; + LayoutToolStrip(); + } + } + + /// + /// This will be set through ToolStripItemDesigner.SetItemVisible( ) if we find there is atleast one time that toggled from Visible==false to Visible==true In such a case we need to call BehaviorService.SyncSelection( ) toupdate the glyphs. + /// + public bool FireSyncSelection + { + get => _fireSyncSelection; + set => _fireSyncSelection = value; + } + + /// + /// Since the Itemglyphs are recreated on the SelectionChanged, we need to cache in the "index" of last MouseDown while the item Drag-Drop operation. + /// + public int IndexOfItemUnderMouseToDrag + { + get => _indexOfItemUnderMouseToDrag; + set => _indexOfItemUnderMouseToDrag = value; + } + + /// + /// ToolStrips if inherited act as ReadOnly. + /// + protected override InheritanceAttribute InheritanceAttribute + { + get + { + if ((base.InheritanceAttribute == InheritanceAttribute.Inherited)) + { + return InheritanceAttribute.InheritedReadOnly; + } + return base.InheritanceAttribute; + } + } + + /// + /// This is the insert Transaction. Now insert can happen at Main Menu level or the DropDown Level. This transaction is used to keep both in sync. + /// + public DesignerTransaction InsertTansaction + { + get => _insertMenuItemTransaction; + set => _insertMenuItemTransaction = value; + } + + /// + /// Checks if there is a seleciton of the ToolStrip or one of it's items. + /// + private bool IsToolStripOrItemSelected + { + get => _toolStripSelected; + } + + /// + /// CacheItems is set to TRUE by the ToolStripMenuItemDesigner, when the Transaction of setting the DropDown property is undone. In this case the Undo adds the original items to the Main MenustripDesigners Items collection and later are moved to to the appropriate ToolStripMenuItem. This is the Items Collection. + /// + public ArrayList Items + { + get + { + if (_items == null) + { + _items = new ArrayList(); + } + return _items; + } + } + + /// + /// This is the new item Transaction. This is used when the Insitu editor adds new Item. + /// + public DesignerTransaction NewItemTransaction + { + get => _newItemTransaction; + set => _newItemTransaction = value; + } + + /// + /// Compute the rect for the "OverFlow" button. + /// + private Rectangle OverFlowButtonRect + { + get + { + Rectangle rect = new Rectangle(); + if (ToolStrip.OverflowButton.Visible) + { + return ToolStrip.OverflowButton.Bounds; + } + else + { + return rect; + } + } + } + + /// + /// Get and cache the selection service + /// + internal ISelectionService SelectionService + { + get + { + if (_selectionSvc == null) + { + _selectionSvc = (ISelectionService)GetService(typeof(ISelectionService)); + Debug.Assert(_selectionSvc != null, "Failed to get Selection Service!"); + } + return _selectionSvc; + } + } + + public bool SupportEditing + { + get + { + if (GetService(typeof(DesignerOptionService)) is WindowsFormsDesignerOptionService dos) + { + return dos.CompatibilityOptions.EnableInSituEditing; + } + return true; + } + } + + /// + /// Handy way of gettting our ToolStrip + /// + protected ToolStrip ToolStrip + { + get => (ToolStrip)Component; + } + + /// + /// Get and cache the toolStripKeyBoard service + /// + private ToolStripKeyboardHandlingService KeyboardHandlingService + { + get + { + if (_keyboardHandlingService == null) + { + //Add the EditService so that the ToolStrip can do its own Tab and Keyboard Handling + _keyboardHandlingService = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (_keyboardHandlingService == null) + { + _keyboardHandlingService = new ToolStripKeyboardHandlingService(Component.Site); + } + } + return _keyboardHandlingService; + } + } + + /// + /// There are certain containers (like ToolStrip) that require PerformLayout to be serialized in the code gen. + /// + internal override bool SerializePerformLayout + { + get => true; + } + + /// + /// Un - ShadowProperty. + /// + internal bool Visible + { + get => _currentVisible; + set + { + _currentVisible = value; + // If the user has set the Visible to false, sync the controls visible property. + if (ToolStrip.Visible != value && !SelectionService.GetComponentSelected(ToolStrip)) + { + Control.Visible = value; + } + } + } + + /// + /// This will add BodyGlyphs for the Items on the OverFlow. Since ToolStripItems are component we have to manage Adding and Deleting the glyphs ourSelves. + /// + private void AddBodyGlyphsForOverflow() + { + // now walk the ToolStrip and add glyphs for each of it's children + foreach (ToolStripItem item in ToolStrip.Items) + { + if (item is DesignerToolStripControlHost) + { + continue; + } + // make sure it's on the Overflow... + if (item.Placement == ToolStripItemPlacement.Overflow) + { + AddItemBodyGlyph(item); + } + } + } + + /// + /// This will add BodyGlyphs for the Items on the OverFlow. Since ToolStripItems are component we have to manage Adding and Deleting the glyphs ourSelves. Called by AddBodyGlyphsForOverflow() + /// + private void AddItemBodyGlyph(ToolStripItem item) + { + if (item != null) + { + ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item); + if (dropDownItemDesigner != null) + { + Rectangle bounds = dropDownItemDesigner.GetGlyphBounds(); + Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior(); + // Initialize Glyph + ToolStripItemGlyph bodyGlyphForddItem = new ToolStripItemGlyph(item, dropDownItemDesigner, bounds, toolStripBehavior); + //Set the glyph for the item .. so that we can remove it later.... + dropDownItemDesigner.bodyGlyph = bodyGlyphForddItem; + //Add ItemGlyph to the Collection + if (_toolStripAdornerWindowService != null) + { + _toolStripAdornerWindowService.DropDownAdorner.Glyphs.Add(bodyGlyphForddItem); + } + } + } + } + + /// + /// Fired when a new item is chosen from the AddItems menu from the Template Node. + /// + private ToolStripItem AddNewItem(Type t) + { + Debug.Assert(_host != null, "Why didn't we get a designer host?"); + NewItemTransaction = _host.CreateTransaction(SR.ToolStripCreatingNewItemTransaction); + IComponent component = null; + try + { + _addingItem = true; + // Suspend the Layout as we are about to add Item to the ToolStrip + ToolStrip.SuspendLayout(); + ToolStripItemDesigner designer = null; + try + { + // The code in ComponentAdded will actually get the add done. This should be inside the try finally because it could throw an exception and keep the toolstrip in SuspendLayout mode + component = _host.CreateComponent(t); + designer = _host.GetDesigner(component) as ToolStripItemDesigner; + designer.InternalCreate = true; + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + } + finally + { + if (designer != null) + { + designer.InternalCreate = false; + } + // Resume the Layout as we are about to add Item to the ToolStrip + ToolStrip.ResumeLayout(); + } + } + catch (Exception e) + { + if (NewItemTransaction != null) + { + NewItemTransaction.Cancel(); + NewItemTransaction = null; + } + + // Throw the exception unless it's a canceled checkout + if ((!(e is CheckoutException checkoutException)) || (!checkoutException.Equals(CheckoutException.Canceled))) + { + throw; + } + } + finally + { + _addingItem = false; + } + return component as ToolStripItem; + } + + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + internal ToolStripItem AddNewItem(Type t, string text, bool enterKeyPressed, bool tabKeyPressed) + { + Debug.Assert(_host != null, "Why didn't we get a designer host?"); + Debug.Assert(_pendingTransaction == null, "Adding item with pending transaction?"); + DesignerTransaction outerTransaction = _host.CreateTransaction(string.Format(SR.ToolStripAddingItem, t.Name)); + ToolStripItem item = null; + try + { + _addingItem = true; + // Suspend the Layout as we are about to add Item to the ToolStrip + ToolStrip.SuspendLayout(); + // The code in ComponentAdded will actually get the add done. + IComponent component = _host.CreateComponent(t, NameFromText(text, t, Component.Site)); + ToolStripItemDesigner designer = _host.GetDesigner(component) as ToolStripItemDesigner; + try + { + // ToolStripItem designer tries to set the TEXT for the item in the InitializeNewComponent(). But since we are create item thru InSitu .. we shouldnt do this. Also we shouldn't set the TEXT if we are creating a dummyItem. + if (!string.IsNullOrEmpty(text)) + { + designer.InternalCreate = true; + } + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + } + finally + { + designer.InternalCreate = false; + } + + //Set the Text and Image.. + item = component as ToolStripItem; + if (item != null) + { + PropertyDescriptor textProperty = TypeDescriptor.GetProperties(item)["Text"]; + Debug.Assert(textProperty != null, "Could not find 'Text' property in ToolStripItem."); + if (textProperty != null && !string.IsNullOrEmpty(text)) + { + textProperty.SetValue(item, text); + } + + //Set the Image property and DisplayStyle... + if (item is ToolStripButton || item is ToolStripSplitButton || item is ToolStripDropDownButton) + { + Image image = null; + try + { + image = new Bitmap(typeof(ToolStripButton), "blank.bmp"); + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + + PropertyDescriptor imageProperty = TypeDescriptor.GetProperties(item)["Image"]; + Debug.Assert(imageProperty != null, "Could not find 'Image' property in ToolStripItem."); + if (imageProperty != null && image != null) + { + imageProperty.SetValue(item, image); + } + + PropertyDescriptor dispProperty = TypeDescriptor.GetProperties(item)["DisplayStyle"]; + Debug.Assert(dispProperty != null, "Could not find 'DisplayStyle' property in ToolStripItem."); + if (dispProperty != null) + { + dispProperty.SetValue(item, ToolStripItemDisplayStyle.Image); + } + + PropertyDescriptor imageTransProperty = TypeDescriptor.GetProperties(item)["ImageTransparentColor"]; + Debug.Assert(imageTransProperty != null, "Could not find 'DisplayStyle' property in ToolStripItem."); + if (imageTransProperty != null) + { + imageTransProperty.SetValue(item, Color.Magenta); + } + } + } + + // ResumeLayout on ToolStrip. + ToolStrip.ResumeLayout(); + if (!tabKeyPressed) + { + if (enterKeyPressed) + { + if (!designer.SetSelection(enterKeyPressed)) + { + if (KeyboardHandlingService != null) + { + KeyboardHandlingService.SelectedDesignerControl = _editorNode; + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + } + } + } + else + { + // put the templateNode into nonselection mode && select the existing Item + KeyboardHandlingService.SelectedDesignerControl = null; + SelectionService.SetSelectedComponents(new IComponent[] { item }, SelectionTypes.Replace); + _editorNode.RefreshSelectionGlyph(); + } + } + else + { + if (_keyboardHandlingService != null) + { + KeyboardHandlingService.SelectedDesignerControl = _editorNode; + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + } + } + + if (designer != null && item.Placement != ToolStripItemPlacement.Overflow) + { + Rectangle bounds = designer.GetGlyphBounds(); + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior(); + ToolStripItemGlyph bodyGlyphForItem = new ToolStripItemGlyph(item, designer, bounds, toolStripBehavior); + //Add ItemGlyph to the Collection + selMgr.BodyGlyphAdorner.Glyphs.Insert(0, bodyGlyphForItem); + } + else if (designer != null && item.Placement == ToolStripItemPlacement.Overflow) + { + // Add Glyphs for overflow... + RemoveBodyGlyphsForOverflow(); + AddBodyGlyphsForOverflow(); + } + } + catch (Exception exception) + { + // ResumeLayout on ToolStrip. + ToolStrip.ResumeLayout(); + if (_pendingTransaction != null) + { + _pendingTransaction.Cancel(); + _pendingTransaction = null; + } + if (outerTransaction != null) + { + outerTransaction.Cancel(); + outerTransaction = null; + } + + if (exception is CheckoutException checkoutEx && checkoutEx != CheckoutException.Canceled) + { + throw; + } + } + finally + { + if (_pendingTransaction != null) + { + _pendingTransaction.Cancel(); + _pendingTransaction = null; + + if (outerTransaction != null) + { + outerTransaction.Cancel(); + } + } + else if (outerTransaction != null) + { + outerTransaction.Commit(); + outerTransaction = null; + } + _addingItem = false; + } + return item; + } + + // + // Adds the new TemplateNode to the ToolStrip or MenuStrip. + // + internal void AddNewTemplateNode(ToolStrip wb) + { + // setup the MINIToolStrip host... + _tn = new ToolStripTemplateNode(Component, SR.ToolStripDesignerTemplateNodeEnterText, null); + _miniToolStrip = _tn.EditorToolStrip; + int width = _tn.EditorToolStrip.Width; + _editorNode = new DesignerToolStripControlHost(_tn.EditorToolStrip); + _tn.ControlHost = _editorNode; + _editorNode.Width = width; + ToolStrip.Items.Add(_editorNode); + _editorNode.Visible = false; + } + + internal void CancelPendingMenuItemTransaction() + { + if (_insertMenuItemTransaction != null) + { + _insertMenuItemTransaction.Cancel(); + } + } + + // + // Check if the ToolStripItems are selected. + // + private bool CheckIfItemSelected() + { + bool showToolStrip = false; + object comp = SelectionService.PrimarySelection; + if (comp == null) + { + comp = (IComponent)KeyboardHandlingService.SelectedDesignerControl; + } + if (comp is ToolStripItem item) + { + if (item.Placement == ToolStripItemPlacement.Overflow && item.Owner == ToolStrip) + { + if (ToolStrip.CanOverflow && !ToolStrip.OverflowButton.DropDown.Visible) + { + ToolStrip.OverflowButton.ShowDropDown(); + } + showToolStrip = true; + } + else + { + + if (!ItemParentIsOverflow(item)) + { + if (ToolStrip.OverflowButton.DropDown.Visible) + { + ToolStrip.OverflowButton.HideDropDown(); + } + } + if (item.Owner == ToolStrip) + { + showToolStrip = true; + } + else if (item is DesignerToolStripControlHost) + { + if (item.IsOnDropDown && item.Placement != ToolStripItemPlacement.Overflow) + { + ToolStripDropDown dropDown = (ToolStripDropDown)((DesignerToolStripControlHost)comp).GetCurrentParent(); + if (dropDown != null) + { + ToolStripItem ownerItem = dropDown.OwnerItem; + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)_host.GetDesigner(ownerItem); + ToolStripDropDown topmost = itemDesigner.GetFirstDropDown((ToolStripDropDownItem)(ownerItem)); + ToolStripItem topMostItem = (topmost == null) ? ownerItem : topmost.OwnerItem; + + if (topMostItem != null && topMostItem.Owner == ToolStrip) + { + showToolStrip = true; + } + } + } + } + else if (item.IsOnDropDown && item.Placement != ToolStripItemPlacement.Overflow) + { + ToolStripItem parentItem = ((ToolStripDropDown)(item.Owner)).OwnerItem; + if (parentItem != null) + { + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)_host.GetDesigner(parentItem); + ToolStripDropDown topmost = (itemDesigner == null) ? null : itemDesigner.GetFirstDropDown((ToolStripDropDownItem)parentItem); + ToolStripItem topMostItem = (topmost == null) ? parentItem : topmost.OwnerItem; + if (topMostItem != null && topMostItem.Owner == ToolStrip) + { + showToolStrip = true; + } + } + } + } + } + return showToolStrip; + } + + // + // This is called ToolStripItemGlyph to commit the TemplateNode Edition on the Parent ToolStrip. + // + internal bool Commit() + { + if (_tn != null && _tn.Active) + { + _tn.Commit(false, false); + _editorNode.Width = _tn.EditorToolStrip.Width; + } + else + { + if (SelectionService.PrimarySelection is ToolStripDropDownItem selectedItem) + { + if (_host.GetDesigner(selectedItem) is ToolStripMenuItemDesigner itemDesigner && itemDesigner.IsEditorActive) + { + itemDesigner.Commit(); + return true; + } + } + else + { + if (KeyboardHandlingService != null) + { + if (KeyboardHandlingService.SelectedDesignerControl is ToolStripItem designerItem && designerItem.IsOnDropDown) + { + if (designerItem.GetCurrentParent() is ToolStripDropDown parent) + { + if (parent.OwnerItem is ToolStripDropDownItem ownerItem) + { + if (_host.GetDesigner(ownerItem) is ToolStripMenuItemDesigner itemDesigner && itemDesigner.IsEditorActive) + { + itemDesigner.Commit(); + return true; + } + } + } + } + else + { //check for normal ToolStripItem selection .... + if (SelectionService.PrimarySelection is ToolStripItem toolItem) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(toolItem); + if (itemDesigner != null && itemDesigner.IsEditorActive) + { + itemDesigner.Editor.Commit(false, false); + return true; + } + } + } + } + } + } + return false; + } + + /// + /// Make sure the AddNewItem button is setup properly. + /// + private void Control_HandleCreated(object sender, EventArgs e) + { + InitializeNewItemDropDown(); + } + + /// + /// Fired after a component has been added. Here, we add it to the ToolStrip and select it. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private void ComponentChangeSvc_ComponentAdded(object sender, ComponentEventArgs e) + { + // If another ToolStrip is getting added and we are currently selected then unselect us .. the newly added toolStrip should get selected. + if (_toolStripSelected && e.Component is ToolStrip) + { + _toolStripSelected = false; + } + try + { + // make sure it's one of ours and not on DropDown. + if (e.Component is ToolStripItem newItem && _addingItem && !newItem.IsOnDropDown) + { + _addingItem = false; + if (CacheItems) + { + _items.Add(newItem); + } + else + { + // Get the current count of ToolStripItems. + int count = ToolStrip.Items.Count; + // notify the designer what's changed. + try + { + base.RaiseComponentChanging(TypeDescriptor.GetProperties(Component)["Items"]); + if (SelectionService.PrimarySelection is ToolStripItem selectedItem) + { + //ADD at the current Selection ... + if (selectedItem.Owner == ToolStrip) + { + int indexToInsert = ToolStrip.Items.IndexOf(selectedItem); + ToolStrip.Items.Insert(indexToInsert, newItem); + } + + } + else if (count > 0) + { + // ADD at Last but one, the last one being the TemplateNode always... + ToolStrip.Items.Insert(count - 1, newItem); + } + else + { + ToolStrip.Items.Add(newItem); + } + } + finally + { + base.RaiseComponentChanged(TypeDescriptor.GetProperties(Component)["Items"], null, null); + } + } + } + } + catch + { + if (_pendingTransaction != null) + { + _pendingTransaction.Cancel(); + _pendingTransaction = null; + _insertMenuItemTransaction = null; + } + } + finally + { + if (_pendingTransaction != null) + { + _pendingTransaction.Commit(); + _pendingTransaction = null; + _insertMenuItemTransaction = null; + } + } + } + + /// + /// Checks if the component being added is a child ToolStripItem. + /// + private void ComponentChangeSvc_ComponentAdding(object sender, ComponentEventArgs e) + { + if (KeyboardHandlingService != null && KeyboardHandlingService.CopyInProgress) + { + return; + } + + // Return if we are not the owner !! + object selectedItem = SelectionService.PrimarySelection; + if (selectedItem == null) + { + if (_keyboardHandlingService != null) + { + selectedItem = KeyboardHandlingService.SelectedDesignerControl; + } + } + if (selectedItem is ToolStripItem currentSel && currentSel.Owner != ToolStrip) + { + return; + } + + // we'll be adding a child item if the component is a ToolStrip item and we've currently got this ToolStrip or one of it's items selected. we do this so things like paste and undo automagically work. + ToolStripItem addingItem = e.Component as ToolStripItem; + if (addingItem != null && addingItem.Owner != null) + { + if (addingItem.Owner.Site == null) + { + //we are DummyItem to the ToolStrip... + return; + } + } + if (_insertMenuItemTransaction == null && s_autoAddNewItems && addingItem != null && !_addingItem && IsToolStripOrItemSelected && !EditingCollection) + { + _addingItem = true; + + if (_pendingTransaction == null) + { + Debug.Assert(_host != null, "Why didn't we get a designer host?"); + _insertMenuItemTransaction = _pendingTransaction = _host.CreateTransaction(SR.ToolStripDesignerTransactionAddingItem); + } + } + } + + /// + /// Required to check if we need to show the Overflow, if any change has caused the item to go into the overflow. + /// + private void ComponentChangeSvc_ComponentChanged(object sender, ComponentChangedEventArgs e) + { + if (e.Component is ToolStripItem changingItem) + { + ToolStrip parent = changingItem.Owner; + if (parent == ToolStrip && e.Member != null && e.Member.Name == "Overflow") + { + ToolStripItemOverflow oldValue = (ToolStripItemOverflow)e.OldValue; + ToolStripItemOverflow newValue = (ToolStripItemOverflow)e.NewValue; + if (oldValue != ToolStripItemOverflow.Always && newValue == ToolStripItemOverflow.Always) + { + // If now the Item falls in the Overflow .. Open the Overflow.. + if (ToolStrip.CanOverflow && !ToolStrip.OverflowButton.DropDown.Visible) + { + ToolStrip.OverflowButton.ShowDropDown(); + } + } + } + } + } + + /// + /// After a ToolStripItem is removed, remove it from the ToolStrip and select the next item. + /// + private void ComponentChangeSvc_ComponentRemoved(object sender, ComponentEventArgs e) + { + if (e.Component is ToolStripItem && ((ToolStripItem)e.Component).Owner == Component) + { + ToolStripItem item = (ToolStripItem)e.Component; + int itemIndex = ToolStrip.Items.IndexOf(item); + // send notifications. + try + { + if (itemIndex != -1) + { + ToolStrip.Items.Remove(item); + base.RaiseComponentChanged(TypeDescriptor.GetProperties(Component)["Items"], null, null); + } + } + finally + { + if (_pendingTransaction != null) + { + _pendingTransaction.Commit(); + _pendingTransaction = null; + } + } + + // select the next item or the ToolStrip itself. + if (ToolStrip.Items.Count > 1) + { + itemIndex = Math.Min(ToolStrip.Items.Count - 1, itemIndex); + itemIndex = Math.Max(0, itemIndex); + } + else + { + itemIndex = -1; + } + LayoutToolStrip(); + + //Reset the Glyphs if the item removed is on the OVERFLOW, + if (item.Placement == ToolStripItemPlacement.Overflow) + { + // Add Glyphs for overflow... + RemoveBodyGlyphsForOverflow(); + AddBodyGlyphsForOverflow(); + } + + if (_toolStripAdornerWindowService != null && _boundsToInvalidate != Rectangle.Empty) + { + _toolStripAdornerWindowService.Invalidate(_boundsToInvalidate); + BehaviorService.Invalidate(_boundsToInvalidate); + } + + if (KeyboardHandlingService.CutOrDeleteInProgress) + { + IComponent targetSelection = (itemIndex == -1) ? (IComponent)ToolStrip : (IComponent)ToolStrip.Items[itemIndex]; + // if the TemplateNode becomes the targetSelection, then set the targetSelection to null. + if (targetSelection != null) + { + if (targetSelection is DesignerToolStripControlHost) + { + if (KeyboardHandlingService != null) + { + KeyboardHandlingService.SelectedDesignerControl = targetSelection; + } + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + + } + else + { + SelectionService.SetSelectedComponents(new IComponent[] { targetSelection }, SelectionTypes.Replace); + } + } + } + } + } + + /// + /// Before a ToolStripItem is removed, open a transaction to batch the operation. + /// + private void ComponentChangeSvc_ComponentRemoving(object sender, ComponentEventArgs e) + { + if (e.Component is ToolStripItem && ((ToolStripItem)e.Component).Owner == Component) + { + Debug.Assert(_host != null, "Why didn't we get a designer host?"); + Debug.Assert(_pendingTransaction == null, "Removing item with pending transaction?"); + try + { + _pendingTransaction = _host.CreateTransaction(SR.ToolStripDesignerTransactionRemovingItem); + base.RaiseComponentChanging(TypeDescriptor.GetProperties(Component)["Items"]); + if (e.Component is ToolStripDropDownItem dropDownItem) + { + dropDownItem.HideDropDown(); + _boundsToInvalidate = dropDownItem.DropDown.Bounds; + } + } + catch + { + if (_pendingTransaction != null) + { + _pendingTransaction.Cancel(); + _pendingTransaction = null; + } + } + } + } + + /// + /// Clean up the mess we've made! + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + _disposed = true; + if (_items != null) + { + _items = null; + } + if (_selectionSvc != null) + { + _selectionSvc = null; + } + + EnableDragDrop(false); + //Dispose of the EitManager + if (_editManager != null) + { + _editManager.CloseManager(); + _editManager = null; + } + + //tear down the TemplateNode + if (_tn != null) + { + _tn.RollBack(); + _tn.CloseEditor(); + _tn = null; + } + + // teardown the add item button. + if (_miniToolStrip != null) + { + _miniToolStrip.Dispose(); + _miniToolStrip = null; + } + + //tearDown the EditorNode.. + if (_editorNode != null) + { + _editorNode.Dispose(); + _editorNode = null; + } + + // tear off the ContextMenu.. + if (_toolStripContextMenu != null) + { + _toolStripContextMenu.Dispose(); + _toolStripContextMenu = null; + } + //Always Remove all the glyphs we added + RemoveBodyGlyphsForOverflow(); + //tear off the OverFlow if its being shown + if (ToolStrip.OverflowButton.DropDown.Visible) + { + ToolStrip.OverflowButton.HideDropDown(); + } + + if (_toolStripAdornerWindowService != null) + { + _toolStripAdornerWindowService = null; + } + } + base.Dispose(disposing); + } + + /// + /// Creates a method signature in the source code file for the default event on the component and navigates the user's cursor to that location in preparation to assign the default action. + /// + public override void DoDefaultAction() + { + //Dont Fire the Events if the Component is Inherited. + if (InheritanceAttribute != InheritanceAttribute.InheritedReadOnly) + { + IComponent selectedItem = SelectionService.PrimarySelection as IComponent; + if (selectedItem == null) + { + if (KeyboardHandlingService != null) + { + selectedItem = (IComponent)KeyboardHandlingService.SelectedDesignerControl; + } + + } + // if one of the sub-items is selected, delegate to it. + if (selectedItem is ToolStripItem) + { + if (_host != null) + { + IDesigner itemDesigner = _host.GetDesigner(selectedItem); + if (itemDesigner != null) + { + itemDesigner.DoDefaultAction(); + return; + } + } + } + base.DoDefaultAction(); + } + } + + + /// + /// We add our BodyGlyphs as well as bodyGlyphs for the ToolStripItems here. + /// + protected override ControlBodyGlyph GetControlGlyph(GlyphSelectionType selectionType) + { + // Get the glyphs iff Handle is created for the toolStrip. + if (!ToolStrip.IsHandleCreated) + { + return null; + } + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + if (selMgr != null && ToolStrip != null && CanAddItems && ToolStrip.Visible) + { + object primarySelection = SelectionService.PrimarySelection; + Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior(); + //sometimes the Collection changes when the ToolStrip gets the Selection and we are in Dummy Insitu edit... so remove that before you access the collection.. + if (ToolStrip.Items.Count > 0) + { + ToolStripItem[] items = new ToolStripItem[ToolStrip.Items.Count]; + ToolStrip.Items.CopyTo(items, 0); + foreach (ToolStripItem toolItem in items) + { + if (toolItem != null) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(toolItem); + bool isPrimary = (toolItem == primarySelection); + if (!isPrimary && + itemDesigner != null && + itemDesigner.IsEditorActive) + { + + itemDesigner.Editor.Commit(false, false); + } + } + } + } + + // Check if menuEditor is present and active... + IMenuEditorService menuEditorService = (IMenuEditorService)GetService(typeof(IMenuEditorService)); + if (menuEditorService == null || (menuEditorService != null && !menuEditorService.IsActive())) + { + + // now walk the ToolStrip and add glyphs for each of it's children + foreach (ToolStripItem item in ToolStrip.Items) + { + if (item is DesignerToolStripControlHost) + { + continue; + } + // make sure it's on the ToolStrip... + if (item.Placement == ToolStripItemPlacement.Main) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item); + if (itemDesigner != null) + { + bool isPrimary = (item == primarySelection); + if (isPrimary) + { + ((ToolStripItemBehavior)toolStripBehavior)._dragBoxFromMouseDown = _dragBoxFromMouseDown; + } + + // Get Back the Current Bounds if current selection is not a primary selection + if (!isPrimary) + { + item.AutoSize = (itemDesigner != null) ? itemDesigner.AutoSize : true; + } + + Rectangle itemBounds = itemDesigner.GetGlyphBounds(); + Control parent = ToolStrip.Parent; + Rectangle parentBounds = BehaviorService.ControlRectInAdornerWindow(parent); + if (IsGlyphTotallyVisible(itemBounds, parentBounds) && item.Visible) + { + // Add Glyph ONLY AFTER item width is changed... + ToolStripItemGlyph bodyGlyphForItem = new ToolStripItemGlyph(item, itemDesigner, itemBounds, toolStripBehavior); + itemDesigner.bodyGlyph = bodyGlyphForItem; + //Add ItemGlyph to the Collection + selMgr.BodyGlyphAdorner.Glyphs.Add(bodyGlyphForItem); + } + } + } + } + } + } + return (base.GetControlGlyph(selectionType)); + } + + /// + /// We add our SelectionGlyphs here. Since ToolStripItems are components we add the SelectionGlyphs for those in this call as well. + /// + public override GlyphCollection GetGlyphs(GlyphSelectionType selType) + { + // get the default glyphs for this component. + GlyphCollection glyphs = new GlyphCollection(); + ICollection selComponents = SelectionService.GetSelectedComponents(); + foreach (object comp in selComponents) + { + if (comp is ToolStrip) + { + GlyphCollection toolStripGlyphs = base.GetGlyphs(selType); + glyphs.AddRange(toolStripGlyphs); + } + else + { + if (comp is ToolStripItem item && item.Visible) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item); + if (itemDesigner != null) + { + itemDesigner.GetGlyphs(ref glyphs, StandardBehavior); + } + } + } + } + + if ((SelectionRules & SelectionRules.Moveable) != 0 && InheritanceAttribute != InheritanceAttribute.InheritedReadOnly && (selType != GlyphSelectionType.NotSelected)) + { + //get the adornerwindow-relative coords for the container control + Point loc = BehaviorService.ControlToAdornerWindow((Control)Component); + Rectangle translatedBounds = new Rectangle(loc, ((Control)Component).Size); + int glyphOffset = (int)(DesignerUtils.CONTAINERGRABHANDLESIZE * .5); + //if the control is too small for our ideal position... + if (translatedBounds.Width < 2 * DesignerUtils.CONTAINERGRABHANDLESIZE) + { + glyphOffset = -1 * glyphOffset; + } + + ContainerSelectorBehavior behavior = new ContainerSelectorBehavior(ToolStrip, Component.Site, true); + ContainerSelectorGlyph containerSelectorGlyph = new ContainerSelectorGlyph(translatedBounds, DesignerUtils.CONTAINERGRABHANDLESIZE, glyphOffset, behavior); + glyphs.Insert(0, containerSelectorGlyph); + } + return glyphs; + } + + /// + /// Allow hit testing over the AddNewItem button only. + /// + protected override bool GetHitTest(Point point) + { + // convert to client coords. + point = Control.PointToClient(point); + + if (_miniToolStrip != null && _miniToolStrip.Visible && AddItemRect.Contains(point)) + { + return true; + } + if (OverFlowButtonRect.Contains(point)) + { + return true; + } + return base.GetHitTest(point); + + } + + /// + /// Get the designer set up to run. + /// + // EditorServiceContext is newed up to add Edit Items verb. + [SuppressMessage("Microsoft.Performance", "CA1806:DoNotIgnoreMethodResults")] + public override void Initialize(IComponent component) + { + base.Initialize(component); + AutoResizeHandles = true; + _host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (_host != null) + { + _componentChangeSvc = (IComponentChangeService)_host.GetService(typeof(IComponentChangeService)); + } + + // initialize new Manager For Editing ToolStrips + _editManager = new ToolStripEditorManager(component); + // setup the dropdown if our handle has been created. + if (Control.IsHandleCreated) + { + InitializeNewItemDropDown(); + } + + //hookup to the AdornerService..for the overflow dropdown to be parent properly. + _toolStripAdornerWindowService = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService)); + + // Make sure the overflow is not toplevel + ToolStrip.OverflowButton.DropDown.TopLevel = false; + + // init the verb. + if (CanAddItems) + { + new EditorServiceContext(this, TypeDescriptor.GetProperties(Component)["Items"], SR.ToolStripItemCollectionEditorVerb); + //Add the EditService so that the ToolStrip can do its own Tab and Keyboard Handling + _keyboardHandlingService = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (_keyboardHandlingService == null) + { + _keyboardHandlingService = new ToolStripKeyboardHandlingService(Component.Site); + } + + //Add the InsituEditService so that the ToolStrip can do its own Tab and Keyboard Handling + ISupportInSituService inSituService = (ISupportInSituService)GetService(typeof(ISupportInSituService)); + if (inSituService == null) + { + inSituService = new ToolStripInSituService(Component.Site); + } + } + + // ToolStrip is selected... + _toolStripSelected = true; + // Reset the TemplateNode Selection if any... + if (_keyboardHandlingService != null) + { + KeyboardHandlingService.SelectedDesignerControl = null; + } + } + + /// + /// ControlDesigner overrides this method. It will look at the default property for the control and, if it is of type string, it will set this property's value to the name of the component. It only does this if the designer has been configured with this option in the options service. This method also connects the control to its parent and positions it. If you override this method, you should always call base. + /// + public override void InitializeNewComponent(IDictionary defaultValues) + { + Control parent = defaultValues["Parent"] as Control; + Form parentForm = _host.RootComponent as Form; + MainMenu parentMenu = null; + FormDocumentDesigner parentFormDesigner = null; + if (parentForm != null) + { + parentFormDesigner = _host.GetDesigner(parentForm) as FormDocumentDesigner; + if (parentFormDesigner != null && parentFormDesigner.Menu != null) + { + // stash off the main menu while we initialize + parentMenu = parentFormDesigner.Menu; + parentFormDesigner.Menu = null; + } + } + + ToolStripPanel parentPanel = parent as ToolStripPanel; + // smoke the Dock Property if the toolStrip is getting parented to the ContentPanel. + if (parentPanel == null && parent is ToolStripContentPanel) + { + // smoke the dock property whenever we add a toolstrip to a toolstrip panel. + PropertyDescriptor dockProp = TypeDescriptor.GetProperties(ToolStrip)["Dock"]; + if (dockProp != null) + { + dockProp.SetValue(ToolStrip, DockStyle.None); + } + } + + /// set up parenting and all the base stuff... + if (parentPanel == null || ToolStrip is MenuStrip) + { + base.InitializeNewComponent(defaultValues); + } + + if (parentFormDesigner != null) + { + //Add MenuBack + if (parentMenu != null) + { + parentFormDesigner.Menu = parentMenu; + } + //Set MainMenuStrip property + if (ToolStrip is MenuStrip) + { + PropertyDescriptor mainMenuStripProperty = TypeDescriptor.GetProperties(parentForm)["MainMenuStrip"]; + if (mainMenuStripProperty != null && mainMenuStripProperty.GetValue(parentForm) == null) + { + mainMenuStripProperty.SetValue(parentForm, ToolStrip as MenuStrip); + } + } + } + + if (parentPanel != null) + { + if (!(ToolStrip is MenuStrip)) + { + PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(parentPanel)["Controls"]; + + if (_componentChangeSvc != null) + { + _componentChangeSvc.OnComponentChanging(parentPanel, controlsProp); + } + + parentPanel.Join(ToolStrip, parentPanel.Rows.Length); + + if (_componentChangeSvc != null) + { + _componentChangeSvc.OnComponentChanged(parentPanel, controlsProp, parentPanel.Controls, parentPanel.Controls); + } + + //Try to fire ComponentChange on the Location Property for ToolStrip. + PropertyDescriptor locationProp = TypeDescriptor.GetProperties(ToolStrip)["Location"]; + if (_componentChangeSvc != null) + { + _componentChangeSvc.OnComponentChanging(ToolStrip, locationProp); + _componentChangeSvc.OnComponentChanged(ToolStrip, locationProp, null, null); + } + } + } + // If we are added to any container other than ToolStripPanel. + else if (parent != null) + { + // If we are adding the MenuStrip ... put it at the Last in the Controls Collection so it gets laid out first. + if (ToolStrip is MenuStrip) + { + int index = -1; + foreach (Control c in parent.Controls) + { + if (c is ToolStrip && (c != ToolStrip)) + { + index = parent.Controls.IndexOf(c); + } + } + if (index == -1) + { + // always place the toolStrip first. + index = parent.Controls.Count - 1; + } + parent.Controls.SetChildIndex(ToolStrip, index); + } + // If we are not a MenuStrip then we still need to be first to be laid out "after the menuStrip" + else + { + int index = -1; + foreach (Control c in parent.Controls) + { + // If we found an existing toolstrip (and not a menuStrip) then we can just return .. the base would have done correct parenting for us + MenuStrip menu = c as MenuStrip; + if (c is ToolStrip && menu == null) + { + return; + } + if (menu != null) + { + index = parent.Controls.IndexOf(c); + break; + } + } + if (index == -1) + { + // always place the toolStrip first. + index = parent.Controls.Count; + } + parent.Controls.SetChildIndex(ToolStrip, index - 1); + } + } + } + + /// + /// Setup the "AddNewItem" button + /// + private void InitializeNewItemDropDown() + { + if (!CanAddItems || !SupportEditing) + { + return; + } + ToolStrip toolStrip = (ToolStrip)Component; + AddNewTemplateNode(toolStrip); + // set up the right visibility state for the ToolStrip. + SelSvc_SelectionChanged(null, EventArgs.Empty); + } + + /// + /// This is called to ascertain if the Glyph is totally visible. This is called from ToolStripMenuItemDesigner too. + /// + internal static bool IsGlyphTotallyVisible(Rectangle itemBounds, Rectangle parentBounds) + { + return parentBounds.Contains(itemBounds); + } + + /// + /// Returns true if the item is on the overflow. + /// + private bool ItemParentIsOverflow(ToolStripItem item) + { + ToolStripDropDown topmost = item.Owner as ToolStripDropDown; + if (topmost != null) + { + // walk back up the chain of windows to get the topmost + while (topmost != null && !(topmost is ToolStripOverflow)) + { + if (topmost.OwnerItem != null) + { + topmost = topmost.OwnerItem.GetCurrentParent() as ToolStripDropDown; + } + else + { + topmost = null; + } + } + } + return (topmost is ToolStripOverflow); + } + + /// + /// Sets up the add new button, and invalidates the behavior glyphs if needed so they always stay in sync. + /// + private void LayoutToolStrip() + { + if (!_disposed) + { + ToolStrip.PerformLayout(); + } + } + + internal static string NameFromText(string text, Type componentType, IServiceProvider serviceProvider, bool adjustCapitalization) + { + string name = NameFromText(text, componentType, serviceProvider); + if (adjustCapitalization) + { + string nameOfRandomItem = NameFromText(null, typeof(ToolStripMenuItem), + serviceProvider); + if (!string.IsNullOrEmpty(nameOfRandomItem) && char.IsUpper(nameOfRandomItem[0])) + { + name = char.ToUpper(name[0], CultureInfo.InvariantCulture) + name.Substring(1); + } + } + return name; + } + + /// + /// Computes a name from a text label by removing all spaces and non-alphanumeric characters. + /// + internal static string NameFromText(string text, Type componentType, IServiceProvider serviceProvider) + { + if (serviceProvider == null) + { + return null; + } + + INameCreationService nameCreate = serviceProvider.GetService(typeof(INameCreationService)) as INameCreationService; + IContainer container = (IContainer)serviceProvider.GetService(typeof(IContainer)); + string defaultName; + if (nameCreate != null && container != null) + { + defaultName = nameCreate.CreateName(container, componentType); + } + else + { + return null; + } + + Debug.Assert(defaultName != null && defaultName.Length > 0, "Couldn't create default name for item"); + + if (text == null || text.Length == 0 || text == "-") + { + return defaultName; + } + + string nameSuffix = componentType.Name; + // remove all the non letter and number characters. Append length of the item name... + System.Text.StringBuilder name = new System.Text.StringBuilder(text.Length + nameSuffix.Length); + bool nextCharToUpper = false; + for (int i = 0; i < text.Length; i++) + { + char c = text[i]; + if (nextCharToUpper) + { + if (char.IsLower(c)) + { + c = char.ToUpper(c, CultureInfo.CurrentCulture); + } + nextCharToUpper = false; + } + + if (char.IsLetterOrDigit(c)) + { + if (name.Length == 0) + { + if (char.IsDigit(c)) + { + // most languages don't allow a digit as the first char in an identifier. + continue; + } + + if (char.IsLower(c) != char.IsLower(defaultName[0])) + { + // match up the first char of the generated identifier with the case of the default. + if (char.IsLower(c)) + { + c = char.ToUpper(c, CultureInfo.CurrentCulture); + } + else + { + c = char.ToLower(c, CultureInfo.CurrentCulture); + } + } + } + name.Append(c); + } + else + { + if (char.IsWhiteSpace(c)) + { + nextCharToUpper = true; + } + } + } + + if (name.Length == 0) + { + return defaultName; + } + + name.Append(nameSuffix); + string baseName = name.ToString(); + + // verify we have a valid name. If not, start appending numbers if it matches one in the container. see if this name matches another one in the container.. + object existingComponent = container.Components[baseName]; + + if (existingComponent == null) + { + if (!nameCreate.IsValidName(baseName)) + { + // we don't have a name collision but this still isn't a valid name...something is wrong and we can't make a valid identifier out of this so bail. + return defaultName; + } + else + { + return baseName; + } + } + else + { + // start appending numbers. + string newName = baseName; + for (int indexer = 1; !nameCreate.IsValidName(newName) || container.Components[newName] != null; indexer++) + { + newName = baseName + indexer.ToString(CultureInfo.InvariantCulture); + } + return newName; + } + } + + /// + /// DesignerContextMenu should be shown when the ToolStripDesigner. + /// + protected override void OnContextMenu(int x, int y) + { + Component selComp = SelectionService.PrimarySelection as Component; + if (selComp is ToolStrip) + { + DesignerContextMenu.Show(x, y); + } + } + + protected override void OnDragEnter(DragEventArgs de) + { + base.OnDragEnter(de); + SetDragDropEffects(de); + } + + protected override void OnDragOver(DragEventArgs de) + { + base.OnDragOver(de); + SetDragDropEffects(de); + } + + /// + /// Add item on Drop and it its a MenuItem, open its dropDown. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + protected override void OnDragDrop(DragEventArgs de) + { + base.OnDragDrop(de); + // There is a "drop region" before firstItem which is not included in the "ToolStrip Item glyhs" so if the drop point falls in this drop region we should insert the items at the head instead of the tail of the toolStrip. + bool dropAtHead = false; + ToolStrip parentToolStrip = ToolStrip; + NativeMethods.POINT offset = new NativeMethods.POINT(de.X, de.Y); + NativeMethods.MapWindowPoints(IntPtr.Zero, parentToolStrip.Handle, offset, 1); + Point dropPoint = new Point(offset.x, offset.y); + if (ToolStrip.Orientation == Orientation.Horizontal) + { + if (ToolStrip.RightToLeft == RightToLeft.Yes) + { + if (dropPoint.X >= parentToolStrip.Items[0].Bounds.X) + { + dropAtHead = true; + } + } + else if (dropPoint.X <= parentToolStrip.Items[0].Bounds.X) + { + dropAtHead = true; + } + } + else + { + if (dropPoint.Y <= parentToolStrip.Items[0].Bounds.Y) + { + dropAtHead = true; + } + } + + if (de.Data is ToolStripItemDataObject data) + { + if (data.Owner == parentToolStrip) + { + string transDesc; + ArrayList components = data.DragComponents; + ToolStripItem primaryItem = data.PrimarySelection as ToolStripItem; + int primaryIndex = -1; + bool copy = (de.Effect == DragDropEffects.Copy); + + if (components.Count == 1) + { + string name = TypeDescriptor.GetComponentName(components[0]); + if (name == null || name.Length == 0) + { + name = components[0].GetType().Name; + } + transDesc = string.Format(copy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name); + } + else + { + transDesc = string.Format(copy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, components.Count); + } + + // create a transaction so this happens as an atomic unit. + DesignerTransaction changeParent = _host.CreateTransaction(transDesc); + try + { + IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (changeSvc != null) + { + changeSvc.OnComponentChanging(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"]); + } + + // If we are copying, then we want to make a copy of the components we are dragging + if (copy) + { + // Remember the primary selection if we had one + if (primaryItem != null) + { + primaryIndex = components.IndexOf(primaryItem); + } + if (KeyboardHandlingService != null) + { + KeyboardHandlingService.CopyInProgress = true; + } + components = DesignerUtils.CopyDragObjects(components, Component.Site) as ArrayList; + if (KeyboardHandlingService != null) + { + KeyboardHandlingService.CopyInProgress = false; + } + if (primaryIndex != -1) + { + primaryItem = components[primaryIndex] as ToolStripItem; + } + } + + if (de.Effect == DragDropEffects.Move || copy) + { + // Add the item. + for (int i = 0; i < components.Count; i++) + { + if (dropAtHead) + { + parentToolStrip.Items.Insert(0, components[i] as ToolStripItem); + } + else + { + parentToolStrip.Items.Add(components[i] as ToolStripItem); + } + } + + // show the dropDown for the primarySelection before the Drag-Drop operation started. + if (primaryItem is ToolStripDropDownItem primaryDropDownItem) + { + if (_host.GetDesigner(primaryDropDownItem) is ToolStripMenuItemDesigner dropDownItemDesigner) + { + dropDownItemDesigner.InitializeDropDown(); + } + } + + //Set the Selection .. + SelectionService.SetSelectedComponents(new IComponent[] { primaryItem }, SelectionTypes.Primary | SelectionTypes.Replace); + } + + if (changeSvc != null) + { + changeSvc.OnComponentChanged(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"], null, null); + } + //fire extra changing/changed events so that the order is "restored" after undo/redo + if (copy) + { + if (changeSvc != null) + { + changeSvc.OnComponentChanging(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"]); + changeSvc.OnComponentChanged(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"], null, null); + } + } + // Refresh Glyphs... + BehaviorService.SyncSelection(); + } + + catch + { + if (changeParent != null) + { + changeParent.Cancel(); + changeParent = null; + } + + } + finally + { + if (changeParent != null) + { + changeParent.Commit(); + changeParent = null; + } + } + } + } + } + + + /// + /// Everytime we add Item .. the TemplateNode needs to go at the end if its not there. + /// + private void OnItemAdded(object sender, ToolStripItemEventArgs e) + { + if (_editorNode != null && (e.Item != _editorNode)) + { + int currentIndexOfEditor = ToolStrip.Items.IndexOf(_editorNode); + if (currentIndexOfEditor == -1 || currentIndexOfEditor != ToolStrip.Items.Count - 1) + { + // if the editor is not there or not at the end, add it to the end. + ToolStrip.SuspendLayout(); + ToolStrip.Items.Add(_editorNode); + ToolStrip.ResumeLayout(); + } + } + LayoutToolStrip(); + } + + /// + /// Overriden so that the ToolStrip honors dragging only through container selector glyph. + /// + protected override void OnMouseDragMove(int x, int y) + { + if (!SelectionService.GetComponentSelected(ToolStrip)) + { + base.OnMouseDragMove(x, y); + } + } + + /// + /// Controls the dismissal of the drop down, here - we just cancel it + /// + private void OnOverflowDropDownClosing(object sender, ToolStripDropDownClosingEventArgs e) + { + //always dismiss this so we don't collapse the dropdown when the user clicks @ design time + e.Cancel = (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked); + } + + + /// + /// Remove the Glyphs for Items on the overflow when the Overflow closes. + /// + private void OnOverFlowDropDownClosed(object sender, EventArgs e) + { + if (_toolStripAdornerWindowService != null && sender is ToolStripDropDownItem ddi) + { + _toolStripAdornerWindowService.Invalidate(ddi.DropDown.Bounds); + RemoveBodyGlyphsForOverflow(); + } + //select the last item on the parent toolStrip if the current selection is on the DropDown. + if (SelectionService.PrimarySelection is ToolStripItem curSel && curSel.IsOnOverflow) + { + ToolStripItem nextItem = ToolStrip.GetNextItem(ToolStrip.OverflowButton, ArrowDirection.Left); + if (nextItem != null) + { + SelectionService.SetSelectedComponents(new IComponent[] { nextItem }, SelectionTypes.Replace); + } + } + } + + /// + /// Add Glyphs when the OverFlow opens .... + /// + private void OnOverFlowDropDownOpened(object sender, EventArgs e) + { + //Show the TemplateNode + if (_editorNode != null) + { + _editorNode.Control.Visible = true; + _editorNode.Visible = true; + } + + ToolStripDropDownItem ddi = sender as ToolStripDropDownItem; + if (ddi != null) + { + RemoveBodyGlyphsForOverflow(); + AddBodyGlyphsForOverflow(); + } + //select the last item on the parent toolStrip if the current selection is on the DropDown. + if (!(SelectionService.PrimarySelection is ToolStripItem curSel) || (curSel != null && !curSel.IsOnOverflow)) + { + ToolStripItem nextItem = ddi.DropDown.GetNextItem(null, ArrowDirection.Down); + if (nextItem != null) + { + SelectionService.SetSelectedComponents(new IComponent[] { nextItem }, SelectionTypes.Replace); + BehaviorService.Invalidate(BehaviorService.ControlRectInAdornerWindow(ToolStrip)); + } + } + } + + /// + /// In Order to Draw the Selection Glyphs we need to reforce painting on the the AdonerWindow.This method forces the repaint + /// + private void OnOverFlowDropDownPaint(object sender, System.Windows.Forms.PaintEventArgs e) + { + foreach (ToolStripItem item in ToolStrip.Items) + { + if (item.Visible && item.IsOnOverflow && SelectionService.GetComponentSelected(item)) + { + if (_host.GetDesigner(item) is ToolStripItemDesigner designer) + { + Rectangle r = designer.GetGlyphBounds(); + ToolStripDesignerUtils.GetAdjustedBounds(item, ref r); + r.Inflate(GLYPHBORDER, GLYPHBORDER); + //this will allow any Glyphs to re-paint + //after this control and its designer has painted + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + if (b != null) + { + b.ProcessPaintMessage(r); + } + } + } + } + } + + /// + /// Change the parent of the overFlow so that it is parented to the ToolStripAdornerWindow + /// + private void OnOverFlowDropDownOpening(object sender, EventArgs e) + { + ToolStripDropDownItem ddi = sender as ToolStripDropDownItem; + if (ddi.DropDown.TopLevel) + { + ddi.DropDown.TopLevel = false; + } + + if (_toolStripAdornerWindowService != null) + { + ToolStrip.SuspendLayout(); + ddi.DropDown.Parent = _toolStripAdornerWindowService.ToolStripAdornerWindowControl; + ToolStrip.ResumeLayout(); + } + } + + /// + /// When Items change the size, Recalculate the glyph sizes. + /// + private void OnOverflowDropDownResize(object sender, EventArgs e) + { + ToolStripDropDown dropDown = sender as ToolStripDropDown; + if (dropDown.Visible) + { + // Re-Add the Glyphs to refresh the bounds... and Add new ones if new items get pushed into the OverFlow. + RemoveBodyGlyphsForOverflow(); + AddBodyGlyphsForOverflow(); + } + + if (_toolStripAdornerWindowService != null && dropDown != null) + { + _toolStripAdornerWindowService.Invalidate(); + } + } + + /// + /// Set proper cursor + /// + protected override void OnSetCursor() + { + if (_toolboxService == null) + { + _toolboxService = (IToolboxService)GetService(typeof(IToolboxService)); + } + + if (_toolboxService == null || !_toolboxService.SetCursor() || InheritanceAttribute.Equals(InheritanceAttribute.InheritedReadOnly)) + { + Cursor.Current = Cursors.Default; + } + } + + /// + /// ResumeLayout after Undone. + /// + private void OnUndone(object source, EventArgs e) + { + /// IMPORTANT : The Undo Unit .. Clears of the ITems.... + if (_editorNode != null && (ToolStrip.Items.IndexOf(_editorNode) == -1)) + { + ToolStrip.Items.Add(_editorNode); + } + if (_undoingCalled) + { + // StatusStrip required a ResumeLayout and then a performLayout... So that the Layout is proper after any user-transaction UNDONE. + ToolStrip.ResumeLayout(true/*performLayout*/); + ToolStrip.PerformLayout(); + // ReInitialize the Glyphs after Layout is resumed !! + if (SelectionService.PrimarySelection is ToolStripDropDownItem selectedItem) + { + if (_host.GetDesigner(selectedItem) is ToolStripMenuItemDesigner selectedItemDesigner) + { + selectedItemDesigner.InitializeBodyGlyphsForItems(false, selectedItem); + selectedItemDesigner.InitializeBodyGlyphsForItems(true, selectedItem); + } + } + _undoingCalled = false; + } + BehaviorService.SyncSelection(); + } + + /// + /// SuspendLayout before unDoing. + /// + private void OnUndoing(object source, EventArgs e) + { + if (CheckIfItemSelected() || SelectionService.GetComponentSelected(ToolStrip)) + { + _undoingCalled = true; + ToolStrip.SuspendLayout(); + } + } + + /// + /// SyncSelection on ToolStrip move. + /// + private void OnToolStripMove(object sender, System.EventArgs e) + { + if (SelectionService.GetComponentSelected(ToolStrip)) + { + BehaviorService.SyncSelection(); + } + } + + /// + /// Remove all the glyphs we were are not visible.. + /// + private void OnToolStripVisibleChanged(object sender, System.EventArgs e) + { + if (sender is ToolStrip tool && !tool.Visible) + { + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + Glyph[] currentBodyGlyphs = new Glyph[selMgr.BodyGlyphAdorner.Glyphs.Count]; + selMgr.BodyGlyphAdorner.Glyphs.CopyTo(currentBodyGlyphs, 0); + //Remove the ToolStripItemGlyphs. + foreach (Glyph g in currentBodyGlyphs) + { + if (g is ToolStripItemGlyph) + { + selMgr.BodyGlyphAdorner.Glyphs.Remove(g); + } + } + } + } + + /// + /// Allows a designer to filter the set of properties the component it is designing will expose through the TypeDescriptor object. This method is called immediately before its corresponding "Post" method. If you are overriding this method you should call the base implementation before you perform your own filtering. + /// + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + PropertyDescriptor prop; + string[] shadowProps = new string[] { + "Visible", + "AllowDrop", + "AllowItemReorder" + }; + Attribute[] empty = new Attribute[0]; + for (int i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ToolStripDesigner), prop, empty); + } + } + } + + /// + /// Remove the glyphs for individual items on the DropDown. + /// + private void RemoveBodyGlyphsForOverflow() + { + // now walk the ToolStrip and add glyphs for each of it's children + foreach (ToolStripItem item in ToolStrip.Items) + { + if (item is DesignerToolStripControlHost) + { + continue; + } + // make sure it's on the Overflow... + if (item.Placement == ToolStripItemPlacement.Overflow) + { + ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item); + if (dropDownItemDesigner != null) + { + ControlBodyGlyph glyph = dropDownItemDesigner.bodyGlyph; + if (glyph != null && _toolStripAdornerWindowService != null && _toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(glyph)) + { + _toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(glyph); + } + } + } + } + } + + // + // IMPORTANT FUNCTION: THIS IS CALLED FROM THE ToolStripItemGlyph to rollback + // the TemplateNode Edition on the Parent ToolStrip. + // + internal void RollBack() + { + if (_tn != null) + { + _tn.RollBack(); + _editorNode.Width = _tn.EditorToolStrip.Width; + } + } + + // + // Resets the ToolStrip Visible to be the default value + // + private void ResetVisible() + { + Visible = true; + } + + /// + /// When the Drag Data does not contain ToolStripItem; change the dragEffect to None; This will result current cursor to change into NO-SMOKING cursor + /// + private void SetDragDropEffects(DragEventArgs de) + { + if (de.Data is ToolStripItemDataObject data) + { + if (data.Owner != ToolStrip) + { + de.Effect = DragDropEffects.None; + } + else + { + de.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move; + } + } + } + + /// + /// When selection changes to the ToolStrip, show the "AddItemsButton", when it leaves, hide it. + /// + private void SelSvc_SelectionChanging(object sender, EventArgs e) + { + if (_toolStripSelected) + { + // first commit the node + if (_tn != null && _tn.Active) + { + _tn.Commit(false, false); + } + } + + bool showToolStrip = CheckIfItemSelected(); + //Check All the SelectedComponents to find is toolstrips are selected + if (!showToolStrip && !SelectionService.GetComponentSelected(ToolStrip)) + { + ToolStrip.Visible = _currentVisible; + if (!_currentVisible && _parentNotVisible) + { + ToolStrip.Parent.Visible = _currentVisible; + _parentNotVisible = false; + } + if (ToolStrip.OverflowButton.DropDown.Visible) + { + ToolStrip.OverflowButton.HideDropDown(); + } + //Always Hide the EditorNode if the ToolStrip Is Not Selected... + if (_editorNode != null) + { + _editorNode.Visible = false; + } + // Show Hide Items... + ShowHideToolStripItems(false); + _toolStripSelected = false; + } + } + + /// + /// When selection changes to the ToolStrip, show the "AddItemsButton", when it leaves, hide it. + /// + private void SelSvc_SelectionChanged(object sender, EventArgs e) + { + if (_miniToolStrip != null && _host != null) + { + bool showToolStrip = false; + bool itemSelected = CheckIfItemSelected(); + showToolStrip = itemSelected || SelectionService.GetComponentSelected(ToolStrip); + //Check All the SelectedComponents to find is toolstrips are selected + if (showToolStrip) + { + // If now the ToolStrip is selected,, Hide its Overflow + + if (SelectionService.GetComponentSelected(ToolStrip)) + { + if (!DontCloseOverflow && ToolStrip.OverflowButton.DropDown.Visible) + { + ToolStrip.OverflowButton.HideDropDown(); + } + } + + // Show Hide Items... + ShowHideToolStripItems(true); + if (!_currentVisible || !Control.Visible) + { + // Since the control wasn't visible make it visible + Control.Visible = true; + // make the current parent visible too. + if (ToolStrip.Parent is ToolStripPanel && !ToolStrip.Parent.Visible) + { + _parentNotVisible = true; + ToolStrip.Parent.Visible = true; + } + // Since the GetBodyGlyphs is called before we come here In this case where the ToolStrip is going from visible==false to visible==true we need to re-add the glyphs for the items. + BehaviorService.SyncSelection(); + } + //Always Show the EditorNode if the ToolStripIsSelected and is PrimarySelection or one of item is selected. + if (_editorNode != null && (SelectionService.PrimarySelection == ToolStrip || itemSelected)) + { + bool originalSyncSelection = FireSyncSelection; + ToolStripPanel parent = ToolStrip.Parent as ToolStripPanel; + try + { + FireSyncSelection = true; + _editorNode.Visible = true; + } + finally + { + FireSyncSelection = originalSyncSelection; + } + } + + // REQUIRED FOR THE REFRESH OF GLYPHS BUT TRY TO BE SMART ABOUT THE REGION TO INVALIDATE.... + if (!(SelectionService.PrimarySelection is ToolStripItem selectedItem)) + { + if (KeyboardHandlingService != null) + { + selectedItem = KeyboardHandlingService.SelectedDesignerControl as ToolStripItem; + } + } + _toolStripSelected = true; + } + } + } + + // + // Determines when should the Visible property be serialized. + // + private bool ShouldSerializeVisible() => !Visible; + + // + // Determines when should the AllowDrop property be serialized. + // + private bool ShouldSerializeAllowDrop() => (bool)ShadowProperties["AllowDrop"]; + + // + // Determines when should the AllowItemReorder property be serialized. + // + private bool ShouldSerializeAllowItemReorder() => (bool)ShadowProperties["AllowItemReorder"]; + + // + // This is the method that gets called when the Designer has to show thwe InSitu Edit Node, + // + internal void ShowEditNode(bool clicked) + { + // SPECIAL LOGIC TO MIMIC THE MAINMENU BEHAVIOR.. PUSH THE TEMPLATE NODE and ADD A MENUITEM HERE... + if (ToolStrip is MenuStrip) + { + // The TemplateNode should no longer be selected. + if (KeyboardHandlingService != null) + { + KeyboardHandlingService.ResetActiveTemplateNodeSelectionState(); + } + try + { + ToolStripItem newItem = AddNewItem(typeof(ToolStripMenuItem)); + if (newItem != null) + { + if (_host.GetDesigner(newItem) is ToolStripItemDesigner newItemDesigner) + { + newItemDesigner.dummyItemAdded = true; + ((ToolStripMenuItemDesigner)newItemDesigner).InitializeDropDown(); + try + { + _addingDummyItem = true; + newItemDesigner.ShowEditNode(clicked); + } + finally + { + _addingDummyItem = false; + } + } + } + } + catch (InvalidOperationException ex) + { + Debug.Assert(NewItemTransaction == null, "NewItemTransaction should have been nulled out and cancelled by now."); + IUIService uiService = (IUIService)GetService(typeof(IUIService)); + uiService.ShowError(ex.Message); + + if (KeyboardHandlingService != null) + { + KeyboardHandlingService.ResetActiveTemplateNodeSelectionState(); + } + } + } + } + + //Helper function to toggle the Item Visibility + private void ShowHideToolStripItems(bool toolStripSelected) + { + //If we arent Selected then turn the TOPLEVEL ITEMS visibility WYSIWYG + foreach (ToolStripItem item in ToolStrip.Items) + { + if (item is DesignerToolStripControlHost) + { + continue; + } + // Get the itemDesigner... + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item); + if (itemDesigner != null) + { + itemDesigner.SetItemVisible(toolStripSelected, this); + } + } + if (FireSyncSelection) + { + BehaviorService.SyncSelection(); + FireSyncSelection = false; + } + } + + // this is required when addition of TemplateNode causes the toolStrip to Layout .. E.g : Spring ToolStripStatusLabel. + private void ToolStrip_LayoutCompleted(object sender, EventArgs e) + { + if (FireSyncSelection) + { + BehaviorService.SyncSelection(); + } + } + + /// + /// Make sure the AddItem button stays in the right spot. + /// + private void ToolStrip_Resize(object sender, EventArgs e) + { + if (!_addingDummyItem && !_disposed && (CheckIfItemSelected() || SelectionService.GetComponentSelected(ToolStrip))) + { + if (_miniToolStrip != null && _miniToolStrip.Visible) + { + LayoutToolStrip(); + } + BehaviorService.SyncSelection(); + } + } + + /// + /// Handle lower level mouse input. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_CONTEXTMENU: + int x = NativeMethods.Util.SignedLOWORD(m.LParam); + int y = NativeMethods.Util.SignedHIWORD(m.LParam); + bool inBounds = GetHitTest(new Point(x, y)); + if (inBounds) + { + return; + } + base.WndProc(ref m); + break; + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: + // commit any insitu if any... + Commit(); + base.WndProc(ref m); + break; + default: + base.WndProc(ref m); + break; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDesignerUtils.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDesignerUtils.cs new file mode 100644 index 00000000000..1041b29a29a --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDesignerUtils.cs @@ -0,0 +1,646 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Design; +using System.Reflection; +using System.Security; +using System.Windows.Forms.Design.Behavior; +using Microsoft.Win32; + +namespace System.Windows.Forms.Design +{ + internal sealed class ToolStripDesignerUtils + { + private static readonly Type s_toolStripItemType = typeof(ToolStripItem); + [ThreadStatic] + private static Dictionary s_cachedToolboxItems; + [ThreadStatic] + private static int s_customToolStripItemCount = 0; + private const int TOOLSTRIPCHARCOUNT = 9; + // used to cache in the selection. This is used when the selection is changing and we need to invalidate the original selection Especially, when the selection is changed through NON UI designer action like through propertyGrid or through Doc Outline. + public static ArrayList originalSelComps; + + [ThreadStatic] + private static Dictionary s_cachedWinformsImages; + private static string s_systemWindowsFormsNamespace = typeof(ToolStripItem).Namespace; + + private ToolStripDesignerUtils() + { + } + + #region NewItemTypeLists + // This section controls the ordering of standard item types in all the various pieces of toolstrip designer UI. + // ToolStrip - Default item is determined by being first in the list + private static readonly Type[] s_newItemTypesForToolStrip = + new Type[]{typeof(ToolStripButton), typeof(ToolStripLabel), typeof(ToolStripSplitButton), typeof(ToolStripDropDownButton), typeof(ToolStripSeparator), typeof(ToolStripComboBox), typeof(ToolStripTextBox), typeof(ToolStripProgressBar)}; + // StatusStrip - Default item is determined by being first in the list + private static readonly Type[] s_newItemTypesForStatusStrip = + new Type[]{typeof(ToolStripStatusLabel), typeof(ToolStripProgressBar), typeof(ToolStripDropDownButton), typeof(ToolStripSplitButton)}; + // MenuStrip - Default item is determined by being first in the list + private static readonly Type[] s_newItemTypesForMenuStrip = + new Type[]{typeof(ToolStripMenuItem), typeof(ToolStripComboBox), typeof(ToolStripTextBox)}; + // ToolStripDropDown - roughly same as menu strip. + private static readonly Type[] s_newItemTypesForToolStripDropDownMenu = + new Type[]{typeof(ToolStripMenuItem), typeof(ToolStripComboBox), typeof(ToolStripSeparator), typeof(ToolStripTextBox)}; + #endregion + + // Get the Correct bounds for painting... + [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] + public static void GetAdjustedBounds(ToolStripItem item, ref Rectangle r) + { + // adjust bounds as per item + if (!(item is ToolStripControlHost && item.IsOnDropDown)) + { + //Deflate the SelectionGlyph for the MenuItems... + if (item is ToolStripMenuItem && item.IsOnDropDown) + { + r.Inflate(-3, -2); + r.Width++; + } + else if (item is ToolStripControlHost && !item.IsOnDropDown) + { + r.Inflate(0, -2); + } + else if (item is ToolStripMenuItem && !item.IsOnDropDown) + { + r.Inflate(-3, -3); + } + else + { + r.Inflate(-1, -1); + } + } + } + + /// + /// If IComponent is ToolStrip return ToolStrip + /// If IComponent is ToolStripItem return the Owner ToolStrip + /// If IComponent is ToolStripDropDownItem return the child DropDown ToolStrip + /// + private static ToolStrip GetToolStripFromComponent(IComponent component) + { + ToolStrip parent; + if (component is ToolStripItem stripItem) + { + if (!(stripItem is ToolStripDropDownItem)) + { + parent = stripItem.Owner; + } + else + { + parent = ((ToolStripDropDownItem)stripItem).DropDown; + } + } + else + { + parent = component as ToolStrip; + } + return parent; + } + + private static ToolboxItem GetCachedToolboxItem(Type itemType) + { + ToolboxItem tbxItem = null; + if (s_cachedToolboxItems == null) + { + s_cachedToolboxItems = new Dictionary(); + } + else if (s_cachedToolboxItems.ContainsKey(itemType)) + { + tbxItem = s_cachedToolboxItems[itemType]; + return tbxItem; + } + + // no cache hit - load the item. + if (tbxItem == null) + { + // create a toolbox item to match + tbxItem = new ToolboxItem(itemType); + } + + s_cachedToolboxItems[itemType] = tbxItem; + if (s_customToolStripItemCount > 0 && (s_customToolStripItemCount * 2 < s_cachedToolboxItems.Count)) + { + // time to clear the toolbox item cache - we've got twice the number of toolbox items than actual custom item types. + s_cachedToolboxItems.Clear(); + } + return tbxItem; + } + + // only call this for well known items. + private static Bitmap GetKnownToolboxBitmap(Type itemType) + { + if (s_cachedWinformsImages == null) + { + s_cachedWinformsImages = new Dictionary(); + } + if (!s_cachedWinformsImages.ContainsKey(itemType)) + { + Bitmap knownImage = ToolboxBitmapAttribute.GetImageFromResource(itemType, null, false) as Bitmap; + s_cachedWinformsImages[itemType] = knownImage; + return knownImage; + } + return s_cachedWinformsImages[itemType]; + } + + public static Bitmap GetToolboxBitmap(Type itemType) + { + // if and only if the namespace of the type is System.Windows.Forms. try to pull the image out of the manifest. + if (itemType.Namespace == s_systemWindowsFormsNamespace) + { + return GetKnownToolboxBitmap(itemType); + } + + // check to see if we've got a toolbox item, and use it. + ToolboxItem tbxItem = GetCachedToolboxItem(itemType); + if (tbxItem != null) + { + return tbxItem.Bitmap; + } + // if all else fails, throw up a default image. + return GetKnownToolboxBitmap(typeof(Component)); + } + + /// + /// Fishes out the display name attribute from the Toolbox item if not present, uses Type.Name + /// + public static string GetToolboxDescription(Type itemType) + { + string currentName = null; + ToolboxItem tbxItem = GetCachedToolboxItem(itemType); + if (tbxItem != null) + { + currentName = tbxItem.DisplayName; + } + if (currentName == null) + { + currentName = itemType.Name; + } + if (currentName.StartsWith("ToolStrip")) + { + return currentName.Substring(TOOLSTRIPCHARCOUNT); + } + return currentName; + } + + + /// + /// The first item returned should be the DefaultItem to create on the ToolStrip + /// + public static Type[] GetStandardItemTypes(IComponent component) + { + ToolStrip toolStrip = GetToolStripFromComponent(component); + if (toolStrip is MenuStrip) + { + return s_newItemTypesForMenuStrip; + } + else if (toolStrip is ToolStripDropDownMenu) + { + // ToolStripDropDown gets default items. + return s_newItemTypesForToolStripDropDownMenu; + } + else if (toolStrip is StatusStrip) + { + return s_newItemTypesForStatusStrip; + } + Debug.Assert(toolStrip != null, "why werent we handed a toolstrip here? returning default list"); + return s_newItemTypesForToolStrip; + } + + private static ToolStripItemDesignerAvailability GetDesignerVisibility(ToolStrip toolStrip) + { + ToolStripItemDesignerAvailability visiblity; + if (toolStrip is StatusStrip) + { + visiblity = ToolStripItemDesignerAvailability.StatusStrip; + } + else if (toolStrip is MenuStrip) + { + visiblity = ToolStripItemDesignerAvailability.MenuStrip; + } + else if (toolStrip is ToolStripDropDownMenu) + { + visiblity = ToolStripItemDesignerAvailability.ContextMenuStrip; + } + else + { + visiblity = ToolStripItemDesignerAvailability.ToolStrip; + } + return visiblity; + } + + + public static Type[] GetCustomItemTypes(IComponent component, IServiceProvider serviceProvider) + { + ITypeDiscoveryService discoveryService = null; + if (serviceProvider != null) + { + discoveryService = serviceProvider.GetService(typeof(ITypeDiscoveryService)) as ITypeDiscoveryService; + } + return GetCustomItemTypes(component, discoveryService); + } + public static Type[] GetCustomItemTypes(IComponent component, ITypeDiscoveryService discoveryService) + { + if (discoveryService != null) + { + // fish out all types which derive from toolstrip item + ICollection itemTypes = discoveryService.GetTypes(s_toolStripItemType, false /*excludeGlobalTypes*/); + ToolStrip toolStrip = GetToolStripFromComponent(component); + // determine the value of the visibility attribute which matches the current toolstrip type. + ToolStripItemDesignerAvailability currentToolStripVisibility = GetDesignerVisibility(toolStrip); + Debug.Assert(currentToolStripVisibility != ToolStripItemDesignerAvailability.None, "Why is GetDesignerVisibility returning None?"); + // fish out the ones we've already listed. + Type[] stockItemTypeList = GetStandardItemTypes(component); + if (currentToolStripVisibility != ToolStripItemDesignerAvailability.None) + { + ArrayList createableTypes = new ArrayList(itemTypes.Count); + foreach (Type t in itemTypes) + { + if (t.IsAbstract) + { + continue; + } + if (!t.IsPublic && !t.IsNestedPublic) + { + continue; + } + if (t.ContainsGenericParameters) + { + continue; + } + // Check if we have public constructor... + ConstructorInfo ctor = t.GetConstructor(new Type[0]); + if (ctor == null) + { + continue; + } + + // if the visibility matches the current toolstrip type, add it to the list of possible types to create. + ToolStripItemDesignerAvailabilityAttribute visiblityAttribute = (ToolStripItemDesignerAvailabilityAttribute)TypeDescriptor.GetAttributes(t)[typeof(ToolStripItemDesignerAvailabilityAttribute)]; + if (visiblityAttribute != null && ((visiblityAttribute.ItemAdditionVisibility & currentToolStripVisibility) == currentToolStripVisibility)) + { + bool isStockType = false; + // PERF: consider a dictionary - but this list will usually be 3-7 items. + foreach (Type stockType in stockItemTypeList) + { + if (stockType == t) + { + isStockType = true; + break; + } + } + if (!isStockType) + { + createableTypes.Add(t); + } + } + } + + if (createableTypes.Count > 0) + { + Type[] createableTypesArray = new Type[createableTypes.Count]; + createableTypes.CopyTo(createableTypesArray, 0); + s_customToolStripItemCount = createableTypes.Count; + return createableTypesArray; + } + } + } + s_customToolStripItemCount = 0; + return new Type[0]; + } + + /// + /// wraps the result of GetStandardItemTypes in ItemTypeToolStripMenuItems. + /// + public static ToolStripItem[] GetStandardItemMenuItems(IComponent component, EventHandler onClick, bool convertTo) + { + Type[] standardTypes = GetStandardItemTypes(component); + ToolStripItem[] items = new ToolStripItem[standardTypes.Length]; + for (int i = 0; i < standardTypes.Length; i++) + { + ItemTypeToolStripMenuItem item = new ItemTypeToolStripMenuItem(standardTypes[i]) + { + ConvertTo = convertTo + }; + if (onClick != null) + { + item.Click += onClick; + } + items[i] = item; + } + return items; + } + + /// + /// wraps the result of GetCustomItemTypes in ItemTypeToolStripMenuItems. + /// + public static ToolStripItem[] GetCustomItemMenuItems(IComponent component, EventHandler onClick, bool convertTo, IServiceProvider serviceProvider) + { + Type[] customTypes = GetCustomItemTypes(component, serviceProvider); + ToolStripItem[] items = new ToolStripItem[customTypes.Length]; + for (int i = 0; i < customTypes.Length; i++) + { + ItemTypeToolStripMenuItem item = new ItemTypeToolStripMenuItem(customTypes[i]) + { + ConvertTo = convertTo + }; + if (onClick != null) + { + item.Click += onClick; + } + items[i] = item; + } + return items; + } + + /// + /// build up a list of standard items separated by the custom items + /// + + public static NewItemsContextMenuStrip GetNewItemDropDown(IComponent component, ToolStripItem currentItem, EventHandler onClick, bool convertTo, IServiceProvider serviceProvider, bool populateCustom) + { + NewItemsContextMenuStrip contextMenu = new NewItemsContextMenuStrip(component, currentItem, onClick, convertTo, serviceProvider); + contextMenu.GroupOrdering.Add("StandardList"); + contextMenu.GroupOrdering.Add("CustomList"); + // plumb through the standard and custom items. + foreach (ToolStripItem item in GetStandardItemMenuItems(component, onClick, convertTo)) + { + contextMenu.Groups["StandardList"].Items.Add(item); + if (convertTo) + { + if (item is ItemTypeToolStripMenuItem toolItem && currentItem != null && toolItem.ItemType == currentItem.GetType()) + { + toolItem.Enabled = false; + } + } + } + if (populateCustom) + { + GetCustomNewItemDropDown(contextMenu, component, currentItem, onClick, convertTo, serviceProvider); + } + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + contextMenu.Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]; + contextMenu.Font = (Font)uis.Styles["DialogFont"]; + if (uis.Styles["VsColorPanelText"] is Color) + { + contextMenu.ForeColor = (Color)uis.Styles["VsColorPanelText"]; + } + } + contextMenu.Populate(); + return contextMenu; + } + + public static void GetCustomNewItemDropDown(NewItemsContextMenuStrip contextMenu, IComponent component, ToolStripItem currentItem, EventHandler onClick, bool convertTo, IServiceProvider serviceProvider) + { + foreach (ToolStripItem item in GetCustomItemMenuItems(component, onClick, convertTo, serviceProvider)) + { + contextMenu.Groups["CustomList"].Items.Add(item); + if (convertTo) + { + if (item is ItemTypeToolStripMenuItem toolItem && currentItem != null && toolItem.ItemType == currentItem.GetType()) + { + toolItem.Enabled = false; + } + } + } + contextMenu.Populate(); + } + + public static void InvalidateSelection(ArrayList originalSelComps, ToolStripItem nextSelection, IServiceProvider provider, bool shiftPressed) + { + // if we are not selecting a ToolStripItem then return (dont invalidate). + if (nextSelection == null || provider == null) + { + return; + } + //InvalidateOriginal SelectedComponents. + Region invalidateRegion = null; + Region itemRegion = null; + int GLYPHBORDER = 1; + int GLYPHINSET = 2; + ToolStripItemDesigner designer = null; + bool templateNodeSelected = false; + + try + { + Rectangle invalidateBounds = Rectangle.Empty; + IDesignerHost designerHost = (IDesignerHost)provider.GetService(typeof(IDesignerHost)); + + if (designerHost != null) + { + foreach (Component comp in originalSelComps) + { + if (comp is ToolStripItem selItem) + { + if ((originalSelComps.Count > 1) || + (originalSelComps.Count == 1 && selItem.GetCurrentParent() != nextSelection.GetCurrentParent()) || + selItem is ToolStripSeparator || selItem is ToolStripControlHost || !selItem.IsOnDropDown || selItem.IsOnOverflow) + { + // finally Invalidate the selection rect ... + designer = designerHost.GetDesigner(selItem) as ToolStripItemDesigner; + if (designer != null) + { + invalidateBounds = designer.GetGlyphBounds(); + GetAdjustedBounds(selItem, ref invalidateBounds); + invalidateBounds.Inflate(GLYPHBORDER, GLYPHBORDER); + + if (invalidateRegion == null) + { + invalidateRegion = new Region(invalidateBounds); + invalidateBounds.Inflate(-GLYPHINSET, -GLYPHINSET); + invalidateRegion.Exclude(invalidateBounds); + } + else + { + itemRegion = new Region(invalidateBounds); + invalidateBounds.Inflate(-GLYPHINSET, -GLYPHINSET); + itemRegion.Exclude(invalidateBounds); + invalidateRegion.Union(itemRegion); + } + } + } + } + } + } + + if (invalidateRegion != null || templateNodeSelected || shiftPressed) + { + BehaviorService behaviorService = (BehaviorService)provider.GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + if (invalidateRegion != null) + { + behaviorService.Invalidate(invalidateRegion); + } + + // When a ToolStripItem is PrimarySelection, the glyph bounds are not invalidated through the SelectionManager so we have to do this. + designer = designerHost.GetDesigner(nextSelection) as ToolStripItemDesigner; + if (designer != null) + { + invalidateBounds = designer.GetGlyphBounds(); + GetAdjustedBounds(nextSelection, ref invalidateBounds); + invalidateBounds.Inflate(GLYPHBORDER, GLYPHBORDER); + invalidateRegion = new Region(invalidateBounds); + + invalidateBounds.Inflate(-GLYPHINSET, -GLYPHINSET); + invalidateRegion.Exclude(invalidateBounds); + behaviorService.Invalidate(invalidateRegion); + } + } + } + } + finally + { + if (invalidateRegion != null) + { + invalidateRegion.Dispose(); + } + + if (itemRegion != null) + { + itemRegion.Dispose(); + } + } + } + + /// represents cached information about the display + internal static class DisplayInformation + { + private static bool s_highContrast; //whether we are under hight contrast mode + private static bool s_lowRes; //whether we are under low resolution mode + private static bool s_isTerminalServerSession; //whether this application is run on a terminal server (remote desktop) + private static bool s_highContrastSettingValid; //indicates whether the high contrast setting is correct + private static bool s_lowResSettingValid; //indicates whether the low resolution setting is correct + private static bool s_terminalSettingValid; //indicates whether the terminal server setting is correct + private static short s_bitsPerPixel; + private static bool s_dropShadowSettingValid; + private static bool s_dropShadowEnabled; + + + static DisplayInformation() + { + SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(UserPreferenceChanged); + SystemEvents.DisplaySettingsChanged += new EventHandler(DisplaySettingChanged); + } + + public static short BitsPerPixel + { + get + { + if (s_bitsPerPixel == 0) + { + foreach (Screen s in Screen.AllScreens) + { + if (s_bitsPerPixel == 0) + { + s_bitsPerPixel = (short)s.BitsPerPixel; + } + else + { + s_bitsPerPixel = (short)Math.Min(s.BitsPerPixel, s_bitsPerPixel); + } + } + } + return s_bitsPerPixel; + } + } + + /// + ///tests to see if the monitor is in low resolution mode (8-bit color depth or less). + /// + public static bool LowResolution + { + get + { + if (s_lowResSettingValid) + { + return s_lowRes; + } + s_lowRes = BitsPerPixel <= 8; + s_lowResSettingValid = true; + return s_lowRes; + } + } + + /// + ///tests to see if we are under high contrast mode + /// + public static bool HighContrast + { + get + { + if (s_highContrastSettingValid) + { + return s_highContrast; + } + s_highContrast = SystemInformation.HighContrast; + s_highContrastSettingValid = true; + return s_highContrast; + } + } + public static bool IsDropShadowEnabled + { + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + get + { + if (s_dropShadowSettingValid) + { + return s_dropShadowEnabled; + } + s_dropShadowEnabled = SystemInformation.IsDropShadowEnabled; + s_dropShadowSettingValid = true; + return s_dropShadowEnabled; + } + } + + /// + ///test to see if we are under terminal server mode + /// + public static bool TerminalServer + { + get + { + if (s_terminalSettingValid) + { + return s_isTerminalServerSession; + } + s_isTerminalServerSession = SystemInformation.TerminalServerSession; + s_terminalSettingValid = true; + return s_isTerminalServerSession; + } + } + + /// + ///event handler for change in display setting + /// + private static void DisplaySettingChanged(object obj, EventArgs ea) + { + s_highContrastSettingValid = false; + s_lowResSettingValid = false; + s_terminalSettingValid = false; + s_dropShadowSettingValid = false; + } + + /// + ///event handler for change in user preference + /// + private static void UserPreferenceChanged(object obj, UserPreferenceChangedEventArgs ea) + { + s_highContrastSettingValid = false; + s_lowResSettingValid = false; + s_terminalSettingValid = false; + s_dropShadowSettingValid = false; + s_bitsPerPixel = 0; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDropDownDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDropDownDesigner.cs new file mode 100644 index 00000000000..c340dd338d3 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDropDownDesigner.cs @@ -0,0 +1,784 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Configuration; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Globalization; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// Designer for ToolStripDropDowns...just provides the Edit... verb. + /// + internal class ToolStripDropDownDesigner : ComponentDesigner + { + private ISelectionService selSvc; + private MenuStrip designMenu; + private ToolStripMenuItem menuItem; + private IDesignerHost host; + private ToolStripDropDown dropDown; + private bool selected; + private ControlBodyGlyph dummyToolStripGlyph; + private uint _editingCollection = 0; // non-zero if the collection editor is up for this ToolStrip or a child of it. + MainMenu parentMenu = null; + FormDocumentDesigner parentFormDesigner = null; + internal ToolStripMenuItem currentParent = null; + private INestedContainer nestedContainer = null; //NestedContainer for our DesignTime MenuItem. + private UndoEngine undoEngine = null; + + /// + /// ShadowProperty. + /// + private bool AutoClose + { + get => (bool)ShadowProperties["AutoClose"]; + set => ShadowProperties["AutoClose"] = value; + } + + private bool AllowDrop + { + get => (bool)ShadowProperties["AllowDrop"]; + set => ShadowProperties["AllowDrop"] = value; + } + + /// + /// Adds designer actions to the ActionLists collection. + /// + public override DesignerActionListCollection ActionLists + { + get + { + DesignerActionListCollection actionLists = new DesignerActionListCollection(); + actionLists.AddRange(base.ActionLists); + ContextMenuStripActionList cmActionList = new ContextMenuStripActionList(this); + if (cmActionList != null) + { + actionLists.Add(cmActionList); + } + // finally add the verbs for this component there... + DesignerVerbCollection cmVerbs = this.Verbs; + if (cmVerbs != null && cmVerbs.Count != 0) + { + DesignerVerb[] cmverbsArray = new DesignerVerb[cmVerbs.Count]; + cmVerbs.CopyTo(cmverbsArray, 0); + actionLists.Add(new DesignerActionVerbList(cmverbsArray)); + } + return actionLists; + } + } + + /// + /// The ToolStripItems are the associated components. We want those to come with in any cut, copy opreations. + /// + public override System.Collections.ICollection AssociatedComponents + { + get => ((ToolStrip)Component).Items; + } + + // Dummy menuItem that is used for the contextMenuStrip design + public ToolStripMenuItem DesignerMenuItem + { + get => menuItem; + } + + /// + /// Set by the ToolStripItemCollectionEditor when it's launched for this The Items property doesnt open another instance + /// of collectioneditor. We count this so that we can deal with nestings. + /// + internal bool EditingCollection + { + get => _editingCollection != 0; + set + { + if (value) + { + _editingCollection++; + } + else + { + _editingCollection--; + } + } + } + + // ContextMenuStrip if Inherited ACT as Readonly. + protected override InheritanceAttribute InheritanceAttribute + { + get + { + if ((base.InheritanceAttribute == InheritanceAttribute.Inherited)) + { + return InheritanceAttribute.InheritedReadOnly; + } + return base.InheritanceAttribute; + } + } + + /// + /// Prefilter this property so that we can set the right To Left on the Design Menu... + /// + private RightToLeft RightToLeft + { + get => dropDown.RightToLeft; + set + { + if (menuItem != null && designMenu != null && value != RightToLeft) + { + Rectangle bounds = Rectangle.Empty; + try + { + bounds = dropDown.Bounds; + menuItem.HideDropDown(); + designMenu.RightToLeft = value; + dropDown.RightToLeft = value; + } + finally + { + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null && bounds != Rectangle.Empty) + { + behaviorService.Invalidate(bounds); + } + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)host.GetDesigner(menuItem); + if (itemDesigner != null) + { + itemDesigner.InitializeDropDown(); + } + } + } + } + } + + /// + /// shadowing the SettingsKey so we can default it to be RootComponent.Name + "." + Control.Name + /// + private string SettingsKey + { + get + { + if (string.IsNullOrEmpty((string)ShadowProperties["SettingsKey"])) + { + IPersistComponentSettings persistableComponent = Component as IPersistComponentSettings; + if (persistableComponent != null && host != null) + { + if (persistableComponent.SettingsKey == null) + { + IComponent rootComponent = host.RootComponent; + if (rootComponent != null && rootComponent != persistableComponent) + { + ShadowProperties["SettingsKey"] = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", rootComponent.Site.Name, Component.Site.Name); + } + else + { + ShadowProperties["SettingsKey"] = Component.Site.Name; + } + } + persistableComponent.SettingsKey = ShadowProperties["SettingsKey"] as string; + return persistableComponent.SettingsKey; + } + } + return ShadowProperties["SettingsKey"] as string; + } + set + { + ShadowProperties["SettingsKey"] = value; + if (Component is IPersistComponentSettings persistableComponent) + { + persistableComponent.SettingsKey = value; + } + } + } + + // We have to add the glyphs ourselves. + private void AddSelectionGlyphs(SelectionManager selMgr, ISelectionService selectionService) + { + //If one or many of our items are selected then Add Selection Glyphs ourselces since this is a ComponentDesigner which wont get called on the "GetGlyphs" + ICollection selComponents = selectionService.GetSelectedComponents(); + GlyphCollection glyphs = new GlyphCollection(); + foreach (object selComp in selComponents) + { + if (selComp is ToolStripItem item) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)host.GetDesigner(item); + if (itemDesigner != null) + { + itemDesigner.GetGlyphs(ref glyphs, new ResizeBehavior(item.Site)); + } + } + } + // Get the Glyphs union Rectangle. + if (glyphs.Count > 0) + { + // Add Glyphs and then invalidate the unionRect + selMgr.SelectionGlyphAdorner.Glyphs.AddRange(glyphs); + } + } + + // internal method called by outside designers to add glyphs for the ContextMenuStrip + internal void AddSelectionGlyphs() + { + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + if (selMgr != null) + { + AddSelectionGlyphs(selMgr, selSvc); + } + } + + /// + /// Disposes of this designer. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + // Unhook our services + if (selSvc != null) + { + selSvc.SelectionChanged -= new EventHandler(this.OnSelectionChanged); + selSvc.SelectionChanging -= new EventHandler(this.OnSelectionChanging); + } + + DisposeMenu(); + if (designMenu != null) + { + designMenu.Dispose(); + designMenu = null; + } + if (dummyToolStripGlyph != null) + { + dummyToolStripGlyph = null; + } + if (undoEngine != null) + { + undoEngine.Undone -= new EventHandler(this.OnUndone); + } + } + base.Dispose(disposing); + } + + /// + /// Disposes of this dummy menuItem and its designer.. + /// + private void DisposeMenu() + { + HideMenu(); + if (host.RootComponent is Control form) + { + if (designMenu != null) + { + form.Controls.Remove(designMenu); + } + if (menuItem != null) + { + if (nestedContainer != null) + { + nestedContainer.Dispose(); + nestedContainer = null; + } + menuItem.Dispose(); + menuItem = null; + } + } + } + + // private helper function to Hide the ContextMenu structure. + private void HideMenu() + { + if (menuItem == null) + { + return; + } + //Add MenuBack + if (parentMenu != null && parentFormDesigner != null) + { + parentFormDesigner.Menu = parentMenu; + } + + selected = false; + if (host.RootComponent is Control form) + { + menuItem.DropDown.AutoClose = true; + menuItem.HideDropDown(); + menuItem.Visible = false; + //Hide the MenuItem DropDown. + designMenu.Visible = false; + //Invalidate the Bounds.. + ToolStripAdornerWindowService toolStripAdornerWindowService = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService)); + if (toolStripAdornerWindowService != null) + { + //toolStripAdornerWindowService.Invalidate(boundsToInvalidate); + toolStripAdornerWindowService.Invalidate(); + } + + //Query for the Behavior Service and Remove Glyph.... + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + if (dummyToolStripGlyph != null) + { + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + if (selMgr != null) + { + if (selMgr.BodyGlyphAdorner.Glyphs.Contains(dummyToolStripGlyph)) + { + selMgr.BodyGlyphAdorner.Glyphs.Remove(dummyToolStripGlyph); + } + selMgr.Refresh(); + } + } + dummyToolStripGlyph = null; + } + + //Unhook all the events for DesignMenuItem + if (menuItem != null) + { + if (host.GetDesigner(menuItem) is ToolStripMenuItemDesigner itemDesigner) + { + itemDesigner.UnHookEvents(); + itemDesigner.RemoveTypeHereNode(menuItem); + } + } + } + } + + /// + /// Initialize the item. + /// + // EditorServiceContext is newed up to add Edit Items verb. + [SuppressMessage("Microsoft.Performance", "CA1806:DoNotIgnoreMethodResults")] + public override void Initialize(IComponent component) + { + base.Initialize(component); + host = (IDesignerHost)GetService(typeof(IDesignerHost)); + //Add the EditService so that the ToolStrip can do its own Tab and Keyboard Handling + ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (keyboardHandlingService == null) + { + keyboardHandlingService = new ToolStripKeyboardHandlingService(component.Site); + } + + //Add the InsituEditService so that the ToolStrip can do its own Insitu Editing + ISupportInSituService inSituService = (ISupportInSituService)GetService(typeof(ISupportInSituService)); + if (inSituService == null) + { + inSituService = new ToolStripInSituService(Component.Site); + } + + dropDown = (ToolStripDropDown)Component; + dropDown.Visible = false; + //shadow properties as we would change these for DropDowns at DesignTime. + AutoClose = dropDown.AutoClose; + AllowDrop = dropDown.AllowDrop; + + selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + if (selSvc != null) + { + // first select the rootComponent and then hook on the events... but not if we are loading - VSWhidbey #484576 + if (host != null && !host.Loading) + { + selSvc.SetSelectedComponents(new IComponent[] { host.RootComponent }, SelectionTypes.Replace); + } + selSvc.SelectionChanging += new EventHandler(OnSelectionChanging); + selSvc.SelectionChanged += new EventHandler(OnSelectionChanged); + } + + designMenu = new MenuStrip + { + Visible = false, + AutoSize = false, + Dock = DockStyle.Top + }; + if (DpiHelper.IsScalingRequired) + { + designMenu.Height = DpiHelper.LogicalToDeviceUnitsY(designMenu.Height); + } + //Add MenuItem + if (host.RootComponent is Control form) + { + menuItem = new ToolStripMenuItem + { + BackColor = SystemColors.Window, + Name = Component.Site.Name + }; + menuItem.Text = (dropDown != null) ? dropDown.GetType().Name : menuItem.Name; + designMenu.Items.Add(menuItem); + form.Controls.Add(designMenu); + designMenu.SendToBack(); + nestedContainer = GetService(typeof(INestedContainer)) as INestedContainer; + if (nestedContainer != null) + { + nestedContainer.Add(menuItem, "ContextMenuStrip"); + } + } + + // init the verb. + new EditorServiceContext(this, TypeDescriptor.GetProperties(Component)["Items"], SR.ToolStripItemCollectionEditorVerb); + // use the UndoEngine.Undone to Show the DropDown Again.. + if (undoEngine == null) + { + undoEngine = GetService(typeof(UndoEngine)) as UndoEngine; + if (undoEngine != null) + { + undoEngine.Undone += new EventHandler(OnUndone); + } + } + } + + // Helper function to check if the ToolStripItem on the ContextMenu is selected. + private bool IsContextMenuStripItemSelected(ISelectionService selectionService) + { + bool showDesignMenu = false; + if (menuItem == null) + { + return showDesignMenu; + } + + ToolStripDropDown topmost = null; + IComponent comp = (IComponent)selectionService.PrimarySelection; + if (comp == null && dropDown.Visible) + { + ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (keyboardHandlingService != null) + { + comp = (IComponent)keyboardHandlingService.SelectedDesignerControl; + } + } + // This case covers (a) and (b) above.... + if (comp is ToolStripDropDownItem) + { + if (comp is ToolStripDropDownItem currentItem && currentItem == menuItem) + { + topmost = menuItem.DropDown; + } + else + { + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)host.GetDesigner(comp); + if (itemDesigner != null) + { + topmost = itemDesigner.GetFirstDropDown((ToolStripDropDownItem)comp); + } + } + } + else if (comp is ToolStripItem) //case (c) + { + if (!(((ToolStripItem)comp).GetCurrentParent() is ToolStripDropDown parent)) + { + // Try if the item has not laid out... + parent = ((ToolStripItem)comp).Owner as ToolStripDropDown; + } + if (parent != null && parent.Visible) + { + ToolStripItem ownerItem = parent.OwnerItem; + if (ownerItem != null && ownerItem == menuItem) + { + topmost = menuItem.DropDown; + } + else + { + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)host.GetDesigner(ownerItem); + if (itemDesigner != null) + { + topmost = itemDesigner.GetFirstDropDown((ToolStripDropDownItem)ownerItem); + } + } + } + } + if (topmost != null) + { + ToolStripItem topMostItem = topmost.OwnerItem; + if (topMostItem == menuItem) + { + showDesignMenu = true; + } + } + return showDesignMenu; + } + + /// + /// Listens SelectionChanging to Show the MenuDesigner. + /// + private void OnSelectionChanging(object sender, EventArgs e) + { + ISelectionService selectionService = (ISelectionService)sender; + // If we are no longer selected ... Hide the DropDown + bool showDesignMenu = IsContextMenuStripItemSelected(selectionService) || Component.Equals(selectionService.PrimarySelection); + if (selected && !showDesignMenu) + { + HideMenu(); + } + } + + /// + /// Listens SelectionChanged to Show the MenuDesigner. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + if (Component == null || menuItem == null) + { + return; + } + ISelectionService selectionService = (ISelectionService)sender; + // Select the container if TopLevel Dummy MenuItem is selected. + if (selectionService.GetComponentSelected(menuItem)) + { + selectionService.SetSelectedComponents(new IComponent[] { Component }, SelectionTypes.Replace); + } + + //return if DropDown is already is selected. + if (Component.Equals(selectionService.PrimarySelection) && selected) + { + return; + } + + bool showDesignMenu = IsContextMenuStripItemSelected(selectionService) || Component.Equals(selectionService.PrimarySelection); + + if (showDesignMenu) + { + if (!dropDown.Visible) + { + ShowMenu(); + } + //Selection change would remove our Glyph from the BodyGlyph Collection. + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + if (selMgr != null) + { + if (dummyToolStripGlyph != null) + { + selMgr.BodyGlyphAdorner.Glyphs.Insert(0, dummyToolStripGlyph); + } + // Add our SelectionGlyphs and Invalidate. + AddSelectionGlyphs(selMgr, selectionService); + } + } + } + + + /// + /// Allows a designer to filter the set of properties the component it is designing will expose through the TypeDescriptor object. This method is called immediately before its corresponding "Post" method. If you are overriding this method you should call the base implementation before you perform your own filtering. + /// + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + PropertyDescriptor prop; + string[] shadowProps = new string[] { "AutoClose", "SettingsKey", "RightToLeft", "AllowDrop" }; + Attribute[] empty = new Attribute[0]; + for (int i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ToolStripDropDownDesigner), prop, empty); + } + } + } + + // Reset Settings. + public void ResetSettingsKey() + { + if (Component is IPersistComponentSettings persistableComponent) + { + SettingsKey = null; + } + } + + // + // Resets the ToolStripDropDown AutoClose to be the default padding + // + private void ResetAutoClose() + { + ShadowProperties["AutoClose"] = true; + } + + // + // Restores the ToolStripDropDown AutoClose to be the value set in the property grid. + // + private void RestoreAutoClose() + { + dropDown.AutoClose = (bool)ShadowProperties["AutoClose"]; + } + + // + // Resets the ToolStripDropDown AllowDrop to be the default padding + // + private void ResetAllowDrop() + { + ShadowProperties["AllowDrop"] = false; + } + + // + // Restores the ToolStripDropDown AllowDrop to be the value set in the property grid. + // + private void RestoreAllowDrop() + { + dropDown.AutoClose = (bool)ShadowProperties["AllowDrop"]; + } + + // + // Resets the ToolStripDropDown RightToLeft to be the default RightToLeft + // + private void ResetRightToLeft() + { + RightToLeft = RightToLeft.No; + } + + /// + /// Show the MenuDesigner; used by ToolStripmenuItemdesigner to show the menu when the user selects the dropDown item through the PG or Document outline. The editor node will be selected by default. + /// + public void ShowMenu() + { + int count = dropDown.Items.Count - 1; + if (count >= 0) + { + ShowMenu(dropDown.Items[count]); + } + else + { + ShowMenu(null); + } + } + + /// + /// Show the MenuDesigner; used by ToolStripmenuItemdesigner to show the menu when the user selects the dropDown item through the PG or Document outline. The input toolstrip item will be selected. + /// + public void ShowMenu(ToolStripItem selectedItem) + { + if (menuItem == null) + { + return; + } + Control parent = designMenu.Parent as Control; + if (parent is Form parentForm) + { + parentFormDesigner = host.GetDesigner(parentForm) as FormDocumentDesigner; + if (parentFormDesigner != null && parentFormDesigner.Menu != null) + { + parentMenu = parentFormDesigner.Menu; + parentFormDesigner.Menu = null; + } + } + selected = true; + designMenu.Visible = true; + designMenu.BringToFront(); + menuItem.Visible = true; + // Check if this is a design-time DropDown + if (currentParent != null && currentParent != menuItem) + { + if (host.GetDesigner(currentParent) is ToolStripMenuItemDesigner ownerItemDesigner) + { + ownerItemDesigner.RemoveTypeHereNode(currentParent); + } + } + + //Everytime you hide/show .. set the DropDown of the designer MenuItem to the component dropDown beign designed. + menuItem.DropDown = dropDown; + menuItem.DropDown.OwnerItem = menuItem; + if (dropDown.Items.Count > 0) + { + ToolStripItem[] items = new ToolStripItem[dropDown.Items.Count]; + dropDown.Items.CopyTo(items, 0); + foreach (ToolStripItem toolItem in items) + { + if (toolItem is DesignerToolStripControlHost) + { + dropDown.Items.Remove(toolItem); + } + } + } + + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)host.GetDesigner(menuItem); + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + // Show the contextMenu only if the dummy menuStrip is contained in the Form. Refer to VsWhidbey 484317 for more details. + if (itemDesigner != null && parent != null) + { + Rectangle parentBounds = behaviorService.ControlRectInAdornerWindow(parent); + Rectangle menuBounds = behaviorService.ControlRectInAdornerWindow(designMenu); + if (ToolStripDesigner.IsGlyphTotallyVisible(menuBounds, parentBounds)) + { + itemDesigner.InitializeDropDown(); + } + } + + if (dummyToolStripGlyph == null) + { + Point loc = behaviorService.ControlToAdornerWindow(designMenu); + Rectangle r = designMenu.Bounds; + r.Offset(loc); + dummyToolStripGlyph = new ControlBodyGlyph(r, Cursor.Current, menuItem, new ContextMenuStripBehavior(menuItem)); + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + if (selMgr != null) + { + selMgr.BodyGlyphAdorner.Glyphs.Insert(0, dummyToolStripGlyph); + } + } + + if (selectedItem != null) + { + ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (keyboardHandlingService != null) + { + keyboardHandlingService.SelectedDesignerControl = selectedItem; + } + } + } + } + + // Should the designer serialize the settings? + private bool ShouldSerializeSettingsKey() => (Component is IPersistComponentSettings persistableComponent && persistableComponent.SaveSettings && SettingsKey != null); + + // + // Since we're shadowing ToolStripDropDown AutoClose, we get called here to determine whether or not to serialize + // + private bool ShouldSerializeAutoClose() => (!(bool)ShadowProperties["AutoClose"]); + + // + // Since we're shadowing ToolStripDropDown AllowDrop, we get called here to determine whether or not to serialize + // + private bool ShouldSerializeAllowDrop() => AllowDrop; + + // + // Since we're shadowing ToolStripDropDown RightToLeft, we get called here to determine whether or not to serialize + // + private bool ShouldSerializeRightToLeft() => RightToLeft != RightToLeft.No; + + /// + /// ResumeLayout after Undone. + /// + private void OnUndone(object source, EventArgs e) + { + if (selSvc != null && Component.Equals(selSvc.PrimarySelection)) + { + HideMenu(); + ShowMenu(); + } + } + + /// + /// This is an internal class which provides the Behavior for our MenuStrip Body Glyph. This will just eat the MouseUps... + /// + internal class ContextMenuStripBehavior : System.Windows.Forms.Design.Behavior.Behavior + { + readonly ToolStripMenuItem _item; + internal ContextMenuStripBehavior(ToolStripMenuItem menuItem) + { + _item = menuItem; + } + + public override bool OnMouseUp(Glyph g, MouseButtons button) + { + if (button == MouseButtons.Left) + { + return true; + } + return false; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDropDownItemDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDropDownItemDesigner.cs new file mode 100644 index 00000000000..000a4254095 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripDropDownItemDesigner.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; + +namespace System.Windows.Forms.Design +{ + /// + /// Designer for ToolStripDropDownItems. This is here so only the dropdown items get the "Edit Items..." verb. + /// + internal class ToolStripDropDownItemDesigner : ToolStripItemDesigner + { + /// + /// Initialize the item. + /// + public override void Initialize(IComponent component) + { + base.Initialize(component); + } + + /// + /// The ToolStripItems are the associated components. We want those to come with in any cut, copy opreations. + /// + public override System.Collections.ICollection AssociatedComponents + { + get + { + if (Component is ToolStripDropDownItem item && item.DropDown.IsAutoGenerated) + { + return item.DropDownItems; + } + return base.AssociatedComponents; + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripEditorManager.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripEditorManager.cs new file mode 100644 index 00000000000..649a3961b2f --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripEditorManager.cs @@ -0,0 +1,140 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// This internal Class is used by all TOPLEVEL ToolStripItems to show the InSitu Editor. When the ToolStripItem receives the MouseDown on its Glyph it calls the "ActivateEditor" Function on this EditorManager. The ActivateEditor Function checks for any existing "EDITOR" active, closes that down and now opens the new editor on the "AdornerWindow". This class is also responsible for "hookingup" to the F2 Command on VS. + /// + internal class ToolStripEditorManager + { + // Local copy of BehaviorService so that we can add the Insitu Editor to the AdornerWindow. + private readonly BehaviorService _behaviorService; + // Component for this InSitu Editor... (this is a ToolStripItem) that wants to go into InSitu + private readonly IDesignerHost _designerHost; + // This is always ToolStrip + private readonly IComponent _comp; + // The current Bounds of the Insitu Editor on Adorner Window.. These are required for invalidation. + private Rectangle _lastKnownEditorBounds = Rectangle.Empty; + // The encapsulated Editor. + private ToolStripEditorControl _editor; + // Actual ToolStripEditor for the current ToolStripItem. + private ToolStripTemplateNode _editorUI; + // The Current ToolStripItem that needs to go into the InSitu Mode. We keep a local copy so that when a new item comes in, we can "ROLLBACK" the existing edit. + private ToolStripItem _currentItem; + // The designer for current ToolStripItem. + private ToolStripItemDesigner _itemDesigner; + + public ToolStripEditorManager(IComponent comp) + { + // get the parent + _comp = comp; + _behaviorService = (BehaviorService)comp.Site.GetService(typeof(BehaviorService)); + _designerHost = (IDesignerHost)comp.Site.GetService(typeof(IDesignerHost)); + } + + /// + /// Activates the editor for the given item.If there's still an editor around for the previous-edited item, it is deactivated. Pass in 'null' to deactivate and remove the current editor, if any. + /// + internal void ActivateEditor(ToolStripItem item, bool clicked) + { + if (item != _currentItem) + { + // Remove old editor + if (_editor != null) + { + _behaviorService.AdornerWindowControl.Controls.Remove(_editor); + _behaviorService.Invalidate(_editor.Bounds); + _editorUI = null; + _editor = null; + _currentItem = null; + _itemDesigner.IsEditorActive = false; + + // Show the previously edited glyph + if (_currentItem != null) + { + _currentItem = null; + } + } + if (item != null) + { + // Add new editor from the item... + _currentItem = item; + if (_designerHost != null) + { + _itemDesigner = (ToolStripItemDesigner)_designerHost.GetDesigner(_currentItem); + } + _editorUI = (ToolStripTemplateNode)_itemDesigner.Editor; + // If we got an editor, position and focus it. + if (_editorUI != null) + { + // Hide this glyph while it's being edited + _itemDesigner.IsEditorActive = true; + _editor = new ToolStripEditorControl(_editorUI.EditorToolStrip, _editorUI.Bounds); + _behaviorService.AdornerWindowControl.Controls.Add(_editor); + _lastKnownEditorBounds = _editor.Bounds; + _editor.BringToFront(); + // this is important since the ToolStripEditorControl listens to textchanged messages from TextBox. + _editorUI.ignoreFirstKeyUp = true; + // Select the Editor... Put Text and Select it ... + _editorUI.FocusEditor(_currentItem); + } + } + } + } + + /// + /// This will remove the Command for F2. + /// + internal void CloseManager() + { + } + + /// + /// This LISTENs to the Editor Resize for resizing the Insitu edit on the Adorner Window ... CURRENTLY DISABLED. + /// + private void OnEditorResize(object sender, EventArgs e) + { + // THIS IS CURRENTLY DISABLE !!!!! TO DO !! SHOULD WE SUPPORT AUTOSIZED INSITU ????? + _behaviorService.Invalidate(_lastKnownEditorBounds); + if (_editor != null) + { + _lastKnownEditorBounds = _editor.Bounds; + } + } + + // Private Class Implemented for InSitu Editor. This class just Wraps the ToolStripEditor from the TemplateNode and puts it in a Panel. + private class ToolStripEditorControl : Panel + { + private readonly Control _wrappedEditor; + private Rectangle _bounds; + + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + public ToolStripEditorControl(Control editorToolStrip, Rectangle bounds) + { + _wrappedEditor = editorToolStrip; + Bounds1 = bounds; + _wrappedEditor.Resize += new EventHandler(OnWrappedEditorResize); + Controls.Add(editorToolStrip); + Location = new Point(bounds.X, bounds.Y); + Text = "InSituEditorWrapper"; + UpdateSize(); + } + + public Rectangle Bounds1 { get => _bounds; set => _bounds = value; } + + private void OnWrappedEditorResize(object sender, EventArgs e) + { + } + + private void UpdateSize() => Size = new Size(_wrappedEditor.Size.Width, _wrappedEditor.Size.Height); + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripInSituService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripInSituService.cs new file mode 100644 index 00000000000..95e8a37026a --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripInSituService.cs @@ -0,0 +1,251 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; + +namespace System.Windows.Forms.Design +{ + /// + /// This class implements the ISupportInSituService which enables some designers to go into InSitu Editing when Keys are pressed while the Component is Selected. + /// + internal class ToolStripInSituService : ISupportInSituService, IDisposable + { + private readonly IServiceProvider _sp; + private readonly IDesignerHost _designerHost; + private IComponentChangeService _componentChangeSvc; + private ToolStripDesigner _toolDesigner; + private ToolStripItemDesigner _toolItemDesigner; + private ToolStripKeyboardHandlingService _toolStripKeyBoardService; + + /// + /// The constructor for this class which takes the serviceprovider used to get the selectionservice. This ToolStripInSituService is ToolStrip specific. + /// + public ToolStripInSituService(IServiceProvider provider) + { + _sp = provider; + _designerHost = (IDesignerHost)provider.GetService(typeof(IDesignerHost)); + Debug.Assert(_designerHost != null, "ToolStripKeyboardHandlingService relies on the selection service, which is unavailable."); + if (_designerHost != null) + { + _designerHost.AddService(typeof(ISupportInSituService), this); + } + _componentChangeSvc = (IComponentChangeService)_designerHost.GetService(typeof(IComponentChangeService)); + Debug.Assert(_componentChangeSvc != null, "ToolStripKeyboardHandlingService relies on the componentChange service, which is unavailable."); + if (_componentChangeSvc != null) + { + _componentChangeSvc.ComponentRemoved += new ComponentEventHandler(OnComponentRemoved); + } + } + + /// + /// Disposes of this object, removing all commands from the menu service. + /// + public void Dispose() + { + if (_toolDesigner != null) + { + _toolDesigner.Dispose(); + _toolDesigner = null; + } + if (_toolItemDesigner != null) + { + _toolItemDesigner.Dispose(); + _toolItemDesigner = null; + } + if (_componentChangeSvc != null) + { + _componentChangeSvc.ComponentRemoved -= new ComponentEventHandler(OnComponentRemoved); + _componentChangeSvc = null; + } + } + + private ToolStripKeyboardHandlingService ToolStripKeyBoardService + { + get + { + if (_toolStripKeyBoardService == null) + { + _toolStripKeyBoardService = (ToolStripKeyboardHandlingService)_sp.GetService(typeof(ToolStripKeyboardHandlingService)); + } + return _toolStripKeyBoardService; + } + } + + /// + /// Returning true for IgnoreMessages means that this service is interested in getting the KeyBoard characters. + /// + public bool IgnoreMessages + { + get + { + ISelectionService selectionService = (ISelectionService)_sp.GetService(typeof(ISelectionService)); + IDesignerHost host = (IDesignerHost)_sp.GetService(typeof(IDesignerHost)); + if (selectionService != null && host != null) + { + if (!(selectionService.PrimarySelection is IComponent comp)) + { + comp = (IComponent)ToolStripKeyBoardService.SelectedDesignerControl; + } + if (comp != null) + { + if (comp is DesignerToolStripControlHost c) + { + if (c.GetCurrentParent() is ToolStripDropDown dropDown) + { + if (dropDown.OwnerItem is ToolStripDropDownItem parentItem) + { + if (parentItem is ToolStripOverflowButton) + { + return false; + } + else + { + _toolItemDesigner = host.GetDesigner(parentItem) as ToolStripMenuItemDesigner; + if (_toolItemDesigner != null) + { + _toolDesigner = null; + return true; + } + } + } + } + else + { + if (c.GetCurrentParent() is MenuStrip tool) + { + _toolDesigner = host.GetDesigner(tool) as ToolStripDesigner; + if (_toolDesigner != null) + { + _toolItemDesigner = null; + return true; + } + } + } + } + else if (comp is ToolStripDropDown) //case for ToolStripDropDown.. + { + if (host.GetDesigner(comp) is ToolStripDropDownDesigner designer) + { + ToolStripMenuItem toolItem = designer.DesignerMenuItem; + if (toolItem != null) + { + _toolItemDesigner = host.GetDesigner(toolItem) as ToolStripItemDesigner; + if (_toolItemDesigner != null) + { + _toolDesigner = null; + return true; + } + } + } + } + else if (comp is MenuStrip) + { + _toolDesigner = host.GetDesigner(comp) as ToolStripDesigner; + if (_toolDesigner != null) + { + _toolItemDesigner = null; + return true; + } + } + else if (comp is ToolStripMenuItem) + { + _toolItemDesigner = host.GetDesigner(comp) as ToolStripItemDesigner; + if (_toolItemDesigner != null) + { + _toolDesigner = null; + return true; + } + } + } + } + return false; + } + } + + /// + /// This function is called on the service when the PBRSFORWARD gets the first WM_CHAR message. + /// + public void HandleKeyChar() + { + if (_toolDesigner != null || _toolItemDesigner != null) + { + if (_toolDesigner != null) + { + _toolDesigner.ShowEditNode(false); + } + else if (_toolItemDesigner != null) + { + if (_toolItemDesigner is ToolStripMenuItemDesigner menuDesigner) + { + ISelectionService selService = (ISelectionService)_sp.GetService(typeof(ISelectionService)); + if (selService != null) + { + object comp = selService.PrimarySelection; + if (comp == null) + { + comp = ToolStripKeyBoardService.SelectedDesignerControl; + } + DesignerToolStripControlHost designerItem = comp as DesignerToolStripControlHost; + if (designerItem != null || comp is ToolStripDropDown) + { + menuDesigner.EditTemplateNode(false); + } + else + { + menuDesigner.ShowEditNode(false); + } + } + } + else + { + _toolItemDesigner.ShowEditNode(false); + } + } + } + } + + /// + /// This function returns the Window handle that should get all the Keyboard messages. + /// + public IntPtr GetEditWindow() + { + IntPtr hWnd = IntPtr.Zero; + if (_toolDesigner != null && _toolDesigner.Editor != null && _toolDesigner.Editor.EditBox != null) + { + hWnd = (_toolDesigner.Editor.EditBox.Visible) ? _toolDesigner.Editor.EditBox.Handle : hWnd; + } + else if (_toolItemDesigner != null && _toolItemDesigner.Editor != null && _toolItemDesigner.Editor.EditBox != null) + { + hWnd = (_toolItemDesigner.Editor.EditBox.Visible) ? _toolItemDesigner.Editor.EditBox.Handle : hWnd; + } + return hWnd; + } + + // Remove the Service when the last toolStrip is removed. + private void OnComponentRemoved(object sender, ComponentEventArgs e) + { + bool toolStripPresent = false; + ComponentCollection comps = _designerHost.Container.Components; + foreach (IComponent comp in comps) + { + if (comp is ToolStrip) + { + toolStripPresent = true; + break; + } + } + if (!toolStripPresent) + { + ToolStripInSituService inSituService = (ToolStripInSituService)_sp.GetService(typeof(ISupportInSituService)); + if (inSituService != null) + { + //since we are going away .. restore the old commands. + _designerHost.RemoveService(typeof(ISupportInSituService)); + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemBehavior.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemBehavior.cs new file mode 100644 index 00000000000..fce793214cc --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemBehavior.cs @@ -0,0 +1,985 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// The behavior for the glpyh that covers the items themselves. This selects the items when they are clicked, and will (when implemented) do the dragging/reordering of them. + /// + internal class ToolStripItemBehavior : Behavior.Behavior + { + private const int GLYPHBORDER = 1; + private const int GLYPHINSET = 2; + //new privates for "Drag Drop" + internal Rectangle _dragBoxFromMouseDown = Rectangle.Empty; + private Timer _timer = null; + private ToolStripItemGlyph _selectedGlyph; + private bool _doubleClickFired = false; + private bool _mouseUpFired = false; + private Control _dropSource; + private IEventHandlerService _eventSvc = null; + + public ToolStripItemBehavior() + { + } + + // Gets the DropSource control. + private Control DropSource + { + get + { + if (_dropSource == null) + { + _dropSource = new Control(); + } + return _dropSource; + } + } + + + // Returns true if oldSelection and newSelection have a commonParent. + private bool CommonParent(ToolStripItem oldSelection, ToolStripItem newSelection) + { + ToolStrip oldSelectionParent = oldSelection.GetCurrentParent(); + ToolStrip newSelectionParent = newSelection.GetCurrentParent(); + return (oldSelectionParent == newSelectionParent); + } + + /// + /// Clears the insertion mark when items are being reordered + /// + private void ClearInsertionMark(ToolStripItem item) + { + // Dont paint if cursor hasnt moved. + if (ToolStripDesigner.s_lastCursorPosition != Point.Empty && ToolStripDesigner.s_lastCursorPosition == Cursor.Position) + { + return; + } + // Dont paint any "MouseOver" glyohs if TemplateNode is ACTIVE ! + ToolStripKeyboardHandlingService keyService = GetKeyBoardHandlingService(item); + if (keyService != null && keyService.TemplateNodeActive) + { + return; + } + + // stuff away the lastInsertionMarkRect and clear it out _before_ we call paint OW the call to invalidate wont help as it will get repainted. + if (item != null && item.Site != null) + { + IDesignerHost designerHost = (IDesignerHost)item.Site.GetService(typeof(IDesignerHost)); + if (designerHost != null) + { + Rectangle bounds = GetPaintingBounds(designerHost, item); + bounds.Inflate(GLYPHBORDER, GLYPHBORDER); + Region rgn = new Region(bounds); + try + { + bounds.Inflate(-GLYPHINSET, -GLYPHINSET); + rgn.Exclude(bounds); + BehaviorService bSvc = GetBehaviorService(item); + if (bSvc != null && bounds != Rectangle.Empty) + { + bSvc.Invalidate(rgn); + } + } + finally + { + rgn.Dispose(); + rgn = null; + } + } + } + } + + // Tries to put the item in the Insitu edit mode after the double click timer has ticked + private void EnterInSituMode(ToolStripItemGlyph glyph) + { + if (glyph.ItemDesigner != null && !glyph.ItemDesigner.IsEditorActive) + { + glyph.ItemDesigner.ShowEditNode(false); + } + } + + // Gets the Selection Service. + private ISelectionService GetSelectionService(ToolStripItem item) + { + Debug.Assert(item != null, "Item passed is null, SelectionService cannot be obtained"); + if (item.Site != null) + { + ISelectionService selSvc = (ISelectionService)item.Site.GetService(typeof(ISelectionService)); + Debug.Assert(selSvc != null, "Failed to get Selection Service!"); + return selSvc; + } + return null; + } + + // Gets the Behavior Service. + private BehaviorService GetBehaviorService(ToolStripItem item) + { + Debug.Assert(item != null, "Item passed is null, BehaviorService cannot be obtained"); + if (item.Site != null) + { + BehaviorService behaviorSvc = (BehaviorService)item.Site.GetService(typeof(BehaviorService)); + Debug.Assert(behaviorSvc != null, "Failed to get Behavior Service!"); + return behaviorSvc; + } + return null; + } + + // Gets the ToolStripKeyBoardHandling Service. + private ToolStripKeyboardHandlingService GetKeyBoardHandlingService(ToolStripItem item) + { + Debug.Assert(item != null, "Item passed is null, ToolStripKeyBoardHandlingService cannot be obtained"); + if (item.Site != null) + { + ToolStripKeyboardHandlingService keyBoardSvc = (ToolStripKeyboardHandlingService)item.Site.GetService(typeof(ToolStripKeyboardHandlingService)); + Debug.Assert(keyBoardSvc != null, "Failed to get ToolStripKeyboardHandlingService!"); + return keyBoardSvc; + } + return null; + } + + // Gets the painting rect for SelectionRects + private static Rectangle GetPaintingBounds(IDesignerHost designerHost, ToolStripItem item) + { + Rectangle bounds = Rectangle.Empty; + if (designerHost.GetDesigner(item) is ToolStripItemDesigner itemDesigner) + { + bounds = itemDesigner.GetGlyphBounds(); + ToolStripDesignerUtils.GetAdjustedBounds(item, ref bounds); + // So that the mouseOver glyph matches the selectionGlyph. + bounds.Inflate(1, 1); + bounds.Width--; + bounds.Height--; + } + return bounds; + } + + // This helper function will return true if any other MouseHandler (say TabOrder UI) is active, in which case we should not handle any Mouse Messages.. Since the TabOrder UI is pre-Whidbey when the TabOrder UI is up, It adds a new Overlay (a window) to the DesignerFrame (something similar to AdornerWindow). This UI is a transaparent control which has overrides foir Mouse Messages. It listens for all mouse messages through the IMouseHandler interface instead of using the new BehaviorService. Hence we have to special case this scenario. (CONTROL DESIGNER ALSO DOES THIS). + private bool MouseHandlerPresent(ToolStripItem item) + { + IMouseHandler mouseHandler = null; + if (_eventSvc == null) + { + _eventSvc = (IEventHandlerService)item.Site.GetService(typeof(IEventHandlerService)); + } + if (_eventSvc != null) + { + mouseHandler = (IMouseHandler)_eventSvc.GetHandler(typeof(IMouseHandler)); + } + return (mouseHandler != null); + } + + // Occurs when the timer ticks after user has doubleclicked an item + private void OnDoubleClickTimerTick(object sender, EventArgs e) + { + if (_timer != null) + { + _timer.Enabled = false; + _timer.Tick -= new System.EventHandler(OnDoubleClickTimerTick); + _timer.Dispose(); + _timer = null; + // Enter Insitu ... + if (_selectedGlyph != null && _selectedGlyph.Item is ToolStripMenuItem) + { + EnterInSituMode(_selectedGlyph); + } + } + } + + + + + // Occurs when user doubleclicks on the TooLStripItem glyph + public override bool OnMouseDoubleClick(Glyph g, MouseButtons button, Point mouseLoc) + { + if (_mouseUpFired) + { + _doubleClickFired = true; + } + return false; + } + + // Occurs when MouseUp TooLStripItem glyph + public override bool OnMouseUp(Glyph g, MouseButtons button) + { + ToolStripItemGlyph glyph = g as ToolStripItemGlyph; + ToolStripItem glyphItem = glyph.Item; + if (MouseHandlerPresent(glyphItem)) + { + return false; + } + SetParentDesignerValuesForDragDrop(glyphItem, false, Point.Empty); + if (_doubleClickFired) + { + if (glyph != null && button == MouseButtons.Left) + { + ISelectionService selSvc = GetSelectionService(glyphItem); + if (selSvc == null) + { + return false; + } + + ToolStripItem selectedItem = selSvc.PrimarySelection as ToolStripItem; + // Check if this item is already selected ... + if (selectedItem == glyphItem) + { + // If timer != null.. we are in DoubleClick before the "InSitu Timer" so KILL IT. + if (_timer != null) + { + _timer.Enabled = false; + _timer.Tick -= new System.EventHandler(OnDoubleClickTimerTick); + _timer.Dispose(); + _timer = null; + } + // If the Selecteditem is already in editmode ... bail out + if (selectedItem != null) + { + ToolStripItemDesigner selectedItemDesigner = glyph.ItemDesigner; + if (selectedItemDesigner != null && selectedItemDesigner.IsEditorActive) + { + return false; + } + selectedItemDesigner.DoDefaultAction(); + } + _doubleClickFired = false; + _mouseUpFired = false; + } + } + } + else + { + _mouseUpFired = true; + } + return false; + } + + // Occurs when MouseDown on the TooLStripItem glyph + public override bool OnMouseDown(Glyph g, MouseButtons button, Point mouseLoc) + { + ToolStripItemGlyph glyph = g as ToolStripItemGlyph; + ToolStripItem glyphItem = glyph.Item; + ISelectionService selSvc = GetSelectionService(glyphItem); + BehaviorService bSvc = GetBehaviorService(glyphItem); + ToolStripKeyboardHandlingService keyService = GetKeyBoardHandlingService(glyphItem); + if ((button == MouseButtons.Left) && (keyService != null) && (keyService.TemplateNodeActive)) + { + if (keyService.ActiveTemplateNode.IsSystemContextMenuDisplayed) + { + // skip behaviors when the context menu is displayed + return false; + } + } + + IDesignerHost designerHost = (IDesignerHost)glyphItem.Site.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Invalid DesignerHost"); + + //Cache original selection + ICollection originalSelComps = null; + if (selSvc != null) + { + originalSelComps = selSvc.GetSelectedComponents(); + } + + // Add the TemplateNode to the Selection if it is currently Selected as the GetSelectedComponents wont do it for us. + ArrayList origSel = new ArrayList(originalSelComps); + if (origSel.Count == 0) + { + if (keyService != null && keyService.SelectedDesignerControl != null) + { + origSel.Add(keyService.SelectedDesignerControl); + } + } + + if (keyService != null) + { + keyService.SelectedDesignerControl = null; + if (keyService.TemplateNodeActive) + { + // If templateNode Active .. commit and Select it + keyService.ActiveTemplateNode.CommitAndSelect(); + // if the selected item is clicked .. then commit the node and reset the selection (refer 488002) + if (selSvc.PrimarySelection is ToolStripItem currentSel && currentSel == glyphItem) + { + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + } + } + + if (selSvc == null || MouseHandlerPresent(glyphItem)) + { + return false; + } + + if (glyph != null && button == MouseButtons.Left) + { + ToolStripItem selectedItem = selSvc.PrimarySelection as ToolStripItem; + // Always set the Drag-Rect for Drag-Drop... + SetParentDesignerValuesForDragDrop(glyphItem, true, mouseLoc); + // Check if this item is already selected ... + if (selectedItem != null && selectedItem == glyphItem) + { + // If the Selecteditem is already in editmode ... bail out + if (selectedItem != null) + { + ToolStripItemDesigner selectedItemDesigner = glyph.ItemDesigner; + if (selectedItemDesigner != null && selectedItemDesigner.IsEditorActive) + { + return false; + } + } + + // Check if this is CTRL + Click or SHIFT + Click, if so then just remove the selection + bool removeSel = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) > 0; + if (removeSel) + { + selSvc.SetSelectedComponents(new IComponent[] { selectedItem }, SelectionTypes.Remove); + return false; + } + + //start Double Click Timer + // This is required for the second down in selection which can be the first down of a Double click on the glyph confusing... hence this comment ... + // Heres the scenario .... + // DOWN 1 - selects the ITEM + // DOWN 2 - ITEM goes into INSITU.... + // DOUBLE CLICK - dont show code.. + // Open INSITU after the double click time + if (selectedItem is ToolStripMenuItem) + { + _timer = new Timer + { + Interval = SystemInformation.DoubleClickTime + }; + _timer.Tick += new EventHandler(OnDoubleClickTimerTick); + _timer.Enabled = true; + _selectedGlyph = glyph; + } + } + else + { + bool shiftPressed = (Control.ModifierKeys & Keys.Shift) > 0; + // We should process MouseDown only if we are not yet selected.... + if (!selSvc.GetComponentSelected(glyphItem)) + { + //Reset the State... On the Glpyhs .. we get MouseDown - Mouse UP (for single Click) And we get MouseDown - MouseUp - DoubleClick - Up (for double Click) Hence reset the state at start.... + _mouseUpFired = false; + _doubleClickFired = false; + //Implementing Shift + Click.... + // we have 2 items, namely, selectedItem (current PrimarySelection) and glyphItem (item which has received mouseDown) FIRST check if they have common parent... IF YES then get the indices of the two and SELECT all items from LOWER index to the HIGHER index. + if (shiftPressed && (selectedItem != null && CommonParent(selectedItem, glyphItem))) + { + ToolStrip parent = null; + if (glyphItem.IsOnOverflow) + { + parent = glyphItem.Owner; + } + else + { + parent = glyphItem.GetCurrentParent(); + } + int startIndexOfSelection = Math.Min(parent.Items.IndexOf(selectedItem), parent.Items.IndexOf(glyphItem)); + int endIndexOfSelection = Math.Max(parent.Items.IndexOf(selectedItem), parent.Items.IndexOf(glyphItem)); + int countofItemsSelected = (endIndexOfSelection - startIndexOfSelection) + 1; + + // if two adjacent items are selected ... + if (countofItemsSelected == 2) + { + selSvc.SetSelectedComponents(new IComponent[] { glyphItem }); + } + else + { + object[] totalObjects = new object[countofItemsSelected]; + int j = 0; + for (int i = startIndexOfSelection; i <= endIndexOfSelection; i++) + { + totalObjects[j++] = parent.Items[i]; + } + selSvc.SetSelectedComponents(new IComponent[] { parent }, SelectionTypes.Replace); + ToolStripDesigner.s_shiftState = true; + selSvc.SetSelectedComponents(totalObjects, SelectionTypes.Replace); + } + } + //End Implmentation + else + { + if (glyphItem.IsOnDropDown && ToolStripDesigner.s_shiftState) + { + //Invalidate glyh only if we are in ShiftState... + ToolStripDesigner.s_shiftState = false; + if (bSvc != null) + { + bSvc.Invalidate(glyphItem.Owner.Bounds); + } + } + selSvc.SetSelectedComponents(new IComponent[] { glyphItem }, SelectionTypes.Auto); + } + // Set the appropriate object. + if (keyService != null) + { + keyService.ShiftPrimaryItem = glyphItem; + } + } + // we are already selected and if shiftpressed... + else if (shiftPressed || (Control.ModifierKeys & Keys.Control) > 0) + { + selSvc.SetSelectedComponents(new IComponent[] { glyphItem }, SelectionTypes.Remove); + } + } + } + + if (glyph != null && button == MouseButtons.Right) + { + if (!selSvc.GetComponentSelected(glyphItem)) + { + selSvc.SetSelectedComponents(new IComponent[] { glyphItem }); + } + } + + // finally Invalidate all selections + ToolStripDesignerUtils.InvalidateSelection(origSel, glyphItem, glyphItem.Site, false); + return false; + } + + /// + /// Overriden to paint the border on mouse enter..... + /// + public override bool OnMouseEnter(Glyph g) + { + if (g is ToolStripItemGlyph glyph) + { + ToolStripItem glyphItem = glyph.Item; + if (MouseHandlerPresent(glyphItem)) + { + return false; + } + + ISelectionService selSvc = GetSelectionService(glyphItem); + if (selSvc != null) + { + if (!selSvc.GetComponentSelected(glyphItem)) + { + PaintInsertionMark(glyphItem); + } + } + } + return false; + } + + /// + /// overriden to "clear" the boundary-paint when the mouse leave the item + /// + public override bool OnMouseLeave(Glyph g) + { + if (g is ToolStripItemGlyph glyph) + { + ToolStripItem glyphItem = glyph.Item; + if (MouseHandlerPresent(glyphItem)) + { + return false; + } + ISelectionService selSvc = GetSelectionService(glyphItem); + if (selSvc != null) + { + if (!selSvc.GetComponentSelected(glyphItem)) + { + ClearInsertionMark(glyphItem); + } + } + } + return false; + } + + /// + /// When any MouseMove message enters the BehaviorService's AdornerWindow (mousemove, ncmousemove) it is first passed here, to the top-most Behavior in the BehaviorStack. Returning 'true' from this function signifies that the Message was 'handled' by the Behavior and should not continue to be processed. + /// + public override bool OnMouseMove(Glyph g, MouseButtons button, Point mouseLoc) + { + bool retVal = false; + ToolStripItemGlyph glyph = g as ToolStripItemGlyph; + ToolStripItem glyphItem = glyph.Item; + ISelectionService selSvc = GetSelectionService(glyphItem); + if (selSvc == null || glyphItem.Site == null || MouseHandlerPresent(glyphItem)) + { + return false; + } + if (!selSvc.GetComponentSelected(glyphItem)) + { + PaintInsertionMark(glyphItem); + retVal = false; + } + + if (button == MouseButtons.Left && glyph != null && glyph.ItemDesigner != null && !glyph.ItemDesigner.IsEditorActive) + { + Rectangle dragBox = Rectangle.Empty; + IDesignerHost designerHost = (IDesignerHost)glyphItem.Site.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Invalid DesignerHost"); + if (glyphItem.Placement == ToolStripItemPlacement.Overflow || (glyphItem.Placement == ToolStripItemPlacement.Main && !(glyphItem.IsOnDropDown))) + { + ToolStripItemDesigner itemDesigner = glyph.ItemDesigner; + ToolStrip parentToolStrip = itemDesigner.GetMainToolStrip(); + if (designerHost.GetDesigner(parentToolStrip) is ToolStripDesigner parentDesigner) + { + dragBox = parentDesigner.DragBoxFromMouseDown; + } + } + else if (glyphItem.IsOnDropDown) + { + //Get the OwnerItem's Designer and set the value... + if (glyphItem.Owner is ToolStripDropDown parentDropDown) + { + ToolStripItem ownerItem = parentDropDown.OwnerItem; + if (designerHost.GetDesigner(ownerItem) is ToolStripItemDesigner ownerItemDesigner) + { + dragBox = ownerItemDesigner.dragBoxFromMouseDown; + } + } + } + // If the mouse moves outside the rectangle, start the drag. + if (dragBox != Rectangle.Empty && !dragBox.Contains(mouseLoc.X, mouseLoc.Y)) + { + if (_timer != null) + { + _timer.Enabled = false; + _timer.Tick -= new System.EventHandler(OnDoubleClickTimerTick); + _timer.Dispose(); + _timer = null; + } + + // Proceed with the drag and drop, passing in the list item. + try + { + ArrayList dragItems = new ArrayList(); + ICollection selComps = selSvc.GetSelectedComponents(); + //create our list of controls-to-drag + foreach (IComponent comp in selComps) + { + if (comp is ToolStripItem item) + { + dragItems.Add(item); + } + } + + //Start Drag-Drop only if ToolStripItem is the primary Selection + if (selSvc.PrimarySelection is ToolStripItem selectedItem) + { + ToolStrip owner = selectedItem.Owner; + ToolStripItemDataObject data = new ToolStripItemDataObject(dragItems, selectedItem, owner); + DropSource.QueryContinueDrag += new QueryContinueDragEventHandler(QueryContinueDrag); + if (glyphItem is ToolStripDropDownItem ddItem) + { + if (designerHost.GetDesigner(ddItem) is ToolStripMenuItemDesigner itemDesigner) + { + itemDesigner.InitializeBodyGlyphsForItems(false, ddItem); + ddItem.HideDropDown(); + } + } + else if (glyphItem.IsOnDropDown && !glyphItem.IsOnOverflow) + { + ToolStripDropDown dropDown = glyphItem.GetCurrentParent() as ToolStripDropDown; + ToolStripDropDownItem ownerItem = dropDown.OwnerItem as ToolStripDropDownItem; + selSvc.SetSelectedComponents(new IComponent[] { ownerItem }, SelectionTypes.Replace); + } + DropSource.DoDragDrop(data, DragDropEffects.All); + } + } + finally + { + DropSource.QueryContinueDrag -= new QueryContinueDragEventHandler(QueryContinueDrag); + //Reset all Drag-Variables + SetParentDesignerValuesForDragDrop(glyphItem, false, Point.Empty); + ToolStripDesigner.s_dragItem = null; + _dropSource = null; + } + retVal = false; + } + } + return retVal; + } + + // OLE DragDrop virtual methods + /// + /// OnDragDrop can be overridden so that a Behavior can specify its own Drag/Drop rules. + /// + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + public override void OnDragDrop(Glyph g, DragEventArgs e) + { + ToolStripItem currentDropItem = ToolStripDesigner.s_dragItem; + // Ensure that the list item index is contained in the data. + if (e.Data is ToolStripItemDataObject && currentDropItem != null) + { + ToolStripItemDataObject data = (ToolStripItemDataObject)e.Data; + // Get the PrimarySelection before the Drag operation... + ToolStripItem selectedItem = data.PrimarySelection; + IDesignerHost designerHost = (IDesignerHost)currentDropItem.Site.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Invalid DesignerHost"); + //Do DragDrop only if currentDropItem has changed. + if (currentDropItem != selectedItem && designerHost != null) + { + ArrayList components = data.DragComponents; + ToolStrip parentToolStrip = currentDropItem.GetCurrentParent() as ToolStrip; + int primaryIndex = -1; + string transDesc; + bool copy = (e.Effect == DragDropEffects.Copy); + if (components.Count == 1) + { + string name = TypeDescriptor.GetComponentName(components[0]); + if (name == null || name.Length == 0) + { + name = components[0].GetType().Name; + } + transDesc = string.Format(copy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name); + } + else + { + transDesc = string.Format(copy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, components.Count); + } + + DesignerTransaction designerTransaction = designerHost.CreateTransaction(transDesc); + try + { + IComponentChangeService changeSvc = (IComponentChangeService)currentDropItem.Site.GetService(typeof(IComponentChangeService)); + if (changeSvc != null) + { + if (parentToolStrip is ToolStripDropDown dropDown) + { + ToolStripItem ownerItem = dropDown.OwnerItem; + changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + } + else + { + changeSvc.OnComponentChanging(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"]); + } + } + + // If we are copying, then we want to make a copy of the components we are dragging + if (copy) + { + // Remember the primary selection if we had one + if (selectedItem != null) + { + primaryIndex = components.IndexOf(selectedItem); + } + ToolStripKeyboardHandlingService keyboardHandlingService = GetKeyBoardHandlingService(selectedItem); + if (keyboardHandlingService != null) + { + keyboardHandlingService.CopyInProgress = true; + } + components = DesignerUtils.CopyDragObjects(components, currentDropItem.Site) as ArrayList; + if (keyboardHandlingService != null) + { + keyboardHandlingService.CopyInProgress = false; + } + if (primaryIndex != -1) + { + selectedItem = components[primaryIndex] as ToolStripItem; + } + } + + if (e.Effect == DragDropEffects.Move || copy) + { + ISelectionService selSvc = GetSelectionService(currentDropItem); + if (selSvc != null) + { + // Insert the item. + if (parentToolStrip is ToolStripOverflow) + { + parentToolStrip = (((ToolStripOverflow)parentToolStrip).OwnerItem).Owner; + } + + int indexOfItemUnderMouseToDrop = parentToolStrip.Items.IndexOf(ToolStripDesigner.s_dragItem); + if (indexOfItemUnderMouseToDrop != -1) + { + int indexOfPrimarySelection = 0; + if (selectedItem != null) + { + indexOfPrimarySelection = parentToolStrip.Items.IndexOf(selectedItem); + } + + if (indexOfPrimarySelection != -1 && indexOfItemUnderMouseToDrop > indexOfPrimarySelection) + { + indexOfItemUnderMouseToDrop--; + } + foreach (ToolStripItem item in components) + { + parentToolStrip.Items.Insert(indexOfItemUnderMouseToDrop, item); + } + } + selSvc.SetSelectedComponents(new IComponent[] { selectedItem }, SelectionTypes.Primary | SelectionTypes.Replace); + } + } + if (changeSvc != null) + { + ToolStripDropDown dropDown = parentToolStrip as ToolStripDropDown; + if (dropDown != null) + { + ToolStripItem ownerItem = dropDown.OwnerItem; + changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + else + { + changeSvc.OnComponentChanged(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"], null, null); + } + + //fire extra changing/changed events. + if (copy) + { + if (dropDown != null) + { + ToolStripItem ownerItem = dropDown.OwnerItem; + changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + else + { + changeSvc.OnComponentChanging(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"]); + changeSvc.OnComponentChanged(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)["Items"], null, null); + } + } + } + + //If Parent is DropDown... we have to manage the Glyphs .... + foreach (ToolStripItem item in components) + { + if (item is ToolStripDropDownItem) + { + if (designerHost.GetDesigner(item) is ToolStripMenuItemDesigner itemDesigner) + { + itemDesigner.InitializeDropDown(); + } + } + if (item.GetCurrentParent() is ToolStripDropDown dropDown && !(dropDown is ToolStripOverflow)) + { + if (dropDown.OwnerItem is ToolStripDropDownItem ownerItem) + { + if (designerHost.GetDesigner(ownerItem) is ToolStripMenuItemDesigner ownerDesigner) + { + ownerDesigner.InitializeBodyGlyphsForItems(false, ownerItem); + ownerDesigner.InitializeBodyGlyphsForItems(true, ownerItem); + } + } + } + } + // Refresh on SelectionManager... + BehaviorService bSvc = GetBehaviorService(currentDropItem); + if (bSvc != null) + { + bSvc.SyncSelection(); + } + } + catch (Exception ex) + { + if (designerTransaction != null) + { + designerTransaction.Cancel(); + designerTransaction = null; + } + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + finally + { + if (designerTransaction != null) + { + designerTransaction.Commit(); + designerTransaction = null; + } + } + } + } + } + + /// + /// OnDragEnter can be overridden so that a Behavior can specify its own Drag/Drop rules. + /// + public override void OnDragEnter(Glyph g, DragEventArgs e) + { + ToolStripItemGlyph glyph = g as ToolStripItemGlyph; + ToolStripItem glyphItem = glyph.Item; + if (e.Data is ToolStripItemDataObject data) + { + // support move only within same container. + if (data.Owner == glyphItem.Owner) + { + PaintInsertionMark(glyphItem); + ToolStripDesigner.s_dragItem = glyphItem; + e.Effect = DragDropEffects.Move; + } + else + { + e.Effect = DragDropEffects.None; + } + } + else + { + e.Effect = DragDropEffects.None; + } + } + + /// + /// OnDragLeave can be overridden so that a Behavior can specify its own Drag/Drop rules. + /// + public override void OnDragLeave(Glyph g, EventArgs e) + { + ToolStripItemGlyph glyph = g as ToolStripItemGlyph; + ClearInsertionMark(glyph.Item); + } + + /// + /// OnDragOver can be overridden so that a Behavior can specify its own Drag/Drop rules. + /// + public override void OnDragOver(Glyph g, DragEventArgs e) + { + // Determine whether string data exists in the drop data. If not, then the drop effect reflects that the drop cannot occur. + ToolStripItemGlyph glyph = g as ToolStripItemGlyph; + ToolStripItem glyphItem = glyph.Item; + if (e.Data is ToolStripItemDataObject) + { + PaintInsertionMark(glyphItem); + e.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move; + } + else + { + e.Effect = DragDropEffects.None; + } + } + + /// + /// Paints the insertion mark when items are being reordered + /// + private void PaintInsertionMark(ToolStripItem item) + { + // Dont paint if cursor hasnt moved. + if (ToolStripDesigner.s_lastCursorPosition != Point.Empty && ToolStripDesigner.s_lastCursorPosition == Cursor.Position) + { + return; + } + // Dont paint any "MouseOver" glyohs if TemplateNode is ACTIVE ! + ToolStripKeyboardHandlingService keyService = GetKeyBoardHandlingService(item); + if (keyService != null && keyService.TemplateNodeActive) + { + return; + } + + //Start from fresh State... + if (item != null && item.Site != null) + { + ToolStripDesigner.s_lastCursorPosition = Cursor.Position; + IDesignerHost designerHost = (IDesignerHost)item.Site.GetService(typeof(IDesignerHost)); + if (designerHost != null) + { + Rectangle bounds = GetPaintingBounds(designerHost, item); + BehaviorService bSvc = GetBehaviorService(item); + if (bSvc != null) + { + Graphics g = bSvc.AdornerWindowGraphics; + try + { + using (Pen p = new Pen(new SolidBrush(Color.Black))) + { + p.DashStyle = DashStyle.Dot; + g.DrawRectangle(p, bounds); + } + } + finally + { + g.Dispose(); + } + } + } + } + } + + /// + /// QueryContinueDrag can be overridden so that a Behavior can specify its own Drag/Drop rules. + /// + private void QueryContinueDrag(object sender, QueryContinueDragEventArgs e) + { + // Cancel the drag if the mouse moves off the form. + if (e.Action == DragAction.Continue) + { + return; + } + if (e.EscapePressed) + { + e.Action = DragAction.Cancel; + ToolStripItem item = sender as ToolStripItem; + SetParentDesignerValuesForDragDrop(item, false, Point.Empty); + ISelectionService selSvc = GetSelectionService(item); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new IComponent[] { item }, SelectionTypes.Auto); + } + ToolStripDesigner.s_dragItem = null; + } + } + + // Set values before initiating the Drag-Drop + private void SetParentDesignerValuesForDragDrop(ToolStripItem glyphItem, bool setValues, Point mouseLoc) + { + if (glyphItem.Site == null) + { + return; + } + // Remember the point where the mouse down occurred. The DragSize indicates the size that the mouse can move before a drag event should be started. + Size dragSize = new Size(1, 1); + + IDesignerHost designerHost = (IDesignerHost)glyphItem.Site.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Invalid DesignerHost"); + + + // implement Drag Drop for individual ToolStrip Items While this item is getting selected.. Get the index of the item the mouse is below. + if (glyphItem.Placement == ToolStripItemPlacement.Overflow || (glyphItem.Placement == ToolStripItemPlacement.Main && !(glyphItem.IsOnDropDown))) + { + ToolStripItemDesigner itemDesigner = designerHost.GetDesigner(glyphItem) as ToolStripItemDesigner; + ToolStrip parentToolStrip = itemDesigner.GetMainToolStrip(); + if (designerHost.GetDesigner(parentToolStrip) is ToolStripDesigner parentDesigner) + { + if (setValues) + { + parentDesigner.IndexOfItemUnderMouseToDrag = parentToolStrip.Items.IndexOf(glyphItem); + // Create a rectangle using the DragSize, with the mouse position being at the center of the rectangle. On SelectionChanged we recreate the Glyphs ... so need to stash this value on the parentDesigner.... + parentDesigner.DragBoxFromMouseDown = _dragBoxFromMouseDown = new Rectangle(new Point(mouseLoc.X - (dragSize.Width / 2), mouseLoc.Y - (dragSize.Height / 2)), dragSize); + } + else + { + parentDesigner.IndexOfItemUnderMouseToDrag = -1; + parentDesigner.DragBoxFromMouseDown = _dragBoxFromMouseDown = Rectangle.Empty; + } + } + } + else if (glyphItem.IsOnDropDown) + { + //Get the OwnerItem's Designer and set the value... + if (glyphItem.Owner is ToolStripDropDown parentDropDown) + { + ToolStripItem ownerItem = parentDropDown.OwnerItem; + if (designerHost.GetDesigner(ownerItem) is ToolStripItemDesigner ownerItemDesigner) + { + if (setValues) + { + ownerItemDesigner.indexOfItemUnderMouseToDrag = parentDropDown.Items.IndexOf(glyphItem); + // Create a rectangle using the DragSize, with the mouse position being at the center of the rectangle. On SelectionChanged we recreate the Glyphs ... so need to stash this value on the parentDesigner.... + ownerItemDesigner.dragBoxFromMouseDown = _dragBoxFromMouseDown = new Rectangle(new Point(mouseLoc.X - (dragSize.Width / 2), mouseLoc.Y - (dragSize.Height / 2)), dragSize); + } + else + { + ownerItemDesigner.indexOfItemUnderMouseToDrag = -1; + ownerItemDesigner.dragBoxFromMouseDown = _dragBoxFromMouseDown = Rectangle.Empty; + } + } + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemCustomMenuItemCollection.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemCustomMenuItemCollection.cs new file mode 100644 index 00000000000..3157e67ff23 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemCustomMenuItemCollection.cs @@ -0,0 +1,700 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace System.Windows.Forms.Design +{ + /// + /// Custom ContextMenu section for ToolStripMenuItems. + /// + internal class ToolStripItemCustomMenuItemCollection : CustomMenuItemCollection + { + private ToolStripItem currentItem; + private IServiceProvider serviceProvider; + + private ToolStripMenuItem imageToolStripMenuItem; + private ToolStripMenuItem enabledToolStripMenuItem; + + private ToolStripMenuItem isLinkToolStripMenuItem; + private ToolStripMenuItem springToolStripMenuItem; + + private ToolStripMenuItem checkedToolStripMenuItem; + private ToolStripMenuItem showShortcutKeysToolStripMenuItem; + + private ToolStripMenuItem alignmentToolStripMenuItem; + private ToolStripMenuItem displayStyleToolStripMenuItem; + + private ToolStripSeparator toolStripSeparator1; + + private ToolStripMenuItem convertToolStripMenuItem; + private ToolStripMenuItem insertToolStripMenuItem; + + + private ToolStripMenuItem leftToolStripMenuItem; + private ToolStripMenuItem rightToolStripMenuItem; + + private ToolStripMenuItem noneStyleToolStripMenuItem; + private ToolStripMenuItem textStyleToolStripMenuItem; + private ToolStripMenuItem imageStyleToolStripMenuItem; + private ToolStripMenuItem imageTextStyleToolStripMenuItem; + + private ToolStripMenuItem editItemsToolStripMenuItem; + private CollectionEditVerbManager verbManager; + + public ToolStripItemCustomMenuItemCollection(IServiceProvider provider, Component currentItem) : base() + { + serviceProvider = provider; + this.currentItem = currentItem as ToolStripItem; + PopulateList(); + } + + /// + /// Parent ToolStrip. + /// + private ToolStrip ParentTool + { + get => currentItem.Owner; + } + + /// + /// creates a item representing an item, respecting Browsable. + /// + private ToolStripMenuItem CreatePropertyBasedItem(string text, string propertyName, string imageName) + { + ToolStripMenuItem item = new ToolStripMenuItem(text); + bool browsable = IsPropertyBrowsable(propertyName); + item.Visible = browsable; + if (browsable) + { + if (!string.IsNullOrEmpty(imageName)) + { + item.Image = new Icon(typeof(ToolStripMenuItem), imageName).ToBitmap(); + item.ImageTransparentColor = Color.Magenta; + } + + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + item.DropDown.Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]; + item.DropDown.Font = (Font)uis.Styles["DialogFont"]; + } + } + return item; + } + + /// + /// creates an item that when clicked changes the enum value. + /// + private ToolStripMenuItem CreateEnumValueItem(string propertyName, string name, object value) + { + ToolStripMenuItem item = new ToolStripMenuItem(name); + item.Tag = new EnumValueDescription(propertyName, value); + item.Click += new EventHandler(OnEnumValueChanged); + return item; + } + + private ToolStripMenuItem CreateBooleanItem(string text, string propertyName) + { + ToolStripMenuItem item = new ToolStripMenuItem(text); + bool browsable = IsPropertyBrowsable(propertyName); + item.Visible = browsable; + item.Tag = propertyName; + item.CheckOnClick = true; + item.Click += new EventHandler(OnBooleanValueChanged); + return item; + } + + // Property names are hard-coded intentionally + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + private void PopulateList() + { + ToolStripItem selectedItem = currentItem; + if (!(selectedItem is ToolStripControlHost) && !(selectedItem is ToolStripSeparator)) + { + imageToolStripMenuItem = new ToolStripMenuItem(); + imageToolStripMenuItem.Text = SR.ToolStripItemContextMenuSetImage; + imageToolStripMenuItem.Image = new Bitmap(typeof(ToolStripMenuItem), "image.bmp"); + imageToolStripMenuItem.ImageTransparentColor = Color.Magenta; + //Add event Handlers + imageToolStripMenuItem.Click += new EventHandler(OnImageToolStripMenuItemClick); + enabledToolStripMenuItem = CreateBooleanItem("E&nabled", "Enabled"); + this.AddRange(new ToolStripItem[] { imageToolStripMenuItem, enabledToolStripMenuItem}); + if (selectedItem is ToolStripMenuItem) + { + checkedToolStripMenuItem = CreateBooleanItem("C&hecked", "Checked"); + showShortcutKeysToolStripMenuItem = CreateBooleanItem("ShowShortcut&Keys", "ShowShortcutKeys"); + this.AddRange(new System.Windows.Forms.ToolStripItem[] { checkedToolStripMenuItem, showShortcutKeysToolStripMenuItem}); + } + else + { + if (selectedItem is ToolStripLabel) + { + isLinkToolStripMenuItem = CreateBooleanItem("IsLin&k", "IsLink"); + this.Add(isLinkToolStripMenuItem); + } + + if (selectedItem is ToolStripStatusLabel) + { + springToolStripMenuItem = CreateBooleanItem("Sprin&g", "Spring"); + this.Add(springToolStripMenuItem); + } + + leftToolStripMenuItem = CreateEnumValueItem("Alignment", "Left", ToolStripItemAlignment.Left); + rightToolStripMenuItem = CreateEnumValueItem("Alignment", "Right", ToolStripItemAlignment.Right); + noneStyleToolStripMenuItem = CreateEnumValueItem("DisplayStyle", "None", ToolStripItemDisplayStyle.None); + textStyleToolStripMenuItem = CreateEnumValueItem("DisplayStyle", "Text", ToolStripItemDisplayStyle.Text); + imageStyleToolStripMenuItem = CreateEnumValueItem("DisplayStyle", "Image", ToolStripItemDisplayStyle.Image); + imageTextStyleToolStripMenuItem = CreateEnumValueItem("DisplayStyle", "ImageAndText", ToolStripItemDisplayStyle.ImageAndText); + // alignmentToolStripMenuItem + alignmentToolStripMenuItem = CreatePropertyBasedItem("Ali&gnment", "Alignment", "alignment.bmp"); + alignmentToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { leftToolStripMenuItem, rightToolStripMenuItem}); + // displayStyleToolStripMenuItem + displayStyleToolStripMenuItem = CreatePropertyBasedItem("Displa&yStyle", "DisplayStyle", "displaystyle.bmp"); + displayStyleToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { noneStyleToolStripMenuItem, textStyleToolStripMenuItem, imageStyleToolStripMenuItem, imageTextStyleToolStripMenuItem}); + + if (serviceProvider.GetService(typeof(IUIService)) is IUIService uis) + { + // We already have code which expects VsRenderer and DialogFont to be always available without the need for null checks + ToolStripProfessionalRenderer renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]; + alignmentToolStripMenuItem.DropDown.Renderer = renderer; + displayStyleToolStripMenuItem.DropDown.Renderer = renderer; + + Font font = (Font)uis.Styles["DialogFont"]; + alignmentToolStripMenuItem.DropDown.Font = font; + displayStyleToolStripMenuItem.DropDown.Font = font; + + // VsColorPanelText may be undefined, so we do need the check for Color here + object panelTextObject = uis.Styles["VsColorPanelText"]; + if (panelTextObject is Color panelTextColor) + { + alignmentToolStripMenuItem.DropDown.ForeColor = panelTextColor; + displayStyleToolStripMenuItem.DropDown.ForeColor = panelTextColor; + } + } + this.AddRange(new System.Windows.Forms.ToolStripItem[] { alignmentToolStripMenuItem, displayStyleToolStripMenuItem, }); + } + toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.Add(toolStripSeparator1); + } + + convertToolStripMenuItem = new ToolStripMenuItem + { + Text = SR.ToolStripItemContextMenuConvertTo, + DropDown = ToolStripDesignerUtils.GetNewItemDropDown(ParentTool, currentItem, new EventHandler(AddNewItemClick), true, serviceProvider, true) + }; + insertToolStripMenuItem = new ToolStripMenuItem + { + Text = SR.ToolStripItemContextMenuInsert, + DropDown = ToolStripDesignerUtils.GetNewItemDropDown(ParentTool, currentItem, new EventHandler(AddNewItemClick), false, serviceProvider, true) + }; + + this.AddRange(new System.Windows.Forms.ToolStripItem[] { convertToolStripMenuItem, insertToolStripMenuItem}); + + if (currentItem is ToolStripDropDownItem) + { + IDesignerHost _designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + if (_designerHost != null) + { + if (_designerHost.GetDesigner(currentItem) is ToolStripItemDesigner itemDesigner) + { + verbManager = new CollectionEditVerbManager(string.Format(SR.ToolStripDropDownItemCollectionEditorVerb), itemDesigner, TypeDescriptor.GetProperties(currentItem)["DropDownItems"], false); + editItemsToolStripMenuItem = new ToolStripMenuItem(); + editItemsToolStripMenuItem.Text = SR.ToolStripDropDownItemCollectionEditorVerb; + editItemsToolStripMenuItem.Click += new EventHandler(OnEditItemsMenuItemClick); + editItemsToolStripMenuItem.Image = new Icon(typeof(ToolStripMenuItem), "editdropdownlist.bmp").ToBitmap(); + editItemsToolStripMenuItem.ImageTransparentColor = Color.Magenta; + this.Add(editItemsToolStripMenuItem); + } + } + } + } + + private void OnEditItemsMenuItemClick(object sender, EventArgs e) + { + if (verbManager != null) + { + verbManager.EditItemsVerb.Invoke(); + } + } + + private void OnImageToolStripMenuItemClick(object sender, EventArgs e) + { + IDesignerHost _designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + if (_designerHost != null) + { + if (_designerHost.GetDesigner(currentItem) is ToolStripItemDesigner itemDesigner) + { + try + { + // EditorServiceContext will check if the user has changed the property and set it for us. + EditorServiceContext.EditValue(itemDesigner, currentItem, "Image"); + } + catch (InvalidOperationException ex) + { + IUIService uiService = (IUIService)serviceProvider.GetService(typeof(IUIService)); + uiService.ShowError(ex.Message); + } + } + } + } + + private void OnBooleanValueChanged(object sender, EventArgs e) + { + ToolStripItem item = sender as ToolStripItem; + Debug.Assert(item != null, "Why is item null?"); + if (item != null) + { + string propertyName = item.Tag as string; + Debug.Assert(propertyName != null, "Why is propertyName null?"); + if (propertyName != null) + { + bool currentValue = (bool)GetProperty(propertyName); + ChangeProperty(propertyName, !currentValue); + } + } + } + + private void OnEnumValueChanged(object sender, EventArgs e) + { + ToolStripItem item = sender as ToolStripItem; + Debug.Assert(item != null, "Why is item null?"); + if (item != null) + { + EnumValueDescription desc = item.Tag as EnumValueDescription; + Debug.Assert(desc != null, "Why is desc null?"); + if (desc != null && !string.IsNullOrEmpty(desc.PropertyName)) + { + ChangeProperty(desc.PropertyName, desc.Value); + } + } + } + + private void AddNewItemClick(object sender, EventArgs e) + { + ItemTypeToolStripMenuItem senderItem = (ItemTypeToolStripMenuItem)sender; + Type t = senderItem.ItemType; + if (senderItem.ConvertTo) + { + //we are morphing the currentItem + MorphToolStripItem(t); + } + else + { + // we are inserting a new item.. + InsertItem(t); + } + } + + private void MorphToolStripItem(Type t) + { + // Go thru morphing routine only if we have different type. + if (t != currentItem.GetType()) + { + IDesignerHost _designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + ToolStripItemDesigner _designer = (ToolStripItemDesigner)_designerHost.GetDesigner(currentItem); + _designer.MorphCurrentItem(t); + } + } + + private void InsertItem(Type t) + { + if (currentItem is ToolStripMenuItem) + { + InsertMenuItem(t); + } + else + { + InsertStripItem(t); + } + } + + /// + /// Insert MenuItem into ToolStrip. + /// + private void InsertStripItem(Type t) + { + if (ParentTool is StatusStrip parent) + { + InsertIntoStatusStrip(parent, t); + } + else + { + InsertToolStripItem(t); + } + } + + /// + /// Insert MenuItem into ToolStrip. + /// + private void InsertMenuItem(Type t) + { + if (ParentTool is MenuStrip parent) + { + InsertIntoMainMenu(parent, t); + } + else + { + InsertIntoDropDown((ToolStripDropDown)currentItem.Owner, t); + } + } + + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private void TryCancelTransaction(ref DesignerTransaction transaction) + { + if (transaction != null) + { + try + { + transaction.Cancel(); + transaction = null; + } + catch + { + } + } + } + + /// + /// Insert Item into DropDownMenu. + /// + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void InsertIntoDropDown(ToolStripDropDown parent, Type t) + { + IDesignerHost designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + int dummyIndex = parent.Items.IndexOf(currentItem); + if (parent != null) + { + if (parent.OwnerItem is ToolStripDropDownItem ownerItem) + { + if (ownerItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || ownerItem.DropDownDirection == ToolStripDropDownDirection.AboveRight) + { + dummyIndex++; + } + } + + } + + DesignerTransaction newItemTransaction = designerHost.CreateTransaction(SR.ToolStripAddingItem); + try + { + // the code in ComponentAdded will actually get the add done. + IComponent component = designerHost.CreateComponent(t); + IDesigner designer = designerHost.GetDesigner(component); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + + parent.Items.Insert(dummyIndex, (ToolStripItem)component); + // set the selection to our new item.. since we destroyed Original component.. we have to ask SelectionServive from new Component + ISelectionService selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { component }, SelectionTypes.Replace); + } + } + catch (Exception ex) + { + // We need to cancel the ToolStripDesigner's nested MenuItemTransaction; otherwise, we can't cancel our Transaction and the Designer will be left in an unusable state + if ((parent != null) && (parent.OwnerItem != null) && (parent.OwnerItem.Owner != null)) + { + ToolStripDesigner toolStripDesigner = designerHost.GetDesigner(parent.OwnerItem.Owner) as ToolStripDesigner; + if (toolStripDesigner != null) + { + toolStripDesigner.CancelPendingMenuItemTransaction(); + } + } + + // Cancel our new Item transaction + TryCancelTransaction(ref newItemTransaction); + + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + finally + { + if (newItemTransaction != null) + { + newItemTransaction.Commit(); + newItemTransaction = null; + } + } + } + + /// + /// Insert Item into Main MenuStrip. + /// + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void InsertIntoMainMenu(MenuStrip parent, Type t) + { + IDesignerHost designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + int dummyIndex = parent.Items.IndexOf(currentItem); + DesignerTransaction newItemTransaction = designerHost.CreateTransaction(SR.ToolStripAddingItem); + try + { + // the code in ComponentAdded will actually get the add done. + IComponent component = designerHost.CreateComponent(t); + IDesigner designer = designerHost.GetDesigner(component); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + Debug.Assert(dummyIndex != -1, "Why is item index negative?"); + parent.Items.Insert(dummyIndex, (ToolStripItem)component); + // set the selection to our new item.. since we destroyed Original component.. we have to ask SelectionServive from new Component + ISelectionService selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { component }, SelectionTypes.Replace); + } + } + catch (Exception ex) + { + TryCancelTransaction(ref newItemTransaction); + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + finally + { + if (newItemTransaction != null) + { + newItemTransaction.Commit(); + newItemTransaction = null; + } + } + } + + /// + /// Insert Item into StatusStrip. + /// + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void InsertIntoStatusStrip(StatusStrip parent, Type t) + { + IDesignerHost designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + int dummyIndex = parent.Items.IndexOf(currentItem); + DesignerTransaction newItemTransaction = designerHost.CreateTransaction(SR.ToolStripAddingItem); + try + { + // the code in ComponentAdded will actually get the add done. + IComponent component = designerHost.CreateComponent(t); + IDesigner designer = designerHost.GetDesigner(component); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + Debug.Assert(dummyIndex != -1, "Why is item index negative?"); + parent.Items.Insert(dummyIndex, (ToolStripItem)component); + // set the selection to our new item.. since we destroyed Original component.. we have to ask SelectionServive from new Component + ISelectionService selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { component }, SelectionTypes.Replace); + } + } + catch (Exception ex) + { + TryCancelTransaction(ref newItemTransaction); + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + finally + { + if (newItemTransaction != null) + { + newItemTransaction.Commit(); + newItemTransaction = null; + } + } + } + + /// + /// Insert Item into ToolStrip. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void InsertToolStripItem(Type t) + { + IDesignerHost designerHost = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost)); + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + ToolStrip parent = ParentTool; + int dummyIndex = parent.Items.IndexOf(currentItem); + DesignerTransaction newItemTransaction = designerHost.CreateTransaction(SR.ToolStripAddingItem); + try + { + // the code in ComponentAdded will actually get the add done. + IComponent component = designerHost.CreateComponent(t); + IDesigner designer = designerHost.GetDesigner(component); + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + //Set the Image property and DisplayStyle... + if (component is ToolStripButton || component is ToolStripSplitButton || component is ToolStripDropDownButton) + { + Image image = null; + try + { + image = new Bitmap(typeof(ToolStripButton), "blank.bmp"); + } + catch (Exception ex) + { + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + ChangeProperty(component, "Image", image); + ChangeProperty(component, "DisplayStyle", ToolStripItemDisplayStyle.Image); + ChangeProperty(component, "ImageTransparentColor", Color.Magenta); + } + + Debug.Assert(dummyIndex != -1, "Why is item index negative?"); + parent.Items.Insert(dummyIndex, (ToolStripItem)component); + // set the selection to our new item.. since we destroyed Original component.. we have to ask SelectionServive from new Component + ISelectionService selSvc = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { component }, SelectionTypes.Replace); + } + } + catch (Exception ex) + { + if (newItemTransaction != null) + { + newItemTransaction.Cancel(); + newItemTransaction = null; + } + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + + finally + { + if (newItemTransaction != null) + { + newItemTransaction.Commit(); + newItemTransaction = null; + } + } + } + + private bool IsPropertyBrowsable(string propertyName) + { + PropertyDescriptor getProperty = TypeDescriptor.GetProperties(currentItem)[propertyName]; + Debug.Assert(getProperty != null, "Could not find given property in control."); + if (getProperty != null) + { + if (getProperty.Attributes[typeof(BrowsableAttribute)] is BrowsableAttribute attribute) + { + return attribute.Browsable; + } + } + return true; + } + + + //helper function to get the property on the actual Control + private object GetProperty(string propertyName) + { + PropertyDescriptor getProperty = TypeDescriptor.GetProperties(currentItem)[propertyName]; + Debug.Assert(getProperty != null, "Could not find given property in control."); + if (getProperty != null) + { + return getProperty.GetValue(currentItem); + } + return null; + } + + //helper function to change the property on the actual Control + protected void ChangeProperty(string propertyName, object value) + { + ChangeProperty(currentItem, propertyName, value); + } + + protected void ChangeProperty(IComponent target, string propertyName, object value) + { + PropertyDescriptor changingProperty = TypeDescriptor.GetProperties(target)[propertyName]; + Debug.Assert(changingProperty != null, "Could not find given property in control."); + try + { + if (changingProperty != null) + { + changingProperty.SetValue(target, value); + } + } + catch (InvalidOperationException ex) + { + IUIService uiService = (IUIService)serviceProvider.GetService(typeof(IUIService)); + uiService.ShowError(ex.Message); + } + } + + private void RefreshAlignment() + { + ToolStripItemAlignment currentAlignmentValue = (ToolStripItemAlignment)GetProperty("Alignment"); + leftToolStripMenuItem.Checked = (currentAlignmentValue == ToolStripItemAlignment.Left) ? true : false; + rightToolStripMenuItem.Checked = (currentAlignmentValue == ToolStripItemAlignment.Right) ? true : false; + } + + private void RefreshDisplayStyle() + { + ToolStripItemDisplayStyle currentDisplayStyleValue = (ToolStripItemDisplayStyle)GetProperty("DisplayStyle"); + noneStyleToolStripMenuItem.Checked = (currentDisplayStyleValue == ToolStripItemDisplayStyle.None) ? true : false; + textStyleToolStripMenuItem.Checked = (currentDisplayStyleValue == ToolStripItemDisplayStyle.Text) ? true : false; + imageStyleToolStripMenuItem.Checked = (currentDisplayStyleValue == ToolStripItemDisplayStyle.Image) ? true : false; + imageTextStyleToolStripMenuItem.Checked = (currentDisplayStyleValue == ToolStripItemDisplayStyle.ImageAndText) ? true : false; + } + + public override void RefreshItems() + { + base.RefreshItems(); + ToolStripItem selectedItem = currentItem; + if (!(selectedItem is ToolStripControlHost) && !(selectedItem is ToolStripSeparator)) + { + enabledToolStripMenuItem.Checked = (bool)GetProperty("Enabled"); + if (selectedItem is ToolStripMenuItem) + { + checkedToolStripMenuItem.Checked = (bool)GetProperty("Checked"); + showShortcutKeysToolStripMenuItem.Checked = (bool)GetProperty("ShowShortcutKeys"); + } + else + { + if (selectedItem is ToolStripLabel) + { + isLinkToolStripMenuItem.Checked = (bool)GetProperty("IsLink"); + } + RefreshAlignment(); + RefreshDisplayStyle(); + } + } + } + + // tiny little class to handle enum value changes + private class EnumValueDescription + { + public EnumValueDescription(string propertyName, object value) + { + PropertyName = propertyName; + Value = value; + } + public string PropertyName; + public object Value; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemDataObject.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemDataObject.cs new file mode 100644 index 00000000000..c46d9fb877f --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemDataObject.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; + +namespace System.Windows.Forms.Design +{ + /// + /// Wrapper class for DataObject. This wrapped object is passed when a ToolStripItem is Drag-Dropped during DesignTime. + /// + internal class ToolStripItemDataObject : DataObject + { + private readonly ArrayList _dragComponents; + private readonly ToolStrip _owner; + private readonly ToolStripItem _primarySelection; + internal ToolStripItemDataObject(ArrayList dragComponents, ToolStripItem primarySelection, ToolStrip owner) : base() + { + _dragComponents = dragComponents; + _owner = owner; + _primarySelection = primarySelection; + } + + internal ArrayList DragComponents + { + get => _dragComponents; + } + + internal ToolStrip Owner + { + get => _owner; + } + + internal ToolStripItem PrimarySelection + { + get => _primarySelection; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemDesigner.cs new file mode 100644 index 00000000000..4bbb8acf1d1 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemDesigner.cs @@ -0,0 +1,1360 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + internal class ToolStripItemDesigner : ComponentDesigner + { + private const int GLYPHBORDER = 1; + private const int GLYPHINSET = 2; + // Cached in value of the TemplateNode (which is the InSitu Editor) + private ToolStripTemplateNode _editorNode; + // Used by the ParentDesigner (ToolStripDesigner) to know whether there is any active Editor. + private bool isEditorActive = false; + // this property is used in the InitializeNewComponent not to set the text for the ToolstripItem + private bool internalCreate = false; + //hook to SelectionService to listen to SelectionChanged + private ISelectionService selSvc = null; + //ToolStripItems Visibility needs to be WYSIWYG. + private bool currentVisible = false; + private Rectangle lastInsertionMarkRect = Rectangle.Empty; + // Required to remove Body Glyphs .... + internal ControlBodyGlyph bodyGlyph = null; + //bool which is set if we Add Dummy Item + internal bool dummyItemAdded = false; + //Needed to Store the DRAGDROP Rect from the ToolStripItemBehavior. + internal Rectangle dragBoxFromMouseDown = Rectangle.Empty; + //defaulted to invalid index. this will be set by the behaviour. + internal int indexOfItemUnderMouseToDrag = -1; + private ToolStripItemCustomMenuItemCollection toolStripItemCustomMenuItemCollection; + + internal bool AutoSize + { + get => (bool)ShadowProperties["AutoSize"]; + set + { + bool autoSize = (bool)ShadowProperties["AutoSize"]; + // always set this in regardless of whether the property changed. it can come back to bite later after in-situ editing if we dont. + ShadowProperties["AutoSize"] = value; + if (value != autoSize) + { + ToolStripItem.AutoSize = value; + } + } + } + + private string AccessibleName + { + get + { + return (string)ShadowProperties["AccessibleName"]; + } + set + { + ShadowProperties["AccessibleName"] = value; + } + } + + /// + /// Associated Parent Designer + /// + internal override bool CanBeAssociatedWith(IDesigner parentDesigner) + { + return (parentDesigner is ToolStripDesigner); + } + + + /// + /// Designer Custom ContextMenu. + /// + private ContextMenuStrip DesignerContextMenu + { + get + { + BaseContextMenuStrip toolStripContextMenu = new BaseContextMenuStrip(Component.Site, ToolStripItem); + // If multiple Items Selected dont show the custom properties... + if (selSvc.SelectionCount > 1) + { + toolStripContextMenu.GroupOrdering.Clear(); + toolStripContextMenu.GroupOrdering.AddRange(new string[] { StandardGroups.Code, StandardGroups.Selection, StandardGroups.Edit, StandardGroups.Properties}); + } + else + { + toolStripContextMenu.GroupOrdering.Clear(); + toolStripContextMenu.GroupOrdering.AddRange(new string[] { StandardGroups.Code, StandardGroups.Custom, StandardGroups.Selection, StandardGroups.Edit, StandardGroups.Properties}); + toolStripContextMenu.Text = "CustomContextMenu"; + if (toolStripItemCustomMenuItemCollection == null) + { + toolStripItemCustomMenuItemCollection = new ToolStripItemCustomMenuItemCollection(Component.Site, ToolStripItem); + } + foreach (ToolStripItem item in toolStripItemCustomMenuItemCollection) + { + toolStripContextMenu.Groups[StandardGroups.Custom].Items.Add(item); + } + } + + // Refresh the list on every show.. + if (toolStripItemCustomMenuItemCollection != null) + { + toolStripItemCustomMenuItemCollection.RefreshItems(); + } + toolStripContextMenu.Populated = false; + return toolStripContextMenu; + } + } + + /// + /// ToolStripEditorManager used this internal property to Activate the editor. + /// + internal virtual ToolStripTemplateNode Editor + { + get => _editorNode; + set => _editorNode = value; + } + + + // ToolStripItems if Inherited ACT as Readonly. + protected override InheritanceAttribute InheritanceAttribute + { + get + { + if ((base.InheritanceAttribute == InheritanceAttribute.Inherited)) + { + return InheritanceAttribute.InheritedReadOnly; + } + return base.InheritanceAttribute; + } + } + + /// + /// ToolStripEditorManager used this internal property to set the the desinger's IsEditorActive to notify if this item has entered or exited the InSitu Edit Mode. + /// + internal bool IsEditorActive + { + get => isEditorActive; + set => isEditorActive = value; + } + + /// + /// When the ToolStripItem is created we dont want InitializeNewComponent to set the "text" we do it ourselves from the Text the User has provided in the InSitu Edit Mode. Reason being the item and the Parent unnecessarily Layout and cause flicker. + /// + internal bool InternalCreate + { + get => internalCreate; + set => internalCreate = value; + } + + protected IComponent ImmediateParent + { + get + { + if (ToolStripItem != null) + { + ToolStrip parent = ToolStripItem.GetCurrentParent(); + return parent ?? ToolStripItem.Owner; + } + return null; + } + } + + private ToolStripItemOverflow Overflow + { + get => (ToolStripItemOverflow)ShadowProperties["Overflow"]; + set + { + // first Hide the Overflow.. + if (ToolStripItem.IsOnOverflow) + { + ToolStrip strip = ToolStripItem.Owner as ToolStrip; + if (strip.OverflowButton.DropDown.Visible) + { + strip.OverflowButton.HideDropDown(); + } + } + if (ToolStripItem is ToolStripDropDownItem) + { + ToolStripDropDownItem item = ToolStripItem as ToolStripDropDownItem; + item.HideDropDown(); + } + //set the value on actual item + if (value != ToolStripItem.Overflow) + { + ToolStripItem.Overflow = value; + ShadowProperties["Overflow"] = value; + } + + // Since this cause the whole Layout to Change ... Call SyncSelection to reset the glyphs... + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + if (b != null) + { + b.SyncSelection(); + } + } + } + + protected override IComponent ParentComponent + { + get + { + if (ToolStripItem != null) + { + if (ToolStripItem.IsOnDropDown && !ToolStripItem.IsOnOverflow) + { + if (ImmediateParent is ToolStripDropDown parentDropDown) + { + if (parentDropDown.IsAutoGenerated) + { + return parentDropDown.OwnerItem; + } + else + { + return parentDropDown; + } + } + } + return GetMainToolStrip(); + } + return null; + } + } + + /// + /// Easy method for getting to the ToolStripItem + /// + public ToolStripItem ToolStripItem + { + get => (ToolStripItem)Component; + } + + protected bool Visible + { + get => (bool)ShadowProperties["Visible"]; + set + { + ShadowProperties["Visible"] = value; + currentVisible = value; + } + } + + /// + /// This method adds the Parent Hierarchy to arraylist and returns that arraylist to the Base ContextMenu provider. This way the ToolStripItem can show the right parents in the contextMenu + /// + internal ArrayList AddParentTree() + { + ArrayList parentControls = new ArrayList(); + IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (designerHost != null) + { + IComponent root = designerHost.RootComponent; + Component startComp = ToolStripItem; + if (startComp != null && root != null) + { + while (startComp != root) + { + if (startComp is ToolStripItem) + { + ToolStripItem item = startComp as ToolStripItem; + if (item.IsOnDropDown) + { + if (item.IsOnOverflow) + { + parentControls.Add(item.Owner); + startComp = item.Owner; + } + else + { + if (item.Owner is ToolStripDropDown parentDropDown) + { + ToolStripItem ownerItem = parentDropDown.OwnerItem; + if (ownerItem != null) + { + parentControls.Add(ownerItem); + startComp = ownerItem; + } + } + } + } + else + { + if (item.Owner.Site != null) + { + parentControls.Add(item.Owner); + } + startComp = item.Owner; + } + } + else if (startComp is Control) + { + Control selectedControl = startComp as Control; + Control parentControl = selectedControl.Parent; + if (parentControl.Site != null) + { + parentControls.Add(parentControl); + } + startComp = parentControl; + } + } + } + } + return parentControls; + } + + /// + /// Creates the InSitu Edit Node (which is called the TemplateNode). + /// + private void CreateDummyNode() + { + _editorNode = new ToolStripTemplateNode(ToolStripItem, ToolStripItem.Text, ToolStripItem.Image); + } + + /// + /// This is called by the TemplateNode to Commit the Edit. This Function Simply changes the "Text and Image" property of the current ToolStripItem. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + internal virtual void CommitEdit(Type type, string text, bool commit, bool enterKeyPressed, bool tabKeyPressed) + { + ToolStripItem newItem = null; + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + BehaviorService bSvc = (BehaviorService)GetService(typeof(BehaviorService)); + ToolStrip immediateParent = ImmediateParent as ToolStrip; + immediateParent.SuspendLayout(); + HideDummyNode(); + IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); + ToolStripDesigner designer = (ToolStripDesigner)designerHost.GetDesigner(ToolStripItem.Owner); + if (designer != null && designer.EditManager != null) + { + designer.EditManager.ActivateEditor(null, false); + } + // Cannot Add ToolStripSeparator to MenuStrip + if (immediateParent is MenuStrip && type == typeof(ToolStripSeparator)) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + IUIService uiSvc = (IUIService)host.GetService(typeof(IUIService)); + if (uiSvc != null) + { + uiSvc.ShowError(SR.ToolStripSeparatorError); + // dont commit the item.. + commit = false; + // Select the MenuStrip + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { immediateParent }); + } + } + } + } + if (commit) + { + if (dummyItemAdded) + { + try + { + RemoveItem(); + newItem = designer.AddNewItem(type, text, enterKeyPressed, false /* Dont select the templateNode but select the newly added item */); + } + finally + { + if (designer.NewItemTransaction != null) + { + designer.NewItemTransaction.Commit(); + designer.NewItemTransaction = null; + } + } + } + else + { + //create our transaction + DesignerTransaction designerTransaction = designerHost.CreateTransaction(SR.ToolStripItemPropertyChangeTransaction); + try + { + //Change the Text... + PropertyDescriptor textProp = TypeDescriptor.GetProperties(ToolStripItem)["Text"]; + string oldValue = (string)textProp.GetValue(ToolStripItem); + if (textProp != null && text != oldValue) + { + textProp.SetValue(ToolStripItem, text); + } + if (enterKeyPressed && selSvc != null) + { + SelectNextItem(selSvc, enterKeyPressed, designer); + } + } + catch (Exception e) + { + if (designerTransaction != null) + { + designerTransaction.Cancel(); + designerTransaction = null; + } + if (selMgr != null) + { + selMgr.Refresh(); + } + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + finally + { + if (designerTransaction != null) + { + designerTransaction.Commit(); + designerTransaction = null; + } + } + } + //Reset the DummyItem flag + dummyItemAdded = false; + } + else + { + // Refresh on SelectionManager... To Change Glyph Size. + if (dummyItemAdded) + { + dummyItemAdded = false; + RemoveItem(); + + if (designer.NewItemTransaction != null) + { + designer.NewItemTransaction.Cancel(); + designer.NewItemTransaction = null; + } + } + } + immediateParent.ResumeLayout(); + if (newItem != null && !newItem.IsOnDropDown) + { + if (newItem is ToolStripDropDownItem dropDown) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(newItem); + Rectangle itemBounds = itemDesigner.GetGlyphBounds(); + if (designerHost.RootComponent is Control parent) + { + if (bSvc != null) + { + Rectangle parentBounds = bSvc.ControlRectInAdornerWindow(parent); + if (!ToolStripDesigner.IsGlyphTotallyVisible(itemBounds, parentBounds)) + { + dropDown.HideDropDown(); + } + } + } + } + } + + // used the SelectionManager to Add the glyphs. + if (selMgr != null) + { + selMgr.Refresh(); + } + } + + /// + /// Disposes of this designer. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + //clean up + if (_editorNode != null) + { + _editorNode.CloseEditor(); + _editorNode = null; + } + + if (ToolStripItem != null) + { + ToolStripItem.Paint -= new System.Windows.Forms.PaintEventHandler(OnItemPaint); + } + // Now, unhook the component rename event + IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (cs != null) + { + cs.ComponentRename -= new ComponentRenameEventHandler(OnComponentRename); + } + + //clean up + if (selSvc != null) + { + selSvc.SelectionChanged -= new EventHandler(OnSelectionChanged); + } + //clean up the ToolStripItem Glyph if Any + if (bodyGlyph != null) + { + ToolStripAdornerWindowService toolStripAdornerWindowService = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService)); + if (toolStripAdornerWindowService != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(bodyGlyph)) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(bodyGlyph); + } + } + // Remove the Collection + if (toolStripItemCustomMenuItemCollection != null && toolStripItemCustomMenuItemCollection.Count > 0) + { + foreach (ToolStripItem item in toolStripItemCustomMenuItemCollection) + { + item.Dispose(); + } + toolStripItemCustomMenuItemCollection.Clear(); + } + toolStripItemCustomMenuItemCollection = null; + } + base.Dispose(disposing); + } + + /// + /// Returns the owner of the current ToolStripItem. + /// + protected virtual Component GetOwnerForActionList() => (ToolStripItem.Placement == ToolStripItemPlacement.Main) ? ToolStripItem.GetCurrentParent() : ToolStripItem.Owner; + + internal virtual ToolStrip GetMainToolStrip() => ToolStripItem.Owner; + + public Rectangle GetGlyphBounds() + { + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + Rectangle r = Rectangle.Empty; + if (b != null && ImmediateParent != null) + { + Point loc = b.ControlToAdornerWindow((Control)ImmediateParent); + r = ToolStripItem.Bounds; + r.Offset(loc); + } + return r; + } + + // Need to Fire ComponentChanging on all the DropDownItems. Please see "MorphToolStripItem" function for more details. + private void FireComponentChanging(ToolStripDropDownItem parent) + { + if (parent != null) + { + IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (changeSvc != null && parent.Site != null) + { + changeSvc.OnComponentChanging(parent, TypeDescriptor.GetProperties(parent)["DropDownItems"]); + } + foreach (ToolStripItem item in parent.DropDownItems) + { + //Dont Serialize the DesignerToolStripControlHost... + if (item is ToolStripDropDownItem dropDownItem && dropDownItem.DropDownItems.Count > 1 /*including TN*/) + { + FireComponentChanging(dropDownItem); + } + } + } + } + + private void FireComponentChanged(ToolStripDropDownItem parent) + { + if (parent != null) + { + IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (changeSvc != null && parent.Site != null) + { + changeSvc.OnComponentChanged(parent, TypeDescriptor.GetProperties(parent)["DropDownItems"], null, null); + } + + foreach (ToolStripItem item in parent.DropDownItems) + { + //Dont Serialize the DesignerToolStripControlHost... + if (item is ToolStripDropDownItem dropDownItem && dropDownItem.DropDownItems.Count > 1 /*including TN*/) + { + FireComponentChanged(dropDownItem); + } + } + } + } + + public void GetGlyphs(ref GlyphCollection glyphs, System.Windows.Forms.Design.Behavior.Behavior standardBehavior) + { + if (ImmediateParent != null) + { + Rectangle r = GetGlyphBounds(); + ToolStripDesignerUtils.GetAdjustedBounds(ToolStripItem, ref r); + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + Rectangle parentBounds = b.ControlRectInAdornerWindow((Control)ImmediateParent); + if (parentBounds.Contains(r.Left, r.Top)) + { + // Dont paint the glyphs if we are opening a DropDown... + if (ToolStripItem.IsOnDropDown) + { + ToolStrip parent = ToolStripItem.GetCurrentParent(); + if (parent == null) + { + parent = ToolStripItem.Owner; + } + if (parent != null && parent.Visible) + { + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Top, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Bottom, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Left, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Right, standardBehavior, true)); + } + } + else + { + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Top, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Bottom, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Left, standardBehavior, true)); + glyphs.Add(new MiniLockedBorderGlyph(r, SelectionBorderGlyphType.Right, standardBehavior, true)); + } + } + } + } + + /// + /// Returns the root dropdown in the chain. + /// + internal ToolStripDropDown GetFirstDropDown(ToolStripItem currentItem) + { + if (currentItem.Owner is ToolStripDropDown) + { + ToolStripDropDown topmost = currentItem.Owner as ToolStripDropDown; + // walk back up the chain of windows to get the topmost + while (topmost.OwnerItem != null && (topmost.OwnerItem.Owner is ToolStripDropDown)) + { + topmost = topmost.OwnerItem.Owner as ToolStripDropDown; + } + return topmost; + } + return null; + } + + /// + /// This helper function resets the AutoSize property so that the item SNAPS back to its "preferredSize". + /// + private void HideDummyNode() + { + ToolStripItem.AutoSize = AutoSize; + if (_editorNode != null) + { + _editorNode.CloseEditor(); + _editorNode = null; + } + } + + /// + /// Get the designer set up to run. + /// + public override void Initialize(IComponent component) + { + base.Initialize(component); + //Shadow AutoSize + AutoSize = ToolStripItem.AutoSize; + Visible = true; + currentVisible = Visible; + //Shadow the AccessibleName as we are going to change it at DesignTime + AccessibleName = ToolStripItem.AccessibleName; + ToolStripItem.Paint += new System.Windows.Forms.PaintEventHandler(OnItemPaint); + //Change the AccessibleName to point to ToolStirpItem.Name + ToolStripItem.AccessibleName = ToolStripItem.Name; + // Now, hook the component rename event so we can update the AccessibleName + IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (cs != null) + { + cs.ComponentRename += new ComponentRenameEventHandler(this.OnComponentRename); + } + + //hook our SelectionService. + selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SelectionChanged += new EventHandler(this.OnSelectionChanged); + } + } + + /// + /// Overriden to always Initialise the ToolStripItem with Text property. + /// + public override void InitializeNewComponent(IDictionary defaultValues) + { + //Set the Text only if the item is not created internally (via InSitu Edit) + if (!internalCreate) + { + ISite site = Component.Site; + if (site != null && Component is ToolStripDropDownItem) + { + if (defaultValues == null) + defaultValues = new Hashtable(); + defaultValues["Text"] = site.Name; + IComponent component = Component; + PropertyDescriptor pd = TypeDescriptor.GetProperties(ToolStripItem)["Text"]; + + if (pd != null && pd.PropertyType.Equals(typeof(string))) + { + string current = (string)pd.GetValue(component); + if (current == null || current.Length == 0) + { + pd.SetValue(component, site.Name); + } + } + } + } + base.InitializeNewComponent(defaultValues); + // ComboBoxes and TextBoxes shouldnt have Texts... In TextBoxBaseDesigner we do similar thing where we call the base (which sets the text) and then reset it back + if (Component is ToolStripTextBox || Component is ToolStripComboBox) + { + PropertyDescriptor textProp = TypeDescriptor.GetProperties(Component)["Text"]; + if (textProp != null && textProp.PropertyType == typeof(string) && !textProp.IsReadOnly && textProp.IsBrowsable) + { + textProp.SetValue(Component, ""); + } + } + } + + /// + /// This will morph the current item to the provided type "t" of the item... + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + internal virtual ToolStripItem MorphCurrentItem(Type t) + { + ToolStripItem newItem = null; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host == null) + { + Debug.Fail("Couldn't get designer host!"); + return newItem; + } + + //create our transaction + DesignerTransaction designerTransaction = host.CreateTransaction(SR.ToolStripMorphingItemTransaction); + ToolStrip parent = (ToolStrip)ImmediateParent; + // Sepcial case overflow... + if (parent is ToolStripOverflow) + { + parent = ToolStripItem.Owner; + } + ToolStripMenuItemDesigner ownerItemDesigner = null; + + int dummyIndex = parent.Items.IndexOf(ToolStripItem); + string name = ToolStripItem.Name; + ToolStripItem ownerItem = null; + + // Get the main ToolStrip to Set the Glyph for the new Item once it is MORPHED. + if (ToolStripItem.IsOnDropDown) + { + if (ImmediateParent is ToolStripDropDown parentDropDown) + { + ownerItem = parentDropDown.OwnerItem; + if (ownerItem != null) + { + ownerItemDesigner = (ToolStripMenuItemDesigner)host.GetDesigner(ownerItem); + } + } + } + + try + { + //turn off Adding and Added Transactions.. + ToolStripDesigner.s_autoAddNewItems = false; + ComponentSerializationService _serializationService = GetService(typeof(ComponentSerializationService)) as ComponentSerializationService; + SerializationStore _serializedData = null; + if (_serializationService != null) + { + _serializedData = _serializationService.CreateStore(); + _serializationService.Serialize(_serializedData, Component); //notice the use of component... since we want to preserve the type. + + //Serialize all the DropDownItems for this Item.... + SerializationStore _serializedDataForDropDownItems = null; + ToolStripDropDownItem dropDownItem = ToolStripItem as ToolStripDropDownItem; + if (dropDownItem != null && typeof(ToolStripDropDownItem).IsAssignableFrom(t)) + { + // Hide the DropDown. + dropDownItem.HideDropDown(); + _serializedDataForDropDownItems = _serializationService.CreateStore(); + SerializeDropDownItems(dropDownItem, ref _serializedDataForDropDownItems, _serializationService); + //close the SerializationStore to Serialize Items.. + _serializedDataForDropDownItems.Close(); + } + + //close the SerializationStore to Serialize the ToolStripItem + _serializedData.Close(); + //Remove the currentItem that is getting morphed.. + IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + if (changeSvc != null) + { + if (parent.Site != null) + { + changeSvc.OnComponentChanging(parent, TypeDescriptor.GetProperties(parent)["Items"]); + } + else if (ownerItem != null) + { + changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + } + + FireComponentChanging(dropDownItem); + parent.Items.Remove(ToolStripItem); + host.DestroyComponent(ToolStripItem); + //Create our new Item + ToolStripItem component = (ToolStripItem)host.CreateComponent(t, name); + //Since destroying the original item took away its DropDownItems. We need to Deserialize the items again... + if (component is ToolStripDropDownItem) + { + if (_serializedDataForDropDownItems != null) + { + _serializationService.Deserialize(_serializedDataForDropDownItems); + } + } + + //Now deserialize the newItem to morph to the old item... + _serializationService.DeserializeTo(_serializedData, host.Container, false, true); + // Add the new Item... + newItem = (ToolStripItem)host.Container.Components[name]; + //Set the Image property and DisplayStyle... + if (newItem.Image == null && newItem is ToolStripButton) + { + Image image = null; + try + { + image = new Bitmap(typeof(ToolStripButton), "blank.bmp"); + } + catch (Exception ex) + { + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + + PropertyDescriptor imageProperty = TypeDescriptor.GetProperties(newItem)["Image"]; + Debug.Assert(imageProperty != null, "Could not find 'Image' property in ToolStripItem."); + if (imageProperty != null && image != null) + { + imageProperty.SetValue(newItem, image); + } + + PropertyDescriptor dispProperty = TypeDescriptor.GetProperties(newItem)["DisplayStyle"]; + Debug.Assert(dispProperty != null, "Could not find 'DisplayStyle' property in ToolStripItem."); + if (dispProperty != null) + { + dispProperty.SetValue(newItem, ToolStripItemDisplayStyle.Image); + } + + PropertyDescriptor imageTransProperty = TypeDescriptor.GetProperties(newItem)["ImageTransparentColor"]; + Debug.Assert(imageTransProperty != null, "Could not find 'DisplayStyle' property in ToolStripItem."); + if (imageTransProperty != null) + { + imageTransProperty.SetValue(newItem, Color.Magenta); + } + + } + + parent.Items.Insert(dummyIndex, newItem); + if (changeSvc != null) + { + if (parent.Site != null) + { + changeSvc.OnComponentChanged(parent, TypeDescriptor.GetProperties(parent)["Items"], null, null); + } + else if (ownerItem != null) + { + changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + } + + FireComponentChanged(dropDownItem); + // Add the Glyph for the DropDown ... We are responsible for the Glyh Addition since BodyGlyphs for DropDownItems are added by us. + if (newItem.IsOnDropDown && ownerItemDesigner != null) + { + ownerItemDesigner.RemoveItemBodyGlyph(newItem); + ownerItemDesigner.AddItemBodyGlyph(newItem); + } + // re start the ComponentAdding/Added events + ToolStripDesigner.s_autoAddNewItems = true; + //Invalidate the AdornerWindow to refresh selectionglyphs. + if (newItem != null) + { + if (newItem is ToolStripSeparator) + { + parent.PerformLayout(); + } + BehaviorService windowService = (BehaviorService)newItem.Site.GetService(typeof(BehaviorService)); + if (windowService != null) + { + windowService.Invalidate(); + } + + // set the selection to our new item.. since we destroyed Original component.. we have to ask SelectionServive from new Component + ISelectionService selSvc = (ISelectionService)newItem.Site.GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SetSelectedComponents(new object[] { newItem }, SelectionTypes.Replace); + } + } + } + } + catch + { + host.Container.Add(ToolStripItem); + parent.Items.Insert(dummyIndex, ToolStripItem); + if (designerTransaction != null) + { + designerTransaction.Cancel(); + designerTransaction = null; + } + } + finally + { + if (designerTransaction != null) + { + designerTransaction.Commit(); + designerTransaction = null; + } + } + return newItem; + } + + /// + /// Raised when a component's name changes. Here we update the AccessibleName Property to match the newName. + /// + private void OnComponentRename(object sender, ComponentRenameEventArgs e) + { + if (e.Component == ToolStripItem) + { + ToolStripItem.AccessibleName = e.NewName; + } + } + + /// + /// This can be used for OVERFLOW !!! + /// + private void OnItemPaint(object sender, System.Windows.Forms.PaintEventArgs e) + { + if (ToolStripItem.GetCurrentParent() is ToolStripDropDown dropDown) + { + if (selSvc != null) + { + if (!IsEditorActive && ToolStripItem.Equals(selSvc.PrimarySelection)) + { + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + + if (behaviorService != null) + { + Point loc = behaviorService.ControlToAdornerWindow((Control)ImmediateParent); + Rectangle r = ToolStripItem.Bounds; + r.Offset(loc); + r.Inflate(GLYPHINSET, GLYPHINSET); + //this will allow any Glyphs to re-paint + //after this control and its designer has painted + behaviorService.ProcessPaintMessage(r); + + } + } + } + } + } + + /// + /// For ToolStripItems that are not MenuItems and are on Dropdown we need ot update Selection Rect. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + if (!(sender is ISelectionService sSvc)) + { + return; + } + //determine if we are selected + ToolStripItem currentSelection = sSvc.PrimarySelection as ToolStripItem; + // Accessibility information + if (ToolStripItem.AccessibilityObject is ToolStripItem.ToolStripItemAccessibleObject acc) + { + acc.AddState(AccessibleStates.None); + ToolStrip tool = GetMainToolStrip(); + if (sSvc.GetComponentSelected(ToolStripItem)) + { + ToolStrip owner = ImmediateParent as ToolStrip; + int focusIndex = 0; + if (owner != null) + { + focusIndex = owner.Items.IndexOf(currentSelection); + } + acc.AddState(AccessibleStates.Selected); + if (tool != null) + { + Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "MSAA: SelectionAdd, tool = " + tool.ToString()); + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.SelectionAdd, new HandleRef(owner, owner.Handle), NativeMethods.OBJID_CLIENT, focusIndex + 1); + } + if (currentSelection == ToolStripItem) + { + acc.AddState(AccessibleStates.Focused); + if (tool != null) + { + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.Focus, new HandleRef(owner, owner.Handle), NativeMethods.OBJID_CLIENT, focusIndex + 1); + } + } + } + } + + if (currentSelection != null && currentSelection.Equals(ToolStripItem) && !(ToolStripItem is ToolStripMenuItem)) + { + if (currentSelection.IsOnDropDown) + { + //If the Item is on DropDown ... Show its DropDown and all PArent Dropdown if not visible.. + IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (designerHost != null) + { + if (currentSelection.Owner is ToolStripDropDown parentDropDown) + { + bool needRefresh = false; + if (parentDropDown.OwnerItem is ToolStripDropDownItem parentItem) + { + ToolStripMenuItemDesigner parentItemDesigner = (ToolStripMenuItemDesigner)designerHost.GetDesigner(parentItem); + if (parentItemDesigner != null) + { + parentItemDesigner.InitializeDropDown(); + } + needRefresh = true; + } + else if (parentDropDown is ContextMenuStrip) + { + // For ContextMenuStrip, we need use different ways to show the menu. + ToolStripDropDownDesigner parentDropDownDesigner = (ToolStripDropDownDesigner)designerHost.GetDesigner(parentDropDown); + if (parentDropDownDesigner != null) + { + parentDropDownDesigner.ShowMenu(currentSelection); + } + needRefresh = true; + } + + if (needRefresh) + { + // Refresh on SelectionManager... To Change Glyph Size. + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + // used the cached value... + if (selMgr != null) + { + selMgr.Refresh(); + } + // Invalidate the dropdown area. This is necessary when a different item is selected in the same dropdown. + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + behaviorService.Invalidate(parentDropDown.Bounds); + } + } + } + } + } + else if (currentSelection.Owner != null) + { + // The selected item could be in a MenuStrip, StatusStrip or ToolStrip. Need invalidate the BehaviorService to reflect the selection change. + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + behaviorService.Invalidate(behaviorService.ControlRectInAdornerWindow(currentSelection.Owner)); + } + } + } + } + + /// + /// Allows a designer to filter the set of properties the component it is designing will expose through the TypeDescriptor object. This method is called immediately before its corresponding "Post" method. If you are overriding this method you should call the base implementation before you perform your own filtering. + /// + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + // Handle shadowed properties + string[] shadowProps = new string[] { "AutoSize", "AccessibleName", "Visible", "Overflow" }; + + PropertyDescriptor prop; + Attribute[] empty = new Attribute[0]; + for (int i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ToolStripItemDesigner), prop, empty); + } + } + } + + // CALLED ONLY IF THE EDIT ACTION WAS ROLLBACKED!!! + public void RemoveItem() + { + dummyItemAdded = false; + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host == null) + { + Debug.Fail("Couldn't get designer host!"); + return; + } + //Remove the dummy Item since the Edit was CANCELLED.. + ToolStrip parent = (ToolStrip)ImmediateParent; + if (parent is ToolStripOverflow) + { + parent = ParentComponent as ToolStrip; + } + parent.Items.Remove(ToolStripItem); + host.DestroyComponent(ToolStripItem); + } + + + // + // Resets the ToolStripItemAutoSize to be the default autosize + // + private void ResetAutoSize() => ShadowProperties["AutoSize"] = false; + + // + // Restores the AutoSize to be the value set in the property grid. + // + private void RestoreAutoSize() => ToolStripItem.AutoSize = (bool)ShadowProperties["AutoSize"]; + + // + // Resets the ToolStrip Visible to be the default value + // + private void ResetVisible() => Visible = true; + + // + // Restore Overflow + // + private void RestoreOverflow() => ToolStripItem.Overflow = (ToolStripItemOverflow)ShadowProperties["Overflow"]; + + // + // Resets Overflow + // + private void ResetOverflow() => ToolStripItem.Overflow = ToolStripItemOverflow.AsNeeded; + + // + // Resets the ToolStripItem AccessibleName to the default + // + private void ResetAccessibleName() => ShadowProperties["AccessibleName"] = null; + + // + // Restores the AutoSize to be the value set in the property grid. + // + private void RestoreAccessibleName() => ToolStripItem.AccessibleName = (string)ShadowProperties["AccessibleName"]; + + // internal method called to select the next item from the current item. + internal void SelectNextItem(ISelectionService service, bool enterKeyPressed, ToolStripDesigner designer) + { + if (ToolStripItem is ToolStripDropDownItem dropDownItem) + { + SetSelection(enterKeyPressed); + } + else + //We are here for simple ToolStripItems... + { + ToolStrip parent = (ToolStrip)ImmediateParent; + if (parent is ToolStripOverflow) + { + parent = ToolStripItem.Owner; + } + int currentIndex = parent.Items.IndexOf(ToolStripItem); + ToolStripItem nextItem = parent.Items[currentIndex + 1]; + // Set the Selection to the NEXT ITEM in the TOOLSTRIP... + ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (keyboardHandlingService != null) + { + if (nextItem == designer.EditorNode) + { + keyboardHandlingService.SelectedDesignerControl = nextItem; + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + else + { + keyboardHandlingService.SelectedDesignerControl = null; + selSvc.SetSelectedComponents(new object[] { nextItem }); + } + } + } + } + + // Recursive function to add all the menuItems to the SerializationStore during Morphing.. + private void SerializeDropDownItems(ToolStripDropDownItem parent, ref SerializationStore _serializedDataForDropDownItems, ComponentSerializationService _serializationService) + { + foreach (ToolStripItem item in parent.DropDownItems) + { + //Dont Serialize the DesignerToolStripControlHost... + if (!(item is DesignerToolStripControlHost)) + { + _serializationService.Serialize(_serializedDataForDropDownItems, item); + if (item is ToolStripDropDownItem dropDownItem) + { + SerializeDropDownItems(dropDownItem, ref _serializedDataForDropDownItems, _serializationService); + } + } + } + } + + + // Sets the Item visibility to honor WYSIWYG + internal void SetItemVisible(bool toolStripSelected, ToolStripDesigner designer) + { + if (toolStripSelected) + { + // Set the Visiblity if different. + if (!currentVisible) + { + ToolStripItem.Visible = true; + if (designer != null && !designer.FireSyncSelection) + { + designer.FireSyncSelection = true; + } + } + } + else + { + if (!currentVisible) + { + ToolStripItem.Visible = currentVisible; + } + } + } + + private bool ShouldSerializeVisible() => !Visible; + + // + // Since we're shadowing autosize, we get called here to determine whether or not to serialize + // + private bool ShouldSerializeAutoSize() => (ShadowProperties.Contains("AutoSize")); + + // + // Since we're shadowing autosize, we get called here to determine whether or not to serialize + // + private bool ShouldSerializeAccessibleName() => (ShadowProperties["AccessibleName"] != null); + + // + // Since we're Overflow Size, we get called here to determine whether or not to serialize + // + private bool ShouldSerializeOverflow() => (ShadowProperties["Overflow"] != null); + + /// + /// This Function is called thru the ToolStripEditorManager which is listening for the F2 command. + /// + internal virtual void ShowEditNode(bool clicked) + { + // ACTIVATION ONLY FOR TOOLSTRIPMENUITEMS + if (ToolStripItem is ToolStripMenuItem) + { + if (_editorNode == null) + { + CreateDummyNode(); + } + + IDesignerHost designerHost = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost)); + ToolStrip parent = ImmediateParent as ToolStrip; + Debug.Assert(parent != null, "ImmediateParent is null for the current ToolStripItem !!"); + if (parent != null) + { + ToolStripDesigner parentDesigner = (ToolStripDesigner)designerHost.GetDesigner(parent); + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + Point loc = b.ControlToAdornerWindow(parent); + + //Get the original ToolStripItem bounds. + Rectangle origBoundsInAdornerWindow = ToolStripItem.Bounds; + origBoundsInAdornerWindow.Offset(loc); + ToolStripItem.AutoSize = false; + _editorNode.SetWidth(ToolStripItem.Text); + if (parent.Orientation == Orientation.Horizontal) + { + ToolStripItem.Width = _editorNode.EditorToolStrip.Width + 2; + } + else + { + ToolStripItem.Height = _editorNode.EditorToolStrip.Height; + } + // Refresh the glyphs. + if (!dummyItemAdded) + { + b.SyncSelection(); + } + + if (ToolStripItem.Placement != ToolStripItemPlacement.None) + { + Rectangle boundsInAdornerWindow = ToolStripItem.Bounds; + boundsInAdornerWindow.Offset(loc); + + //Center it in verticaldirection. + if (parent.Orientation == Orientation.Horizontal) + { + boundsInAdornerWindow.X++; + boundsInAdornerWindow.Y += (ToolStripItem.Height - _editorNode.EditorToolStrip.Height) / 2; + boundsInAdornerWindow.Y++; + } + else + { + boundsInAdornerWindow.X += (ToolStripItem.Width - _editorNode.EditorToolStrip.Width) / 2; + boundsInAdornerWindow.X++; + } + _editorNode.Bounds = boundsInAdornerWindow; + //Invalidate the union of the original bounds and the new bounds. + boundsInAdornerWindow = Rectangle.Union(origBoundsInAdornerWindow, boundsInAdornerWindow); + b.Invalidate(boundsInAdornerWindow); + // PLEASE DONT CHANGE THIS ORDER !!! + if (parentDesigner != null && parentDesigner.EditManager != null) + { + parentDesigner.EditManager.ActivateEditor(ToolStripItem, clicked); + } + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + if (bodyGlyph != null) + { + selMgr.BodyGlyphAdorner.Glyphs.Remove(bodyGlyph); + } + } + else + { + ToolStripItem.AutoSize = AutoSize; + if (ToolStripItem is ToolStripDropDownItem) //We have no place to show this item... so Hide the DropDown + { + if (ToolStripItem is ToolStripDropDownItem ddItem) + { + ddItem.HideDropDown(); + } + // And select the parent... since we cannot show the current selection. + selSvc.SetSelectedComponents(new object[] { ImmediateParent }); + } + } + } + } + } + + // This method is called by the ToolStripDesigner to SetSelections to proper ToolStripItems after the parent ToolStripItem is committed. Consider this : the ToolStrip would cause the NEXT item on the TOPLEVEL to get selected... while on MenuStrip.. we would want the Child ToolStripItem in the DropDown to get selected after the TopLevel MenuStripItem is commited. + internal virtual bool SetSelection(bool enterKeyPressed) => false; + + internal override void ShowContextMenu(int x, int y) + { + ToolStripKeyboardHandlingService keySvc = (ToolStripKeyboardHandlingService)GetService(typeof(ToolStripKeyboardHandlingService)); + if (keySvc != null) + { + if (!keySvc.ContextMenuShownByKeyBoard) + { + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + Point newPoint = Point.Empty; + if (b != null) + { + newPoint = b.ScreenToAdornerWindow(new Point(x, y)); + } + Rectangle itemBounds = GetGlyphBounds(); + if (itemBounds.Contains(newPoint)) + { + DesignerContextMenu.Show(x, y); + } + } + else + { + keySvc.ContextMenuShownByKeyBoard = false; + DesignerContextMenu.Show(x, y); + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemGlyph.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemGlyph.cs new file mode 100644 index 00000000000..339791195f7 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripItemGlyph.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// The glyph we put over the items. Basically this sets the hit-testable area of the item itself. + /// + internal class ToolStripItemGlyph : ControlBodyGlyph + { + private readonly ToolStripItem _item; + private Rectangle _bounds; + private readonly ToolStripItemDesigner _itemDesigner; + + public ToolStripItemGlyph(ToolStripItem item, ToolStripItemDesigner itemDesigner, Rectangle bounds, System.Windows.Forms.Design.Behavior.Behavior b) : base(bounds, Cursors.Default, item, b) + { + _item = item; + _bounds = bounds; + _itemDesigner = itemDesigner; + } + + public ToolStripItem Item + { + get => _item; + } + + public override Rectangle Bounds + { + get => _bounds; + } + + public ToolStripItemDesigner ItemDesigner + { + get => _itemDesigner; + } + + /// + /// Abstract method that forces Glyph implementations to provide hit test logic. Given any point - if the Glyph has decided to be involved with that location, the Glyph will need to return a valid Cursor. Otherwise, returning null will cause the the BehaviorService to simply ignore it. + /// + public override Cursor GetHitTest(Point p) + { + if (_item.Visible && _bounds.Contains(p)) + { + return Cursors.Default; + } + return null; + } + + /// + /// Control host dont draw on Invalidation... + /// + public override void Paint(PaintEventArgs pe) + { + if (_item is ToolStripControlHost && _item.IsOnDropDown) + { + if (_item is System.Windows.Forms.ToolStripComboBox && VisualStyles.VisualStyleRenderer.IsSupported) + { + // When processing WM_PAINT and the OS has a theme enabled, the native ComboBox sends a WM_PAINT message to its parent when a theme is enabled in the OS forcing a repaint in the AdornerWindow generating an infinite WM_PAINT message processing loop. We guard against this here. + return; + } + _item.Invalidate(); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripKeyboardHandlingService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripKeyboardHandlingService.cs new file mode 100644 index 00000000000..e26e8879848 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripKeyboardHandlingService.cs @@ -0,0 +1,2131 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + internal class ToolStripKeyboardHandlingService + { + private ISelectionService _selectionService; + private IComponentChangeService _componentChangeSvc; + private IServiceProvider _provider; + private IMenuCommandService _menuCommandService; + private readonly IDesignerHost _designerHost; + //primary selection during shift operation is the LAST selected item which is different from selSvc.PrimarySelection, hence cache it + private object _shiftPrimary = null; + private bool _shiftPressed = false; + // our cache of currently selected DesignerToolStripControl Host.... + private object _currentSelection; + //is the templateNode in Insitu Mode? + private bool _templateNodeActive = false; + private ToolStripTemplateNode _activeTemplateNode = null; + //is the TemplateNode ContextMenu open. When the TemplateNode AddItems ContextMenu is opened we want to Disable all the Commands... And we enable them when the contextMenu closes... But if the menu closes by "enter Key" we get OnKeyDefault and hence go into InSitu Edit Mode.. to avoid this we have a new flag to IGNORE the first OnKeyDefault. + private bool _templateNodeContextMenuOpen = false; + // old commands + private ArrayList _oldCommands; + // our commands + private ArrayList _newCommands; + // need to add this separately since the VbDATA guys return us their paste command when the DataSource is copy pasted. + private MenuCommand _oldCommandPaste; + private MenuCommand _newCommandPaste; + private bool _commandsAdded = false; + private bool _copyInProgress = false; + private bool _cutOrDeleteInProgress = false; + private bool _contextMenuShownByKeyBoard = false; //We should know when the contextMenu is shown by KeyBoard shortcut. + private object _ownerItemAfterCut = null; // This value is set only of the ToolStripMenuItem is cut and now we need to reopen the dropDown which was closed in the previous CUT operation. + + /// + /// This creates a service for handling the keyboard navigation at desgin time. + /// + public ToolStripKeyboardHandlingService(IServiceProvider serviceProvider) + { + _provider = serviceProvider; + _selectionService = (ISelectionService)serviceProvider.GetService(typeof(ISelectionService)); + Debug.Assert(_selectionService != null, "ToolStripKeyboardHandlingService relies on the selection service, which is unavailable."); + if (_selectionService != null) + { + _selectionService.SelectionChanging += new EventHandler(OnSelectionChanging); + _selectionService.SelectionChanged += new EventHandler(OnSelectionChanged); + } + + _designerHost = (IDesignerHost)_provider.GetService(typeof(IDesignerHost)); + Debug.Assert(_designerHost != null, "ToolStripKeyboardHandlingService relies on the selection service, which is unavailable."); + if (_designerHost != null) + { + _designerHost.AddService(typeof(ToolStripKeyboardHandlingService), this); + } + _componentChangeSvc = (IComponentChangeService)_designerHost.GetService(typeof(IComponentChangeService)); + Debug.Assert(_componentChangeSvc != null, "ToolStripKeyboardHandlingService relies on the componentChange service, which is unavailable."); + if (_componentChangeSvc != null) + { + _componentChangeSvc.ComponentRemoved += new ComponentEventHandler(OnComponentRemoved); + } + } + + //Currently active TemplateNode + internal ToolStripTemplateNode ActiveTemplateNode + { + get => _activeTemplateNode; + set + { + _activeTemplateNode = value; + ResetActiveTemplateNodeSelectionState(); + } + } + + // This property is set on the controlDesigner and used in the ToolStripItemDesigner. There is no way of knowing whether the ContextMenu is show via-keyBoard or Click and we need to know this since we check if the Bounds are within the toolStripItem while showing the ContextMenu. + internal bool ContextMenuShownByKeyBoard + { + get => _contextMenuShownByKeyBoard; + set => _contextMenuShownByKeyBoard = value; + } + + // When Copy (Through Control + Drag) this boolean is set to true. Problem is that during copy the DesignerUtils creates new components and as a result the ToolStripMenuItemDesigner and ToolStripDesigners get the "ComponentAdding/ComponentAdded" events where they try to parent the components. We dont need to "parent" in case of control + drag. + internal bool CopyInProgress + { + get => _copyInProgress; + set + { + if (value != CopyInProgress) + { + _copyInProgress = value; + } + } + } + + + // We need to listen to MenuCommands.Delete since we are going to change the selection here instead of OnComponentRemoved The OnComponentRemoved gets called through various different places like Partial Reload, Full Reload and Undo-Redo transactions Changing the selection in "OnComponentRemoved" thus is expensive in terms of flicker and code that gets run causing PERF hit. + internal bool CutOrDeleteInProgress + { + get => _cutOrDeleteInProgress; + set + { + if (value != _cutOrDeleteInProgress) + { + _cutOrDeleteInProgress = value; + } + } + } + + /// + /// Retrieves the selection service, which tthis service uses while selecting the toolStrip Item. + /// + private IDesignerHost Host + { + get => _designerHost; + } + + /// + /// Retrieves the menu editor service, which we cache for speed. + /// + private IMenuCommandService MenuService + { + get + { + if (_menuCommandService == null) + { + if (_provider != null) + { + _menuCommandService = (IMenuCommandService)_provider.GetService(typeof(IMenuCommandService)); + } + } + return _menuCommandService; + } + } + + // When the TemplateNode gets selected ... we dont set in the SelectionService.SelectedComponents since we want to blank out the propertygrid ... so we keep the selected cache here. + internal object SelectedDesignerControl + { + get => _currentSelection; + set + { + if (value != SelectedDesignerControl) + { + if (SelectedDesignerControl is DesignerToolStripControlHost prevDesignerNode) + { + prevDesignerNode.RefreshSelectionGlyph(); + } + _currentSelection = value; + if (_currentSelection != null) + { + if (_currentSelection is DesignerToolStripControlHost curDesignerNode) + { + curDesignerNode.SelectControl(); + if (curDesignerNode.AccessibilityObject is ToolStripItem.ToolStripItemAccessibleObject acc) + { + acc.AddState(AccessibleStates.Selected | AccessibleStates.Focused); + ToolStrip owner = curDesignerNode.GetCurrentParent() as ToolStrip; + int focusIndex = 0; + if (owner != null) + { + focusIndex = owner.Items.IndexOf(curDesignerNode); + } + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.SelectionAdd, new HandleRef(owner, owner.Handle), NativeMethods.OBJID_CLIENT, focusIndex + 1); + UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.Focus, new HandleRef(owner, owner.Handle), NativeMethods.OBJID_CLIENT, focusIndex + 1); + } + } + } + } + } + } + + internal object OwnerItemAfterCut + { + get => _ownerItemAfterCut; + set => _ownerItemAfterCut = value; + } + + // When shift key is pressed we need to know where to start from .. this object keeps a track of that item. + internal object ShiftPrimaryItem + { + get => _shiftPrimary; + set => _shiftPrimary = value; + } + + /// + /// Retrieves the selection service, which tthis service uses while selecting the toolStrip Item. + /// + private ISelectionService SelectionService + { + get => _selectionService; + } + + // When the ToolStripTemplateNode becomes active, the ToolStripKeyBoardHandlingService shouldnt process any MenuCommands... + internal bool TemplateNodeActive + { + get => _templateNodeActive; + set + { + _templateNodeActive = value; + + //Disable all our Commands when TemplateNode is Active. Remove the new Commands + if (_newCommands != null) + { + foreach (MenuCommand newCommand in _newCommands) + { + newCommand.Enabled = !_templateNodeActive; + } + } + } + } + + // boolean which returns if the TemplateNode contextMenu is open. + internal bool TemplateNodeContextMenuOpen + { + get => _templateNodeContextMenuOpen; + set + { + _templateNodeContextMenuOpen = value; + //Disable all our Commands when templateNodeContextMenuOpen. Remove the new Commands + if (_newCommands != null) + { + foreach (MenuCommand newCommand in _newCommands) + { + newCommand.Enabled = !_templateNodeActive; + } + } + } + } + + // Adds our commands to the MenuCommandService. + public void AddCommands() + { + IMenuCommandService mcs = MenuService; + if (mcs != null & !_commandsAdded) + { + // Demand Create the oldCommands + if (_oldCommands == null) + { + PopulateOldCommands(); + } + //Remove the Old Commands + foreach (MenuCommand oldCommand in _oldCommands) + { + if (oldCommand != null) + { + mcs.RemoveCommand(oldCommand); + } + } + // DemandCreate the new Commands. + if (_newCommands == null) + { + PopulateNewCommands(); + } + // Add our Commands + foreach (MenuCommand newCommand in _newCommands) + { + if (newCommand != null && mcs.FindCommand(newCommand.CommandID) == null) + { + mcs.AddCommand(newCommand); + } + } + _commandsAdded = true; + } + } + + // private function to get Next toolStripItem based on direction. + private ToolStripItem GetNextItem(ToolStrip parent, ToolStripItem startItem, ArrowDirection direction) + { + if (parent.RightToLeft == RightToLeft.Yes && (direction == ArrowDirection.Left || direction == ArrowDirection.Right)) + { + if (direction == ArrowDirection.Right) + { + direction = ArrowDirection.Left; + } + else if (direction == ArrowDirection.Left) + { + direction = ArrowDirection.Right; + } + } + return parent.GetNextItem(startItem, direction); + } + + /// + /// This is the private helper function which gets the next control in the TabOrder.. + /// + private Control GetNextControlInTab(Control basectl, Control ctl, bool forward) + { + if (forward) + { + while (ctl != basectl) + { + int targetIndex = ctl.TabIndex; + bool hitCtl = false; + Control found = null; + Control p = ctl.Parent; + // Cycle through the controls in z-order looking for the one with the next highest tab index. Because there can be dups, we have to start with the existing tab index and remember to exclude the current control. + int parentControlCount = 0; + Control.ControlCollection parentControls = (Control.ControlCollection)p.Controls; + if (parentControls != null) + { + parentControlCount = parentControls.Count; + } + + for (int c = 0; c < parentControlCount; c++) + { + // The logic for this is a bit lengthy, so I have broken it into separate caluses: We are not interested in ourself. + if (parentControls[c] != ctl) + { + // We are interested in controls with >= tab indexes to ctl. We must include those controls with equal indexes to account for duplicate indexes. + if (parentControls[c].TabIndex >= targetIndex) + { + // Check to see if this control replaces the "best match" we've already found. + if (found == null || found.TabIndex > parentControls[c].TabIndex) + { + // Finally, check to make sure that if this tab index is the same as ctl, that we've already encountered ctl in the z-order. If it isn't the same, than we're more than happy with it. + if (parentControls[c].Site != null && parentControls[c].TabIndex != targetIndex || hitCtl) + { + found = parentControls[c]; + } + } + } + } + else + { + // We track when we have encountered "ctl". We never want to select ctl again, but we want to know when we've seen it in case we find another control with the same tab index. + hitCtl = true; + } + } + + if (found != null) + { + return found; + } + + ctl = ctl.Parent; + } + } + else + { + if (ctl != basectl) + { + int targetIndex = ctl.TabIndex; + bool hitCtl = false; + Control found = null; + Control p = ctl.Parent; + // Cycle through the controls in reverse z-order looking for the next lowest tab index. We must start with the same tab index as ctl, because there can be dups. + int parentControlCount = 0; + Control.ControlCollection parentControls = (Control.ControlCollection)p.Controls; + if (parentControls != null) + { + parentControlCount = parentControls.Count; + } + + for (int c = parentControlCount - 1; c >= 0; c--) + { + // The logic for this is a bit lengthy, so I have broken it into separate caluses: We are not interested in ourself. + if (parentControls[c] != ctl) + { + // We are interested in controls with <= tab indexes to ctl. We must include those controls with equal indexes to account for duplicate indexes. + if (parentControls[c].TabIndex <= targetIndex) + { + // Check to see if this control replaces the "best match" we've already found. + if (found == null || found.TabIndex < parentControls[c].TabIndex) + { + // Finally, check to make sure that if this tab index is the same as ctl, that we've already encountered ctl in the z-order. If it isn't the same, than we're more than happy with it. + if (parentControls[c].TabIndex != targetIndex || hitCtl) + { + found = parentControls[c]; + } + } + } + } + else + { + // We track when we have encountered "ctl". We never want to select ctl again, but we want to know when we've seen it in case we find another control with the same tab index. + hitCtl = true; + } + } + + // If we were unable to find a control we should return the control's parent. However, if that parent is us, return NULL. + if (found != null) + { + ctl = found; + } + else + { + if (p == basectl) + { + return null; + } + else + { + return p; + } + } + } + } + return ctl == basectl ? null : ctl; + } + + // this will invoke the OLD command from our command handler. + private void InvokeOldCommand(object sender) + { + MenuCommand command = sender as MenuCommand; + foreach (MenuCommand oldCommand in _oldCommands) + { + if (oldCommand != null && oldCommand.CommandID == command.CommandID) + { + oldCommand.Invoke(); + break; + } + } + } + + private void OnComponentRemoved(object sender, ComponentEventArgs e) + { + bool toolStripPresent = false; + ComponentCollection comps = _designerHost.Container.Components; + foreach (IComponent comp in comps) + { + if (comp is ToolStrip) + { + toolStripPresent = true; + break; + } + } + if (!toolStripPresent) + { + ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)_provider.GetService(typeof(ToolStripKeyboardHandlingService)); + if (keyboardHandlingService != null) + { + //since we are going away .. restore the old commands. + keyboardHandlingService.RestoreCommands(); + // clean up. + keyboardHandlingService.RemoveCommands(); + _designerHost.RemoveService(typeof(ToolStripKeyboardHandlingService)); + } + } + } + + public bool OnContextMenu(int x, int y) + { + if (TemplateNodeActive) + { + return true; + } + // commandsAdded means that either toolstrip, toolSripItem or templatenode is selected. + if (_commandsAdded && x == -1 && y == -1) + { + ContextMenuShownByKeyBoard = true; + Point p = Cursor.Position; + x = p.X; + y = p.Y; + } + + // This has to be done since ToolStripTemplateNode is unsited component that supports its own contextMenu. When the Selection is null, templateNode can be selected. So this block of code here checks if ToolStripKeyBoardHandlingService is present if so, tries to check if the templatenode is selected if so, then gets the templateNode and shows the ContextMenu. + if (!(SelectionService.PrimarySelection is Component selComp)) + { + if (SelectedDesignerControl is DesignerToolStripControlHost controlHost) + { + if (controlHost.Control is ToolStripTemplateNode.TransparentToolStrip tool) + { + ToolStripTemplateNode node = tool.TemplateNode; + if (node != null) + { + node.ShowContextMenu(new Point(x, y)); + return true; + } + } + } + } + return false; + } + + // Handler for Copy Command + private void OnCommandCopy(object sender, EventArgs e) + { + bool cutCommand = false; + try + { + //If the Command is CUT and the new Selection is DesignerToolStripControlHost then select it and open its parentDropDown. + if (sender is MenuCommand com && com.CommandID == StandardCommands.Cut) + { + cutCommand = true; + CutOrDeleteInProgress = true; + } + + // INVOKE THE OldCommand + InvokeOldCommand(sender); + // END + + if (cutCommand) + { + if (OwnerItemAfterCut is ToolStripDropDownItem parentItem) + { + ToolStripDropDown dropDown = parentItem.DropDown; + if (Host.GetDesigner(dropDown) is ToolStripDropDownDesigner dropDownDesigner) + { + SelectionService.SetSelectedComponents(new object[] { dropDownDesigner.Component }, SelectionTypes.Replace); + } + else if (parentItem != null && !(parentItem.DropDown.Visible)) + { + if (Host.GetDesigner(parentItem) is ToolStripMenuItemDesigner designer) + { + designer.SetSelection(true); + if (SelectedDesignerControl is DesignerToolStripControlHost curDesignerNode) + { + curDesignerNode.SelectControl(); + } + } + } + } + } + + // this is done So that the Data Behavior doesnt mess up with the copy command during addition of the ToolStrip.. + IMenuCommandService mcs = MenuService; + if (mcs != null) + { + if (_newCommandPaste == null) + { + _oldCommandPaste = mcs.FindCommand(StandardCommands.Paste); + if (_oldCommandPaste != null) + { + mcs.RemoveCommand(_oldCommandPaste); + } + _newCommandPaste = new MenuCommand(new EventHandler(OnCommandPaste), StandardCommands.Paste); + if (_newCommandPaste != null && mcs.FindCommand(_newCommandPaste.CommandID) == null) + { + mcs.AddCommand(_newCommandPaste); + } + } + } + } + finally + { + cutCommand = false; + CutOrDeleteInProgress = false; + } + } + + private void OnCommandDelete(object sender, EventArgs e) + { + try + { + CutOrDeleteInProgress = true; + // INVOKE THE OldCommand + InvokeOldCommand(sender); + // END + } + finally + { + CutOrDeleteInProgress = false; + } + + } + + // Handler for Paste Command + private void OnCommandPaste(object sender, EventArgs e) + { + //IF TemplateNode is Active DO NOT Support Paste. This is what MainMenu did + // We used to incorrectly paste the item to the parent's collection; so inorder to make a simple fix I am being consistent with MainMenu + if (TemplateNodeActive) + { + return; + } + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc != null && host != null) + { + if (!(selSvc.PrimarySelection is IComponent comp)) + { + comp = (IComponent)SelectedDesignerControl; + } + ToolStripItem item = comp as ToolStripItem; + ToolStrip parent = null; + //Case 1: If SelectedObj is ToolStripItem select all items in its immediate parent. + if (item != null) + { + parent = item.GetCurrentParent() as ToolStrip; + } + if (parent != null) + { + parent.SuspendLayout(); + } + + // INVOKE THE OldCommand + if (_oldCommandPaste != null) + { + _oldCommandPaste.Invoke(); + } + + if (parent != null) + { + parent.ResumeLayout(); + // Since the Glyphs dont get correct bounds as the ToolStrip Layout is suspended .. force Glyph Updates. + BehaviorService behaviorService = (BehaviorService)_provider.GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + behaviorService.SyncSelection(); + } + + // For ContextMenuStrip; since its not a control .. we dont get called on GetGlyphs directly through the BehaviorService So we need this internal call to push the glyphs on the SelectionManager + if (host.GetDesigner(item) is ToolStripItemDesigner designer) + { + ToolStripDropDown dropDown = designer.GetFirstDropDown(item); + if (dropDown != null && !dropDown.IsAutoGenerated) + { + if (host.GetDesigner(dropDown) is ToolStripDropDownDesigner dropDownDesigner) + { + dropDownDesigner.AddSelectionGlyphs(); + } + } + } + + // For Items on DropDown .. we have to manage Glyphs... + if (parent is ToolStripDropDown parentDropDown && parentDropDown.Visible) + { + if (parentDropDown.OwnerItem is ToolStripDropDownItem ownerItem) + { + if (host.GetDesigner(ownerItem) is ToolStripMenuItemDesigner itemDesigner) + { + itemDesigner.ResetGlyphs(ownerItem); + } + } + } + + // Get the Selection and ShowDropDown only on ToolStripDropDownItems to show dropDowns after paste operation. + if (selSvc.PrimarySelection is ToolStripDropDownItem dropDownItem && dropDownItem.DropDown.Visible) + { + //Hide the DropDown + dropDownItem.HideDropDown(); + if (host.GetDesigner(dropDownItem) is ToolStripMenuItemDesigner selectedItemDesigner) + { + selectedItemDesigner.InitializeDropDown(); + selectedItemDesigner.InitializeBodyGlyphsForItems(false, dropDownItem); + selectedItemDesigner.InitializeBodyGlyphsForItems(true, dropDownItem); + } + } + } + } + } + + // Handler for Home Command + private void OnCommandHome(object sender, EventArgs e) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (!(selSvc.PrimarySelection is ToolStripItem item)) + { + item = SelectedDesignerControl as ToolStripItem; + } + // Process Keys only if we are a ToolStripItem and the TemplateNode is not in Insitu Mode. + if (item != null) + { + //only select the last item only if there is an Item added in addition to the TemplateNode... + ToolStrip parent = item.GetCurrentParent(); + int count = parent.Items.Count; + if (count >= 3) //3 //3 for the total number of items .. two ToolStripItems + 1 TemplateNode. + { + bool shiftPressed = (Control.ModifierKeys & Keys.Shift) > 0; + if (shiftPressed) + { + //Select all the items between current "item" till the Last item + int startIndexOfSelection = 0; + int endIndexOfSelection = Math.Max(0, parent.Items.IndexOf(item)); + int countofItemsSelected = (endIndexOfSelection - startIndexOfSelection) + 1; + + object[] totalObjects = new object[countofItemsSelected]; + int j = 0; + for (int i = startIndexOfSelection; i <= endIndexOfSelection; i++) + { + totalObjects[j++] = parent.Items[i]; + } + selSvc.SetSelectedComponents(totalObjects, SelectionTypes.Replace); + } + else + { + SetSelection(parent.Items[0]); + } + } + } + } + } + + // Handler for End Command + private void OnCommandEnd(object sender, EventArgs e) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (!(selSvc.PrimarySelection is ToolStripItem item)) + { + item = SelectedDesignerControl as ToolStripItem; + } + // Process Keys only if we are a ToolStripItem and the TemplateNode is not in Insitu Mode. + if (item != null) + { + + //only select the last item only if there is an Item added in addition to the TemplateNode... + ToolStrip parent = item.GetCurrentParent(); + int count = parent.Items.Count; + if (count >= 3) //3 //3 for the total number of items .. two ToolStripItems + 1 TemplateNode. + { + bool shiftPressed = (Control.ModifierKeys & Keys.Shift) > 0; + if (shiftPressed) + { + //Select all the items between current "item" till the Last item + int startIndexOfSelection = parent.Items.IndexOf(item); + int endIndexOfSelection = Math.Max(startIndexOfSelection, count - 2); + int countofItemsSelected = (endIndexOfSelection - startIndexOfSelection) + 1; + + object[] totalObjects = new object[countofItemsSelected]; + int j = 0; + for (int i = startIndexOfSelection; i <= endIndexOfSelection; i++) + { + totalObjects[j++] = parent.Items[i]; + } + selSvc.SetSelectedComponents(totalObjects, SelectionTypes.Replace); + } + else + { + SetSelection(parent.Items[count - 2]); + } + } + } + } + } + + // Handler for SelectALL Command + private void OnCommandSelectAll(object sender, EventArgs e) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + object selectedObj = selSvc.PrimarySelection; + //Case 1: If SelectedObj is ToolStripItem select all items in its immediate parent. + if (selectedObj is ToolStripItem) + { + ToolStripItem selectedItem = selectedObj as ToolStripItem; + ToolStrip parent = selectedItem.GetCurrentParent() as ToolStrip; + if (parent is ToolStripOverflow) + { + parent = selectedItem.Owner; + } + SelectItems(parent); + BehaviorService behaviorService = (BehaviorService)_provider.GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + behaviorService.Invalidate(); + } + return; + } + // Case 2: if SelectedObj is ToolStrip ... then select all the item contained in it. + if (selectedObj is ToolStrip) + { + ToolStrip parent = selectedObj as ToolStrip; + SelectItems(parent); + return; + } + //Case 3: if selectedOj is ToolStripPanel ... select the ToolStrips within the ToolStripPanel... + if (selectedObj is ToolStripPanel) + { + ToolStripPanel parentToolStripPanel = selectedObj as ToolStripPanel; + selSvc.SetSelectedComponents((ICollection)parentToolStripPanel.Controls, SelectionTypes.Replace); + return; + } + } + } + + // this will get called for "Chrome Panel" command. We have to show the ItemList if The TemplateNode is selected. + private void OnKeyShowDesignerActions(object sender, EventArgs e) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (selSvc.PrimarySelection == null) + { + if (SelectedDesignerControl is DesignerToolStripControlHost controlHost) + { + if (controlHost.Control is ToolStripTemplateNode.TransparentToolStrip tool) + { + ToolStripTemplateNode node = tool.TemplateNode; + if (node != null) + { + node.ShowDropDownMenu(); + return; + } + } + } + } + } + // INVOKE THE OldCommand + InvokeOldCommand(sender); + // END + } + + // Command handler for enter key. + private void OnKeyDefault(object sender, EventArgs e) + { + // Return if the contextMenu was open during this KeyDefault... + if (_templateNodeContextMenuOpen) + { + _templateNodeContextMenuOpen = false; + return; + } + + // Return key. Handle it like a double-click on the primary selection + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc != null) + { + if (!(selSvc.PrimarySelection is IComponent pri)) + { + if (SelectedDesignerControl is DesignerToolStripControlHost typeHereNode) + { + if (host != null) + { + if (typeHereNode.IsOnDropDown && !typeHereNode.IsOnOverflow) + { + ToolStripDropDownItem ownerItem = (ToolStripDropDownItem)((ToolStripDropDown)(typeHereNode.Owner)).OwnerItem; + if (host.GetDesigner(ownerItem) is ToolStripMenuItemDesigner itemDesigner) + { + if (!itemDesigner.IsEditorActive) + { + itemDesigner.EditTemplateNode(true); + if (ActiveTemplateNode != null) + { + ActiveTemplateNode.ignoreFirstKeyUp = true; + } + } + } + } + else + { + if (host.GetDesigner(typeHereNode.Owner) is ToolStripDesigner tooldesigner) + { + tooldesigner.ShowEditNode(true); + if (ActiveTemplateNode != null) + { + ActiveTemplateNode.ignoreFirstKeyUp = true; + } + } + } + } + } + } + else + { + if (host != null) + { + IDesigner designer = host.GetDesigner(pri); + if (designer is ToolStripMenuItemDesigner tooldesigner) + { + if (tooldesigner.IsEditorActive) + { + return; + } + else + { + tooldesigner.ShowEditNode(false); + if (ActiveTemplateNode != null) + { + ActiveTemplateNode.ignoreFirstKeyUp = true; + } + } + } + else if (designer != null) + { + // INVOKE THE OldCommand + InvokeOldCommand(sender); + } + } + } + } + } + + /// + /// This is a function which gets called when the item goes into InSitu Edit mode. + /// + private void OnKeyEdit(object sender, EventArgs e) + { + // This method allows the ToolStrip Template Node into the EditMode. + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc != null) + { + if (!(selSvc.PrimarySelection is IComponent comp)) + { + comp = (IComponent)SelectedDesignerControl; + } + + if (comp is ToolStripItem) + { + if (host != null) + { + CommandID cmd = ((MenuCommand)sender).CommandID; + if (cmd.Equals(MenuCommands.EditLabel)) + { + if (comp is ToolStripMenuItem) + { + if (host.GetDesigner(comp) is ToolStripMenuItemDesigner designer) + { + if (!designer.IsEditorActive) + { + designer.ShowEditNode(false); + } + } + } + if (comp is DesignerToolStripControlHost) + { + DesignerToolStripControlHost typeHereNode = comp as DesignerToolStripControlHost; + if (typeHereNode.IsOnDropDown) + { + ToolStripDropDownItem ownerItem = (ToolStripDropDownItem)((ToolStripDropDown)(typeHereNode.Owner)).OwnerItem; + if (host.GetDesigner(ownerItem) is ToolStripMenuItemDesigner itemDesigner) + { + if (!itemDesigner.IsEditorActive) + { + itemDesigner.EditTemplateNode(false); + } + } + } + else + { + if (host.GetDesigner(typeHereNode.Owner) is ToolStripDesigner tooldesigner) + { + tooldesigner.ShowEditNode(false); + } + } + } + } + } + } + } + } + + /// + /// This is a function which gets called when the arrow keys are used at design time on ToolStrips. + /// + private void OnKeyMove(object sender, EventArgs e) + { + // Arrow keys. Begin a drag if the selection isn't locked. + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + MenuCommand cmd = (MenuCommand)sender; + if (cmd.CommandID.Equals(MenuCommands.KeySizeWidthIncrease) || cmd.CommandID.Equals(MenuCommands.KeySizeWidthDecrease) || + cmd.CommandID.Equals(MenuCommands.KeySizeHeightDecrease) || cmd.CommandID.Equals(MenuCommands.KeySizeHeightIncrease)) + { + _shiftPressed = true; + } + else + { + _shiftPressed = false; + } + + // check for ContextMenu.. + if (selSvc.PrimarySelection is ContextMenuStrip contextStrip) + { + if (cmd.CommandID.Equals(MenuCommands.KeyMoveDown)) + { + ProcessUpDown(true); + } + return; + } + + if (!(selSvc.PrimarySelection is ToolStripItem item)) + { + item = SelectedDesignerControl as ToolStripItem; + } + + // Process Keys only if we are a ToolStripItem and the TemplateNode is not in Insitu Mode. + if (item != null) + { + if (cmd.CommandID.Equals(MenuCommands.KeyMoveRight) || cmd.CommandID.Equals(MenuCommands.KeyNudgeRight) || cmd.CommandID.Equals(MenuCommands.KeySizeWidthIncrease)) + { + if (!ProcessRightLeft(true)) + { + RotateTab(false); + return; + } + } + if (cmd.CommandID.Equals(MenuCommands.KeyMoveLeft) || cmd.CommandID.Equals(MenuCommands.KeyNudgeLeft) || cmd.CommandID.Equals(MenuCommands.KeySizeWidthDecrease)) + { + if (!ProcessRightLeft(false)) + { + RotateTab(true); + return; + } + } + if (cmd.CommandID.Equals(MenuCommands.KeyMoveDown) || cmd.CommandID.Equals(MenuCommands.KeyNudgeDown) || cmd.CommandID.Equals(MenuCommands.KeySizeHeightIncrease)) + { + ProcessUpDown(true); + return; + } + if (cmd.CommandID.Equals(MenuCommands.KeyMoveUp) || cmd.CommandID.Equals(MenuCommands.KeyNudgeUp) || cmd.CommandID.Equals(MenuCommands.KeySizeHeightDecrease)) + { + ProcessUpDown(false); + return; + } + } + else + { + // INVOKE THE OldCommand + InvokeOldCommand(sender); + } + } + } + + /// + /// This is a function which gets called when Cancel is pressed when we are on ToolStripItem. + /// + private void OnKeyCancel(object sender, EventArgs e) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (!(selSvc.PrimarySelection is ToolStripItem item)) + { + item = SelectedDesignerControl as ToolStripItem; + } + // Process Keys only if we are a ToolStripItem and the TemplateNode is not in Insitu Mode. + if (item != null) + { + MenuCommand cmd = (MenuCommand)sender; + bool reverse = (cmd.CommandID.Equals(MenuCommands.KeyReverseCancel)); + RotateParent(reverse); + return; + } + else + { + // Check if the ToolStripDropDown (which is designable) is currently selected. If so this should select the "RootComponent" + if (selSvc.PrimarySelection is ToolStripDropDown dropDown && dropDown.Site != null) + { + selSvc.SetSelectedComponents(new object[] { Host.RootComponent }, SelectionTypes.Replace); + } + else + { + // INVOKE THE OldCommand + InvokeOldCommand(sender); + } + } + } + } + + /// + /// This function allows the CommandSet to select the right item when the Tab and Arrow keys are used. + /// + private void OnKeySelect(object sender, EventArgs e) + { + MenuCommand cmd = (MenuCommand)sender; + bool reverse = (cmd.CommandID.Equals(MenuCommands.KeySelectPrevious)); + ProcessKeySelect(reverse, cmd); + } + + /// + /// Called when the current selection changes. Here we determine what commands can and can't be enabled. + /// + private void OnSelectionChanging(object sender, EventArgs e) + { + if (!(SelectionService.PrimarySelection is Component primarySelection)) + { + primarySelection = SelectedDesignerControl as ToolStripItem; + } + + ToolStrip tool = primarySelection as ToolStrip; + if (tool != null) + { + InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(tool)[typeof(InheritanceAttribute)]; + if (ia != null && (ia.InheritanceLevel == InheritanceLevel.Inherited || ia.InheritanceLevel == InheritanceLevel.InheritedReadOnly)) + { + return; + } + } + + if (tool == null && !(primarySelection is ToolStripItem)) + { + RestoreCommands(); + // Reset the cached item... + SelectedDesignerControl = null; + } + } + + /// + /// Called when the current selection changes. Here we determine what commands can and can't be enabled. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + if (!(SelectionService.PrimarySelection is Component primarySelection)) + { + primarySelection = SelectedDesignerControl as ToolStripItem; + } + ToolStrip tool = primarySelection as ToolStrip; + if (tool != null) + { + InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(tool)[typeof(InheritanceAttribute)]; + if (ia != null && (ia.InheritanceLevel == InheritanceLevel.Inherited || ia.InheritanceLevel == InheritanceLevel.InheritedReadOnly)) + { + return; + } + } + + if (tool != null || primarySelection is ToolStripItem) + { + // Remove the Panel if any + BehaviorService behaviorService = (BehaviorService)_provider.GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + DesignerActionUI designerUI = behaviorService.DesignerActionUI; + if (designerUI != null) + { + designerUI.HideDesignerActionPanel(); + } + } + AddCommands(); + } + } + + // helper function to select the next item. + public void ProcessKeySelect(bool reverse, MenuCommand cmd) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + if (!(selSvc.PrimarySelection is ToolStripItem item)) + { + item = SelectedDesignerControl as ToolStripItem; + } + // Process Keys only if we are a ToolStripItem and the TemplateNode is not in Insitu Mode. + if (item != null) + { + if (!ProcessRightLeft(!reverse)) + { + RotateTab(reverse); + return; + } + return; + } + else if (item == null && selSvc.PrimarySelection is ToolStrip) + { + RotateTab(reverse); + } + } + } + + /// + /// This is the private helper function which is used to select the toolStripItem in the 'right' direction. + /// + private bool ProcessRightLeft(bool right) + { + Control ctl; + object targetSelection = null; + object currentSelection; + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc == null || host == null || !(host.RootComponent is Control)) + { + return false; + } + + currentSelection = selSvc.PrimarySelection; + if (_shiftPressed && ShiftPrimaryItem != null) + { + currentSelection = ShiftPrimaryItem; + } + if (currentSelection == null) + { + currentSelection = SelectedDesignerControl; + } + + ctl = currentSelection as Control; + if (targetSelection == null && ctl == null) + { + ToolStripItem toolStripItem = selSvc.PrimarySelection as ToolStripItem; + if (_shiftPressed && ShiftPrimaryItem != null) + { + toolStripItem = ShiftPrimaryItem as ToolStripItem; + } + if (toolStripItem == null) + { + toolStripItem = SelectedDesignerControl as ToolStripItem; + } + if (toolStripItem is DesignerToolStripControlHost && toolStripItem.GetCurrentParent() is ToolStripDropDown parent) + { + if (parent != null) + { + if (right) + { + //no where to go .. since we are on DesignerToolStripControlHost for DropDown. + } + else + { + if (parent is ToolStripOverflow) + { + targetSelection = GetNextItem(parent, toolStripItem, ArrowDirection.Left); + } + else + { + targetSelection = parent.OwnerItem; + } + } + } + if (targetSelection != null) + { + SetSelection(targetSelection); + return true; + } + } + else + { + ToolStripItem item = selSvc.PrimarySelection as ToolStripItem; + if (_shiftPressed && ShiftPrimaryItem != null) + { + item = ShiftPrimaryItem as ToolStripDropDownItem; + } + if (item == null) + { + item = SelectedDesignerControl as ToolStripDropDownItem; + } + if (item != null && item.IsOnDropDown) + { + bool menusCascadeRight = SystemInformation.RightAlignedMenus; + if ((menusCascadeRight && right) || (!menusCascadeRight && right)) + { + if (item is ToolStripDropDownItem dropDownItem) + { + targetSelection = GetNextItem(dropDownItem.DropDown, null, ArrowDirection.Right); + if (targetSelection != null) + { + SetSelection(targetSelection); + //Open the DropDown after the Selection is Completed. + if (!(dropDownItem.DropDown.Visible)) + { + if (host.GetDesigner(dropDownItem) is ToolStripMenuItemDesigner designer) + { + designer.InitializeDropDown(); + + } + } + return true; + } + } + } + if (!right && !menusCascadeRight) + { + ToolStripItem owner = ((ToolStripDropDown)item.Owner).OwnerItem; + if (!owner.IsOnDropDown) + { + ToolStrip mainTool = owner.GetCurrentParent(); + targetSelection = GetNextItem(mainTool, owner, ArrowDirection.Left); + + } + else + { + targetSelection = owner; + } + if (targetSelection != null) + { + SetSelection(targetSelection); + return true; + } + } + } + } + } + return false; + } + + + /// + /// This is the private helper function which is used to select the toolStripItem in the 'down' direction. + /// + public void ProcessUpDown(bool down) + { + Control ctl; + object targetSelection = null; + object currentSelection; + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc == null || host == null || !(host.RootComponent is Control)) + { + return; + } + + currentSelection = selSvc.PrimarySelection; + if (_shiftPressed && ShiftPrimaryItem != null) + { + currentSelection = ShiftPrimaryItem; + } + + //Check for ContextMenuStrip first... + if (currentSelection is ContextMenuStrip contextMenu) + { + if (down) + { + targetSelection = GetNextItem(contextMenu, null, ArrowDirection.Down); + SetSelection(targetSelection); + } + return; + } + + if (currentSelection == null) + { + currentSelection = SelectedDesignerControl; + } + ctl = currentSelection as Control; + + if (targetSelection == null && ctl == null) + { + ToolStripItem item = selSvc.PrimarySelection as ToolStripItem; + if (_shiftPressed && ShiftPrimaryItem != null) + { + item = ShiftPrimaryItem as ToolStripItem; + } + if (item == null) + { + item = SelectedDesignerControl as ToolStripItem; + } + ToolStripDropDown parentToMoveOn = null; + if (item != null) + { + if (item is DesignerToolStripControlHost) + { + // so now if Down Arrow is pressed .. open the dropDown.... + if (down) + { + if (SelectedDesignerControl is DesignerToolStripControlHost controlHost) + { + if (controlHost.Control is ToolStripTemplateNode.TransparentToolStrip tool) + { + ToolStripTemplateNode node = tool.TemplateNode; + if (node != null) + { + node.ShowDropDownMenu(); + return; + } + } + } + } + else + { + parentToMoveOn = item.GetCurrentParent() as ToolStripDropDown; + } + } + else + { + ToolStripDropDownItem dropDownItem = item as ToolStripDropDownItem; + if (dropDownItem != null && !dropDownItem.IsOnDropDown) + { + parentToMoveOn = dropDownItem.DropDown; + item = null; + } + else if (dropDownItem != null) + { + parentToMoveOn = ((dropDownItem.Placement == ToolStripItemPlacement.Overflow) ? dropDownItem.Owner.OverflowButton.DropDown : dropDownItem.Owner) as ToolStripDropDown; + item = dropDownItem; + } + if (dropDownItem == null) + { + parentToMoveOn = item.GetCurrentParent() as ToolStripDropDown; + } + } + + if (parentToMoveOn != null) //This will be null for NON dropDownItems... + { + if (down) + { + targetSelection = GetNextItem(parentToMoveOn, item, ArrowDirection.Down); + //lets check the index to know if we have wrapped around... only on NON ContextMenuStrip, ToolStripDropDown (added from toolbox) + if (parentToMoveOn.OwnerItem != null) // this can be null for overflow.... + { + if (!(parentToMoveOn.OwnerItem.IsOnDropDown) && (parentToMoveOn.OwnerItem.Owner != null && parentToMoveOn.OwnerItem.Owner.Site != null)) + { + if (targetSelection is ToolStripItem newSelection) + { + // We are wrapping around on the FirstDropDown select OwnerItem... + if (parentToMoveOn.Items.IndexOf(newSelection) != -1 && parentToMoveOn.Items.IndexOf(newSelection) <= parentToMoveOn.Items.IndexOf(item)) + { + targetSelection = parentToMoveOn.OwnerItem; + } + } + } + } + + if (_shiftPressed && SelectionService.GetComponentSelected(targetSelection)) + { + SelectionService.SetSelectedComponents(new object[] { ShiftPrimaryItem, targetSelection }, SelectionTypes.Remove); + } + } + else + { + // We dont want to WRAP around for items on toolStrip Overflow, if the currentSelection is the topMost item on the Overflow, but select the one on the PARENT toolStrip. + if (parentToMoveOn is ToolStripOverflow) + { + ToolStripItem firstItem = GetNextItem(parentToMoveOn, null, ArrowDirection.Down); + if (item == firstItem) + { + if (item.Owner is ToolStrip owner) + { + targetSelection = GetNextItem(owner, ((ToolStripDropDown)parentToMoveOn).OwnerItem, ArrowDirection.Left); + } + } + else + { + targetSelection = GetNextItem(parentToMoveOn, item, ArrowDirection.Up); + } + } + else + { + targetSelection = GetNextItem(parentToMoveOn, item, ArrowDirection.Up); + } + + //lets check the index to know if we have wrapped around... + if (parentToMoveOn.OwnerItem != null) // this can be null for overflow.... + { + if (!(parentToMoveOn.OwnerItem.IsOnDropDown) && (parentToMoveOn.OwnerItem.Owner != null && parentToMoveOn.OwnerItem.Owner.Site != null)) + { + if (targetSelection is ToolStripItem newSelection && item != null) + { + // We are wrapping around on the FirstDropDown select OwnerItem... + if (parentToMoveOn.Items.IndexOf(newSelection) != -1 && parentToMoveOn.Items.IndexOf(newSelection) >= parentToMoveOn.Items.IndexOf(item)) + { + targetSelection = parentToMoveOn.OwnerItem; + } + } + } + } + + if (_shiftPressed && SelectionService.GetComponentSelected(targetSelection)) + { + SelectionService.SetSelectedComponents(new object[] { ShiftPrimaryItem, targetSelection }, SelectionTypes.Remove); + } + } + if (targetSelection != null && targetSelection != item) + { + SetSelection(targetSelection); + } + } + } + } + } + + // caches the old commands from the menuCommand service. + private void PopulateOldCommands() + { + if (_oldCommands == null) + { + _oldCommands = new ArrayList(); + } + IMenuCommandService mcs = MenuService; + if (mcs != null) + { + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeySelectNext)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeySelectPrevious)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyDefaultAction)); + + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyMoveUp)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyMoveDown)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyMoveLeft)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyMoveRight)); + + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyNudgeUp)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyNudgeDown)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyNudgeLeft)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyNudgeRight)); + + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeySizeWidthIncrease)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeySizeHeightIncrease)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeySizeWidthDecrease)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeySizeHeightDecrease)); + + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyCancel)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyReverseCancel)); + _oldCommands.Add(mcs.FindCommand(StandardCommands.Copy)); + _oldCommands.Add(mcs.FindCommand(StandardCommands.SelectAll)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.KeyInvokeSmartTag)); + + _oldCommands.Add(mcs.FindCommand(StandardCommands.Cut)); + _oldCommands.Add(mcs.FindCommand(MenuCommands.Delete)); + } + } + + // pupulates a list of our custom commands to be added to menu command service. + private void PopulateNewCommands() + { + if (_newCommands == null) + { + _newCommands = new ArrayList(); + } + + _newCommands.Add(new MenuCommand(new EventHandler(OnKeySelect), MenuCommands.KeySelectNext)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeySelect), MenuCommands.KeySelectPrevious)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyDefault), MenuCommands.KeyDefaultAction)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyEdit), MenuCommands.EditLabel)); + + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyMoveUp)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyMoveDown)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyMoveLeft)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyMoveRight)); + + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyNudgeUp)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyNudgeDown)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyNudgeLeft)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeyNudgeRight)); + + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeySizeWidthIncrease)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeySizeHeightIncrease)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeySizeWidthDecrease)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyMove), MenuCommands.KeySizeHeightDecrease)); + + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyCancel), MenuCommands.KeyCancel)); + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyCancel), MenuCommands.KeyReverseCancel)); + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandCopy), StandardCommands.Copy)); + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandSelectAll), StandardCommands.SelectAll)); + + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandHome), MenuCommands.KeyHome)); + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandEnd), MenuCommands.KeyEnd)); + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandHome), MenuCommands.KeyShiftHome)); + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandEnd), MenuCommands.KeyShiftEnd)); + + //Command for opening the DropDown for templatenode. + _newCommands.Add(new MenuCommand(new EventHandler(OnKeyShowDesignerActions), MenuCommands.KeyInvokeSmartTag)); + + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandCopy), StandardCommands.Cut)); + _newCommands.Add(new MenuCommand(new EventHandler(OnCommandDelete), MenuCommands.Delete)); + } + + // restores the old commands back into the menu command service. + public void RestoreCommands() + { + IMenuCommandService mcs = MenuService; + if (mcs != null & _commandsAdded) + { + //Remove the new Commands + if (_newCommands != null) + { + foreach (MenuCommand newCommand in _newCommands) + { + mcs.RemoveCommand(newCommand); + } + } + // Add old Commands + if (_oldCommands != null) + { + foreach (MenuCommand oldCommand in _oldCommands) + { + if (oldCommand != null && mcs.FindCommand(oldCommand.CommandID) == null) + { + mcs.AddCommand(oldCommand); + } + } + } + + if (_newCommandPaste != null) + { + mcs.RemoveCommand(_newCommandPaste); + _newCommandPaste = null; + } + + if (_oldCommandPaste != null && mcs.FindCommand(_oldCommandPaste.CommandID) == null) + { + mcs.AddCommand(_oldCommandPaste); + _oldCommandPaste = null; + } + _commandsAdded = false; + } + } + + internal void ResetActiveTemplateNodeSelectionState() + { + if (SelectedDesignerControl != null) + { + if (SelectedDesignerControl is DesignerToolStripControlHost curDesignerNode) + { + curDesignerNode.RefreshSelectionGlyph(); + } + } + } + + /// + /// Disposes of this object, removing all commands from the menu service. + /// + public void RemoveCommands() + { + IMenuCommandService mcs = MenuService; + if (mcs != null && _commandsAdded) + { + //Remove our Commands... + if (_newCommands != null) + { + foreach (MenuCommand newCommand in _newCommands) + { + mcs.RemoveCommand(newCommand); + } + } + } + if (_newCommandPaste != null) + { + mcs.RemoveCommand(_newCommandPaste); + _newCommandPaste = null; + } + if (_oldCommandPaste != null) + { + _oldCommandPaste = null; + } + + if (_newCommands != null) + { + _newCommands.Clear(); + _newCommands = null; + } + if (_oldCommands != null) + { + _oldCommands.Clear(); + _oldCommands = null; + } + + if (_selectionService != null) + { + _selectionService.SelectionChanging -= new EventHandler(OnSelectionChanging); + _selectionService.SelectionChanged -= new EventHandler(OnSelectionChanged); + _selectionService = null; + } + + if (_componentChangeSvc != null) + { + _componentChangeSvc.ComponentRemoved -= new ComponentEventHandler(OnComponentRemoved); + _componentChangeSvc = null; + } + + _currentSelection = null; + _shiftPrimary = null; + _provider = null; + _menuCommandService = null; + _activeTemplateNode = null; + } + + /// + /// This function allows the service to select the parent for the selected Item. + /// + private void RotateParent(bool backwards) + { + Control current = null; + object next = null; + ToolStripItem toolStripItem = null; + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc == null || host == null || !(host.RootComponent is Control)) + { + return; + } + + IContainer container = host.Container; + if (!(selSvc.PrimarySelection is Control component)) + { + component = SelectedDesignerControl as Control; + } + if (component != null) + { + current = component; + } + else + { + toolStripItem = selSvc.PrimarySelection as ToolStripItem; + if (toolStripItem == null) + { + toolStripItem = SelectedDesignerControl as ToolStripItem; + } + if (toolStripItem == null) + { + current = (Control)host.RootComponent; + } + } + + if (backwards) + { + if (current != null) + { + if (current.Controls.Count > 0) + { + next = current.Controls[0]; + } + else + { + next = current; + } + } + else if (toolStripItem != null) + { + next = toolStripItem.Owner.Controls[0]; + } + } + else + { + if (current != null) + { + next = current.Parent; + if (!(next is Control nextControl) || nextControl.Site == null || nextControl.Site.Container != container) + { + next = current; + } + } + else if (toolStripItem != null) + { + if (toolStripItem.IsOnDropDown && toolStripItem.Placement != ToolStripItemPlacement.Overflow) + { + next = ((ToolStripDropDown)toolStripItem.Owner).OwnerItem; + } + else if (toolStripItem.IsOnDropDown && toolStripItem.Placement == ToolStripItemPlacement.Overflow) + { + ToolStrip owner = toolStripItem.Owner; + if (owner != null) + { + owner.OverflowButton.HideDropDown(); + } + next = toolStripItem.Owner; + + } + else + { + next = toolStripItem.Owner; + } + } + } + + if (next is DesignerToolStripControlHost) + { + SelectedDesignerControl = next; + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + else + { + SelectedDesignerControl = null; + selSvc.SetSelectedComponents(new object[] { next }, SelectionTypes.Replace); + } + } + + /// + /// This function allows the service to rotate the TabSelection when TAB key is pressed. + /// + // Okay to suppress because of complex code path + [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] + public void RotateTab(bool backwards) + { + Control ctl; + Control baseCtl; + object targetSelection = null; + object currentSelection; + ISelectionService selSvc = SelectionService; + IDesignerHost host = Host; + if (selSvc == null || host == null || !(host.RootComponent is Control)) + { + return; + } + + IContainer container = host.Container; + baseCtl = (Control)host.RootComponent; + // We must handle two cases of logic here. We are responsible for handling selection within ourself, and also for components on the tray. For our own tabbing around, we want to go by tab-order. When we get to the end of the form, however, we go by selection order into the tray. And, when we're at the end of the tray we start back at the form. We must reverse this logic to go backwards. + currentSelection = selSvc.PrimarySelection; + if (_shiftPressed && ShiftPrimaryItem != null) + { + currentSelection = ShiftPrimaryItem; + } + if (currentSelection == null) + { + currentSelection = SelectedDesignerControl; + // If we are on templateNode and tabbing ahead ... the select the next Control on the parent ... + if (currentSelection != null) + { + if (currentSelection is DesignerToolStripControlHost templateNodeItem && (!templateNodeItem.IsOnDropDown || (templateNodeItem.IsOnDropDown && templateNodeItem.IsOnOverflow))) + { + ctl = templateNodeItem.Owner; + if ((ctl.RightToLeft != RightToLeft.Yes && !backwards) || (ctl.RightToLeft == RightToLeft.Yes && backwards)) + { + targetSelection = GetNextControlInTab(baseCtl, ctl, !backwards); + if (targetSelection == null) + { + ComponentTray tray = (ComponentTray)_provider.GetService(typeof(ComponentTray)); + if (tray != null) + { + targetSelection = tray.GetNextComponent((IComponent)currentSelection, !backwards); + if (targetSelection != null) + { + ControlDesigner controlDesigner = host.GetDesigner((IComponent)targetSelection) as ControlDesigner; + // In Whidbey controls like ToolStrips have componentTray presence, So dont select them again through compoenent tray since here we select only Components. Hence only components that have ComponentDesigners should be selected via the ComponentTray. + while (controlDesigner != null) + { + // if the targetSelection from the Tray is a control .. try the next one. + targetSelection = tray.GetNextComponent((IComponent)targetSelection, !backwards); + if (targetSelection != null) + { + controlDesigner = host.GetDesigner((IComponent)targetSelection) as ControlDesigner; + } + else + { + controlDesigner = null; + } + } + } + } + if (targetSelection == null) + { + targetSelection = baseCtl; + } + } + } + } + } + } + ctl = currentSelection as Control; + //Added New Code for ToolStrip Tabbing.. + if (targetSelection == null && ctl is ToolStrip wb) + { + ToolStripItemCollection collection = wb.Items; + if (collection != null) + { + if (!backwards) + { + targetSelection = collection[0]; + } + else + { + targetSelection = collection[wb.Items.Count - 1]; + } + } + } + // ctl is NOT A CONTROL ... so its Component. Try this for ToolStripItem. + if (targetSelection == null && ctl == null) + { + ToolStripItem item = selSvc.PrimarySelection as ToolStripItem; + if (_shiftPressed && ShiftPrimaryItem != null) + { + item = ShiftPrimaryItem as ToolStripItem; + } + if (item == null) + { + item = SelectedDesignerControl as ToolStripItem; + } + if (item != null && item.IsOnDropDown && item.Placement != ToolStripItemPlacement.Overflow) + { + // You come here only for DesignerToolStripControlHost on the DropDown ... + Debug.WriteLineIf(item is DesignerToolStripControlHost, " Why are we here for non DesignerMenuItem??"); + if (item is DesignerToolStripControlHost designerItem) + { + ToolStripItem parentItem = ((ToolStripDropDown)designerItem.Owner).OwnerItem; + ToolStripMenuItemDesigner designer = host.GetDesigner(parentItem) as ToolStripMenuItemDesigner; + ToolStripDropDown dropDown = designer.GetFirstDropDown((ToolStripDropDownItem)parentItem); + if (dropDown != null) //the DesignerItem is on DropDown.... + { + item = dropDown.OwnerItem; + } + else //The DesignerItem is on FirstDropDown... + { + item = parentItem; + } + } + } + if (item != null && !(item is DesignerToolStripControlHost)) + { + ToolStrip parent = item.GetCurrentParent(); + if (parent != null) + { + if (backwards) + { + // We are item on ToolStripOverflow... + if (parent is ToolStripOverflow) + { + ToolStripItem firstItem = GetNextItem(parent, null, ArrowDirection.Down); + if (item == firstItem) + { + if (item.Owner is ToolStrip owner) + { + targetSelection = GetNextItem(owner, ((ToolStripDropDown)parent).OwnerItem, ArrowDirection.Left); + } + } + else + { + targetSelection = GetNextItem(parent, item, ArrowDirection.Left); + } + } + // check if this is the first item .. if so move out of ToolStrip... + else if (item == parent.Items[0] && parent.RightToLeft != RightToLeft.Yes) + { + // If Shift Pressed ... stop at 1st Item.. + if (_shiftPressed) + { + return; + } + targetSelection = GetNextControlInTab(baseCtl, parent, !backwards); + if (targetSelection == null) + { + ComponentTray tray = (ComponentTray)_provider.GetService(typeof(ComponentTray)); + if (tray != null) + { + targetSelection = tray.GetNextComponent((IComponent)currentSelection, !backwards); + if (targetSelection != null) + { + ControlDesigner controlDesigner = host.GetDesigner((IComponent)targetSelection) as ControlDesigner; + // In Whidbey controls like ToolStrips have componentTray presence, So dont select them again through compoenent tray since here we select only Components. Hence only components that have ComponentDesigners should be selected via the ComponentTray. + while (controlDesigner != null) + { + // if the targetSelection from the Tray is a control .. try the next one. + targetSelection = tray.GetNextComponent((IComponent)targetSelection, !backwards); + if (targetSelection != null) + { + controlDesigner = host.GetDesigner((IComponent)targetSelection) as ControlDesigner; + } + else + { + controlDesigner = null; + } + } + } + } + if (targetSelection == null) + { + targetSelection = baseCtl; + } + } + } + else + { + targetSelection = GetNextItem(parent, item, ArrowDirection.Left); + if (_shiftPressed && SelectionService.GetComponentSelected(targetSelection)) + { + SelectionService.SetSelectedComponents(new object[] { ShiftPrimaryItem, targetSelection }, SelectionTypes.Remove); + } + } + } + else + { + // We are item on ToolStripOverflow... + if (parent is ToolStripOverflow) + { + targetSelection = GetNextItem(parent, item, ArrowDirection.Down); + } + else if (item == parent.Items[0] && parent.RightToLeft == RightToLeft.Yes) + { + // If Shift Pressed ... stop at 1st Item.. + if (_shiftPressed) + { + return; + } + targetSelection = GetNextControlInTab(baseCtl, parent, !backwards); + // this is the First control in TabOrder... Select the Form.. + if (targetSelection == null) + { + targetSelection = baseCtl; + } + } + else + { + targetSelection = GetNextItem(parent, item, ArrowDirection.Right); + if (_shiftPressed && SelectionService.GetComponentSelected(targetSelection)) + { + SelectionService.SetSelectedComponents(new object[] { ShiftPrimaryItem, targetSelection }, SelectionTypes.Remove); + } + } + } + } + } + // This is a DesignerToolStripControlHost on the Main ToolStrip. + else if (item != null) + { + ToolStrip parent = item.GetCurrentParent(); + if (parent != null) + { + // flip the semantics of bakcwards... + if (parent.RightToLeft == RightToLeft.Yes) + { + backwards = !backwards; + } + if (backwards) + { + ToolStripItemCollection collection = parent.Items; + if (collection.Count >= 2) + { + targetSelection = collection[collection.Count - 2]; + } + else + { + targetSelection = GetNextControlInTab(baseCtl, parent, !backwards); + } + } + else + { + ToolStripItemCollection collection = parent.Items; + targetSelection = collection[0]; + } + } + } + } + + if (targetSelection == null && ctl != null && (baseCtl.Contains(ctl) || baseCtl == currentSelection)) + { + // Our current selection is a control. Select the next control in the z-order. + while (null != (ctl = GetNextControlInTab(baseCtl, ctl, !backwards))) + { + if (ctl.Site != null && ctl.Site.Container == container && !(ctl is ToolStripPanel)) + { + break; + } + } + targetSelection = ctl; + } + + if (targetSelection == null) + { + ComponentTray tray = (ComponentTray)_provider.GetService(typeof(ComponentTray)); + if (tray != null) + { + targetSelection = tray.GetNextComponent((IComponent)currentSelection, !backwards); + } + + if (targetSelection == null || targetSelection == currentSelection) + { + targetSelection = baseCtl; + } + } + + //Special Casing since moving to TemplateNode to TemplateNode is moving from null selection to null selection. + if (targetSelection is DesignerToolStripControlHost && currentSelection is DesignerToolStripControlHost) + { + SelectedDesignerControl = targetSelection; + selSvc.SetSelectedComponents(new object[] { targetSelection }, SelectionTypes.Replace); + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + else + { + SetSelection(targetSelection); + } + } + + // Select components. + private void SelectItems(ToolStrip parent) + { + object[] totalObjects = new object[parent.Items.Count - 1]; + for (int i = 0; i < parent.Items.Count - 1; i++) + { + if (parent.Items[i] is DesignerToolStripControlHost) + { + continue; + } + totalObjects[i] = parent.Items[i]; + } + SelectionService.SetSelectedComponents(totalObjects, SelectionTypes.Replace); + } + + // Helper function called by all handlers to select the target Selection. + private void SetSelection(object targetSelection) + { + ISelectionService selSvc = SelectionService; + if (selSvc != null) + { + //Cache original selection + ICollection originalSelComps = selSvc.GetSelectedComponents(); + // Add the TemplateNode to the Selection if it is currently Selected as the GetSelectedComponents wont do it for us. + ArrayList origSel = new ArrayList(originalSelComps); + if (origSel.Count == 0) + { + if (SelectedDesignerControl != null) + { + origSel.Add(SelectedDesignerControl); + } + } + + if (targetSelection is DesignerToolStripControlHost) + { + if (!_shiftPressed) + { + SelectedDesignerControl = targetSelection; + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + } + else + { + if (targetSelection is ToolStripOverflowButton overFlowButton) + { + SelectedDesignerControl = null; + + if (overFlowButton != null) + { + overFlowButton.ShowDropDown(); + } + object newSelection = GetNextItem(overFlowButton.DropDown, null, ArrowDirection.Down); + + if (!_shiftPressed) + { + ShiftPrimaryItem = null; + selSvc.SetSelectedComponents(new object[] { newSelection }, SelectionTypes.Replace); + } + else + { + selSvc.SetSelectedComponents(new object[] { newSelection }); + ShiftPrimaryItem = targetSelection; + } + } + else + { + SelectedDesignerControl = null; + if (!_shiftPressed) + { + ShiftPrimaryItem = null; + selSvc.SetSelectedComponents(new object[] { targetSelection }, SelectionTypes.Replace); + } + else + { + selSvc.SetSelectedComponents(new object[] { targetSelection }); + ShiftPrimaryItem = targetSelection; + } + } + } + + // Invalidate old & new selection. + ToolStripDesignerUtils.InvalidateSelection(origSel, targetSelection as ToolStripItem, _provider, _shiftPressed); + } + //reset the shiftPressed since we end selection + _shiftPressed = false; + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripMenuItemDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripMenuItemDesigner.cs new file mode 100644 index 00000000000..554b23346da --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripMenuItemDesigner.cs @@ -0,0 +1,2773 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Windows.Forms.Design.Behavior; + +namespace System.Windows.Forms.Design +{ + /// + /// Designer for ToolStripMenuItems. + /// + internal class ToolStripMenuItemDesigner : ToolStripDropDownItemDesigner + { + private const int GLYPHINSET = 2; + // This is the typeHereNode that appears to the bottom and right of each commited ToolStripDropDownItem + private DesignerToolStripControlHost typeHereNode; + private ToolStripTemplateNode typeHereTemplateNode = null; + // This is the TemplateNode.EditorToolStrip. The editor ToolStrip is encapsulated in a ToolStripControlHost and then added as a ToolStripDropDownItem on the current ToolStripDropDownItems DropDown. + private DesignerToolStripControlHost commitedEditorNode; + // Actual InSitu Editor. This is created for every selected ToolStripDropDownItem and is DISPOSED immediately after the item comes out of InSitu edit Mode. + private ToolStripTemplateNode commitedTemplateNode; + + // DesignerHost for current Component + private IDesignerHost designerHost; + private ToolStripItem parentItem = null; + private ToolStripAdornerWindowService toolStripAdornerWindowService = null; + private ToolStripKeyboardHandlingService keyboardHandlingService = null; + //Make Selection service a class level member.. used a lot. + private ISelectionService selSvc = null; + //DesignerTrnasaction used for removing Items + private DesignerTransaction _pendingTransaction = null; + private bool fireComponentChanged = false; + //indicates that we are adding new MenuItem .. + private bool componentAddingFired = false; + //new item index + private int indexToInsertNewItem = -1; + //only used by DropDownMenu, DropDown or ContextMenuStrip. + private DesignerTransaction insertMenuItemTransaction; + + // We want one parent transaction when the item is added by InSitu editing which is now supported only for MenuItems. This parent transaction would include + // - Adding the DummyItem + // - Swapping the DummyItem with the InsItu + // - Committing the new Item with the text entered in the Insitu. + private DesignerTransaction newMenuItemTransaction; + //DropDownToInvalidate + private Rectangle dropDownSizeToInvalidate = Rectangle.Empty; + //DropDownToInvalidate while ComponentRemove + private Rectangle boundsToInvalidateOnRemove = Rectangle.Empty; + private ToolStripDropDownGlyph rootControlGlyph; + private bool initialized = false; + + // Hook on the Undoing and Undone Events... + private UndoEngine undoEngine = null; + private bool undoingCalled = false; + private bool addingDummyItem = false; + + //custom DropDown + private ToolStripDropDown customDropDown = null; + private bool dropDownSet = false; + private SerializationStore serializedDataForDropDownItems = null; + private bool dropDownSetFailed = false; + + /// + /// The ToolStripDropDownItems are the associated components. + /// We want those to come with in any cut, copy opreations. + /// + public override ICollection AssociatedComponents + { + get + { + ArrayList items = new ArrayList(); + // Return the list only if the DropDown is AutoGenerated. else the DropDown property set/get will handle it. + if (MenuItem.DropDown.IsAutoGenerated) + { + foreach (ToolStripItem item in MenuItem.DropDownItems) + { + if (!(item is DesignerToolStripControlHost addNewItem)) + { + items.Add(item); + } + } + } + return (ICollection)items; + } + } + + /// + /// ShadowProperty. + /// + private bool CheckOnClick + { + get => (bool)ShadowProperties["CheckOnClick"]; + set => ShadowProperties["CheckOnClick"] = value; + } + + private bool DoubleClickEnabled + { + get => (bool)ShadowProperties["DoubleClickEnabled"]; + set => ShadowProperties["DoubleClickEnabled"] = value; + } + + private ToolStripDropDown DropDown + { + get => customDropDown; + set + { + dropDownSetFailed = false; + if (IsParentDropDown(value)) + { + dropDownSetFailed = true; + throw new ArgumentException(string.Format(SR.InvalidArgument, "DropDown", value.ToString())); + } + //Check if DropDown Exists .. and if yes then Close the DropDown + if (MenuItem.DropDown != null) + { + RemoveTypeHereNode(MenuItem); + // remove and destroy all the items... + if (MenuItem.DropDown.IsAutoGenerated && MenuItem.DropDownItems.Count > 0) + { + //Serialize all the DropDownItems for this Item.... + if (GetService(typeof(ComponentSerializationService)) is ComponentSerializationService serializationService) + { + serializedDataForDropDownItems = serializationService.CreateStore(); + foreach (ToolStripItem item in MenuItem.DropDownItems) + { + //Dont Serialize the DesignerToolStripControlHost... + if (!(item is DesignerToolStripControlHost)) + { + serializationService.Serialize(serializedDataForDropDownItems, item); + } + } + //close the SerializationStore to Serialize Items.. + serializedDataForDropDownItems.Close(); + } + + ToolStripItem[] items = new ToolStripItem[MenuItem.DropDownItems.Count]; + MenuItem.DropDownItems.CopyTo(items, 0); + foreach (ToolStripItem item in items) + { + MenuItem.DropDownItems.Remove(item); + designerHost.DestroyComponent(item); + } + } + MenuItem.HideDropDown(); + } + + // Set The DropDown + MenuItem.DropDown = value; + //Set the Shadow Property + customDropDown = value; + // If DropDown is Set to null and we have valid serializedData, then use it to recreate Items. + if (value == null && !dropDownSet && serializedDataForDropDownItems != null) + { + try + { + // turn off Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = false; + CreatetypeHereNode(); + if (GetService(typeof(ComponentSerializationService)) is ComponentSerializationService serializationService) + { + serializationService.Deserialize(serializedDataForDropDownItems); + serializedDataForDropDownItems = null; + } + } + finally + { + // turn on Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = true; + } + } + MenuItem.DropDown.OwnerItem = MenuItem; + //hook up to the Disposed event ... + MenuItem.DropDown.Disposed += new EventHandler(OnDropDownDisposed); + // show the dropDown. + if (MenuItem.Equals(selSvc.PrimarySelection)) + { + //Add TypeHereNode & show the Dropdown + InitializeDropDown(); + } + } + } + + /// + /// ToolStripEditorManager used this internal property to + /// Activate the editor. + /// + internal override ToolStripTemplateNode Editor + { + get + { + if (base.Editor != null) + { + return base.Editor; + } + if (commitedTemplateNode != null) + { + return commitedTemplateNode; + } + return typeHereTemplateNode; + } + set => commitedTemplateNode = value; + } + + /// + /// True if the MenuItem is on ContextMenu. + /// + private bool IsOnContextMenu + { + get + { + ToolStrip mainStrip = GetMainToolStrip(); + if (mainStrip != null && mainStrip.Site != null && !(mainStrip is ContextMenuStrip)) + { + return false; + } + return true; + } + } + + /// + /// Easy method for getting to the ToolStripDropDownItem + /// + private ToolStripDropDownItem MenuItem + { + get => ToolStripItem as ToolStripDropDownItem; + } + + /// + /// This property is true when the OwnerItem is selected during COPY & PASTE operations. + /// + private bool MenuItemSelected + { + get + { + // check to see if the primary selection is the ToolStrip or one of it's children. + if (selSvc != null) + { + object selectedItem = selSvc.PrimarySelection; + ToolStripItem toolItem; + if (selectedItem == null) + { + if (KeyboardHandlingService != null) + { + selectedItem = KeyboardHandlingService.SelectedDesignerControl; + } + toolItem = selectedItem as ToolStripItem; + } + else + { + toolItem = selectedItem as ToolStripItem; + } + if (toolItem != null) + { + // We always need to return the current selection if we are adding a DummyNode... + if (designerHost != null) + { + if (designerHost.GetDesigner(toolItem) is ToolStripItemDesigner designer) + { + if (designer.dummyItemAdded) + { + return (toolItem == MenuItem); + } + } + } + // We need to return parent if we are on DropDown... + if (toolItem.IsOnDropDown && toolItem.Owner is ToolStripDropDown) + { + ToolStripDropDownItem parentItem = ((ToolStripDropDown)toolItem.Owner).OwnerItem as ToolStripDropDownItem; + return (parentItem == MenuItem); + } + else + { + return (toolItem == MenuItem); + } + } + else if (selectedItem is ContextMenuStrip && + ((ContextMenuStrip)selectedItem).OwnerItem == this.Component && // VSO 214130--SelectedItem must belong to this designer + MenuItem.DropDown == selectedItem) + { + return true; + } + + } + return false; + } + } + + private ToolStripKeyboardHandlingService KeyboardHandlingService + { + get + { + if (keyboardHandlingService == null) + { + keyboardHandlingService = GetService(typeof(ToolStripKeyboardHandlingService)) as ToolStripKeyboardHandlingService; + } + return keyboardHandlingService; + } + } + + /// + /// ParentComponent in case of MenuItems on the DropDown is the OwnerItem of the DropDown and not the ToolStripDropDown (since the DropDowns are not sited) + /// + protected override IComponent ParentComponent + { + get + { + if (ToolStripItem != null) + { + if (!ToolStripItem.IsOnOverflow && ToolStripItem.IsOnDropDown) + { + // If the dropDown is NOT AutoGenerated then its a dropdown the user has set or its a contextMenuStrip/ToolStripDropDownMenu/ToolStripDropDown that has been added from the ToolBox. In such a case dont return the ownerItem but the DropDown itself as the ParentComponent. + if (MenuItem.Owner is ToolStripDropDown dropDown) + { + if (dropDown.IsAutoGenerated) + { + return dropDown.OwnerItem; + } + else + { + return dropDown; + } + } + } + return base.ParentComponent; + } + return null; + } + } + + /// + /// Adds the dummy node for InSitu Edit. + /// + internal void AddNewTemplateNode(ToolStripDropDown dropDown) + { + + //Check if the DropDown contains a typehereNode.... + foreach (ToolStripItem currentItem in dropDown.Items) + { + if (currentItem is DesignerToolStripControlHost) + { + typeHereNode = (DesignerToolStripControlHost)currentItem; + } + } + if (typeHereNode != null) + { + dropDown.Items.Remove(typeHereNode); + } + // setup the MINIToolStrip host... + typeHereTemplateNode = new ToolStripTemplateNode(Component, SR.ToolStripDesignerTemplateNodeEnterText, null); + int width = typeHereTemplateNode.EditorToolStrip.Width; + typeHereNode = new DesignerToolStripControlHost(typeHereTemplateNode.EditorToolStrip); + typeHereTemplateNode.ControlHost = typeHereNode; + typeHereNode.AutoSize = false; + typeHereNode.Width = width; + dropDown.Items.Add(typeHereNode); + } + + // used by morphing in ToolStripItemDesigner ... hence internal method. + internal void AddItemBodyGlyph(ToolStripItem item) + { + if (item != null) + { + ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(item); + if (dropDownItemDesigner != null) + { + Rectangle bounds = dropDownItemDesigner.GetGlyphBounds(); + Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior(); + // Initialize Glyph + ToolStripItemGlyph bodyGlyphForddItem = new ToolStripItemGlyph(item, dropDownItemDesigner, bounds, toolStripBehavior); + //Set the glyph for the item .. so that we can remove it later.... + dropDownItemDesigner.bodyGlyph = bodyGlyphForddItem; + //Add ItemGlyph to the Collection + if (toolStripAdornerWindowService != null) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Insert(0, bodyGlyphForddItem); + } + } + } + } + + // Add individual item Body Glyphs + private void AddBodyGlyphs(ToolStripDropDownItem item) + { + if (item != null) + { + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)designerHost.GetDesigner(item); + if (itemDesigner != null) + { + foreach (ToolStripItem ddItem in item.DropDownItems) + { + AddItemBodyGlyph(ddItem); + } + } + } + } + + /// + /// This is called by the TemplateNode to Commit the Edit. This function creates a NEW ToolStripDropDownItem if we are committing a dummy node or else just replaces the TEXT and IMAGE if we are changing an existing MenuItem. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + internal override void CommitEdit(Type type, string text, bool commit, bool enterKeyPressed, bool tabKeyPressed) + { + IsEditorActive = false; + if (!(MenuItem.Owner is ToolStripDropDown) && base.Editor != null) //we are on Base Menustrip !! + { + base.CommitEdit(type, text, commit, enterKeyPressed, tabKeyPressed); + } + else if (commit) + { + int index = -1; + bool dummyItem = dummyItemAdded; + dummyItemAdded = false; + MenuItem.DropDown.SuspendLayout(); + if (commitedEditorNode != null) /// this means we have a valid node and we just changed some properties.. + { + index = MenuItem.DropDownItems.IndexOf(commitedEditorNode); + ToolStripItem editedItem = (ToolStripItem)MenuItem.DropDownItems[index + 1]; + // Remove TemplatENode + MenuItem.DropDown.Items.Remove(commitedEditorNode); + // Get rid of the templateNode... + if (commitedTemplateNode != null) + { + commitedTemplateNode.CloseEditor(); + commitedTemplateNode = null; + } + if (commitedEditorNode != null) + { + commitedEditorNode.Dispose(); + commitedEditorNode = null; + } + // If we have type "-" this means the user wants to add a Separator. + if (text == "-") + { + if (designerHost.GetDesigner(editedItem) is ToolStripItemDesigner itemDesigner) + { + try + { + editedItem = itemDesigner.MorphCurrentItem(typeof(ToolStripSeparator)); + //Remove the ActionGlyph Added by morphing + RemoveItemBodyGlyph(editedItem); + } + catch + { + if (newMenuItemTransaction != null) + { + try + { + newMenuItemTransaction.Cancel(); + } + catch //This will cause ROLLBACK and hence throw if the project is already in DEBUG and instuEdit was Active. + { + } + newMenuItemTransaction = null; + } + } + finally + { + if (newMenuItemTransaction != null) + { + newMenuItemTransaction.Commit(); + newMenuItemTransaction = null; + } + } + } + } + else + { + // We are adding the item through INSITU for the first time + if (dummyItem) + { + try + { + dummyItemAdded = true; + CreateNewItem(type, index, text); + designerHost.DestroyComponent(editedItem); + // One place where we need to call this explicitly since the selection doesnt change. + if (enterKeyPressed) + { + typeHereNode.SelectControl(); + } + } + catch + { + if (newMenuItemTransaction != null) + { + try + { + newMenuItemTransaction.Cancel(); + } + catch //This will cause ROLLBACK and hence throw if the project is already in DEBUG and instuEdit was Active. + { + } + newMenuItemTransaction = null; + } + } + finally + { + if (newMenuItemTransaction != null) + { + newMenuItemTransaction.Commit(); + newMenuItemTransaction = null; + } + dummyItemAdded = false; + } + } + else //We are editing item that was already present + { + // put the item back... + editedItem.Visible = true; + + //create our transaction + DesignerTransaction designerTransaction = designerHost.CreateTransaction(SR.ToolStripItemPropertyChangeTransaction); + try + { + //Change the properties + PropertyDescriptor textProp = TypeDescriptor.GetProperties(editedItem)["Text"]; + string oldValue = (string)textProp.GetValue(editedItem); + if (textProp != null && text != oldValue) + { + textProp.SetValue(editedItem, text); + } + } + catch + { + if (designerTransaction != null) + { + designerTransaction.Cancel(); + designerTransaction = null; + } + } + finally + { + if (designerTransaction != null) + { + designerTransaction.Commit(); + designerTransaction = null; + } + } + } + } + } + else //if commitedEditorNode == null and we are in commitEdit then just add the new Item, since this item is added through dropDown. + { + //if no editorNode then we are commiting a NEW NODE... + index = MenuItem.DropDownItems.IndexOf(typeHereNode); + try + { + dummyItemAdded = true; + CreateNewItem(type, index, text); + } + finally + { + dummyItemAdded = false; + } + // One place where we need to call this explicitly since the selection doesnt change. + typeHereNode.SelectControl(); + } + //Invalidate DropDown.. + MenuItem.DropDown.ResumeLayout(true); + MenuItem.DropDown.PerformLayout(); + //Reset the Glyphs after Item addition... + ResetGlyphs(MenuItem); + //set the selection to our new item only if item was commited via ENTER KEY in the Insitu Mode. + if (selSvc != null) + { + if (enterKeyPressed) + { + ToolStripItem nextItem; + if ((MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || + MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight) && index >= 1) + { + nextItem = MenuItem.DropDownItems[index - 1]; + } + else + { + nextItem = MenuItem.DropDownItems[index + 1]; + } + if (KeyboardHandlingService != null) + { + if (nextItem != null) + { + if (MenuItem.DropDownItems[index] is ToolStripDropDownItem currentItem) + { + currentItem.HideDropDown(); + } + } + if (nextItem == typeHereNode) + { + // Put Selection on the TypeHereNode. + KeyboardHandlingService.SelectedDesignerControl = nextItem; + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + else + { + KeyboardHandlingService.SelectedDesignerControl = null; + selSvc.SetSelectedComponents(new object[] { nextItem }); + } + } + } + else if (tabKeyPressed) //just select this the new Item + { + selSvc.SetSelectedComponents(new object[] { MenuItem.DropDownItems[index] }, SelectionTypes.Replace); + } + } + } + else //we come here if we have not committed so revert our state... + { + if (commitedEditorNode != null) /// we just changed some properties which we want to revert... + { + MenuItem.DropDown.SuspendLayout(); + bool dummyItem = dummyItemAdded; + dummyItemAdded = false; + int index = MenuItem.DropDownItems.IndexOf(commitedEditorNode); + ToolStripItem editedItem = (ToolStripItem)MenuItem.DropDownItems[index + 1]; + MenuItem.DropDown.Items.Remove(commitedEditorNode); + // put the item back... + editedItem.Visible = true; + if (commitedTemplateNode != null) + { + commitedTemplateNode.CloseEditor(); + commitedTemplateNode = null; + } + + if (commitedEditorNode != null) + { + commitedEditorNode.Dispose(); + commitedEditorNode = null; + } + if (dummyItem) + { + MenuItem.DropDownItems.Remove(editedItem); + try + { + designerHost.DestroyComponent(editedItem); + } + catch + { + if (newMenuItemTransaction != null) + { + try + { + newMenuItemTransaction.Cancel(); + } + catch //This will cause ROLLBACK and hence throw if the project is already in DEBUG and instuEdit was Active. + { + } + newMenuItemTransaction = null; + } + } + editedItem = null; + } + // Required to do here... + MenuItem.DropDown.ResumeLayout(); + //Remove the Glyphs so that Mouse Message go to the Editor + if (editedItem != null) + { + AddItemBodyGlyph(editedItem); + } + + if (dummyItem) + { + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + /// Since the operation is cancelled and there is no change of glyphs, Set SelectionManager.NeedRefresh to false so that it doesnt REFRESH, + /// when the transaction is cancelled. + selMgr.NeedRefresh = false; + if (newMenuItemTransaction != null) + { + try + { + dummyItemAdded = true; + newMenuItemTransaction.Cancel(); + newMenuItemTransaction = null; + if (MenuItem.DropDownItems.Count == 0) + { + CreatetypeHereNode(); + } + } + finally + { + dummyItemAdded = false; + } + } + dummyItem = false; + } + // Added for Separators... + MenuItem.DropDown.PerformLayout(); + } + } + } + + /// + /// Creates the dummy node for InSitu Edit. + /// + private void CreatetypeHereNode() + { + //Debug.Assert(typeHereNode == null, "Why is our dummy node valid?"); + if (typeHereNode == null) + { + AddNewTemplateNode(MenuItem.DropDown); + //Add Text for Debugging Non Sited DropDown.. + if (MenuItem.DropDown.Site == null) + { + MenuItem.DropDown.Text = MenuItem.Name + ".DropDown"; + } + } + else if (typeHereNode != null && MenuItem.DropDownItems.IndexOf(typeHereNode) == -1) + { + MenuItem.DropDown.Items.Add(typeHereNode); + typeHereNode.Visible = true; + } + //Invalidate DropDown.. + MenuItem.DropDown.PerformLayout(); + } + + /// + /// This Function is called by EnterInSituEdit where in we Swap the typeHereNode by the TemplateNode (the Insitu Editor). Since the TemplateNode had a EditorToolStrip we can just HOST that ToolStrip as a ToolStripContorlHost and add it to the DropDown. + /// + private void CreateDummyMenuItem(ToolStripItem item, string text, Image image) + { + commitedTemplateNode = new ToolStripTemplateNode(Component, text, image) + { + ActiveItem = item + }; + int width = commitedTemplateNode.EditorToolStrip.Width; + commitedEditorNode = new DesignerToolStripControlHost(commitedTemplateNode.EditorToolStrip) + { + AutoSize = false, + Width = width + }; + } + + /// + /// This helper function creates a dummyItem for Insitu editing. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private ToolStripItem CreateDummyItem(Type t, int dummyIndex) + { + if (designerHost == null) + { + Debug.Fail("Couldn't get designer host!"); + return null; + } + + ToolStripItem newItem = null; + // For the "Upward DropDown" add at index +1... + if (MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight) + { + dummyIndex++; + } + try + { + // turn off Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = false; + + //Store the index into a class level member so that the componentChanged can access it + indexToInsertNewItem = dummyIndex; + + try + { + //create our transaction + if (newMenuItemTransaction == null) + { + newMenuItemTransaction = designerHost.CreateTransaction(SR.ToolStripCreatingNewItemTransaction); + } + fireComponentChanged = true; + newItem = (ToolStripItem)designerHost.CreateComponent(t); + } + finally + { + fireComponentChanged = false; + } + ToolStripItemDesigner designer = designerHost.GetDesigner(newItem) as ToolStripItemDesigner; + try + { + // ToolStripItem designer tries to set the TEXT for the item in the InitializeNewComponent(). But since we are create item thru InSitu .. we shouldnt do this. + designer.InternalCreate = true; + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + } + finally + { + designer.InternalCreate = false; + } + } + catch (InvalidOperationException ex) + { + CommitInsertTransaction(/*commit=*/false); + + if (newMenuItemTransaction != null) + { + newMenuItemTransaction.Cancel(); + newMenuItemTransaction = null; + } + IUIService uiService = (IUIService)GetService(typeof(IUIService)); + uiService.ShowError(ex.Message); + } + finally + { + // turn on Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = true; + // Reset the index + indexToInsertNewItem = -1; + } + return newItem; + } + + /// + /// Asks the host to create a new DropDownItem, inserts the item into the collection & selects it. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private ToolStripItem CreateNewItem(Type t, int dummyIndex, string newText) + { + if (designerHost == null) + { + Debug.Fail("Couldn't get designer host!"); + return null; + } + ToolStripItem newItem = null; + // For the "Upward DropDown" add at index +1... + if (MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight) + { + dummyIndex++; + } + //create our transaction + DesignerTransaction outerTransaction = designerHost.CreateTransaction(SR.ToolStripCreatingNewItemTransaction); + try + { + // turn off Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = false; + //Store the index into a class level member so that the componentChanged can access it + indexToInsertNewItem = dummyIndex; + try + { + fireComponentChanged = true; + newItem = (ToolStripItem)designerHost.CreateComponent(t, ToolStripDesigner.NameFromText(newText, t, MenuItem.Site)); + } + finally + { + fireComponentChanged = false; + } + ToolStripItemDesigner designer = designerHost.GetDesigner(newItem) as ToolStripItemDesigner; + try + { + // ToolStripItem designer tries to set the TEXT for the item in the InitializeNewComponent(). But since we are create item thru InSitu .. we shouldnt do this. + if (!string.IsNullOrEmpty(newText) || addingDummyItem) + { + designer.InternalCreate = true; + } + if (designer is ComponentDesigner) + { + ((ComponentDesigner)designer).InitializeNewComponent(null); + } + } + finally + { + designer.InternalCreate = false; + } + + //Set the Text and Image.. + if (newItem != null) + { + PropertyDescriptor textProperty = TypeDescriptor.GetProperties(newItem)["Text"]; + Debug.Assert(textProperty != null, "Could not find 'Text' property in ToolStripItem."); + if (textProperty != null && !string.IsNullOrEmpty(newText)) + { + textProperty.SetValue(newItem, newText); + } + } + } + catch + { + //There might be scenarios where the ComponentAdding is fired but the Added doesnt get fired. Is such cases the InsertTransaction might be still active... So we need to cancel that too here. + CommitInsertTransaction(false); + if (outerTransaction != null) + { + outerTransaction.Cancel(); + outerTransaction = null; + } + } + finally + { + if (outerTransaction != null) + { + outerTransaction.Commit(); + outerTransaction = null; + } + + // turn on Adding/Added events listened to by the ToolStripDesigner... + ToolStripDesigner.s_autoAddNewItems = true; + // Reset the index + indexToInsertNewItem = -1; + } + return newItem; + } + + /// + /// Helper function to find whether the passed in DropDownItems have same owner. + /// + private bool CheckSameOwner(ToolStripDropDownItem lastSelected, ToolStripDropDownItem currentSelected) + { + if (lastSelected != null && currentSelected != null) + { + if (lastSelected.Owner is ToolStripDropDown && currentSelected.Owner is ToolStripDropDown) + { + ToolStripItem ownerLastSelected = ((ToolStripDropDown)(lastSelected.Owner)).OwnerItem; + ToolStripItem ownerCurrentSelected = ((ToolStripDropDown)(currentSelected.Owner)).OwnerItem; + return (ownerLastSelected == ownerCurrentSelected); + } + } + return false; + } + + // internal method to commit any node. + internal void Commit() + { + if (commitedTemplateNode != null && commitedTemplateNode.Active) + { + //Get Index of the CommitedItem.. + int index = MenuItem.DropDownItems.IndexOf(commitedEditorNode); + commitedTemplateNode.Commit(false, false); + if (index != -1 && MenuItem.DropDownItems.Count > index) + { + if (MenuItem.DropDownItems[index] is ToolStripDropDownItem newItem) + { + newItem.HideDropDown(); + } + } + } + else if (typeHereTemplateNode != null && typeHereTemplateNode.Active) + { + typeHereTemplateNode.Commit(false, false); + } + // COMMIT ALL THE THE PARENT CHAIN .... + ToolStripDropDownItem currentItem = MenuItem; + while (currentItem != null && currentItem.Owner is ToolStripDropDown) + { + currentItem = (ToolStripDropDownItem)((ToolStripDropDown)(currentItem.Owner)).OwnerItem; + if (currentItem != null) + { + ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)designerHost.GetDesigner(currentItem); + if (itemDesigner != null) + { + itemDesigner.Commit(); + } + } + } + } + + /// + /// Disposes of this designer. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + //clean up + if (selSvc != null) + { + selSvc.SelectionChanged -= new EventHandler(this.OnSelectionChanged); + } + if (undoEngine != null) + { + undoEngine.Undoing -= new EventHandler(this.OnUndoing); + undoEngine.Undone -= new EventHandler(this.OnUndone); + } + if (MenuItem != null && MenuItem.HasDropDown) + { + MenuItem.DropDown.Hide(); + //Unhook the events... + UnHookEvents(); + } + + if (toolStripAdornerWindowService != null) + { + toolStripAdornerWindowService = null; + } + + if (typeHereTemplateNode != null) + { + typeHereTemplateNode.RollBack(); + typeHereTemplateNode.CloseEditor(); + typeHereTemplateNode = null; + } + + if (typeHereNode != null) + { + typeHereNode.Dispose(); + typeHereNode = null; + } + if (commitedTemplateNode != null) + { + commitedTemplateNode.RollBack(); + commitedTemplateNode.CloseEditor(); + commitedTemplateNode = null; + } + + if (commitedEditorNode != null) + { + commitedEditorNode.Dispose(); + commitedEditorNode = null; + } + + if (parentItem != null) + { + parentItem = null; + } + } + base.Dispose(disposing); + } + + // When the dropDown is clicked; Commit any active insitu node. + private void DropDownClick(object sender, EventArgs e) + { + // Commit any InsituEdit Node. + if (KeyboardHandlingService != null && KeyboardHandlingService.TemplateNodeActive) + { + // If templateNode Active .. commit and Select it + KeyboardHandlingService.ActiveTemplateNode.CommitAndSelect(); + } + } + + // re-paint required to "validate" the glyphs + private void DropDownPaint(object sender, PaintEventArgs e) + { + //Select All requires the repaint of glyphs after the DropDown receives paint message. + if (selSvc != null && MenuItem != null) + { + foreach (ToolStripItem item in MenuItem.DropDownItems) + { + if (item.Visible && selSvc.GetComponentSelected(item)) + { + if (designerHost.GetDesigner(item) is ToolStripItemDesigner designer) + { + Rectangle r = designer.GetGlyphBounds(); + ToolStripDesignerUtils.GetAdjustedBounds(item, ref r); + r.Inflate(GLYPHINSET, GLYPHINSET); + //this will allow any Glyphs to re-paint + //after this control and its designer has painted + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + if (b != null) + { + b.ProcessPaintMessage(r); + } + } + } + // When you alt-tab from VS to any other application and come back and if the dropDown is open; then the templateNode doesnt paint. This happens when you have another control below the dropDown which paints over the controlhost so we need to refresh the TemplateNode in this case. + if (item is DesignerToolStripControlHost controlHost) + { + controlHost.Control.Refresh(); + } + } + } + } + + // Invalidate the BehaviorService if the location changed. + private void DropDownLocationChanged(object sender, EventArgs e) + { + // this shoulnt get fired manytimes.. only in certain case... but in those cases its needed to REFRESH THE ENTIRE adornerWindow. + ToolStripDropDown dropDown = sender as ToolStripDropDown; + if (dropDown.Visible) + { + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + behaviorService.Invalidate(); + } + } + } + + // Change the parent when the DropDown is opening. + private void DropDownItem_DropDownOpening(object sender, EventArgs e) + { + ToolStripDropDownItem ddi = sender as ToolStripDropDownItem; + if (toolStripAdornerWindowService != null) + { + ddi.DropDown.TopLevel = false; + ddi.DropDown.Parent = toolStripAdornerWindowService.ToolStripAdornerWindowControl; + } + } + + // Add the DropDownGlyph when the dropDown is opened. + private void DropDownItem_DropDownOpened(object sender, EventArgs e) + { + //Add Glyphs... + ToolStripDropDownItem ddi = sender as ToolStripDropDownItem; + if (ddi != null) + { + ResetGlyphs(ddi); + } + + // finally add Glyph for the "DropDown" + Control rootControl = ddi.DropDown; + if (rootControl != null) + { + if (designerHost.GetDesigner(designerHost.RootComponent) is ControlDesigner designer) + { + rootControlGlyph = new ToolStripDropDownGlyph(rootControl.Bounds, new DropDownBehavior(designer, this)); + } + if (toolStripAdornerWindowService != null) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Add(rootControlGlyph); + } + } + } + + // Remove the dropDownGlyph after the dropDown is closed. + private void DropDownItem_DropDownClosed(object sender, EventArgs e) + { + if (sender is ToolStripDropDownItem ddi) + { + //Invaliate the ToolStripWindow.... for clearing the dropDowns + if (toolStripAdornerWindowService != null) + { + if (rootControlGlyph != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(rootControlGlyph)) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(rootControlGlyph); + } + } + //Remove body Glyphs... + InitializeBodyGlyphsForItems(false /*remove*/, ddi); + //Unhook all the Events + initialized = false; + UnHookEvents(); + // Check if this is a Sited-DropDown + if (ddi.DropDown.Site != null || ddi.DropDownItems.Count == 1) + { + //Get Designer ... and call Remove on that Designer. + RemoveTypeHereNode(ddi); + } + else if (toolStripAdornerWindowService != null) + { + toolStripAdornerWindowService.Invalidate(ddi.DropDown.Bounds); + } + } + } + + // invalidate the AdornerWindow when the DropDown resizes + private void DropDownResize(object sender, EventArgs e) + { + ToolStripDropDown dropDown = sender as ToolStripDropDown; + if (!dummyItemAdded) + { + if (dropDown != null && dropDown.Visible) + { + //Invalidate only if new Size is LESS than old Size... + if (toolStripAdornerWindowService != null && (dropDown.Width < dropDownSizeToInvalidate.Width || dropDown.Size.Height < dropDownSizeToInvalidate.Height)) + { + using (Region invalidatingRegion = new Region(dropDownSizeToInvalidate)) + { + invalidatingRegion.Exclude(dropDown.Bounds); + toolStripAdornerWindowService.Invalidate(invalidatingRegion); + //Invalidate BehaviorService AdornerWindow as well... but only the DropDownBounds + BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService)); + if (b != null) + { + b.Invalidate(invalidatingRegion); + } + } + } + } + if (toolStripAdornerWindowService != null) + { + if (rootControlGlyph != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(rootControlGlyph)) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(rootControlGlyph); + } + if (designerHost.GetDesigner(designerHost.RootComponent) is ControlDesigner designer) + { + rootControlGlyph = new ToolStripDropDownGlyph(dropDown.Bounds, new DropDownBehavior(designer, this)); + } + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Add(rootControlGlyph); + } + } + dropDownSizeToInvalidate = dropDown.Bounds; + } + + /// + /// Called when a menuItem wants to go into InSitu Editing Mode. + /// + internal void EditTemplateNode(bool clicked) + { + // If the parent has a window which is too small, there won't be any space to draw the entry box and typeHereNode will be null + if (typeHereNode == null) + { + return; + } + + // Refresh the state of the 'TypeHere' node to NotSelected state + typeHereNode.RefreshSelectionGlyph(); + // Commit any InsituEdit Node. + if (KeyboardHandlingService != null && KeyboardHandlingService.TemplateNodeActive) + { + // If templateNode Active .. commit and Select it + KeyboardHandlingService.ActiveTemplateNode.CommitAndSelect(); + } + + // commit any existing insitu editor... + if (clicked) + { + // We should come here for a valid parent !!! + if (MenuItem == null) + { + return; + } + } + + // always select the parent item... but dont redraw the control during this Selection Change as this causes flicker + try + { + ToolStripDesigner.s_editTemplateNode = true; + selSvc.SetSelectedComponents(new object[] { MenuItem }, SelectionTypes.Replace); + } + finally + { + ToolStripDesigner.s_editTemplateNode = false; + } + + // Hide the DropDown of any previous Selection.. First get the SelectedItem... + ToolStripDropDownItem selectedItem = null; + if (selSvc.PrimarySelection == null && KeyboardHandlingService != null) + { + if (KeyboardHandlingService.SelectedDesignerControl is ToolStripItem item) + { + selectedItem = ((ToolStripDropDown)item.Owner).OwnerItem as ToolStripDropDownItem; + } + } + else + { + selectedItem = selSvc.PrimarySelection as ToolStripDropDownItem; + } + + // Now Hide the DropDown and Refresh Glyphs... + if (selectedItem != null && selectedItem != MenuItem) + { + HideSiblingDropDowns(selectedItem); + } + + MenuItem.DropDown.SuspendLayout(); + dummyItemAdded = true; + int index = MenuItem.DropDownItems.IndexOf(typeHereNode); + ToolStripItem newDummyItem = null; + try + { + addingDummyItem = true; + newDummyItem = CreateDummyItem(typeof(ToolStripMenuItem), index); + } + catch (CheckoutException checkoutException) + { + if (checkoutException.Equals(CheckoutException.Canceled)) + { + CommitInsertTransaction(/*commit=*/ false); + + if (newMenuItemTransaction != null) + { + newMenuItemTransaction.Cancel(); + newMenuItemTransaction = null; + } + } + else + { + throw; + } + } + finally + { + dummyItemAdded = (newDummyItem != null); + addingDummyItem = false; + } + + MenuItem.DropDown.ResumeLayout(); + if (newDummyItem != null) + { + if (designerHost.GetDesigner(newDummyItem) is ToolStripMenuItemDesigner newItemDesigner) + { + newItemDesigner.InitializeDropDown(); + newItemDesigner.ShowEditNode(clicked); + } + } + } + + /// + /// Called from OnDoubleClickTimerTick to Enter in InsituMode + /// + private void EnterInSituMode() + { + //we need to tell our parent that we want to enter insitu edit mode + if (MenuItem.Owner is ToolStripDropDown) + { + ToolStripItem ownerItem = ((ToolStripDropDown)(MenuItem.Owner)).OwnerItem; + //need to inform the owner tha we want to enter insitu mode + if (designerHost != null) + { + IDesigner designer = designerHost.GetDesigner(ownerItem); + if (designer is ToolStripMenuItemDesigner) + { + // Need to Add Dummy Node For Direct Insitu.. + MenuItem.HideDropDown(); + ((ToolStripMenuItemDesigner)designer).EnterInSituEdit(MenuItem); + } + } + } + } + + /// + /// This method replaces the menItem with an in-situ TemplateNode. + /// + internal void EnterInSituEdit(ToolStripItem toolItem) + { + MenuItem.DropDown.SuspendLayout(); + //Remove the Glyphs so that Mouse Message go to the Editor + RemoveItemBodyGlyph(toolItem); + + if (toolItem == null) + { + return; + } + // we can only one Active Editor at one time. + if (IsEditorActive) + { + return; + } + + CreateDummyMenuItem(toolItem, toolItem.Text, toolItem.Image); + int index = MenuItem.DropDownItems.IndexOf(toolItem); + //swap in our insitu ToolStrip + MenuItem.DropDownItems.Insert(index, commitedEditorNode); + if (toolItem is ToolStripControlHost) + { + ((ToolStripControlHost)toolItem).Control.Visible = false; + } + toolItem.Visible = false; + MenuItem.DropDown.ResumeLayout(); + // Try Focusing the TextBox.... + if (commitedTemplateNode != null) + { + commitedTemplateNode.FocusEditor(toolItem); + } + ToolStripDropDownItem dropDownItem = toolItem as ToolStripDropDownItem; + if (!(dropDownItem.Owner is ToolStripDropDownMenu) && dropDownItem != null && dropDownItem.Bounds.Width < commitedEditorNode.Bounds.Width) + { + dropDownItem.Width = commitedEditorNode.Width; + dropDownItem.DropDown.Location = new Point(dropDownItem.DropDown.Location.X + commitedEditorNode.Bounds.Width - dropDownItem.Bounds.Width, dropDownItem.DropDown.Location.Y); + } + IsEditorActive = true; + } + + /// + /// Get the Insertion Index to drop the current drag-drop item. + /// + /// Returns the DropDown for this MenuItem else returns the Parent(Owner). + /// + protected override Component GetOwnerForActionList() + { + return MenuItem; + } + + // Helper Function to get the Main ToolStrip (MenuStrip); + internal override ToolStrip GetMainToolStrip() + { + ToolStripDropDown topmost = GetFirstDropDown(MenuItem); + ToolStripItem topMostItem = (topmost == null) ? null : topmost.OwnerItem; + if (topMostItem != null) + { + return topMostItem.Owner; + } + return MenuItem.Owner; + } + + /// + /// Helper function to Hide the Active Dropdown from the given DropDownItem. + /// + // Standard 'catch all - rethrow critical' exception pattern + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void HideAllDropDowns(ToolStripDropDownItem item) + { + try + { + if (MenuItem.Owner is ToolStripDropDown) + { + ToolStripItem ownerItem = ((ToolStripDropDown)(MenuItem.Owner)).OwnerItem; + while (item != ownerItem) + { + if (item.DropDown.Visible) + { + item.HideDropDown(); + } + if (item.Owner is ToolStripDropDown) + { + item = (ToolStripDropDownItem)((ToolStripDropDown)(item.Owner)).OwnerItem; + } + else + { + return; + } + } + } + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + } + + /// + /// Helper function to Hide the Active Dropdown for all the siblings of the given DropDownItem. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + private void HideSiblingDropDowns(ToolStripDropDownItem item) + { + try + { + ToolStripItem ownerItem = MenuItem; + while (item != ownerItem) + { + item.HideDropDown(); + if (item.Owner is ToolStripDropDown) + { + item = (ToolStripDropDownItem)((ToolStripDropDown)(item.Owner)).OwnerItem; + } + else + { + return; + } + } + } + catch (Exception e) + { + if (ClientUtils.IsCriticalException(e)) + { + throw; + } + } + } + + /// + /// This will listen to the necessary dropDown events... now we add the events on selection and unhook when the dropDown is closed. + /// + internal void HookEvents() + { + if (MenuItem != null) + { + MenuItem.DropDown.Closing += new ToolStripDropDownClosingEventHandler(OnDropDownClosing); + MenuItem.DropDownOpening += new EventHandler(DropDownItem_DropDownOpening); + MenuItem.DropDownOpened += new EventHandler(DropDownItem_DropDownOpened); + MenuItem.DropDownClosed += new EventHandler(DropDownItem_DropDownClosed); + MenuItem.DropDown.Resize += new System.EventHandler(this.DropDownResize); + MenuItem.DropDown.ItemAdded += new ToolStripItemEventHandler(OnItemAdded); + MenuItem.DropDown.Paint += new PaintEventHandler(this.DropDownPaint); + MenuItem.DropDown.Click += new EventHandler(this.DropDownClick); + MenuItem.DropDown.LocationChanged += new EventHandler(this.DropDownLocationChanged); + } + } + + /// + /// Initializes the ToolStripDropDownItem Designer. + /// + public override void Initialize(IComponent component) + { + base.Initialize(component); + // initialize the properties we will be shadowing + Visible = true; + DoubleClickEnabled = MenuItem.DoubleClickEnabled; + //hook our services + selSvc = (ISelectionService)GetService(typeof(ISelectionService)); + if (selSvc != null) + { + selSvc.SelectionChanged += new EventHandler(this.OnSelectionChanged); + } + + //hookup to the AdornerService.. + toolStripAdornerWindowService = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService)); + designerHost = (IDesignerHost)GetService(typeof(IDesignerHost)); + //Set the DoubleClickEnabled + MenuItem.DoubleClickEnabled = true; + + if (undoEngine == null) + { + undoEngine = GetService(typeof(UndoEngine)) as UndoEngine; + if (undoEngine != null) + { + undoEngine.Undoing += new EventHandler(this.OnUndoing); + undoEngine.Undone += new EventHandler(this.OnUndone); + } + } + } + + // internal since the Behavior uses this when the Items are moved on the DropDown. + internal void InitializeBodyGlyphsForItems(bool addGlyphs /* true for add */, ToolStripDropDownItem item) + { + if (addGlyphs) + { + AddBodyGlyphs(item); + } + else + { + RemoveBodyGlyphs(item); + } + } + + /// + /// Important function that initializes the dropDown with the typeHereNode , hooks the events and then shows the dropDown. + /// + internal void InitializeDropDown() + { + ToolStrip main = GetMainToolStrip(); + // Check if the TopMostItem is on normal dropdown or on the overflow. + ToolStripDropDown firstDropDown = GetFirstDropDown(MenuItem); + if (firstDropDown != null) + { + ToolStripItem topMostItem = firstDropDown.OwnerItem; + if ((topMostItem != null && topMostItem.GetCurrentParent() is ToolStripOverflow) && !main.CanOverflow) + { + return; + } + } + + if (!initialized) + { + initialized = true; + // When the DropDown is Shared the ownerItem need not be the current MenuItem. In Such a case hide the dropDown for current owner ... this will bring everything to a sane state.. + if (MenuItem.DropDown.OwnerItem is ToolStripDropDownItem currentOwner && currentOwner != MenuItem) + { + if (designerHost.GetDesigner(currentOwner) is ToolStripMenuItemDesigner ownerdesigner) + { + ownerdesigner.RemoveTypeHereNode(currentOwner); + } + currentOwner.HideDropDown(); + } + + // Check if this is a Sited-DropDown + if (MenuItem.DropDown.Site != null) + { + ToolStripDropDownDesigner designer = designerHost.GetDesigner(MenuItem.DropDown) as ToolStripDropDownDesigner; + if (designer != null) + { + designer.currentParent = MenuItem as ToolStripMenuItem; + } + } + + CreatetypeHereNode(); + MenuItem.DropDown.TopLevel = false; + //Allow Drag - Drop.... + MenuItem.DropDown.AllowDrop = true; + HookEvents(); + MenuItem.DropDown.AutoClose = false; + MenuItem.ShowDropDown(); + ShowOwnerDropDown(MenuItem); + + //Everytime you intitalize the dropDown Reset Glyphs + ResetGlyphs(MenuItem); + + if (!IsOnContextMenu && !dummyItemAdded) + { + // Required to show the SelectionBorder when the item is selected through the PropertyGrid or Doc outline. + SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager)); + // used the cached value... + if (selMgr != null) + { + selMgr.Refresh(); + } + } + BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService)); + if (behaviorService != null) + { + behaviorService.Invalidate(MenuItem.Owner.Bounds); + } + } + } + + private bool IsParentDropDown(ToolStripDropDown currentDropDown) + { + if (currentDropDown != null) + { + ToolStripDropDown startDropDown = MenuItem.Owner as ToolStripDropDown; + while (startDropDown != null && startDropDown != currentDropDown) + { + if (startDropDown.OwnerItem is ToolStripDropDownItem ownerItem) + { + startDropDown = ownerItem.Owner as ToolStripDropDown; + } + else + { + startDropDown = null; + } + } + if (startDropDown == null) + { + return false; + } + return true; + } + return false; + } + + /// + /// This will morph the current item to the provided type "t" of the item... + /// + internal override ToolStripItem MorphCurrentItem(Type t) + { + //Get the Hosting DropDown'd bounds + Rectangle hostingDropDownBounds = (MenuItem.GetCurrentParent()).Bounds; + //Get the currentItems DropDownBounds + Rectangle itemDropDownBounds = MenuItem.DropDown.Bounds; + //Remove body Glyphs... + InitializeBodyGlyphsForItems(false /*remove*/, MenuItem); + Rectangle boundstoInvalidate = Rectangle.Union(hostingDropDownBounds, itemDropDownBounds); + ToolStripAdornerWindowService toolStripservice = toolStripAdornerWindowService; + ToolStripItem newItem = base.MorphCurrentItem(t); + // We loose the ToolStripWindowService after Morphing... so use the cached one. + if (toolStripservice != null) + { + toolStripservice.Invalidate(boundstoInvalidate); + toolStripservice = null; + } + return newItem; + } + + /// + /// Fired after a component has been added. Here, we add it to the ToolStrip and select it. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private void ComponentChangeSvc_ComponentAdded(object sender, ComponentEventArgs e) + { + IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); + // make sure it's one of ours and on DropDown. + if (e.Component is ToolStripItem newItem && componentAddingFired && (MenuItemSelected || fireComponentChanged)) + { + componentAddingFired = false; + try + { + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + if (changeSvc != null) + { + MemberDescriptor member = TypeDescriptor.GetProperties(MenuItem.DropDown)["Items"]; + changeSvc.OnComponentChanging(MenuItem.DropDown, member); + } + } + else + { + base.RaiseComponentChanging(TypeDescriptor.GetProperties(MenuItem)["DropDownItems"]); + } + + // Get the current count of ToolStripItems. + int count = MenuItem.DropDownItems.Count; + + // In Cut / Copy and Paste the 'indexToInsertNewItem' is not Set and hence is -1... so check for that value... + if (indexToInsertNewItem != -1) + { + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + MenuItem.DropDown.Items.Insert(indexToInsertNewItem, newItem); + } + else + { + MenuItem.DropDownItems.Insert(indexToInsertNewItem, newItem); + } + } + else + { + // Insert Item at the current Selection... + if (selSvc.PrimarySelection is ToolStripItem selectedItem && selectedItem != MenuItem) + { + int index = MenuItem.DropDownItems.IndexOf(selectedItem); + if (MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight) + { + // Add at the next Index in case of "Up-Directed" dropDown. + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + MenuItem.DropDown.Items.Insert(index + 1, newItem); + } + else + { + MenuItem.DropDownItems.Insert(index + 1, newItem); + } + } + else + { + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + MenuItem.DropDown.Items.Insert(index, newItem); + } + else + { + MenuItem.DropDownItems.Insert(index, newItem); + } + } + } + else + { + if (count > 0) + { + if (MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveLeft && MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveRight) + { + // ADD at Last but one, the last one being the TemplateNode always... + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + MenuItem.DropDown.Items.Insert(count - 1, newItem); + } + else + { + MenuItem.DropDownItems.Insert(count - 1, newItem); + } + } + } + else //count == 0 + { + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + MenuItem.DropDown.Items.Add(newItem); + } + else + { + MenuItem.DropDownItems.Add(newItem); + } + } + } + } + // If the Item is added through Undo/Redo ONLY then select the item + if (undoingCalled) + { + if (selSvc != null) + { + selSvc.SetSelectedComponents(new IComponent[] { newItem }, SelectionTypes.Replace); + } + } + ResetGlyphs(MenuItem); + } + catch + { + CommitInsertTransaction(/*commit=*/false); + } + finally + { + if (IsOnContextMenu && MenuItem.DropDown.Site != null) + { + if (changeSvc != null) + { + MemberDescriptor member = TypeDescriptor.GetProperties(MenuItem.DropDown)["Items"]; + changeSvc.OnComponentChanged(MenuItem.DropDown, member, null, null); + } + } + else + { + base.RaiseComponentChanged(TypeDescriptor.GetProperties(MenuItem)["DropDownItems"], null, null); + } + CommitInsertTransaction(/*commit=*/true); + } + } + } + + private void CommitInsertTransaction(bool commit) + { + if (!IsOnContextMenu) + { + ToolStrip mainStrip = GetMainToolStrip(); + if (designerHost.GetDesigner(mainStrip) is ToolStripDesigner mainStripDesigner && mainStripDesigner.InsertTansaction != null) + { + if (commit) + { + mainStripDesigner.InsertTansaction.Commit(); + } + else + { + mainStripDesigner.InsertTansaction.Cancel(); + } + mainStripDesigner.InsertTansaction = null; + } + } + else + { + if (insertMenuItemTransaction != null) + { + if (commit) + { + insertMenuItemTransaction.Commit(); + } + else + { + insertMenuItemTransaction.Cancel(); + } + insertMenuItemTransaction = null; + } + } + } + + /// + /// Checks if the component being added is a child ToolStripItem. + /// + private void ComponentChangeSvc_ComponentAdding(object sender, ComponentEventArgs e) + { + //Dont do anything if CopyInProgress is true + if (KeyboardHandlingService != null && KeyboardHandlingService.CopyInProgress) + { + return; + } + if (e.Component is ToolStripItem && (MenuItemSelected || fireComponentChanged)) + { + if (!IsOnContextMenu) + { + ToolStrip mainStrip = GetMainToolStrip(); + if (designerHost.GetDesigner(mainStrip) is ToolStripDesigner mainStripDesigner && !mainStripDesigner.EditingCollection && mainStripDesigner.InsertTansaction == null) + { + componentAddingFired = true; + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + mainStripDesigner.InsertTansaction = designerHost.CreateTransaction(SR.ToolStripInsertingIntoDropDownTransaction); + } + } + else //we are on ContextMenuStrip, ToolStripDropDown or ToolStripDropDownMenu.... + { + if (e.Component is ToolStripItem itemAdding && itemAdding.Owner == null) + { + componentAddingFired = true; + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + insertMenuItemTransaction = designerHost.CreateTransaction(SR.ToolStripInsertingIntoDropDownTransaction); + } + } + } + } + + /// + /// After a ToolStripItem is removed, remove it from the ToolStrip and select the next item. + /// + private void ComponentChangeSvc_ComponentRemoved(object sender, ComponentEventArgs e) + { + if (e.Component is ToolStripItem itemToBeDeleted && itemToBeDeleted.IsOnDropDown) + { + if (itemToBeDeleted.Owner is ToolStripDropDown owner) + { + //Get the ownerItem + ToolStripDropDownItem ownerItem = (ToolStripDropDownItem)((ToolStripDropDown)(itemToBeDeleted.Owner)).OwnerItem; + if (ownerItem != null && ownerItem == MenuItem) + { + int itemIndex = ownerItem.DropDownItems.IndexOf(itemToBeDeleted); + // send notifications. + try + { + if (itemIndex != -1) + { + ownerItem.DropDownItems.Remove(itemToBeDeleted); + base.RaiseComponentChanged(TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + } + finally + { + if (_pendingTransaction != null) + { + _pendingTransaction.Commit(); + _pendingTransaction = null; + } + } + + //Remove & Add the Glyphs + ResetGlyphs(ownerItem); + // select the next item or the ToolStrip itself. + if (ownerItem.DropDownItems.Count > 1) + { + itemIndex = Math.Min(ownerItem.DropDownItems.Count - 1, itemIndex); + itemIndex = Math.Max(0, itemIndex); + } + else + { + itemIndex = -1; + } + + // Looks like we need to invalidate the entire + if (toolStripAdornerWindowService != null && boundsToInvalidateOnRemove != Rectangle.Empty) + { + using (Region regionToInvalidate = new Region(boundsToInvalidateOnRemove)) + { + regionToInvalidate.Exclude(MenuItem.DropDown.Bounds); + toolStripAdornerWindowService.Invalidate(regionToInvalidate); + boundsToInvalidateOnRemove = Rectangle.Empty; + } + } + + // Select the item only if Cut/Delete is pressed. + if (KeyboardHandlingService != null && KeyboardHandlingService.CutOrDeleteInProgress) + { + if (selSvc != null && !dummyItemAdded) + { + IComponent targetSelection = (itemIndex == -1) ? (IComponent)ownerItem : (IComponent)ownerItem.DropDownItems[itemIndex]; + // if the TemplateNode becomes the targetSelection, then set the targetSelection to null. + if (targetSelection is DesignerToolStripControlHost) + { + KeyboardHandlingService.SelectedDesignerControl = targetSelection; + KeyboardHandlingService.OwnerItemAfterCut = MenuItem; + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + else + { + selSvc.SetSelectedComponents(new IComponent[] { targetSelection }, SelectionTypes.Replace); + } + } + } + } + } + } + } + + /// + /// Before a ToolStripItem is removed, open a transaction to batch the operation. + /// + private void ComponentChangeSvc_ComponentRemoving(object sender, ComponentEventArgs e) + { + if (dummyItemAdded) + { + return; + } + if (e.Component is ToolStripItem itemToBeDeleted && itemToBeDeleted.IsOnDropDown && itemToBeDeleted.Placement == ToolStripItemPlacement.Main) + { + if (itemToBeDeleted.Owner is ToolStripDropDown owner) + { + //Get the ownerItem + ToolStripDropDownItem ownerItem = (ToolStripDropDownItem)((ToolStripDropDown)(itemToBeDeleted.Owner)).OwnerItem; + if (ownerItem != null && ownerItem == MenuItem) + { + RemoveItemBodyGlyph(itemToBeDeleted); + InitializeBodyGlyphsForItems(false, ownerItem); + boundsToInvalidateOnRemove = ownerItem.DropDown.Bounds; + //Check if the deleted item is a dropDownItem and its DropDown is Visible. + if (itemToBeDeleted is ToolStripDropDownItem dropDownItem) + { + boundsToInvalidateOnRemove = Rectangle.Union(boundsToInvalidateOnRemove, dropDownItem.DropDown.Bounds); + } + Debug.Assert(designerHost != null, "Why didn't we get a designer host?"); + Debug.Assert(_pendingTransaction == null, "Adding item with pending transaction?"); + try + { + _pendingTransaction = designerHost.CreateTransaction(SR.ToolStripDesignerTransactionRemovingItem); + base.RaiseComponentChanging(TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + } + catch + { + if (_pendingTransaction != null) + { + _pendingTransaction.Cancel(); + _pendingTransaction = null; + } + } + } + } + } + } + + /// + /// Controls the dismissal of the drop down, here - we just cancel it + /// + private void OnDropDownClosing(object sender, ToolStripDropDownClosingEventArgs e) + { + //always dismiss this so we don't collapse the dropdown when the user clicks @ design time + e.Cancel = (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked); + } + + /// + /// When DropDown is disposed; nullify the dropDown. + /// + private void OnDropDownDisposed(object sender, EventArgs e) + { + if (MenuItem != null) + { + if (MenuItem.DropDown != null) + { + MenuItem.DropDown.Disposed -= new EventHandler(OnDropDownDisposed); + } + // This is necessary when the MenuItem's DropDown property is SET to something other than the default DropDown. + MenuItem.DropDown = null; + } + } + + /// + /// When a item is added, re-arrange the elements to make sure that the templateNode is at the end.. + /// + private void OnItemAdded(object sender, ToolStripItemEventArgs e) + { + // Reshuffle the TemplateNode only for "Downward" dropdowns... + if (MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveLeft && MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveRight) + { + if (typeHereNode != null && (e.Item != typeHereNode)) + { + int currentIndexOfEditor = MenuItem.DropDown.Items.IndexOf(typeHereNode); + if (currentIndexOfEditor >= 0 && currentIndexOfEditor < MenuItem.DropDown.Items.Count - 1) + { + // we now know the editor is there, but isnt currently at the end of the line. lets add it. + MenuItem.DropDown.ItemAdded -= new ToolStripItemEventHandler(OnItemAdded); + MenuItem.DropDown.SuspendLayout(); + MenuItem.DropDown.Items.Remove(typeHereNode); + MenuItem.DropDown.Items.Add(typeHereNode); + MenuItem.DropDown.ResumeLayout(); + MenuItem.DropDown.ItemAdded += new ToolStripItemEventHandler(OnItemAdded); + } + else + { + CreatetypeHereNode(); + } + } + } + } + + /// + /// Called during Undo (this is used for DropDown Property) + /// + private void OnUndone(object source, EventArgs e) + { + if (undoingCalled) + { + // If we have Undone the SETTING of DropDown Revert back to Original state. + if (dropDownSet && MenuItem.DropDown.IsAutoGenerated) + { + ToolStrip mainStrip = GetMainToolStrip(); + if (designerHost.GetDesigner(mainStrip) is ToolStripDesigner mainStripDesigner && mainStripDesigner.CacheItems) + { + foreach (ToolStripItem item in mainStripDesigner.Items) + { + MenuItem.DropDownItems.Insert(0, item); + } + mainStripDesigner.CacheItems = false; + } + ResetGlyphs(MenuItem); + } + + // since the dropDown is closed during UnDoing .. we need to re-open the dropDown in Undone. + if (MenuItem != null && selSvc.GetComponentSelected(MenuItem)) + { + InitializeDropDown(); + MenuItem.DropDown.PerformLayout(); + } + undoingCalled = false; + dropDownSet = false; + } + // After Redo-Undo Glyphs are broken. + if (selSvc.GetComponentSelected(MenuItem) && !dropDownSetFailed) + { + InitializeDropDown(); + } + } + + /// + /// Called during Undo (this is used for DropDown Property) + /// + private void OnUndoing(object source, EventArgs e) + { + if (dummyItemAdded) + { + return; + } + if (!IsOnContextMenu && MenuItem.DropDown.Visible) + { + MenuItem.HideDropDown(); + + if (!MenuItem.DropDown.IsAutoGenerated) + { + dropDownSet = true; + ToolStrip mainStrip = GetMainToolStrip(); + if (designerHost.GetDesigner(mainStrip) is ToolStripDesigner mainStripDesigner) + { + mainStripDesigner.CacheItems = true; + mainStripDesigner.Items.Clear(); + } + } + undoingCalled = true; + } + } + + /// + /// Once a menuitem designer has selection - be sure to expand and collapse all necessary child/parent items Implements the Selection Paint Logic by adding Text to Tag property. Also Hides Unnecessary DropDowns. + /// + private void OnSelectionChanged(object sender, EventArgs e) + { + //determine if we are selected + if (MenuItem == null) + { + return; + } + + ISelectionService selectionSvc = sender as ISelectionService; + Debug.Assert(selectionSvc != null, "No Selection Service !!"); + if (selectionSvc == null) + { + return; + } + + //ALWAYS COMMIT!!! + if (commitedTemplateNode != null && commitedTemplateNode.Active) + { + commitedTemplateNode.Commit(false, false); + } + else if (typeHereTemplateNode != null && typeHereTemplateNode.Active) + { + typeHereTemplateNode.Commit(false, false); + } + if (MenuItem.Equals(selectionSvc.PrimarySelection)) + { + ArrayList origSel = ToolStripDesignerUtils.originalSelComps; + if (origSel != null) + { + ToolStripDesignerUtils.InvalidateSelection(origSel, MenuItem, MenuItem.Site, false /*shift pressed*/); + } + if (IsOnContextMenu && !MenuItem.Owner.Visible) + { + ToolStripDropDown firstDropDown = GetFirstDropDown(MenuItem); + ToolStripDropDownDesigner firstDropDownDesigner = designerHost.GetDesigner(firstDropDown) as ToolStripDropDownDesigner; + if (firstDropDownDesigner != null) + { + InitializeDropDown(); + firstDropDownDesigner.ShowMenu(); + firstDropDownDesigner.AddSelectionGlyphs(); + } + } + else + { + InitializeDropDown(); + } + + //Cache original selection + ICollection originalSelComps = null; + if (selSvc != null) + { + originalSelComps = selectionSvc.GetSelectedComponents(); + } + + // Add the TemplateNode to the Selection if it is currently Selected as the GetSelectedComponents wont do it for us. + origSel = new ArrayList(originalSelComps); + if (origSel.Count == 0) + { + if (KeyboardHandlingService != null && KeyboardHandlingService.SelectedDesignerControl != null) + { + origSel.Add(KeyboardHandlingService.SelectedDesignerControl); + } + } + + if (origSel.Count > 0) + { + ToolStripDesignerUtils.originalSelComps = origSel; + } + } + else + { + object selectedObj = ((ISelectionService)sender).PrimarySelection; + if (selectedObj == null) + { + if (KeyboardHandlingService != null) + { + selectedObj = KeyboardHandlingService.SelectedDesignerControl; + } + } + if (selectedObj is ToolStripItem currentSelection) + { + ToolStripDropDown parent = currentSelection.Owner as ToolStripDropDown; + while (parent != null) + { + if (parent.OwnerItem == MenuItem || parent.OwnerItem == null) + { + return; + } + else + { + parent = ((ToolStripItem)(parent.OwnerItem)).Owner as ToolStripDropDown; + } + } + } + if (MenuItem.DropDown.Visible) + { + // CASE : Check if the DropDown Selected is the one assigned to this MenuItem's DropDown property. If MenuItem.DropDown matches the currentSelection or is the First Dropdown of any selection THEN return + if (selectedObj is ToolStripDropDown selectedDropDown && MenuItem.DropDown == selectedDropDown) + { + return; + } + else + { + // Any ToolStripItem on the DropDown OR any of its Child DropDowns + ToolStripItem item = selectedObj as ToolStripItem; + if (item != null) + { + ToolStripDropDown parent = item.Owner as ToolStripDropDown; + while (parent != null) + { + if (parent == MenuItem.DropDown) + { + return; + } + else + { + parent = ((ToolStripItem)(parent.OwnerItem)).Owner as ToolStripDropDown; + } + } + } + } + // Close your own dropDown... + if (MenuItem.DropDown.OwnerItem == MenuItem) + { + MenuItem.HideDropDown(); + } + } + } + } + + /// + /// Allows a designer to filter the set of properties the component it is designing will expose through the TypeDescriptor object. This method is called immediately before its corresponding "Post" method. If you are overriding this method you should call the base implementation before you perform your own filtering. + /// + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + // Handle shadowed properties + string[] shadowProps = new string[] { "Visible", "DoubleClickEnabled", "CheckOnClick", "DropDown" }; + PropertyDescriptor prop; + Attribute[] empty = new Attribute[0]; + for (int i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ToolStripMenuItemDesigner), prop, empty); + } + } + } + + // + // Resets the ToolStripMenuItem DoubleClickEnabled to be the default visible + // + private void ResetDoubleClickEnabled() => DoubleClickEnabled = false; + + // + // Resets the ToolStripMenuItem CheckOnClick to be the default visible + // + private void ResetCheckOnClick() => CheckOnClick = false; + + // + // Resets the ToolStripMenuItem CheckOnClick to be the default visible + // + private void ResetDropDown() => DropDown = null; + + // + // Resets the ToolStripMenuItem Visible to be the default visible + // + private void ResetVisible() => Visible = true; + + // + // Restores the ToolStripMenuItem Visible to be the value set in the property grid. + // + private void RestoreVisible() => MenuItem.Visible = Visible; + + // + // Removes the TypeHere node when the DropDownCloses. + // + internal void RemoveTypeHereNode(ToolStripDropDownItem ownerItem) + { + //This will cause the DropDown to Relayout so that during the DropDownClosed event we wont have proper Bounds to Invalidate the ToolStripAdorner... So for this case do it here... + Rectangle bounds = ownerItem.DropDown.Bounds; + if (ownerItem.DropDownItems.Count > 0 && ownerItem.DropDownItems[0] is DesignerToolStripControlHost) + { + ownerItem.DropDownItems.RemoveAt(0); + } + if (typeHereTemplateNode != null && typeHereTemplateNode.Active) + { + typeHereTemplateNode.RollBack(); + typeHereTemplateNode.CloseEditor(); + typeHereTemplateNode = null; + } + if (typeHereNode != null) + { + typeHereNode.Dispose(); + typeHereNode = null; + } + if (toolStripAdornerWindowService != null) + { + toolStripAdornerWindowService.Invalidate(bounds); + } + } + + /// + /// This private function is called to ROLLBACK the current Insitu editing mode. + /// + private void RollBack() + { + if (commitedEditorNode != null) + { + int index = MenuItem.DropDownItems.IndexOf(commitedEditorNode); + Debug.Assert(index != -1, "Invalid Index"); + ToolStripDropDownItem editedItem = (ToolStripDropDownItem)MenuItem.DropDownItems[index + 1]; + if (editedItem != null) + { + editedItem.Visible = true; + } + MenuItem.DropDown.Items.Remove(commitedEditorNode); + if (commitedTemplateNode != null) + { + commitedTemplateNode.RollBack(); + commitedTemplateNode.CloseEditor(); + commitedTemplateNode = null; + } + if (commitedEditorNode != null) + { + commitedEditorNode.Dispose(); + commitedEditorNode = null; + } + } + } + + /// + /// Remove Body glyphs when the dropDown is closed. + /// + private void RemoveBodyGlyphs(ToolStripDropDownItem item) + { + if (item != null) + { + foreach (ToolStripItem ddItem in item.DropDownItems) + { + ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(ddItem); + if (dropDownItemDesigner != null) + { + ControlBodyGlyph glyph = dropDownItemDesigner.bodyGlyph; + if (glyph != null && toolStripAdornerWindowService != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(glyph)) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(glyph); + dropDownItemDesigner.bodyGlyph = null; + } + } + } + } + } + + /// + /// Remove glyphs per item + /// + internal void RemoveItemBodyGlyph(ToolStripItem item) + { + if (item != null) + { + ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(item); + if (itemDesigner != null) + { + ControlBodyGlyph glyph = itemDesigner.bodyGlyph; + if (glyph != null && toolStripAdornerWindowService != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(glyph)) + { + toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(glyph); + itemDesigner.bodyGlyph = null; + } + } + } + } + + /// + /// Helper function to remove and then re-add the glyphs. + /// + internal void ResetGlyphs(ToolStripDropDownItem item) + { + //Reset the glyphs only if the DropDown is visible. + if (item.DropDown.Visible) + { + InitializeBodyGlyphsForItems(false, item); + InitializeBodyGlyphsForItems(true, item); + } + } + + /// + /// Set the Selection after a insitu edit is complete. + /// + internal override bool SetSelection(bool enterKeyPressed) + { + if (enterKeyPressed) + { + if (!initialized) + { + InitializeDropDown(); + } + //set the selection to our new item + if (selSvc != null) + { + if (KeyboardHandlingService != null) + { + int count = 0; + if (MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveLeft && MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveRight) + { + // index to the last item. + count = MenuItem.DropDownItems.Count; + count--; + } + selSvc.SetSelectedComponents(new object[] { MenuItem }, SelectionTypes.Replace); + if (count >= 0) + { + KeyboardHandlingService.SelectedDesignerControl = MenuItem.DropDownItems[count]; + selSvc.SetSelectedComponents(null, SelectionTypes.Replace); + } + } + } + return true; + } + return false; + } + + /// + /// Returns true if the visible property should be persisted in code gen. + /// + private bool ShouldSerializeDoubleClickEnabled() => (bool)ShadowProperties["DoubleClickEnabled"]; + + /// + /// Returns true if the CheckOnClick property should be persisted in code gen. + /// + private bool ShouldSerializeCheckOnClick() => (bool)ShadowProperties["CheckOnClick"]; + + /// + /// Returns true if the CheckOnClick property should be persisted in code gen. + /// + private bool ShouldSerializeDropDown() => (customDropDown != null); + + /// + /// Returns true if the visible property should be persisted in code gen. + /// + private bool ShouldSerializeVisible() => !Visible; + + /// + /// This Function is called thru the ToolStripEditorManager which is listening for the F2 command. + /// + internal override void ShowEditNode(bool clicked) + { + if (MenuItem == null) + { + return; + } + try + { + if (MenuItem.Owner is ToolStripDropDown) + { + parentItem = ((ToolStripDropDown)(MenuItem.Owner)).OwnerItem; + //need to inform the owner tha we want to enter insitu mode + if (designerHost != null) + { + IDesigner designer = designerHost.GetDesigner(parentItem); + if (designer is ToolStripMenuItemDesigner) + { + ((ToolStripMenuItemDesigner)designer).EnterInSituEdit(MenuItem); + } + } + } + // We come here for TOP LEVEL MENUITEM .. So call base version... + else + { + base.ShowEditNode(clicked); + } + } + catch (CheckoutException checkoutException) + { + // Do not crash on canceled checkout + if (checkoutException.Equals(CheckoutException.Canceled)) + { + return; + } + else + { + throw; + } + } + } + + /// + /// This Function would select all items starting form oldSelection to the Current MenuItem. + /// + private void SelectItems(ToolStripDropDownItem oldSelection, ISelectionService selSvc) + { + ToolStripDropDown ownerDropDown = (ToolStripDropDown)MenuItem.Owner; + int maxIndex = Math.Max(ownerDropDown.Items.IndexOf(oldSelection), ownerDropDown.Items.IndexOf(MenuItem)); + int minIndex = Math.Min(ownerDropDown.Items.IndexOf(oldSelection), ownerDropDown.Items.IndexOf(MenuItem)); + ToolStripItem[] selectedItems = new ToolStripItem[maxIndex - minIndex + 1]; + int i = 0; + while (minIndex <= maxIndex) + { + selectedItems[i] = ownerDropDown.Items[minIndex]; + i++; + minIndex++; + } + selSvc.SetSelectedComponents(selectedItems); + + } + + /// + /// Shows ALL the owner DropDowns if passed in MenuItem is Selected + /// + internal void ShowOwnerDropDown(ToolStripDropDownItem currentSelection) + { + // We MIGHT HAVE TO START TOP - DOWN Instead of BOTTOM-UP. Sometimes we DONT get the Owner POPUP and hence all the popup are parented to Wrong guy. + while (currentSelection != null && currentSelection.Owner is ToolStripDropDown) + { + ToolStripDropDown currentDropDown = (ToolStripDropDown)(currentSelection.Owner); + currentSelection = (ToolStripDropDownItem)currentDropDown.OwnerItem; + if (currentSelection != null && !currentSelection.DropDown.Visible) + { + ToolStripMenuItemDesigner currentSelectionDesigner = designerHost.GetDesigner(currentSelection) as ToolStripMenuItemDesigner; + if (currentSelectionDesigner != null) + { + currentSelectionDesigner.InitializeDropDown(); + } + } + else if (currentDropDown is ContextMenuStrip && !currentDropDown.Visible) + { + // ContextMenuStrip does not have an owner item, and need be shown with different method + ToolStripDropDownDesigner dropDownDesigner = (ToolStripDropDownDesigner)designerHost.GetDesigner(currentDropDown); + if (dropDownDesigner != null) + { + dropDownDesigner.ShowMenu(null); + } + } + } + } + + /// + /// This will listen to the necessary dropDown events... now we add the events on selection and unhook when the dropDown is closed. + /// + internal void UnHookEvents() + { + if (MenuItem != null) + { + MenuItem.DropDown.Closing -= new ToolStripDropDownClosingEventHandler(OnDropDownClosing); + MenuItem.DropDownOpening -= new EventHandler(DropDownItem_DropDownOpening); + MenuItem.DropDownOpened -= new EventHandler(DropDownItem_DropDownOpened); + MenuItem.DropDownClosed -= new EventHandler(DropDownItem_DropDownClosed); + MenuItem.DropDown.Resize -= new EventHandler(DropDownResize); + MenuItem.DropDown.ItemAdded -= new ToolStripItemEventHandler(OnItemAdded); + MenuItem.DropDown.Paint -= new PaintEventHandler(DropDownPaint); + MenuItem.DropDown.LocationChanged -= new EventHandler(DropDownLocationChanged); + MenuItem.DropDown.Click -= new EventHandler(DropDownClick); + } + } + + /// + /// The glyph we put over the items. Basically this sets the hit-testable area of the item itself. + /// + internal class ToolStripDropDownGlyph : Glyph + { + private Rectangle _bounds; + internal ToolStripDropDownGlyph(Rectangle bounds, System.Windows.Forms.Design.Behavior.Behavior b) : base(b) + { + _bounds = bounds; + } + + /// + /// Abstract method that forces Glyph implementations to provide hit test logic. Given any point - if the Glyph has decided to be involved with that location, the Glyph will need to return a valid Cursor. Otherwise, returning null will cause the the BehaviorService to simply ignore it. + /// + public override Cursor GetHitTest(Point p) + { + if (_bounds.Contains(p)) + { + return Cursors.Default; + } + return null; + } + + /// + /// Overrides Glyph::Paint - this implementation does nothing. + /// + public override void Paint(PaintEventArgs pe) + { + } + } + + /// + /// The transparent behavior on top of the DropDownGlyphs. + /// + internal class DropDownBehavior : ControlDesigner.TransparentBehavior + { + /// + /// Constructor that accepts the related ControlDesigner. + /// + private ToolStripMenuItemDesigner menuItemDesigner; + + internal DropDownBehavior(ControlDesigner designer, ToolStripMenuItemDesigner menuItemDesigner) : base(designer) + { + this.menuItemDesigner = menuItemDesigner; + } + + /// + /// Drag drop support on the DropDown... + /// + public override void OnDragEnter(Glyph g, DragEventArgs e) + { + ToolStripItemDataObject data = e.Data as ToolStripItemDataObject; + if (data != null) + { + e.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move; + } + else + { + base.OnDragEnter(g, e); + } + } + + /// + /// Drag drop support on the DropDown... + /// + public override void OnDragOver(Glyph g, DragEventArgs e) + { + ToolStripItemDataObject data = e.Data as ToolStripItemDataObject; + if (data != null) + { + e.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move; + } + else + { + base.OnDragOver(g, e); + } + } + + /// + /// Drag drop support on the DropDown... + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + public override void OnDragDrop(Glyph g, DragEventArgs e) + { + ToolStripItemDataObject data = e.Data as ToolStripItemDataObject; + if (data != null) + { + ToolStripItem primaryItem = data.PrimarySelection; + IDesignerHost host = (IDesignerHost)primaryItem.Site.GetService(typeof(IDesignerHost)); + ToolStripDropDown parentToolStrip = primaryItem.GetCurrentParent() as ToolStripDropDown; + ToolStripDropDownItem ownerItem = null; + if (parentToolStrip != null) + { + ownerItem = parentToolStrip.OwnerItem as ToolStripDropDownItem; + } + Debug.Assert(ownerItem != null, "How can ownerItem be null for a menu item on a dropdown?"); + if (ownerItem != null && host != null) + { + string transDesc; + ArrayList components = data.DragComponents; + int primaryIndex = -1; + bool copy = (e.Effect == DragDropEffects.Copy); + if (components.Count == 1) + { + string name = TypeDescriptor.GetComponentName(components[0]); + if (name == null || name.Length == 0) + { + name = components[0].GetType().Name; + } + transDesc = string.Format(copy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name); + } + else + { + transDesc = string.Format(copy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, components.Count); + } + // create a transaction so this happens as an atomic unit. + DesignerTransaction changeParent = host.CreateTransaction(transDesc); + try + { + IComponentChangeService changeSvc = (IComponentChangeService)primaryItem.Site.GetService(typeof(IComponentChangeService)); + if (changeSvc != null) + changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + // If we are copying, then we want to make a copy of the components we are dragging + if (copy) + { + // Remember the primary selection if we had one + if (primaryItem != null) + { + primaryIndex = components.IndexOf(primaryItem); + } + ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)primaryItem.Site.GetService(typeof(ToolStripKeyboardHandlingService)); + if (keyboardHandlingService != null) + { + keyboardHandlingService.CopyInProgress = true; + } + components = DesignerUtils.CopyDragObjects(components, primaryItem.Site) as ArrayList; + + if (keyboardHandlingService != null) + { + keyboardHandlingService.CopyInProgress = false; + } + if (primaryIndex != -1) + { + primaryItem = components[primaryIndex] as ToolStripItem; + } + } + + if (e.Effect == DragDropEffects.Move || copy) + { + // Add the item. + foreach (ToolStripItem toolItem in components) + { + parentToolStrip.Items.Add(toolItem); + } + + // Open the DropDown for the PrimarySelection before the DRAG-DROP operation. + if (primaryItem is ToolStripDropDownItem dropDownItem) + { + if (host.GetDesigner(dropDownItem) is ToolStripMenuItemDesigner dropDownItemDesigner) + { + dropDownItemDesigner.InitializeDropDown(); + } + } + //Set the Selection .. + menuItemDesigner.selSvc.SetSelectedComponents(new IComponent[] { primaryItem }, SelectionTypes.Primary | SelectionTypes.Replace); + } + if (changeSvc != null) + { + changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + + //fire extra changing/changed events so that the order is "restored" after undo/redo + if (copy) + { + if (changeSvc != null) + { + changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]); + changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null); + } + } + + //If Parent is DropDown... we have to manage the Glyphs .... + if (ownerItem != null) + { + if (host.GetDesigner(ownerItem) is ToolStripMenuItemDesigner ownerDesigner) + { + ownerDesigner.InitializeBodyGlyphsForItems(false, ownerItem); + ownerDesigner.InitializeBodyGlyphsForItems(true, ownerItem); + } + } + // Refresh the BehaviorService. + BehaviorService bSvc = (BehaviorService)primaryItem.Site.GetService(typeof(BehaviorService)); + if (bSvc != null) + { + bSvc.SyncSelection(); + } + } + catch + { + if (changeParent != null) + { + changeParent.Cancel(); + changeParent = null; + } + } + finally + { + if (changeParent != null) + changeParent.Commit(); + changeParent = null; + } + } + } + } + } + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripTemplateNode.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripTemplateNode.cs new file mode 100644 index 00000000000..d222587faf4 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ToolStripTemplateNode.cs @@ -0,0 +1,2045 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms.Design.Behavior; +using static System.Windows.Forms.UnsafeNativeMethods; + +namespace System.Windows.Forms.Design +{ + /// + /// This internal class wraps the InSitu Editor. The editor is a runtime ToolStrip control which contains a leftButton (for image), centerLabel (for text) which gets swaped by a centerTextBox (when InSitu is ON). The ToolStripTemplateNode is also responsible for intercepting the Escape and Enter keys and implements the IMenuStatusHandler so that it can commit and rollback as required. Finally this ToolStripTemplateNode has a private class ItemTypeToolStripMenuItem for adding ToolStripItem types to the Dropdown for addItemButton. + /// + internal class ToolStripTemplateNode : IMenuStatusHandler + { + private const int GLYPHBORDER = 1; + private const int GLYPHINSET = 2; + + private const int TOOLSTRIP_TEMPLATE_HEIGHT_ORIGINAL = 22; + private const int TEMPLATE_HEIGHT_ORIGINAL = 19; + private const int TOOLSTRIP_TEMPLATE_WIDTH_ORIGINAL = 120; + private const int TEMPLATE_WIDTH_ORIGINAL = 31; + private const int MINITOOLSTRIP_DROPDOWN_BUTTON_WIDTH_ORIGINAL = 11; + private const int TEMPLATE_HOTREGION_WIDTH_ORIGINAL = 9; + private const int MINITOOLSTRIP_TEXTBOX_WIDTH_ORIGINAL = 90; + + private static int TOOLSTRIP_TEMPLATE_HEIGHT = TOOLSTRIP_TEMPLATE_HEIGHT_ORIGINAL; + private static int TEMPLATE_HEIGHT = TEMPLATE_HEIGHT_ORIGINAL; + private static int TOOLSTRIP_TEMPLATE_WIDTH = TOOLSTRIP_TEMPLATE_WIDTH_ORIGINAL; + private static int TEMPLATE_WIDTH = TEMPLATE_WIDTH_ORIGINAL; + private static int MINITOOLSTRIP_DROPDOWN_BUTTON_WIDTH = MINITOOLSTRIP_DROPDOWN_BUTTON_WIDTH_ORIGINAL; + private static int TEMPLATE_HOTREGION_WIDTH = TEMPLATE_HOTREGION_WIDTH_ORIGINAL; + private static int MINITOOLSTRIP_TEXTBOX_WIDTH = MINITOOLSTRIP_TEXTBOX_WIDTH_ORIGINAL; + + private static bool s_isScalingInitialized = false; + internal const string CenterLabelName = "centerLabel"; + + // Component for this InSitu Editor... (this is a ToolStripItem) that wants to go into InSitu + private readonly IComponent _component; + // Current Designer for the comopenent that in InSitu mode + private IDesigner _designer = null; + //Get DesignerHost. + private readonly IDesignerHost _designerHost = null; + // Menu Commands to override + private readonly MenuCommand[] _commands; + // MenuCommands to Add + private readonly MenuCommand[] _addCommands; + // Actual InSitu Editor and its components... + private TransparentToolStrip _miniToolStrip; + // Center Label for MenuStrip TemplateNode + private ToolStripLabel _centerLabel; + // SplitButton reAdded for ToolStrip specific TemplateNode + private ToolStripSplitButton _addItemButton; + //swaped in text... + private ToolStripControlHost _centerTextBox; + + //reqd as rtb does accept Enter.. + internal bool ignoreFirstKeyUp = false; + + // This is the Bounding Rectangle for the ToolStripTemplateNode. This is set by the itemDesigner in terms of the "AdornerWindow" bounds. The ToolStripEditorManager uses this Bounds to actually activate the editor on the AdornerWindow. + private Rectangle _boundingRect; + // Keeps track of Insitu Mode. + private bool _inSituMode = false; + // Tells whether the editorNode is listening to Menu commands. + private bool _active = false; + + // Need to keep a track of Last Selection to uncheck it. This is the Checked property on ToolStripItems on the Menu. We check this cached in value to the current Selection on the addItemButton and if different then uncheck the Checked for this lastSelection.. Check for the currentSelection and finally save the currentSelection as the lastSelection for future check. + private ItemTypeToolStripMenuItem _lastSelection = null; + + // This is the renderer used to Draw the Strips..... + private MiniToolStripRenderer _renderer; + // This is the Type that the user has selected for the new Item + private Type _itemType; + //Get the ToolStripKeyBoardService to notify that the TemplateNode is Active and so it shouldnt process the KeyMessages. + private ToolStripKeyboardHandlingService _toolStripKeyBoardService; + + //Cached ISelectionService + private ISelectionService _selectionService; + //Cached BehaviorService + private BehaviorService _behaviorService; + //ControlHost for selection on mouseclicks + private DesignerToolStripControlHost _controlHost = null; + // On DropDowns the component passed in is the parent (ownerItem) and hence we need the reference for actual item + private ToolStripItem _activeItem = null; + + private EventHandler _onActivated; + private EventHandler _onClosed; + private EventHandler _onDeactivated; + private MenuCommand _oldUndoCommand = null; + private MenuCommand _oldRedoCommand = null; + // The DropDown for the TemplateNode + private NewItemsContextMenuStrip _contextMenu; + // the Hot Region within the templateNode ... this is used for the menustrips + private Rectangle _hotRegion; + + private bool _imeModeSet = false; + //DesignSurface to hook up to the Flushed event + private DesignSurface _designSurface = null; + // Is system context menu displayed for the insitu text box? + private bool _isSystemContextMenuDisplayed = false; + // delay population of custom menu items until ready to open the drop down + private bool _isPopulated; + + public ToolStripTemplateNode(IComponent component, string text, Image image) + { + _component = component; + // In most of the cases this is true; except for ToolStripItems on DropDowns. the toolstripMenuItemDesigners sets the public property in those cases. + _activeItem = component as ToolStripItem; + _designerHost = (IDesignerHost)component.Site.GetService(typeof(IDesignerHost)); + _designer = _designerHost.GetDesigner(component); + _designSurface = (DesignSurface)component.Site.GetService(typeof(DesignSurface)); + if (_designSurface != null) + { + _designSurface.Flushed += new EventHandler(OnLoaderFlushed); + } + + if (!s_isScalingInitialized) + { + if (DpiHelper.IsScalingRequired) + { + // dimensions of the "Type Here" text box + TOOLSTRIP_TEMPLATE_HEIGHT = DpiHelper.LogicalToDeviceUnitsY(TOOLSTRIP_TEMPLATE_HEIGHT_ORIGINAL); + TEMPLATE_HEIGHT = DpiHelper.LogicalToDeviceUnitsY(TEMPLATE_HEIGHT_ORIGINAL); + TOOLSTRIP_TEMPLATE_WIDTH = DpiHelper.LogicalToDeviceUnitsX(TOOLSTRIP_TEMPLATE_WIDTH_ORIGINAL); + TEMPLATE_WIDTH = DpiHelper.LogicalToDeviceUnitsX(TEMPLATE_WIDTH_ORIGINAL); + //hotregion is the arrow button next to "Type Here" box + TEMPLATE_HOTREGION_WIDTH = DpiHelper.LogicalToDeviceUnitsX(TEMPLATE_HOTREGION_WIDTH_ORIGINAL); + + MINITOOLSTRIP_DROPDOWN_BUTTON_WIDTH = DpiHelper.LogicalToDeviceUnitsX(MINITOOLSTRIP_DROPDOWN_BUTTON_WIDTH_ORIGINAL); + MINITOOLSTRIP_TEXTBOX_WIDTH = DpiHelper.LogicalToDeviceUnitsX(MINITOOLSTRIP_TEXTBOX_WIDTH_ORIGINAL); + } + s_isScalingInitialized = true; + } + + SetupNewEditNode(this, text, image, component); + _commands = new MenuCommand[] { }; + _addCommands = new MenuCommand[] { }; + } + + /// + /// This property enables / disables Menu Command Handler. + /// + public bool Active + { + get => _active; + set + { + if (_active != value) + { + _active = value; + + if (KeyboardService != null) + { + KeyboardService.TemplateNodeActive = value; + } + + if (_active) + { + //Active.. Fire Activated + OnActivated(new EventArgs()); + if (KeyboardService != null) + { + KeyboardService.ActiveTemplateNode = this; + } + + IMenuCommandService menuService = (IMenuCommandService)_component.Site.GetService(typeof(IMenuCommandService)); + if (menuService != null) + { + _oldUndoCommand = menuService.FindCommand(MenuCommands.Undo); + if (_oldUndoCommand != null) + { + menuService.RemoveCommand(_oldUndoCommand); + } + + _oldRedoCommand = menuService.FindCommand(MenuCommands.Redo); + if (_oldRedoCommand != null) + { + menuService.RemoveCommand(_oldRedoCommand); + } + + // Disable the Commands + for (int i = 0; i < _addCommands.Length; i++) + { + _addCommands[i].Enabled = false; + menuService.AddCommand(_addCommands[i]); + } + } + + // Listen to command and key events + IEventHandlerService ehs = (IEventHandlerService)_component.Site.GetService(typeof(IEventHandlerService)); + if (ehs != null) + { + ehs.PushHandler(this); + } + } + else + { + OnDeactivated(new EventArgs()); + if (KeyboardService != null) + { + KeyboardService.ActiveTemplateNode = null; + } + + IMenuCommandService menuService = (IMenuCommandService)_component.Site.GetService(typeof(IMenuCommandService)); + if (menuService != null) + { + for (int i = 0; i < _addCommands.Length; i++) + { + menuService.RemoveCommand(_addCommands[i]); + } + } + + if (_oldUndoCommand != null) + { + menuService.AddCommand(_oldUndoCommand); + } + + if (_oldRedoCommand != null) + { + menuService.AddCommand(_oldRedoCommand); + } + + // Stop listening to command and key events + IEventHandlerService ehs = (IEventHandlerService)_component.Site.GetService(typeof(IEventHandlerService)); + if (ehs != null) + { + ehs.PopHandler(this); + } + } + } + } + } + + // Need to have a reference of the actual item that is edited. + public ToolStripItem ActiveItem + { + get => _activeItem; + set => _activeItem = value; + } + + public event EventHandler Activated + { + add => _onActivated += value; + remove => _onActivated -= value; + } + + /// + /// Returns the Bounds of this ToolStripTemplateNode. + /// + public Rectangle Bounds + { + get => _boundingRect; + set => _boundingRect = value; + } + + public DesignerToolStripControlHost ControlHost + { + get => _controlHost; + set => _controlHost = value; + } + + /// + /// This is the designer contextMenu that pops when rightclicked on the TemplateNode. + /// + private ContextMenuStrip DesignerContextMenu + { + get + { + BaseContextMenuStrip templateNodeContextMenu = new BaseContextMenuStrip(_component.Site, _controlHost) + { + Populated = false + }; + templateNodeContextMenu.GroupOrdering.Clear(); + templateNodeContextMenu.GroupOrdering.AddRange(new string[] { StandardGroups.Code, StandardGroups.Custom, StandardGroups.Selection, StandardGroups.Edit }); + templateNodeContextMenu.Text = "CustomContextMenu"; + + TemplateNodeCustomMenuItemCollection templateNodeCustomMenuItemCollection = new TemplateNodeCustomMenuItemCollection(_component.Site, _controlHost); + foreach (ToolStripItem item in templateNodeCustomMenuItemCollection) + { + templateNodeContextMenu.Groups[StandardGroups.Custom].Items.Add(item); + } + return templateNodeContextMenu; + } + } + + public event EventHandler Deactivated + { + add => _onDeactivated += value; + remove => _onDeactivated -= value; + } + + public event EventHandler Closed + { + add => _onClosed += value; + remove => _onClosed -= value; + } + + /// + /// This property returns the actual editor ToolStrip. + /// + public ToolStrip EditorToolStrip + { + get => _miniToolStrip; + } + + /// + /// This property returns the actual editor ToolStrip. + /// + internal TextBox EditBox + { + get => (_centerTextBox != null) ? (TextBox)_centerTextBox.Control : null; + } + + /// + /// HotRegion within the templateNode. this is the region which responds to the mouse. + /// + public Rectangle HotRegion + { + get => _hotRegion; + set => _hotRegion = value; + } + + /// + /// value to suggest if IME mode is set. + /// + public bool IMEModeSet + { + get => _imeModeSet; + set => _imeModeSet = value; + } + + /// + /// KeyBoardHandling service. + /// + private ToolStripKeyboardHandlingService KeyboardService + { + get + { + if (_toolStripKeyBoardService == null) + { + _toolStripKeyBoardService = (ToolStripKeyboardHandlingService)_component.Site.GetService(typeof(ToolStripKeyboardHandlingService)); + } + return _toolStripKeyBoardService; + } + } + + /// + /// SelectionService. + /// + private ISelectionService SelectionService + { + get + { + if (_selectionService == null) + { + _selectionService = (ISelectionService)_component.Site.GetService(typeof(ISelectionService)); + } + return _selectionService; + } + } + + + private BehaviorService BehaviorService + { + get + { + if (_behaviorService == null) + { + _behaviorService = (BehaviorService)_component.Site.GetService(typeof(BehaviorService)); + } + return _behaviorService; + } + } + + /// + /// Type of the new Item to be added. + /// + public Type ToolStripItemType + { + get => _itemType; + set => _itemType = value; + } + + /// + /// Is system context menu for the insitu edit box displayed?. + /// + internal bool IsSystemContextMenuDisplayed + { + get => _isSystemContextMenuDisplayed; + set => _isSystemContextMenuDisplayed = value; + } + + /// + /// Helper function to add new Item when the DropDownItem (in the ToolStripTemplateNode) is clicked + /// + private void AddNewItemClick(object sender, EventArgs e) + { + // Close the DropDown.. Important for Morphing .... + if (_addItemButton != null) + { + _addItemButton.DropDown.Visible = false; + } + + if (_component is ToolStrip && SelectionService != null) + { + // Stop the Designer from closing the Overflow if its open + ToolStripDesigner designer = _designerHost.GetDesigner(_component) as ToolStripDesigner; + try + { + if (designer != null) + { + designer.DontCloseOverflow = true; + } + SelectionService.SetSelectedComponents(new object[] { _component }); + } + finally + { + if (designer != null) + { + designer.DontCloseOverflow = false; + } + } + } + + ItemTypeToolStripMenuItem senderItem = (ItemTypeToolStripMenuItem)sender; + if (_lastSelection != null) + { + _lastSelection.Checked = false; + } + + // set the appropriate Checked state + senderItem.Checked = true; + _lastSelection = senderItem; + // Set the property used in the CommitEditor (.. ) to add the correct Type. + ToolStripItemType = senderItem.ItemType; + //Select the parent before adding + ToolStrip parent = _controlHost.GetCurrentParent() as ToolStrip; + // this will add the item to the ToolStrip.. + if (parent is MenuStrip) + { + CommitEditor(true, true, false); + } + else + { + // In case of toolStrips/StatusStrip we want the currently added item to be selected instead of selecting the next item + CommitEditor(true, false, false); + } + + if (KeyboardService != null) + { + KeyboardService.TemplateNodeActive = false; + } + } + + /// + /// Called when the user clicks the CenterLabel of the ToolStripTemplateNode. + /// + private void CenterLabelClick(object sender, MouseEventArgs e) + { + //For Right Button we show the DesignerContextMenu... + if (e.Button == MouseButtons.Right) + { + //Dont show the DesignerContextMenu if there is any active templateNode. + if (KeyboardService != null && KeyboardService.TemplateNodeActive) + { + return; + } + if (KeyboardService != null) + { + KeyboardService.SelectedDesignerControl = _controlHost; + } + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + if (BehaviorService != null) + { + Point loc = BehaviorService.ControlToAdornerWindow(_miniToolStrip); + loc = BehaviorService.AdornerWindowPointToScreen(loc); + loc.Offset(e.Location); + DesignerContextMenu.Show(loc); + } + } + else + { + if (_hotRegion.Contains(e.Location) && !KeyboardService.TemplateNodeActive) + { + if (KeyboardService != null) + { + KeyboardService.SelectedDesignerControl = _controlHost; + } + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + ToolStripDropDown oldContextMenu = _contextMenu; + // PERF: Consider refresh mechanism for the derived items. + if (oldContextMenu != null) + { + oldContextMenu.Closed -= new ToolStripDropDownClosedEventHandler(OnContextMenuClosed); + oldContextMenu.Closing -= OnContextMenuClosing; + oldContextMenu.Opened -= new EventHandler(OnContextMenuOpened); + oldContextMenu.Dispose(); + } + _contextMenu = null; + ShowDropDownMenu(); + + } + else + { + // Remember the click position. + ToolStripDesigner.s_lastCursorPosition = Cursor.Position; + + if (_designer is ToolStripDesigner) + { + if (KeyboardService.TemplateNodeActive) + { + KeyboardService.ActiveTemplateNode.Commit(false, false); + } + // cause a selectionChange... + if (SelectionService.PrimarySelection == null) + { + SelectionService.SetSelectedComponents(new object[] { _component }, SelectionTypes.Replace); + } + + KeyboardService.SelectedDesignerControl = _controlHost; + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + ((ToolStripDesigner)_designer).ShowEditNode(true); + } + if (_designer is ToolStripMenuItemDesigner) + { + // cache the serviceProvider (Site) since the component can potential get disposed after the call to CommitAndSelect(); + IServiceProvider svcProvider = _component.Site as IServiceProvider; + // Commit any InsituEdit Node. + if (KeyboardService.TemplateNodeActive) + { + if (_component is ToolStripItem currentItem) + { + // We have clicked the TemplateNode of a visible Item .. so just commit the current Insitu... + if (currentItem.Visible) + { + // If templateNode Active .. commit + KeyboardService.ActiveTemplateNode.Commit(false, false); + } + else //we have clicked the templateNode of a Invisible Item ... so a dummyItem. In this case select the item. + { + // If templateNode Active .. commit and Select + KeyboardService.ActiveTemplateNode.Commit(false, true); + } + } + else //If Component is not a ToolStripItem + { + KeyboardService.ActiveTemplateNode.Commit(false, false); + } + } + if (_designer != null) + { + ((ToolStripMenuItemDesigner)_designer).EditTemplateNode(true); + } + else + { + ISelectionService cachedSelSvc = (ISelectionService)svcProvider.GetService(typeof(ISelectionService)); + if (cachedSelSvc.PrimarySelection is ToolStripItem selectedItem && _designerHost != null) + { + if (_designerHost.GetDesigner(selectedItem) is ToolStripMenuItemDesigner itemDesigner) + { + //Invalidate the item only if its toplevel. + if (!selectedItem.IsOnDropDown) + { + Rectangle bounds = itemDesigner.GetGlyphBounds(); + ToolStripDesignerUtils.GetAdjustedBounds(selectedItem, ref bounds); + if (svcProvider.GetService(typeof(BehaviorService)) is BehaviorService bSvc) + { + bSvc.Invalidate(bounds); + } + } + itemDesigner.EditTemplateNode(true); + } + } + } + } + } + } + } + + /// + /// Painting of the templateNode on MouseEnter. + /// + private void CenterLabelMouseEnter(object sender, EventArgs e) + { + if (_renderer != null && !KeyboardService.TemplateNodeActive) + { + if (_renderer.State != (int)TemplateNodeSelectionState.HotRegionSelected) + { + _renderer.State = (int)TemplateNodeSelectionState.MouseOverLabel; + _miniToolStrip.Invalidate(); + } + } + } + + /// + /// Painting of the templateNode on MouseMove + /// + private void CenterLabelMouseMove(object sender, MouseEventArgs e) + { + if (_renderer != null && !KeyboardService.TemplateNodeActive) + { + if (_renderer.State != (int)TemplateNodeSelectionState.HotRegionSelected) + { + if (_hotRegion.Contains(e.Location)) + { + _renderer.State = (int)TemplateNodeSelectionState.MouseOverHotRegion; + } + else + { + _renderer.State = (int)TemplateNodeSelectionState.MouseOverLabel; + } + _miniToolStrip.Invalidate(); + } + } + } + + /// + /// Painting of the templateNode on MouseLeave + /// + private void CenterLabelMouseLeave(object sender, EventArgs e) + { + if (_renderer != null && !KeyboardService.TemplateNodeActive) + { + if (_renderer.State != (int)TemplateNodeSelectionState.HotRegionSelected) + { + _renderer.State = (int)TemplateNodeSelectionState.None; + } + if (KeyboardService != null && KeyboardService.SelectedDesignerControl == _controlHost) + { + _renderer.State = (int)TemplateNodeSelectionState.TemplateNodeSelected; + } + _miniToolStrip.Invalidate(); + } + } + + /// + /// Painting of the templateNode on MouseEnter + /// + private void CenterTextBoxMouseEnter(object sender, EventArgs e) + { + if (_renderer != null) + { + _renderer.State = (int)TemplateNodeSelectionState.TemplateNodeSelected; + _miniToolStrip.Invalidate(); + } + } + + /// + /// Painting of the templateNode on TextBox mouseLeave (in case of MenuStrip) + /// + private void CenterTextBoxMouseLeave(object sender, EventArgs e) + { + if (_renderer != null && !Active) + { + _renderer.State = (int)TemplateNodeSelectionState.None; + _miniToolStrip.Invalidate(); + } + } + + /// + /// This Internal function is called from the ToolStripItemDesigner to relinquish the resources used by the EditorToolStrip. This Fucntion disposes the ToolStrip and its components and also clears the event handlers associated. + /// + internal void CloseEditor() + { + if (_miniToolStrip != null) + { + Active = false; + if (_lastSelection != null) + { + _lastSelection.Dispose(); + _lastSelection = null; + } + + if (_component is ToolStrip strip) + { + strip.RightToLeftChanged -= new System.EventHandler(OnRightToLeftChanged); + } + else + { + if (_component is ToolStripDropDownItem stripItem) + { + stripItem.RightToLeftChanged -= new System.EventHandler(OnRightToLeftChanged); + } + } + + if (_centerLabel != null) + { + _centerLabel.MouseUp -= new MouseEventHandler(CenterLabelClick); + _centerLabel.MouseEnter -= new EventHandler(CenterLabelMouseEnter); + _centerLabel.MouseMove -= new MouseEventHandler(CenterLabelMouseMove); + _centerLabel.MouseLeave -= new EventHandler(CenterLabelMouseLeave); + _centerLabel.Dispose(); + _centerLabel = null; + } + + if (_addItemButton != null) + { + _addItemButton.MouseMove -= new MouseEventHandler(OnMouseMove); + _addItemButton.MouseUp -= new MouseEventHandler(OnMouseUp); + _addItemButton.MouseDown -= new MouseEventHandler(OnMouseDown); + _addItemButton.DropDownOpened -= new EventHandler(OnAddItemButtonDropDownOpened); + _addItemButton.DropDown.Dispose(); + _addItemButton.Dispose(); + _addItemButton = null; + } + if (_contextMenu != null) + { + _contextMenu.Closed -= new ToolStripDropDownClosedEventHandler(OnContextMenuClosed); + _contextMenu.Closing -= OnContextMenuClosing; + _contextMenu.Opened -= new EventHandler(OnContextMenuOpened); + _contextMenu = null; + } + + _miniToolStrip.MouseLeave -= new EventHandler(OnMouseLeave); + _miniToolStrip.Dispose(); + _miniToolStrip = null; + // Surface can be null. VS Whidbey #572862 + if (_designSurface != null) + { + _designSurface.Flushed -= new EventHandler(OnLoaderFlushed); + _designSurface = null; + } + _designer = null; + OnClosed(new EventArgs()); + } + } + + /// + /// This internal Function is called by item designers to ROLLBACK the current Insitu editing mode. + /// + internal void Commit(bool enterKeyPressed, bool tabKeyPressed) + { + // Commit only if we are still available !! + if (_miniToolStrip != null && _inSituMode) + { + string text = ((TextBox)(_centerTextBox.Control)).Text; + if (string.IsNullOrEmpty(text)) + { + RollBack(); + } + else + { + CommitEditor(true, enterKeyPressed, tabKeyPressed); + } + } + } + + /// + /// Internal function that would commit the TemplateNode + /// + internal void CommitAndSelect() + { + Commit(false, false); + } + + private void CommitTextToDesigner(string text, bool commit, bool enterKeyPressed, bool tabKeyPressed) + { + if (commit && (_designer is ToolStripDesigner || _designer is ToolStripMenuItemDesigner)) + { + Type selectedType; + // If user has typed in "-" then Add a Separator only on DropDowns. + if (text == "-" && _designer is ToolStripMenuItemDesigner) + { + ToolStripItemType = typeof(ToolStripSeparator); + } + if (ToolStripItemType != null) + { + selectedType = ToolStripItemType; + ToolStripItemType = null; + } + else + { + Type[] supportedTypes = ToolStripDesignerUtils.GetStandardItemTypes(_component); + selectedType = supportedTypes[0]; + } + if (_designer is ToolStripDesigner) + { + ((ToolStripDesigner)_designer).AddNewItem(selectedType, text, enterKeyPressed, tabKeyPressed); + } + else + { + ((ToolStripItemDesigner)_designer).CommitEdit(selectedType, text, commit, enterKeyPressed, tabKeyPressed); + } + } + else if (_designer is ToolStripItemDesigner) + { + ((ToolStripItemDesigner)_designer).CommitEdit(_designer.Component.GetType(), text, commit, enterKeyPressed, tabKeyPressed); + } + } + + /// + /// This private function performs the job of commiting the current InSitu Editor. This will call the CommitEdit(...) function for the appropriate designers so that they can actually do their own Specific things for commiting (or ROLLBACKING) the Insitu Edit mode. The commit flag is used for commit or rollback. BE SURE TO ALWAYS call ExitInSituEdit from this function to put the EditorToolStrip in a sane "NON EDIT" mode. + /// + private void CommitEditor(bool commit, bool enterKeyPressed, bool tabKeyPressed) + { + // After the node is commited the templateNode gets the selection. But the original selection is not invalidated. consider following case + // FOO -> BAR -> TEMPLATENODE node + // When the TemplateNode is committed "FOO" is selected but after the commit is complete, The TemplateNode gets the selection but "FOO" is never invalidated and hence retains selection. So we get the selection and then invalidate it at the end of this function. Get the currentSelection to invalidate + string text = (_centerTextBox != null) ? ((TextBox)(_centerTextBox.Control)).Text : string.Empty; + ExitInSituEdit(); + FocusForm(); + CommitTextToDesigner(text, commit, enterKeyPressed, tabKeyPressed); + // finally Invalidate the selection rect ... + if (SelectionService.PrimarySelection is ToolStripItem curSel) + { + if (_designerHost != null) + { + if (_designerHost.GetDesigner(curSel) is ToolStripItemDesigner designer) + { + Rectangle invalidateBounds = designer.GetGlyphBounds(); + ToolStripDesignerUtils.GetAdjustedBounds(curSel, ref invalidateBounds); + invalidateBounds.Inflate(GLYPHBORDER, GLYPHBORDER); + Region rgn = new Region(invalidateBounds); + invalidateBounds.Inflate(-GLYPHINSET, -GLYPHINSET); + rgn.Exclude(invalidateBounds); + if (BehaviorService != null) + { + BehaviorService.Invalidate(rgn); + } + rgn.Dispose(); + } + } + } + } + + /// + /// The ToolStripTemplateNode enters into InSitu Edit Mode through this Function. This Function is called by FocusEditor( ) which starts the InSitu. The centerLabel is SWAPPED by centerTextBox and the ToolStripTemplateNode is Ready for Text. Settting "Active = true" pushes the IEventHandler which now intercepts the Escape and Enter keys to ROLLBACK or COMMIT the InSitu Editing respectively. + /// + private void EnterInSituEdit() + { + if (!_inSituMode) + { + // Listen For Commandss.... + if (_miniToolStrip.Parent != null) + { + _miniToolStrip.Parent.SuspendLayout(); + } + try + { + Active = true; + _inSituMode = true; + // set the renderer state to Selected... + if (_renderer != null) + { + _renderer.State = (int)TemplateNodeSelectionState.TemplateNodeSelected; + } + + // Set UP textBox for InSitu + TextBox tb = new TemplateTextBox(_miniToolStrip, this) + { + BorderStyle = BorderStyle.FixedSingle, + Text = _centerLabel.Text, + ForeColor = SystemColors.WindowText + }; + _centerTextBox = new ToolStripControlHost(tb) + { + Dock = DockStyle.None, + AutoSize = false, + Width = MINITOOLSTRIP_TEXTBOX_WIDTH + }; + + if (_activeItem is ToolStripDropDownItem item && !item.IsOnDropDown) + { + _centerTextBox.Margin = new System.Windows.Forms.Padding(1, 2, 1, 3); + } + else + { + _centerTextBox.Margin = new System.Windows.Forms.Padding(1); + } + _centerTextBox.Size = _miniToolStrip.DisplayRectangle.Size - _centerTextBox.Margin.Size; + _centerTextBox.Name = "centerTextBox"; + _centerTextBox.MouseEnter += new EventHandler(CenterTextBoxMouseEnter); + _centerTextBox.MouseLeave += new EventHandler(CenterTextBoxMouseLeave); + int index = _miniToolStrip.Items.IndexOf(_centerLabel); + //swap in our insitu textbox + if (index != -1) + { + _miniToolStrip.Items.Insert(index, _centerTextBox); + _miniToolStrip.Items.Remove(_centerLabel); + } + + tb.KeyUp += new KeyEventHandler(OnKeyUp); + tb.KeyDown += new KeyEventHandler(OnKeyDown); + tb.SelectAll(); + Control baseComponent = null; + if (_designerHost != null) + { + baseComponent = (Control)_designerHost.RootComponent; + NativeMethods.SendMessage(baseComponent.Handle, Interop.WindowMessages.WM_SETREDRAW, 0, 0); + tb.Focus(); + NativeMethods.SendMessage(baseComponent.Handle, Interop.WindowMessages.WM_SETREDRAW, 1, 0); + } + } + finally + { + if (_miniToolStrip.Parent != null) + { + _miniToolStrip.Parent.ResumeLayout(); + } + } + } + } + + /// + /// The ToolStripTemplateNode exits from InSitu Edit Mode through this Function. This Function is called by CommitEditor( ) which stops the InSitu. The centerTextBox is SWAPPED by centerLabel and the ToolStripTemplateNode is exits the InSitu Mode. Settting "Active = false" pops the IEventHandler. + /// + private void ExitInSituEdit() + { + // put the ToolStripTemplateNode back into "non edit state" + if (_centerTextBox != null && _inSituMode) + { + if (_miniToolStrip.Parent != null) + { + _miniToolStrip.Parent.SuspendLayout(); + } + try + { + //if going insitu with a real item, set & select all the text + int index = _miniToolStrip.Items.IndexOf(_centerTextBox); + //validate index + if (index != -1) + { + _centerLabel.Text = SR.ToolStripDesignerTemplateNodeEnterText; + //swap in our insitu textbox + _miniToolStrip.Items.Insert(index, _centerLabel); + _miniToolStrip.Items.Remove(_centerTextBox); + ((TextBox)(_centerTextBox.Control)).KeyUp -= new KeyEventHandler(OnKeyUp); + ((TextBox)(_centerTextBox.Control)).KeyDown -= new KeyEventHandler(OnKeyDown); + } + + _centerTextBox.MouseEnter -= new EventHandler(CenterTextBoxMouseEnter); + _centerTextBox.MouseLeave -= new EventHandler(CenterTextBoxMouseLeave); + _centerTextBox.Dispose(); + _centerTextBox = null; + _inSituMode = false; + //reset the Size.... + SetWidth(null); + } + finally + { + if (_miniToolStrip.Parent != null) + { + _miniToolStrip.Parent.ResumeLayout(); + } + // POP of the Handler !!! + Active = false; + } + } + } + + /// + /// This internal function is called from ToolStripItemDesigner to put the current item into InSitu Edit Mode. + /// + internal void FocusEditor(ToolStripItem currentItem) + { + if (currentItem != null) + { + _centerLabel.Text = currentItem.Text; + } + EnterInSituEdit(); + } + + /// + /// Called when the user enters into the InSitu edit mode.This keeps the fdesigner Form Active..... + /// + private void FocusForm() + { + if (_component.Site.GetService(typeof(ISplitWindowService)) is DesignerFrame designerFrame) + { + if (_designerHost != null) + { + Control baseComponent = (Control)_designerHost.RootComponent; + NativeMethods.SendMessage(baseComponent.Handle, Interop.WindowMessages.WM_SETREDRAW, 0, 0); + designerFrame.Focus(); + NativeMethods.SendMessage(baseComponent.Handle, Interop.WindowMessages.WM_SETREDRAW, 1, 0); + } + } + } + + protected void OnActivated(EventArgs e) + { + _onActivated?.Invoke(this, e); + } + + private void OnAddItemButtonDropDownOpened(object sender, EventArgs e) + { + _addItemButton.DropDown.Focus(); + } + + protected void OnClosed(EventArgs e) + { + _onClosed?.Invoke(this, e); + } + + /// + /// Painting of the templateNode on when the contextMenu is closed + /// + private void OnContextMenuClosed(object sender, ToolStripDropDownClosedEventArgs e) + { + if (_renderer != null) + { + _renderer.State = (int)TemplateNodeSelectionState.TemplateNodeSelected; + _miniToolStrip.Invalidate(); + } + } + + private void OnContextMenuClosing(object sender, ToolStripDropDownClosingEventArgs e) + { + if (_addItemButton == null) + { + _miniToolStrip.RaiseStateChangeEvent(); + } + } + + /// + /// Set the KeyBoardService member, so the designer knows that the "ContextMenu" is opened. + /// + private void OnContextMenuOpened(object sender, EventArgs e) + { + // Disable All Commands .. the Commands would be reenabled by AddNewItemClick call. + if (KeyboardService != null) + { + KeyboardService.TemplateNodeContextMenuOpen = true; + } + } + + protected void OnDeactivated(EventArgs e) + { + _onDeactivated?.Invoke(this, e); + } + + /// + /// Called by the design surface when it is being flushed. This will save any changes made to TemplateNode. + /// + private void OnLoaderFlushed(object sender, EventArgs e) + { + Commit(false, false); + } + + /// + /// This is small HACK. For some reason if the InSituEditor's textbox has focus the escape key is lost and the menu service doesnt get it.... but the textbox gets it. So need to check for the escape key here and call CommitEditor(false) which will ROLLBACK the edit. + /// + private void OnKeyUp(object sender, KeyEventArgs e) + { + if (IMEModeSet) + { + return; + } + switch (e.KeyCode) + { + + case Keys.Up: + Commit(false, true); + if (KeyboardService != null) + { + KeyboardService.ProcessUpDown(false); + } + break; + case Keys.Down: + Commit(true, false); + break; + case Keys.Escape: + CommitEditor(false, false, false); + break; + case Keys.Return: + if (ignoreFirstKeyUp) + { + ignoreFirstKeyUp = false; + return; + } + OnKeyDefaultAction(sender, e); + break; + } + } + + /// + /// Select text on KeyDown. + /// + private void OnKeyDown(object sender, KeyEventArgs e) + { + if (IMEModeSet) + { + return; + } + if (e.KeyCode == Keys.A && (e.KeyData & Keys.Control) != 0) + { + if (sender is TextBox t) + { + t.SelectAll(); + } + } + } + + /// + /// Check for the Enter key here and call CommitEditor(true) which will COMMIT the edit. + /// + private void OnKeyDefaultAction(object sender, EventArgs e) + { + //exit Insitu with commiting.... + Active = false; + Debug.Assert(_centerTextBox.Control != null, "The TextBox is null"); + if (_centerTextBox.Control != null) + { + string text = ((TextBox)(_centerTextBox.Control)).Text; + if (string.IsNullOrEmpty(text)) + { + CommitEditor(false, false, false); + } + else + { + CommitEditor(true, true, false); + } + } + } + + /// + /// Called when the delete menu item is selected. + /// + private void OnMenuCut(object sender, EventArgs e) + { + } + + /// + /// Show ContextMenu if the Right Mouse button was pressed and we have received the following MouseUp + /// + private void OnMouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + if (BehaviorService != null) + { + Point loc = BehaviorService.ControlToAdornerWindow(_miniToolStrip); + loc = BehaviorService.AdornerWindowPointToScreen(loc); + loc.Offset(e.Location); + DesignerContextMenu.Show(loc); + } + } + } + + /// + /// Set the selection to the component. + /// + private void OnMouseDown(object sender, MouseEventArgs e) + { + if (KeyboardService != null) + { + KeyboardService.SelectedDesignerControl = _controlHost; + } + SelectionService.SetSelectedComponents(null, SelectionTypes.Replace); + } + + /// + /// Painting on the button for mouse Move. + /// + private void OnMouseMove(object sender, MouseEventArgs e) + { + _renderer.State = (int)TemplateNodeSelectionState.None; + if (_renderer != null) + { + if (_addItemButton != null) + { + if (_addItemButton.ButtonBounds.Contains(e.Location)) + { + _renderer.State = (int)TemplateNodeSelectionState.SplitButtonSelected; + } + else if (_addItemButton.DropDownButtonBounds.Contains(e.Location)) + { + _renderer.State = (int)TemplateNodeSelectionState.DropDownSelected; + } + } + _miniToolStrip.Invalidate(); + } + } + + /// + /// Painting on the button for mouse Leave. + /// + private void OnMouseLeave(object sender, EventArgs e) + { + if (SelectionService != null) + { + if (SelectionService.PrimarySelection is ToolStripItem && _renderer != null && _renderer.State != (int)TemplateNodeSelectionState.HotRegionSelected) + { + _renderer.State = (int)TemplateNodeSelectionState.None; + } + if (KeyboardService != null && KeyboardService.SelectedDesignerControl == _controlHost) + { + _renderer.State = (int)TemplateNodeSelectionState.TemplateNodeSelected; + } + _miniToolStrip.Invalidate(); + } + } + + private void OnRightToLeftChanged(object sender, EventArgs e) + { + if (sender is ToolStrip strip) + { + _miniToolStrip.RightToLeft = strip.RightToLeft; + } + else + { + ToolStripDropDownItem stripItem = sender as ToolStripDropDownItem; + _miniToolStrip.RightToLeft = stripItem.RightToLeft; + } + } + + /// + /// Intercept invokation of specific commands and keys + /// + public bool OverrideInvoke(MenuCommand cmd) + { + for (int i = 0; i < _commands.Length; i++) + { + if (_commands[i].CommandID.Equals(cmd.CommandID)) + { + if (cmd.CommandID == MenuCommands.Delete || cmd.CommandID == MenuCommands.Cut || cmd.CommandID == MenuCommands.Copy) + { + _commands[i].Invoke(); + return true; + } + } + } + return false; + } + + /// + /// Intercept invokation of specific commands and keys + /// + public bool OverrideStatus(MenuCommand cmd) + { + + for (int i = 0; i < _commands.Length; i++) + { + if (_commands[i].CommandID.Equals(cmd.CommandID)) + { + cmd.Enabled = false; + return true; + } + } + + return false; + } + + /// + /// This internal Function is called by item designers to ROLLBACK the current Insitu editing mode. + /// + internal void RollBack() + { + // RollBack only iff we are still available !! + if (_miniToolStrip != null && _inSituMode) + { + CommitEditor(false, false, false); + } + } + + internal void ShowContextMenu(Point pt) + { + DesignerContextMenu.Show(pt); + } + + internal void ShowDropDownMenu() + { + if (_addItemButton != null) + { + if (!_isPopulated) + { + _isPopulated = true; + ToolStripDesignerUtils.GetCustomNewItemDropDown(_contextMenu, _component, null, new EventHandler(AddNewItemClick), false, _component.Site); + } + _addItemButton.ShowDropDown(); + } + else + { + if (BehaviorService != null) + { + Point loc = BehaviorService.ControlToAdornerWindow(_miniToolStrip); + loc = BehaviorService.AdornerWindowPointToScreen(loc); + Rectangle translatedBounds = new Rectangle(loc, _miniToolStrip.Size); + _miniToolStrip.RaiseStateChangeEvent(); + + if (_contextMenu == null) + { + _isPopulated = true; + _contextMenu = ToolStripDesignerUtils.GetNewItemDropDown(_component, null, new EventHandler(AddNewItemClick), false, _component.Site, true); + _contextMenu.Closed += new ToolStripDropDownClosedEventHandler(OnContextMenuClosed); + _contextMenu.Closing += OnContextMenuClosing; + _contextMenu.Opened += new EventHandler(OnContextMenuOpened); + _contextMenu.Text = "ItemSelectionMenu"; + } + else if (!_isPopulated) + { + _isPopulated = true; + ToolStripDesignerUtils.GetCustomNewItemDropDown(_contextMenu, _component, null, new EventHandler(AddNewItemClick), false, _component.Site); + } + + if (_component is ToolStrip strip) + { + _contextMenu.RightToLeft = strip.RightToLeft; + } + else + { + if (_component is ToolStripDropDownItem stripItem) + { + _contextMenu.RightToLeft = stripItem.RightToLeft; + } + } + _contextMenu.Show(translatedBounds.X, translatedBounds.Y + translatedBounds.Height); + _contextMenu.Focus(); + if (_renderer != null) + { + _renderer.State = (int)TemplateNodeSelectionState.HotRegionSelected; + _miniToolStrip.Invalidate(); + } + } + } + } + + /// + /// This function sets up the MenuStrip specific TemplateNode. + /// + private void SetUpMenuTemplateNode(ToolStripTemplateNode owner, string text, Image image, IComponent currentItem) + { + _centerLabel = new ToolStripLabel + { + Text = text, + AutoSize = false, + IsLink = false, + AccessibleDescription = SR.ToolStripDesignerTemplateNodeLabelToolTip, + AccessibleRole = AccessibleRole.Text, + + Margin = new Padding(1) + }; + if (currentItem is ToolStripDropDownItem) + { + _centerLabel.Margin = new Padding(1, 2, 1, 3); + } + _centerLabel.Padding = new Padding(0, 1, 0, 0); + _centerLabel.Name = CenterLabelName; + _centerLabel.Size = _miniToolStrip.DisplayRectangle.Size - _centerLabel.Margin.Size; + _centerLabel.ToolTipText = SR.ToolStripDesignerTemplateNodeLabelToolTip; + _centerLabel.MouseUp += new MouseEventHandler(CenterLabelClick); + _centerLabel.MouseEnter += new EventHandler(CenterLabelMouseEnter); + _centerLabel.MouseMove += new MouseEventHandler(CenterLabelMouseMove); + _centerLabel.MouseLeave += new EventHandler(CenterLabelMouseLeave); + + _miniToolStrip.Items.AddRange(new ToolStripItem[] { _centerLabel }); + } + + /// + /// This function sets up TemplateNode for ToolStrip, StatusStrip, ContextMenuStrip. + /// + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + private void SetUpToolTemplateNode(ToolStripTemplateNode owner, string text, Image image, IComponent component) + { + _addItemButton = new ToolStripSplitButton + { + AutoSize = false, + Margin = new Padding(1) + }; + _addItemButton.Size = _miniToolStrip.DisplayRectangle.Size - _addItemButton.Margin.Size; + _addItemButton.DropDownButtonWidth = MINITOOLSTRIP_DROPDOWN_BUTTON_WIDTH; + _addItemButton.DisplayStyle = ToolStripItemDisplayStyle.Image; + if (component is StatusStrip) + { + _addItemButton.ToolTipText = SR.ToolStripDesignerTemplateNodeSplitButtonStatusStripToolTip; + } + else + { + _addItemButton.ToolTipText = SR.ToolStripDesignerTemplateNodeSplitButtonToolTip; + } + + _addItemButton.MouseDown += new System.Windows.Forms.MouseEventHandler(OnMouseDown); + _addItemButton.MouseMove += new System.Windows.Forms.MouseEventHandler(OnMouseMove); + _addItemButton.MouseUp += new System.Windows.Forms.MouseEventHandler(OnMouseUp); + _addItemButton.DropDownOpened += OnAddItemButtonDropDownOpened; + _contextMenu = ToolStripDesignerUtils.GetNewItemDropDown(component, null, new EventHandler(AddNewItemClick), false, component.Site, false); + _contextMenu.Text = "ItemSelectionMenu"; + _contextMenu.Closed += new ToolStripDropDownClosedEventHandler(OnContextMenuClosed); + _contextMenu.Closing += OnContextMenuClosing; + _contextMenu.Opened += new EventHandler(OnContextMenuOpened); + _addItemButton.DropDown = _contextMenu; + _addItemButton.AccessibleName = SR.ToolStripDesignerTemplateNodeSplitButtonStatusStripAccessibleName; + _addItemButton.AccessibleRole = AccessibleRole.ButtonDropDown; + // Set up default item and image. + try + { + if (_addItemButton.DropDownItems.Count > 0) + { + ItemTypeToolStripMenuItem firstItem = (ItemTypeToolStripMenuItem)_addItemButton.DropDownItems[0]; + _addItemButton.ImageTransparentColor = Color.Lime; + Bitmap bmp = new Bitmap(typeof(ToolStripTemplateNode), "ToolStripTemplateNode.bmp"); + if (DpiHelper.IsScalingRequired) + { + bmp.MakeTransparent(Color.Lime); + DpiHelper.ScaleBitmapLogicalToDevice(ref bmp); + } + _addItemButton.Image = bmp; + _addItemButton.DefaultItem = firstItem; + } + Debug.Assert(_addItemButton.DropDownItems.Count > 0); + } + catch (Exception ex) + { + if (ClientUtils.IsCriticalException(ex)) + { + throw; + } + } + _miniToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + _addItemButton + }); + } + + /// + /// This method does actual edit node creation. + /// + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] + private void SetupNewEditNode(ToolStripTemplateNode owner, string text, Image image, IComponent currentItem) + { + // setup the MINIToolStrip host... + _renderer = new MiniToolStripRenderer(owner); + _miniToolStrip = new TransparentToolStrip(owner); + if (currentItem is ToolStrip strip) + { + _miniToolStrip.RightToLeft = strip.RightToLeft; + strip.RightToLeftChanged += new System.EventHandler(OnRightToLeftChanged); + // Make TransparentToolStrip has the same "Site" as ToolStrip. This could make sure TransparentToolStrip has the same design time behavior as ToolStrip. + _miniToolStrip.Site = strip.Site; + } + if (currentItem is ToolStripDropDownItem stripItem) + { + _miniToolStrip.RightToLeft = stripItem.RightToLeft; + stripItem.RightToLeftChanged += new System.EventHandler(this.OnRightToLeftChanged); + } + _miniToolStrip.SuspendLayout(); + _miniToolStrip.CanOverflow = false; + _miniToolStrip.Cursor = System.Windows.Forms.Cursors.Default; + _miniToolStrip.Dock = System.Windows.Forms.DockStyle.None; + _miniToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + _miniToolStrip.Name = "miniToolStrip"; + _miniToolStrip.TabIndex = 0; + _miniToolStrip.Visible = true; + _miniToolStrip.Renderer = _renderer; + + // Add items to the Template ToolStrip depending upon the Parent Type... + if (currentItem is MenuStrip || currentItem is ToolStripDropDownItem) + { + SetUpMenuTemplateNode(owner, text, image, currentItem); + _miniToolStrip.AccessibleRole = AccessibleRole.ComboBox; + _miniToolStrip.Text = text; + } + else + { + SetUpToolTemplateNode(owner, text, image, currentItem); + _miniToolStrip.AccessibleRole = AccessibleRole.ButtonDropDown; + } + _miniToolStrip.MouseLeave += new System.EventHandler(OnMouseLeave); + _miniToolStrip.ResumeLayout(); + } + + /// + /// This method does sets the width of the Editor (_miniToolStrip) based on the text passed in. + /// + internal void SetWidth(string text) + { + // REVIEW: is this function necessary anymore? + if (string.IsNullOrEmpty(text)) + { + _miniToolStrip.Width = _centerLabel.Width + 2; + } + else + { + _centerLabel.Text = text; + } + } + + /// + /// Private class that implements the textBox for the InSitu Editor. + /// + private class TemplateTextBox : TextBox + { + TransparentToolStrip parent; + ToolStripTemplateNode owner; + private const int IMEMODE = 229; + + public TemplateTextBox(TransparentToolStrip parent, ToolStripTemplateNode owner) : base() + { + this.parent = parent; + this.owner = owner; + AutoSize = false; + Multiline = false; + } + + /// + /// Get Parent Handle. + /// + private bool IsParentWindow(IntPtr hWnd) + { + if (hWnd == parent.Handle) + { + return true; + } + return false; + } + + protected override bool IsInputKey(Keys keyData) + { + switch (keyData & Keys.KeyCode) + { + case Keys.Return: + owner.Commit(true, false); + return true; + } + return base.IsInputKey(keyData); + } + + /// + /// Process the IMEMode message.. + /// + protected override bool ProcessDialogKey(Keys keyData) + { + if ((int)keyData == IMEMODE) + { + owner.IMEModeSet = true; + } + else + { + owner.IMEModeSet = false; + owner.ignoreFirstKeyUp = false; + } + return base.ProcessDialogKey(keyData); + } + + /// + /// Process the WNDPROC for WM_KILLFOCUS to commit the Insitu Editor.. + /// + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_KILLFOCUS: + base.WndProc(ref m); + IntPtr focussedWindow = (IntPtr)m.WParam; + if (!IsParentWindow(focussedWindow)) + { + owner.Commit(false, false); + } + break; + + // 1.Slowly click on a menu strip item twice to make it editable, while the item's dropdown menu is visible + // 2.Select the text of the item and right click on it + // 3.Left click 'Copy' or 'Cut' in the context menu IDE crashed because left click in step3 invoked glyph behavior, which commited and destroyed the insitu edit box and thus the 'copy' or 'cut' action has no text to work with. Thus need to block glyph behaviors while the context menu is displayed. + case Interop.WindowMessages.WM_CONTEXTMENU: + owner.IsSystemContextMenuDisplayed = true; + base.WndProc(ref m); + owner.IsSystemContextMenuDisplayed = false; + break; + default: + base.WndProc(ref m); + break; + } + } + } + + /// + /// Private class to Change the ToolStrip to a TransparentToolStrip. Our EditorToolStrip is a TranparentToolStrip so that it picks up the itemColor. + /// + public class TransparentToolStrip : ToolStrip + { + ToolStripTemplateNode owner; + IComponent currentItem; + + public TransparentToolStrip(ToolStripTemplateNode owner) + { + this.owner = owner; + currentItem = owner._component; + TabStop = true; + SetStyle(ControlStyles.Selectable, true); + AutoSize = false; + AccessibleName = SR.ToolStripDesignerToolStripAccessibleName; + AccessibleRole = AccessibleRole.ComboBox; + } + + /// + /// Owner TemplateNode.. + /// + public ToolStripTemplateNode TemplateNode + { + get => owner; + } + + /// + /// Commit the node and move to next selection. + /// + private void CommitAndSelectNext(bool forward) + { + owner.Commit(false, true); + if (owner.KeyboardService != null) + { + owner.KeyboardService.ProcessKeySelect(!forward, null); + } + } + + /// + /// get current selection. + /// + private ToolStripItem GetSelectedItem() + { + ToolStripItem selectedItem = null; + for (int i = 0; i < Items.Count; i++) + { + if (Items[i].Selected) + { + selectedItem = Items[i]; + } + } + return selectedItem; + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + public override Size GetPreferredSize(Size proposedSize) + { + if (currentItem is ToolStripDropDownItem) + { + return new Size(Width, TOOLSTRIP_TEMPLATE_HEIGHT); + } + else + { + return new Size(Width, TEMPLATE_HEIGHT); + } + } + + /// + /// Process the Tab Key.. + /// + private bool ProcessTabKey(bool forward) + { + // Give the ToolStripItem first dibs + ToolStripItem item = this.GetSelectedItem(); + if (item is ToolStripControlHost) + { + + CommitAndSelectNext(forward); + return true; + } + return false; + } + + /// + /// Process the Dialog Keys for the Templatenode ToolStrip.. + /// + protected override bool ProcessDialogKey(Keys keyData) + { + bool retVal = false; + if (owner.Active) + { + if ((keyData & (Keys.Alt | Keys.Control)) == Keys.None) + { + Keys keyCode = (Keys)keyData & Keys.KeyCode; + switch (keyCode) + { + case Keys.Tab: + retVal = ProcessTabKey((keyData & Keys.Shift) == Keys.None); + break; + } + } + + if (retVal) + { + return retVal; + } + } + return base.ProcessDialogKey(keyData); + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) + { + if (currentItem is ToolStripDropDownItem) + { + base.SetBoundsCore(x, y, TOOLSTRIP_TEMPLATE_WIDTH, TOOLSTRIP_TEMPLATE_HEIGHT, specified); + } + else if (currentItem is MenuStrip) + { + base.SetBoundsCore(x, y, TOOLSTRIP_TEMPLATE_WIDTH, TEMPLATE_HEIGHT, specified); + } + else + { + base.SetBoundsCore(x, y, TEMPLATE_WIDTH, TEMPLATE_HEIGHT, specified); + } + } + + internal void RaiseStateChangeEvent() + { + AccessibilityNotifyClients(AccessibleEvents.StateChange, -1); + } + + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_GETOBJECT: + if (owner._addItemButton == null) + { + // only adding patterns to _miniToolStrip associated with MenuStrip or ContextMenu + // m.Result = AutomationInteropProvider.ReturnRawElementProvider(Handle, m.WParam, m.LParam, (IRawElementProviderSimple)(new TransparentToolStripUiaProvider(this))); + return; + } + break; + } + base.WndProc(ref m); + } + } + + /* + internal class TransparentToolStripUiaProvider : ControlUiaProvider, IExpandCollapseProvider + { + public TransparentToolStripUiaProvider(TransparentToolStrip owner) : base(owner) + { + } + + private ToolStripTemplateNode TemplateNode + { + get => (_owner as TransparentToolStrip).TemplateNode; + } + + #region IValueProvider + public override void SetValue(string newValue) + { + TemplateNode.CommitTextToDesigner(newValue, true, true, false); + } + #endregion + + #region Expand/Collapse pattern + public override object GetPatternProvider(int patternId) + { + if (patternId == ExpandCollapsePatternIdentifiers.Pattern.Id && TemplateNode != null) + { + return this as IExpandCollapseProvider; + } + + return base.GetPatternProvider(patternId); + } + + public ExpandCollapseState ExpandCollapseState + { + get + { + NewItemsContextMenuStrip menu = TemplateNode._contextMenu; + return ((menu != null) && menu.Visible) ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed; + } + } + + public void Expand() + { + TemplateNode.ShowDropDownMenu(); + } + + public void Collapse() + { + // Drop down for the MenuStrip is implemented as a context menu and thus closes as soon as keyboard focus leaves it. When Collapse method is invoked in Inspect, context menu is already closed. + TemplateNode._contextMenu?.Hide(); + } + #endregion + } + */ + + /// + /// Private class that implements the custom Renderer for the TemplateNode ToolStrip. + /// + public class MiniToolStripRenderer : ToolStripSystemRenderer + { + private int state = (int)TemplateNodeSelectionState.None; + private Color selectedBorderColor; + private Color defaultBorderColor; + private Color dropDownMouseOverColor; + private Color dropDownMouseDownColor; + private Color toolStripBorderColor; + private ToolStripTemplateNode owner; + private Rectangle hotRegion = Rectangle.Empty; + + public MiniToolStripRenderer(ToolStripTemplateNode owner) : base() + { + //Add Colors + this.owner = owner; + selectedBorderColor = Color.FromArgb(46, 106, 197); + defaultBorderColor = Color.FromArgb(171, 171, 171); + dropDownMouseOverColor = Color.FromArgb(193, 210, 238); + dropDownMouseDownColor = Color.FromArgb(152, 181, 226); + toolStripBorderColor = Color.White; + } + + /// + /// Current state of the TemplateNode UI.. + /// + public int State + { + get => state; + set => state = value; + } + + /// + /// Custom method to draw DOWN arrow on the DropDown. + /// + private void DrawArrow(Graphics g, Rectangle bounds) + { + bounds.Width--; + DrawArrow(new ToolStripArrowRenderEventArgs(g, null, bounds, SystemInformation.HighContrast ? Color.Black : SystemColors.ControlText, ArrowDirection.Down)); + } + + /// + /// Drawing different DropDown states. + /// + private void DrawDropDown(Graphics g, Rectangle bounds, int state) + { + switch (state) + { + case 1: //TemplateNodeSelected + case 4: //MouseOver + using (LinearGradientBrush brush = new LinearGradientBrush(bounds, Color.White, defaultBorderColor, LinearGradientMode.Vertical)) + { + g.FillRectangle(brush, bounds); + } + break; + case 5: //MouseOnthe HotRegion + using (SolidBrush b = new SolidBrush(dropDownMouseOverColor)) + { + g.FillRectangle(b, hotRegion); + } + break; + case 6: //HotRegionSelected + using (SolidBrush b = new SolidBrush(dropDownMouseDownColor)) + { + g.FillRectangle(b, hotRegion); + } + break; + } + DrawArrow(g, bounds); + } + + protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) + { + if (owner._component is MenuStrip || owner._component is ToolStripDropDownItem) + { + Graphics g = e.Graphics; + g.Clear(toolStripBorderColor); + } + else + { + base.OnRenderToolStripBackground(e); + } + } + + + /// + /// Render ToolStrip Border + /// + protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) + { + Graphics g = e.Graphics; + Rectangle bounds = new Rectangle(Point.Empty, e.ToolStrip.Size); + Pen selectborderPen = new Pen(toolStripBorderColor); + Rectangle drawRect = new Rectangle(bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + g.DrawRectangle(selectborderPen, drawRect); + selectborderPen.Dispose(); + } + + /// + /// Render the Center Label on the TemplateNode ToolStrip. + /// + protected override void OnRenderLabelBackground(ToolStripItemRenderEventArgs e) + { + base.OnRenderLabelBackground(e); + ToolStripItem item = e.Item; + Graphics g = e.Graphics; + Rectangle bounds = new Rectangle(Point.Empty, item.Size); + Rectangle drawRect = new Rectangle(bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + Pen borderPen = new Pen(defaultBorderColor); + if (state == (int)TemplateNodeSelectionState.TemplateNodeSelected) //state Template node is selected. + { + using (SolidBrush brush = new SolidBrush(toolStripBorderColor)) + { + g.FillRectangle(brush, drawRect); + } + if (owner.EditorToolStrip.RightToLeft == RightToLeft.Yes) + { + hotRegion = new Rectangle(bounds.Left + 2, bounds.Top + 2, TEMPLATE_HOTREGION_WIDTH, bounds.Bottom - 4); + } + else + { + hotRegion = new Rectangle(bounds.Right - TEMPLATE_HOTREGION_WIDTH - 2, bounds.Top + 2, TEMPLATE_HOTREGION_WIDTH, bounds.Bottom - 4); + } + owner.HotRegion = hotRegion; + + // do the Actual Drawing + DrawDropDown(g, hotRegion, state); + + borderPen.Color = Color.Black; + item.ForeColor = defaultBorderColor; + g.DrawRectangle(borderPen, drawRect); + } + + if (state == (int)TemplateNodeSelectionState.MouseOverLabel) //state Template node is selected. + { + if (owner.EditorToolStrip.RightToLeft == RightToLeft.Yes) + { + hotRegion = new Rectangle(bounds.Left + 2, bounds.Top + 2, TEMPLATE_HOTREGION_WIDTH, bounds.Bottom - 4); + } + else + { + hotRegion = new Rectangle(bounds.Right - TEMPLATE_HOTREGION_WIDTH - 2, bounds.Top + 2, TEMPLATE_HOTREGION_WIDTH, bounds.Bottom - 4); + } + owner.HotRegion = hotRegion; + + g.Clear(toolStripBorderColor); + DrawDropDown(g, hotRegion, state); + borderPen.Color = Color.Black; + borderPen.DashStyle = DashStyle.Dot; + g.DrawRectangle(borderPen, drawRect); + } + + if (state == (int)TemplateNodeSelectionState.MouseOverHotRegion) + { + g.Clear(toolStripBorderColor); + DrawDropDown(g, hotRegion, state); + borderPen.Color = Color.Black; + borderPen.DashStyle = DashStyle.Dot; + item.ForeColor = defaultBorderColor; + g.DrawRectangle(borderPen, drawRect); + } + + if (state == (int)TemplateNodeSelectionState.HotRegionSelected) + { + g.Clear(toolStripBorderColor); + DrawDropDown(g, hotRegion, state); + borderPen.Color = Color.Black; + item.ForeColor = defaultBorderColor; + g.DrawRectangle(borderPen, drawRect); + } + + if (state == (int)TemplateNodeSelectionState.None) //state Template node is not selected. + { + g.Clear(toolStripBorderColor); + g.DrawRectangle(borderPen, drawRect); + item.ForeColor = defaultBorderColor; + } + borderPen.Dispose(); + } + + /// + /// Render the splitButton on the TemplateNode ToolStrip.. + /// + protected override void OnRenderSplitButtonBackground(ToolStripItemRenderEventArgs e) + { + // DONT CALL THE BASE AS IT DOESNT ALLOW US TO RENDER THE DROPDOWN BUTTON .... + //base.OnRenderSplitButtonBackground(e); + Graphics g = e.Graphics; + if (e.Item is ToolStripSplitButton splitButton) + { + // Get the DropDownButton Bounds + Rectangle buttonBounds = splitButton.DropDownButtonBounds; + // Draw the White Divider Line... + using (Pen p = new Pen(toolStripBorderColor)) + { + g.DrawLine(p, buttonBounds.Left, buttonBounds.Top + 1, buttonBounds.Left, buttonBounds.Bottom - 1); + } + + Rectangle bounds = new Rectangle(Point.Empty, splitButton.Size); + Pen selectborderPen = null; + bool splitButtonSelected = false; + if (splitButton.DropDownButtonPressed) + { + //Button is pressed + state = 0; + Rectangle fillRect = new Rectangle(buttonBounds.Left + 1, buttonBounds.Top, buttonBounds.Right, buttonBounds.Bottom); + using (SolidBrush brush = new SolidBrush(dropDownMouseDownColor)) + { + g.FillRectangle(brush, fillRect); + } + splitButtonSelected = true; + } + else if (state == (int)TemplateNodeSelectionState.SplitButtonSelected) + { + using (SolidBrush brush = new SolidBrush(dropDownMouseOverColor)) + { + g.FillRectangle(brush, splitButton.ButtonBounds); + } + splitButtonSelected = true; + } + else if (state == (int)TemplateNodeSelectionState.DropDownSelected) + { + Rectangle fillRect = new Rectangle(buttonBounds.Left + 1, buttonBounds.Top, buttonBounds.Right, buttonBounds.Bottom); + using (SolidBrush brush = new SolidBrush(dropDownMouseOverColor)) + { + g.FillRectangle(brush, fillRect); + } + splitButtonSelected = true; + } + else if (state == (int)TemplateNodeSelectionState.TemplateNodeSelected) + { + splitButtonSelected = true; + } + + if (splitButtonSelected) + { + //DrawSeleted Boder + selectborderPen = new Pen(selectedBorderColor); + } + else + { + // Draw Gray Border + selectborderPen = new Pen(defaultBorderColor); + } + + Rectangle drawRect = new Rectangle(bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + g.DrawRectangle(selectborderPen, drawRect); + selectborderPen.Dispose(); + + // Draw the Arrow + DrawArrow(new ToolStripArrowRenderEventArgs(g, splitButton, splitButton.DropDownButtonBounds, SystemColors.ControlText, ArrowDirection.Down)); + } + } + + protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) + { + ToolStripItem item = e.Item as ToolStripLabel; + if (item != null && String.Equals(item.Name, CenterLabelName, StringComparison.InvariantCulture) && SystemInformation.HighContrast) + { + // "Type Here" node always has white background, text should be painted in black + e.TextColor = Color.Black; + } + base.OnRenderItemText(e); + } + } + } +} + + diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/UndoEngine.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/UndoEngine.cs index 120d2c1146a..37249235932 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/UndoEngine.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/UndoEngine.cs @@ -578,8 +578,6 @@ public ReferencingComponent(IComponent component, MemberDescriptor member) /// protected class UndoUnit { - private readonly string _name; // the name of the undo unit - private readonly UndoEngine _engine; // the undo engine we're tied to private ArrayList _events; // the list of events we've captured private ArrayList _changeEvents; // the list of change events we're currently capturing. Only valid until Commit is called. private ArrayList _removeEvents; // the list of remove events we're currently capturing. Only valid until a matching Removed is encountered. @@ -588,22 +586,19 @@ protected class UndoUnit private bool _reverse; // if true, we walk the events list from the bottom up private readonly Hashtable _lastSelection; // the selection as it was before we gathered undo info - /// - /// Creates a new UndoUnit. - /// public UndoUnit(UndoEngine engine, string name) { if (name == null) { - Debug.Fail("Null name passed to new undo unit"); name = string.Empty; } + UndoEngine.Trace("Creating undo unit '{0}'", name); - _name = name; - _engine = engine ?? throw new ArgumentNullException(nameof(engine)); + Name = name; + UndoEngine = engine ?? throw new ArgumentNullException(nameof(engine)); _reverse = true; - if (_engine.GetService(typeof(ISelectionService)) is ISelectionService ss) + if (UndoEngine.GetService(typeof(ISelectionService)) is ISelectionService ss) { ICollection selection = ss.GetSelectedComponents(); Hashtable selectedNames = new Hashtable(); @@ -618,29 +613,14 @@ public UndoUnit(UndoEngine engine, string name) } } - /// - /// The name of the unit. - /// - public string Name - { - get => _name; - } + public string Name { get; } /// /// This returns true if the undo unit has nothing in it to undo. The unit will be discarded. /// - public virtual bool IsEmpty - { - get => _events == null || _events.Count == 0; - } + public virtual bool IsEmpty => _events == null || _events.Count == 0; - /// - /// The undo engine that was passed into the constructor. - /// - protected UndoEngine UndoEngine - { - get => _engine; - } + protected UndoEngine UndoEngine { get; } /// /// Adds the given event to our event list. @@ -651,6 +631,7 @@ private void AddEvent(UndoEvent e) { _events = new ArrayList(); } + _events.Add(e); } @@ -663,7 +644,7 @@ public virtual void Close() { foreach (ChangeUndoEvent e in _changeEvents) { - e.Commit(_engine); + e.Commit(UndoEngine); } } @@ -671,7 +652,7 @@ public virtual void Close() { foreach (AddRemoveUndoEvent e in _removeEvents) { - e.Commit(_engine); + e.Commit(UndoEngine); } } @@ -693,7 +674,7 @@ public virtual void ComponentAdded(ComponentEventArgs e) // do nothing } else - AddEvent(new AddRemoveUndoEvent(_engine, e.Component, true)); + AddEvent(new AddRemoveUndoEvent(UndoEngine, e.Component, true)); if (_ignoreAddingList != null) { @@ -795,7 +776,7 @@ public virtual void ComponentChanging(ComponentChangingEventArgs e) } // The site check here is done because the data team is calling us for components that are not yet sited. We end up writing them out as Guid-named locals. That's fine, except that we cannot capture after state for these types of things so we assert. - if (_engine != null && _engine.GetName(e.Component, false) != null) + if (UndoEngine.GetName(e.Component, false) != null) { // The caller provided us with a component. This is the common case. We will add a new change event provided there is not already one open for this component. bool hasChange = false; @@ -814,7 +795,7 @@ public virtual void ComponentChanging(ComponentChangingEventArgs e) (e.Member != null && e.Member.Attributes != null && e.Member.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content))) { #if DEBUG - string name = _engine.GetName(e.Component, false); + string name = UndoEngine.GetName(e.Component, false); string memberName = "(none)"; if (e.Member != null && e.Member.Name != null) { memberName = e.Member.Name; @@ -836,7 +817,7 @@ public virtual void ComponentChanging(ComponentChangingEventArgs e) if (e.Component is IComponent comp && comp.Site != null) { - changeEvent = new ChangeUndoEvent(_engine, e, serializeBeforeState); + changeEvent = new ChangeUndoEvent(UndoEngine, e, serializeBeforeState); } else if (e.Component != null) { @@ -846,7 +827,7 @@ public virtual void ComponentChanging(ComponentChangingEventArgs e) if (owningComp != null) { - changeEvent = new ChangeUndoEvent(_engine, new ComponentChangingEventArgs(owningComp, null), serializeBeforeState); + changeEvent = new ChangeUndoEvent(UndoEngine, new ComponentChangingEventArgs(owningComp, null), serializeBeforeState); } } } @@ -881,7 +862,7 @@ public virtual void ComponentRemoved(ComponentEventArgs e) if (_events[idx] is AddRemoveUndoEvent evt && evt.OpenComponent == e.Component) { - evt.Commit(_engine); + evt.Commit(UndoEngine); // We should only reorder events if there are change events coming between OnRemoving and OnRemoved. // If there are other events (such as AddRemoving), the serialization done in OnComponentRemoving might refer to components that aren't available. if (idx != _events.Count - 1 && changeEvt != null) @@ -927,7 +908,7 @@ public virtual void ComponentRemoving(ComponentEventArgs e) } try { - AddRemoveUndoEvent evt = new AddRemoveUndoEvent(_engine, e.Component, false); + AddRemoveUndoEvent evt = new AddRemoveUndoEvent(UndoEngine, e.Component, false); AddEvent(evt); _removeEvents.Add(evt); } @@ -947,7 +928,7 @@ public virtual void ComponentRename(ComponentRenameEventArgs e) /// protected object GetService(Type serviceType) { - return _engine.GetService(serviceType); + return UndoEngine.GetService(serviceType); } /// @@ -964,17 +945,17 @@ public override string ToString() public void Undo() { UndoEngine.Trace("Performing undo '{0}'", Name); - UndoUnit savedUnit = _engine._executingUnit; - _engine._executingUnit = this; + UndoUnit savedUnit = UndoEngine._executingUnit; + UndoEngine._executingUnit = this; DesignerTransaction transaction = null; try { if (savedUnit == null) { - _engine.OnUndoing(EventArgs.Empty); + UndoEngine.OnUndoing(EventArgs.Empty); } // create a transaction here so things that do work on componentchanged can ignore that while the transaction is opened...big perf win. - transaction = _engine._host.CreateTransaction(); + transaction = UndoEngine._host.CreateTransaction(); UndoCore(); } catch (CheckoutException) @@ -990,10 +971,10 @@ public void Undo() transaction.Commit(); } - _engine._executingUnit = savedUnit; + UndoEngine._executingUnit = savedUnit; if (savedUnit == null) { - _engine.OnUndone(EventArgs.Empty); + UndoEngine.OnUndone(EventArgs.Empty); } } } @@ -1028,12 +1009,12 @@ protected virtual void UndoCore() for (int beforeIdx = idx; beforeIdx >= groupEndIdx; beforeIdx--) { - ((UndoEvent)_events[beforeIdx]).BeforeUndo(_engine); + ((UndoEvent)_events[beforeIdx]).BeforeUndo(UndoEngine); } for (int undoIdx = idx; undoIdx >= groupEndIdx; undoIdx--) { - ((UndoEvent)_events[undoIdx]).Undo(_engine); + ((UndoEvent)_events[undoIdx]).Undo(UndoEngine); } Debug.Assert(idx >= groupEndIdx, "We're going backwards"); @@ -1043,7 +1024,7 @@ protected virtual void UndoCore() // Now, if we have a selection, apply it. if (_lastSelection != null) { - if (_engine.GetService(typeof(ISelectionService)) is ISelectionService ss) + if (UndoEngine.GetService(typeof(ISelectionService)) is ISelectionService ss) { string[] names = new string[_lastSelection.Keys.Count]; _lastSelection.Keys.CopyTo(names, 0); @@ -1084,12 +1065,12 @@ protected virtual void UndoCore() for (int beforeIdx = idx; beforeIdx <= groupEndIdx; beforeIdx++) { - ((UndoEvent)_events[beforeIdx]).BeforeUndo(_engine); + ((UndoEvent)_events[beforeIdx]).BeforeUndo(UndoEngine); } for (int undoIdx = idx; undoIdx <= groupEndIdx; undoIdx++) { - ((UndoEvent)_events[undoIdx]).Undo(_engine); + ((UndoEvent)_events[undoIdx]).Undo(UndoEngine); } Debug.Assert(idx <= groupEndIdx, "We're going backwards"); diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs index 2bd233dad39..c44cada0915 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs @@ -7,16 +7,30 @@ namespace System.Windows.Forms.Design { /// - /// Makes the DesignerOptions queryable through the IDesignerOption service. + /// Makes the DesignerOptions queryable through the IDesignerOption service. /// public class WindowsFormsDesignerOptionService : DesignerOptionService { - public virtual DesignerOptions CompatibilityOptions => throw new NotImplementedException(SR.NotImplementedByDesign); + private DesignerOptions _options; + + public virtual DesignerOptions CompatibilityOptions => _options ?? (_options = new DesignerOptions()); /// - /// This method is called on demand the first time a user asks for child - /// options or properties of an options collection. + /// This method is called on demand the first time a user asks for child options or + /// properties of an options collection. /// - protected override void PopulateOptionCollection(DesignerOptionCollection options) => throw new NotImplementedException(SR.NotImplementedByDesign); + protected override void PopulateOptionCollection(DesignerOptionCollection options) + { + if (options == null || options.Parent != null) + { + return; + } + + DesignerOptions designerOptions = CompatibilityOptions; + if (designerOptions != null) + { + CreateOptionCollection(options, "DesignerOptions", designerOptions); + } + } } } diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/ControlDesignerTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/ControlDesignerTests.cs index e4fa0febbd4..51568c546ab 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/ControlDesignerTests.cs +++ b/src/System.Windows.Forms.Design/tests/UnitTests/ControlDesignerTests.cs @@ -9,212 +9,213 @@ namespace System.Windows.Forms.Design.Tests { public class ControlDesignerTests { - internal MockControlDesigner controlDesigner = new MockControlDesigner(); - [Fact] public void AccessibleObjectField() { + TestControlDesigner controlDesigner = new TestControlDesigner(); Assert.Null(controlDesigner.GetAccessibleObjectField()); } [Fact] public void BehaviorServiceProperty() { - Assert.Throws(() => controlDesigner.GetBehaviorServiceProperty()); - } - - [Fact] - public void AssociatedComponentsProperty() - { - Assert.Throws(() => controlDesigner.AssociatedComponents); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.Null(controlDesigner.GetBehaviorServiceProperty()); } [Fact] public void AccessibilityObjectField() { - Assert.Throws(() => controlDesigner.AccessibilityObject); - } - - [Fact] - public void ControlProperty() - { - Assert.Throws(() => controlDesigner.Control); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.NotNull(controlDesigner.AccessibilityObject); } [Fact] public void EnableDragRectProperty() { - Assert.Throws(() => controlDesigner.GetEnableDragRectProperty()); - } - - [Fact] - public void ParentComponentProperty() - { - Assert.Throws(() => controlDesigner.GetParentComponentProperty()); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.False(controlDesigner.GetEnableDragRectProperty()); } [Fact] public void ParticipatesWithSnapLinesProperty() { - Assert.Throws(() => controlDesigner.ParticipatesWithSnapLines); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.True(controlDesigner.ParticipatesWithSnapLines); } [Fact] public void AutoResizeHandlesProperty() { - Assert.Throws(() => controlDesigner.AutoResizeHandles = true); - Assert.Throws(() => controlDesigner.AutoResizeHandles); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.True(controlDesigner.AutoResizeHandles = true); + Assert.True(controlDesigner.AutoResizeHandles); } [Fact] public void SelectionRulesProperty() { - Assert.Throws(() => controlDesigner.SelectionRules); - } - - [Fact] - public void SnapLinesProperty() - { - Assert.Throws(() => controlDesigner.SnapLines); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.Equal(SelectionRules.Visible ,controlDesigner.SelectionRules); } [Fact] public void InheritanceAttributeProperty() { - Assert.Throws(() => controlDesigner.GetInheritanceAttributeProperty()); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.NotNull(controlDesigner); + controlDesigner.Initialize(new Button()); + Assert.NotNull(controlDesigner.GetInheritanceAttributeProperty()); } [Fact] public void NumberOfInternalControlDesignersTest() { - Assert.Throws(() => controlDesigner.NumberOfInternalControlDesigners()); - } - - [Fact] - public void InternalControlDesignerTest() - { - Assert.Throws(() => controlDesigner.InternalControlDesigner(1)); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.Equal(0, controlDesigner.NumberOfInternalControlDesigners()); } [Fact] public void BaseWndProcTest() { + TestControlDesigner controlDesigner = new TestControlDesigner(); Message m = default; - Assert.Throws(() => controlDesigner.BaseWndProcMethod(ref m)); + try + { + controlDesigner.BaseWndProcMethod(ref m); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } [Fact] public void CanBeParentedToTest() { - Assert.Throws(() => controlDesigner.CanBeParentedTo(new ParentControlDesigner())); - } - - [Fact] - public void DefWndProcTest() - { - Message m = default; - Assert.Throws(() => controlDesigner.DefWndProcMethod(ref m)); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.NotNull(controlDesigner); + controlDesigner.Initialize(new Button()); + Assert.True(controlDesigner.CanBeParentedTo(new ParentControlDesigner())); } - [Fact] - public void DisplayErrorTest() - { - Assert.Throws(() => controlDesigner.DisplayErrorMethod(new Exception())); - } - - /// - /// Bool data - /// public static TheoryData BoolData => CommonTestHelper.GetBoolTheoryData(); - [Theory] - [MemberData(nameof(BoolData))] - public void DisposeTest(bool val) - { - Assert.Throws(() => controlDesigner.DisposeMethod(val)); - } - - [Fact] - public void EnableDesignModeTest() - { - Assert.Throws(() => controlDesigner.EnableDesignModeMethod(null, "fake")); - } - [Theory] [MemberData(nameof(BoolData))] public void EnableDragDropTest(bool val) { - Assert.Throws(() => controlDesigner.EnableDragDropMethod(val)); - } - - /// - /// Data for the GlyphSelectionType enum - /// - public static TheoryData GlyphSelectionTypeData => - CommonTestHelper.GetEnumTheoryData(); - - [Theory] - [MemberData(nameof(GlyphSelectionTypeData))] - public void GetControlGlyphTest(Behavior.GlyphSelectionType glyphSelectionType) - { - Assert.Throws(() => controlDesigner.GetControlGlyphMethod(glyphSelectionType)); - } - - [Theory] - [MemberData(nameof(GlyphSelectionTypeData))] - public void GetGlyphsTest(Behavior.GlyphSelectionType glyphSelectionType) - { - Assert.Throws(() => controlDesigner.GetGlyphs(glyphSelectionType)); + TestControlDesigner controlDesigner = new TestControlDesigner(); + try + { + controlDesigner.EnableDragDropMethod(val); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } [Fact] public void GetHitTest() { + TestControlDesigner controlDesigner = new TestControlDesigner(); Assert.False(controlDesigner.GetHitTestMethod(new Drawing.Point())); } [Fact] public void HookChildControlsTest() { - Assert.Throws(() => controlDesigner.HookChildControlsMethod(null)); - } + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.NotNull(controlDesigner); + controlDesigner.Initialize(new Button()); + try + { - [Fact] - public void InitializeTest() - { - Assert.Throws(() => controlDesigner.Initialize(null)); + controlDesigner.HookChildControlsMethod(new Control()); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } [Fact] - public void InitializeExistingComponentTest() + public void InitializeTest() { - Assert.Throws(() => controlDesigner.InitializeExistingComponent(null)); + TestControlDesigner controlDesigner = new TestControlDesigner(); + try + { + controlDesigner.Initialize(new Button()); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } [Fact] public void InitializeNewComponentTest() { - Assert.Throws(() => controlDesigner.InitializeNewComponent(null)); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.NotNull(controlDesigner); + controlDesigner.Initialize(new Button()); + try + { + controlDesigner.InitializeNewComponent(null); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } [Fact] public void OnSetComponentDefaultsTest() { + TestControlDesigner controlDesigner = new TestControlDesigner(); #pragma warning disable 618 - Assert.Throws(() => controlDesigner.OnSetComponentDefaults()); + Assert.NotNull(controlDesigner); + controlDesigner.Initialize(new Button()); + try + { + controlDesigner.OnSetComponentDefaults(); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } #pragma warning restore 618 } [Fact] public void OnContextMenuTest() { - Assert.Null(Record.Exception(() => controlDesigner.OnContextMenuMethod(0, 0))); + TestControlDesigner controlDesigner = new TestControlDesigner(); + try + { + controlDesigner.OnContextMenuMethod(0, 0); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } [Fact] public void OnCreateHandleTest() { - Assert.Throws(() => controlDesigner.OnCreateHandleMethod()); + TestControlDesigner controlDesigner = new TestControlDesigner(); + Assert.NotNull(controlDesigner); + controlDesigner.Initialize(new Button()); + try + { + controlDesigner.OnCreateHandleMethod(); + } + catch (Exception ex) + { + Assert.True(false, "Expected no exception, but got: " + ex.Message); + } } } } diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionItemCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionItemCollectionTests.cs deleted file mode 100644 index ea258c17671..00000000000 --- a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionItemCollectionTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.ComponentModel.Design; -using Xunit; - -namespace System.Windows.Forms.Design.Tests -{ - public class DesignerActionItemCollectionTests - { - [Fact] - public void DesignerActionItemCollection_Constructor() - { - DesignerActionItemCollection underTest = new DesignerActionItemCollection(); - Assert.NotNull(underTest); - Assert.Empty(underTest); - } - - [Fact] - public void DesignerActionItemCollection_Add_Contains_IndexOf() - { - DesignerActionItemCollection underTest = new DesignerActionItemCollection(); - - DesignerActionItem item1 = new DesignerActionItemTest("name", "category", "description"); - underTest.Add(item1); - Assert.True(underTest.Contains(item1)); - Assert.Equal(0, underTest.IndexOf(item1)); - - DesignerActionItem item2 = new DesignerActionItemTest("name1", "category1", "description1"); - underTest.Add(item2); - Assert.True(underTest.Contains(item2)); - Assert.Equal(1, underTest.IndexOf(item2)); - } - - [Fact] - public void DesignerActionItemCollection_Insert_Remove_Count() - { - DesignerActionItemCollection underTest = new DesignerActionItemCollection(); - DesignerActionItem item1 = new DesignerActionItemTest("name", "category", "description"); - DesignerActionItem item2 = new DesignerActionItemTest("name1", "category1", "description1"); - DesignerActionItem item3 = new DesignerActionItemTest("name2", "category2", "description2"); - DesignerActionItem item4 = new DesignerActionItemTest("name3", "category3", "description3"); - - underTest.Add(item1); - underTest.Add(item2); - - underTest.Add(item3); - Assert.Equal(2, underTest.IndexOf(item3)); - - underTest.Insert(2, item4); - Assert.Equal(3, underTest.IndexOf(item3)); - Assert.Equal(2, underTest.IndexOf(item4)); - - underTest.Remove(item4); - Assert.False(underTest.Contains(item4)); - Assert.Equal(2, underTest.IndexOf(item3)); - Assert.Equal(3, underTest.Count); - } - - private class DesignerActionItemTest : DesignerActionItem - { - public DesignerActionItemTest(string displayName, string category, string description) : base(displayName, category, description) - { - } - } - } -} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionListCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionListCollectionTests.cs deleted file mode 100644 index e871d4719e4..00000000000 --- a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionListCollectionTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.ComponentModel.Design; -using WinForms.Common.Tests; -using Xunit; - -namespace System.Windows.Forms.Design.Tests -{ - public class DesignerActionListCollectionTests - { - [Fact] - public void DesignerActionListCollection_Constructor() - { - DesignerActionListCollection underTest = new DesignerActionListCollection(); - Assert.NotNull(underTest); - } - - [Fact] - public void DesignerActionListCollection_Constructor_DesignerActionList() - { - DesignerActionListCollection underTest = CreateNewCollectionOfItems(); - Assert.NotNull(underTest); - } - - [Fact] - public void DesignerActionItemCollection_Add_AddRange() - { - DesignerActionListCollection underTest = CreateNewCollectionOfItems(5); - Assert.Equal(5, underTest.Count); - - Button button = new Button(); - DesignerActionList list = new DesignerActionList(button); - underTest.Add(list); - Assert.Equal(6, underTest.Count); - - DesignerActionListCollection other = CreateNewCollectionOfItems(3); - underTest.AddRange(other); - Assert.Equal(9, underTest.Count); - } - - - [Fact] - public void DesignerActionItemCollection_Insert_Contains_IndexOf() - { - DesignerActionListCollection underTest = CreateNewCollectionOfItems(5); - - Button button = new Button(); - DesignerActionList list = new DesignerActionList(button); - underTest.Insert(3, list); - Assert.True(underTest.Contains(list)); - Assert.Equal(3, underTest.IndexOf(list)); - } - - [Fact] - public void DesignerActionItemCollection_Remove() - { - DesignerActionListCollection underTest = CreateNewCollectionOfItems(5); - - Button button = new Button(); - DesignerActionList list = new DesignerActionList(button); - underTest.Insert(3, list); - underTest.Remove(list); - Assert.False(underTest.Contains(list)); - Assert.Equal(5, underTest.Count); - } - - private DesignerActionListCollection CreateNewCollectionOfItems(int numberOfItems = 1) - { - Button button = new Button(); - DesignerActionList[] list = new DesignerActionList[] { new DesignerActionList(button) }; - DesignerActionListCollection underTest = new DesignerActionListCollection(list); - - for (int i = 1; i < numberOfItems; i++) - { - underTest.Add(new DesignerActionList(button)); - } - - return underTest; - } - } -} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionMethodItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionMethodItemTests.cs deleted file mode 100644 index eee7ac462eb..00000000000 --- a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionMethodItemTests.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.ComponentModel.Design; -using WinForms.Common.Tests; -using Xunit; - -namespace System.Windows.Forms.Design.Tests -{ - public class DesignerActionMethodItemTests - { - [Theory] - [InlineData("memberName", "displayName", "category", "description", true)] - [InlineData("memberName", "displayName", "category", "", true)] - [InlineData("memberName", "displayName", "", "", false)] - [InlineData("memberName", "", "", "", false)] - public void DesignerActionMethodItem_Constructor(string memberName, string displayName, string category, string description, bool includeAsDesignerVerb) - { - DesignerActionMethodItem underTest = CreateDesignerActionMethodItem(memberName, displayName, category, description, includeAsDesignerVerb); - Assert.NotNull(underTest); - Assert.Equal(memberName, underTest.MemberName); - Assert.Equal(displayName, underTest.DisplayName); - Assert.Equal(category, underTest.Category); - Assert.Equal(description, underTest.Description); - Assert.Equal(includeAsDesignerVerb, underTest.IncludeAsDesignerVerb); - } - - [Fact] - public void DesignerActionMethodItem_Constructor2() - { - DesignerActionMethodItem underTest = CreateDesignerActionMethodItem("memberName", "displayName", "category"); - Assert.NotNull(underTest); - Assert.Equal("memberName", underTest.MemberName); - Assert.Equal("displayName", underTest.DisplayName); - Assert.Equal("category", underTest.Category); - Assert.Null(underTest.Description); - } - - [Fact] - public void DesignerActionMethodItem_Constructor3() - { - DesignerActionMethodItem underTest = CreateDesignerActionMethodItem("memberName", "displayName"); - Assert.NotNull(underTest); - Assert.Equal("memberName", underTest.MemberName); - Assert.Equal("displayName", underTest.DisplayName); - Assert.Null(underTest.Category); - Assert.Null(underTest.Description); - } - - [Fact] - public void DesignerActionMethodItem_RelatedComponent_getter_setter() - { - DesignerActionMethodItem underTest = CreateDesignerActionMethodItem("memberName", "displayName"); - - Button button = new Button(); - underTest.RelatedComponent = button; - Assert.Equal(button, underTest.RelatedComponent); - } - - private DesignerActionMethodItem CreateDesignerActionMethodItem(string memberName, string displayName, string category, string description, bool includeAsDesignerVerb) - { - Button button = new Button(); - DesignerActionList actionList = new DesignerActionList(button); - - if (category == null && description == null) - { - return new DesignerActionMethodItem(actionList, memberName, displayName, includeAsDesignerVerb); - } - else if (description == null) - { - return new DesignerActionMethodItem(actionList, memberName, displayName, category, includeAsDesignerVerb); - } - else - { - return new DesignerActionMethodItem(actionList, memberName, displayName, category, description, includeAsDesignerVerb); - } - } - - private DesignerActionMethodItem CreateDesignerActionMethodItem(string memberName, string displayName, string category, string description) - { - return CreateDesignerActionMethodItem(memberName, displayName, category, description, false); - } - - private DesignerActionMethodItem CreateDesignerActionMethodItem(string memberName, string displayName, string category) - { - return CreateDesignerActionMethodItem(memberName, displayName, category, null, false); - } - private DesignerActionMethodItem CreateDesignerActionMethodItem(string memberName, string displayName) - { - return CreateDesignerActionMethodItem(memberName, displayName, null, null, false); - } - } -} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionPropertyItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionPropertyItemTests.cs deleted file mode 100644 index 4ce807673e4..00000000000 --- a/src/System.Windows.Forms.Design/tests/UnitTests/DesignerActionPropertyItemTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.ComponentModel.Design; -using WinForms.Common.Tests; -using Xunit; - -namespace System.Windows.Forms.Design.Tests -{ - public class DesignerActionPropertyItemTests - { - [Theory] - [InlineData("memberName", "displayName", "category", "description")] - [InlineData("memberName", "displayName", "category", "")] - [InlineData("memberName", "displayName", "", "")] - [InlineData("memberName", "", "", "")] - public void DesignerActionPropertyItem_Constructor(string memberName, string displayName, string category, string description) - { - DesignerActionPropertyItem underTest = new DesignerActionPropertyItem(memberName, displayName, category, description); - Assert.NotNull(underTest); - Assert.Equal(memberName, underTest.MemberName); - Assert.Equal(displayName, underTest.DisplayName); - Assert.Equal(category, underTest.Category); - Assert.Equal(description, underTest.Description); - } - - [Fact] - public void DesignerActionPropertyItem_Constructor2() - { - DesignerActionPropertyItem underTest = new DesignerActionPropertyItem("memberName", "displayName", "category"); - Assert.NotNull(underTest); - Assert.Equal("memberName", underTest.MemberName); - Assert.Equal("displayName", underTest.DisplayName); - Assert.Equal("category", underTest.Category); - Assert.Null(underTest.Description); - } - - [Fact] - public void DesignerActionPropertyItem_Constructor3() - { - DesignerActionPropertyItem underTest = new DesignerActionPropertyItem("memberName", "displayName"); - Assert.NotNull(underTest); - Assert.Equal("memberName", underTest.MemberName); - Assert.Equal("displayName", underTest.DisplayName); - Assert.Null(underTest.Category); - Assert.Null(underTest.Description); - } - - [Fact] - public void DesignerActionPropertyItem_RelatedComponent_getter_setter() - { - DesignerActionPropertyItem underTest = new DesignerActionPropertyItem("name", "displayname"); - - Button button = new Button(); - underTest.RelatedComponent = button; - Assert.Equal(button, underTest.RelatedComponent); - - } - } -} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x16.bmp b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x16.bmp new file mode 100644 index 00000000000..8bf35136370 Binary files /dev/null and b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x16.bmp differ diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x24.bmp b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x24.bmp new file mode 100644 index 00000000000..9fa2469f870 Binary files /dev/null and b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x24.bmp differ diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Resources/24x16.bmp b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/24x16.bmp new file mode 100644 index 00000000000..d3fdc521f1f Binary files /dev/null and b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/24x16.bmp differ diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CodeDomSerializerExceptionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CodeDomSerializerExceptionTests.cs deleted file mode 100644 index eb09161140c..00000000000 --- a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CodeDomSerializerExceptionTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.CodeDom; -using System.ComponentModel.Design.Serialization; -using Moq; -using Xunit; - -namespace System.Windows.Forms.Design.Serialization.Tests -{ - public class CodeDomSerializerExceptionTests - { - Mock _mockDesignerSerializationManager; - - [Fact] - public void CodeDomSerializerException_Constructor_Message_Pragma() - { - var pragma = new CodeLinePragma(); - var underTest = new CodeDomSerializerException("message", pragma); - Assert.NotNull(underTest); - Assert.Equal(pragma, underTest.LinePragma); - } - - [Fact] - public void CodeDomSerializerException_Constructor_Exception_Pragma() - { - var ex = new Exception(); - var pragma = new CodeLinePragma(); - var underTest = new CodeDomSerializerException(ex, pragma); - Assert.NotNull(underTest); - Assert.Equal(pragma, underTest.LinePragma); - } - - [Fact] - public void CodeDomSerializerException_Constructor_SerializationManager() - { - _mockDesignerSerializationManager = new Mock(MockBehavior.Strict); - var underTest = new CodeDomSerializerException("message", _mockDesignerSerializationManager.Object); - Assert.NotNull(underTest); - } - - [Fact] - public void CodeDomSerializerException_Constructor_Exception_SerializationManager() - { - var ex = new Exception(); - _mockDesignerSerializationManager = new Mock(MockBehavior.Strict); - var underTest = new CodeDomSerializerException(ex, _mockDesignerSerializationManager.Object); - Assert.NotNull(underTest); - } - } -} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CollectionCodeDomSerializerTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CollectionCodeDomSerializerTests.cs index b5aa4372701..e0e72414e56 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CollectionCodeDomSerializerTests.cs +++ b/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/CollectionCodeDomSerializerTests.cs @@ -12,7 +12,7 @@ public class CollectionCodeDomSerializerTests [Fact] public void CollectionCodeDomSerializer_Constructor() { - var underTest = CollectionCodeDomSerializer.GetDefault(); + var underTest = CollectionCodeDomSerializer.Default; Assert.NotNull(underTest); } } diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/ExpressionContextTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/ExpressionContextTests.cs deleted file mode 100644 index d03fa06e376..00000000000 --- a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/ExpressionContextTests.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.CodeDom; -using System.ComponentModel.Design.Serialization; -using Xunit; - -namespace System.Windows.Forms.Design.Serialization.Tests -{ - public class ExpressionContextTests - { - [Fact] - public void ExpressionContext_Constructor() - { - CodeExpression expression = new CodeExpression(); - Type type = expression.GetType(); - object owner = "owner"; - object presetValue = null; - - var underTest = new ExpressionContext(expression, type, owner, presetValue); - Assert.NotNull(underTest); - Assert.Equal(expression, underTest.Expression); - } - } -} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/TypeCodeDomSerializerTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/TypeCodeDomSerializerTests.cs new file mode 100644 index 00000000000..910eb1b34cf --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/Serialization/TypeCodeDomSerializerTests.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.CodeDom; +using System.CodeDom.Compiler; +using Moq; +using Xunit; + +namespace System.ComponentModel.Design.Serialization.Tests +{ + public class TypeCodeDomSerializerTests + { + [Fact] + public void TypeCodeDomSerializer_Constructor() + { + var underTest = new TypeCodeDomSerializer(); + Assert.NotNull(underTest); + } + + [Fact] + public void TypeCodeDomSerializer_Serialize_Manager_Null () + { + var underTest = new TypeCodeDomSerializer(); + Assert.Throws(() => underTest.Serialize(null, null, null)); + } + + [Fact] + public void TypeCodeDomSerializer_Serialize_Root_Null() + { + var mockSerializationManager = new Mock(MockBehavior.Strict); + var underTest = new TypeCodeDomSerializer(); + Assert.Throws(() => underTest.Serialize(mockSerializationManager.Object, null, null)); + } + + [Fact] + public void TypeCodeDomSerializer_Deserialize_Manager_Null() + { + var underTest = new TypeCodeDomSerializer(); + Assert.Throws(() => underTest.Deserialize(null, null)); + } + + [Fact] + public void TypeCodeDomSerializer_Deserialize_CodeTypeDec_Null() + { + var mockSerializationManager = new Mock(MockBehavior.Strict); + var underTest = new TypeCodeDomSerializer(); + Assert.Throws(() => underTest.Deserialize(mockSerializationManager.Object, null)); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj b/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj index 2db090483e3..3c66db51f45 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj @@ -14,8 +14,20 @@ + + + + System.Drawing.Design.Tests.16x16.bmp + + + System.Drawing.Design.Tests.24x16.bmp + + + System.Drawing.Design.Tests.16x24.bmp + + diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionHeaderItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionHeaderItemTests.cs new file mode 100644 index 00000000000..93c48db9808 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionHeaderItemTests.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Specialized; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionHeaderItemTests + { + [Theory] + [InlineData("displayName", "category", "displayName")] + [InlineData("displa(&a)yName", "cate(&a)gory", "displayName")] + [InlineData("", "", "")] + [InlineData(null, null, null)] + public void DesignerActionItem_Ctor_String_String(string displayName, string category, string expectedDisplayName) + { + var item = new DesignerActionHeaderItem(displayName, category); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Null(item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + } + + [Theory] + [InlineData("displayName", "displayName")] + [InlineData("displa(&a)yName", "displayName")] + [InlineData("", "")] + [InlineData(null, null)] + public void DesignerActionItem_Ctor_String(string displayName, string expectedDisplayName) + { + var item = new DesignerActionHeaderItem(displayName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(displayName, item.Category); + Assert.Null(item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionItemCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionItemCollectionTests.cs new file mode 100644 index 00000000000..453e955f5b8 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionItemCollectionTests.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionItemCollectionTests + { + [Fact] + public void DesignerActionItemCollection_Ctor_Default() + { + var collection = new DesignerActionItemCollection(); + Assert.Empty(collection); + } + + [Fact] + public void DesignerActionItemCollection_Add_DesignerActionItem_Success() + { + var collection = new DesignerActionItemCollection(); + + var value1 = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value1); + Assert.Same(value1, Assert.Single(collection)); + Assert.Same(value1, collection[0]); + Assert.True(collection.Contains(value1)); + Assert.Equal(0, collection.IndexOf(value1)); + + var value2 = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value2); + Assert.Equal(new object[] { value1, value2 }, collection.Cast()); + Assert.True(collection.Contains(value2)); + Assert.Equal(1, collection.IndexOf(value2)); + } + + [Fact] + public void DesignerActionItemCollection_Add_NullValue_ThrowsArgumentNullException() + { + var collection = new DesignerActionItemCollection(); + Assert.Throws("value", () => collection.Add(null)); + } + + [Fact] + public void DesignerActionItemCollection_Insert_DesignerActionItem_Success() + { + var collection = new DesignerActionItemCollection(); + + var value1 = new SubDesignerActionItem("displayName", "category", "description"); + collection.Insert(0, value1); + Assert.Same(value1, Assert.Single(collection)); + Assert.Same(value1, collection[0]); + Assert.True(collection.Contains(value1)); + Assert.Equal(0, collection.IndexOf(value1)); + + var value2 = new SubDesignerActionItem("displayName", "category", "description"); + collection.Insert(0, value2); + Assert.Equal(new object[] { value2, value1 }, collection.Cast()); + Assert.True(collection.Contains(value2)); + Assert.Equal(0, collection.IndexOf(value2)); + } + + [Fact] + public void DesignerActionItemCollection_Insert_NullValue_ThrowsArgumentNullException() + { + var collection = new DesignerActionItemCollection(); + Assert.Throws("value", () => collection.Insert(0, null)); + } + + [Fact] + public void DesignerActionItemCollection_Remove_Invoke_Success() + { + var collection = new DesignerActionItemCollection(); + var value = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value); + Assert.Same(value, Assert.Single(collection)); + + collection.Remove(value); + Assert.Empty(collection); + Assert.False(collection.Contains(value)); + Assert.Equal(-1, collection.IndexOf(value)); + } + + [Fact] + public void DesignerActionItemCollection_Remove_NullValue_ThrowsArgumentNullException() + { + var collection = new DesignerActionItemCollection(); + Assert.Throws("value", () => collection.Remove(null)); + } + + [Fact] + public void DesignerActionItemCollection_Item_Set_GetReturnsExpected() + { + var collection = new DesignerActionItemCollection(); + var value1 = new SubDesignerActionItem("displayName", "category", "description"); + var value2 = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value1); + Assert.Same(value1, Assert.Single(collection)); + + collection[0] = value2; + Assert.Same(value2, Assert.Single(collection)); + Assert.Same(value2, collection[0]); + Assert.False(collection.Contains(value1)); + Assert.Equal(-1, collection.IndexOf(value1)); + Assert.True(collection.Contains(value2)); + Assert.Equal(0, collection.IndexOf(value2)); + } + + [Fact] + public void DesignerActionItemCollection_Item_SetNull_ThrowsArgumentNullException() + { + var collection = new DesignerActionItemCollection(); + var value = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value); + Assert.Throws("value", () => collection[0] = null); + } + + [Fact] + public void DesignerActionItemCollection_CopyTo_Invoke_Success() + { + var collection = new DesignerActionItemCollection(); + var value = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value); + + var array = new DesignerActionItem[3]; + collection.CopyTo(array, 1); + Assert.Equal(new DesignerActionItem[] { null, value, null }, array); + } + + [Fact] + public void DesignerActionItemCollection_Contains_NoSuchValue_ReturnsFalse() + { + var collection = new DesignerActionItemCollection(); + var value = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value); + + Assert.False(collection.Contains(new SubDesignerActionItem("displayName", "category", "description"))); + Assert.False(collection.Contains(null)); + } + + [Fact] + public void DesignerActionItemCollection_IndexOf_NoSuchValue_ReturnsNegativeOne() + { + var collection = new DesignerActionItemCollection(); + var value = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value); + + Assert.Equal(-1, collection.IndexOf(new SubDesignerActionItem("displayName", "category", "description"))); + Assert.Equal(-1, collection.IndexOf(null)); + } + + [Fact] + public void DesignerActionItemCollection_Clear_Success() + { + var collection = new DesignerActionItemCollection(); + var value = new SubDesignerActionItem("displayName", "category", "description"); + collection.Add(value); + + collection.Clear(); + Assert.Empty(collection); + + // Clear again. + collection.Clear(); + Assert.Empty(collection); + } + + private class SubDesignerActionItem : DesignerActionItem + { + public SubDesignerActionItem(string displayName, string category, string description) : base(displayName, category, description) + { + } + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionItemTests.cs new file mode 100644 index 00000000000..1d45ff3ac0b --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionItemTests.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionItemTests + { + [Theory] + [InlineData("displayName", "category", "description", "displayName")] + [InlineData("displa(&a)yName", "cate(&a)gory", "descr(&a)iption", "displayName")] + [InlineData("", "", "", "")] + [InlineData(null, null, null, null)] + public void DesignerActionItem_Ctor_String_String_String(string displayName, string category, string description, string expectedDisplayName) + { + var item = new SubDesignerActionItem(displayName, category, description); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Equal(description, item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerActionItem_AllowAssociate_Set_GetReturnsExpected(bool value) + { + var item = new SubDesignerActionItem("displayName", "category", "description") + { + AllowAssociate = value + }; + Assert.Equal(value, item.AllowAssociate); + + // Set same. + item.AllowAssociate = value; + Assert.Equal(value, item.AllowAssociate); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerActionItem_ShowInSourceView_Set_GetReturnsExpected(bool value) + { + var item = new SubDesignerActionItem("displayName", "category", "description") + { + ShowInSourceView = value + }; + Assert.Equal(value, item.ShowInSourceView); + + // Set same. + item.ShowInSourceView = value; + Assert.Equal(value, item.ShowInSourceView); + } + + private class SubDesignerActionItem : DesignerActionItem + { + public SubDesignerActionItem(string displayName, string category, string description) : base(displayName, category, description) + { + } + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListCollectionTests.cs new file mode 100644 index 00000000000..2a5faee57c8 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListCollectionTests.cs @@ -0,0 +1,209 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionListCollectionTests + { + [Fact] + public void DesignerActionListCollection_Ctor_Default() + { + var collection = new DesignerActionListCollection(); + Assert.Empty(collection); + } + + public static IEnumerable Ctor_DesignerActionListArray_TestData() + { + yield return new object[] { new DesignerActionList[0] }; + yield return new object[] { new DesignerActionList[] { new DesignerActionList(null), null } }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionListArray_TestData))] + public void DesignerActionListCollection_Ctor_DesignerActionListArray(DesignerActionList[] value) + { + var collection = new DesignerActionListCollection(value); + Assert.Equal(value, collection.Cast()); + } + + [Fact] + public void DesignerActionListCollection_Ctor_NullValue_ThrowsArgumentNullException() + { + Assert.Throws("value", () => new DesignerActionListCollection(null)); + } + + [Fact] + public void DesignerActionListCollection_Add_DesignerActionList_Success() + { + var collection = new DesignerActionListCollection(); + + var value1 = new DesignerActionList(null); + collection.Add(value1); + Assert.Same(value1, Assert.Single(collection)); + Assert.Same(value1, collection[0]); + Assert.True(collection.Contains(value1)); + Assert.Equal(0, collection.IndexOf(value1)); + + var value2 = new DesignerActionList(null); + collection.Add(value2); + Assert.Equal(new object[] { value1, value2 }, collection.Cast()); + Assert.True(collection.Contains(value2)); + Assert.Equal(1, collection.IndexOf(value2)); + + collection.Add(null); + Assert.Equal(new object[] { value1, value2, null }, collection.Cast()); + Assert.True(collection.Contains(null)); + Assert.Equal(2, collection.IndexOf(null)); + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionListArray_TestData))] + public void DesignerActionListCollection_AddRange_DesignerActionListArray_Success(DesignerActionList[] value) + { + var collection = new DesignerActionListCollection(); + collection.AddRange(value); + Assert.Equal(value, collection.Cast()); + + // Add again. + collection.AddRange(value); + Assert.Equal(value.Concat(value), collection.Cast()); + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionListArray_TestData))] + public void DesignerActionListCollection_AddRange_DesignerActionListCollection_Success(DesignerActionList[] value) + { + var collection = new DesignerActionListCollection(); + collection.AddRange(new DesignerActionListCollection(value)); + Assert.Equal(value, collection.Cast()); + + // Add again. + collection.AddRange(new DesignerActionListCollection(value)); + Assert.Equal(value.Concat(value), collection.Cast()); + } + + [Fact] + public void DesignerActionListCollection_Insert_DesignerActionList_Success() + { + var collection = new DesignerActionListCollection(); + + var value1 = new DesignerActionList(null); + collection.Insert(0, value1); + Assert.Same(value1, Assert.Single(collection)); + Assert.Same(value1, collection[0]); + Assert.True(collection.Contains(value1)); + Assert.Equal(0, collection.IndexOf(value1)); + + var value2 = new DesignerActionList(null); + collection.Insert(0, value2); + Assert.Equal(new object[] { value2, value1 }, collection.Cast()); + Assert.True(collection.Contains(value2)); + Assert.Equal(0, collection.IndexOf(value2)); + + collection.Insert(1, null); + Assert.Equal(new object[] { value2, null, value1 }, collection.Cast()); + Assert.True(collection.Contains(null)); + Assert.Equal(1, collection.IndexOf(null)); + } + + [Fact] + public void DesignerActionListCollection_Remove_Invoke_Success() + { + var collection = new DesignerActionListCollection(); + var value = new DesignerActionList(null); + collection.Add(value); + Assert.Same(value, Assert.Single(collection)); + + collection.Remove(value); + Assert.Empty(collection); + Assert.False(collection.Contains(value)); + Assert.Equal(-1, collection.IndexOf(value)); + + collection.Add(null); + collection.Remove(null); + Assert.Empty(collection); + Assert.False(collection.Contains(null)); + Assert.Equal(-1, collection.IndexOf(null)); + } + + [Fact] + public void DesignerActionListCollection_Item_Set_GetReturnsExpected() + { + var collection = new DesignerActionListCollection(); + var value1 = new DesignerActionList(null); + var value2 = new DesignerActionList(null); + collection.Add(value1); + Assert.Same(value1, Assert.Single(collection)); + + collection[0] = value2; + Assert.Same(value2, Assert.Single(collection)); + Assert.Same(value2, collection[0]); + Assert.False(collection.Contains(value1)); + Assert.Equal(-1, collection.IndexOf(value1)); + Assert.True(collection.Contains(value2)); + Assert.Equal(0, collection.IndexOf(value2)); + + collection[0] = null; + Assert.Null(Assert.Single(collection)); + Assert.Null(collection[0]); + Assert.False(collection.Contains(value2)); + Assert.Equal(-1, collection.IndexOf(value2)); + Assert.True(collection.Contains(null)); + Assert.Equal(0, collection.IndexOf(null)); + } + + [Fact] + public void DesignerActionListCollection_CopyTo_Invoke_Success() + { + var collection = new DesignerActionListCollection(); + var value = new DesignerActionList(null); + collection.Add(value); + + var array = new DesignerActionList[3]; + collection.CopyTo(array, 1); + Assert.Equal(new DesignerActionList[] { null, value, null }, array); + } + + [Fact] + public void DesignerActionListCollection_Contains_NoSuchValue_ReturnsFalse() + { + var collection = new DesignerActionListCollection(); + var value = new DesignerActionList(null); + collection.Add(value); + + Assert.False(collection.Contains(new DesignerActionList(null))); + Assert.False(collection.Contains(null)); + } + + [Fact] + public void DesignerActionListCollection_IndexOf_NoSuchValue_ReturnsNegativeOne() + { + var collection = new DesignerActionListCollection(); + var value = new DesignerActionList(null); + collection.Add(value); + + Assert.Equal(-1, collection.IndexOf(new DesignerActionList(null))); + Assert.Equal(-1, collection.IndexOf(null)); + } + + [Fact] + public void DesignerActionListCollection_Clear_Success() + { + var collection = new DesignerActionListCollection(); + var value = new DesignerActionList(null); + collection.Add(value); + + collection.Clear(); + Assert.Empty(collection); + + // Clear again. + collection.Clear(); + Assert.Empty(collection); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListTests.cs new file mode 100644 index 00000000000..50973392849 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListTests.cs @@ -0,0 +1,205 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionListTests + { + public static IEnumerable Ctor_IComponent_TestDat() + { + yield return new object[] { null }; + yield return new object[] { new Component() }; + } + + [Theory] + [MemberData(nameof(Ctor_IComponent_TestDat))] + public void DesignerActionList_Ctor_IComponent(IComponent component) + { + var list = new DesignerActionList(component); + Assert.Equal(component, list.Component); + Assert.False(list.AutoShow); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerActionList_AutoShow_Set_GetReturnsExpected(bool value) + { + var list = new DesignerActionList(new Component()) + { + AutoShow = value + }; + Assert.Equal(value, list.AutoShow); + + // Set same. + list.AutoShow = value; + Assert.Equal(value, list.AutoShow); + } + + public static IEnumerable GetService_TestData() + { + yield return new object[] { null, null }; + yield return new object[] { new Component(), null }; + + var o = new object(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.GetService(typeof(int))) + .Returns(o); + mockSite + .Setup(s => s.Container) + .Returns((IContainer)null); + yield return new object[] { new Component { Site = mockSite.Object }, o }; + } + + [Theory] + [MemberData(nameof(GetService_TestData))] + public void DesignerActionList_GetService_Invoke_ReturnsExpected(Component component, object expected) + { + var list = new DesignerActionList(component); + Assert.Equal(expected, list.GetService(typeof(int))); + } + + [Fact] + public void DesignerActionList_GetSortedActionItems_CustomClass_ReturnsExpected() + { + var list = new SubDesignerActionList(); + DesignerActionItemCollection items = list.GetSortedActionItems(); + Assert.Equal(8, items.Count); + + DesignerActionMethodItem item1 = Assert.IsType(items[0]); + Assert.Equal("AnnotatedMethod", item1.MemberName); + Assert.Equal("DisplayName", item1.DisplayName); + Assert.Equal("Description", item1.Description); + Assert.Equal("Category", item1.Category); + + DesignerActionPropertyItem item2 = Assert.IsType(items[1]); + Assert.Equal("AnnotatedProperty", item2.MemberName); + Assert.Equal("DisplayName", item2.DisplayName); + Assert.Equal("Description", item2.Description); + Assert.Equal("Category", item2.Category); + + DesignerActionMethodItem item3 = Assert.IsType(items[2]); + Assert.Equal("EmptyAnnotatedMethod", item3.MemberName); + Assert.Equal("EmptyAnnotatedMethod", item3.DisplayName); + Assert.Empty(item3.Description); + Assert.Empty(item3.Category); + + DesignerActionPropertyItem item4 = Assert.IsType(items[3]); + Assert.Equal("EmptyAnnotatedProperty", item4.MemberName); + Assert.Equal("EmptyAnnotatedProperty", item4.DisplayName); + Assert.Empty(item4.Description); + Assert.Empty(item4.Category); + + DesignerActionMethodItem item5 = Assert.IsType(items[4]); + Assert.Equal("NullAnnotatedMethod", item5.MemberName); + Assert.Equal("NullAnnotatedMethod", item5.DisplayName); + Assert.Null(item5.Description); + Assert.Null(item5.Category); + + DesignerActionPropertyItem item6 = Assert.IsType(items[5]); + Assert.Equal("NullAnnotatedProperty", item6.MemberName); + Assert.Equal("NullAnnotatedProperty", item6.DisplayName); + Assert.Null(item6.Description); + Assert.Null(item6.Category); + + DesignerActionMethodItem item7 = Assert.IsType(items[6]); + Assert.Equal("PublicMethod", item7.MemberName); + Assert.Equal("PublicMethod", item7.DisplayName); + Assert.Empty(item7.Description); + Assert.Empty(item7.Category); + + DesignerActionPropertyItem item8 = Assert.IsType(items[7]); + Assert.Equal("PublicProperty", item8.MemberName); + Assert.Equal("PublicProperty", item8.DisplayName); + Assert.Empty(item8.Description); + Assert.Empty(item8.Category); + } + + [Fact] + public void DesignerActionList_GetSortedActionItems_BaseClass_ReturnsEmpty() + { + var list = new DesignerActionList(null); + DesignerActionItemCollection items = list.GetSortedActionItems(); + Assert.Empty(items); + } + + private class SubDesignerActionList : DesignerActionList + { + public SubDesignerActionList() : base(null) + { + } + + public void PublicMethod() + { + } + + [Description("Description")] + [DisplayName("DisplayName")] + [Category("Category")] + public void AnnotatedMethod() + { + } + + [Description("")] + [DisplayName("")] + [Category("")] + public void EmptyAnnotatedMethod() + { + } + + [Description(null)] + [DisplayName(null)] + [Category(null)] + public void NullAnnotatedMethod() + { + } + + private void PrivateMethod() + { + } + + public void MethodWithParameters(object o) + { + } + + [SpecialName] + public void MethodWithSpecialName() + { + } + + public static void StaticMethod() + { + } + + public int PublicProperty { get; set; } + + [Description("Description")] + [DisplayName("DisplayName")] + [Category("Category")] + public int AnnotatedProperty { get; set; } + + [Description("")] + [DisplayName("")] + [Category("")] + public int EmptyAnnotatedProperty { get; set; } + + [Description(null)] + [DisplayName(null)] + [Category(null)] + public int NullAnnotatedProperty { get; set; } + + private int PrivateProperty { get; set; } + + public static int StaticProperty { get; set; } + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListsChangedEventArgsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListsChangedEventArgsTests.cs new file mode 100644 index 00000000000..495f2c09ef0 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionListsChangedEventArgsTests.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionListsChangedEventArgsTests + { + public static IEnumerable Ctor_Object_DesignerActionListsChangedType_DesignerActionListCollection_TestData() + { + yield return new object[] { null, DesignerActionListsChangedType.ActionListsAdded - 1, null }; + yield return new object[] { new object(), DesignerActionListsChangedType.ActionListsAdded, new DesignerActionListCollection() }; + } + + [Theory] + [MemberData(nameof(Ctor_Object_DesignerActionListsChangedType_DesignerActionListCollection_TestData))] + public void Ctor_Object_DesignerActionListsChangedType_DesignerActionListCollection(object relatedObject, DesignerActionListsChangedType changeType, DesignerActionListCollection actionLists) + { + var e = new DesignerActionListsChangedEventArgs(relatedObject, changeType, actionLists); + Assert.Same(relatedObject, e.RelatedObject); + Assert.Equal(changeType, e.ChangeType); + Assert.Same(actionLists, e.ActionLists); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionMethodItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionMethodItemTests.cs new file mode 100644 index 00000000000..a07245949e6 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionMethodItemTests.cs @@ -0,0 +1,274 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Reflection; +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionMethodItemTests + { + public static IEnumerable Ctor_DesignerActionList_String_String_String_String_Bool_TestData() + { + yield return new object[] { new DesignerActionList(null), "memberName", "displayName", "category", "description", false, "displayName" }; + yield return new object[] { new DesignerActionList(null), "member(&a)Name", "displa(&a)yName", "cate(&a)gory", "description", true, "displayName" }; + yield return new object[] { null, string.Empty, string.Empty, string.Empty, string.Empty, false, string.Empty }; + yield return new object[] { null, null, null, null, null, false, null }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionList_String_String_String_String_Bool_TestData))] + public void DesignerActionMethodItem_Ctor_DesignerActionList_String_String_String_String_Bool(DesignerActionList actionList, string memberName, string displayName, string category, string description, bool includeAsDesignerVerb, string expectedDisplayName) + { + var item = new DesignerActionMethodItem(actionList, memberName, displayName, category, description, includeAsDesignerVerb); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Equal(description, item.Description); + Assert.Equal(includeAsDesignerVerb, item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable Ctor_DesignerActionList_String_String_String_String_TestData() + { + yield return new object[] { new DesignerActionList(null), "memberName", "displayName", "category", "description", "displayName" }; + yield return new object[] { new DesignerActionList(null), "member(&a)Name", "displa(&a)yName", "cate(&a)gory", "description", "displayName" }; + yield return new object[] { null, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty }; + yield return new object[] { null, null, null, null, null, null }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionList_String_String_String_String_TestData))] + public void DesignerActionMethodItem_Ctor_DesignerActionList_String_String_String_String(DesignerActionList actionList, string memberName, string displayName, string category, string description, string expectedDisplayName) + { + var item = new DesignerActionMethodItem(actionList, memberName, displayName, category, description); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Equal(description, item.Description); + Assert.False(item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable Ctor_DesignerActionList_String_String_String_Bool_TestData() + { + yield return new object[] { new DesignerActionList(null), "memberName", "displayName", "category", false, "displayName" }; + yield return new object[] { new DesignerActionList(null), "member(&a)Name", "displa(&a)yName", "cate(&a)gory", true, "displayName" }; + yield return new object[] { null, string.Empty, string.Empty, string.Empty, false, string.Empty }; + yield return new object[] { null, null, null, null, false, null }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionList_String_String_String_Bool_TestData))] + public void DesignerActionMethodItem_Ctor_DesignerActionList_String_String_String_Bool(DesignerActionList actionList, string memberName, string displayName, string category, bool includeAsDesignerVerb, string expectedDisplayName) + { + var item = new DesignerActionMethodItem(actionList, memberName, displayName, category, includeAsDesignerVerb); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Null(item.Description); + Assert.Equal(includeAsDesignerVerb, item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable Ctor_DesignerActionList_String_String_String_TestData() + { + yield return new object[] { new DesignerActionList(null), "memberName", "displayName", "category", "displayName" }; + yield return new object[] { new DesignerActionList(null), "member(&a)Name", "displa(&a)yName", "cate(&a)gory", "displayName" }; + yield return new object[] { null, string.Empty, string.Empty, string.Empty, string.Empty }; + yield return new object[] { null, null, null, null, null }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionList_String_String_String_TestData))] + public void DesignerActionMethodItem_Ctor_DesignerActionList_String_String_String(DesignerActionList actionList, string memberName, string displayName, string category, string expectedDisplayName) + { + var item = new DesignerActionMethodItem(actionList, memberName, displayName, category); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Null(item.Description); + Assert.False(item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable Ctor_DesignerActionList_String_String_Bool_TestData() + { + yield return new object[] { new DesignerActionList(null), "memberName", "displayName", false, "displayName" }; + yield return new object[] { new DesignerActionList(null), "member(&a)Name", "displa(&a)yName", true, "displayName" }; + yield return new object[] { null, string.Empty, string.Empty, false, string.Empty }; + yield return new object[] { null, null, null, false, null }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionList_String_String_Bool_TestData))] + public void DesignerActionMethodItem_Ctor_DesignerActionList_String_String_Bool(DesignerActionList actionList, string memberName, string displayName, bool includeAsDesignerVerb, string expectedDisplayName) + { + var item = new DesignerActionMethodItem(actionList, memberName, displayName, includeAsDesignerVerb); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Null(item.Category); + Assert.Null(item.Description); + Assert.Equal(includeAsDesignerVerb, item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable Ctor_DesignerActionList_String_String_TestData() + { + yield return new object[] { new DesignerActionList(null), "memberName", "displayName", "displayName" }; + yield return new object[] { new DesignerActionList(null), "member(&a)Name", "displa(&a)yName", "displayName" }; + yield return new object[] { null, string.Empty, string.Empty, string.Empty }; + yield return new object[] { null, null, null, null }; + } + + [Theory] + [MemberData(nameof(Ctor_DesignerActionList_String_String_TestData))] + public void DesignerActionMethodItem_Ctor_DesignerActionList_String_String(DesignerActionList actionList, string memberName, string displayName, string expectedDisplayName) + { + var item = new DesignerActionMethodItem(actionList, memberName, displayName); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Null(item.Category); + Assert.Null(item.Description); + Assert.False(item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable RelatedComponent_Set_TestData() + { + yield return new object[] { new Component() }; + yield return new object[] { null }; + } + + [Theory] + [MemberData(nameof(RelatedComponent_Set_TestData))] + public void DesignerActionMethodItem_RelatedComponent_Set_GetReturnsExpected(IComponent value) + { + var item = new DesignerActionMethodItem(null, "memberName", "displayName", "category", "description") + { + RelatedComponent = value + }; + Assert.Same(value, item.RelatedComponent); + + // Set same. + item.RelatedComponent = value; + Assert.Same(value, item.RelatedComponent); + } + + [Theory] + [InlineData(nameof(SubDesignerActionList.PublicMethod))] + [InlineData("PrivateMethod")] + public void Invoke_ValidMemberName_ReturnsExpected(string memberName) + { + var list = new SubDesignerActionList(); + var item = new DesignerActionMethodItem(list, memberName, "displayName", "category", "description"); + item.Invoke(); + Assert.Equal(memberName, list.CalledMethod); + + // Call again to test caching behaviour. + list.CalledMethod = null; + item.Invoke(); + Assert.Equal(memberName, list.CalledMethod); + } + + [Fact] + public void Invoke_NullActionList_ThrowsInvalidOperationException() + { + var item = new DesignerActionMethodItem(null, "memberName", "displayName", "category", "description"); + Assert.Throws(() => item.Invoke()); + } + + [Theory] + [InlineData("")] + [InlineData("NoSuchMember")] + [InlineData(nameof(SubDesignerActionList.StaticMethod))] + public void Invoke_NoSuchMemberName_ThrowsInvalidOperationException(string memberName) + { + var list = new SubDesignerActionList(); + var item = new DesignerActionMethodItem(list, memberName, "displayName", "category", "description"); + Assert.Throws(() => item.Invoke()); + } + + [Fact] + public void Invoke_NullMemberName_ThrowsArgumentNullException() + { + var list = new SubDesignerActionList(); + var item = new DesignerActionMethodItem(list, null, "displayName", "category", "description"); + Assert.Throws("name", () => item.Invoke()); + } + + [Fact] + public void Invoke_MemberWithParameters_ThrowsTargetParameterCountException() + { + var list = new SubDesignerActionList(); + var item = new DesignerActionMethodItem(list, nameof(SubDesignerActionList.MethodWithParameters), "displayName", "category", "description"); + Assert.Throws(() => item.Invoke()); + } + + private class SubDesignerActionList : DesignerActionList + { + public SubDesignerActionList() : base(null) + { + } + + public string CalledMethod { get; set; } + + public void PublicMethod() + { + Assert.Null(CalledMethod); + CalledMethod = nameof(PublicMethod); + } + + private void PrivateMethod() + { + Assert.Null(CalledMethod); + CalledMethod = nameof(PrivateMethod); + } + + public static void StaticMethod() + { + throw new InvalidOperationException(); + } + + public void MethodWithParameters(object o) + { + throw new InvalidOperationException(); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionPropertyItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionPropertyItemTests.cs new file mode 100644 index 00000000000..088cf9a16e4 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionPropertyItemTests.cs @@ -0,0 +1,96 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionPropertyItemTests + { + [Theory] + [InlineData("memberName", "displayName", "category", "description", "displayName")] + [InlineData("member(&a)Name", "displa(&a)yName", "cate(&a)gory", "descr(&a)iption", "displayName")] + [InlineData("", "", "", "", "")] + [InlineData(null, null, null, null, null)] + public void DesignerActionPropertyItem_Ctor_String_String_String_String(string memberName, string displayName, string category, string description, string expectedDisplayName) + { + var item = new DesignerActionPropertyItem(memberName, displayName, category, description); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Equal(description, item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + [Theory] + [InlineData("memberName", "displayName", "category", "displayName")] + [InlineData("member(&a)Name", "displa(&a)yName", "cate(&a)gory", "displayName")] + [InlineData("", "", "", "")] + [InlineData(null, null, null, null)] + public void DesignerActionPropertyItem_Ctor_String_String_String(string memberName, string displayName, string category, string expectedDisplayName) + { + var item = new DesignerActionPropertyItem(memberName, displayName, category); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Null(item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + [Theory] + [InlineData("memberName", "displayName", "displayName")] + [InlineData("member(&a)Name", "displa(&a)yName", "displayName")] + [InlineData("", "", "")] + [InlineData(null, null, null)] + public void DesignerActionPropertyItem_Ctor_String_String(string memberName, string displayName, string expectedDisplayName) + { + var item = new DesignerActionPropertyItem(memberName, displayName); + Assert.Equal(memberName, item.MemberName); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Null(item.Category); + Assert.Null(item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + public static IEnumerable RelatedComponent_Set_TestData() + { + yield return new object[] { new Component() }; + yield return new object[] { null }; + } + + [Theory] + [MemberData(nameof(RelatedComponent_Set_TestData))] + public void DesignerActionPropertyItem_RelatedComponent_Set_GetReturnsExpected(IComponent value) + { + var item = new DesignerActionPropertyItem("memberName", "displayName", "category", "description") + { + RelatedComponent = value + }; + Assert.Same(value, item.RelatedComponent); + + // Set same. + item.RelatedComponent = value; + Assert.Same(value, item.RelatedComponent); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionTextItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionTextItemTests.cs new file mode 100644 index 00000000000..c65d1756b83 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionTextItemTests.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Specialized; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionTextItemTests + { + [Theory] + [InlineData("displayName", "category", "displayName")] + [InlineData("displa(&a)yName", "cate(&a)gory", "displayName")] + [InlineData("", "", "")] + [InlineData(null, null, null)] + public void DesignerActionItem_Ctor_String_String(string displayName, string category, string expectedDisplayName) + { + var item = new DesignerActionTextItem(displayName, category); + Assert.Equal(expectedDisplayName, item.DisplayName); + Assert.Equal(category, item.Category); + Assert.Null(item.Description); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionUIStateChangeEventArgsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionUIStateChangeEventArgsTests.cs new file mode 100644 index 00000000000..ad66eca14e7 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionUIStateChangeEventArgsTests.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionUIStateChangeEventArgsTests + { + public static IEnumerable Ctor_Object_DesignerActionUIStateChangeType_TestData() + { + yield return new object[] { null, DesignerActionUIStateChangeType.Show - 1 }; + yield return new object[] { new object(), DesignerActionUIStateChangeType.Show }; + } + + [Theory] + [MemberData(nameof(Ctor_Object_DesignerActionUIStateChangeType_TestData))] + public void Ctor_Object_DesignerActionUIStateChangeType(object relatedObject, DesignerActionUIStateChangeType changeType) + { + var e = new DesignerActionUIStateChangeEventArgs(relatedObject, changeType); + Assert.Same(relatedObject, e.RelatedObject); + Assert.Equal(changeType, e.ChangeType); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionVerbItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionVerbItemTests.cs new file mode 100644 index 00000000000..38e4aebe072 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerActionVerbItemTests.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Specialized; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerActionVerbItemTests + { + [Fact] + public void DesignerActionVerbItem_Ctor_DesignerVerb() + { + var verb = new DesignerVerb("text", null); + var item = new DesignerActionVerbItem(verb); + Assert.Null(item.MemberName); + Assert.Equal("text", item.DisplayName); + Assert.Equal("Verbs", item.Category); + Assert.Null(item.Description); + Assert.False(item.IncludeAsDesignerVerb); + Assert.False(item.AllowAssociate); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.IsType(item.Properties); + Assert.True(item.ShowInSourceView); + Assert.Null(item.RelatedComponent); + } + + [Fact] + public void DesignerActionVerbItem_Ctor_NullVerb_ThrowsArgumentNullException() + { + Assert.Throws("verb", () => new DesignerActionVerbItem(null)); + } + + [Fact] + public void DesignerActionVerbItem_Invoke_Invoke_CallsVerbInvoke() + { + DesignerVerb verb = null; + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(verb, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + verb = new DesignerVerb("text", handler); + var item = new DesignerActionVerbItem(verb); + item.Invoke(); + Assert.Equal(1, callCount); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerCommandSetTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerCommandSetTests.cs new file mode 100644 index 00000000000..a2a1c93d2a0 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/DesignerCommandSetTests.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class DesignerCommandSetTests + { + [Fact] + public void DesignerCommandSet_Ctor_Default() + { + var set = new DesignerCommandSet(); + Assert.Null(set.ActionLists); + Assert.Null(set.Verbs); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void DesignerCommandSet_GetCommands_Invoke_ReturnsNull(string name) + { + var set = new DesignerCommandSet(); + Assert.Null(set.GetCommands(name)); + } + + [Fact] + public void DesignerCommandSet_Verbs_OverridenGetCommands_ReturnsExpected() + { + var collection = new DesignerVerbCollection(); + var mockSet = new Mock(MockBehavior.Strict); + mockSet + .Setup(s => s.GetCommands("Verbs")) + .Returns(collection); + Assert.Same(collection, mockSet.Object.Verbs); + } + + [Fact] + public void DesignerCommandSet_Verbs_InvalidOverridenGetCommands_ThrowsInvalidCastException() + { + var mockSet = new Mock(MockBehavior.Strict); + mockSet + .Setup(s => s.GetCommands("Verbs")) + .Returns(new object[0]); + Assert.Throws(() => mockSet.Object.Verbs); + } + + [Fact] + public void DesignerCommandSet_ActionLists_OverridenGetCommands_ReturnsExpected() + { + var collection = new DesignerActionListCollection(); + var mockSet = new Mock(MockBehavior.Strict); + mockSet + .Setup(s => s.GetCommands("ActionLists")) + .Returns(collection); + Assert.Same(collection, mockSet.Object.ActionLists); + } + + [Fact] + public void DesignerCommandSet_ActionLists_InvalidOverridenGetCommands_ThrowsInvalidCastException() + { + var mockSet = new Mock(MockBehavior.Strict); + mockSet + .Setup(s => s.GetCommands("ActionLists")) + .Returns(new object[0]); + Assert.Throws(() => mockSet.Object.ActionLists); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/ExceptionCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/ExceptionCollectionTests.cs new file mode 100644 index 00000000000..eb0908474c0 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/ExceptionCollectionTests.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class ExceptionCollectionTests + { + public static IEnumerable Ctor_ArrayList_TestData() + { + yield return new object[] { null }; + yield return new object[] { new ArrayList() }; + yield return new object[] { new ArrayList { 1, 2, 3 } }; + } + + [Theory] + [MemberData(nameof(Ctor_ArrayList_TestData))] + public void ExceptionCollection_Ctor_ArrayList(ArrayList exceptions) + { + var collection = new ExceptionCollection(exceptions); + if (exceptions == null) + { + Assert.Null(collection.Exceptions); + } + else + { + Assert.Equal(exceptions, collection.Exceptions); + Assert.NotSame(exceptions, collection.Exceptions); + Assert.Equal(collection.Exceptions, collection.Exceptions); + Assert.NotSame(collection.Exceptions, collection.Exceptions); + } + } + + [Theory] + [MemberData(nameof(Ctor_ArrayList_TestData))] + public void ExceptionCollection_Serialize_Deserialize_Success(ArrayList exceptions) + { + using (var stream = new MemoryStream()) + { + var formatter = new BinaryFormatter(); + var collection = new ExceptionCollection(exceptions); + formatter.Serialize(stream, collection); + + stream.Position = 0; + ExceptionCollection deserialized = Assert.IsType(formatter.Deserialize(stream)); + Assert.Equal(exceptions, deserialized.Exceptions); + } + } + + [Fact] + public void ExceptionCollection_GetObjectData_NullInfo_ThrowsArgumentNullException() + { + var collection = new ExceptionCollection(new ArrayList()); + Assert.Throws("info", () => collection.GetObjectData(null, new StreamingContext())); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/LoadedEventArgsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/LoadedEventArgsTests.cs new file mode 100644 index 00000000000..b9851ec8627 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/LoadedEventArgsTests.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class LoadedEventArgsTests + { + public static IEnumerable Ctor_Bool_ICollection_TestData() + { + yield return new object[] { true, null }; + yield return new object[] { false, new object[0] }; + yield return new object[] { true, new object[] { null } }; + } + + [Theory] + [MemberData(nameof(Ctor_Bool_ICollection_TestData))] + public void Ctor_Bool_ICollection(bool succeeded, ICollection errors) + { + var e = new LoadedEventArgs(succeeded, errors); + Assert.Equal(succeeded, e.HasSucceeded); + if (errors == null) + { + Assert.Empty(e.Errors); + } + else + { + Assert.Same(errors, e.Errors); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/ProjectTargetFrameworkAttributeTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/ProjectTargetFrameworkAttributeTests.cs new file mode 100644 index 00000000000..a49b73e3e1d --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/ProjectTargetFrameworkAttributeTests.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class ProjectTargetFrameworkAttributeTests + { + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void ProjectTargetFrameworkAttribute_Ctor_String(string targetFrameworkMoniker) + { + var attribute = new ProjectTargetFrameworkAttribute(targetFrameworkMoniker); + Assert.Equal(targetFrameworkMoniker, attribute.TargetFrameworkMoniker); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/CodeDomSerializerExceptionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/CodeDomSerializerExceptionTests.cs new file mode 100644 index 00000000000..ebb9a521f4d --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/CodeDomSerializerExceptionTests.cs @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.CodeDom; +using System.Collections.Generic; +using System.ComponentModel.Design.Serialization; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using Moq; +using Xunit; + +namespace System.Windows.Forms.Design.Serialization.Tests +{ + public class CodeDomSerializerExceptionTests + { + public static IEnumerable Ctor_String_CodeLinePragma_TestData() + { + yield return new object[] { "message", new CodeLinePragma() }; + yield return new object[] { null, null }; + } + + [Theory] + [MemberData(nameof(Ctor_String_CodeLinePragma_TestData))] + public void CodeDomSerializerException_Ctor_String_CodeLinePragma(string message, CodeLinePragma linePragma) + { + var exception = new CodeDomSerializerException(message, linePragma); + Assert.NotEmpty(exception.Message); + Assert.Null(exception.InnerException); + Assert.Same(linePragma, exception.LinePragma); + } + + public static IEnumerable Ctor_Exception_CodeLinePragma_TestData() + { + yield return new object[] { new Exception(), new CodeLinePragma() }; + yield return new object[] { null, null }; + } + + [Theory] + [MemberData(nameof(Ctor_Exception_CodeLinePragma_TestData))] + public void CodeDomSerializerException_Ctor_Exception_CodeLinePragma(Exception innerException, CodeLinePragma linePragma) + { + var exception = new CodeDomSerializerException(innerException, linePragma); + Assert.NotEmpty(exception.Message); + Assert.Same(innerException, exception.InnerException); + Assert.Same(linePragma, exception.LinePragma); + } + + public static IEnumerable Ctor_String_IDesignerSerializationManager_TestData() + { + var mockDesignerSerializationManager = new Mock(MockBehavior.Strict); + yield return new object[] { "message", mockDesignerSerializationManager.Object }; + yield return new object[] { null, mockDesignerSerializationManager.Object }; + } + + [Theory] + [MemberData(nameof(Ctor_String_IDesignerSerializationManager_TestData))] + public void CodeDomSerializerException_Ctor_String_IDesignerSerializationManager(string message, IDesignerSerializationManager manager) + { + var exception = new CodeDomSerializerException(message, manager); + Assert.NotEmpty(exception.Message); + Assert.Null(exception.InnerException); + Assert.Null(exception.LinePragma); + } + + public static IEnumerable Ctor_Exception_IDesignerSerializationManager_TestData() + { + var mockDesignerSerializationManager = new Mock(MockBehavior.Strict); + yield return new object[] { new Exception(), mockDesignerSerializationManager.Object }; + yield return new object[] { null, mockDesignerSerializationManager.Object }; + } + + [Theory] + [MemberData(nameof(Ctor_Exception_IDesignerSerializationManager_TestData))] + public void CodeDomSerializerException_Ctor_Exception_IDesignerSerializationManager(Exception innerException, IDesignerSerializationManager manager) + { + var exception = new CodeDomSerializerException(innerException, manager); + Assert.NotEmpty(exception.Message); + Assert.Same(innerException, exception.InnerException); + Assert.Null(exception.LinePragma); + } + + [Fact] + public void CodeDomSerializerException_NullManager_ThrowsArgumentNullException() + { + Assert.Throws("manager", () => new CodeDomSerializerException("message", (IDesignerSerializationManager)null)); + Assert.Throws("manager", () => new CodeDomSerializerException(new Exception(), (IDesignerSerializationManager)null)); + } + + [Fact] + public void CodeDomSerializerException_SerializeWithoutPragma_Deserialize_Success() + { + using (var stream = new MemoryStream()) + { + var formatter = new BinaryFormatter(); + var exception = new CodeDomSerializerException("message", (CodeLinePragma)null); + formatter.Serialize(stream, exception); + + stream.Position = 0; + CodeDomSerializerException deserialized = Assert.IsType(formatter.Deserialize(stream)); + Assert.Equal(exception.Message, deserialized.Message); + Assert.Null(deserialized.LinePragma); + } + } + + [Fact] + public void CodeDomSerializerException_SerializeWithPragma_Deserialize_Success() + { + using (var stream = new MemoryStream()) + { + var formatter = new BinaryFormatter(); + var exception = new CodeDomSerializerException("message", new CodeLinePragma()); + Assert.Throws(() => formatter.Serialize(stream, exception)); + } + } + + [Fact] + public void CodeDomSerializerException_GetObjectData_NullInfo_ThrowsArgumentNullException() + { + var exception = new CodeDomSerializerException("message", new CodeLinePragma()); + Assert.Throws("info", () => exception.GetObjectData(null, new StreamingContext())); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/ExpressionContextTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/ExpressionContextTests.cs new file mode 100644 index 00000000000..cea66d7c28f --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/ExpressionContextTests.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.CodeDom; +using System.Collections.Generic; +using Xunit; + +namespace System.ComponentModel.Design.Serialization.Tests +{ + public class ExpressionContextTests + { + public static IEnumerable Ctor_CodeExpression_Type_Object_Object_TestData() + { + yield return new object[] { new CodeExpression(), typeof(int), new object(), new object() }; + yield return new object[] { new CodeExpression(), typeof(int), new object(), null }; + } + + [Theory] + [MemberData(nameof(Ctor_CodeExpression_Type_Object_Object_TestData))] + public void ExpressionContext_Ctor_CodeExpression_Type_Object_Object_TestData(CodeExpression expression, Type expressionType, object owner, object presetValue) + { + var context = new ExpressionContext(expression, expressionType, owner, presetValue); + Assert.Same(expression, context.Expression); + Assert.Same(expressionType, context.ExpressionType); + Assert.Same(owner, context.Owner); + Assert.Same(presetValue, context.PresetValue); + } + public static IEnumerable Ctor_CodeExpression_Type_Object_TestData() + { + yield return new object[] { new CodeExpression(), typeof(int), new object() }; + } + + [Theory] + [MemberData(nameof(Ctor_CodeExpression_Type_Object_TestData))] + public void ExpressionContext_Ctor_CodeExpression_Type_Object_TestData(CodeExpression expression, Type expressionType, object owner) + { + var context = new ExpressionContext(expression, expressionType, owner); + Assert.Same(expression, context.Expression); + Assert.Same(expressionType, context.ExpressionType); + Assert.Same(owner, context.Owner); + Assert.Null(context.PresetValue); + } + + [Fact] + public void ExpressionContext_Ctor_NullExpression_ThrowsArgumentNullException() + { + Assert.Throws("expression", () => new ExpressionContext(null, typeof(int), new object(), new object())); + } + + [Fact] + public void RootContext_Ctor_NullExpressionType_ThrowsArgumentNullException() + { + Assert.Throws("expressionType", () => new ExpressionContext(new CodeExpression(), null, new object(), new object())); + } + + [Fact] + public void RootContext_Ctor_NullOwner_ThrowsArgumentNullException() + { + Assert.Throws("owner", () => new ExpressionContext(new CodeExpression(), typeof(int), null, new object())); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/RootContextTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/RootContextTests.cs new file mode 100644 index 00000000000..467568420dd --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/RootContextTests.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.CodeDom; +using Xunit; + +namespace System.ComponentModel.Design.Serialization.Tests +{ + public class RootContextTests + { + [Fact] + public void RootContext_Ctor_CodeExpression_Object() + { + var expression = new CodeExpression(); + var value = new object(); + var context = new RootContext(expression, value); + Assert.Same(expression, context.Expression); + Assert.Same(value, context.Value); + } + + [Fact] + public void RootContext_Ctor_NullExpression_ThrowsArgumentNullException() + { + Assert.Throws("expression", () => new RootContext(null, new object())); + } + + [Fact] + public void RootContext_Ctor_NullValue_ThrowsArgumentNullException() + { + var expression = new CodeExpression(); + Assert.Throws("value", () => new RootContext(expression, null)); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/SerializeAbsoluteContextTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/SerializeAbsoluteContextTests.cs new file mode 100644 index 00000000000..d301475c386 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/SerializeAbsoluteContextTests.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Xunit; + +namespace System.ComponentModel.Design.Serialization.Tests +{ + public class SerializeAbsoluteContextTests + { + [Fact] + public void SerializeAbsoluteContext_Ctor_Default() + { + var context = new SerializeAbsoluteContext(); + Assert.Null(context.Member); + } + + public static IEnumerable Ctor_MemberDescriptor_TestData() + { + yield return new object[] { null }; + + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(RootContext)); + yield return new object[] { properties[nameof(RootContext.Expression)] }; + } + + [Theory] + [MemberData(nameof(Ctor_MemberDescriptor_TestData))] + public void SerializeAbsoluteContext_Ctor_MemberDescriptor(MemberDescriptor member) + { + var context = new SerializeAbsoluteContext(member); + Assert.Same(member, context.Member); + } + + public static IEnumerable ShouldSerialize_TestData() + { + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(RootContext)); + MemberDescriptor member1 = properties[nameof(RootContext.Expression)]; + MemberDescriptor member2 = properties[nameof(RootContext.Value)]; + + yield return new object[] { new SerializeAbsoluteContext(null), null, true }; + yield return new object[] { new SerializeAbsoluteContext(null), member1, true }; + + yield return new object[] { new SerializeAbsoluteContext(member1), null, false }; + yield return new object[] { new SerializeAbsoluteContext(member1), member1, true }; + yield return new object[] { new SerializeAbsoluteContext(member2), member2, true }; + } + + [Theory] + [MemberData(nameof(ShouldSerialize_TestData))] + public void SerializeAbsoluteContext_ShouldSerialize_Invoke_ReturnsExpected(SerializeAbsoluteContext context, MemberDescriptor member, bool expected) + { + Assert.Equal(expected, context.ShouldSerialize(member)); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/StatementContextTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/StatementContextTests.cs new file mode 100644 index 00000000000..8b32fb2343c --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/Serialization/StatementContextTests.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.ComponentModel.Design.Serialization.Tests +{ + public class StatementContextTests + { + [Fact] + public void StatementContext_Ctor_Default() + { + var context = new StatementContext(); + Assert.Empty(context.StatementCollection); + Assert.Same(context.StatementCollection, context.StatementCollection); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/UndoUnitTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/UndoUnitTests.cs new file mode 100644 index 00000000000..cd1ba09ed6f --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/ComponentModel/Design/UndoUnitTests.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Design.Serialization; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.ComponentModel.Design.Tests +{ + public class UndoUnitTests: UndoEngine + { + public UndoUnitTests() : base(GetServiceProvider()) + { + } + + private static IServiceProvider GetServiceProvider() + { + var mockServiceProvider = new Mock(); + var mockDesignerHost = new Mock(); + var mockComponentChangeService = new Mock(); + mockServiceProvider + .Setup(p => p.GetService(typeof(IDesignerHost))) + .Returns(mockDesignerHost.Object); + mockServiceProvider + .Setup(p => p.GetService(typeof(IComponentChangeService))) + .Returns(mockComponentChangeService.Object); + mockServiceProvider + .Setup(p => p.GetService(typeof(ComponentSerializationService))) + .Returns(new object()); + return mockServiceProvider.Object; + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void UndoUnit_Ctor_UndoEngine_String(string name) + { + var unit = new SubUndoUnit(this, name); + Assert.Same(this, unit.UndoEngine); + Assert.Equal(name ?? string.Empty, unit.Name); + Assert.True(unit.IsEmpty); + } + + [Fact] + public void UndoUnit_NullEngine_ThrowsArgumentNullException() + { + Assert.Throws("engine", () => new UndoUnit(null, "name")); + } + + protected override void AddUndoUnit(UndoUnit unit) + { + } + + protected class SubUndoUnit : UndoUnit + { + public SubUndoUnit(UndoEngine engine, string name) : base(engine, name) + { + } + + public new UndoEngine UndoEngine => base.UndoEngine; + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxComponentsCreatedEventArgsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxComponentsCreatedEventArgsTests.cs new file mode 100644 index 00000000000..4a4679e5fd3 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxComponentsCreatedEventArgsTests.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class ToolboxComponentsCreatedEventArgsTests + { + public static IEnumerable Ctor_IComponentArray_TestData() + { + yield return new object[] { null }; + yield return new object[] { new IComponent[0] }; + yield return new object[] { new IComponent[] { null } }; + } + + [Theory] + [MemberData(nameof(Ctor_IComponentArray_TestData))] + public void Ctor_IComponentArray(IComponent[] components) + { + var e = new ToolboxComponentsCreatedEventArgs(components); + if (components == null) + { + Assert.Null(e.Components); + } + else + { + Assert.Equal(components, e.Components); + Assert.NotSame(components, e.Components); + Assert.Equal(e.Components, e.Components); + Assert.NotSame(e.Components, e.Components); + } + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxComponentsCreatingEventArgsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxComponentsCreatingEventArgsTests.cs new file mode 100644 index 00000000000..96e3967bb18 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxComponentsCreatingEventArgsTests.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel.Design; +using Moq; +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class ToolboxComponentsCreatingEventArgsTests + { + public static IEnumerable Ctor_IDesignerHost_TestData() + { + yield return new object[] { null }; + yield return new object[] { new Mock(MockBehavior.Strict).Object }; + } + + [Theory] + [MemberData(nameof(Ctor_IDesignerHost_TestData))] + public void Ctor_IDesignerHost(IDesignerHost host) + { + var e = new ToolboxComponentsCreatingEventArgs(host); + Assert.Equal(host, e.DesignerHost); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs new file mode 100644 index 00000000000..0c65b8cc261 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class ToolboxItemCollectionTests + { + [Fact] + public void ToolboxItemCollection_Ctor_ToolboxItemArray() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + Assert.Same(item, Assert.Single(collection)); + Assert.Same(item, collection[0]); + Assert.True(collection.Contains(item)); + Assert.Equal(0, collection.IndexOf(item)); + } + + [Fact] + public void ToolboxItemCollection_Ctor_NullToolboxItemArray_ThrowsArgumentNullException() + { + Assert.Throws("c", () => new ToolboxItemCollection((ToolboxItem[])null)); + } + + [Fact] + public void ToolboxItemCollection_Ctor_ToolboxItemCollection() + { + var item = new ToolboxItem(); + var value = new ToolboxItemCollection(new ToolboxItem[] { item }); + var collection = new ToolboxItemCollection(value); + Assert.Same(item, Assert.Single(collection)); + Assert.Same(item, collection[0]); + Assert.True(collection.Contains(item)); + Assert.Equal(0, collection.IndexOf(item)); + } + + [Fact] + public void ToolboxItemCollection_Ctor_NullToolboxItemCollection_ThrowsArgumentNullException() + { + Assert.Throws("c", () => new ToolboxItemCollection((ToolboxItemCollection)null)); + } + + [Fact] + public void ToolboxItemCollection_Contains_NoSuchValue_ReturnsFalse() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + Assert.False(collection.Contains(new ToolboxItem { DisplayName = "Other" })); + Assert.False(collection.Contains(null)); + } + + [Fact] + public void ToolboxItemCollection_IndexOf_NoSuchValue_ReturnsNegativeOne() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + Assert.Equal(-1, collection.IndexOf(new ToolboxItem { DisplayName = "Other" })); + Assert.Equal(-1, collection.IndexOf(null)); + } + + [Fact] + public void ToolboxItemCollection_CopyTo_Invoke_Success() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + + var array = new ToolboxItem[3]; + collection.CopyTo(array, 1); + Assert.Equal(new ToolboxItem[] { null, item, null }, array); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs new file mode 100644 index 00000000000..56f0e181697 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs @@ -0,0 +1,1775 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class ToolboxItemTests + { + [Fact] + public void ToolboxItem_Ctor_Default() + { + var item = new ToolboxItem(); + Assert.Null(item.AssemblyName); + Assert.Null(item.Bitmap); + Assert.Null(item.Company); + Assert.Equal(".NET Component", item.ComponentType); + Assert.Null(item.DependentAssemblies); + Assert.Null(item.Description); + Assert.Empty(item.DisplayName); + Assert.Empty(item.Filter); + Assert.Same(item.Filter, item.Filter); + Assert.False(item.IsTransient); + Assert.False(item.Locked); + Assert.Null(item.OriginalBitmap); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.False(item.Properties.IsFixedSize); + Assert.False(item.Properties.IsReadOnly); + Assert.Empty(item.TypeName); + Assert.Empty(item.Version); + } + + public static IEnumerable AssemblyName_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new AssemblyName() }; + yield return new object[] { new AssemblyName(typeof(int).Assembly.FullName) }; + } + + [Theory] + [MemberData(nameof(AssemblyName_Set_TestData))] + public void ToolboxItem_AssemblyName_Set_GetReturnsExpected(AssemblyName value) + { + var item = new ToolboxItem + { + AssemblyName = value + }; + if (value == null) + { + Assert.Null(item.AssemblyName); + Assert.Null(item.Properties["AssemblyName"]); + Assert.Empty(item.Version); + } + else + { + Assert.Equal(value.FullName, item.AssemblyName.FullName); + Assert.NotSame(value, item.AssemblyName); + Assert.NotSame(item.AssemblyName, item.AssemblyName); + Assert.Equal(value.FullName, ((AssemblyName)item.Properties["AssemblyName"]).FullName); + Assert.NotSame(value, item.Properties["AssemblyName"]); + Assert.NotSame(item.Properties["AssemblyName"], item.Properties["AssemblyName"]); + Assert.Equal(value.Version?.ToString() ?? string.Empty, item.Version); + } + + // Set same. + item.AssemblyName = value; + if (value == null) + { + Assert.Null(item.AssemblyName); + Assert.Null(item.Properties["AssemblyName"]); + Assert.Empty(item.Version); + } + else + { + Assert.Equal(value.FullName, item.AssemblyName.FullName); + Assert.NotSame(value, item.AssemblyName); + Assert.NotSame(item.AssemblyName, item.AssemblyName); + Assert.Equal(value.FullName, ((AssemblyName)item.Properties["AssemblyName"]).FullName); + Assert.NotSame(value, item.Properties["AssemblyName"]); + Assert.NotSame(item.Properties["AssemblyName"], item.Properties["AssemblyName"]); + Assert.Equal(value.Version?.ToString() ?? string.Empty, item.Version); + } + } + + [Fact] + public void ToolboxItem_AssemblyName_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("AssemblyName", new object())); + } + + public static IEnumerable Bitmap_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new Bitmap(10, 10) }; + } + + [Theory] + [MemberData(nameof(Bitmap_Set_TestData))] + public void ToolboxItem_Bitmap_Set_GetReturnsExpected(Bitmap value) + { + var item = new ToolboxItem + { + Bitmap = value + }; + Assert.Same(value, item.Bitmap); + Assert.Same(value, item.Properties["Bitmap"]); + + // Set same. + item.Bitmap = value; + Assert.Same(value, item.Bitmap); + Assert.Same(value, item.Properties["Bitmap"]); + } + + [Fact] + public void ToolboxItem_Bitmap_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Bitmap", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_Company_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + Company = value + }; + Assert.Same(value, item.Company); + Assert.Same(value, item.Properties["Company"]); + + // Set same. + item.Company = value; + Assert.Same(value, item.Company); + Assert.Same(value, item.Properties["Company"]); + } + + [Fact] + public void ToolboxItem_Company_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Company", new object())); + } + + public static IEnumerable DependentAssemblies_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new AssemblyName[0] }; + yield return new object[] { new AssemblyName[] { null } }; + yield return new object[] { new AssemblyName[] { new AssemblyName() } }; + } + + [Theory] + [MemberData(nameof(DependentAssemblies_Set_TestData))] + public void ToolboxItem_DependentAssemblies_Set_GetReturnsExpected(AssemblyName[] value) + { + var item = new ToolboxItem + { + DependentAssemblies = value + }; + if (value == null) + { + Assert.Null(item.DependentAssemblies); + Assert.Null(item.Properties["DependentAssemblies"]); + } + else + { + Assert.Equal(value, item.DependentAssemblies); + Assert.NotSame(value, item.DependentAssemblies); + Assert.Equal(value, item.Properties["DependentAssemblies"]); + Assert.NotSame(value, item.Properties["DependentAssemblies"]); + } + + // Set same. + item.DependentAssemblies = value; + if (value == null) + { + Assert.Null(item.DependentAssemblies); + Assert.Null(item.Properties["DependentAssemblies"]); + } + else + { + Assert.Equal(value, item.DependentAssemblies); + Assert.NotSame(value, item.DependentAssemblies); + Assert.Equal(value, item.Properties["DependentAssemblies"]); + Assert.NotSame(value, item.Properties["DependentAssemblies"]); + } + } + + [Fact] + public void ToolboxItem_DependentAssemblies_SetWithInvalidPropertyType_GetThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("DependentAssemblies", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_Description_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + Description = value + }; + Assert.Same(value, item.Description); + Assert.Same(value, item.Properties["Description"]); + + // Set same. + item.Description = value; + Assert.Same(value, item.Description); + Assert.Same(value, item.Properties["Description"]); + } + + [Fact] + public void ToolboxItem_Description_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Description", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_DisplayName_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + DisplayName = value + }; + Assert.Same(value ?? string.Empty, item.DisplayName); + Assert.Same(value ?? string.Empty, item.Properties["DisplayName"]); + + // Set same. + item.DisplayName = value; + Assert.Same(value ?? string.Empty, item.DisplayName); + Assert.Same(value ?? string.Empty, item.Properties["DisplayName"]); + } + + [Fact] + public void ToolboxItem_DisplayName_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("DisplayName", new object())); + } + + public static IEnumerable Filter_Set_TestData() + { + yield return new object[] { null, new object[0] }; + yield return new object[] { new object[0], new object[0] }; + yield return new object[] { new object[] { null }, new object[0] }; + yield return new object[] { new object[] { new object(), new ToolboxItemFilterAttribute("filterString") }, new object[] { new ToolboxItemFilterAttribute("filterString") } }; + } + + [Theory] + [MemberData(nameof(Filter_Set_TestData))] + public void ToolboxItem_Filter_Set_GetReturnsExpected(ICollection value, ICollection expected) + { + var item = new ToolboxItem + { + Filter = value + }; + Assert.Equal(expected , item.Filter); + Assert.Equal(expected, item.Properties["Filter"]); + + // Set same. + item.Filter = value; + Assert.Equal(expected , item.Filter); + Assert.Equal(expected, item.Properties["Filter"]); + } + + [Fact] + public void ToolboxItem_Filter_SetWithInvalidPropertyType_GetThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Filter", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void ToolboxItem_IsTransient_Set_GetReturnsExpected(bool value) + { + var item = new ToolboxItem + { + IsTransient = value + }; + Assert.Equal(value , item.IsTransient); + Assert.Equal(value, item.Properties["IsTransient"]); + + // Set same. + item.IsTransient = value; + Assert.Equal(value , item.IsTransient); + Assert.Equal(value, item.Properties["IsTransient"]); + } + + [Fact] + public void ToolboxItem_IsTransient_SetWithNullPropertyType_GetThrowsArgumentNullException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("IsTransient", null)); + } + + [Fact] + public void ToolboxItem_IsTransient_SetWithInvalidPropertyType_GetThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("IsTransient", new object())); + } + + [Theory] + [MemberData(nameof(Bitmap_Set_TestData))] + public void ToolboxItem_OriginalBitmap_Set_GetReturnsExpected(Bitmap value) + { + var item = new ToolboxItem + { + OriginalBitmap = value + }; + Assert.Same(value, item.OriginalBitmap); + Assert.Same(value, item.Properties["OriginalBitmap"]); + + // Set same. + item.OriginalBitmap = value; + Assert.Same(value, item.OriginalBitmap); + Assert.Same(value, item.Properties["OriginalBitmap"]); + } + + [Fact] + public void ToolboxItem_OriginalBitmap_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("OriginalBitmap", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_TypeName_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + TypeName = value + }; + Assert.Same(value ?? string.Empty, item.TypeName); + Assert.Same(value ?? string.Empty, item.Properties["TypeName"]); + + // Set same. + item.TypeName = value; + Assert.Same(value ?? string.Empty, item.TypeName); + Assert.Same(value ?? string.Empty, item.Properties["TypeName"]); + } + + [Fact] + public void ToolboxItem_TypeName_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("TypeName", new object())); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithoutHost_ReturnsExpected() + { + var item = new ToolboxItem + { + AssemblyName = typeof(Component).Assembly.GetName(true), + TypeName = "System.ComponentModel.Component" + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.IsType(Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.IsType(Assert.Single(item.CreateComponents())); + Assert.Equal(1, creatingCallCount); + Assert.Equal(1, createdCallCount); + + Assert.IsType(Assert.Single(item.CreateComponents(null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.IsType(Assert.Single(item.CreateComponents(null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + } + + public static IEnumerable CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_TestData() + { + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + + yield return new object[] { new Component(), null }; + yield return new object[] { new Component(), mockDesigner.Object }; + + yield return new object[] { null, null }; + yield return new object[] { null, mockDesigner.Object }; + } + + [Theory] + [MemberData(nameof(CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_TestData))] + public void ToolboxItem_CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_ReturnsExpected(Component component, IDesigner designer) + { + var item = new ToolboxItem + { + TypeName = "typeName" + }; + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(designer); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(1, creatingCallCount); + Assert.Equal(1, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithHostWithIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new ToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(1, creatingCallCount); + Assert.Equal(1, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithHostWithThrowingIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new ToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)) + .Throws(new Exception()); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())) + .Throws(new Exception()); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + mockDesignerHost + .Setup(h => h.DestroyComponent(component)); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(1, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object, null)); + Assert.Equal(2, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object, new Hashtable())); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithNullComponentsCoreWithHost_ReturnsExpected() + { + var item = new NullComponentsToolboxItem + { + TypeName = "typeName" + }; + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(new Component()); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.Components); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Null(item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(1, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Null(item.CreateComponents(mockDesignerHost.Object, null)); + Assert.Equal(2, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Null(item.CreateComponents(mockDesignerHost.Object, new Hashtable())); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Null(item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Theory] + [InlineData("")] + [InlineData("NoSuchType")] + [InlineData("System.Int32")] + public void ToolboxItem_CreateComponents_InvokeInvalidType_ReturnsEmpty(string typeName) + { + var item = new ToolboxItem + { + TypeName = typeName + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.Components); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + Assert.Empty(item.CreateComponents()); + Assert.Equal(1, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponentsCore_InvokeWithoutHost_ReturnsExpected() + { + var item = new SubToolboxItem + { + AssemblyName = typeof(Component).Assembly.GetName(true), + TypeName = "System.ComponentModel.Component" + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.IsType(Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.IsType(Assert.Single(item.CreateComponentsCore(null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.IsType(Assert.Single(item.CreateComponentsCore(null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Theory] + [MemberData(nameof(CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_TestData))] + public void ToolboxItem_CreateComponentsCore_InvokeWithHostWithNonIComponentInitializerDesigner_ReturnsExpected(Component component, IDesigner designer) + { + var item = new SubToolboxItem + { + TypeName = "typeName" + }; + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(designer); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponentsCore_InvokeWithHostWithIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new SubToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponentsCore_InvokeWithHostWithThrowingIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new SubToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)) + .Throws(new Exception()); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())) + .Throws(new Exception()); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + mockDesignerHost + .Setup(h => h.DestroyComponent(component)); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponentsCore(mockDesignerHost.Object, null)); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponentsCore(mockDesignerHost.Object, new Hashtable())); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Theory] + [InlineData("")] + [InlineData("NoSuchType")] + [InlineData("System.Int32")] + public void ToolboxItem_CreateComponentsCore_InvokeInvalidType_ReturnsEmpty(string typeName) + { + var item = new SubToolboxItem + { + TypeName = typeName + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.Components); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + Assert.Empty(item.CreateComponentsCore(null)); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CheckUnlocked_NotLocked_Nop() + { + var item = new SubToolboxItem(); + item.CheckUnlocked(); + item.CheckUnlocked(); + } + + [Fact] + public void ToolboxItem_CheckUnlocked_Locked_ThrowsInvalidOperationException() + { + var item = new SubToolboxItem(); + item.Lock(); + Assert.Throws(() => item.CheckUnlocked()); + } + + public static IEnumerable Equals_TestData() + { + var item = new ToolboxItem(); + yield return new object[] { item, item, true }; + yield return new object[] { item, new ToolboxItem(), true }; + yield return new object[] { item, new SubToolboxItem(), false }; + + yield return new object[] + { + item, + new ToolboxItem + { + Company = "Company", + DependentAssemblies = new AssemblyName[] { null }, + Description = "Description", + Filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }, + IsTransient = true + }, + true + }; + + yield return new object[] + { + new ToolboxItem { TypeName = "TypeName" }, + new ToolboxItem { TypeName = "TypeName" }, + true + }; + yield return new object[] + { + new ToolboxItem { TypeName = "TypeName" }, + new ToolboxItem { TypeName = "typename" }, + false + }; + yield return new object[] + { + new ToolboxItem { TypeName = "TypeName" }, + new ToolboxItem(), + false + }; + yield return new object[] + { + new ToolboxItem(), + new ToolboxItem { TypeName = "TypeName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { TypeName = null }, + new NoValidationToolboxItem { TypeName = null }, + true + }; + yield return new object[] + { + new NoValidationToolboxItem { TypeName = null }, + new NoValidationToolboxItem { TypeName = "TypeName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { TypeName = "TypeName" }, + new NoValidationToolboxItem { TypeName = null }, + false + }; + + yield return new object[] + { + new ToolboxItem { DisplayName = "DisplayName" }, + new ToolboxItem { DisplayName = "DisplayName" }, + true + }; + yield return new object[] + { + new ToolboxItem { DisplayName = "DisplayName" }, + new ToolboxItem { DisplayName = "displayname" }, + false + }; + yield return new object[] + { + new ToolboxItem { DisplayName = "DisplayName" }, + new ToolboxItem(), + false + }; + yield return new object[] + { + new ToolboxItem(), + new ToolboxItem { DisplayName = "DisplayName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { DisplayName = null }, + new NoValidationToolboxItem { DisplayName = null }, + true + }; + yield return new object[] + { + new NoValidationToolboxItem { DisplayName = null }, + new NoValidationToolboxItem { DisplayName = "TypeName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { DisplayName = "TypeName" }, + new NoValidationToolboxItem { DisplayName = null }, + false + }; + + yield return new object[] + { + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + true + }; + yield return new object[] + { + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + new ToolboxItem { AssemblyName = new AssemblyName("name") }, + false + }; + yield return new object[] + { + new ToolboxItem(), + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + false + }; + yield return new object[] + { + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + new ToolboxItem(), + false + }; + + yield return new object[] { new ToolboxItem(), new object(), false }; + yield return new object[] { new ToolboxItem(), null, false }; + } + + [Theory] + [MemberData(nameof(Equals_TestData))] + public void ToolboxItem_Equals_Invoke_ReturnsExpected(ToolboxItem item, object other, bool expected) + { + Assert.Equal(expected, item.Equals(other)); + + } + + public static IEnumerable FilterPropertyValue_TestData() + { + var o = new object(); + yield return new object[] { "AssemblyName", null, null, true }; + yield return new object[] { "AssemblyName", new AssemblyName("Name"), new AssemblyName("Name"), false }; + yield return new object[] { "AssemblyName", o, o, true }; + yield return new object[] { "assemblyName", new AssemblyName("Name"), new AssemblyName("Name"), true }; + + yield return new object[] { "DisplayName", null, string.Empty, false }; + yield return new object[] { "DisplayName", "value", "value", true }; + yield return new object[] { "DisplayName", o, o, true }; + yield return new object[] { "displayname", null, null, true }; + + yield return new object[] { "TypeName", null, string.Empty, false }; + yield return new object[] { "TypeName", "value", "value", true }; + yield return new object[] { "TypeName", o, o, true }; + yield return new object[] { "typename", null, null, true }; + + yield return new object[] { "Filter", null, Array.Empty(), false }; + yield return new object[] { "Filter", new ToolboxItemFilterAttribute[0], new ToolboxItemFilterAttribute[0], true }; + yield return new object[] { "Filter", o, o, true }; + yield return new object[] { "filter", null, null, true }; + + yield return new object[] { "IsTransient", null, false, false }; + yield return new object[] { "IsTransient", true, true, true }; + yield return new object[] { "IsTransient", o, o, true }; + yield return new object[] { "istransient", null, null, true }; + + yield return new object[] { "NoSuchProperty", null, null, true }; + yield return new object[] { "NoSuchProperty", "value", "value", true }; + yield return new object[] { "NoSuchProperty", o, o, true }; + } + + [Theory] + [MemberData(nameof(FilterPropertyValue_TestData))] + public void ToolboxItem_FilterPropertyValue_Invoke_ReturnsExpected(string propertyName, object value, object expected, bool same) + { + var item = new SubToolboxItem(); + object actual = item.FilterPropertyValue(propertyName, value); + if (expected is AssemblyName expectedName) + { + Assert.Equal(expectedName.FullName, Assert.IsType(actual).FullName); + } + else + { + Assert.Equal(expected, actual); + } + Assert.Equal(same, object.ReferenceEquals(value, actual)); + } + + public static IEnumerable GetHashCode_TestData() + { + yield return new object[] { new ToolboxItem() }; + yield return new object[] { new ToolboxItem { TypeName = "TypeName", DisplayName = "DisplayName" } }; + yield return new object[] { new NoValidationToolboxItem { TypeName = null, DisplayName = null } }; + } + + [Theory] + [MemberData(nameof(GetHashCode_TestData))] + public void ToolboxItem_GetHashCode_Invoke_ReturnsExpected(ToolboxItem item) + { + Assert.Equal(item.GetHashCode(), item.GetHashCode()); + } + + public static IEnumerable GetType_TestData() + { + var nullServiceDesignerHost = new Mock(MockBehavior.Strict); + nullServiceDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(null); + foreach (object host in new object[] { null, nullServiceDesignerHost.Object }) + { + yield return new object[] { null, null, "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName("NoSuchAssembly"), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName(typeof(int).Assembly.FullName), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItem).Assembly.FullName), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName(typeof(int).Assembly.FullName), "System.Drawing.Design.Tests.ToolboxItemTests", false, null }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItemTests).Assembly.FullName), "System.Drawing.Design.Tests.ToolboxItemTests", false, typeof(ToolboxItemTests) }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItemTests).Assembly.FullName), "System.Drawing.Design.Tests.toolboxitemtests", false, null }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItemTests).Assembly.FullName), "NoSuchType", false, null }; + yield return new object[] { null, null, string.Empty, false, null }; + + var validNameWithCodeBase = new AssemblyName(typeof(int).Assembly.FullName); + validNameWithCodeBase.CodeBase = "System.Windows.Forms.Design.Tests.dll"; + yield return new object[] { null, validNameWithCodeBase, "System.Drawing.Design.Tests.ToolboxItemTests", false, null }; + + var invalidNameWithCodeBase = new AssemblyName("NoSuchAssembly"); + invalidNameWithCodeBase.CodeBase = "System.Windows.Forms.Design.Tests.dll"; + yield return new object[] { null, invalidNameWithCodeBase, "System.Drawing.Design.Tests.ToolboxItemTests", false, typeof(ToolboxItemTests) }; + + var invalidNameWithInvalidCodeBase = new AssemblyName("NoSuchAssembly"); + invalidNameWithInvalidCodeBase.CodeBase = "AlsoNoSuchAssembly"; + yield return new object[] { null, invalidNameWithInvalidCodeBase, "System.Drawing.Design.Tests.ToolboxItemTests", false, null }; + + AssemblyLoadContext.Default.Resolving += (context, name) => + { + if (name.Name == "ThrowBadImageFormatException") + { + throw new BadImageFormatException(); + } + else if (name.Name == "ThrowIOException") + { + throw new IOException(); + } + + return null; + }; + yield return new object[] { null, new AssemblyName("ThrowBadImageFormatException"), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName("ThrowIOException"), "System.Int32", false, typeof(int) }; + + var badImageFormatExceptionCodeBase = new AssemblyName("NoSuchAssembly"); + badImageFormatExceptionCodeBase.CodeBase = "ThrowBadImageFormatException"; + yield return new object[] { null, badImageFormatExceptionCodeBase, "System.Int32", false, typeof(int) }; + + var ioFormatExceptionCodeBase = new AssemblyName("NoSuchAssembly"); + ioFormatExceptionCodeBase.CodeBase = "ThrowIOException"; + yield return new object[] { null, ioFormatExceptionCodeBase, "System.Int32", false, typeof(int) }; + } + + var invalidServiceDesignerHost = new Mock(MockBehavior.Strict); + invalidServiceDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new object()); + yield return new object[] { invalidServiceDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Int32", false, typeof(int) }; + + foreach (bool reference in new bool[] { true, false }) + { + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + yield return new object[] { mockDesignerHost.Object, null, "typeName", reference, typeof(bool) }; + yield return new object[] { mockDesignerHost.Object, null, string.Empty, false, null }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(), "typeName", reference, typeof(bool) }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Int32", reference, typeof(int) }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Drawing.Design.Tests.ToolboxItemTests", reference, typeof(ToolboxItemTests) }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Drawing.Design.Tests.toolboxitemtests", reference, null }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "NoSuchType", reference, null }; + } + } + + [Theory] + [MemberData(nameof(GetType_TestData))] + public void ToolboxItem_GetType_InvokeWithoutTypeNameAssemblyName_ReturnsExpected(IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference, Type expected) + { + if (reference) + { + return; + } + + var item = new ToolboxItem + { + AssemblyName = assemblyName, + TypeName = typeName + }; + Assert.Equal(expected, item.GetType(host)); + } + + [Theory] + [MemberData(nameof(GetType_TestData))] + public void ToolboxItem_GetType_InvokeWithTypeNameAssemblyName_ReturnsExpected(IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference, Type expected) + { + var item = new SubToolboxItem(); + Assert.Equal(expected, item.GetType(host, assemblyName, typeName, reference)); + } + + [Fact] + public void ToolboxItem_GetType_NullTypeName_ThrowsArgumentNullException() + { + var item = new SubToolboxItem(); + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(null); + Assert.Throws("typeName", () => item.GetType(mockDesignerHost.Object, null, null, false)); + Assert.Throws("typeName", () => item.GetType(null, null, null, false)); + } + + [Fact] + public void ToolboxItem_GetType_EmptyAssemblyName_ThrowsArgumentException() + { + var item = new SubToolboxItem(); + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(null); + Assert.Throws(null, () => item.GetType(mockDesignerHost.Object, new AssemblyName(), "typeName", false)); + Assert.Throws(null, () => item.GetType(null, new AssemblyName(), "typeName", false)); + } + + public static IEnumerable Initialize_TypeWithAttributes_TestData() + { + yield return new object[] { typeof(ClassWithValidAttributes), new Size(16, 16) }; + yield return new object[] { typeof(ClassWithStretchedWidthImage), new Size(24, 16) }; + yield return new object[] { typeof(ClassWithStretchedHeightImage), new Size(16, 24) }; + yield return new object[] { typeof(ClassWithInvalidImage), new Size(16, 16) }; + } + + [Theory] + [MemberData(nameof(Initialize_TypeWithAttributes_TestData))] + public void ToolboxItem_Initialize_TypeWithAttributes_Success(Type type, Size expectedOriginalBitmapSize) + { + using (var bitmap = new Bitmap(10, 10)) + using (var originalBitmap = new Bitmap(10, 10)) + { + var filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }; + var item = new ToolboxItem + { + AssemblyName = new AssemblyName("AssemblyName"), + Bitmap = bitmap, + Company = "Company", + Description = "Description", + DependentAssemblies = new AssemblyName[2], + DisplayName = "DisplayName", + Filter = filter, + OriginalBitmap = originalBitmap + }; + item.Initialize(type); + if (expectedOriginalBitmapSize == new Size(10, 10)) + { + Assert.NotEqual(bitmap, item.Bitmap); + Assert.Same(item.Bitmap, item.Bitmap); + } + else + { + Assert.Equal(new Size(16, 16), item.Bitmap.Size); + } + Assert.Equal("Microsoft Corporation", item.Company); + Assert.Equal("Description", item.Description); + Assert.Equal(type.Assembly.FullName, item.AssemblyName.FullName); + Assert.Equal(new string[] { type.Assembly.FullName }, item.DependentAssemblies.Select(a => a.FullName)); + Assert.Equal(type.Name, item.DisplayName); + Assert.Equal(new string[] { type.Name, "Filter", "System.Drawing.Design.Tests.ToolboxItemTests+" + type.Name }, item.Filter.Cast().Select(a => a.FilterString).OrderBy(f => f)); + Assert.Equal(expectedOriginalBitmapSize, item.OriginalBitmap.Size); + } + } + + [Fact] + public void ToolboxItem_Initialize_ObjectType_Success() + { + using (var bitmap = new Bitmap(10, 10)) + using (var originalBitmap = new Bitmap(10, 10)) + { + var filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }; + var item = new ToolboxItem + { + AssemblyName = new AssemblyName("AssemblyName"), + Bitmap = bitmap, + Company = "Company", + Description = "Description", + DependentAssemblies = new AssemblyName[2], + DisplayName = "DisplayName", + Filter = filter, + OriginalBitmap = originalBitmap + }; + item.Initialize(typeof(object)); + Assert.NotEqual(bitmap, item.Bitmap); + Assert.Same(item.Bitmap, item.Bitmap); + Assert.Equal("Microsoft Corporation", item.Company); + Assert.Empty(item.Description); + Assert.Equal(typeof(object).Assembly.FullName, item.AssemblyName.FullName); + Assert.Equal(new string[] { typeof(object).Assembly.FullName }, item.DependentAssemblies.Select(a => a.FullName)); + Assert.Equal("Object", item.DisplayName); + Assert.Equal(new string[] { "System.Object" }, item.Filter.Cast().Select(a => a.FilterString)); + Assert.Same(item.OriginalBitmap, item.OriginalBitmap); + } + } + + [Fact] + public void ToolboxItem_Initialize_NullType_Nop() + { + using (var bitmap = new Bitmap(10, 10)) + using (var originalBitmap = new Bitmap(10, 10)) + { + var filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }; + var item = new ToolboxItem + { + AssemblyName = new AssemblyName("AssemblyName"), + Bitmap = bitmap, + Company = "Company", + Description = "Description", + DependentAssemblies = new AssemblyName[2], + DisplayName = "DisplayName", + Filter = filter, + OriginalBitmap = originalBitmap + }; + item.Initialize(null); + Assert.Equal("AssemblyName", item.AssemblyName.FullName); + Assert.Same(bitmap, item.Bitmap); + Assert.Equal("Company", item.Company); + Assert.Equal("Description", item.Description); + Assert.Equal(new AssemblyName[2], item.DependentAssemblies); + Assert.Equal("DisplayName", item.DisplayName); + Assert.Equal(filter, item.Filter); + Assert.Same(originalBitmap, item.OriginalBitmap); + } + } + + [Theory] + [InlineData(null)] + [InlineData(typeof(int))] + public void ToolboxItem_Initialize_Locked_ThrowsInvalidOperationException(Type type) + { + var item = new ToolboxItem(); + item.Lock(); + Assert.Throws(() => item.Initialize(type)); + } + + [Fact] + public void ToolboxItem_Lock_Invoke_Success() + { + var item = new ToolboxItem(); + item.Lock(); + Assert.True(item.Locked); + Assert.True(item.Properties.IsFixedSize); + Assert.True(item.Properties.IsReadOnly); + + // Lock again. + item.Lock(); + Assert.True(item.Locked); + Assert.True(item.Properties.IsFixedSize); + Assert.True(item.Properties.IsReadOnly); + } + + [Fact] + public void ToolboxItem_OnComponentsCreated_Invoke_Success() + { + var item = new SubToolboxItem(); + + // No handler. + item.OnComponentsCreated(null); + + // Handler. + int callCount = 0; + ToolboxComponentsCreatedEventHandler handler = (sender, e) => + { + Assert.Equal(item, sender); + Assert.Null(e); + callCount++; + }; + + item.ComponentsCreated += handler; + item.OnComponentsCreated(null); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + item.ComponentsCreated -= handler; + item.OnComponentsCreated(null); + Assert.Equal(1, callCount); + } + [Fact] + public void ToolboxItem_OnComponentsCreating_Invoke_Success() + { + var item = new SubToolboxItem(); + + // No handler. + item.OnComponentsCreating(null); + + // Handler. + int callCount = 0; + ToolboxComponentsCreatingEventHandler handler = (sender, e) => + { + Assert.Equal(item, sender); + Assert.Null(e); + callCount++; + }; + + item.ComponentsCreating += handler; + item.OnComponentsCreating(null); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + item.ComponentsCreating -= handler; + item.OnComponentsCreating(null); + Assert.Equal(1, callCount); + } + + public static IEnumerable ToString_TestData() + { + yield return new object[] { new ToolboxItem(), string.Empty }; + yield return new object[] { new ToolboxItem { DisplayName = "DisplayName" }, "DisplayName" }; + yield return new object[] { new NoValidationToolboxItem { DisplayName = null }, string.Empty }; + } + + [Theory] + [MemberData(nameof(ToString_TestData))] + public void ToolboxItem_ToString_Invoke_ReturnsExpected(ToolboxItem item, string expected) + { + Assert.Equal(expected, item.ToString()); + } + + public static IEnumerable ValidatePropertyValue_TestData() + { + var name = new AssemblyName(); + yield return new object[] { "AssemblyName", null, null }; + yield return new object[] { "AssemblyName", name, name }; + + var bitmap = new Bitmap(10, 10); + yield return new object[] { "Bitmap", null, null }; + yield return new object[] { "Bitmap", bitmap, bitmap }; + + var originalBitmap = new Bitmap(10, 10); + yield return new object[] { "OriginalBitmap", null, null }; + yield return new object[] { "OriginalBitmap", originalBitmap, originalBitmap }; + + yield return new object[] { "Company", null, string.Empty }; + yield return new object[] { "Company", "value", "value" }; + + yield return new object[] { "Description", null, string.Empty }; + yield return new object[] { "Description", "value", "value" }; + + yield return new object[] { "DisplayName", null, string.Empty }; + yield return new object[] { "DisplayName", "value", "value" }; + + yield return new object[] { "TypeName", null, string.Empty }; + yield return new object[] { "TypeName", "value", "value" }; + + var filter = new ToolboxItemFilterAttribute("filter"); + yield return new object[] { "Filter", null, new ToolboxItemFilterAttribute[0] }; + yield return new object[] { "Filter", new ToolboxItemFilterAttribute[0], new ToolboxItemFilterAttribute[0] }; + yield return new object[] { "Filter", new object[] { null, "value", filter, filter }, new ToolboxItemFilterAttribute[] { filter, filter } }; + + yield return new object[] { "NoSuchProperty", null, null }; + yield return new object[] { "NoSuchProperty", 1, 1 }; + + yield return new object[] { "istransient", null, null }; + yield return new object[] { "istransient", 1, 1 }; + } + + [Theory] + [MemberData(nameof(ValidatePropertyValue_TestData))] + public void ToolboxItem_ValidatePropertyValue_ValueAllowed_ReturnsExpected(string propertyName, object value, object expected) + { + var item = new SubToolboxItem(); + Assert.Equal(expected, item.ValidatePropertyValue(propertyName, value)); + } + + [Theory] + [InlineData("IsTransient")] + public void ToolboxItem_ValidatePropertyValue_NullValueDisallowed_ThrowsArgumentNullException(string propertyName) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyValue(propertyName, null)); + } + + [Theory] + [InlineData("AssemblyName")] + [InlineData("Bitmap")] + [InlineData("OriginalBitmap")] + [InlineData("Company")] + [InlineData("Description")] + [InlineData("DisplayName")] + [InlineData("TypeName")] + [InlineData("Filter")] + [InlineData("DependentAssemblies")] + public void ToolboxItem_ValidatePropertyValue_InvalidValue_ThrowsArgumentException(string propertyName) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyValue(propertyName, new object())); + } + + [Theory] + [InlineData(null, null)] + [InlineData("propertyName", typeof(int))] + public void ToolboxItem_ValidatePropertyType_NullDisallowed_ThrowsArgumentNullException(string propertyName, Type expectedType) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyType(propertyName, null, expectedType, allowNull: false)); + } + + [Theory] + [InlineData(null, null)] + [InlineData("propertyName", typeof(int))] + public void ToolboxItem_ValidatePropertyType_NullAllowed_Nop(string propertyName, Type expectedType) + { + var item = new SubToolboxItem(); + item.ValidatePropertyType(propertyName, null, expectedType, allowNull: true); + } + + [Theory] + [InlineData(null, false)] + [InlineData("propertyName", true)] + public void ToolboxItem_ValidatePropertyType_ValidType_Nop(string propertyName, bool allowNull) + { + var item = new SubToolboxItem(); + item.ValidatePropertyType(propertyName, 1, typeof(int), allowNull); + } + + [Theory] + [InlineData(null, false)] + [InlineData("propertyName", true)] + public void ToolboxItem_ValidatePropertyType_InvalidType_ThrowsArgumentException(string propertyName, bool allowNull) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyType(propertyName, new object(), typeof(int), allowNull)); + } + + private class SubToolboxItem : ToolboxItem + { + public new void CheckUnlocked() => base.CheckUnlocked(); + + public new IComponent[] CreateComponentsCore(IDesignerHost host) + { + return base.CreateComponentsCore(host); + } + + public new IComponent[] CreateComponentsCore(IDesignerHost host, IDictionary defaultValues) + { + return base.CreateComponentsCore(host, defaultValues); + } + + public new object FilterPropertyValue(string propertyName, object value) + { + return base.FilterPropertyValue(propertyName, value); + } + + public new Type GetType(IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference) + { + return base.GetType(host, assemblyName, typeName, reference); + } + + public new void OnComponentsCreated(ToolboxComponentsCreatedEventArgs args) + { + base.OnComponentsCreated(args); + } + + public new void OnComponentsCreating(ToolboxComponentsCreatingEventArgs args) + { + base.OnComponentsCreating(args); + } + + public new object ValidatePropertyValue(string propertyName, object value) + { + return base.ValidatePropertyValue(propertyName, value); + } + + public new void ValidatePropertyType(string propertyName, object value, Type expectedType, bool allowNull) + { + base.ValidatePropertyType(propertyName, value, expectedType, allowNull); + } + } + + private class CustomTypeResolutionService : ITypeResolutionService + { + public Assembly GetAssemblyResult { get; set; } + + public Assembly GetAssembly(AssemblyName name) => GetAssemblyResult; + + public Assembly GetAssembly(AssemblyName name, bool throwOnError) + { + throw new NotImplementedException(); + } + + public string GetPathOfAssembly(AssemblyName name) + { + throw new NotImplementedException(); + } + + public Type GetType(string name) + { + if (name == "typeName") + { + return typeof(bool); + } + + return Type.GetType(name); + } + + public Type GetType(string name, bool throwOnError) + { + throw new NotImplementedException(); + } + + public Type GetType(string name, bool throwOnError, bool ignoreCase) + { + throw new NotImplementedException(); + } + + public List ReferenceAssemblies { get; } = new List(); + + public void ReferenceAssembly(AssemblyName name) + { + ReferenceAssemblies.Add(name); + } + } + + private class NoValidationToolboxItem : ToolboxItem + { + protected override object FilterPropertyValue(string propertyName, object value) + { + // Don't normalize. + return value; + } + + protected override object ValidatePropertyValue(string propertyName, object value) + { + // Don't normalize. + return value; + } + } + + private class NullComponentsToolboxItem : ToolboxItem + { + protected override IComponent[] CreateComponentsCore(IDesignerHost host) + { + return null; + } + } + + [Description("Description")] + [ToolboxBitmap(typeof(ToolboxItemTests), "16x16.bmp")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithValidAttributes")] + [ToolboxItemFilter("ClassWithValidAttributes")] + [ToolboxItemFilter("Filter")] + private class ClassWithValidAttributes + { + } + + [Description("Description")] + [ToolboxBitmap(typeof(ToolboxItemTests), "24x16.bmp")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithStretchedWidthImage")] + [ToolboxItemFilter("ClassWithStretchedWidthImage")] + [ToolboxItemFilter("Filter")] + private class ClassWithStretchedWidthImage + { + } + + [Description("Description")] + [ToolboxBitmap(typeof(ToolboxItemTests), "16x24.bmp")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithStretchedHeightImage")] + [ToolboxItemFilter("ClassWithStretchedHeightImage")] + [ToolboxItemFilter("Filter")] + private class ClassWithStretchedHeightImage + { + } + + [Description("Description")] + [ToolboxBitmap("NoSuchImage")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithInvalidImage")] + [ToolboxItemFilter("ClassWithInvalidImage")] + [ToolboxItemFilter("Filter")] + private class ClassWithInvalidImage + { + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgsTests.cs new file mode 100644 index 00000000000..bc9db5ef906 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/Behavior/BehaviorDragDropEventArgsTests.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using Xunit; + +namespace System.Windows.Forms.Design.Behavior.Tests +{ + public class BehaviorDragDropEventArgsTests + { + public static IEnumerable Ctor_ICollection_TestData() + { + yield return new object[] { null }; + yield return new object[] { new object[0] }; + yield return new object[] { new object[] { null } }; + } + + [Theory] + [MemberData(nameof(Ctor_ICollection_TestData))] + public void Ctor_ICollection(ICollection components) + { + var e = new BehaviorDragDropEventArgs(components); + Assert.Same(components, e.DragComponents); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs new file mode 100644 index 00000000000..e12708de140 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs @@ -0,0 +1,187 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Drawing; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class DesignerOptionsTests + { + [Fact] + public void DesignerOptions_Ctor_Default() + { + var options = new DesignerOptions(); + Assert.True(options.EnableInSituEditing); + Assert.Equal(new Size(8, 8), options.GridSize); + Assert.True(options.ObjectBoundSmartTagAutoShow); + Assert.True(options.ShowGrid); + Assert.True(options.SnapToGrid); + Assert.False(options.UseOptimizedCodeGeneration); + Assert.False(options.UseSmartTags); + Assert.False(options.UseSnapLines); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_EnableInSituEditing_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + EnableInSituEditing = value + }; + Assert.Equal(value, options.EnableInSituEditing); + + // Set same. + options.EnableInSituEditing = value; + Assert.Equal(value, options.EnableInSituEditing); + + // Set different. + options.EnableInSituEditing = !value; + Assert.Equal(!value, options.EnableInSituEditing); + } + + public static IEnumerable GridSize_Set_TestData() + { + yield return new object[] { new Size(0, 0), new Size(2, 2) }; + yield return new object[] { new Size(0, 2), new Size(2, 2) }; + yield return new object[] { new Size(2, 0), new Size(2, 2) }; + yield return new object[] { new Size(2, 2), new Size(2, 2) }; + yield return new object[] { new Size(200, 200), new Size(200, 200) }; + yield return new object[] { new Size(201, 200), new Size(200, 200) }; + yield return new object[] { new Size(200, 201), new Size(200, 200) }; + } + + [Theory] + [MemberData(nameof(GridSize_Set_TestData))] + public void DesignerOptions_GridSize_Set_GetReturnsExpected(Size value, Size expected) + { + var options = new DesignerOptions + { + GridSize = value + }; + Assert.Equal(expected, options.GridSize); + + // Set same. + options.GridSize = value; + Assert.Equal(expected, options.GridSize); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_ObjectBoundSmartTagAutoShow_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + ObjectBoundSmartTagAutoShow = value + }; + Assert.Equal(value, options.ObjectBoundSmartTagAutoShow); + + // Set same. + options.ObjectBoundSmartTagAutoShow = value; + Assert.Equal(value, options.ObjectBoundSmartTagAutoShow); + + // Set different. + options.ObjectBoundSmartTagAutoShow = !value; + Assert.Equal(!value, options.ObjectBoundSmartTagAutoShow); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_ShowGrid_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + ShowGrid = value + }; + Assert.Equal(value, options.ShowGrid); + + // Set same. + options.ShowGrid = value; + Assert.Equal(value, options.ShowGrid); + + // Set different. + options.ShowGrid = !value; + Assert.Equal(!value, options.ShowGrid); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_SnapToGrid_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + SnapToGrid = value + }; + Assert.Equal(value, options.SnapToGrid); + + // Set same. + options.SnapToGrid = value; + Assert.Equal(value, options.SnapToGrid); + + // Set different. + options.SnapToGrid = !value; + Assert.Equal(!value, options.SnapToGrid); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_UseOptimizedCodeGeneration_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + UseOptimizedCodeGeneration = value + }; + Assert.Equal(value, options.UseOptimizedCodeGeneration); + + // Set same. + options.UseOptimizedCodeGeneration = value; + Assert.Equal(value, options.UseOptimizedCodeGeneration); + + // Set different. + options.UseOptimizedCodeGeneration = !value; + Assert.Equal(!value, options.UseOptimizedCodeGeneration); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_UseSmartTags_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + UseSmartTags = value + }; + Assert.Equal(value, options.UseSmartTags); + + // Set same. + options.UseSmartTags = value; + Assert.Equal(value, options.UseSmartTags); + + // Set different. + options.UseSmartTags = !value; + Assert.Equal(!value, options.UseSmartTags); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_UseSnapLines_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + UseSnapLines = value + }; + Assert.Equal(value, options.UseSnapLines); + + // Set same. + options.UseSnapLines = value; + Assert.Equal(value, options.UseSnapLines); + + // Set different. + options.UseSnapLines = !value; + Assert.Equal(!value, options.UseSnapLines); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs new file mode 100644 index 00000000000..a24ce0401f5 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel.Design; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class MenuCommandsTests + { + [Fact] + public void MenuCommands_Ctor_Default() + { + // Make sure it doesn't throw. + new MenuCommands(); + } + + public static IEnumerable Commands_TestData() + { + yield return new object[] { MenuCommands.ComponentTrayMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1286) }; + yield return new object[] { MenuCommands.ContainerMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1281) }; + yield return new object[] { MenuCommands.DesignerProperties, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 4097) }; + yield return new object[] { MenuCommands.EditLabel, new CommandID(new Guid("5efc7975-14bc-11cf-9b2b-00aa00573819"), 338) }; + yield return new object[] { MenuCommands.KeyCancel, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 103) }; + yield return new object[] { MenuCommands.KeyDefaultAction, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 3) }; + yield return new object[] { MenuCommands.KeyEnd, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 17) }; + yield return new object[] { MenuCommands.KeyHome, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 15) }; + yield return new object[] { MenuCommands.KeyInvokeSmartTag, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 147) }; + yield return new object[] { MenuCommands.KeyMoveDown, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 13) }; + yield return new object[] { MenuCommands.KeyMoveLeft, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 7) }; + yield return new object[] { MenuCommands.KeyMoveRight, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 9) }; + yield return new object[] { MenuCommands.KeyMoveUp, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 11) }; + yield return new object[] { MenuCommands.KeyNudgeDown, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1225) }; + yield return new object[] { MenuCommands.KeyNudgeHeightDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1229) }; + yield return new object[] { MenuCommands.KeyNudgeHeightIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1228) }; + yield return new object[] { MenuCommands.KeyNudgeLeft, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1224) }; + yield return new object[] { MenuCommands.KeyNudgeRight, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1226) }; + yield return new object[] { MenuCommands.KeyNudgeUp, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1227) }; + yield return new object[] { MenuCommands.KeyNudgeWidthDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1230) }; + yield return new object[] { MenuCommands.KeyNudgeWidthDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1230) }; + yield return new object[] { MenuCommands.KeyNudgeHeightIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1228) }; + yield return new object[] { MenuCommands.KeyReverseCancel, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16385) }; + yield return new object[] { MenuCommands.KeySelectNext, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 4) }; + yield return new object[] { MenuCommands.KeySelectPrevious, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 5) }; + yield return new object[] { MenuCommands.KeyShiftEnd, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 18) }; + yield return new object[] { MenuCommands.KeyShiftHome, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 16) }; + yield return new object[] { MenuCommands.KeySizeHeightDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 14) }; + yield return new object[] { MenuCommands.KeySizeHeightIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 12) }; + yield return new object[] { MenuCommands.KeySizeWidthDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 8) }; + yield return new object[] { MenuCommands.KeySizeWidthIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 10) }; + yield return new object[] { MenuCommands.KeyTabOrderSelect, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16405) }; + yield return new object[] { MenuCommands.SelectionMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1280) }; + yield return new object[] { MenuCommands.SetStatusRectangle, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16388) }; + yield return new object[] { MenuCommands.SetStatusText, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16387) }; + yield return new object[] { MenuCommands.TraySelectionMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1283) }; + } + + [Theory] + [MemberData(nameof(Commands_TestData))] + public void MenuCommands_Commands_Get_ReturnsExected(CommandID command, CommandID expected) + { + Assert.Equal(expected, command); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs new file mode 100644 index 00000000000..2de5130c1b7 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Linq; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class WindowsFormsDesignerOptionServiceTests + { + [Fact] + public void WindowsFormsDesignerOptionService_Ctor_Default() + { + var service = new WindowsFormsDesignerOptionService(); + DesignerOptions options = service.CompatibilityOptions; + Assert.True(options.EnableInSituEditing); + Assert.Equal(new Size(8, 8), options.GridSize); + Assert.True(options.ObjectBoundSmartTagAutoShow); + Assert.True(options.ShowGrid); + Assert.True(options.SnapToGrid); + Assert.False(options.UseSmartTags); + Assert.False(options.UseSnapLines); + Assert.False(options.UseOptimizedCodeGeneration); + Assert.Same(options, service.CompatibilityOptions); + } + + [Fact] + public void WindowsFormsDesignerOptionService_Options_Get_ReturnsExpected() + { + var service = new WindowsFormsDesignerOptionService(); + Assert.Empty(service.Options.Name); + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + } + + [Fact] + public void WindowsFormsDesignerOptionService_Options_GetNullDesignerOptions_ReturnsExpected() + { + var service = new NullCompatibilityOptions(); + Assert.Empty(service.Options.Name); + Assert.Empty(service.Options); + } + + [Fact] + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_ValidOptionsFromSameClass_Success() + { + var service = new SubWindowsFormsDesignerOptionService(); + service.PopulateOptionCollectionEntry(service.Options); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + + // Should not retrieve again when accessing Options. + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + } + + [Fact] + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_ValidOptionsFromOtherClass_Success() + { + var service = new SubWindowsFormsDesignerOptionService(); + var otherService = new SubWindowsFormsDesignerOptionService(); + service.PopulateOptionCollectionEntry(otherService.Options); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + + // Should retrieve again when accessing Options. + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(2, service.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + + DesignerOptionService.DesignerOptionCollection otherChildCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(0, otherService.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", otherChildCollection.Name); + Assert.Same(service.Options, otherChildCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(otherChildCollection); + } + + [Fact] + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_NullOptions_Success() + { + var service = new SubWindowsFormsDesignerOptionService(); + service.PopulateOptionCollectionEntry(null); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + + // Should retrieve again when accessing Options. + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(2, service.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + Assert.Equal(3, service.PopulateOptionCollectionCallCount); + } + + private class SubWindowsFormsDesignerOptionService : WindowsFormsDesignerOptionService + { + public int PopulateOptionCollectionCallCount { get; set; } + + public void PopulateOptionCollectionEntry(DesignerOptionCollection options) + { + PopulateOptionCollection(options); + } + + protected override void PopulateOptionCollection(DesignerOptionCollection options) + { + PopulateOptionCollectionCallCount++; + base.PopulateOptionCollection(options); + } + } + + private class NullCompatibilityOptions : WindowsFormsDesignerOptionService + { + public override DesignerOptions CompatibilityOptions => null; + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Mocks/MockControlDesigner.cs b/src/System.Windows.Forms.Design/tests/UnitTests/TestControlDesigner.cs similarity index 97% rename from src/System.Windows.Forms.Design/tests/UnitTests/Mocks/MockControlDesigner.cs rename to src/System.Windows.Forms.Design/tests/UnitTests/TestControlDesigner.cs index b39961fa395..cbb2d7bb8b4 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/Mocks/MockControlDesigner.cs +++ b/src/System.Windows.Forms.Design/tests/UnitTests/TestControlDesigner.cs @@ -8,7 +8,7 @@ namespace System.Windows.Forms.Design.Tests { - internal class MockControlDesigner : ControlDesigner + internal class TestControlDesigner : ControlDesigner { internal AccessibleObject GetAccessibleObjectField() { diff --git a/src/System.Windows.Forms/src/BitmapSelector.cs b/src/System.Windows.Forms/src/BitmapSelector.cs deleted file mode 100644 index db468642757..00000000000 --- a/src/System.Windows.Forms/src/BitmapSelector.cs +++ /dev/null @@ -1,217 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Drawing { - using System; - using System.Configuration; - using System.Drawing.Configuration; - using System.IO; - using System.Reflection; - - /// - /// Provides methods to select from multiple bitmaps depending on a "bitmapSuffix" config setting. - /// - internal static class BitmapSelector { - - /// - /// Gets the bitmap ID suffix defined in the application configuration, or string.Empty if - /// the suffix is not specified. Internal for unit tests - /// - /// - /// For performance, the suffix is cached in a static variable so it only has to be read - /// once per appdomain. - /// - private static string _suffix; - internal static string Suffix { - get { - if (_suffix == null) { - _suffix = string.Empty; - var section = ConfigurationManager.GetSection("system.drawing") as SystemDrawingSection; - if (section != null) { - var value = section.BitmapSuffix; - if (value != null && value is string) { - _suffix = (string)value; - } - } - } - return _suffix; - } - set { - // So unit tests can clear the cached suffix - _suffix = value; - } - } - - /// - /// Appends the current suffix to . The suffix is appended - /// before the existing extension (if any). Internal for unit tests. - /// - /// - /// The new path with the suffix included. If there is no suffix defined or there are - /// invalid characters in the original path, the original path is returned. - /// - internal static string AppendSuffix(string filePath) { - try { - return Path.ChangeExtension(filePath, Suffix + Path.GetExtension(filePath)); - } - catch (ArgumentException) { // there are invalid characters in the path - return filePath; - } - } - - /// - /// Returns with the current suffix appended (before the - /// existing extension) if the resulting file path exists; otherwise the original path is - /// returned. - /// - public static string GetFileName(string originalPath) { - if (Suffix == string.Empty) - return originalPath; - - string newPath = AppendSuffix(originalPath); - return File.Exists(newPath) ? newPath : originalPath; - } - - // Calls assembly.GetManifestResourceStream in a try/catch and returns null if not found - private static Stream GetResourceStreamHelper(Assembly assembly, Type type, string name) { - Stream stream = null; - try { - stream = assembly.GetManifestResourceStream(type, name); - } - catch (FileNotFoundException) { - } - return stream; - } - - private static bool DoesAssemblyHaveCustomAttribute(Assembly assembly, string typeName) { - return DoesAssemblyHaveCustomAttribute(assembly, assembly.GetType(typeName)); - } - - private static bool DoesAssemblyHaveCustomAttribute(Assembly assembly, Type attrType) { - if (attrType != null) { - var attr = assembly.GetCustomAttributes(attrType, false); - if (attr.Length > 0) { - return true; - } - } - return false; - } - - // internal for unit tests - internal static bool SatelliteAssemblyOptIn(Assembly assembly) { - // Try 4.5 public attribute type first - if (DoesAssemblyHaveCustomAttribute(assembly, typeof(BitmapSuffixInSatelliteAssemblyAttribute))) { - return true; - } - - // Also load attribute type by name for dlls compiled against older frameworks - return DoesAssemblyHaveCustomAttribute(assembly, "System.Drawing.BitmapSuffixInSatelliteAssemblyAttribute"); - } - - // internal for unit tests - internal static bool SameAssemblyOptIn(Assembly assembly) { - // Try 4.5 public attribute type first - if (DoesAssemblyHaveCustomAttribute(assembly, typeof(BitmapSuffixInSameAssemblyAttribute))) { - return true; - } - - // Also load attribute type by name for dlls compiled against older frameworks - return DoesAssemblyHaveCustomAttribute(assembly, "System.Drawing.BitmapSuffixInSameAssemblyAttribute"); - } - - /// - /// Returns a resource stream loaded from the appropriate location according to the current - /// suffix. - /// - /// The assembly from which the stream is loaded - /// The type whose namespace is used to scope the manifest resource name - /// The name of the manifest resource being requested - /// - /// The manifest resource stream corresponding to with the - /// current suffix applied; or if that is not found, the stream corresponding to . - /// - public static Stream GetResourceStream(Assembly assembly, Type type, string originalName) { - if (Suffix != string.Empty) { - try { - // Resource with suffix has highest priority - if (SameAssemblyOptIn(assembly)) { - string newName = AppendSuffix(originalName); - Stream stream = GetResourceStreamHelper(assembly, type, newName); - if (stream != null) { - return stream; - } - } - } - catch { - // Ignore failures and continue to try other options - } - - try { - // Satellite assembly has second priority, using the original name - if (SatelliteAssemblyOptIn(assembly)) { - AssemblyName assemblyName = assembly.GetName(); - assemblyName.Name += Suffix; - assemblyName.ProcessorArchitecture = ProcessorArchitecture.None; - Assembly satellite = Assembly.Load(assemblyName); - if (satellite != null) { - Stream stream = GetResourceStreamHelper(satellite, type, originalName); - if (stream != null) { - return stream; - } - } - } - } - catch { - // Ignore failures and continue to try other options - } - } - - // Otherwise fall back to specified assembly and original name requested - return assembly.GetManifestResourceStream(type, originalName); - } - - /// - /// Returns a resource stream loaded from the appropriate location according to the current - /// suffix. - /// - /// The type from whose assembly the stream is loaded and whose namespace is used to scope the resource name - /// The name of the manifest resource being requested - /// - /// The manifest resource stream corresponding to with the - /// current suffix applied; or if that is not found, the stream corresponding to . - /// - public static Stream GetResourceStream(Type type, string originalName) { - return GetResourceStream(type.Module.Assembly, type, originalName); - } - - /// - /// Returns an Icon created from a resource stream loaded from the appropriate location according to the current - /// suffix. - /// - /// The type from whose assembly the stream is loaded and whose namespace is used to scope the resource name - /// The name of the manifest resource being requested - /// - /// The icon created from a manifest resource stream corresponding to with the - /// current suffix applied; or if that is not found, the stream corresponding to . - /// - public static Icon CreateIcon(Type type, string originalName) { - return new Icon(GetResourceStream(type, originalName)); - } - - /// - /// Returns an Bitmap created from a resource stream loaded from the appropriate location according to the current - /// suffix. - /// - /// The type from whose assembly the stream is loaded and whose namespace is used to scope the resource name - /// The name of the manifest resource being requested - /// - /// The bitmap created from a manifest resource stream corresponding to with the - /// current suffix applied; or if that is not found, the stream corresponding to . - /// - public static Bitmap CreateBitmap(Type type, string originalName) { - return new Bitmap(GetResourceStream(type, originalName)); - } - - } -} diff --git a/src/System.Windows.Forms/src/Resources/SR.resx b/src/System.Windows.Forms/src/Resources/SR.resx index 2675c0bb22c..f491e8b9faf 100644 --- a/src/System.Windows.Forms/src/Resources/SR.resx +++ b/src/System.Windows.Forms/src/Resources/SR.resx @@ -1613,7 +1613,7 @@ Editing Panel - Horizontal Scroll Bar + Horizontal Click @@ -1646,7 +1646,7 @@ Top Row - Vertical Scroll Bar + Vertical At least one of the DataGridView control's columns has no cell template. @@ -5516,32 +5516,6 @@ Stack trace where the illegal operation occurred was: Gets or sets a Boolean value controlling whether the scrollbar is showing. - - Mixed Zone - - - Multiple Sites - - - Unknown Site - - - Unknown Zone - - - Microsoft .NET Security Warning - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - - - Source: {0} - - - {0} - -{1} - Occurs when the value of the SelectedIndex property changes. diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ActiveDocumentHost.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ActiveDocumentHost.bmp deleted file mode 100644 index a92e932cd84..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ActiveDocumentHost.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ActiveDocumentHost.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ActiveDocumentHost.ico new file mode 100644 index 00000000000..8547f692a9d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ActiveDocumentHost.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Animation.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Animation.bmp deleted file mode 100644 index e267db6a1de..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Animation.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Animation.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Animation.ico new file mode 100644 index 00000000000..f54e2196b5b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Animation.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/App/Timer.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/App/Timer.bmp deleted file mode 100644 index f750fbb2d26..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/App/Timer.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/App/Timer.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/App/Timer.ico new file mode 100644 index 00000000000..003dad76486 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/App/Timer.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Arrow.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Arrow.bmp deleted file mode 100644 index ef847d027be..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Arrow.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Arrow.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Arrow.ico new file mode 100644 index 00000000000..b25612d2973 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Arrow.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.AddNew.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.AddNew.bmp deleted file mode 100644 index 324ad95e6fa..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.AddNew.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.AddNew.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.AddNew.ico new file mode 100644 index 00000000000..8113fff9449 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.AddNew.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.Delete.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.Delete.bmp deleted file mode 100644 index 219a72c6e84..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.Delete.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.Delete.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.Delete.ico new file mode 100644 index 00000000000..2bf258ceee0 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.Delete.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveFirst.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveFirst.bmp deleted file mode 100644 index a38290f3b78..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveFirst.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveFirst.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveFirst.ico new file mode 100644 index 00000000000..9bf00477b0e Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveFirst.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveLast.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveLast.bmp deleted file mode 100644 index f6d6ac3ec0f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveLast.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveLast.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveLast.ico new file mode 100644 index 00000000000..19d9dd546cf Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveLast.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveNext.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveNext.bmp deleted file mode 100644 index fa1ceb58c4c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveNext.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveNext.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveNext.ico new file mode 100644 index 00000000000..328dd2f624b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MoveNext.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MovePrevious.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MovePrevious.bmp deleted file mode 100644 index 7c7f89c4ed7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MovePrevious.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MovePrevious.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MovePrevious.ico new file mode 100644 index 00000000000..071c5079a8c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.MovePrevious.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.bmp deleted file mode 100644 index a461710fd80..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.ico new file mode 100644 index 00000000000..f23e9fb0615 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingNavigator.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingSource.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingSource.bmp deleted file mode 100644 index 0bd1194cceb..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingSource.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingSource.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingSource.ico new file mode 100644 index 00000000000..0468b8c2fb6 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/BindingSource.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Button.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Button.bmp deleted file mode 100644 index 405f89f9ee9..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Button.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Button.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Button.ico new file mode 100644 index 00000000000..bfbd41a2534 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Button.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckBox.bmp deleted file mode 100644 index f5c398a8802..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckBox.ico new file mode 100644 index 00000000000..49c6bb9f5e4 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Checked.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Checked.ico index bae5a66eb47..f0801e26c4a 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Checked.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Checked.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckedListBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckedListBox.bmp deleted file mode 100644 index 19cc16d6cc7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckedListBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckedListBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckedListBox.ico new file mode 100644 index 00000000000..4cc6dd7aedc Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/CheckedListBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ColorDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ColorDialog.bmp deleted file mode 100644 index c0a77b56959..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ColorDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ColorDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ColorDialog.ico new file mode 100644 index 00000000000..84f6d957ecd Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ColorDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComboBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComboBox.bmp deleted file mode 100644 index ec050261c3b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComboBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComboBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComboBox.ico new file mode 100644 index 00000000000..09eee5dd8b4 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComboBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComponentModel/OrderImages.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComponentModel/OrderImages.bmp deleted file mode 100644 index a47a8654fb2..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComponentModel/OrderImages.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComponentModel/OrderImages.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComponentModel/OrderImages.ico new file mode 100644 index 00000000000..845cc4742bd Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ComponentModel/OrderImages.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ContextMenu.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ContextMenu.bmp deleted file mode 100644 index 011fa7e6fbd..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ContextMenu.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ContextMenu.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ContextMenu.ico new file mode 100644 index 00000000000..a143ca87bf9 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ContextMenu.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataConnector.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataConnector.bmp deleted file mode 100644 index c0d2015fc43..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataConnector.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataConnector.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataConnector.ico new file mode 100644 index 00000000000..8040cb6209f Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataConnector.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGrid.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGrid.bmp deleted file mode 100644 index 9b6a6179aee..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGrid.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGrid.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGrid.ico new file mode 100644 index 00000000000..1224f417dce Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGrid.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.Details.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.Details.bmp deleted file mode 100644 index f6c73b07975..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.Details.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.Details.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.Details.ico new file mode 100644 index 00000000000..0972abc3e68 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.Details.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow.bmp deleted file mode 100644 index e847385afe1..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow.ico new file mode 100644 index 00000000000..0cc431d3289 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow_bidi.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow_bidi.bmp deleted file mode 100644 index 89378ff0e5c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow_bidi.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow_bidi.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow_bidi.ico new file mode 100644 index 00000000000..f40ff076e96 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.backarrow_bidi.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.down.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.down.bmp deleted file mode 100644 index da8a6843a87..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.down.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.down.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.down.ico new file mode 100644 index 00000000000..50d27e244e6 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.down.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.right.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.right.bmp deleted file mode 100644 index d64896979fa..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.right.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.right.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.right.ico new file mode 100644 index 00000000000..6746a855c5d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.right.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.up.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.up.bmp deleted file mode 100644 index 7367e7fd4e3..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.up.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.up.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.up.ico new file mode 100644 index 00000000000..30b8893ae7b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridCaption.up.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.LeftArrow.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.LeftArrow.bmp deleted file mode 100644 index 7d14ee77004..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.LeftArrow.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.LeftArrow.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.LeftArrow.ico new file mode 100644 index 00000000000..071c5079a8c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.LeftArrow.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.RightArrow.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.RightArrow.bmp deleted file mode 100644 index 84fc0e1a58c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.RightArrow.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.RightArrow.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.RightArrow.ico new file mode 100644 index 00000000000..328dd2f624b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridParentRows.RightArrow.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.error.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.error.bmp deleted file mode 100644 index ab1de1cd58c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.error.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.error.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.error.ico new file mode 100644 index 00000000000..f9a0da7ec5d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.error.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.left.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.left.bmp deleted file mode 100644 index 02ce71a9aed..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.left.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.left.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.left.ico new file mode 100644 index 00000000000..3dd5582cf2d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.left.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.pencil.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.pencil.bmp deleted file mode 100644 index 983725ce63b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.pencil.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.pencil.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.pencil.ico new file mode 100644 index 00000000000..be5398d2b44 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.pencil.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.right.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.right.bmp deleted file mode 100644 index 0640fd62b14..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.right.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.right.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.right.ico new file mode 100644 index 00000000000..6262753da1d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.right.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.star.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.star.bmp deleted file mode 100644 index 559b9e7d845..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.star.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.star.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.star.ico new file mode 100644 index 00000000000..dbdc71ddc7e Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridRow.star.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridView.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridView.bmp deleted file mode 100644 index 7345da04386..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridView.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridView.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridView.ico new file mode 100644 index 00000000000..1224f417dce Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridView.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewButtonColumn.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewButtonColumn.bmp deleted file mode 100644 index fd3e3bf92e1..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewButtonColumn.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewButtonColumn.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewButtonColumn.ico new file mode 100644 index 00000000000..bfbd41a2534 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewButtonColumn.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewCheckBoxColumn.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewCheckBoxColumn.bmp deleted file mode 100644 index c9661e4aafc..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewCheckBoxColumn.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewCheckBoxColumn.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewCheckBoxColumn.ico new file mode 100644 index 00000000000..49c6bb9f5e4 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewCheckBoxColumn.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewComboBoxColumn.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewComboBoxColumn.bmp deleted file mode 100644 index b07d897effe..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewComboBoxColumn.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewComboBoxColumn.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewComboBoxColumn.ico new file mode 100644 index 00000000000..09eee5dd8b4 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewComboBoxColumn.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewImageColumn.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewImageColumn.bmp deleted file mode 100644 index bff74d6d47c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewImageColumn.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewImageColumn.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewImageColumn.ico new file mode 100644 index 00000000000..ae863d72d5d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewImageColumn.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewLinkColumn.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewLinkColumn.bmp deleted file mode 100644 index a0451475ce7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewLinkColumn.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewLinkColumn.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewLinkColumn.ico new file mode 100644 index 00000000000..35c6a9cfd42 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewLinkColumn.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.error.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.error.bmp deleted file mode 100644 index ab1de1cd58c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.error.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.error.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.error.ico new file mode 100644 index 00000000000..f9a0da7ec5d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.error.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.bmp deleted file mode 100644 index 02ce71a9aed..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.ico index 0abcdb80653..3dd5582cf2d 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.left.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.bmp deleted file mode 100644 index ac042015d56..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.ico index fd7f4307ae1..802bce06380 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.leftstar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.bmp deleted file mode 100644 index 983725ce63b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.ico index 38e51003ff1..be5398d2b44 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_ltr.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.bmp deleted file mode 100644 index 342da116434..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.ico index ac25e58fbbf..600b31774f6 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.pencil_rtl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.bmp deleted file mode 100644 index 0640fd62b14..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.ico index aeeca1b7a8f..6262753da1d 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.right.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.bmp deleted file mode 100644 index e483e527560..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.ico index a89d769cbde..784ddf4bb01 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.rightstar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.bmp deleted file mode 100644 index 559b9e7d845..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.ico index c46c638e721..dbdc71ddc7e 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewRow.star.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewTextBoxColumn.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewTextBoxColumn.bmp deleted file mode 100644 index d2894577bc0..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewTextBoxColumn.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewTextBoxColumn.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewTextBoxColumn.ico new file mode 100644 index 00000000000..1b83771a357 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataGridViewTextBoxColumn.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.AddNew.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.AddNew.bmp deleted file mode 100644 index b46c65f2280..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.AddNew.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.AddNew.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.AddNew.ico new file mode 100644 index 00000000000..670bb049917 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.AddNew.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.Delete.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.Delete.bmp deleted file mode 100644 index f009ad8bf64..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.Delete.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.Delete.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.Delete.ico new file mode 100644 index 00000000000..bd95c7398d3 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.Delete.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveFirst.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveFirst.bmp deleted file mode 100644 index a38290f3b78..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveFirst.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveFirst.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveFirst.ico new file mode 100644 index 00000000000..9bf00477b0e Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveFirst.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveLast.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveLast.bmp deleted file mode 100644 index f6d6ac3ec0f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveLast.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveLast.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveLast.ico new file mode 100644 index 00000000000..19d9dd546cf Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveLast.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveNext.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveNext.bmp deleted file mode 100644 index fa1ceb58c4c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveNext.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveNext.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveNext.ico new file mode 100644 index 00000000000..328dd2f624b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MoveNext.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MovePrevious.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MovePrevious.bmp deleted file mode 100644 index 7c7f89c4ed7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MovePrevious.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MovePrevious.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MovePrevious.ico new file mode 100644 index 00000000000..071c5079a8c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.MovePrevious.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.bmp deleted file mode 100644 index a461710fd80..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.ico new file mode 100644 index 00000000000..f23e9fb0615 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DataNavigator.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DateTimePicker.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DateTimePicker.bmp deleted file mode 100644 index 4a96ccf8c27..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DateTimePicker.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DateTimePicker.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DateTimePicker.ico new file mode 100644 index 00000000000..298fc1be98c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DateTimePicker.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DefaultControl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DefaultControl.bmp deleted file mode 100644 index 3706785425f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DefaultControl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DefaultControl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DefaultControl.ico new file mode 100644 index 00000000000..f01f01eff8f Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DefaultControl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/ComponentEditorPage.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/ComponentEditorPage.ico index f0ec5f7f856..41d5510e4dc 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/ComponentEditorPage.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/ComponentEditorPage.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/Thumbs.db b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/Thumbs.db new file mode 100644 index 00000000000..b70d974c9af Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Design/Thumbs.db differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DomainUpDown.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DomainUpDown.bmp deleted file mode 100644 index 118cc684019..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DomainUpDown.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DomainUpDown.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DomainUpDown.ico new file mode 100644 index 00000000000..80cf851283f Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/DomainUpDown.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Edit.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Edit.bmp deleted file mode 100644 index 9b62d4c6aa6..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Edit.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Edit.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Edit.ico new file mode 100644 index 00000000000..1b83771a357 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Edit.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Error.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Error.ico index 97abee5d3b2..19788fda171 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Error.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Error.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorControl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorControl.bmp deleted file mode 100644 index 49a5c36bdec..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorControl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorControl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorControl.ico new file mode 100644 index 00000000000..19788fda171 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorControl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorProvider.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorProvider.bmp deleted file mode 100644 index b0f7f59cb35..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorProvider.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorProvider.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorProvider.ico new file mode 100644 index 00000000000..19788fda171 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ErrorProvider.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FlowLayoutPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FlowLayoutPanel.bmp deleted file mode 100644 index 2b378286617..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FlowLayoutPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FlowLayoutPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FlowLayoutPanel.ico new file mode 100644 index 00000000000..05eec2dcfab Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FlowLayoutPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FolderBrowserDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FolderBrowserDialog.bmp deleted file mode 100644 index c5c673a9bef..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FolderBrowserDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FolderBrowserDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FolderBrowserDialog.ico new file mode 100644 index 00000000000..5f1a9d2d945 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FolderBrowserDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FontDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FontDialog.bmp deleted file mode 100644 index c6d4bfab888..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FontDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FontDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FontDialog.ico new file mode 100644 index 00000000000..3986861f2ec Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/FontDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Form.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Form.bmp deleted file mode 100644 index 107d19ec99f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Form.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Form.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Form.ico new file mode 100644 index 00000000000..37e8b294a73 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Form.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Grid.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Grid.bmp deleted file mode 100644 index 0492fddc306..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Grid.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Grid.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Grid.ico new file mode 100644 index 00000000000..1224f417dce Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Grid.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/GroupBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/GroupBox.bmp deleted file mode 100644 index 827dfab23ff..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/GroupBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/GroupBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/GroupBox.ico new file mode 100644 index 00000000000..7703190e238 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/GroupBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HScrollBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HScrollBar.bmp deleted file mode 100644 index cdd937f81b2..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HScrollBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HScrollBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HScrollBar.ico new file mode 100644 index 00000000000..cd0dae240af Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HScrollBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HTMLControl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HTMLControl.bmp deleted file mode 100644 index 808b0acdb2c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HTMLControl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HTMLControl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HTMLControl.ico new file mode 100644 index 00000000000..fc276945d18 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HTMLControl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HelpProvider.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HelpProvider.bmp deleted file mode 100644 index 6de813e0b7f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HelpProvider.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HelpProvider.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HelpProvider.ico new file mode 100644 index 00000000000..69afaa9d433 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/HelpProvider.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IconInError.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IconInError.ico index e4a925143ef..73c9ca27334 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IconInError.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IconInError.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageInError.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageInError.bmp deleted file mode 100644 index 2b2dd8dbeae..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageInError.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageInError.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageInError.ico new file mode 100644 index 00000000000..22cd1cd039e Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageInError.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageList.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageList.bmp deleted file mode 100644 index c68414ed413..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageList.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageList.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageList.ico new file mode 100644 index 00000000000..18a8f63855b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ImageList.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IndeterminateChecked.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IndeterminateChecked.ico index ff8ac4d73ee..1a40873d33d 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IndeterminateChecked.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/IndeterminateChecked.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Label.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Label.bmp deleted file mode 100644 index 8ab432db6ee..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Label.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Label.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Label.ico new file mode 100644 index 00000000000..d01d5212b90 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Label.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/LinkLabel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/LinkLabel.bmp deleted file mode 100644 index 8fa9a673bcc..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/LinkLabel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/LinkLabel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/LinkLabel.ico new file mode 100644 index 00000000000..0380e6cfc0c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/LinkLabel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListBox.bmp deleted file mode 100644 index 938781b4897..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListBox.ico new file mode 100644 index 00000000000..4cc6dd7aedc Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListView.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListView.bmp deleted file mode 100644 index a1be5319dfb..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListView.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListView.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListView.ico new file mode 100644 index 00000000000..80af9756fc4 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ListView.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MainMenu.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MainMenu.bmp deleted file mode 100644 index 9ce84c6248a..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MainMenu.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MainMenu.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MainMenu.ico new file mode 100644 index 00000000000..4ed90f33d27 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MainMenu.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MaskedTextBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MaskedTextBox.bmp deleted file mode 100644 index 19ba5f9d4e7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MaskedTextBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MaskedTextBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MaskedTextBox.ico new file mode 100644 index 00000000000..85b14283c4a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MaskedTextBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MonthCalendar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MonthCalendar.bmp deleted file mode 100644 index b1efec72212..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MonthCalendar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MonthCalendar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MonthCalendar.ico new file mode 100644 index 00000000000..8e53f6c64f5 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MonthCalendar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MultiplexPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MultiplexPanel.bmp deleted file mode 100644 index f91c6aa9b60..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MultiplexPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MultiplexPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MultiplexPanel.ico new file mode 100644 index 00000000000..83d076ea161 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/MultiplexPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NotifyIcon.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NotifyIcon.bmp deleted file mode 100644 index 986033cff19..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NotifyIcon.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NotifyIcon.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NotifyIcon.ico new file mode 100644 index 00000000000..059e5a1c459 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NotifyIcon.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NumericUpDown.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NumericUpDown.bmp deleted file mode 100644 index a68cbff6312..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NumericUpDown.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NumericUpDown.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NumericUpDown.ico new file mode 100644 index 00000000000..0ceca3fd328 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/NumericUpDown.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/OpenFileDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/OpenFileDialog.bmp deleted file mode 100644 index 47d90d908f5..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/OpenFileDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/OpenFileDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/OpenFileDialog.ico new file mode 100644 index 00000000000..d0f633d601b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/OpenFileDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Panel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Panel.bmp deleted file mode 100644 index 76b67b75025..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Panel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Panel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Panel.ico new file mode 100644 index 00000000000..c17bf2770de Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Panel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox.bmp deleted file mode 100644 index 86016e9ecd7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox.ico new file mode 100644 index 00000000000..1a0c09d9ef0 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox/Loading.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox/Loading.bmp deleted file mode 100644 index c65e89c4a26..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox/Loading.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox/Loading.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox/Loading.ico new file mode 100644 index 00000000000..7a12b86bf3a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PictureBox/Loading.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewControl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewControl.bmp deleted file mode 100644 index 9e57891d3b7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewControl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewControl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewControl.ico new file mode 100644 index 00000000000..03ff7c04c2b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewControl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewDialog.bmp deleted file mode 100644 index ecfa916e631..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewDialog.ico new file mode 100644 index 00000000000..0255b5e40ad Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewStrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewStrip.bmp deleted file mode 100644 index 2df8906fd2a..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewStrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewStrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewStrip.ico new file mode 100644 index 00000000000..2d2dd145b27 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PrintPreviewStrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PageSetupDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PageSetupDialog.bmp deleted file mode 100644 index 190b8a6e6c9..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PageSetupDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PageSetupDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PageSetupDialog.ico new file mode 100644 index 00000000000..d13972a3726 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PageSetupDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PrintDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PrintDialog.bmp deleted file mode 100644 index 811f6a11dcb..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PrintDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PrintDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PrintDialog.ico new file mode 100644 index 00000000000..f0a4a29c9d1 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Printing/PrintDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ProgressBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ProgressBar.bmp deleted file mode 100644 index 7edf5865344..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ProgressBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ProgressBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ProgressBar.ico new file mode 100644 index 00000000000..04b56e6caec Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ProgressBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/EventsTab.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/EventsTab.bmp deleted file mode 100644 index 8c7eb2be01f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/EventsTab.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/EventsTab.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/EventsTab.ico new file mode 100644 index 00000000000..556ece2d4cd Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/EventsTab.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBAlpha.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBAlpha.bmp deleted file mode 100644 index 9b4c023aad6..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBAlpha.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBAlpha.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBAlpha.ico new file mode 100644 index 00000000000..a92175fa529 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBAlpha.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBCatego.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBCatego.bmp deleted file mode 100644 index febf09d45dd..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBCatego.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBCatego.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBCatego.ico new file mode 100644 index 00000000000..e924d0678b7 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBCatego.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBEvent.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBEvent.bmp deleted file mode 100644 index f7d321795c1..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBEvent.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBEvent.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBEvent.ico new file mode 100644 index 00000000000..dab2c8aa092 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBEvent.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBPPage.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBPPage.bmp deleted file mode 100644 index 2500d36b842..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBPPage.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBPPage.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBPPage.ico new file mode 100644 index 00000000000..8db8eb917b7 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBPPage.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBProp.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBProp.bmp deleted file mode 100644 index 5a8b72a200b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBProp.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBProp.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBProp.ico new file mode 100644 index 00000000000..cbabdace50a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PBProp.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertiesTab.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertiesTab.bmp deleted file mode 100644 index e488fb28694..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertiesTab.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertiesTab.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertiesTab.ico new file mode 100644 index 00000000000..cbabdace50a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertiesTab.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertyGrid.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertyGrid.bmp deleted file mode 100644 index 5a8b72a200b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertyGrid.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertyGrid.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertyGrid.ico new file mode 100644 index 00000000000..cbabdace50a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/PropertyGrid.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/arrow.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/arrow.ico index 726070727a2..b25612d2973 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/arrow.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/arrow.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.ico index 8a94f992496..4e3f5791d30 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.png b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.png deleted file mode 100644 index d0a45d86d7b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/PropertyGrid/dotdotdot.png and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RadioButton.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RadioButton.bmp deleted file mode 100644 index 38a344a589f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RadioButton.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RadioButton.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RadioButton.ico new file mode 100644 index 00000000000..c467a241981 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RadioButton.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Rebar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Rebar.bmp deleted file mode 100644 index d607e89472d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Rebar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Rebar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Rebar.ico new file mode 100644 index 00000000000..9d650366ae4 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Rebar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichEdit.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichEdit.bmp deleted file mode 100644 index d548137cb88..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichEdit.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichEdit.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichEdit.ico new file mode 100644 index 00000000000..d9dcc902244 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichEdit.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichTextBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichTextBox.bmp deleted file mode 100644 index 72641f7be77..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichTextBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichTextBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichTextBox.ico new file mode 100644 index 00000000000..d9dcc902244 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/RichTextBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SaveFileDialog.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SaveFileDialog.bmp deleted file mode 100644 index ff76598cca8..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SaveFileDialog.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SaveFileDialog.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SaveFileDialog.ico new file mode 100644 index 00000000000..aead779aa94 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SaveFileDialog.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Server/Arrow.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Server/Arrow.bmp deleted file mode 100644 index ef847d027be..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Server/Arrow.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Server/Arrow.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Server/Arrow.ico new file mode 100644 index 00000000000..b25612d2973 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Server/Arrow.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitContainer.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitContainer.bmp deleted file mode 100644 index c309fdcb8e5..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitContainer.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitContainer.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitContainer.ico new file mode 100644 index 00000000000..51ea4049c95 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitContainer.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Splitter.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Splitter.bmp deleted file mode 100644 index b1f06be1085..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Splitter.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Splitter.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Splitter.ico new file mode 100644 index 00000000000..ae51bbbd243 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/Splitter.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitterPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitterPanel.bmp deleted file mode 100644 index 325d8021f95..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitterPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitterPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitterPanel.ico new file mode 100644 index 00000000000..ae48c4d76a5 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/SplitterPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/StatusBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/StatusBar.bmp deleted file mode 100644 index 1a5a66cbb1d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/StatusBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/StatusBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/StatusBar.ico new file mode 100644 index 00000000000..862dba163dc Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/StatusBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabControl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabControl.bmp deleted file mode 100644 index e7db4b7f79c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabControl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabControl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabControl.ico new file mode 100644 index 00000000000..8f90c03bbb3 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabControl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabPage.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabPage.bmp deleted file mode 100644 index 802536d4f47..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabPage.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabPage.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabPage.ico new file mode 100644 index 00000000000..6ec57e37a2d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabPage.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabStrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabStrip.bmp deleted file mode 100644 index 84d62bdafad..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabStrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabStrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabStrip.ico new file mode 100644 index 00000000000..8f90c03bbb3 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TabStrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TableLayoutPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TableLayoutPanel.bmp deleted file mode 100644 index f6d219610c7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TableLayoutPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TableLayoutPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TableLayoutPanel.ico new file mode 100644 index 00000000000..f8905fd2a41 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TableLayoutPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TextBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TextBox.bmp deleted file mode 100644 index 50f94af451d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TextBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TextBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TextBox.ico new file mode 100644 index 00000000000..d93d3f95516 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TextBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolBar.bmp deleted file mode 100644 index 199d58b21ef..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolBar.ico new file mode 100644 index 00000000000..2beae602c8b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/AlignToGridHS.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/AlignToGridHS.bmp deleted file mode 100644 index e9da561ae0f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/AlignToGridHS.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/AlignToGridHS.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/AlignToGridHS.ico new file mode 100644 index 00000000000..c96379552e3 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/AlignToGridHS.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BlankToolstrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BlankToolstrip.bmp deleted file mode 100644 index 948a9df5397..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BlankToolstrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BlankToolstrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BlankToolstrip.ico new file mode 100644 index 00000000000..395bf4e2f0d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BlankToolstrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BringToFrontHS.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BringToFrontHS.bmp deleted file mode 100644 index 4696efc65de..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BringToFrontHS.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BringToFrontHS.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BringToFrontHS.ico new file mode 100644 index 00000000000..b330827b311 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/BringToFrontHS.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip.bmp deleted file mode 100644 index 228448d7078..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip.ico new file mode 100644 index 00000000000..f686b8fd147 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip_copy.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip_copy.bmp deleted file mode 100644 index 228448d7078..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ContextMenuStrip_copy.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ImageEditor.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ImageEditor.bmp deleted file mode 100644 index e6c9b2eb3c6..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ImageEditor.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ImageEditor.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ImageEditor.ico new file mode 100644 index 00000000000..a5d823e5c8b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ImageEditor.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/MenuStrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/MenuStrip.bmp deleted file mode 100644 index 9ce84c6248a..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/MenuStrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/MenuStrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/MenuStrip.ico new file mode 100644 index 00000000000..0fdc8b09706 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/MenuStrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonDown.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonDown.bmp deleted file mode 100644 index 3de97d33717..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonDown.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonDown.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonDown.ico new file mode 100644 index 00000000000..0ebeec60633 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonDown.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonUp.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonUp.bmp deleted file mode 100644 index 5ee7c56a85e..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonUp.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonUp.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonUp.ico new file mode 100644 index 00000000000..641cadbffa8 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ScrollButtonUp.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/SendToBackHS.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/SendToBackHS.bmp deleted file mode 100644 index 1523a3a8d62..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/SendToBackHS.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/SendToBackHS.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/SendToBackHS.ico new file mode 100644 index 00000000000..39dbf76c0af Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/SendToBackHS.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStrip.bmp deleted file mode 100644 index 1a5a66cbb1d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStrip.ico new file mode 100644 index 00000000000..c7b2603f8fc Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStripPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStripPanel.bmp deleted file mode 100644 index 26b64912951..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStripPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStripPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStripPanel.ico new file mode 100644 index 00000000000..0caff7741ad Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/StatusStripPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/Thumbs.db b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/Thumbs.db new file mode 100644 index 00000000000..110548ec789 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/Thumbs.db differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolBarGrip-Temporary.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolBarGrip-Temporary.bmp deleted file mode 100644 index 19aaccff981..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolBarGrip-Temporary.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolBarGrip-Temporary.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolBarGrip-Temporary.ico new file mode 100644 index 00000000000..a05b7f9ac9d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolBarGrip-Temporary.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStrip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStrip.bmp deleted file mode 100644 index 199d58b21ef..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStrip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStrip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStrip.ico new file mode 100644 index 00000000000..3a28910d058 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStrip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripButton.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripButton.bmp deleted file mode 100644 index f1843f1e474..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripButton.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripButton.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripButton.ico new file mode 100644 index 00000000000..2f9b47b5afc Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripButton.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripComboBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripComboBox.bmp deleted file mode 100644 index 53d335293a4..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripComboBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripComboBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripComboBox.ico new file mode 100644 index 00000000000..653e95ed835 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripComboBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer.bmp deleted file mode 100644 index 3cadf82ac8b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer.ico new file mode 100644 index 00000000000..dd948315c34 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_BottomToolStripPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_BottomToolStripPanel.bmp deleted file mode 100644 index 297415ad25a..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_BottomToolStripPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_BottomToolStripPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_BottomToolStripPanel.ico new file mode 100644 index 00000000000..3b1badf4c29 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_BottomToolStripPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_LeftToolStripPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_LeftToolStripPanel.bmp deleted file mode 100644 index b463e378778..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_LeftToolStripPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_LeftToolStripPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_LeftToolStripPanel.ico new file mode 100644 index 00000000000..d60f798f686 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_LeftToolStripPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_RightToolStripPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_RightToolStripPanel.bmp deleted file mode 100644 index 293ff2ac6a4..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_RightToolStripPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_RightToolStripPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_RightToolStripPanel.ico new file mode 100644 index 00000000000..d254c488eeb Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_RightToolStripPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_TopToolStripPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_TopToolStripPanel.bmp deleted file mode 100644 index 52db326899c..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_TopToolStripPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_TopToolStripPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_TopToolStripPanel.ico new file mode 100644 index 00000000000..c828a45e1df Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContainer_TopToolStripPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContentPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContentPanel.bmp deleted file mode 100644 index 83f54e7d044..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContentPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContentPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContentPanel.ico new file mode 100644 index 00000000000..25f0077fa99 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripContentPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDown.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDown.bmp deleted file mode 100644 index 228448d7078..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDown.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDown.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDown.ico new file mode 100644 index 00000000000..f686b8fd147 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDown.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownButton.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownButton.bmp deleted file mode 100644 index bdcc3d4c5ac..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownButton.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownButton.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownButton.ico new file mode 100644 index 00000000000..0fdc8b09706 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownButton.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownMenu.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownMenu.bmp deleted file mode 100644 index 228448d7078..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownMenu.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownMenu.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownMenu.ico new file mode 100644 index 00000000000..f686b8fd147 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripDropDownMenu.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripLabel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripLabel.bmp deleted file mode 100644 index 26b64912951..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripLabel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripLabel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripLabel.ico new file mode 100644 index 00000000000..0caff7741ad Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripLabel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripMenuItem.bmp deleted file mode 100644 index 469dc72cdb9..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripMenuItem.ico new file mode 100644 index 00000000000..0fdc8b09706 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripPanel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripPanel.bmp deleted file mode 100644 index 4298bab4e2d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripPanel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripPanel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripPanel.ico new file mode 100644 index 00000000000..7448efb718d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripPanel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripProgressBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripProgressBar.bmp deleted file mode 100644 index 3a08885cd9a..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripProgressBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripProgressBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripProgressBar.ico new file mode 100644 index 00000000000..ec52de79ea3 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripProgressBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSeparator.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSeparator.bmp deleted file mode 100644 index c521d3525f5..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSeparator.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSeparator.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSeparator.ico new file mode 100644 index 00000000000..9a8f3c1d462 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSeparator.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSplitButton.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSplitButton.bmp deleted file mode 100644 index 1ee46102027..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSplitButton.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSplitButton.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSplitButton.ico new file mode 100644 index 00000000000..bd6b8d16f55 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripSplitButton.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripStatusLabel.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripStatusLabel.bmp deleted file mode 100644 index 26b64912951..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripStatusLabel.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripStatusLabel.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripStatusLabel.ico new file mode 100644 index 00000000000..0caff7741ad Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripStatusLabel.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripTextBox.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripTextBox.bmp deleted file mode 100644 index 4a0bd743f6d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripTextBox.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripTextBox.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripTextBox.ico new file mode 100644 index 00000000000..bcca8d1aa3d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/ToolStripTextBox.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/alignmenttoolstripmenuitem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/alignmenttoolstripmenuitem.bmp deleted file mode 100644 index 9f1b17f84ea..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/alignmenttoolstripmenuitem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/alignmenttoolstripmenuitem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/alignmenttoolstripmenuitem.ico new file mode 100644 index 00000000000..055ef2ac8ef Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/alignmenttoolstripmenuitem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/copyToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/copyToolStripMenuItem.bmp deleted file mode 100644 index c1e37e4cd4d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/copyToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/copyToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/copyToolStripMenuItem.ico new file mode 100644 index 00000000000..80a566dd4a1 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/copyToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/cutToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/cutToolStripMenuItem.bmp deleted file mode 100644 index 5e90e0c98f6..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/cutToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/cutToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/cutToolStripMenuItem.ico new file mode 100644 index 00000000000..9d18330ae88 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/cutToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/deleteToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/deleteToolStripMenuItem.bmp deleted file mode 100644 index 3b0a7002b87..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/deleteToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/deleteToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/deleteToolStripMenuItem.ico new file mode 100644 index 00000000000..1d778197d88 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/deleteToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/displaystyletoolstripmenuitem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/displaystyletoolstripmenuitem.bmp deleted file mode 100644 index 69d770aa21f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/displaystyletoolstripmenuitem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/displaystyletoolstripmenuitem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/displaystyletoolstripmenuitem.ico new file mode 100644 index 00000000000..395bf4e2f0d Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/displaystyletoolstripmenuitem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/editdropdownlisttoolstripmenuitem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/editdropdownlisttoolstripmenuitem.bmp deleted file mode 100644 index 5c5204694b6..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/editdropdownlisttoolstripmenuitem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/editdropdownlisttoolstripmenuitem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/editdropdownlisttoolstripmenuitem.ico new file mode 100644 index 00000000000..8a92d54bf78 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/editdropdownlisttoolstripmenuitem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/helpToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/helpToolStripMenuItem.bmp deleted file mode 100644 index b5b89835aa9..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/helpToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/helpToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/helpToolStripMenuItem.ico new file mode 100644 index 00000000000..802d926203c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/helpToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/imagetoolstripmenuitem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/imagetoolstripmenuitem.bmp deleted file mode 100644 index a4939d0635b..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/imagetoolstripmenuitem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/imagetoolstripmenuitem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/imagetoolstripmenuitem.ico new file mode 100644 index 00000000000..c12350bfc1a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/imagetoolstripmenuitem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/lockControls.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/lockControls.bmp deleted file mode 100644 index 30e791a51b6..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/lockControls.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/lockControls.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/lockControls.ico new file mode 100644 index 00000000000..da49de07db5 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/lockControls.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/newToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/newToolStripMenuItem.bmp deleted file mode 100644 index 669f3db62e2..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/newToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/newToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/newToolStripMenuItem.ico new file mode 100644 index 00000000000..cf7a5b43167 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/newToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/openToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/openToolStripMenuItem.bmp deleted file mode 100644 index 98471e4f154..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/openToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/openToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/openToolStripMenuItem.ico new file mode 100644 index 00000000000..24741579c30 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/openToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/overflowButton-Temporary.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/overflowButton-Temporary.bmp deleted file mode 100644 index f94e99eb61f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/overflowButton-Temporary.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/overflowButton-Temporary.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/overflowButton-Temporary.ico new file mode 100644 index 00000000000..db06608e326 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/overflowButton-Temporary.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/pasteToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/pasteToolStripMenuItem.bmp deleted file mode 100644 index 1cf85ec181f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/pasteToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/pasteToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/pasteToolStripMenuItem.ico new file mode 100644 index 00000000000..938964ae767 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/pasteToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printPreviewToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printPreviewToolStripMenuItem.bmp deleted file mode 100644 index 2acae51dedd..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printPreviewToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printPreviewToolStripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printPreviewToolStripMenuItem.ico new file mode 100644 index 00000000000..17c658a02b7 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printPreviewToolStripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printToolStripMenuItem.bmp deleted file mode 100644 index 5e897c2236d..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printToolstripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printToolstripMenuItem.ico new file mode 100644 index 00000000000..7d2f14b0a2a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/printToolstripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/propertiestoolstripmenuitem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/propertiestoolstripmenuitem.bmp deleted file mode 100644 index 8b850d58a80..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/propertiestoolstripmenuitem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/propertiestoolstripmenuitem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/propertiestoolstripmenuitem.ico new file mode 100644 index 00000000000..875258b0093 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/propertiestoolstripmenuitem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/saveToolStripMenuItem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/saveToolStripMenuItem.bmp deleted file mode 100644 index e59f0d211d4..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/saveToolStripMenuItem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/saveToolstripMenuItem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/saveToolstripMenuItem.ico new file mode 100644 index 00000000000..f649255281a Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/saveToolstripMenuItem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/viewcodetoolstripmenuitem.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/viewcodetoolstripmenuitem.bmp deleted file mode 100644 index 95c27019d71..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/viewcodetoolstripmenuitem.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/viewcodetoolstripmenuitem.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/viewcodetoolstripmenuitem.ico new file mode 100644 index 00000000000..aacb4e2e86c Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStrip/viewcodetoolstripmenuitem.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStripContainer.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStripContainer.bmp deleted file mode 100644 index 871a41dc09f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStripContainer.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStripContainer.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStripContainer.ico new file mode 100644 index 00000000000..3dfc89bd28f Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolStripContainer.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolTip.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolTip.bmp deleted file mode 100644 index 21889c998d7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolTip.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolTip.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolTip.ico new file mode 100644 index 00000000000..fe523f9ff44 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/ToolTip.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrackBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrackBar.bmp deleted file mode 100644 index 21cc9b4b4eb..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrackBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrackBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrackBar.ico new file mode 100644 index 00000000000..5073727fc61 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrackBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrayIcon.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrayIcon.bmp deleted file mode 100644 index 16cd265f2bf..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrayIcon.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrayIcon.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrayIcon.ico new file mode 100644 index 00000000000..4ffb3ab72bc Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrayIcon.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TreeView.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TreeView.bmp deleted file mode 100644 index 18e858395b7..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TreeView.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TreeView.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TreeView.ico new file mode 100644 index 00000000000..c195f3b5969 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TreeView.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerGlobe.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerGlobe.ico new file mode 100644 index 00000000000..52d16b230c9 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerGlobe.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerHighRisk.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerHighRisk.ico new file mode 100644 index 00000000000..ad5c8c44da0 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerHighRisk.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerOK.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerOK.ico new file mode 100644 index 00000000000..2d1c90722ab Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerOK.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerWarning.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerWarning.ico new file mode 100644 index 00000000000..d86eb74647b Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/TrustManagerWarning.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/UserControl.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/UserControl.bmp deleted file mode 100644 index 3706785425f..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/UserControl.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/UserControl.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/UserControl.ico new file mode 100644 index 00000000000..19d9c52a381 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/UserControl.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/VScrollBar.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/VScrollBar.bmp deleted file mode 100644 index eb66caa788e..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/VScrollBar.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/VScrollBar.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/VScrollBar.ico new file mode 100644 index 00000000000..5cb48a83a57 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/VScrollBar.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/WebBrowser.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/WebBrowser.bmp deleted file mode 100644 index 3846d1c8ba0..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/WebBrowser.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/WebBrowser.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/WebBrowser.ico new file mode 100644 index 00000000000..692d79b48c7 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/WebBrowser.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/checked.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/checked.bmp deleted file mode 100644 index ba1ccb56d47..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/checked.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/down.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/down.bmp deleted file mode 100644 index 5dd9c420122..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/down.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/down.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/down.ico new file mode 100644 index 00000000000..152c78c80ea Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/down.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/indeterminatechecked.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/indeterminatechecked.bmp deleted file mode 100644 index f5d637fd05a..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/indeterminatechecked.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/sm_TrustManagerGlobe.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/sm_TrustManagerGlobe.ico new file mode 100644 index 00000000000..52d16b230c9 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/sm_TrustManagerGlobe.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/up.bmp b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/up.bmp deleted file mode 100644 index eae5dea7c75..00000000000 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/up.bmp and /dev/null differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/up.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/up.ico new file mode 100644 index 00000000000..133ccd66af3 Binary files /dev/null and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/up.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfc.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfc.ico index 982e89042bd..a04b745a865 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfc.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfc.ico differ diff --git a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfsecurity.ico b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfsecurity.ico index bbffea3dde3..74d2e49737b 100644 Binary files a/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfsecurity.ico and b/src/System.Windows.Forms/src/Resources/System/Windows/Forms/wfsecurity.ico differ diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf index 0ac74682191..a65c41a2488 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Vodorovný posuvník + Horizontal + Vodorovný posuvník @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Svislý posuvník + Vertical + Svislý posuvník @@ -9201,50 +9201,6 @@ Trasování zásobníku, kde došlo k neplatné operaci: Získá svislý posuvník pro tento ovládací prvek ScrollableControl. - - Mixed Zone - Smíšená zóna - - - - Multiple Sites - Několik serverů - - - - Unknown Site - Neznámý server - - - - Unknown Zone - Neznámá zóna - - - - Microsoft .NET Security Warning - Upozornění zabezpečení Microsoft .NET - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - Nikdy do okna nezadávejte osobní informace nebo hesla, pokud nelze ověřit zdroj požadavku a považovat ho za důvěryhodný. - - - - Source: {0} - Zdroj: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. Hodnota SelTabCount je mimo rozsah. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf index 4f0c60de06c..39efde771a5 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Horizontale Bildlaufeiste + Horizontal + Horizontale Bildlaufeiste @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Vertikale Bildlaufleiste + Vertical + Vertikale Bildlaufleiste @@ -9201,50 +9201,6 @@ Stapelüberwachung, in der der unzulässige Vorgang auftrat: Ruft die vertikale Schiebeleiste für diese ScrollableControl ab. - - Mixed Zone - Gemischte Zone - - - - Multiple Sites - Mehrere Sites - - - - Unknown Site - Unbekannte Site. - - - - Unknown Zone - Unbekannte Zone. - - - - Microsoft .NET Security Warning - Microsoft .NET-Sicherheitswarnung - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - Geben Sie nie persönliche Informationen oder Kennwörter in ein Fenster ein, außer Sie können die Quelle der Anforderung überprüfen und dieser vertrauen. - - - - Source: {0} - Quelle: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount liegt außerhalb des definierten Bereichs. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf index e229b441bc7..d93bdf621f0 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Barra de desplazamiento horizontal + Horizontal + Barra de desplazamiento horizontal @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Barra de desplazamiento vertical + Vertical + Barra de desplazamiento vertical @@ -9201,50 +9201,6 @@ El seguimiento de la pila donde tuvo lugar la operación no válida fue: Obtiene la barra de desplazamiento vertical para este ScrollableControl. - - Mixed Zone - Zona mixta - - - - Multiple Sites - Varios sitios - - - - Unknown Site - Sitio desconocido - - - - Unknown Zone - Zona desconocida - - - - Microsoft .NET Security Warning - Advertencia de seguridad Microsoft .NET - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - No proporcione información ni contraseñas personales en una ventana a menos que pueda comprobar y confiar en el origen de la solicitud. - - - - Source: {0} - Origen: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount fuera del intervalo. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf index 57f6332ecd9..b1d7483dcff 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Barre de défilement horizontale + Horizontal + Barre de défilement horizontale @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Barre de défilement verticale + Vertical + Barre de défilement verticale @@ -9201,50 +9201,6 @@ Cette opération non conforme s'est produite sur la trace de la pile : Obtient la barre de défilement verticale pour ce ScrollableControl. - - Mixed Zone - Zone mixte - - - - Multiple Sites - Plusieurs sites - - - - Unknown Site - Site inconnu - - - - Unknown Zone - Zone inconnue - - - - Microsoft .NET Security Warning - Avertissement de sécurité Microsoft .NET - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - N'entrez jamais d'informations personnelles ou de mot de passe dans une fenêtre sauf si vous pouvez vérifier et faire confiance à la source de la demande. - - - - Source: {0} - Source : {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount hors limites. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf index 7a3eecadc9f..f666ea8f14b 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Barra di scorrimento orizzontale + Horizontal + Barra di scorrimento orizzontale @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Barra di scorrimento verticale + Vertical + Barra di scorrimento verticale @@ -9201,50 +9201,6 @@ Traccia dello stack da cui si è verificata l'operazione non valida: Ottiene la barra di scorrimento verticale per ScrollableControl corrente. - - Mixed Zone - Zona mista - - - - Multiple Sites - Più siti - - - - Unknown Site - Sito sconosciuto - - - - Unknown Zone - Zona sconosciuta - - - - Microsoft .NET Security Warning - Microsoft .NET - Avviso di sicurezza - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - Non inserire informazioni personali né password in una finestra a meno che non si possa verificare e considerare attendibile l'origine della richiesta. - - - - Source: {0} - Origine: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount non compreso nell'intervallo. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf index bb5ef565e5d..29f75859c77 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - 水平スクロール バー + Horizontal + 水平スクロール バー @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - 垂直スクロール バー + Vertical + 垂直スクロール バー @@ -9201,50 +9201,6 @@ Stack trace where the illegal operation occurred was: この ScrollableControl に垂直スクロール バーを取得します。 - - Mixed Zone - 混合ゾーン - - - - Multiple Sites - 複数のサイト - - - - Unknown Site - 不明なサイト - - - - Unknown Zone - 不明なゾーン - - - - Microsoft .NET Security Warning - Microsoft .NET セキュリティ警告 - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - 要求元を検証および信頼できない場合、個人情報またはパスワードをウィンドウに入力しないでください。 - - - - Source: {0} - ソース: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount が範囲外です。 diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf index 563ca4d4de6..256f0bd52ce 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - 가로 스크롤 막대 + Horizontal + 가로 스크롤 막대 @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - 세로 스크롤 막대 + Vertical + 세로 스크롤 막대 @@ -9201,50 +9201,6 @@ Stack trace where the illegal operation occurred was: 이 ScrollableControl의 세로 스크롤 막대를 가져옵니다. - - Mixed Zone - 혼합 영역입니다. - - - - Multiple Sites - 사이트가 여러 개입니다. - - - - Unknown Site - 알 수 없는 사이트입니다. - - - - Unknown Zone - 알 수 없는 영역입니다. - - - - Microsoft .NET Security Warning - Microsoft .NET 보안 경고 - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - 요청의 소스를 확인하거나 신뢰할 수 있는 경우가 아니라면 창에 개인 정보 또는 암호를 입력하지 않는 것이 좋습니다. - - - - Source: {0} - 소스: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount가 범위를 벗어났습니다. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf index f4c3e468bb9..0868676e111 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Poziomy pasek przewijania + Horizontal + Poziomy pasek przewijania @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Pionowy pasek przewijania + Vertical + Pionowy pasek przewijania @@ -9201,50 +9201,6 @@ Stos śledzenia, w którym wystąpiła zabroniona operacja: Pobiera pionowy pasek przewijania dla tego elementu ScrollableControl. - - Mixed Zone - Strefa mieszana - - - - Multiple Sites - Wiele witryn - - - - Unknown Site - Nieznana witryna - - - - Unknown Zone - Nieznana strefa - - - - Microsoft .NET Security Warning - Ostrzeżenie zabezpieczeń Microsoft .NET - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - Nigdy nie podawaj informacji osobistych ani haseł w oknach, jeśli nie możesz sprawdzić źródła żądania i zaufać mu. - - - - Source: {0} - Źródło: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. Wartość elementu SelTabCount poza zakresem. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf index ed059a5c981..0ae8fa0c601 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Barra de rolagem horizontal + Horizontal + Barra de rolagem horizontal @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Barra de Rolagem Vertical + Vertical + Barra de Rolagem Vertical @@ -9201,50 +9201,6 @@ Rastreamento de pilha em que a operação ilegal ocorreu: Obtém a barra de rolagem vertical para ScrollableControl. - - Mixed Zone - Zona Mista - - - - Multiple Sites - Vários Sites - - - - Unknown Site - Site Desconhecido - - - - Unknown Zone - Zona Desconhecida - - - - Microsoft .NET Security Warning - Aviso de Segurança do Microsoft .NET - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - Nunca insira informações pessoais ou senhas em uma janela, a menos que possa verificar e confiar na fonte da solicitação. - - - - Source: {0} - Origem: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount fora do intervalo. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf index 9c48c130d79..24c5b731773 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Горизонтальная полоса прокрутки + Horizontal + Горизонтальная полоса прокрутки @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Вертикальная полоса прокрутки + Vertical + Вертикальная полоса прокрутки @@ -9202,50 +9202,6 @@ Stack trace where the illegal operation occurred was: Получает вертикальную полосу прокрутки для данного ScrollableControl. - - Mixed Zone - Смешанная зона - - - - Multiple Sites - Несколько сайтов - - - - Unknown Site - Неизвестный сайт - - - - Unknown Zone - Неизвестная зона - - - - Microsoft .NET Security Warning - Информация о безопасности Microsoft .NET - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - Никогда не вводите личные данные или пароли в окна, если вы не проверили источник запроса и не можете ему доверять. - - - - Source: {0} - Источник: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount вне допустимого диапазона. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf index 715927f790e..effd9f27d82 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - Yatay Kaydırma Çubuğu + Horizontal + Yatay Kaydırma Çubuğu @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - Dikey Kaydırma Çubuğu + Vertical + Dikey Kaydırma Çubuğu @@ -9201,50 +9201,6 @@ Geçersiz işlemin gerçekleştiği yığın izi: Bu ScrollableControl için dikey kaydırma çubuğunu alır. - - Mixed Zone - Karışık Bölge - - - - Multiple Sites - Birden Çok Site - - - - Unknown Site - Bilinmeyen Site - - - - Unknown Zone - Bilinmeyen Bölge - - - - Microsoft .NET Security Warning - Microsoft .NET Güvenlik Uyarısı - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - İstek kaynağını doğrulayamıyor ve güvenmiyorsanız bir pencereye kişisel bilgiler veya parolalar girmeyin. - - - - Source: {0} - Kaynak: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount aralık dışında. diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf index 12463af6401..75d5e8f8400 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - 水平滚动条 + Horizontal + 水平滚动条 @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - 垂直滚动条 + Vertical + 垂直滚动条 @@ -9201,50 +9201,6 @@ Stack trace where the illegal operation occurred was: 获取此 ScrollableControl 的垂直滚动条。 - - Mixed Zone - 混合区域 - - - - Multiple Sites - 多个站点 - - - - Unknown Site - 未知站点 - - - - Unknown Zone - 未知区域 - - - - Microsoft .NET Security Warning - Microsoft .NET 安全警告 - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - 除非您能够验证并信任请求的来源,否则,切勿在窗口中输入个人信息或密码。 - - - - Source: {0} - 源: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount 超出范围。 diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf index e9ef0335039..21e92b3354f 100644 --- a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf +++ b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf @@ -3133,8 +3133,8 @@ - Horizontal Scroll Bar - 水平捲軸 + Horizontal + 水平捲軸 @@ -3188,8 +3188,8 @@ - Vertical Scroll Bar - 垂直捲軸 + Vertical + 垂直捲軸 @@ -9201,50 +9201,6 @@ Stack trace where the illegal operation occurred was: 取得此 ScrollableControl 的垂直捲軸。 - - Mixed Zone - 混合區域 - - - - Multiple Sites - 多站台 - - - - Unknown Site - 不明站台 - - - - Unknown Zone - 不明區域 - - - - Microsoft .NET Security Warning - Microsoft .NET 安全性警告 - - - - Never enter personal information or passwords into a window unless you can verify and trust the source of the request. - 除非您可以驗證並信任要求的來源,否則絕對不要在視窗中輸入個人資訊或密碼。 - - - - Source: {0} - 來源: {0} - - - - {0} - -{1} - {0} - -{1} - - SelTabCount out of range. SelTabCount 超出範圍。 diff --git a/src/System.Windows.Forms/src/System.Windows.Forms.csproj b/src/System.Windows.Forms/src/System.Windows.Forms.csproj index 8c8b66436fd..67cc29030f3 100644 --- a/src/System.Windows.Forms/src/System.Windows.Forms.csproj +++ b/src/System.Windows.Forms/src/System.Windows.Forms.csproj @@ -8,7 +8,7 @@ true $(NoWarn);618 - $(DefineConstants);WIN95_SUPPORT;WINDOWS_FORMS_SWITCHES;WINFORMS_NAMESPACE;OPTIMIZED_MEASUREMENTDC; + $(DefineConstants);DRAWING_DESIGN_NAMESPACE;OPTIMIZED_MEASUREMENTDC; Resources\System\Windows\Forms\XPThemes.manifest true true @@ -42,6 +42,17 @@ + + + + + + + + + + + @@ -58,428 +69,395 @@ - - System.Windows.Forms.Animation.bmp + + System.Windows.Forms.Animation - - System.Windows.Forms.ActiveDocumentHost.bmp + + System.Windows.Forms.ActiveDocumentHost - - System.Windows.Forms.BindingNavigator.bmp + + System.Windows.Forms.BindingNavigator - - System.Windows.Forms.DataGridViewButtonColumn.bmp + + System.Windows.Forms.DataGridViewButtonColumn - - System.Windows.Forms.DataGridViewCheckBoxColumn.bmp + + System.Windows.Forms.DataGridViewCheckBoxColumn - - System.Windows.Forms.DataGridViewComboBoxColumn.bmp + + System.Windows.Forms.DataGridViewComboBoxColumn - - System.Windows.Forms.DataGridViewImageColumn.bmp + + System.Windows.Forms.DataGridViewImageColumn - - System.Windows.Forms.DataGridViewLinkColumn.bmp + + System.Windows.Forms.DataGridViewLinkColumn - - System.Windows.Forms.DataGridViewTextBoxColumn.bmp + + System.Windows.Forms.DataGridViewTextBoxColumn - - System.Windows.Forms.BindingNavigator.MoveFirst.bmp + + System.Windows.Forms.BindingNavigator.MoveFirst - - System.Windows.Forms.BindingNavigator.MoveLast.bmp + + System.Windows.Forms.BindingNavigator.MoveLast - - System.Windows.Forms.BindingNavigator.MovePrevious.bmp + + System.Windows.Forms.BindingNavigator.MovePrevious - - System.Windows.Forms.BindingNavigator.MoveNext.bmp + + System.Windows.Forms.BindingNavigator.MoveNext - - System.Windows.Forms.BindingNavigator.AddNew.bmp + + System.Windows.Forms.BindingNavigator.AddNew - - System.Windows.Forms.BindingNavigator.Delete.bmp + + System.Windows.Forms.BindingNavigator.Delete - - System.Windows.Forms.BindingSource.bmp + + System.Windows.Forms.BindingSource - - System.Windows.Forms.Button.bmp + + System.Windows.Forms.Button - - System.Windows.Forms.CheckBox.bmp - - - System.Windows.Forms.Checked.bmp + + System.Windows.Forms.CheckBox - System.Windows.Forms.Checked.ico + System.Windows.Forms.Checked - - System.Windows.Forms.CheckedListBox.bmp + + System.Windows.Forms.CheckedListBox - - System.Windows.Forms.ColorDialog.bmp + + System.Windows.Forms.ColorDialog - - System.Windows.Forms.ComboBox.bmp + + System.Windows.Forms.ComboBox - - System.Windows.Forms.ContextMenu.bmp + + System.Windows.Forms.ContextMenu - - System.Windows.Forms.DataGrid.bmp + + System.Windows.Forms.DataGrid - - System.Windows.Forms.DataGridCaption.down.bmp + + System.Windows.Forms.DataGridCaption.down - - System.Windows.Forms.DataGridCaption.backarrow.bmp + + System.Windows.Forms.DataGridCaption.backarrow - - System.Windows.Forms.DataGridCaption.backarrow_bidi.bmp + + System.Windows.Forms.DataGridCaption.backarrow_bidi - - System.Windows.Forms.DataGridCaption.Details.bmp + + System.Windows.Forms.DataGridCaption.Details - - System.Windows.Forms.DataGridCaption.right.bmp + + System.Windows.Forms.DataGridCaption.right - - System.Windows.Forms.DataGridCaption.up.bmp + + System.Windows.Forms.DataGridCaption.up - - System.Windows.Forms.DataGridRow.right.bmp + + System.Windows.Forms.DataGridRow.right - - System.Windows.Forms.DataGridRow.left.bmp + + System.Windows.Forms.DataGridRow.left - - System.Windows.Forms.DataGridRow.error.bmp + + System.Windows.Forms.DataGridRow.error - - System.Windows.Forms.DataGridRow.star.bmp + + System.Windows.Forms.DataGridRow.star - - System.Windows.Forms.DataGridRow.pencil.bmp + + System.Windows.Forms.DataGridRow.pencil - - System.Windows.Forms.DataGridParentRows.LeftArrow.bmp + + System.Windows.Forms.DataGridParentRows.LeftArrow - - System.Windows.Forms.DataGridParentRows.RightArrow.bmp + + System.Windows.Forms.DataGridParentRows.RightArrow - - System.Windows.Forms.DataConnector.bmp + + System.Windows.Forms.DataConnector - - System.Windows.Forms.DataNavigator.bmp + + System.Windows.Forms.DataNavigator - - System.Windows.Forms.DataNavigator.MoveFirst.bmp + + System.Windows.Forms.DataNavigator.MoveFirst - - System.Windows.Forms.DataNavigator.MoveLast.bmp + + System.Windows.Forms.DataNavigator.MoveLast - - System.Windows.Forms.DataNavigator.MovePrevious.bmp + + System.Windows.Forms.DataNavigator.MovePrevious - - System.Windows.Forms.DataNavigator.MoveNext.bmp + + System.Windows.Forms.DataNavigator.MoveNext - - System.Windows.Forms.DataNavigator.AddNew.bmp + + System.Windows.Forms.DataNavigator.AddNew - - System.Windows.Forms.DataNavigator.Delete.bmp + + System.Windows.Forms.DataNavigator.Delete - - System.Windows.Forms.DateTimePicker.bmp + + System.Windows.Forms.DateTimePicker - - System.Windows.Forms.DefaultControl.bmp + + System.Windows.Forms.DefaultControl - - System.Windows.Forms.DomainUpDown.bmp + + System.Windows.Forms.DomainUpDown - - System.Windows.Forms.Edit.bmp + + System.Windows.Forms.Edit - - System.Windows.Forms.TextBox.bmp + + System.Windows.Forms.TextBox - - System.Windows.Forms.MaskedTextBox.bmp + + System.Windows.Forms.MaskedTextBox - System.Windows.Forms.Error.ico - - - System.Windows.Forms.ErrorProvider.bmp + System.Windows.Forms.Error - - System.Windows.Forms.FlowLayoutPanel.bmp + + System.Windows.Forms.ErrorProvider - - System.Windows.Forms.FolderBrowserDialog.bmp + + System.Windows.Forms.FlowLayoutPanel - - System.Windows.Forms.Form.bmp + + System.Windows.Forms.FolderBrowserDialog - - System.Windows.Forms.FontDialog.bmp + + System.Windows.Forms.Form - - System.Windows.Forms.Grid.bmp + + System.Windows.Forms.FontDialog - - System.Windows.Forms.DataGridView.bmp + + System.Windows.Forms.Grid - - System.Windows.Forms.DataGridViewRow.error.bmp + + System.Windows.Forms.DataGridView - - System.Windows.Forms.DataGridViewRow.left.bmp + + System.Windows.Forms.DataGridViewRow.error - System.Windows.Forms.DataGridViewRow.left.ico - - - System.Windows.Forms.DataGridViewRow.leftstar.bmp + System.Windows.Forms.DataGridViewRow.left - System.Windows.Forms.DataGridViewRow.leftstar.ico - - - System.Windows.Forms.DataGridViewRow.pencil_ltr.bmp + System.Windows.Forms.DataGridViewRow.leftstar - System.Windows.Forms.DataGridViewRow.pencil_ltr.ico - - - System.Windows.Forms.DataGridViewRow.pencil_rtl.bmp + System.Windows.Forms.DataGridViewRow.pencil_ltr - System.Windows.Forms.DataGridViewRow.pencil_rtl.ico - - - System.Windows.Forms.DataGridViewRow.right.bmp + System.Windows.Forms.DataGridViewRow.pencil_rtl - System.Windows.Forms.DataGridViewRow.right.ico - - - System.Windows.Forms.DataGridViewRow.rightstar.bmp + System.Windows.Forms.DataGridViewRow.right - System.Windows.Forms.DataGridViewRow.rightstar.ico - - - System.Windows.Forms.DataGridViewRow.star.bmp + System.Windows.Forms.DataGridViewRow.rightstar - System.Windows.Forms.DataGridViewRow.star.ico - - - System.Windows.Forms.GroupBox.bmp + System.Windows.Forms.DataGridViewRow.star - - System.Windows.Forms.HelpProvider.bmp + + System.Windows.Forms.GroupBox - - System.Windows.Forms.HScrollBar.bmp + + System.Windows.Forms.HelpProvider - - System.Windows.Forms.HTMLControl.bmp + + System.Windows.Forms.HScrollBar - - System.Windows.Forms.IndeterminateChecked.bmp + + System.Windows.Forms.HTMLControl - System.Windows.Forms.IndeterminateChecked.ico + System.Windows.Forms.IndeterminateChecked - - System.Windows.Forms.ImageList.bmp + + System.Windows.Forms.ImageList - - System.Windows.Forms.Label.bmp + + System.Windows.Forms.Label - - System.Windows.Forms.LinkLabel.bmp + + System.Windows.Forms.LinkLabel - - System.Windows.Forms.ListBox.bmp + + System.Windows.Forms.ListBox - - System.Windows.Forms.ListView.bmp + + System.Windows.Forms.ListView - - System.Windows.Forms.MainMenu.bmp + + System.Windows.Forms.MainMenu - - System.Windows.Forms.MonthCalendar.bmp + + System.Windows.Forms.MonthCalendar - - System.Windows.Forms.MultiplexPanel.bmp + + System.Windows.Forms.MultiplexPanel - - System.Windows.Forms.NotifyIcon.bmp + + System.Windows.Forms.NotifyIcon - - System.Windows.Forms.NumericUpDown.bmp + + System.Windows.Forms.NumericUpDown - - System.Windows.Forms.OpenFileDialog.bmp + + System.Windows.Forms.OpenFileDialog - - System.Windows.Forms.Panel.bmp + + System.Windows.Forms.Panel - - System.Windows.Forms.PictureBox.bmp + + System.Windows.Forms.PictureBox - - System.Windows.Forms.PrintPreviewControl.bmp + + System.Windows.Forms.PrintPreviewControl - - System.Windows.Forms.WebBrowser.bmp + + System.Windows.Forms.WebBrowser - - System.Windows.Forms.PrintPreviewDialog.bmp + + System.Windows.Forms.PrintPreviewDialog - - System.Windows.Forms.PrintPreviewStrip.bmp + + System.Windows.Forms.PrintPreviewStrip - - System.Windows.Forms.ProgressBar.bmp + + System.Windows.Forms.ProgressBar - - System.Windows.Forms.RadioButton.bmp + + System.Windows.Forms.RadioButton - - System.Windows.Forms.Rebar.bmp + + System.Windows.Forms.Rebar - - System.Windows.Forms.RichEdit.bmp + + System.Windows.Forms.RichEdit - - System.Windows.Forms.RichTextBox.bmp + + System.Windows.Forms.RichTextBox - - System.Windows.Forms.SaveFileDialog.bmp + + System.Windows.Forms.SaveFileDialog - - System.Windows.Forms.Splitter.bmp + + System.Windows.Forms.Splitter - - System.Windows.Forms.SplitterPanel.bmp + + System.Windows.Forms.SplitterPanel - - System.Windows.Forms.SplitContainer.bmp + + System.Windows.Forms.SplitContainer - - System.Windows.Forms.ErrorControl.bmp + + System.Windows.Forms.ErrorControl - - System.Windows.Forms.StatusBar.bmp + + System.Windows.Forms.StatusBar - - System.Windows.Forms.TabControl.bmp + + System.Windows.Forms.TabControl - - System.Windows.Forms.TableLayoutPanel.bmp + + System.Windows.Forms.TableLayoutPanel - - System.Windows.Forms.TabStrip.bmp + + System.Windows.Forms.TabStrip - - System.Windows.Forms.TabPage.bmp + + System.Windows.Forms.TabPage - - System.Windows.Forms.ToolBar.bmp + + System.Windows.Forms.ToolBar - - System.Windows.Forms.ToolTip.bmp + + System.Windows.Forms.ToolTip - - System.Windows.Forms.TrackBar.bmp + + System.Windows.Forms.TrackBar - - System.Windows.Forms.TrayIcon.bmp + + System.Windows.Forms.TrayIcon - - System.Windows.Forms.TreeView.bmp + + System.Windows.Forms.TreeView - - System.Windows.Forms.UserControl.bmp + + System.Windows.Forms.UserControl - - System.Windows.Forms.VScrollBar.bmp + + System.Windows.Forms.VScrollBar - System.Windows.Forms.wfc.ico + System.Windows.Forms.wfc - - System.Windows.Forms.wfsecurity.ico + + System.Windows.Forms.Timer - - System.Windows.Forms.Timer.bmp + + System.Windows.Forms.ComponentModel.OrderImages - - System.Windows.Forms.ComponentModel.OrderImages.bmp + + System.Windows.Forms.PageSetupDialog - - System.Windows.Forms.PageSetupDialog.bmp - - - System.Windows.Forms.PrintDialog.bmp + + System.Windows.Forms.PrintDialog - System.Windows.Forms.Arrow.ico - - - System.Windows.Forms.dotdotdot.png + System.Windows.Forms.Arrow - System.Windows.Forms.dotdotdot.ico + System.Windows.Forms.dotdotdot - - System.Windows.Forms.Design.EventsTab.bmp + + System.Windows.Forms.Design.EventsTab - - System.Windows.Forms.PBAlpha.bmp + + System.Windows.Forms.PBAlpha - - System.Windows.Forms.PBCatego.bmp + + System.Windows.Forms.PBCatego - - System.Windows.Forms.PBEvent.bmp + + System.Windows.Forms.PBEvent - - System.Windows.Forms.PBPPage.bmp + + System.Windows.Forms.PBPPage - - System.Windows.Forms.PBProp.bmp + + System.Windows.Forms.PBProp - - System.Windows.Forms.PropertyGridInternal.PropertiesTab.bmp + + System.Windows.Forms.PropertyGridInternal.PropertiesTab - - System.Windows.Forms.PropertyGrid.bmp + + System.Windows.Forms.PropertyGrid - - System.Windows.Forms.Server.Arrow.bmp + + System.Windows.Forms.Server.Arrow - - System.Windows.Forms.PictureBox.Loading.bmp + + System.Windows.Forms.PictureBox.Loading - System.Windows.Forms.IconInError.ico + System.Windows.Forms.IconInError - - System.Windows.Forms.ImageInError.bmp + + System.Windows.Forms.ImageInError System.Windows.Forms.east.cur @@ -523,161 +501,158 @@ System.Windows.Forms.west.cur - - System.Windows.Forms.up.bmp + + System.Windows.Forms.up - - System.Windows.Forms.down.bmp + + System.Windows.Forms.down - System.Windows.Forms.Design.ComponentEditorPage.ico - - - System.Windows.Forms.ScrollButtonUp.bmp + System.Windows.Forms.Design.ComponentEditorPage - - System.Windows.Forms.ScrollButtonDown.bmp + + System.Windows.Forms.ScrollButtonUp - - System.Windows.Forms.overflowButton.bmp + + System.Windows.Forms.ScrollButtonDown - - System.Windows.Forms.ToolBarGrip.bmp + + System.Windows.Forms.overflowButton - - System.Windows.Forms.ToolStrip.bmp + + System.Windows.Forms.ToolBarGrip - - System.Windows.Forms.ToolStripContainer.bmp + + System.Windows.Forms.ToolStrip - - System.Windows.Forms.ToolStripPanel_standalone.bmp + + System.Windows.Forms.ToolStripContainer - - System.Windows.Forms.ToolStripContentPanel.bmp + + System.Windows.Forms.ToolStripPanel_standalone - - System.Windows.Forms.ToolStripContainer_TopToolStripPanel.bmp + + System.Windows.Forms.ToolStripContentPanel - - System.Windows.Forms.ToolStripContainer_BottomToolStripPanel.bmp + + System.Windows.Forms.ToolStripContainer_TopToolStripPanel - - System.Windows.Forms.ToolStripContainer_LeftToolStripPanel.bmp + + System.Windows.Forms.ToolStripContainer_BottomToolStripPanel - - System.Windows.Forms.ToolStripContainer_RightToolStripPanel.bmp + + System.Windows.Forms.ToolStripContainer_LeftToolStripPanel - - System.Windows.Forms.MenuStrip.bmp + + System.Windows.Forms.ToolStripContainer_RightToolStripPanel - - System.Windows.Forms.StatusStrip.bmp + + System.Windows.Forms.MenuStrip - - System.Windows.Forms.StatusStripPanel.bmp + + System.Windows.Forms.StatusStrip - - System.Windows.Forms.ToolStripStatusLabel.bmp + + System.Windows.Forms.StatusStripPanel - - System.Windows.Forms.ToolStripProgressBar.bmp + + System.Windows.Forms.ToolStripStatusLabel - - System.Windows.Forms.ContextMenuStrip.bmp + + System.Windows.Forms.ToolStripProgressBar - - System.Windows.Forms.ToolStripDropDownMenu.bmp + + System.Windows.Forms.ContextMenuStrip - - System.Windows.Forms.ToolStripDropDown.bmp + + System.Windows.Forms.ToolStripDropDown - - System.Windows.Forms.ToolStripButton.bmp + + System.Windows.Forms.ToolStripButton - - System.Windows.Forms.ToolStripLabel.bmp + + System.Windows.Forms.ToolStripLabel - - System.Windows.Forms.ToolStripTextBox.bmp + + System.Windows.Forms.ToolStripTextBox - - System.Windows.Forms.ToolStripComboBox.bmp + + System.Windows.Forms.ToolStripComboBox - - System.Windows.Forms.ToolStripMenuItem.bmp + + System.Windows.Forms.ToolStripMenuItem - - System.Windows.Forms.ToolStripDropDownButton.bmp + + System.Windows.Forms.ToolStripDropDownButton - - System.Windows.Forms.ToolStripSplitButton.bmp + + System.Windows.Forms.ToolStripSplitButton - - System.Windows.Forms.ToolStripSeparator.bmp + + System.Windows.Forms.ToolStripSeparator - - System.Windows.Forms.copy.bmp + + System.Windows.Forms.copy - - System.Windows.Forms.cut.bmp + + System.Windows.Forms.cut - - System.Windows.Forms.help.bmp + + System.Windows.Forms.help - - System.Windows.Forms.new.bmp + + System.Windows.Forms.new - - System.Windows.Forms.open.bmp + + System.Windows.Forms.open - - System.Windows.Forms.paste.bmp + + System.Windows.Forms.paste - - System.Windows.Forms.delete.bmp + + System.Windows.Forms.delete - - System.Windows.Forms.viewcode.bmp + + System.Windows.Forms.viewcode - - System.Windows.Forms.properties.bmp + + System.Windows.Forms.properties - - System.Windows.Forms.image.bmp + + System.Windows.Forms.image - - System.Windows.Forms.alignment.bmp + + System.Windows.Forms.alignment - - System.Windows.Forms.displaystyle.bmp + + System.Windows.Forms.displaystyle - - System.Windows.Forms.editdropdownlist.bmp + + System.Windows.Forms.editdropdownlist - - System.Windows.Forms.print.bmp + + System.Windows.Forms.print - - System.Windows.Forms.printPreview.bmp + + System.Windows.Forms.printPreview - - System.Windows.Forms.save.bmp + + System.Windows.Forms.save - - System.Windows.Forms.lockControls.bmp + + System.Windows.Forms.lockControls - - System.Windows.Forms.alignToGrid.bmp + + System.Windows.Forms.alignToGrid - - System.Windows.Forms.bringToFront.bmp + + System.Windows.Forms.bringToFront - - System.Windows.Forms.sendToBack.bmp + + System.Windows.Forms.sendToBack - - System.Windows.Forms.blank.bmp + + System.Windows.Forms.blank diff --git a/src/System.Windows.Forms/src/System/Resources/ResXDataNode.cs b/src/System.Windows.Forms/src/System/Resources/ResXDataNode.cs index 14870b3d11a..9079665d42a 100644 --- a/src/System.Windows.Forms/src/System/Resources/ResXDataNode.cs +++ b/src/System.Windows.Forms/src/System/Resources/ResXDataNode.cs @@ -825,13 +825,7 @@ public Assembly GetAssembly(AssemblyName name, bool throwOnError) { } if (result == null) { - // try to load it first from the gac -#pragma warning disable 0618 - //Although LoadWithPartialName is obsolete, we still have to call it: changing - //this would be breaking in cases where people edited their resource files by - //hand. - result = Assembly.LoadWithPartialName(name.FullName); -#pragma warning restore 0618 + result = Assembly.Load(name.FullName); if(result != null) { cachedAssemblies[name] = result; } @@ -882,13 +876,11 @@ public Type GetType(string name, bool throwOnError, bool ignoreCase) { return result; } - // Missed in cache, try to resolve the type. First try to resolve in the GAC + // Missed in cache, try to resolve the type from the reference assemblies. if(name.IndexOf(',') != -1) { result = Type.GetType(name, false, ignoreCase); } - // - // Did not find it in the GAC, check the reference assemblies if(result == null && names != null) { // // If the type is assembly qualified name, we sort the assembly names @@ -944,9 +936,9 @@ public Type GetType(string name, bool throwOnError, bool ignoreCase) { } if(result != null) { - // Only cache types from .Net framework or GAC because they don't need to update. + // Only cache types from .Net framework because they don't need to update. // For simplicity, don't cache custom types - if (result.Assembly.GlobalAssemblyCache || IsNetFrameworkAssembly(result.Assembly.Location)) { + if (IsNetFrameworkAssembly(result.Assembly.Location)) { cachedTypes[name] = result; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/AccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/AccessibleObject.cs index 9b7e51dae89..b3829cd4ee3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/AccessibleObject.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/AccessibleObject.cs @@ -528,7 +528,7 @@ internal virtual bool IsIAccessibleExSupported() internal virtual bool IsPatternSupported(int patternId) { // Override this, in your derived class, if you implement UIAutomation patterns - if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_InvokePatternId) + if (patternId == NativeMethods.UIA_InvokePatternId) { return IsInvokePatternAvailable; } @@ -550,7 +550,7 @@ internal virtual UnsafeNativeMethods.IRawElementProviderSimple HostRawElementPro internal virtual object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_IsInvokePatternAvailablePropertyId) + if (propertyID == NativeMethods.UIA_IsInvokePatternAvailablePropertyId) { return IsInvokePatternAvailable; } @@ -2094,9 +2094,6 @@ protected void UseStdAccessibleObjects(IntPtr handle, int objid) ref IID_IEnumVariant, ref en); - Debug.Assert(acc != null, "SystemIAccessible is null"); - Debug.Assert(en != null, "SystemIEnumVariant is null"); - if (acc != null || en != null) { systemIAccessible = (IAccessible)acc; @@ -2384,8 +2381,7 @@ UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.ISelectionItem /// public bool RaiseAutomationNotification(AutomationNotificationKind notificationKind, AutomationNotificationProcessing notificationProcessing, string notificationText) { - - if (!AccessibilityImprovements.Level3 || !notificationEventAvailable) + if (!notificationEventAvailable) { return false; } @@ -2706,7 +2702,7 @@ internal sealed class InternalAccessibleObject : StandardOleMarshalObject, private UnsafeNativeMethods.IRawElementProviderHwndOverride publicIRawElementProviderHwndOverride; // AccessibleObject as IRawElementProviderHwndOverride /// - /// Create a new wrapper. Protect this with UnmanagedCode Permission + /// Create a new wrapper. /// internal InternalAccessibleObject(AccessibleObject accessibleImplemention) { @@ -3019,7 +3015,7 @@ object UnsafeNativeMethods.IRawElementProviderSimple.GetPatternProvider(int patt { return (UnsafeNativeMethods.IValueProvider)this; } - else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_RangeValuePatternId) + else if (patternId == NativeMethods.UIA_RangeValuePatternId) { return (UnsafeNativeMethods.IRangeValueProvider)this; } @@ -3043,19 +3039,19 @@ object UnsafeNativeMethods.IRawElementProviderSimple.GetPatternProvider(int patt { return (UnsafeNativeMethods.IGridItemProvider)this; } - else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_InvokePatternId) + else if (patternId == NativeMethods.UIA_InvokePatternId) { return (UnsafeNativeMethods.IInvokeProvider)this; } - else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_LegacyIAccessiblePatternId) + else if (patternId == NativeMethods.UIA_LegacyIAccessiblePatternId) { return (UnsafeNativeMethods.ILegacyIAccessibleProvider)this; } - else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_SelectionPatternId) + else if (patternId == NativeMethods.UIA_SelectionPatternId) { return (UnsafeNativeMethods.ISelectionProvider)this; } - else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_SelectionItemPatternId) + else if (patternId == NativeMethods.UIA_SelectionItemPatternId) { return (UnsafeNativeMethods.ISelectionItemProvider)this; } @@ -3102,15 +3098,7 @@ NativeMethods.UiaRect UnsafeNativeMethods.IRawElementProviderFragment.BoundingRe UnsafeNativeMethods.IRawElementProviderFragmentRoot UnsafeNativeMethods.IRawElementProviderFragment.FragmentRoot { - get - { - if (AccessibilityImprovements.Level3) - { - return publicIRawElementProviderFragment.FragmentRoot; - } - - return AsNativeAccessible(publicIRawElementProviderFragment.FragmentRoot) as UnsafeNativeMethods.IRawElementProviderFragmentRoot; - } + get => publicIRawElementProviderFragment.FragmentRoot; } object UnsafeNativeMethods.IRawElementProviderFragmentRoot.ElementProviderFromPoint(double x, double y) @@ -3293,16 +3281,7 @@ object UnsafeNativeMethods.IGridProvider.GetItem(int row, int column) UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IGridItemProvider.ContainingGrid { - get - { - // Do not wrap returned UIA provider by InternalAccessibleObject in Level 3. - if (AccessibilityImprovements.Level3) - { - return publicIGridItemProvider.ContainingGrid; - } - - return AsNativeAccessible(publicIGridItemProvider.ContainingGrid) as UnsafeNativeMethods.IRawElementProviderSimple; - } + get => publicIGridItemProvider.ContainingGrid; } /// diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs index a1853e2df21..e1c9ea03571 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -709,27 +709,22 @@ public static RegistryKey UserAppDataRegistry { } } -#if (WINFORMS_NAMESPACE || WINFORMS_DESIGN_NAMESPACE) +#if (DRAWING_DESIGN_NAMESPACE) public static bool UseVisualStyles { get { return useVisualStyles; } } #endif - internal static string WindowsFormsVersion { - get { - // Notice : Don't never ever change this name, since window class of Winforms control is dependent on this. - // And lots of partner team are related to window class of Winforms control. Changing this will introduce breaking. - // If there is some reason need to change this, should take the accountability to notify partner team. - return "WindowsForms10"; - } - } - internal static string WindowMessagesVersion { - get { - return "WindowsForms12"; - } - } + /// + /// Don't never ever change this name, since the window class and partner teams + /// dependent on this. Changing this will introduce breaking changes. + /// If there is some reason need to change this, notify any partner teams affected. + /// + internal static string WindowsFormsVersion => "WindowsForms10"; + + internal static string WindowMessagesVersion => "WindowsForms12"; /// /// @@ -802,7 +797,7 @@ private static bool SendThemeChangedRecursive(IntPtr handle, IntPtr lparam) { NativeMethods.NullHandleRef); //then do myself. - UnsafeNativeMethods.SendMessage(new HandleRef(null, handle), NativeMethods.WM_THEMECHANGED, 0, 0); + UnsafeNativeMethods.SendMessage(new HandleRef(null, handle), Interop.WindowMessages.WM_THEMECHANGED, 0, 0); return true; } @@ -2033,7 +2028,7 @@ int pvLoopData // PVOID UnsafeNativeMethods.GetMessageA(ref msg, NativeMethods.NullHandleRef, 0, 0); } - if (msg.message == NativeMethods.WM_QUIT) { + if (msg.message == Interop.WindowMessages.WM_QUIT) { Debug.WriteLineIf(CompModSwitches.MSOComponentManager.TraceInfo, "ComponentManager : Normal message loop termination"); Application.ThreadContext.FromCurrent().DisposeThreadWindows(); @@ -2453,7 +2448,7 @@ internal UnsafeNativeMethods.IMsoComponentManager ComponentManager { // Debug.WriteLineIf(CompModSwitches.MSOComponentManager.TraceInfo, "Registering MSO component with the component manager"); NativeMethods.MSOCRINFOSTRUCT info = new NativeMethods.MSOCRINFOSTRUCT(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MSOCRINFOSTRUCT)); + info.cbSize = Marshal.SizeOf(); info.uIdleTimeInterval = 0; info.grfcrf = NativeMethods.MSOCM.msocrfPreTranslateAll | NativeMethods.MSOCM.msocrfNeedIdleTime; info.grfcadvf = NativeMethods.MSOCM.msocadvfModal; @@ -2501,8 +2496,6 @@ internal ParkingWindow GetParkingWindow(DpiAwarenessContext context) { var parkingWindow = GetParkingWindowForContext(context); if (parkingWindow == null) { #if DEBUG - // if we use Debug.WriteLine instead of "if", we need extra security permissions - // to get the stack trace! if (CoreSwitches.PerfTrack.Enabled) { Debug.WriteLine("Creating parking form!"); Debug.WriteLine(CoreSwitches.PerfTrack.Enabled, Environment.StackTrace); @@ -2578,8 +2571,6 @@ internal Control MarshalingControl { lock (this) { if (marshalingControl == null) { #if DEBUG - // if we use Debug.WriteLine instead of "if", we need extra security permissions - // to get the stack trace! if (CoreSwitches.PerfTrack.Enabled) { Debug.WriteLine("Creating marshalling control!"); Debug.WriteLine(CoreSwitches.PerfTrack.Enabled, Environment.StackTrace); @@ -3180,7 +3171,7 @@ internal void PostQuit() { // We can't follow the KB article exactly, becasue we don't have an HWND to PostMessage // to. // - UnsafeNativeMethods.PostThreadMessage(id, NativeMethods.WM_QUIT, IntPtr.Zero, IntPtr.Zero); + UnsafeNativeMethods.PostThreadMessage(id, Interop.WindowMessages.WM_QUIT, IntPtr.Zero, IntPtr.Zero); SetState(STATE_POSTEDQUIT, true); } @@ -3262,8 +3253,6 @@ private void RunMessageLoopInner(int reason, ApplicationContext context) { } DpiHelper.InitializeDpiHelperForWinforms(); - - AccessibilityImprovements.ValidateLevels(); } Form oldForm = currentForm; @@ -3511,9 +3500,9 @@ internal bool PreTranslateMessage(ref NativeMethods.MSG msg) { return true; } - if (msg.message >= NativeMethods.WM_KEYFIRST - && msg.message <= NativeMethods.WM_KEYLAST) { - if (msg.message == NativeMethods.WM_CHAR) { + if (msg.message >= Interop.WindowMessages.WM_KEYFIRST + && msg.message <= Interop.WindowMessages.WM_KEYLAST) { + if (msg.message == Interop.WindowMessages.WM_CHAR) { int breakLParamMask = 0x1460000; // 1 = extended keyboard, 46 = scan code if (unchecked( (int) (long)msg.wParam) == 3 && ( unchecked( (int) (long)msg.lParam) & breakLParamMask) == breakLParamMask) { // ctrl-brk // wParam is the key character, which for ctrl-brk is the same as ctrl-C. @@ -3954,7 +3943,7 @@ internal sealed class ParkingWindow : ContainerControl, IArrangedElement { // in whidbey we now aggressively tear down the parking window // when the last control has been removed off of it. - private const int WM_CHECKDESTROY = NativeMethods.WM_USER + 0x01; + private const int WM_CHECKDESTROY = Interop.WindowMessages.WM_USER + 0x01; private int childCount = 0; @@ -4064,10 +4053,10 @@ protected override void OnLayout(LayoutEventArgs levent) {} void IArrangedElement.PerformLayout(IArrangedElement affectedElement, string affectedProperty) {} protected override void WndProc(ref Message m) { - if (m.Msg != NativeMethods.WM_SHOWWINDOW) { + if (m.Msg != Interop.WindowMessages.WM_SHOWWINDOW) { base.WndProc(ref m); - if (m.Msg == NativeMethods.WM_PARENTNOTIFY) { - if (NativeMethods.Util.LOWORD(unchecked( (int) (long)m.WParam)) == NativeMethods.WM_DESTROY) { + if (m.Msg == Interop.WindowMessages.WM_PARENTNOTIFY) { + if (NativeMethods.Util.LOWORD(unchecked( (int) (long)m.WParam)) == Interop.WindowMessages.WM_DESTROY) { UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), WM_CHECKDESTROY, IntPtr.Zero, IntPtr.Zero); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/AutoCompleteStringCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/AutoCompleteStringCollection.cs index 20235c076d5..476a07e7610 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/AutoCompleteStringCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/AutoCompleteStringCollection.cs @@ -7,7 +7,6 @@ namespace System.Windows.Forms { using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Collections; - using System.Security.Permissions; using System.ComponentModel; /// @@ -210,7 +209,6 @@ public void RemoveAt(int index) { /// Gets an object that can be used to synchronize access to the . /// public object SyncRoot { - [HostProtection(Synchronization=true)] [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] get { return this; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs b/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs index cccfccadd40..32ae6e57e6a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs @@ -1976,7 +1976,7 @@ protected internal override bool ProcessMnemonic(char charCode) { // A bit of ugliness here (a bit? more like a bucket...) // The message we are faking is a WM_SYSKEYDOWN w/ the right alt key setting... msg.hwnd = (ContainingControl == null) ? IntPtr.Zero : ContainingControl.Handle; - msg.message = NativeMethods.WM_SYSKEYDOWN; + msg.message = Interop.WindowMessages.WM_SYSKEYDOWN; msg.wParam = (IntPtr)char.ToUpper(charCode, CultureInfo.CurrentCulture); msg.lParam = (IntPtr) 0x20180001; msg.time = SafeNativeMethods.GetTickCount(); @@ -3232,38 +3232,38 @@ protected override void WndProc(ref Message m) { switch (m.Msg) { // Things we explicitly ignore and pass to the ocx's windproc - case NativeMethods.WM_ERASEBKGND: + case Interop.WindowMessages.WM_ERASEBKGND: - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFYFORMAT: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFYFORMAT: - case NativeMethods.WM_SETCURSOR: - case NativeMethods.WM_SYSCOLORCHANGE: + case Interop.WindowMessages.WM_SETCURSOR: + case Interop.WindowMessages.WM_SYSCOLORCHANGE: // Some of the MSComCtl controls respond to this message // to do some custom painting. So, we should just pass this message // through. // - case NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_DRAWITEM: - case NativeMethods.WM_LBUTTONDBLCLK: - case NativeMethods.WM_LBUTTONUP: - case NativeMethods.WM_MBUTTONDBLCLK: - case NativeMethods.WM_MBUTTONUP: - case NativeMethods.WM_RBUTTONDBLCLK: - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONUP: DefWndProc(ref m); break; - case NativeMethods.WM_LBUTTONDOWN: - case NativeMethods.WM_MBUTTONDOWN: - case NativeMethods.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: if (IsUserMode()) { Focus(); } DefWndProc(ref m); break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: { hwndFocus = m.WParam; try { @@ -3275,16 +3275,16 @@ protected override void WndProc(ref Message m) { break; } - case NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_COMMAND: if (!ReflectMessageInternal(m.LParam, ref m)) DefWndProc(ref m); break; - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_CONTEXTMENU: DefWndProc(ref m); break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: #if DEBUG if (!OwnWindow()) { Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "WM_DESTROY naughty control is destroying the window from under us..." + GetType().ToString()); @@ -3315,13 +3315,13 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_HELP: + case Interop.WindowMessages.WM_HELP: // We want to both fire the event, and let the ocx have the message... base.WndProc(ref m); DefWndProc(ref m); break; - case NativeMethods.WM_KEYUP: + case Interop.WindowMessages.WM_KEYUP: if (axState[processingKeyUp]) break; @@ -3336,7 +3336,7 @@ protected override void WndProc(ref Message m) { break; - case NativeMethods.WM_NCDESTROY: + case Interop.WindowMessages.WM_NCDESTROY: #if DEBUG if (!OwnWindow()) { Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "WM_NCDESTROY naughty control is destroying the window from under us..." + GetType().ToString()); @@ -4044,7 +4044,7 @@ int UnsafeNativeMethods.IOleInPlaceSite.GetWindowContext(out UnsafeNativeMethods FillInRect(lprcPosRect, host.Bounds); host.GetClipRect(lprcClipRect); if (lpFrameInfo != null) { - lpFrameInfo.cb = Marshal.SizeOf(typeof(NativeMethods.tagOIFI)); + lpFrameInfo.cb = Marshal.SizeOf(); lpFrameInfo.fMDIApp = false; lpFrameInfo.hAccel = IntPtr.Zero; lpFrameInfo.cAccelEntries = 0; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/BindToObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/BindToObject.cs index 248afc16588..ba6a923e059 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/BindToObject.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/BindToObject.cs @@ -2,119 +2,119 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - - using System; - using Microsoft.Win32; - using System.Diagnostics; - using System.ComponentModel; - using System.ComponentModel.Design; - using System.Collections; - - internal class BindToObject { - private PropertyDescriptor fieldInfo; - private BindingMemberInfo dataMember; - private object dataSource; - private BindingManagerBase bindingManager; - private Binding owner; - private string errorText = string.Empty; - - private bool dataSourceInitialized = false; - private bool waitingOnDataSource = false; - - private void PropValueChanged(object sender, EventArgs e) { - if(this.bindingManager != null) { - this.bindingManager.OnCurrentChanged(EventArgs.Empty); - } +using System.ComponentModel; +using System.Diagnostics; + +namespace System.Windows.Forms +{ + internal class BindToObject + { + private PropertyDescriptor _fieldInfo; + private BindingMemberInfo _dataMember; + private object _dataSource; + private BindingManagerBase _bindingManager; + private Binding _owner; + private string _errorText = string.Empty; + + private bool _dataSourceInitialized = false; + private bool _waitingOnDataSource = false; + + private void PropValueChanged(object sender, EventArgs e) + { + _bindingManager?.OnCurrentChanged(EventArgs.Empty); } - private bool IsDataSourceInitialized { - get { - Debug.Assert(this.dataSource != null, "how can we determine if DataSource is initialized or not if we have no data source?"); - - if (this.dataSourceInitialized) { + private bool IsDataSourceInitialized + { + get + { + Debug.Assert(_dataSource != null, "how can we determine if DataSource is initialized or not if we have no data source?"); + if (_dataSourceInitialized) + { return true; } - ISupportInitializeNotification ds = this.dataSource as ISupportInitializeNotification; - if (ds == null || ds.IsInitialized) { - this.dataSourceInitialized = true; + if (!(_dataSource is ISupportInitializeNotification ds) || ds.IsInitialized) + { + _dataSourceInitialized = true; return true; } // We have an ISupportInitializeNotification which was not initialized yet. - // We already hooked up the Initialized event and the data source is not initialized yet. - if (this.waitingOnDataSource) { + if (_waitingOnDataSource) + { return false; } // Hook up the Initialized event. ds.Initialized += new EventHandler(DataSource_Initialized); - this.waitingOnDataSource = true; + _waitingOnDataSource = true; return false; } } - internal BindToObject(Binding owner, object dataSource, string dataMember) { - this.owner = owner; - this.dataSource = dataSource; - this.dataMember = new BindingMemberInfo(dataMember); + internal BindToObject(Binding owner, object dataSource, string dataMember) + { + this._owner = owner; + this._dataSource = dataSource; + this._dataMember = new BindingMemberInfo(dataMember); CheckBinding(); } - private void DataSource_Initialized(object sender, EventArgs e) { - Debug.Assert(sender == this.dataSource, "data source should not change"); - Debug.Assert(this.dataSource is ISupportInitializeNotification, "data source should not change on the BindToObject"); - Debug.Assert(this.waitingOnDataSource); + private void DataSource_Initialized(object sender, EventArgs e) + { + Debug.Assert(sender == _dataSource, "data source should not change"); + Debug.Assert(_dataSource is ISupportInitializeNotification, "data source should not change on the BindToObject"); + Debug.Assert(_waitingOnDataSource); - ISupportInitializeNotification ds = this.dataSource as ISupportInitializeNotification; // Unhook the Initialized event. - if (ds != null) { + if (_dataSource is ISupportInitializeNotification ds) + { ds.Initialized -= new EventHandler(DataSource_Initialized); } // The wait is over: DataSource is initialized. - this.waitingOnDataSource = false; - this.dataSourceInitialized = true; + _waitingOnDataSource = false; + _dataSourceInitialized = true; // Rebind. CheckBinding(); } - internal void SetBindingManagerBase(BindingManagerBase lManager) { - if (bindingManager == lManager) + internal void SetBindingManagerBase(BindingManagerBase lManager) + { + if (_bindingManager == lManager) { return; } // remove notification from the backEnd - if (bindingManager != null && fieldInfo != null && bindingManager.IsBinding && !(bindingManager is CurrencyManager)) { - fieldInfo.RemoveValueChanged(bindingManager.Current, new EventHandler(PropValueChanged)); - fieldInfo = null; + if (_bindingManager != null && _fieldInfo != null && _bindingManager.IsBinding && !(_bindingManager is CurrencyManager)) + { + _fieldInfo.RemoveValueChanged(_bindingManager.Current, new EventHandler(PropValueChanged)); + _fieldInfo = null; } - this.bindingManager = lManager; + _bindingManager = lManager; CheckBinding(); } - internal string DataErrorText - { - get - { - return this.errorText; - } - } - - // Returns any data error info on the data source for the bound data field in the current row - string GetErrorText(object value) { + internal string DataErrorText => _errorText; - IDataErrorInfo errorInfo = value as IDataErrorInfo; + /// + /// Returns any data error info on the data source for the bound data field + /// in the current row + /// + private string GetErrorText(object value) + { string text = string.Empty; - if (errorInfo != null) { + if (value is IDataErrorInfo errorInfo) + { // Get the row error if there is no DataMember - if (fieldInfo == null) { + if (_fieldInfo == null) + { text = errorInfo.Error; } // Get the column error if there is a DataMember. @@ -122,59 +122,70 @@ string GetErrorText(object value) { // So passing the DataMember from the BindingField could cause problems. // Pass the name from the PropertyDescriptor that the DataTable gave us. // (If there is no fieldInfo, data binding would have failed already ) - else { - text = errorInfo[fieldInfo.Name]; + else + { + text = errorInfo[_fieldInfo.Name]; } } return text ?? string.Empty; } - internal object GetValue() { - object obj = bindingManager.Current; + internal object GetValue() + { + object obj = _bindingManager.Current; // Update IDataErrorInfo text: it's ok to get this now because we're going to need // this as part of the BindingCompleteEventArgs anyway. - this.errorText = GetErrorText(obj); + _errorText = GetErrorText(obj); - if (fieldInfo != null) { - obj = fieldInfo.GetValue(obj); + if (_fieldInfo != null) + { + obj = _fieldInfo.GetValue(obj); } return obj; } - internal Type BindToType { - get { - if (dataMember.BindingField.Length == 0) { + internal Type BindToType + { + get + { + if (_dataMember.BindingField.Length == 0) + { // if we are bound to a list w/o any properties, then // take the type from the BindingManager - Type type = this.bindingManager.BindType; + Type type = _bindingManager.BindType; if (typeof(Array).IsAssignableFrom(type)) + { type = type.GetElementType(); + } return type; } - else - return fieldInfo == null ? null : fieldInfo.PropertyType; + + return _fieldInfo?.PropertyType; } } - internal void SetValue(object value) { + internal void SetValue(object value) + { object obj = null; - if (fieldInfo != null) { - obj = bindingManager.Current; - if (obj is IEditableObject) - ((IEditableObject) obj).BeginEdit(); - //( - if (!fieldInfo.IsReadOnly) { - fieldInfo.SetValue(obj, value); + if (_fieldInfo != null) + { + obj = _bindingManager.Current; + if (obj is IEditableObject editableObject) + { + editableObject.BeginEdit(); + } + if (!_fieldInfo.IsReadOnly) + { + _fieldInfo.SetValue(obj, value); } - } - else { - CurrencyManager cm = bindingManager as CurrencyManager; - if (cm != null) + else + { + if (_bindingManager is CurrencyManager cm) { cm[cm.Position] = value; obj = value; @@ -182,86 +193,66 @@ internal void SetValue(object value) { } // Update IDataErrorInfo text. - this.errorText = GetErrorText(obj); + _errorText = GetErrorText(obj); } - internal BindingMemberInfo BindingMemberInfo { - get { - return this.dataMember; - } - } - - internal object DataSource { - get { - return dataSource; - } - } + internal BindingMemberInfo BindingMemberInfo => _dataMember; - internal PropertyDescriptor FieldInfo { - get { - return fieldInfo; - } - } + internal object DataSource => _dataSource; - internal BindingManagerBase BindingManagerBase { - get { - return this.bindingManager; - } - } + internal PropertyDescriptor FieldInfo => _fieldInfo; - internal void CheckBinding() { + internal BindingManagerBase BindingManagerBase => _bindingManager; + internal void CheckBinding() + { // At design time, don't check anything. - // - if (owner != null && - owner.BindableComponent != null && - owner.ControlAtDesignTime()) { - + if (_owner != null && _owner.BindableComponent != null && _owner.ControlAtDesignTime()) + { return; } - // force Column to throw if it's currently a bad column. - //DataColumn tempColumn = this.Column; - - // remove propertyChangedNotification when this binding is deleted - if (this.owner.BindingManagerBase != null && - this.fieldInfo != null && - this.owner.BindingManagerBase.IsBinding && - !(this.owner.BindingManagerBase is CurrencyManager)) { + // Remove propertyChangedNotification when this binding is deleted + if (_owner.BindingManagerBase != null && + _fieldInfo != null && + _owner.BindingManagerBase.IsBinding && + !(_owner.BindingManagerBase is CurrencyManager)) + { - fieldInfo.RemoveValueChanged(owner.BindingManagerBase.Current, new EventHandler(PropValueChanged)); + _fieldInfo.RemoveValueChanged(_owner.BindingManagerBase.Current, new EventHandler(PropValueChanged)); } - if (owner != null && - owner.BindingManagerBase != null && - owner.BindableComponent != null && - owner.ComponentCreated && - this.IsDataSourceInitialized) { + if (_owner != null && + _owner.BindingManagerBase != null && + _owner.BindableComponent != null && + _owner.ComponentCreated && + IsDataSourceInitialized) + { - string dataField = dataMember.BindingField; + string dataField = _dataMember.BindingField; - fieldInfo = owner.BindingManagerBase.GetItemProperties().Find(dataField, true); - if (owner.BindingManagerBase.DataSource != null && fieldInfo == null && dataField.Length > 0) { + _fieldInfo = _owner.BindingManagerBase.GetItemProperties().Find(dataField, true); + if (_owner.BindingManagerBase.DataSource != null && _fieldInfo == null && dataField.Length > 0) + { throw new ArgumentException(string.Format(SR.ListBindingBindField, dataField), "dataMember"); } - // Do not add propertyChange notification if - // the fieldInfo is null + // Do not add propertyChange notification if the fieldInfo is null // - // we add an event handler to the dataSource in the BindingManagerBase because + // We add an event handler to the dataSource in the BindingManagerBase because // if the binding is of the form (Control, ControlProperty, DataSource, Property1.Property2.Property3) // then we want to get notification from Current.Property1.Property2 and not from DataSource // when we get the backEnd notification we push the new value into the Control's property - // - if (fieldInfo != null && - owner.BindingManagerBase.IsBinding && - !(this.owner.BindingManagerBase is CurrencyManager)) { + if (_fieldInfo != null && _owner.BindingManagerBase.IsBinding && + !(_owner.BindingManagerBase is CurrencyManager)) + { - fieldInfo.AddValueChanged(this.owner.BindingManagerBase.Current, new EventHandler(PropValueChanged)); + _fieldInfo.AddValueChanged(_owner.BindingManagerBase.Current, new EventHandler(PropValueChanged)); } } - else { - fieldInfo = null; + else + { + _fieldInfo = null; } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Binding.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Binding.cs index 0682db65add..a2452737c5e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Binding.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Binding.cs @@ -2,409 +2,340 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - - using System; - using Microsoft.Win32; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.ComponentModel; - using System.ComponentModel.Design; - using System.Collections; - using System.Globalization; - - /// - /// - /// - /// Represents a simple binding of a value in a list - /// and the property of a control. - /// - /// +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace System.Windows.Forms +{ + /// + /// Represents a simple binding of a value in a list and the property of a control. + /// [TypeConverterAttribute(typeof(ListBindingConverter))] - public class Binding { - + public class Binding + { // the two collection owners that this binding belongs to. - private IBindableComponent control; - private BindingManagerBase bindingManagerBase; - - private BindToObject bindToObject = null; - - private string propertyName = ""; + private IBindableComponent _control; + private BindingManagerBase _bindingManagerBase; + + private BindToObject _bindToObject = null; + + private string _propertyName = string.Empty; - private PropertyDescriptor propInfo; - private PropertyDescriptor propIsNullInfo; - private EventDescriptor validateInfo; - private TypeConverter propInfoConverter; + private PropertyDescriptor _propInfo; + private PropertyDescriptor _propIsNullInfo; + private EventDescriptor _validateInfo; + private TypeConverter _propInfoConverter; - private bool formattingEnabled = false; + private bool _formattingEnabled = false; - private bool bound = false; - private bool modified = false; + private bool _bound = false; + private bool _modified = false; - //Recursion guards - private bool inSetPropValue = false; - private bool inPushOrPull = false; - private bool inOnBindingComplete = false; + // Recursion guards + private bool _inSetPropValue = false; + private bool _inPushOrPull = false; + private bool _inOnBindingComplete = false; // formatting stuff - private string formatString = string.Empty; - private IFormatProvider formatInfo = null; - private object nullValue = null; - private object dsNullValue = Formatter.GetDefaultDataSourceNullValue(null); - private bool dsNullValueSet; - private ConvertEventHandler onParse = null; - private ConvertEventHandler onFormat = null; + private string _formatString = string.Empty; + private IFormatProvider _formatInfo = null; + private object _nullValue = null; + private object _dsNullValue = Formatter.GetDefaultDataSourceNullValue(null); + private bool _dsNullValueSet; + private ConvertEventHandler _onParse = null; + private ConvertEventHandler _onFormat = null; // binding stuff - private ControlUpdateMode controlUpdateMode = ControlUpdateMode.OnPropertyChanged; - private DataSourceUpdateMode dataSourceUpdateMode = DataSourceUpdateMode.OnValidation; - private BindingCompleteEventHandler onComplete = null; - - /// - /// - /// Initializes a new instance of the class - /// that binds a property on the owning control to a property on a data source. - /// - public Binding(string propertyName, object dataSource, string dataMember) : this(propertyName, dataSource, dataMember, false, 0, null, string.Empty, null) { + private ControlUpdateMode _controlUpdateMode = ControlUpdateMode.OnPropertyChanged; + private BindingCompleteEventHandler _onComplete = null; + + /// + /// Initializes a new instance of the class + /// that binds a property on the owning control to a property on a data source. + /// + public Binding(string propertyName, object dataSource, string dataMember) : this(propertyName, dataSource, dataMember, false, 0, null, string.Empty, null) + { } - /// - public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled) : this(propertyName, dataSource, dataMember, formattingEnabled, 0, null, string.Empty, null) { + public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled) : this(propertyName, dataSource, dataMember, formattingEnabled, 0, null, string.Empty, null) + { } - /// - public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode) : this(propertyName, dataSource, dataMember, formattingEnabled, dataSourceUpdateMode, null, string.Empty, null) { + public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode) : this(propertyName, dataSource, dataMember, formattingEnabled, dataSourceUpdateMode, null, string.Empty, null) + { } - /// - public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode, object nullValue) : this(propertyName, dataSource, dataMember, formattingEnabled, dataSourceUpdateMode, nullValue, string.Empty, null) { + public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode, object nullValue) : this(propertyName, dataSource, dataMember, formattingEnabled, dataSourceUpdateMode, nullValue, string.Empty, null) + { } - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")] // 'formatString' is an appropriate name, since its a string passed to the Format method - public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode, object nullValue, string formatString) : this(propertyName, dataSource, dataMember, formattingEnabled, dataSourceUpdateMode, nullValue, formatString, null) { + [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", Justification = "'formatString' is an appropriate name, since its a string passed to the Format method")] + public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode, object nullValue, string formatString) : this(propertyName, dataSource, dataMember, formattingEnabled, dataSourceUpdateMode, nullValue, formatString, null) + { } - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] // By design (no-one should be subclassing this class) - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")] // 'formatString' is an appropriate name, since its a string passed to the Format method - public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode, object nullValue, string formatString, IFormatProvider formatInfo) { - this.bindToObject = new BindToObject(this, dataSource, dataMember); + [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "By design (no-one should be subclassing this class)")] + [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", Justification = "'formatString' is an appropriate name, since its a string passed to the Format method")] + public Binding(string propertyName, object dataSource, string dataMember, bool formattingEnabled, DataSourceUpdateMode dataSourceUpdateMode, object nullValue, string formatString, IFormatProvider formatInfo) + { + _bindToObject = new BindToObject(this, dataSource, dataMember); - this.propertyName = propertyName; - this.formattingEnabled = formattingEnabled; - this.formatString = formatString; - this.nullValue = nullValue; - this.formatInfo = formatInfo; - this.formattingEnabled = formattingEnabled; - this.dataSourceUpdateMode = dataSourceUpdateMode; + _propertyName = propertyName; + _formattingEnabled = formattingEnabled; + _formatString = formatString; + _nullValue = nullValue; + _formatInfo = formatInfo; + _formattingEnabled = formattingEnabled; + DataSourceUpdateMode = dataSourceUpdateMode; CheckBinding(); } - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - private Binding() { + /// + /// Initializes a new instance of the class. + /// + private Binding() + { } - internal BindToObject BindToObject { - get { - return this.bindToObject; - } - } + internal BindToObject BindToObject => _bindToObject; - /// - public object DataSource { - get { - return this.bindToObject.DataSource; - } - } + public object DataSource => _bindToObject.DataSource; - /// - public BindingMemberInfo BindingMemberInfo { - get { - return this.bindToObject.BindingMemberInfo; - } - } + public BindingMemberInfo BindingMemberInfo => _bindToObject.BindingMemberInfo; - /// - /// - /// - /// Gets the control to which the binding belongs. - /// - /// - [ - DefaultValue(null) - ] - public IBindableComponent BindableComponent { - get { - return this.control; - } - } - - /// - /// - /// - /// Gets the control to which the binding belongs. - /// - /// - [ - DefaultValue(null) - ] - public Control Control { - get { - return this.control as Control; - } - } - - // Is the binadable component in a 'created' (ready-to-use) state? For controls, - // this depends on whether the window handle has been created yet. For everything - // else, we'll assume they are always in a created state. - internal static bool IsComponentCreated(IBindableComponent component) { - Control ctrl = (component as Control); + /// + /// Gets the control to which the binding belongs. + /// + [DefaultValue(null)] + public IBindableComponent BindableComponent => _control; - if (ctrl != null) { - return ctrl.Created; - } - else { - return true; - } + /// + /// Gets the control to which the binding belongs. + /// + [DefaultValue(null)] + public Control Control => _control as Control; + + /// + /// Is the binadable component in a 'created' (ready-to-use) state? For controls, + /// this depends on whether the window handle has been created yet. For everything + /// else, we'll assume they are always in a created state. + /// + internal static bool IsComponentCreated(IBindableComponent component) + { + return !(component is Control control) || control.Created; } - // Instance-specific property equivalent to the static method above - internal bool ComponentCreated { - get { - return IsComponentCreated(this.control); - } - } + // + /// Instance-specific property equivalent to the static method above + // + internal bool ComponentCreated => IsComponentCreated(_control); - private void FormLoaded(object sender, EventArgs e) { - Debug.Assert(sender == control, "which other control can send us the Load event?"); + private void FormLoaded(object sender, EventArgs e) + { + Debug.Assert(sender == _control, "which other control can send us the Load event?"); // update the binding CheckBinding(); } - internal void SetBindableComponent(IBindableComponent value) { - if (this.control != value) { - IBindableComponent oldTarget = control; + internal void SetBindableComponent(IBindableComponent value) + { + if (_control != value) + { + IBindableComponent oldTarget = _control; BindTarget(false); - this.control = value; + _control = value; BindTarget(true); - try { + try + { CheckBinding(); } - catch { + catch + { BindTarget(false); - control = oldTarget; + _control = oldTarget; BindTarget(true); throw; } // We are essentially doing to the listManager what we were doing to the // BindToObject: bind only when the control is created and it has a BindingContext - BindingContext.UpdateBinding((control != null && IsComponentCreated(control) ? control.BindingContext: null), this); + BindingContext.UpdateBinding((_control != null && IsComponentCreated(_control) ? _control.BindingContext : null), this); Form form = value as Form; - if (form != null) { + if (form != null) + { form.Load += new EventHandler(FormLoaded); } } } - /// - /// - /// - /// Gets a value indicating whether the binding is active. - /// - /// - public bool IsBinding { - get { - return bound; - } - } + /// + /// Gets a value indicating whether the binding is active. + /// + public bool IsBinding => _bound; - /// - /// - /// - /// Gets the - /// of this binding that allows enumeration of a set of - /// bindings. - /// - /// - public BindingManagerBase BindingManagerBase{ - get { - return bindingManagerBase; - } - } + /// + /// Gets the of this binding that + /// allows enumeration of a set of bindings. + /// + public BindingManagerBase BindingManagerBase => _bindingManagerBase; - internal void SetListManager(BindingManagerBase bindingManagerBase) { - if (this.bindingManagerBase is CurrencyManager) { - ((CurrencyManager)this.bindingManagerBase).MetaDataChanged -= new EventHandler(binding_MetaDataChanged); + internal void SetListManager(BindingManagerBase newBindingManagerBase) + { + if (_bindingManagerBase is CurrencyManager oldCurrencyManagEr) + { + oldCurrencyManagEr.MetaDataChanged -= new EventHandler(binding_MetaDataChanged); } - this.bindingManagerBase = bindingManagerBase; + _bindingManagerBase = newBindingManagerBase; - if (this.bindingManagerBase is CurrencyManager ) { - ((CurrencyManager)this.bindingManagerBase).MetaDataChanged += new EventHandler(binding_MetaDataChanged); + if (newBindingManagerBase is CurrencyManager newCurrencyManager) + { + newCurrencyManager.MetaDataChanged += new EventHandler(binding_MetaDataChanged); } - this.BindToObject.SetBindingManagerBase(bindingManagerBase); + _bindToObject.SetBindingManagerBase(newBindingManagerBase); CheckBinding(); } - - /// - /// - /// - /// Gets or sets the property on the control to bind to. - /// - /// + + /// + /// Gets or sets the property on the control to bind to. + /// [DefaultValue("")] - public string PropertyName { - get { - return propertyName; - } - } + public string PropertyName => _propertyName; - /// - public event BindingCompleteEventHandler BindingComplete { - add { - onComplete += value; - } - remove { - onComplete -= value; - } + public event BindingCompleteEventHandler BindingComplete + { + add => _onComplete += value; + remove => _onComplete -= value; } - /// - public event ConvertEventHandler Parse { - add { - onParse += value; - } - remove { - onParse -= value; - } + public event ConvertEventHandler Parse + { + add => _onParse += value; + remove => _onParse -= value; } - /// - public event ConvertEventHandler Format { - add { - onFormat += value; - } - remove { - onFormat -= value; - } + public event ConvertEventHandler Format + { + add => _onFormat += value; + remove => _onFormat -= value; } - /// [DefaultValue(false)] - public bool FormattingEnabled { - + public bool FormattingEnabled + { // A note about FormattingEnabled: This flag was introduced in Whidbey, to enable new // formatting features. However, it is also used to trigger other new Whidbey binding // behavior not related to formatting (such as error handling). This preserves Everett // legacy behavior for old bindings (where FormattingEnabled = false). - - get { - return formattingEnabled; - } - set { - if (formattingEnabled != value) { - formattingEnabled = value; - if (IsBinding) { + get => _formattingEnabled; + set + { + if (_formattingEnabled != value) + { + _formattingEnabled = value; + if (IsBinding) + { PushData(); } } } } - /// [DefaultValue(null)] - public IFormatProvider FormatInfo { - get { - return this.formatInfo; - } - set { - if (formatInfo != value) { - this.formatInfo = value; - if (IsBinding) { + public IFormatProvider FormatInfo + { + get => _formatInfo; + set + { + if (_formatInfo != value) + { + _formatInfo = value; + if (IsBinding) + { PushData(); } } } } - /// - public string FormatString { - get { - return this.formatString; - } - set { + public string FormatString + { + get => _formatString; + set + { if (value == null) + { value = string.Empty; - if (!value.Equals(formatString)) { - this.formatString = value; - if (IsBinding) { + } + + if (!value.Equals(_formatString)) + { + _formatString = value; + if (IsBinding) + { PushData(); } } } } - /// - public object NullValue { - get { - return this.nullValue; - } - set { + public object NullValue + { + get => _nullValue; + set + { // Try to compare logical values, not object references... - if (!Object.Equals(nullValue, value)) { - this.nullValue = value; + if (!object.Equals(_nullValue, value)) + { + _nullValue = value; // If data member is currently DBNull, force update of bound // control property so that it displays the new NullValue - // - if (IsBinding && Formatter.IsNullData(bindToObject.GetValue(), this.dsNullValue)) { + if (IsBinding && Formatter.IsNullData(_bindToObject.GetValue(), _dsNullValue)) + { PushData(); } } } } - /// - public object DataSourceNullValue { - get { - return this.dsNullValue; - } - set { + public object DataSourceNullValue + { + get => _dsNullValue; + set + { // Try to compare logical values, not object references... - if (!Object.Equals(this.dsNullValue, value)) { - + if (!object.Equals(_dsNullValue, value)) + { // Save old Value - object oldValue = this.dsNullValue; + object oldValue = _dsNullValue; // Set value - this.dsNullValue = value; + _dsNullValue = value; - this.dsNullValueSet = true; + _dsNullValueSet = true; // If control's property is capable of displaying a special value for DBNull, // and the DBNull status of data source's property has changed, force the // control property to refresh itself from the data source property. - // - if (IsBinding) { - object dsValue = bindToObject.GetValue(); + if (IsBinding) + { + object dsValue = _bindToObject.GetValue(); // Check previous DataSourceNullValue for null - if (Formatter.IsNullData(dsValue, oldValue)) { + if (Formatter.IsNullData(dsValue, oldValue)) + { // Update DataSource Value to new DataSourceNullValue WriteValue(); } // Check current DataSourceNullValue - if (Formatter.IsNullData(dsValue, value)) { + if (Formatter.IsNullData(dsValue, value)) + { // Update Control because the DataSource is now null ReadValue(); } @@ -413,200 +344,209 @@ public object DataSourceNullValue { } } - /// [DefaultValue(ControlUpdateMode.OnPropertyChanged)] - public ControlUpdateMode ControlUpdateMode { - get { - return this.controlUpdateMode; - } - set { - if (this.controlUpdateMode != value) { - this.controlUpdateMode = value; + public ControlUpdateMode ControlUpdateMode + { + get => _controlUpdateMode; + set + { + if (_controlUpdateMode != value) + { + _controlUpdateMode = value; // Refresh the control from the data source, to reflect the new update mode - if (IsBinding) { + if (IsBinding) + { PushData(); } } } } - /// [DefaultValue(DataSourceUpdateMode.OnValidation)] - public DataSourceUpdateMode DataSourceUpdateMode { - get { - return this.dataSourceUpdateMode; - } - set { - if (this.dataSourceUpdateMode != value) { - this.dataSourceUpdateMode = value; - } - } - } - - private void BindTarget(bool bind) { - if (bind) { - if (IsBinding) { - if (propInfo != null && control != null) { - EventHandler handler = new EventHandler(this.Target_PropertyChanged); - propInfo.AddValueChanged(control, handler); + public DataSourceUpdateMode DataSourceUpdateMode { get; set; } = DataSourceUpdateMode.OnValidation; + + private void BindTarget(bool bind) + { + if (bind) + { + if (IsBinding) + { + if (_propInfo != null && _control != null) + { + EventHandler handler = new EventHandler(Target_PropertyChanged); + _propInfo.AddValueChanged(_control, handler); } - if (validateInfo != null) { - CancelEventHandler handler = new CancelEventHandler(this.Target_Validate); - validateInfo.AddEventHandler(control, handler); + if (_validateInfo != null) + { + CancelEventHandler handler = new CancelEventHandler(Target_Validate); + _validateInfo.AddEventHandler(_control, handler); } } } - else { - if (propInfo != null && control != null) { - EventHandler handler = new EventHandler(this.Target_PropertyChanged); - propInfo.RemoveValueChanged(control, handler); + else + { + if (_propInfo != null && _control != null) + { + EventHandler handler = new EventHandler(Target_PropertyChanged); + _propInfo.RemoveValueChanged(_control, handler); + } + if (_validateInfo != null) + { + CancelEventHandler handler = new CancelEventHandler(Target_Validate); + _validateInfo.RemoveEventHandler(_control, handler); } - if (validateInfo != null) { - CancelEventHandler handler = new CancelEventHandler(this.Target_Validate); - validateInfo.RemoveEventHandler(control, handler); - } } } - private void binding_MetaDataChanged(object sender, EventArgs e) { - Debug.Assert(sender == this.bindingManagerBase, "we should only receive notification from our binding manager base"); + private void binding_MetaDataChanged(object sender, EventArgs e) + { + Debug.Assert(sender == _bindingManagerBase, "we should only receive notification from our binding manager base"); CheckBinding(); } - private void CheckBinding() { - this.bindToObject.CheckBinding(); + private void CheckBinding() + { + _bindToObject.CheckBinding(); - if (control != null && !string.IsNullOrEmpty(propertyName)) { - control.DataBindings.CheckDuplicates(this); - - Type controlClass = control.GetType(); + if (_control != null && !string.IsNullOrEmpty(_propertyName)) + { + _control.DataBindings.CheckDuplicates(this); + + Type controlClass = _control.GetType(); // Check Properties - string propertyNameIsNull = propertyName + "IsNull"; + string propertyNameIsNull = _propertyName + "IsNull"; Type propType = null; PropertyDescriptor tempPropInfo = null; PropertyDescriptor tempPropIsNullInfo = null; PropertyDescriptorCollection propInfos; - + // If the control is being inherited, then get the properties for // the control's type rather than for the control itself. Getting // properties for the control will merge the control's properties with // those of its designer. Normally we want that, but for // inherited controls we don't because an inherited control should // "act" like a runtime control. - // - InheritanceAttribute attr = (InheritanceAttribute)TypeDescriptor.GetAttributes(control)[typeof(InheritanceAttribute)]; - if (attr != null && attr.InheritanceLevel != InheritanceLevel.NotInherited) { + InheritanceAttribute attr = (InheritanceAttribute)TypeDescriptor.GetAttributes(_control)[typeof(InheritanceAttribute)]; + if (attr != null && attr.InheritanceLevel != InheritanceLevel.NotInherited) + { propInfos = TypeDescriptor.GetProperties(controlClass); } - else { - propInfos = TypeDescriptor.GetProperties(control); + else + { + propInfos = TypeDescriptor.GetProperties(_control); } - - for (int i = 0; i < propInfos.Count; i++) { - if(tempPropInfo==null && string.Equals (propInfos[i].Name, propertyName, StringComparison.OrdinalIgnoreCase)) { + + for (int i = 0; i < propInfos.Count; i++) + { + if (tempPropInfo == null && string.Equals(propInfos[i].Name, _propertyName, StringComparison.OrdinalIgnoreCase)) + { tempPropInfo = propInfos[i]; if (tempPropIsNullInfo != null) + { break; + } } - if(tempPropIsNullInfo == null && string.Equals (propInfos[i].Name, propertyNameIsNull, StringComparison.OrdinalIgnoreCase)) { + if (tempPropIsNullInfo == null && string.Equals(propInfos[i].Name, propertyNameIsNull, StringComparison.OrdinalIgnoreCase)) + { tempPropIsNullInfo = propInfos[i]; if (tempPropInfo != null) + { break; + } } } - if (tempPropInfo == null) { - throw new ArgumentException(string.Format(SR.ListBindingBindProperty, propertyName), "PropertyName"); + if (tempPropInfo == null) + { + throw new ArgumentException(string.Format(SR.ListBindingBindProperty, _propertyName), "PropertyName"); } - if (tempPropInfo.IsReadOnly && this.controlUpdateMode != ControlUpdateMode.Never) { - throw new ArgumentException(string.Format(SR.ListBindingBindPropertyReadOnly, propertyName), "PropertyName"); + if (tempPropInfo.IsReadOnly && _controlUpdateMode != ControlUpdateMode.Never) + { + throw new ArgumentException(string.Format(SR.ListBindingBindPropertyReadOnly, _propertyName), "PropertyName"); } - propInfo = tempPropInfo; - propType = propInfo.PropertyType; - propInfoConverter = propInfo.Converter; + _propInfo = tempPropInfo; + propType = _propInfo.PropertyType; + _propInfoConverter = _propInfo.Converter; if (tempPropIsNullInfo != null && tempPropIsNullInfo.PropertyType == typeof(bool) && !tempPropIsNullInfo.IsReadOnly) - propIsNullInfo = tempPropIsNullInfo; + { + _propIsNullInfo = tempPropIsNullInfo; + } // Check events EventDescriptor tempValidateInfo = null; string validateName = "Validating"; - EventDescriptorCollection eventInfos = TypeDescriptor.GetEvents(control); - for (int i = 0; i < eventInfos.Count; i++) { - if(tempValidateInfo==null && string.Equals (eventInfos[i].Name, validateName, StringComparison.OrdinalIgnoreCase)) { + EventDescriptorCollection eventInfos = TypeDescriptor.GetEvents(_control); + for (int i = 0; i < eventInfos.Count; i++) + { + if (tempValidateInfo == null && string.Equals(eventInfos[i].Name, validateName, StringComparison.OrdinalIgnoreCase)) + { tempValidateInfo = eventInfos[i]; break; } } - validateInfo = tempValidateInfo; + _validateInfo = tempValidateInfo; } - else { - propInfo = null; - validateInfo = null; + else + { + _propInfo = null; + _validateInfo = null; } // go see if we become bound now. UpdateIsBinding(); } - internal bool ControlAtDesignTime() { - IComponent comp = (this.control as IComponent); - if (comp == null) - return false; - - ISite site = comp.Site; - if (site == null) + internal bool ControlAtDesignTime() + { + if (!(_control is IComponent comp)) + { return false; + } - return site.DesignMode; + return comp.Site?.DesignMode ?? false; } - private object GetDataSourceNullValue(Type type) { - return this.dsNullValueSet ? this.dsNullValue : Formatter.GetDefaultDataSourceNullValue(type); + private object GetDataSourceNullValue(Type type) + { + return _dsNullValueSet ? _dsNullValue : Formatter.GetDefaultDataSourceNullValue(type); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] // Perfectly acceptible when dealing with PropertyDescriptors - private object GetPropValue() { - bool isNull = false; - if (propIsNullInfo != null) { - isNull = (bool) propIsNullInfo.GetValue(control); - } - object value; - if (isNull) { - value = DataSourceNullValue; - } - else { - value = propInfo.GetValue(control); - // - - - if (value == null) { - value = DataSourceNullValue; - } + [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes", Justification = "Perfectly acceptible when dealing with PropertyDescriptors")] + private object GetPropValue() + { + if (_propIsNullInfo != null && (bool)_propIsNullInfo.GetValue(_control)) + { + return DataSourceNullValue; } - return value; + + return _propInfo.GetValue(_control) ?? DataSourceNullValue; } - private BindingCompleteEventArgs CreateBindingCompleteEventArgs(BindingCompleteContext context, Exception ex) { + private BindingCompleteEventArgs CreateBindingCompleteEventArgs(BindingCompleteContext context, Exception ex) + { bool cancel = false; string errorText = string.Empty; BindingCompleteState state = BindingCompleteState.Success; - if (ex != null) { + if (ex != null) + { // If an exception was provided, report that errorText = ex.Message; state = BindingCompleteState.Exception; cancel = true; } - else { + else + { // If data error info on data source for this binding, report that - errorText = this.BindToObject.DataErrorText; + errorText = _bindToObject.DataErrorText; // We should not cancel with an IDataErrorInfo error - we didn't in Everett - if (!string.IsNullOrEmpty(errorText)) { + if (!string.IsNullOrEmpty(errorText)) + { state = BindingCompleteState.DataError; } } @@ -614,298 +554,306 @@ private BindingCompleteEventArgs CreateBindingCompleteEventArgs(BindingCompleteC return new BindingCompleteEventArgs(this, state, context, errorText, ex, cancel); } - /// - protected virtual void OnBindingComplete(BindingCompleteEventArgs e) { + protected virtual void OnBindingComplete(BindingCompleteEventArgs e) + { // This recursion guard will only be in effect if FormattingEnabled because this method // is only called if formatting is enabled. - if (!inOnBindingComplete) { - try { - inOnBindingComplete = true; - if (onComplete != null) { - onComplete(this, e); - } + if (!_inOnBindingComplete) + { + try + { + _inOnBindingComplete = true; + _onComplete?.Invoke(this, e); } - catch (Exception ex) { - if (ClientUtils.IsSecurityOrCriticalException(ex)) { - throw; - } - + catch (Exception ex) when (!ClientUtils.IsSecurityOrCriticalException(ex)) + { // BindingComplete event is intended primarily as an "FYI" event with support for cancellation. // User code should not be throwing exceptions from this event as a way to signal new error conditions (they should use // things like the Format or Parse events for that). Exceptions thrown here can mess up currency manager behavior big time. // For now, eat any non-critical exceptions and instead just cancel the current push/pull operation. e.Cancel = true; } - finally { - inOnBindingComplete = false; + finally + { + _inOnBindingComplete = false; } } } - /// - protected virtual void OnParse(ConvertEventArgs cevent) { - if (onParse != null) { - onParse(this, cevent); - } + protected virtual void OnParse(ConvertEventArgs cevent) + { + _onParse?.Invoke(this, cevent); - if (!formattingEnabled) { - if (!(cevent.Value is System.DBNull) && cevent.Value != null && cevent.DesiredType != null && !cevent.DesiredType.IsInstanceOfType(cevent.Value) && (cevent.Value is IConvertible)) { + if (!_formattingEnabled) + { + if (!(cevent.Value is DBNull) && cevent.Value != null && cevent.DesiredType != null && !cevent.DesiredType.IsInstanceOfType(cevent.Value) && (cevent.Value is IConvertible)) + { cevent.Value = Convert.ChangeType(cevent.Value, cevent.DesiredType, CultureInfo.CurrentCulture); } } } - /// - protected virtual void OnFormat(ConvertEventArgs cevent) { - if (onFormat!= null) { - onFormat(this, cevent); - } - if (!formattingEnabled) { - if (!(cevent.Value is System.DBNull) && cevent.DesiredType != null && !cevent.DesiredType.IsInstanceOfType(cevent.Value) && (cevent.Value is IConvertible)) { + protected virtual void OnFormat(ConvertEventArgs cevent) + { + _onFormat?.Invoke(this, cevent); + + if (!_formattingEnabled) + { + if (!(cevent.Value is DBNull) && cevent.DesiredType != null && !cevent.DesiredType.IsInstanceOfType(cevent.Value) && (cevent.Value is IConvertible)) + { cevent.Value = Convert.ChangeType(cevent.Value, cevent.DesiredType, CultureInfo.CurrentCulture); } } } - private object ParseObject(object value) { - Type type = this.bindToObject.BindToType; - - if (formattingEnabled) { - // ------------------------------- - // Behavior for Whidbey and beyond - // ------------------------------- - + private object ParseObject(object value) + { + Type type = _bindToObject.BindToType; + if (_formattingEnabled) + { // Fire the Parse event so that user code gets a chance to supply the parsed value for us - ConvertEventArgs e = new ConvertEventArgs(value, type); + var e = new ConvertEventArgs(value, type); OnParse(e); object newValue = e.Value; - - if (!object.Equals(value, newValue)) { + if (!object.Equals(value, newValue)) + { // If event handler replaced formatted value with parsed value, use that return newValue; } - else { + else + { // Otherwise parse the formatted value ourselves TypeConverter fieldInfoConverter = null; - if (bindToObject.FieldInfo != null) { - fieldInfoConverter = bindToObject.FieldInfo.Converter; + if (_bindToObject.FieldInfo != null) + { + fieldInfoConverter = _bindToObject.FieldInfo.Converter; } - return Formatter.ParseObject(value, type, (value == null ? propInfo.PropertyType : value.GetType()), fieldInfoConverter, propInfoConverter, formatInfo, nullValue, GetDataSourceNullValue(type)); - } - } else { - // ---------------------------- - // Behavior for RTM and Everett [DO NOT MODIFY!] - // ---------------------------- - - ConvertEventArgs e = new ConvertEventArgs(value, type); + return Formatter.ParseObject(value, type, (value == null ? _propInfo.PropertyType : value.GetType()), fieldInfoConverter, _propInfoConverter, _formatInfo, _nullValue, GetDataSourceNullValue(type)); + } + } + else + { + var e = new ConvertEventArgs(value, type); // first try: use the OnParse event OnParse(e); - // - if (e.Value != null && (e.Value.GetType().IsSubclassOf(type) || e.Value.GetType() == type || e.Value is System.DBNull)) + if (e.Value != null && (e.Value.GetType().IsSubclassOf(type) || e.Value.GetType() == type || e.Value is DBNull)) + { return e.Value; + } + // second try: use the TypeConverter TypeConverter typeConverter = TypeDescriptor.GetConverter(value != null ? value.GetType() : typeof(object)); - if (typeConverter != null && typeConverter.CanConvertTo(type)) { + if (typeConverter != null && typeConverter.CanConvertTo(type)) + { return typeConverter.ConvertTo(value, type); } // last try: use Convert.ToType - if (value is IConvertible) { + if (value is IConvertible) + { object ret = Convert.ChangeType(value, type, CultureInfo.CurrentCulture); if (ret != null && (ret.GetType().IsSubclassOf(type) || ret.GetType() == type)) + { return ret; + } } - // time to fail: (RTM/Everett just returns null, whereas Whidbey throws an exception) + return null; } } - private object FormatObject(object value) { + private object FormatObject(object value) + { // We will not format the object when the control is in design time. // This is because if we bind a boolean property on a control to a // row that is full of DBNulls then we cause problems in the shell. if (ControlAtDesignTime()) + { return value; + } - Type type = propInfo.PropertyType; - - if (formattingEnabled) { - // ------------------------------- - // Behavior for Whidbey and beyond - // ------------------------------- - + Type type = _propInfo.PropertyType; + if (_formattingEnabled) + { // Fire the Format event so that user code gets a chance to supply the formatted value for us - ConvertEventArgs e = new ConvertEventArgs(value, type); + var e = new ConvertEventArgs(value, type); OnFormat(e); - if (e.Value != value) { + if (e.Value != value) + { // If event handler replaced parsed value with formatted value, use that return e.Value; } - else { + else + { // Otherwise format the parsed value ourselves TypeConverter fieldInfoConverter = null; - if (bindToObject.FieldInfo != null) { - fieldInfoConverter = bindToObject.FieldInfo.Converter; + if (_bindToObject.FieldInfo != null) + { + fieldInfoConverter = _bindToObject.FieldInfo.Converter; } - return Formatter.FormatObject(value, type, fieldInfoConverter, propInfoConverter, formatString, formatInfo, nullValue, dsNullValue); - } - - } else { - // ---------------------------- - // Behavior for RTM and Everett [DO NOT MODIFY!] - // ---------------------------- + return Formatter.FormatObject(value, type, fieldInfoConverter, _propInfoConverter, _formatString, _formatInfo, _nullValue, _dsNullValue); + } + } + else + { // first try: use the Format event - ConvertEventArgs e = new ConvertEventArgs(value, type); + var e = new ConvertEventArgs(value, type); OnFormat(e); object ret = e.Value; - // Approved breaking-change behavior between RTM and Everett: Fire the Format event even if the control property is of type - // Object (RTM used to skip the event for properties of this type). - + // Fire the Format event even if the control property is of type Object. if (type == typeof(object)) + { return value; + } // stop now if we have a value of a compatible type if (ret != null && (ret.GetType().IsSubclassOf(type) || ret.GetType() == type)) + { return ret; + } + // second try: use type converter for the desiredType TypeConverter typeConverter = TypeDescriptor.GetConverter(value != null ? value.GetType() : typeof(object)); - if (typeConverter != null && typeConverter.CanConvertTo(type)) { - ret = typeConverter.ConvertTo(value, type); - return ret; + if (typeConverter != null && typeConverter.CanConvertTo(type)) + { + return typeConverter.ConvertTo(value, type); } + // last try: use Convert.ChangeType - if (value is IConvertible) { + if (value is IConvertible) + { ret = Convert.ChangeType(value, type, CultureInfo.CurrentCulture); if (ret != null && (ret.GetType().IsSubclassOf(type) || ret.GetType() == type)) + { return ret; + } } - // time to fail: throw new FormatException(SR.ListBindingFormatFailed); } } - // - // PullData() - // - // Pulls data from control property into data source. Returns bool indicating whether caller - // should cancel the higher level operation. Raises a BindingComplete event regardless of - // success or failure. - // - // When the user leaves the control, it will raise a Validating event, calling the Binding.Target_Validate - // method, which in turn calls PullData. PullData is also called by the binding manager when pulling data - // from all bounds properties in one go. - // - - internal bool PullData() { - return PullData(true, false); - } - - internal bool PullData(bool reformat) { - return PullData(reformat, false); - } - - internal bool PullData(bool reformat, bool force) { - //Don't update the control if the control update mode is never. - if (ControlUpdateMode == ControlUpdateMode.Never) { + /// + /// Pulls data from control property into data source. Returns bool indicating whether caller + /// should cancel the higher level operation. Raises a BindingComplete event regardless of + /// success or failure. + /// + /// When the user leaves the control, it will raise a Validating event, calling the Binding.Target_Validate + /// method, which in turn calls PullData. PullData is also called by the binding manager when pulling data + /// from all bounds properties in one go. + /// + internal bool PullData() => PullData(reformat: true, force: false); + + internal bool PullData(bool reformat) => PullData(reformat, force: false); + + internal bool PullData(bool reformat, bool force) + { + // Don't update the control if the control update mode is never. + if (ControlUpdateMode == ControlUpdateMode.Never) + { reformat = false; } + bool parseFailed = false; object parsedValue = null; Exception lastException = null; // Check whether binding has been suspended or is simply not possible right now - if (!IsBinding) { + if (!IsBinding) + { return false; } // If caller is not FORCING us to pull, determine whether we want to pull right now... - if (!force) { + if (!force) + { // If control property supports change events, only pull if the value has been changed since // the last update (ie. its dirty). For properties that do NOT support change events, we cannot // track the dirty state, so we just have to pull all the time. - if (propInfo.SupportsChangeEvents && !modified) { + if (_propInfo.SupportsChangeEvents && !_modified) + { return false; } // Don't pull if the update mode is 'Never' (ie. read-only binding) - if (DataSourceUpdateMode == DataSourceUpdateMode.Never) { + if (DataSourceUpdateMode == DataSourceUpdateMode.Never) + { return false; } } // Re-entrancy check between push and pull (new for Whidbey - requires FormattingEnabled) - if (inPushOrPull && formattingEnabled) { + if (_inPushOrPull && _formattingEnabled) + { return false; } - inPushOrPull = true; + _inPushOrPull = true; // Get the value from the bound control property object value = GetPropValue(); // Attempt to parse the property value into a format suitable for the data source - try { + try + { parsedValue = ParseObject(value); } - catch (Exception ex) { + catch (Exception ex) + { + // Eat parsing exceptions. lastException = ex; - - // ...pre-Whidbey behavior was to eat parsing exceptions. This behavior is preserved. } - try { + try + { // If parse failed, reset control property value back to original data source value. - // An exception always indicates a parsing failure. A parsed value of null only indicates - // a parsing failure when following pre-Whidbey behavior (ie. FormattingEnabled=False) since - // in Whidbey we now support writing null back to the data source (eg. for business objects). - if (lastException != null || (!FormattingEnabled && parsedValue == null)) { + // An exception always indicates a parsing failure. + if (lastException != null || (!FormattingEnabled && parsedValue == null)) + { parseFailed = true; - parsedValue = this.bindToObject.GetValue(); + parsedValue = _bindToObject.GetValue(); } // Format the parsed value to be re-displayed in the control - if (reformat) { - if (FormattingEnabled && parseFailed) { - // New behavior for Whidbey (ie. requires FormattingEnabled=true). If parsing - // fails, do NOT push the original data source value back into the control. - // This blows away the invalid value before the user gets a chance to see - // what needs correcting, which was the Everett behavior. + if (reformat) + { + if (FormattingEnabled && parseFailed) + { + // If parsing fails, do NOT push the original data source value back + // into the control. } - else { + else + { object formattedObject = FormatObject(parsedValue); - - if (force || !FormattingEnabled || !Object.Equals(formattedObject, value)) { + if (force || !FormattingEnabled || !object.Equals(formattedObject, value)) + { SetPropValue(formattedObject); } } } // Put the value into the data model - if (!parseFailed) { - this.bindToObject.SetValue(parsedValue); + if (!parseFailed) + { + _bindToObject.SetValue(parsedValue); } } - catch (Exception ex) { + catch (Exception ex) when (FormattingEnabled) + { + // Throw the exception unless this binding has formatting enabled lastException = ex; - - // This try/catch is new for Whidbey. To preserve Everett behavior, re-throw the - // exception unless this binding has formatting enabled (new Whidbey feature). - if (!FormattingEnabled) { - throw; - } } - finally { - inPushOrPull = false; + finally + { + _inPushOrPull = false; } - if (FormattingEnabled) { - // Whidbey... - + if (FormattingEnabled) + { // Raise the BindingComplete event, giving listeners a chance to process any // errors that occured and decide whether the operation should be cancelled. BindingCompleteEventArgs args = CreateBindingCompleteEventArgs(BindingCompleteContext.DataSourceUpdate, lastException); @@ -916,75 +864,73 @@ internal bool PullData(bool reformat, bool force) { // the data source. But if the operation failed (or was cancelled), we must leave the dirty flag // alone, so that the control's value will continue to be re-validated and re-pulled later. if (args.BindingCompleteState == BindingCompleteState.Success && args.Cancel == false) - modified = false; + { + _modified = false; + } return args.Cancel; } - else { - // Everett... - + else + { // Do not emit BindingComplete events, or allow the operation to be cancelled. // If we get this far, treat the operation as successful and clear the dirty flag. - modified = false; + _modified = false; return false; } } - // - // PushData() - // - // Pushes data from data source into control property. Returns bool indicating whether caller - // should cancel the higher level operation. Raises a BindingComplete event regardless of - // success or failure. - // + /// + /// Pushes data from data source into control property. Returns bool indicating whether caller + /// should cancel the higher level operation. Raises a BindingComplete event regardless of + /// success or failure. + /// + internal bool PushData() => PushData(force: false); - internal bool PushData() { - return PushData(false); - } - - internal bool PushData(bool force) { + internal bool PushData(bool force) + { object dataSourceValue = null; Exception lastException = null; // Don't push if update mode is 'Never' (unless caller is FORCING us to push) - if (!force && ControlUpdateMode == ControlUpdateMode.Never) { + if (!force && ControlUpdateMode == ControlUpdateMode.Never) + { return false; } - // Re-entrancy check between push and pull (new for Whidbey - requires FormattingEnabled) - if (inPushOrPull && formattingEnabled) { + // Re-entrancy check between push and pull + if (_inPushOrPull && _formattingEnabled) + { return false; } - inPushOrPull = true; + _inPushOrPull = true; - try { - if (IsBinding) { - dataSourceValue = bindToObject.GetValue(); + try + { + if (IsBinding) + { + dataSourceValue = _bindToObject.GetValue(); object controlValue = FormatObject(dataSourceValue); SetPropValue(controlValue); - modified = false; + _modified = false; } - else { + else + { SetPropValue(null); } } - catch (Exception ex) { + catch (Exception ex) when (FormattingEnabled) + { + // Re-throw the exception unless this binding has formatting enabled lastException = ex; - - // This try/catch is new for Whidbey. To preserve Everett behavior, re-throw the - // exception unless this binding has formatting enabled (new Whidbey feature). - if (!FormattingEnabled) { - throw; - } } - finally { - inPushOrPull = false; + finally + { + _inPushOrPull = false; } - if (FormattingEnabled) { - // Whidbey... - + if (FormattingEnabled) + { // Raise the BindingComplete event, giving listeners a chance to process any errors that occured, and decide // whether the operation should be cancelled. But don't emit the event if we didn't actually update the control. BindingCompleteEventArgs args = CreateBindingCompleteEventArgs(BindingCompleteContext.ControlUpdate, lastException); @@ -992,136 +938,148 @@ internal bool PushData(bool force) { return args.Cancel; } - else { - // Everett... - + else + { // Do not emit BindingComplete events, or allow the operation to be cancelled. return false; } } - /// - /// - /// Reads current value from data source, and sends this to the control. - /// - public void ReadValue() { - PushData(/*force:*/ true); - } - - /// - /// - /// Takes current value from control, and writes this out to the data source. - /// - public void WriteValue() { - // PullData has a guard for ControlUpdateMode == Never. + /// + /// Reads current value from data source, and sends this to the control. + /// + public void ReadValue() => PushData(force: true); - PullData(/*reformat:*/ true, /*force:*/ true); - } + /// + /// Takes current value from control, and writes this out to the data source. + /// + public void WriteValue() => PullData(reformat: true, force: true); - private void SetPropValue(object value) { + private void SetPropValue(object value) + { // we will not pull the data from the back end into the control // when the control is in design time. this is because if we bind a boolean property on a control // to a row that is full of DBNulls then we cause problems in the shell. if (ControlAtDesignTime()) + { return; + } - inSetPropValue = true; + _inSetPropValue = true; - try { + try + { bool isNull = value == null || Formatter.IsNullData(value, DataSourceNullValue); - if (isNull) { - if (propIsNullInfo != null) { - propIsNullInfo.SetValue(control, true); + if (isNull) + { + if (_propIsNullInfo != null) + { + _propIsNullInfo.SetValue(_control, true); } - else { - if (propInfo.PropertyType == typeof(object)) { - propInfo.SetValue(control, DataSourceNullValue); + else + { + if (_propInfo.PropertyType == typeof(object)) + { + _propInfo.SetValue(_control, DataSourceNullValue); } - else { - propInfo.SetValue(control, null); + else + { + _propInfo.SetValue(_control, null); } - } } - else { - propInfo.SetValue(control, value); + else + { + _propInfo.SetValue(_control, value); } } - finally { - inSetPropValue = false; + finally + { + _inSetPropValue = false; } } - private bool ShouldSerializeFormatString() { - return formatString != null && formatString.Length > 0; - - } + private bool ShouldSerializeFormatString() => !string.IsNullOrEmpty(_formatString); - private bool ShouldSerializeNullValue() { - return nullValue != null; - } + private bool ShouldSerializeNullValue() => _nullValue != null; - private bool ShouldSerializeDataSourceNullValue() { - return this.dsNullValueSet && this.dsNullValue != Formatter.GetDefaultDataSourceNullValue(null); + private bool ShouldSerializeDataSourceNullValue() + { + return _dsNullValueSet && _dsNullValue != Formatter.GetDefaultDataSourceNullValue(null); } - private void Target_PropertyChanged(object sender, EventArgs e) { - if (inSetPropValue) + private void Target_PropertyChanged(object sender, EventArgs e) + { + if (_inSetPropValue) + { return; + } - if (IsBinding) { - //dataSource.BeginEdit(); - - modified = true; + if (IsBinding) + { + _modified = true; // If required, update data source every time control property changes. - // NOTE: We need modified=true to be set both before pulling data - // (so that pull will work) and afterwards (so that validation will - // still occur later on). - if (DataSourceUpdateMode == DataSourceUpdateMode.OnPropertyChanged) { - PullData(false); // false = don't reformat property (bad user experience!!) - modified = true; + // NOTE: We need modified=true to be set both before pulling data + // (so that pull will work) and afterwards (so that validation will + // still occur later on). + if (DataSourceUpdateMode == DataSourceUpdateMode.OnPropertyChanged) + { + PullData(reformat: false); + _modified = true; } } } - // Event handler for the Control.Validating event on the control that we are bound to. - // - // If value in control has changed, we want to send that value back up to the data source - // when the control undergoes validation (eg. on loss of focus). If an error occurs, we - // will set e.Cancel=true to make validation fail and force focus to remain on the control. - // - // NOTE: If no error occurs, we MUST leave e.Cancel alone, to respect any value put in there - // by event handlers high up the event chain. - // - private void Target_Validate(object sender, CancelEventArgs e) { - try { - if (PullData(true)) { + /// + /// Event handler for the Control.Validating event on the control that we are bound to. + /// + /// If value in control has changed, we want to send that value back up to the data source + /// when the control undergoes validation (eg. on loss of focus). If an error occurs, we + /// will set e.Cancel=true to make validation fail and force focus to remain on the control. + /// + /// NOTE: If no error occurs, we MUST leave e.Cancel alone, to respect any value put in there + /// by event handlers high up the event chain. + /// + private void Target_Validate(object sender, CancelEventArgs e) + { + try + { + if (PullData(true)) + { e.Cancel = true; } } - catch { + catch + { e.Cancel = true; } } - internal bool IsBindable { - get { - return (control != null && !string.IsNullOrEmpty(propertyName) && - bindToObject.DataSource != null && bindingManagerBase != null); + internal bool IsBindable + { + get + { + return (_control != null && !string.IsNullOrEmpty(_propertyName) && + _bindToObject.DataSource != null && _bindingManagerBase != null); } } - - internal void UpdateIsBinding() { - bool newBound = IsBindable && ComponentCreated && bindingManagerBase.IsBinding; - if (bound != newBound) { - bound = newBound; + + internal void UpdateIsBinding() + { + bool newBound = IsBindable && ComponentCreated && _bindingManagerBase.IsBinding; + if (_bound != newBound) + { + _bound = newBound; BindTarget(newBound); - if (bound) { - if (controlUpdateMode == ControlUpdateMode.Never) { - PullData(false, true); //Don't reformat, force pull - } - else { + if (_bound) + { + if (_controlUpdateMode == ControlUpdateMode.Never) + { + PullData(reformat: false, force: true); + } + else + { PushData(); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/BindingContext.cs b/src/System.Windows.Forms/src/System/Windows/Forms/BindingContext.cs index 48541d1375a..e4eb75dbfd8 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/BindingContext.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/BindingContext.cs @@ -2,438 +2,428 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { +using System.Collections; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; - using System; - using Microsoft.Win32; - using System.ComponentModel; - using System.Collections; - using System.Globalization; - using System.Diagnostics.CodeAnalysis; - - /// +namespace System.Windows.Forms +{ /// - /// Manages the collection of System.Windows.Forms.BindingManagerBase - /// objects for a Win Form. + /// Manages the collection of System.Windows.Forms.BindingManagerBase + /// objects for a Win Form. /// [DefaultEvent(nameof(CollectionChanged))] - public class BindingContext : ICollection { + public class BindingContext : ICollection + { + private Hashtable _listManagers; - private Hashtable listManagers; + /// + /// Initializes a new instance of the System.Windows.Forms.BindingContext class. + /// + public BindingContext() + { + _listManagers = new Hashtable(); + } - /// - /// /// - /// - /// Gets the total number of System.Windows.Forms.BindingManagerBases - /// objects. - /// + /// Gets the total number of System.Windows.Forms.BindingManagerBases objects. /// - int ICollection.Count { - get { + int ICollection.Count + { + get + { ScrubWeakRefs(); - return listManagers.Count; + return _listManagers.Count; } } - /// - /// /// - /// /// Copies the elements of the collection into a specified array, starting /// at the collection index. - /// /// void ICollection.CopyTo(Array ar, int index) { ScrubWeakRefs(); - listManagers.CopyTo(ar, index); + _listManagers.CopyTo(ar, index); } - /// - /// /// - /// /// Gets an enumerator for the collection. - /// /// IEnumerator IEnumerable.GetEnumerator() { ScrubWeakRefs(); - return listManagers.GetEnumerator(); + return _listManagers.GetEnumerator(); } - /// - /// /// - /// - /// Gets a value indicating whether the collection is read-only. - /// + /// Gets a value indicating whether the collection is read-only. /// - public bool IsReadOnly { - get { - return false; - } - } + public bool IsReadOnly => false; - /// - /// /// - /// /// Gets a value indicating whether the collection is synchronized. - /// /// - bool ICollection.IsSynchronized { - get { - // so the user will know that it has to lock this object - return false; - } - } - - /// - /// - /// - /// Gets an object to use for synchronization (thread safety). - /// - object ICollection.SyncRoot { - get { - return null; - } - } + bool ICollection.IsSynchronized => false; - - /// /// - /// Initializes a new instance of the System.Windows.Forms.BindingContext class. + /// Gets an object to use for synchronization (thread safety). /// - public BindingContext() { - listManagers = new Hashtable(); - } + object ICollection.SyncRoot => null; - /// /// - /// - /// Gets the System.Windows.Forms.BindingManagerBase - /// associated with the specified data source. - /// + /// Gets the System.Windows.Forms.BindingManagerBase associated with the specified + /// data source. /// - public BindingManagerBase this[object dataSource] { - get { - return this[dataSource, ""]; - } - } + public BindingManagerBase this[object dataSource] => this[dataSource, string.Empty]; - /// /// - /// Gets the System.Windows.Forms.BindingManagerBase associated with the specified data source and - /// data member. + /// Gets the System.Windows.Forms.BindingManagerBase associated with the specified + /// data source and data member. /// - public BindingManagerBase this[object dataSource, string dataMember] { - get { - return EnsureListManager(dataSource, dataMember); - } + public BindingManagerBase this[object dataSource, string dataMember] + { + get => EnsureListManager(dataSource, dataMember); } - /// /// - /// Adds the listManager to the collection. An ArgumentNullException is thrown if this listManager - /// is null. An exception is thrown if a listManager to the same target and Property as an existing listManager or - /// if the listManager's column isn't a valid column given this DataSource.Table's schema. + /// Adds the listManager to the collection. An ArgumentNullException is thrown if this + /// listManager is null. An exception is thrown if a listManager to the same target + /// and Property as an existing listManager or if the listManager's column isn't a + /// valid column given this DataSource.Table's schema. /// Fires the CollectionChangedEvent. /// - internal protected void Add(object dataSource, BindingManagerBase listManager) { - /* !!THIS METHOD IS OBSOLETE AND UNUSED!! */ + /// + /// This method is obsolete and unused. + /// + internal protected void Add(object dataSource, BindingManagerBase listManager) + { AddCore(dataSource, listManager); OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, dataSource)); } - /// - /// - /// - protected virtual void AddCore(object dataSource, BindingManagerBase listManager) { - /* !!THIS METHOD IS OBSOLETE AND UNUSED!! */ + /// + /// This method is obsolete and unused. + /// + protected virtual void AddCore(object dataSource, BindingManagerBase listManager) + { if (dataSource == null) + { throw new ArgumentNullException(nameof(dataSource)); + } if (listManager == null) + { throw new ArgumentNullException(nameof(listManager)); + } - // listManagers[dataSource] = listManager; - listManagers[GetKey(dataSource, "")] = new WeakReference(listManager, false); + _listManagers[GetKey(dataSource, string.Empty)] = new WeakReference(listManager, false); } - - /// /// - /// - /// Occurs when the collection has changed. - /// + /// Occurs when the collection has changed. /// + /// + /// This method is obsolete and unused. + /// [SRDescription(nameof(SR.collectionChangedEventDescr)), EditorBrowsable(EditorBrowsableState.Never), Browsable(false)] - public event CollectionChangeEventHandler CollectionChanged { - /* !!THIS EVENT IS OBSOLETE AND UNUSED!! */ + public event CollectionChangeEventHandler CollectionChanged + { [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")] - add { + add + { throw new NotImplementedException(); } [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")] - remove { + remove + { } } - /// /// /// Clears the collection of any bindings. /// Fires the CollectionChangedEvent. /// - internal protected void Clear() { - /* !!THIS METHOD IS OBSOLETE AND UNUSED!! */ + /// + /// This method is obsolete and unused. + /// + internal protected void Clear() + { ClearCore(); OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, null)); } - /// /// - /// - /// Clears the collection. - /// + /// Clears the collection. /// - protected virtual void ClearCore() { - /* !!THIS METHOD IS OBSOLETE AND UNUSED!! */ - listManagers.Clear(); - } + /// + /// This method is obsolete and unused. + /// + protected virtual void ClearCore() => _listManagers.Clear(); - /// /// - /// Gets a value indicating whether the System.Windows.Forms.BindingContext - /// contains the specified - /// data source. + /// Gets a value indicating whether the System.Windows.Forms.BindingContext contains + /// the specified data source. /// - public bool Contains(object dataSource) { - return Contains(dataSource, ""); - } + public bool Contains(object dataSource) => Contains(dataSource, string.Empty); - /// /// - /// Gets a value indicating whether the System.Windows.Forms.BindingContext - /// contains the specified data source and data member. + /// Gets a value indicating whether the System.Windows.Forms.BindingContext + /// contains the specified data source and data member. /// - public bool Contains(object dataSource, string dataMember) { - return listManagers.ContainsKey(GetKey(dataSource, dataMember)); + public bool Contains(object dataSource, string dataMember) + { + return _listManagers.ContainsKey(GetKey(dataSource, dataMember)); } - internal HashKey GetKey(object dataSource, string dataMember) { + internal HashKey GetKey(object dataSource, string dataMember) + { return new HashKey(dataSource, dataMember); } - /// - /// - /// - /// - // - internal class HashKey { - WeakReference wRef; - int dataSourceHashCode; - string dataMember; + internal class HashKey + { + private WeakReference _wRef; + private int _dataSourceHashCode; + private string _dataMember; - internal HashKey(object dataSource, string dataMember) { + internal HashKey(object dataSource, string dataMember) + { if (dataSource == null) + { throw new ArgumentNullException(nameof(dataSource)); + } if (dataMember == null) - dataMember = ""; - // The dataMember should be case insensitive. - // so convert the dataMember to lower case - // - this.wRef = new WeakReference(dataSource, false); - this.dataSourceHashCode = dataSource.GetHashCode(); - this.dataMember = dataMember.ToLower(CultureInfo.InvariantCulture); - } + { + dataMember = string.Empty; + } - /// - /// - /// - /// - public override int GetHashCode() { - return dataSourceHashCode * dataMember.GetHashCode(); + // The dataMember should be case insensitive, so convert the + // dataMember to lower case + _wRef = new WeakReference(dataSource, false); + _dataSourceHashCode = dataSource.GetHashCode(); + _dataMember = dataMember.ToLower(CultureInfo.InvariantCulture); } - /// - /// - /// - /// - public override bool Equals(object target) { - if (target is HashKey) { - HashKey keyTarget = (HashKey)target; - return wRef.Target == keyTarget.wRef.Target && dataMember == keyTarget.dataMember; + public override int GetHashCode() => _dataSourceHashCode * _dataMember.GetHashCode(); + + public override bool Equals(object target) + { + if (!(target is HashKey keyTarget)) + { + return false; } - return false; + + return _wRef.Target == keyTarget._wRef.Target && _dataMember == keyTarget._dataMember; } } - /// - /// /// - /// This method is called whenever the collection changes. Overriders - /// of this method should call the base implementation of this method. - /// NOTE: This shipped in Everett, so we need to keep it, but we don't do - /// anything here. + /// This method is called whenever the collection changes. Overriders of this method + /// should call the base implementation of this method. /// - protected virtual void OnCollectionChanged(CollectionChangeEventArgs ccevent) { + protected virtual void OnCollectionChanged(CollectionChangeEventArgs ccevent) + { } - /// /// /// Removes the given listManager from the collection. - /// An ArgumentNullException is thrown if this listManager is null. An ArgumentException is thrown - /// if this listManager doesn't belong to this collection. + /// An ArgumentNullException is thrown if this listManager is null. An ArgumentException + /// is thrown if this listManager doesn't belong to this collection. /// The CollectionChanged event is fired if it succeeds. /// - internal protected void Remove(object dataSource) { - /* !!THIS METHOD IS OBSOLETE AND UNUSED!! */ + /// + /// This method is obsolete and unused. + /// + internal protected void Remove(object dataSource) + { RemoveCore(dataSource); OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, dataSource)); } - /// - /// - /// - /// - protected virtual void RemoveCore(object dataSource) { - /* !!THIS METHOD IS OBSOLETE AND UNUSED!! */ - listManagers.Remove(GetKey(dataSource, "")); + /// + /// This method is obsolete and unused. + /// + protected virtual void RemoveCore(object dataSource) + { + _listManagers.Remove(GetKey(dataSource, string.Empty)); } - /// /// - /// Create a suitable binding manager for the specified dataSource/dataMember combination. - /// - If one has already been created and cached by this BindingContext, return that instead. - /// - If the data source is an ICurrencyManagerProvider, just delegate to the data source. + /// Create a suitable binding manager for the specified dataSource/dataMember combination. + /// - If one has already been created and cached by this BindingContext, return that + /// instead. + /// - If the data source is an ICurrencyManagerProvider, just delegate to the data + /// source. /// - internal BindingManagerBase EnsureListManager(object dataSource, string dataMember) { + internal BindingManagerBase EnsureListManager(object dataSource, string dataMember) + { BindingManagerBase bindingManagerBase = null; if (dataMember == null) - dataMember = ""; + { + dataMember = string.Empty; + } // Check whether data source wants to provide its own binding managers // (but fall through to old logic if it fails to provide us with one) - // - if (dataSource is ICurrencyManagerProvider) { - bindingManagerBase = (dataSource as ICurrencyManagerProvider).GetRelatedCurrencyManager(dataMember); - - if (bindingManagerBase != null) { + if (dataSource is ICurrencyManagerProvider currencyManagerProvider) + { + bindingManagerBase = currencyManagerProvider.GetRelatedCurrencyManager(dataMember); + if (bindingManagerBase != null) + { return bindingManagerBase; } } // Check for previously created binding manager - // HashKey key = GetKey(dataSource, dataMember); - WeakReference wRef; - wRef = listManagers[key] as WeakReference; + WeakReference wRef = _listManagers[key] as WeakReference; if (wRef != null) - bindingManagerBase = (BindingManagerBase) wRef.Target; - if (bindingManagerBase != null) { + { + bindingManagerBase = (BindingManagerBase)wRef.Target; + } + if (bindingManagerBase != null) + { return bindingManagerBase; } - if (dataMember.Length == 0) { + if (dataMember.Length == 0) + { // No data member specified, so create binding manager directly on the data source - // - if (dataSource is IList || dataSource is IListSource) { + if (dataSource is IList || dataSource is IListSource) + { // IListSource so we can bind the dataGrid to a table and a dataSet bindingManagerBase = new CurrencyManager(dataSource); } - else { + else + { // Otherwise assume simple property binding bindingManagerBase = new PropertyManager(dataSource); } } - else { + else + { // Data member specified, so get data source's binding manager, and hook a 'related' binding manager to it - // - int lastDot = dataMember.LastIndexOf("."); - string dataPath = (lastDot == -1) ? "" : dataMember.Substring(0, lastDot); + int lastDot = dataMember.LastIndexOf("."); + string dataPath = (lastDot == -1) ? string.Empty : dataMember.Substring(0, lastDot); string dataField = dataMember.Substring(lastDot + 1); BindingManagerBase formerManager = EnsureListManager(dataSource, dataPath); PropertyDescriptor prop = formerManager.GetItemProperties().Find(dataField, true); if (prop == null) + { throw new ArgumentException(string.Format(SR.RelatedListManagerChild, dataField)); + } if (typeof(IList).IsAssignableFrom(prop.PropertyType)) + { bindingManagerBase = new RelatedCurrencyManager(formerManager, dataField); + } else + { bindingManagerBase = new RelatedPropertyManager(formerManager, dataField); + } } // if wRef == null, then it is the first time we want this bindingManagerBase: so add it // if wRef != null, then the bindingManagerBase was GC'ed at some point: keep the old wRef and change its target if (wRef == null) - listManagers.Add(key, new WeakReference(bindingManagerBase, false)); + { + _listManagers.Add(key, new WeakReference(bindingManagerBase, false)); + } else + { wRef.Target = bindingManagerBase; + } ScrubWeakRefs(); // Return the final binding manager return bindingManagerBase; } - // may throw - private static void CheckPropertyBindingCycles(BindingContext newBindingContext, Binding propBinding) { + private static void CheckPropertyBindingCycles(BindingContext newBindingContext, Binding propBinding) + { if (newBindingContext == null || propBinding == null) + { return; - if (newBindingContext.Contains(propBinding.BindableComponent, "")) { + } + + if (newBindingContext.Contains(propBinding.BindableComponent, string.Empty)) + { // this way we do not add a bindingManagerBase to the // bindingContext if there isn't one already - BindingManagerBase bindingManagerBase = newBindingContext.EnsureListManager(propBinding.BindableComponent, ""); - for (int i = 0; i < bindingManagerBase.Bindings.Count; i++) { + BindingManagerBase bindingManagerBase = newBindingContext.EnsureListManager(propBinding.BindableComponent, string.Empty); + for (int i = 0; i < bindingManagerBase.Bindings.Count; i++) + { Binding binding = bindingManagerBase.Bindings[i]; - if (binding.DataSource == propBinding.BindableComponent) { + if (binding.DataSource == propBinding.BindableComponent) + { if (propBinding.BindToObject.BindingMemberInfo.BindingMember.Equals(binding.PropertyName)) - throw new ArgumentException(string.Format(SR.DataBindingCycle, binding.PropertyName), "propBinding"); - } else if (propBinding.BindToObject.BindingManagerBase is PropertyManager) + { + throw new ArgumentException(string.Format(SR.DataBindingCycle, binding.PropertyName), nameof(propBinding)); + } + } + else if (propBinding.BindToObject.BindingManagerBase is PropertyManager) + { CheckPropertyBindingCycles(newBindingContext, binding); + } } } } - private void ScrubWeakRefs() { + private void ScrubWeakRefs() + { ArrayList cleanupList = null; - foreach (DictionaryEntry de in listManagers) { - WeakReference wRef = (WeakReference) de.Value; - if (wRef.Target == null) { - if (cleanupList == null) { + foreach (DictionaryEntry de in _listManagers) + { + WeakReference wRef = (WeakReference)de.Value; + if (wRef.Target == null) + { + if (cleanupList == null) + { cleanupList = new ArrayList(); } cleanupList.Add(de.Key); } } - if (cleanupList != null) { - foreach (object o in cleanupList) { - listManagers.Remove(o); + if (cleanupList != null) + { + foreach (object o in cleanupList) + { + _listManagers.Remove(o); } } } - /// /// - /// Associates a Binding with a different BindingContext. Intended for use by components that support - /// IBindableComponent, to update their Bindings when the value of IBindableComponent.BindingContext - /// is changed. + /// Associates a Binding with a different BindingContext. Intended for use by components + /// that support IBindableComponent, to update their Bindings when the value of + /// IBindableComponent.BindingContext is changed. /// - public static void UpdateBinding(BindingContext newBindingContext, Binding binding) { + public static void UpdateBinding(BindingContext newBindingContext, Binding binding) + { + if (binding == null) + { + throw new ArgumentNullException(nameof(binding)); + } + BindingManagerBase oldManager = binding.BindingManagerBase; - if (oldManager != null) { + if (oldManager != null) + { oldManager.Bindings.Remove(binding); } - if (newBindingContext != null) { + if (newBindingContext != null) + { // we need to first check for cycles before adding this binding to the collection // of bindings. if (binding.BindToObject.BindingManagerBase is PropertyManager) + { CheckPropertyBindingCycles(newBindingContext, binding); + } BindToObject bindTo = binding.BindToObject; BindingManagerBase newManager = newBindingContext.EnsureListManager(bindTo.DataSource, bindTo.BindingMemberInfo.BindingPath); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/BindingMAnagerBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/BindingMAnagerBase.cs deleted file mode 100644 index 4f8ff3a90cf..00000000000 --- a/src/System.Windows.Forms/src/System/Windows/Forms/BindingMAnagerBase.cs +++ /dev/null @@ -1,370 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Windows.Forms { - using System; - using System.Windows.Forms; - using System.ComponentModel; - using System.Collections; - using System.Diagnostics.CodeAnalysis; - - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors")] // Shipped in Everett - public abstract class BindingManagerBase - { - private BindingsCollection bindings; - private bool pullingData = false; - - /// - protected EventHandler onCurrentChangedHandler; - - /// - protected EventHandler onPositionChangedHandler; - - // Hook BindingComplete events on all owned Binding objects, and propagate those events through our own BindingComplete event - private BindingCompleteEventHandler onBindingCompleteHandler = null; - - // same deal about the new currentItemChanged event - internal EventHandler onCurrentItemChangedHandler; - - // Event handler for the DataError event - internal BindingManagerDataErrorEventHandler onDataErrorHandler; - - /// - public BindingsCollection Bindings { - get { - if (bindings == null) { - bindings = new ListManagerBindingsCollection(this); - - // Hook collection change events on collection, so we can hook or unhook the BindingComplete events on individual bindings - bindings.CollectionChanging += new CollectionChangeEventHandler(OnBindingsCollectionChanging); - bindings.CollectionChanged += new CollectionChangeEventHandler(OnBindingsCollectionChanged); - } - - return bindings; - } - } - - /// - internal protected void OnBindingComplete(BindingCompleteEventArgs args) { - if (onBindingCompleteHandler != null) { - onBindingCompleteHandler(this, args); - } - } - - /// - internal protected abstract void OnCurrentChanged(EventArgs e); - - /// - internal protected abstract void OnCurrentItemChanged(EventArgs e); - - /// - internal protected void OnDataError(Exception e) { - if (onDataErrorHandler != null) { - onDataErrorHandler(this, new BindingManagerDataErrorEventArgs(e)); - } - } - - /// - public abstract object Current { - get; - } - - internal abstract void SetDataSource(object dataSource); - - /// - public BindingManagerBase() { } - - [ - SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors") // If the constructor does not call SetDataSource - // it would be a breaking change. - ] - internal BindingManagerBase(object dataSource) { - this.SetDataSource(dataSource); - } - - internal abstract Type BindType{ - get; - } - - internal abstract PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors); - - /// - public virtual PropertyDescriptorCollection GetItemProperties() { - return GetItemProperties(null); - } - - /// - protected internal virtual PropertyDescriptorCollection GetItemProperties(ArrayList dataSources, ArrayList listAccessors) { - IList list = null; - if (this is CurrencyManager) { - list = ((CurrencyManager)this).List; - } - if (list is ITypedList) { - PropertyDescriptor[] properties = new PropertyDescriptor[listAccessors.Count]; - listAccessors.CopyTo(properties, 0); - return ((ITypedList)list).GetItemProperties(properties); - } - return this.GetItemProperties(this.BindType, 0, dataSources, listAccessors); - } - - // listType is the type of the top list in the list.list.list.list reference - // offset is how far we are in the listAccessors - // listAccessors is the list of accessors (duh) - // - /// - protected virtual PropertyDescriptorCollection GetItemProperties(Type listType, int offset, ArrayList dataSources, ArrayList listAccessors) { - if (listAccessors.Count < offset) - return null; - - if (listAccessors.Count == offset) { - if (typeof(IList).IsAssignableFrom(listType)) { - System.Reflection.PropertyInfo[] itemProps = listType.GetProperties(); - // PropertyDescriptorCollection itemProps = TypeDescriptor.GetProperties(listType); - for (int i = 0; i < itemProps.Length; i ++) { - if ("Item".Equals(itemProps[i].Name) && itemProps[i].PropertyType != typeof(object)) - return TypeDescriptor.GetProperties(itemProps[i].PropertyType, new Attribute[] {new BrowsableAttribute(true)}); - } - // return the properties on the type of the first element in the list - IList list = dataSources[offset - 1] as IList; - if (list != null && list.Count > 0) - return TypeDescriptor.GetProperties(list[0]); - } else { - return TypeDescriptor.GetProperties(listType); - } - return null; - } - - System.Reflection.PropertyInfo[] props = listType.GetProperties(); - // PropertyDescriptorCollection props = TypeDescriptor.GetProperties(listType); - if (typeof(IList).IsAssignableFrom(listType)) { - PropertyDescriptorCollection itemProps = null; - for (int i = 0; i < props.Length; i++) { - if ("Item".Equals(props[i].Name) && props[i].PropertyType != typeof(object)) { - // get all the properties that are not marked as Browsable(false) - // - itemProps = TypeDescriptor.GetProperties(props[i].PropertyType, new Attribute[] {new BrowsableAttribute(true)}); - } - } - - if (itemProps == null) { - // use the properties on the type of the first element in the list - // if offset == 0, then this means that the first dataSource did not have a strongly typed Item property. - // the dataSources are added only for relatedCurrencyManagers, so in this particular case - // we need to use the dataSource in the currencyManager. - IList list; - if (offset == 0) - list = this.DataSource as IList; - else - list = dataSources[offset - 1] as IList; - if (list != null && list.Count > 0) { - itemProps = TypeDescriptor.GetProperties(list[0]); - } - } - - if (itemProps != null) { - for (int j=0; j - public event BindingCompleteEventHandler BindingComplete { - add { - onBindingCompleteHandler += value; - } - remove { - onBindingCompleteHandler -= value; - } - } - - /// - public event EventHandler CurrentChanged { - add { - onCurrentChangedHandler += value; - } - remove { - onCurrentChangedHandler -= value; - } - } - - /// - public event EventHandler CurrentItemChanged { - add { - onCurrentItemChangedHandler += value; - } - remove { - onCurrentItemChangedHandler -= value; - } - } - - /// - public event BindingManagerDataErrorEventHandler DataError { - add { - onDataErrorHandler += value; - } - remove { - onDataErrorHandler -= value; - } - } - - internal abstract string GetListName(); - /// - public abstract void CancelCurrentEdit(); - /// - public abstract void EndCurrentEdit(); - - /// - public abstract void AddNew(); - /// - public abstract void RemoveAt(int index); - - /// - public abstract int Position{get; set;} - - /// - public event EventHandler PositionChanged { - add { - this.onPositionChangedHandler += value; - } - remove { - this.onPositionChangedHandler -= value; - } - } - /// - protected abstract void UpdateIsBinding(); - - /// - protected internal abstract string GetListName(ArrayList listAccessors); - - /// - public abstract void SuspendBinding(); - - /// - public abstract void ResumeBinding(); - - /// - protected void PullData() { - bool success; - PullData(out success); - } - - /// - internal void PullData(out bool success) { - success = true; - pullingData = true; - - try { - UpdateIsBinding(); - - int numLinks = Bindings.Count; - for (int i = 0; i < numLinks; i++) { - if (Bindings[i].PullData()) { - success = false; - } - } - } - finally { - pullingData = false; - } - } - - /// - protected void PushData() { - bool success; - PushData(out success); - } - - /// - internal void PushData(out bool success) { - success = true; - - if (pullingData) - return; - - UpdateIsBinding(); - - int numLinks = Bindings.Count; - for (int i = 0; i < numLinks; i++) { - if (Bindings[i].PushData()) { - success = false; - } - } - } - - internal abstract object DataSource { - get; - } - - internal abstract bool IsBinding { - get; - } - - /// - /// - /// - public bool IsBindingSuspended { - get { - return !IsBinding; - } - } - - /// - public abstract int Count { - get; - } - - // BindingComplete events on individual Bindings are propagated up through the BindingComplete event on - // the owning BindingManagerBase. To do this, we have to track changes to the bindings collection, adding - // or removing handlers on items in the collection as appropriate. - // - // For the Add and Remove cases, we hook the collection 'changed' event, and add or remove handler for - // specific binding. - // - // For the Refresh case, we hook both the 'changing' and 'changed' events, removing handlers for all - // items that were in the collection before the change, then adding handlers for whatever items are - // in the collection after the change. - // - private void OnBindingsCollectionChanged(object sender, CollectionChangeEventArgs e) { - Binding b = e.Element as Binding; - - switch (e.Action) { - case CollectionChangeAction.Add: - b.BindingComplete += new BindingCompleteEventHandler(Binding_BindingComplete); - break; - case CollectionChangeAction.Remove: - b.BindingComplete -= new BindingCompleteEventHandler(Binding_BindingComplete); - break; - case CollectionChangeAction.Refresh: - foreach (Binding bi in bindings) { - bi.BindingComplete += new BindingCompleteEventHandler(Binding_BindingComplete); - } - break; - } - } - - private void OnBindingsCollectionChanging(object sender, CollectionChangeEventArgs e) { - if (e.Action == CollectionChangeAction.Refresh) { - foreach (Binding bi in bindings) { - bi.BindingComplete -= new BindingCompleteEventHandler(Binding_BindingComplete); - } - } - } - - internal void Binding_BindingComplete(object sender, BindingCompleteEventArgs args) { - this.OnBindingComplete(args); - } - - } -} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/BindingManagerBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/BindingManagerBase.cs new file mode 100644 index 00000000000..d3d5221299a --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/BindingManagerBase.cs @@ -0,0 +1,341 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +namespace System.Windows.Forms +{ + [SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors", Justification = "Changing this would be a breaking change")] + public abstract class BindingManagerBase + { + private BindingsCollection _bindings; + private bool _pullingData = false; + + protected EventHandler onCurrentChangedHandler; // Don't rename (breaking change) + + protected EventHandler onPositionChangedHandler; // Don't rename (breaking change) + + // Hook BindingComplete events on all owned Binding objects, and propagate those events through our own BindingComplete event + private BindingCompleteEventHandler _onBindingCompleteHandler = null; + + // same deal about the new currentItemChanged event + private protected EventHandler _onCurrentItemChangedHandler; + + // Event handler for the DataError event + private BindingManagerDataErrorEventHandler _onDataErrorHandler; + + public BindingsCollection Bindings + { + get + { + if (_bindings == null) + { + _bindings = new ListManagerBindingsCollection(this); + + // Hook collection change events on collection, so we can hook or unhook the BindingComplete events on individual bindings + _bindings.CollectionChanging += new CollectionChangeEventHandler(OnBindingsCollectionChanging); + _bindings.CollectionChanged += new CollectionChangeEventHandler(OnBindingsCollectionChanged); + } + + return _bindings; + } + } + + protected internal void OnBindingComplete(BindingCompleteEventArgs args) + { + _onBindingCompleteHandler?.Invoke(this, args); + } + + protected internal abstract void OnCurrentChanged(EventArgs e); + + protected internal abstract void OnCurrentItemChanged(EventArgs e); + + protected internal void OnDataError(Exception e) + { + _onDataErrorHandler?.Invoke(this, new BindingManagerDataErrorEventArgs(e)); + } + + public abstract object Current { get; } + + private protected abstract void SetDataSource(object dataSource); + + public BindingManagerBase() { } + + [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "Changing this would be a breaking change")] + internal BindingManagerBase(object dataSource) + { + SetDataSource(dataSource); + } + + internal abstract Type BindType { get; } + + internal abstract PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors); + + public virtual PropertyDescriptorCollection GetItemProperties() => GetItemProperties(null); + + protected internal virtual PropertyDescriptorCollection GetItemProperties(ArrayList dataSources, ArrayList listAccessors) + { + IList list = null; + if (this is CurrencyManager currencyManager) + { + list = currencyManager.List; + } + if (list is ITypedList typedList) + { + PropertyDescriptor[] properties = new PropertyDescriptor[listAccessors.Count]; + listAccessors.CopyTo(properties, 0); + return typedList.GetItemProperties(properties); + } + + return GetItemProperties(BindType, 0, dataSources, listAccessors); + } + + protected virtual PropertyDescriptorCollection GetItemProperties(Type listType, int offset, ArrayList dataSources, ArrayList listAccessors) + { + if (listAccessors.Count < offset) + { + return null; + } + + if (listAccessors.Count == offset) + { + if (!typeof(IList).IsAssignableFrom(listType)) + { + return TypeDescriptor.GetProperties(listType); + } + + foreach (PropertyInfo property in listType.GetProperties()) + { + if (property.Name == "Item" && property.PropertyType != typeof(object)) + { + return TypeDescriptor.GetProperties(property.PropertyType, new Attribute[] { new BrowsableAttribute(true) }); + } + } + + // return the properties on the type of the first element in the list + if (dataSources[offset - 1] is IList list && list.Count > 0) + { + return TypeDescriptor.GetProperties(list[0]); + } + + return null; + } + + if (typeof(IList).IsAssignableFrom(listType)) + { + PropertyDescriptorCollection itemProps = null; + foreach (PropertyInfo property in listType.GetProperties()) + { + if (property.Name == "Item" && property.PropertyType != typeof(object)) + { + // get all the properties that are not marked as Browsable(false) + itemProps = TypeDescriptor.GetProperties(property.PropertyType, new Attribute[] { new BrowsableAttribute(true) }); + } + } + + if (itemProps == null) + { + // Use the properties on the type of the first element in the list + // if offset == 0, then this means that the first dataSource did not have a strongly typed Item property. + // the dataSources are added only for relatedCurrencyManagers, so in this particular case + // we need to use the dataSource in the currencyManager. + IList list; + if (offset == 0) + { + list = DataSource as IList; + } + else + { + list = dataSources[offset - 1] as IList; + } + if (list != null && list.Count > 0) + { + itemProps = TypeDescriptor.GetProperties(list[0]); + } + } + + if (itemProps != null) + { + for (int j = 0; j < itemProps.Count; j++) + { + if (itemProps[j].Equals(listAccessors[offset])) + { + return GetItemProperties(itemProps[j].PropertyType, offset + 1, dataSources, listAccessors); + } + } + } + + } + else + { + foreach (PropertyInfo property in listType.GetProperties()) + { + if (property.Name.Equals(((PropertyDescriptor)listAccessors[offset]).Name)) + { + return GetItemProperties(property.PropertyType, offset + 1, dataSources, listAccessors); + } + } + } + + return null; + } + + public event BindingCompleteEventHandler BindingComplete + { + add => _onBindingCompleteHandler += value; + remove => _onBindingCompleteHandler -= value; + } + + public event EventHandler CurrentChanged + { + add => onCurrentChangedHandler += value; + remove => onCurrentChangedHandler -= value; + } + + public event EventHandler CurrentItemChanged + { + add => _onCurrentItemChangedHandler += value; + remove => _onCurrentItemChangedHandler -= value; + } + + public event BindingManagerDataErrorEventHandler DataError + { + add => _onDataErrorHandler += value; + remove => _onDataErrorHandler -= value; + } + + internal abstract string GetListName(); + public abstract void CancelCurrentEdit(); + public abstract void EndCurrentEdit(); + + public abstract void AddNew(); + public abstract void RemoveAt(int index); + + public abstract int Position { get; set; } + + public event EventHandler PositionChanged + { + add + { + onPositionChangedHandler += value; + } + remove + { + onPositionChangedHandler -= value; + } + } + + protected abstract void UpdateIsBinding(); + + protected internal abstract string GetListName(ArrayList listAccessors); + + public abstract void SuspendBinding(); + + public abstract void ResumeBinding(); + + protected void PullData() => PullData(out _); + + internal void PullData(out bool success) + { + success = true; + _pullingData = true; + + try + { + UpdateIsBinding(); + + int numLinks = Bindings.Count; + for (int i = 0; i < numLinks; i++) + { + if (Bindings[i].PullData()) + { + success = false; + } + } + } + finally + { + _pullingData = false; + } + } + + protected void PushData() + { + if (_pullingData) + { + return; + } + + UpdateIsBinding(); + + int numLinks = Bindings.Count; + for (int i = 0; i < numLinks; i++) + { + Bindings[i].PushData(); + } + } + + internal abstract object DataSource { get; } + + internal abstract bool IsBinding { get; } + + public bool IsBindingSuspended => !IsBinding; + + public abstract int Count { get; } + + /// + /// BindingComplete events on individual Bindings are propagated up through the BindingComplete event on + /// the owning BindingManagerBase. To do this, we have to track changes to the bindings collection, adding + /// or removing handlers on items in the collection as appropriate. + /// + /// For the Add and Remove cases, we hook the collection 'changed' event, and add or remove handler for + /// specific binding. + /// + /// For the Refresh case, we hook both the 'changing' and 'changed' events, removing handlers for all + /// items that were in the collection before the change, then adding handlers for whatever items are + /// in the collection after the change. + /// + private void OnBindingsCollectionChanged(object sender, CollectionChangeEventArgs e) + { + Binding b = e.Element as Binding; + + switch (e.Action) + { + case CollectionChangeAction.Add: + b.BindingComplete += new BindingCompleteEventHandler(Binding_BindingComplete); + break; + case CollectionChangeAction.Remove: + b.BindingComplete -= new BindingCompleteEventHandler(Binding_BindingComplete); + break; + case CollectionChangeAction.Refresh: + foreach (Binding bi in _bindings) + { + bi.BindingComplete += new BindingCompleteEventHandler(Binding_BindingComplete); + } + break; + } + } + + private void OnBindingsCollectionChanging(object sender, CollectionChangeEventArgs e) + { + if (e.Action != CollectionChangeAction.Refresh) + { + return; + } + + foreach (Binding bi in _bindings) + { + bi.BindingComplete -= new BindingCompleteEventHandler(Binding_BindingComplete); + } + } + + private void Binding_BindingComplete(object sender, BindingCompleteEventArgs args) + { + OnBindingComplete(args); + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/BindingMemberInfo.cs b/src/System.Windows.Forms/src/System/Windows/Forms/BindingMemberInfo.cs index 50601463405..7724b953cbf 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/BindingMemberInfo.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/BindingMemberInfo.cs @@ -29,9 +29,9 @@ public BindingMemberInfo(string dataMember) } } - public string BindingPath => _dataList != null ? _dataList : string.Empty; + public string BindingPath => _dataList ?? string.Empty; - public string BindingField => _dataField != null ? _dataField : string.Empty; + public string BindingField => _dataField ?? string.Empty; public string BindingMember { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/BindingNavigator.cs b/src/System.Windows.Forms/src/System/Windows/Forms/BindingNavigator.cs index fd2fbbe6a9b..0c09da594a4 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/BindingNavigator.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/BindingNavigator.cs @@ -186,19 +186,13 @@ public virtual void AddStandardItems() { // Set up images // - Bitmap moveFirstImage = new Bitmap(typeof(BindingNavigator), "BindingNavigator.MoveFirst.bmp"); - Bitmap movePreviousImage = new Bitmap(typeof(BindingNavigator), "BindingNavigator.MovePrevious.bmp"); - Bitmap moveNextImage = new Bitmap(typeof(BindingNavigator), "BindingNavigator.MoveNext.bmp"); - Bitmap moveLastImage = new Bitmap(typeof(BindingNavigator), "BindingNavigator.MoveLast.bmp"); - Bitmap addNewImage = new Bitmap(typeof(BindingNavigator), "BindingNavigator.AddNew.bmp"); - Bitmap deleteImage = new Bitmap(typeof(BindingNavigator), "BindingNavigator.Delete.bmp"); - - moveFirstImage.MakeTransparent(System.Drawing.Color.Magenta); - movePreviousImage.MakeTransparent(System.Drawing.Color.Magenta); - moveNextImage.MakeTransparent(System.Drawing.Color.Magenta); - moveLastImage.MakeTransparent(System.Drawing.Color.Magenta); - addNewImage.MakeTransparent(System.Drawing.Color.Magenta); - deleteImage.MakeTransparent(System.Drawing.Color.Magenta); + Bitmap moveFirstImage = DpiHelper.GetBitmapFromIcon(typeof(BindingNavigator), "BindingNavigator.MoveFirst"); + Bitmap movePreviousImage = DpiHelper.GetBitmapFromIcon(typeof(BindingNavigator), "BindingNavigator.MovePrevious"); + Bitmap moveNextImage = DpiHelper.GetBitmapFromIcon(typeof(BindingNavigator), "BindingNavigator.MoveNext"); + Bitmap moveLastImage = DpiHelper.GetBitmapFromIcon(typeof(BindingNavigator), "BindingNavigator.MoveLast"); + Bitmap addNewImage = DpiHelper.GetBitmapFromIcon(typeof(BindingNavigator), "BindingNavigator.AddNew"); + Bitmap deleteImage = DpiHelper.GetBitmapFromIcon(typeof(BindingNavigator), "BindingNavigator.Delete"); + MoveFirstItem.Image = moveFirstImage; MovePreviousItem.Image = movePreviousImage; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Button.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Button.cs index 08538185d48..28cf9d50d64 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Button.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Button.cs @@ -392,7 +392,7 @@ public override string ToString() { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_COMMAND: if (NativeMethods.Util.HIWORD(m.WParam) == NativeMethods.BN_CLICKED) { Debug.Assert(!GetStyle(ControlStyles.UserPaint), "Shouldn't get BN_CLICKED when UserPaint"); if (!ValidationCancelled) { @@ -400,7 +400,7 @@ protected override void WndProc(ref Message m) { } } break; - case NativeMethods.WM_ERASEBKGND: + case Interop.WindowMessages.WM_ERASEBKGND: DefWndProc(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonBase.cs index accfbaa69a5..f83a62e5a65 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonBase.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonBase.cs @@ -406,7 +406,7 @@ public int ImageIndex { } set { if (value < -1) { - throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "ImageIndex", (value).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); } if (imageIndex.Index != value) { if (value != -1) { @@ -666,22 +666,22 @@ public virtual ContentAlignment TextAlign { } } - /// - [ - DefaultValue(TextImageRelation.Overlay), - Localizable(true), - SRDescription(nameof(SR.ButtonTextImageRelationDescr)), - SRCategory(nameof(SR.CatAppearance)) - ] - public TextImageRelation TextImageRelation { - get { - return textImageRelation; - } - set { - if (!WindowsFormsUtils.EnumValidator.IsValidTextImageRelation(value)) { + [DefaultValue(TextImageRelation.Overlay)] + [Localizable(true)] + [SRDescription(nameof(SR.ButtonTextImageRelationDescr))] + [SRCategory(nameof(SR.CatAppearance))] + public TextImageRelation TextImageRelation + { + get => textImageRelation; + set + { + if (!ClientUtils.IsEnumValid(value, (int)value, (int)TextImageRelation.Overlay, (int)TextImageRelation.TextBeforeImage,1)) + { throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(TextImageRelation)); } - if(value != TextImageRelation) { + + if(value != TextImageRelation) + { textImageRelation = value; LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.TextImageRelation); Invalidate(); @@ -1246,9 +1246,9 @@ protected override void WndProc(ref Message m) { // things, even though we are ownerdraw. break; - case NativeMethods.WM_KILLFOCUS: - case NativeMethods.WM_CANCELMODE: - case NativeMethods.WM_CAPTURECHANGED: + case Interop.WindowMessages.WM_KILLFOCUS: + case Interop.WindowMessages.WM_CANCELMODE: + case Interop.WindowMessages.WM_CAPTURECHANGED: if (!GetFlag(FlagInButtonUp) && GetFlag(FlagMousePressed)) { SetFlag(FlagMousePressed, false); @@ -1260,9 +1260,9 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); break; - case NativeMethods.WM_LBUTTONUP: - case NativeMethods.WM_MBUTTONUP: - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: try { SetFlag(FlagInButtonUp, true); base.WndProc(ref m); @@ -1279,7 +1279,7 @@ protected override void WndProc(ref Message m) { } else { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_COMMAND: if (NativeMethods.Util.HIWORD(m.WParam) == NativeMethods.BN_CLICKED && !ValidationCancelled) { OnClick(EventArgs.Empty); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonBaseAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonBaseAdapter.cs index daa7e81bc59..b7cc5031eaf 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonBaseAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonBaseAdapter.cs @@ -71,21 +71,6 @@ internal virtual Size GetPreferredSizeCore(Size proposedSize) { [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsHighContrastHighlighted() { - return AccessibilityImprovements.Level1 && IsHighContrastHighlightedInternal(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool IsHighContrastHighlighted2() { - return AccessibilityImprovements.Level2 && IsHighContrastHighlightedInternal(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool IsHighContrastHighlighted3() { - return AccessibilityImprovements.Level3 && IsHighContrastHighlightedInternal(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool IsHighContrastHighlightedInternal() { return SystemInformation.HighContrast && Application.RenderWithVisualStyles && (Control.Focused || Control.MouseIsOver || (Control.IsDefault && Control.Enabled)); } @@ -169,7 +154,7 @@ protected void Draw3DBorder(Graphics g, Rectangle bounds, ColorData colors, bool private void Draw3DBorderHighContrastRaised(Graphics g, ref Rectangle bounds, ColorData colors) { bool stockColor = colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor(); - bool disabledHighContrast = (!Control.Enabled) && SystemInformation.HighContrast && AccessibilityImprovements.Level1; + bool disabledHighContrast = (!Control.Enabled) && SystemInformation.HighContrast; using ( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { @@ -333,7 +318,7 @@ private void Draw3DBorderNormal(Graphics g, ref Rectangle bounds, ColorData colo private void Draw3DBorderRaised(Graphics g, ref Rectangle bounds, ColorData colors) { bool stockColor = colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor(); - bool disabledHighContrast = (!Control.Enabled) && SystemInformation.HighContrast && AccessibilityImprovements.Level1; + bool disabledHighContrast = (!Control.Enabled) && SystemInformation.HighContrast; using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { @@ -622,8 +607,7 @@ void DrawText(Graphics g, LayoutData layout, Color c, ColorData colors) r.X -= 1; } r.Width += 1; - if (disabledText3D && !Control.Enabled && - (!AccessibilityImprovements.Level1 || (!colors.options.highContrast && AccessibilityImprovements.Level1))) { + if (disabledText3D && !Control.Enabled && !colors.options.highContrast) { using (SolidBrush brush = new SolidBrush(colors.highlight)) { r.Offset(1, 1); g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); @@ -652,7 +636,7 @@ void DrawText(Graphics g, LayoutData layout, Color c, ColorData colors) } else { // Draw text using GDI (Whidbey+ feature). TextFormatFlags formatFlags = CreateTextFormatFlags(); - if (disabledText3D && !Control.Enabled && (!AccessibilityImprovements.Level1 || (!colors.options.highContrast && AccessibilityImprovements.Level1))) { + if (disabledText3D && !Control.Enabled && !colors.options.highContrast) { if (Application.RenderWithVisualStyles) { //don't draw chiseled text if themed as win32 app does. TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.buttonShadow, formatFlags); @@ -760,7 +744,7 @@ internal ColorData Calculate() { colors.highlight = ControlPaint.LightLight(backColor); } } - colors.windowDisabled = (highContrast && AccessibilityImprovements.Level1) ? SystemColors.GrayText : colors.buttonShadow; + colors.windowDisabled = highContrast ? SystemColors.GrayText : colors.buttonShadow; const float lowlight = .1f; float adjust = 1 - lowlight; @@ -805,7 +789,7 @@ internal ColorData Calculate() { if (!enabled) { colors.windowText = colors.windowDisabled; - if (highContrast && AccessibilityImprovements.Level1) { + if (highContrast) { colors.windowFrame = colors.windowDisabled; colors.buttonShadow = colors.windowDisabled; } @@ -979,7 +963,7 @@ private int xCompose(Composition composition, int checkSize, int imageSize, int case Composition.AllCombined: return Math.Max(Math.Max(checkSize, imageSize), textSize); default: - Debug.Fail(string.Format(SR.InvalidArgument, "composition", composition.ToString())); + Debug.Fail(string.Format(SR.InvalidArgument, nameof(composition), composition.ToString())); return -7107; } } @@ -1006,7 +990,7 @@ private int xDecompose(Composition composition, int checkSize, int imageSize, in case Composition.AllCombined: return proposedSize; default: - Debug.Fail(string.Format(SR.InvalidArgument, "composition", composition.ToString())); + Debug.Fail(string.Format(SR.InvalidArgument, nameof(composition), composition.ToString())); return -7109; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonFlatAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonFlatAdapter.cs index d7f999541ee..c25df63eaee 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonFlatAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonFlatAdapter.cs @@ -69,14 +69,14 @@ internal override void PaintUp(PaintEventArgs e, CheckState state) { } } - PaintBackground(e, r, IsHighContrastHighlighted2() ? SystemColors.Highlight : backColor); + PaintBackground(e, r, IsHighContrastHighlighted() ? SystemColors.Highlight : backColor); if (Control.IsDefault) { r.Inflate(-1, -1); } PaintImage(e, layout); - PaintField(e, layout, colors, IsHighContrastHighlighted2() ? SystemColors.HighlightText : colors.windowText, false); + PaintField(e, layout, colors, IsHighContrastHighlighted() ? SystemColors.HighlightText : colors.windowText, false); if (Control.Focused && Control.ShowFocusCues) { DrawFlatFocus(g, layout.focus, colors.options.highContrast ? colors.windowText : colors.constrastButtonShadow); @@ -228,14 +228,14 @@ internal override void PaintOver(PaintEventArgs e, CheckState state) { } } - PaintBackground(e, r, IsHighContrastHighlighted2() ? SystemColors.Highlight : backColor); + PaintBackground(e, r, IsHighContrastHighlighted() ? SystemColors.Highlight : backColor); if (Control.IsDefault) { r.Inflate(-1, -1); } PaintImage(e, layout); - PaintField(e, layout, colors, IsHighContrastHighlighted2() ? SystemColors.HighlightText : colors.windowText, false); + PaintField(e, layout, colors, IsHighContrastHighlighted() ? SystemColors.HighlightText : colors.windowText, false); if (Control.Focused && Control.ShowFocusCues) { DrawFlatFocus(g, layout.focus, colors.constrastButtonShadow); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonPopupAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonPopupAdapter.cs index ee53f03b814..3752e910bb9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonPopupAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonPopupAdapter.cs @@ -38,7 +38,7 @@ internal override void PaintUp(PaintEventArgs e, CheckState state) { } } else { - Control.PaintBackground(e, r, IsHighContrastHighlighted2() ? SystemColors.Highlight : Control.BackColor, r.Location); + Control.PaintBackground(e, r, IsHighContrastHighlighted() ? SystemColors.Highlight : Control.BackColor, r.Location); } if (Control.IsDefault) { @@ -46,7 +46,7 @@ internal override void PaintUp(PaintEventArgs e, CheckState state) { } PaintImage(e, layout); - PaintField(e, layout, colors, state != CheckState.Indeterminate && IsHighContrastHighlighted2() ? SystemColors.HighlightText : colors.windowText, true); + PaintField(e, layout, colors, state != CheckState.Indeterminate && IsHighContrastHighlighted() ? SystemColors.HighlightText : colors.windowText, true); DrawDefaultBorder(g, r, colors.options.highContrast ? colors.windowText : colors.buttonShadow, this.Control.IsDefault); @@ -78,7 +78,7 @@ internal override void PaintOver(PaintEventArgs e, CheckState state) { } } else { - Control.PaintBackground(e, r, IsHighContrastHighlighted2() ? SystemColors.Highlight : Control.BackColor, r.Location); + Control.PaintBackground(e, r, IsHighContrastHighlighted() ? SystemColors.Highlight : Control.BackColor, r.Location); } if (Control.IsDefault) { @@ -86,7 +86,7 @@ internal override void PaintOver(PaintEventArgs e, CheckState state) { } PaintImage(e, layout); - PaintField(e, layout, colors, IsHighContrastHighlighted2() ? SystemColors.HighlightText : colors.windowText, true); + PaintField(e, layout, colors, IsHighContrastHighlighted() ? SystemColors.HighlightText : colors.windowText, true); DrawDefaultBorder(g, r, colors.options.highContrast ? colors.windowText : colors.buttonShadow, this.Control.IsDefault); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonStandardAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonStandardAdapter.cs index f81f64b759c..bcf517f5232 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonStandardAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/ButtonStandardAdapter.cs @@ -176,7 +176,7 @@ void PaintWorker(PaintEventArgs e, bool up, CheckState state) { layout.focus.Inflate(1, 1); } - if (up & IsHighContrastHighlighted2()) { + if (up & IsHighContrastHighlighted()) { var highlightTextColor = SystemColors.HighlightText; PaintField(e, layout, colors, highlightTextColor, false); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxBaseAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxBaseAdapter.cs index c4e6d79946d..b8b4e76bbfa 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxBaseAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxBaseAdapter.cs @@ -273,7 +273,7 @@ private static Bitmap GetCheckBoxImage(Color checkColor, Rectangle fullSize, ref } protected void AdjustFocusRectangle(LayoutData layout) { - if (AccessibilityImprovements.Level2 && string.IsNullOrEmpty(Control.Text)) { + if (string.IsNullOrEmpty(Control.Text)) { // When a CheckBox has no text, AutoSize sets the size to zero // and thus there's no place around which to draw the focus rectangle. // So, when AutoSize == true we want the focus rectangle to be rendered inside the box. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxPopupAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxPopupAdapter.cs index dde2d5c0700..7726504239b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxPopupAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxPopupAdapter.cs @@ -35,7 +35,7 @@ internal override void PaintUp(PaintEventArgs e, CheckState state) { DrawCheckBackground(e, layout.checkBounds, colors.windowText, colors.options.highContrast ? colors.buttonFace : colors.highlight, true, colors); DrawFlatBorder(e.Graphics, layout.checkBounds, - (colors.options.highContrast && !Control.Enabled && AccessibilityImprovements.Level1) ? colors.windowFrame : colors.buttonShadow); + (colors.options.highContrast && !Control.Enabled) ? colors.windowFrame : colors.buttonShadow); DrawCheckOnly(e, layout, colors, colors.windowText, colors.highlight); AdjustFocusRectangle(layout); @@ -62,7 +62,7 @@ internal override void PaintOver(PaintEventArgs e, CheckState state) { DrawPopupBorder(g, layout.checkBounds, colors); DrawCheckOnly(e, layout, colors, colors.windowText, colors.highlight); - if (!AccessibilityImprovements.Level2 || !string.IsNullOrEmpty(Control.Text)) { + if (!string.IsNullOrEmpty(Control.Text)) { e.Graphics.Clip = original; e.Graphics.ExcludeClip(layout.checkArea); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxStandardAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxStandardAdapter.cs index e46613ac162..cd9f7ec627e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxStandardAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/CheckBoxStandardAdapter.cs @@ -33,7 +33,7 @@ internal override void PaintUp(PaintEventArgs e, CheckState state) AdjustFocusRectangle(layout); - if (!AccessibilityImprovements.Level2 || !string.IsNullOrEmpty(Control.Text)) { + if (!string.IsNullOrEmpty(Control.Text)) { //minor adjustment to make sure the appearance is exactly the same as Win32 app. int focusRectFixup = layout.focus.X & 0x1; // if it's odd, subtract one pixel for fixup. if (!Application.RenderWithVisualStyles) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonBaseAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonBaseAdapter.cs index 5cff522c645..3d2a5d0dada 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonBaseAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonBaseAdapter.cs @@ -62,7 +62,7 @@ protected void DrawCheckBackgroundFlat(PaintEventArgs e, Rectangle bounds, Color if (!Control.Enabled) { // if we are not in HighContrast mode OR we opted into the legacy behavior - if (!SystemInformation.HighContrast || !AccessibilityImprovements.Level1) { + if (!SystemInformation.HighContrast) { border = ControlPaint.ContrastControlDark; } // otherwise we are in HighContrast mode @@ -192,7 +192,7 @@ protected void DrawCheckBox(PaintEventArgs e, LayoutData layout) { #endregion protected void AdjustFocusRectangle(LayoutData layout) { - if (AccessibilityImprovements.Level2 && string.IsNullOrEmpty(Control.Text)) { + if (string.IsNullOrEmpty(Control.Text)) { // When a RadioButton has no text, AutoSize sets the size to zero // and thus there's no place around which to draw the focus rectangle. // So, when AutoSize == true we want the focus rectangle to be rendered around the circle area. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonPopupAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonPopupAdapter.cs index bbd77c7c0c3..59bfdabcb7b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonPopupAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ButtonInternal/RadioButtonPopupAdapter.cs @@ -51,7 +51,7 @@ internal override void PaintOver(PaintEventArgs e, CheckState state) { PaintImage(e, layout); - Color checkBackgroundColor = (colors.options.highContrast && AccessibilityImprovements.Level1) ? colors.buttonFace : colors.highlight; + Color checkBackgroundColor = colors.options.highContrast ? colors.buttonFace : colors.highlight; DrawCheckBackground3DLite(e, layout.checkBounds, colors.windowText, checkBackgroundColor, colors, true); DrawCheckOnly(e, layout, colors.windowText, colors.highlight, true); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/CheckBoxRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/CheckBoxRenderer.cs index ab2c17c95c4..586a2afabe7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/CheckBoxRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/CheckBoxRenderer.cs @@ -340,8 +340,7 @@ private static bool IsDisabled(CheckBoxState state) { private static void InitializeRenderer(int state) { int part = CheckBoxElement.Part; - if (AccessibilityImprovements.Level2 - && SystemInformation.HighContrast + if (SystemInformation.HighContrast && IsDisabled((CheckBoxState)state) && VisualStyleRenderer.IsCombinationDefined(CheckBoxElement.ClassName, VisualStyleElement.Button.CheckBox.HighContrastDisabledPart)) { part = VisualStyleElement.Button.CheckBox.HighContrastDisabledPart; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/CheckedListBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/CheckedListBox.cs index 424a74dd8da..3dbe3938b51 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/CheckedListBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/CheckedListBox.cs @@ -504,7 +504,7 @@ protected override ListBox.ObjectCollection CreateItemCollection() { public CheckState GetItemCheckState(int index) { if (index < 0 || index >= Items.Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return CheckedItems.GetCheckedState(index); } @@ -574,10 +574,8 @@ private void LbnSelChange() { CheckedItems.SetCheckedState(index, itemCheckEvent.NewValue); // Send accessibility notifications for state change - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.StateChange, index); - AccessibilityNotifyClients(AccessibleEvents.NameChange, index); - } + AccessibilityNotifyClients(AccessibleEvents.StateChange, index); + AccessibilityNotifyClients(AccessibleEvents.NameChange, index); } lastSelected = index; @@ -819,7 +817,7 @@ protected override void OnDrawItem(DrawItemEventArgs e) { } } - if (Items.Count == 0 && AccessibilityImprovements.Level3 && + if (Items.Count == 0 && e.Bounds.Width > 2 * BORDER_SIZE && e.Bounds.Height > 2 * BORDER_SIZE) { Color backColor = (SelectionMode != SelectionMode.None) ? e.BackColor : BackColor; Rectangle bounds = e.Bounds; @@ -958,7 +956,7 @@ protected override void RefreshItems() { /// public void SetItemCheckState(int index, CheckState value) { if (index < 0 || index >= Items.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } // valid values are 0-2 inclusive. if (!ClientUtils.IsEnumValid(value,(int)value, (int)CheckState.Unchecked, (int)CheckState.Indeterminate)){ @@ -1048,10 +1046,10 @@ private void WmReflectVKeyToItem(ref Message m) { protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_CHARTOITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CHARTOITEM: m.Result = NativeMethods.InvalidIntPtr; break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_VKEYTOITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_VKEYTOITEM: WmReflectVKeyToItem(ref m); break; default: @@ -1659,7 +1657,7 @@ public override AccessibleStates State { state |= AccessibleStates.Selected | AccessibleStates.Focused; } - if (AccessibilityImprovements.Level3 && ParentCheckedListBox.Focused && ParentCheckedListBox.SelectedIndex == -1) { + if (ParentCheckedListBox.Focused && ParentCheckedListBox.SelectedIndex == -1) { state |= AccessibleStates.Focused; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Clipboard.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Clipboard.cs index 34d3bf1fa20..7a0b1a351b9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Clipboard.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Clipboard.cs @@ -111,11 +111,11 @@ public static void SetDataObject(object data, bool copy, int retryTimes, int ret } if (retryTimes < 0) { - throw new ArgumentOutOfRangeException(nameof(retryTimes), string.Format(SR.InvalidLowBoundArgumentEx, "retryTimes", retryTimes.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(retryTimes), retryTimes, string.Format(SR.InvalidLowBoundArgumentEx, nameof(retryTimes), retryTimes, 0)); } if (retryDelay < 0) { - throw new ArgumentOutOfRangeException(nameof(retryDelay), string.Format(SR.InvalidLowBoundArgumentEx, "retryDelay", retryDelay.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(retryDelay), retryDelay, string.Format(SR.InvalidLowBoundArgumentEx, nameof(retryDelay), retryDelay, 0)); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ColumnHeader.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ColumnHeader.cs index b1c4e1415e8..09d24763da0 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ColumnHeader.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ColumnHeader.cs @@ -198,7 +198,7 @@ public int ImageIndex { } set { if (value < -1) { - throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "ImageIndex", (value).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); } if (imageIndexer.Index != value) { @@ -497,10 +497,7 @@ public ColumnHeaderImageListIndexer(ColumnHeader ch) { public override ImageList ImageList { get { - if (owner != null && owner.ListView != null) { - return owner.ListView.SmallImageList; - } - return null; + return owner.ListView?.SmallImageList; } set { Debug.Assert(false, "We should never set the image list"); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ComboBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ComboBox.cs index f42c2ef74a0..7d3971e4d9b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ComboBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ComboBox.cs @@ -517,7 +517,7 @@ public int DropDownWidth { set { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(DropDownWidth), string.Format(SR.InvalidArgument, "DropDownWidth", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(DropDownWidth), value)); } if (Properties.GetInteger(PropDropDownWidth) != value) { Properties.SetInteger(PropDropDownWidth, value); @@ -552,7 +552,7 @@ public int DropDownHeight { } set { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(DropDownHeight), string.Format(SR.InvalidArgument, "DropDownHeight", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(DropDownHeight), value)); } if (Properties.GetInteger(PropDropDownHeight) != value) { Properties.SetInteger(PropDropDownHeight, value); @@ -722,7 +722,7 @@ public int ItemHeight { set { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(ItemHeight), string.Format(SR.InvalidArgument, "ItemHeight", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(ItemHeight), value)); } ResetHeightCache(); @@ -788,7 +788,7 @@ public int MaxDropDownItems { } set { if (value < 1 || value > 100) { - throw new ArgumentOutOfRangeException(nameof(MaxDropDownItems), string.Format(SR.InvalidBoundArgument, "MaxDropDownItems", (value).ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture), (100).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(MaxDropDownItems), value, 1, 100)); } maxDropDownItems = (short)value; } @@ -1019,7 +1019,7 @@ public override int SelectedIndex { } if (value < -1 || value >= itemCount) { - throw new ArgumentOutOfRangeException(nameof(SelectedIndex), string.Format(SR.InvalidArgument, "SelectedIndex", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SelectedIndex), value)); } if (IsHandleCreated) { @@ -1100,7 +1100,7 @@ public string SelectedText { if (IsHandleCreated) { Debug.Assert(childEdit != null); if (childEdit != null) { - UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), NativeMethods.EM_REPLACESEL, NativeMethods.InvalidIntPtr, str); + UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), Interop.EditMessages.EM_REPLACESEL, NativeMethods.InvalidIntPtr, str); } } } @@ -1146,7 +1146,7 @@ public int SelectionStart { } set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(SelectionStart), string.Format(SR.InvalidArgument, "SelectionStart", value.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SelectionStart), value)); } Select(value, SelectionLength); } @@ -1338,11 +1338,7 @@ private void NotifyAutoComplete(bool setSelectedIndex) { this.lastTextChangedValue = text; } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; // Returns true if using System AutoComplete private bool SystemAutoCompleteEnabled { @@ -1525,15 +1521,7 @@ private void CheckNoDataSource() { /// /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ComboBoxUiaProvider(this); - } - else if (AccessibilityImprovements.Level1) { - return new ComboBoxExAccessibleObject(this); - } - else { - return new ComboBoxAccessibleObject(this); - } + return new ComboBoxAccessibleObject(this); } /// @@ -1579,7 +1567,7 @@ internal Point EditToComboboxMapping(Message m) { private void ChildWndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_CHAR: + case Interop.WindowMessages.WM_CHAR: if (DropDownStyle == ComboBoxStyle.Simple && m.HWnd == childListBox.Handle) { DefChildWndProc(ref m); } @@ -1592,7 +1580,7 @@ private void ChildWndProc(ref Message m) { } } break; - case NativeMethods.WM_SYSCHAR: + case Interop.WindowMessages.WM_SYSCHAR: if (DropDownStyle == ComboBoxStyle.Simple && m.HWnd == childListBox.Handle) { DefChildWndProc(ref m); } @@ -1605,8 +1593,8 @@ private void ChildWndProc(ref Message m) { } } break; - case NativeMethods.WM_KEYDOWN: - case NativeMethods.WM_SYSKEYDOWN: + case Interop.WindowMessages.WM_KEYDOWN: + case Interop.WindowMessages.WM_SYSKEYDOWN: if (SystemAutoCompleteEnabled && !ACNativeWindow.AutoCompleteActive) { finder.FindDropDowns(false); } @@ -1636,12 +1624,12 @@ private void ChildWndProc(ref Message m) { } break; - case NativeMethods.WM_INPUTLANGCHANGE: + case Interop.WindowMessages.WM_INPUTLANGCHANGE: DefChildWndProc( ref m ); break; - case NativeMethods.WM_KEYUP: - case NativeMethods.WM_SYSKEYUP: + case Interop.WindowMessages.WM_KEYUP: + case Interop.WindowMessages.WM_SYSKEYUP: if (DropDownStyle == ComboBoxStyle.Simple && m.HWnd == childListBox.Handle) { DefChildWndProc(ref m); } @@ -1658,7 +1646,7 @@ private void ChildWndProc(ref Message m) { } break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: // Consider - If we dont' have a childwndproc, then we don't get here, so we don't // update the cache. Do we need to? This happens when we have a DropDownList. if (!DesignMode) { @@ -1677,7 +1665,7 @@ private void ChildWndProc(ref Message m) { } break; - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: // Consider - If we dont' have a childwndproc, then we don't get here, so we don't // set the status. Do we need to? This happens when we have a DropDownList. @@ -1710,14 +1698,14 @@ private void ChildWndProc(ref Message m) { } break; - case NativeMethods.WM_SETFONT: + case Interop.WindowMessages.WM_SETFONT: DefChildWndProc(ref m); if (childEdit != null && m.HWnd == childEdit.Handle) { - UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), NativeMethods.EM_SETMARGINS, + UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), Interop.EditMessages.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN, 0); } break; - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: //the Listbox gets WM_LBUTTONDOWN - WM_LBUTTONUP -WM_LBUTTONDBLCLK - WM_LBUTTONUP... //sequence for doubleclick... //Set MouseEvents... @@ -1733,7 +1721,7 @@ private void ChildWndProc(ref Message m) { OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, Ptlc.X, Ptlc.Y, 0)); break; - case NativeMethods.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: //the Listbox gets WM_LBUTTONDOWN - WM_LBUTTONUP -WM_LBUTTONDBLCLK - WM_LBUTTONUP... //sequence for doubleclick... //Set MouseEvents... @@ -1749,7 +1737,7 @@ private void ChildWndProc(ref Message m) { OnMouseDown(new MouseEventArgs(MouseButtons.Middle, 1, Ptmc.X, Ptmc.Y, 0)); break; - case NativeMethods.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: //the Listbox gets WM_LBUTTONDOWN - WM_LBUTTONUP -WM_LBUTTONDBLCLK - WM_LBUTTONUP... //sequence for doubleclick... //Set MouseEvents... @@ -1765,7 +1753,7 @@ private void ChildWndProc(ref Message m) { OnMouseDown(new MouseEventArgs(MouseButtons.Right, 1, Ptrc.X, Ptrc.Y, 0)); break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: mousePressed = true; mouseEvents = true; //set the mouse capture .. this is the Child Wndproc.. @@ -1778,7 +1766,7 @@ private void ChildWndProc(ref Message m) { OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, Ptl.X, Ptl.Y, 0)); break; - case NativeMethods.WM_LBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: // Get the mouse location // NativeMethods.RECT r = new NativeMethods.RECT(); @@ -1816,7 +1804,7 @@ private void ChildWndProc(ref Message m) { OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, pt.X, pt.Y, 0)); break; - case NativeMethods.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: mousePressed = true; mouseEvents = true; //set the mouse capture .. this is the Child Wndproc.. @@ -1829,7 +1817,7 @@ private void ChildWndProc(ref Message m) { OnMouseDown(new MouseEventArgs(MouseButtons.Middle, 1, P.X, P.Y, 0)); break; - case NativeMethods.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: mousePressed = true; mouseEvents = true; @@ -1847,7 +1835,7 @@ private void ChildWndProc(ref Message m) { OnMouseDown(new MouseEventArgs(MouseButtons.Right, 1, Pt.X, Pt.Y, 0)); break; - case NativeMethods.WM_MBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONUP: mousePressed = false; mouseEvents = false; //set the mouse capture .. this is the Child Wndproc.. @@ -1856,7 +1844,7 @@ private void ChildWndProc(ref Message m) { DefChildWndProc(ref m); OnMouseUp(new MouseEventArgs(MouseButtons.Middle, 1, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0)); break; - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: mousePressed = false; mouseEvents = false; //set the mouse capture .. this is the Child Wndproc.. @@ -1871,17 +1859,17 @@ private void ChildWndProc(ref Message m) { OnMouseUp(new MouseEventArgs(MouseButtons.Right, 1, ptRBtnUp.X, ptRBtnUp.Y, 0)); break; - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_CONTEXTMENU: // Forward context menu messages to the parent control if (this.ContextMenu != null || this.ContextMenuStrip != null) { - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.WM_CONTEXTMENU, m.WParam, m.LParam); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_CONTEXTMENU, m.WParam, m.LParam); } else { DefChildWndProc(ref m); } break; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: Point point = EditToComboboxMapping(m); //Call the DefWndProc() so that mousemove messages get to the windows edit // @@ -1890,7 +1878,7 @@ private void ChildWndProc(ref Message m) { OnMouseMove(new MouseEventArgs(MouseButtons, 0, point.X, point.Y, 0)); break; - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: if (Cursor != DefaultCursor && childEdit != null && m.HWnd == childEdit.Handle && NativeMethods.Util.LOWORD(m.LParam) == NativeMethods.HTCLIENT) { Cursor.CurrentInternal = Cursor; } @@ -1899,7 +1887,7 @@ private void ChildWndProc(ref Message m) { } break; - case NativeMethods.WM_MOUSELEAVE: + case Interop.WindowMessages.WM_MOUSELEAVE: DefChildWndProc(ref m); OnMouseLeaveInternal(EventArgs.Empty); break; @@ -1944,7 +1932,7 @@ private void DefChildWndProc(ref Message m) { NativeWindow childWindow; if (m.HWnd == childEdit.Handle) { childWindow = childEdit; - } else if (AccessibilityImprovements.Level3 && m.HWnd == dropDownHandle) { + } else if (m.HWnd == dropDownHandle) { childWindow = childDropDown; } else { @@ -2001,81 +1989,46 @@ public void EndUpdate() { } } - /// /// - /// Finds the first item in the combo box that starts with the given string. - /// The search is not case sensitive. + /// Finds the first item in the combo box that starts with the given string. + /// The search is not case sensitive. /// - public int FindString(string s) { - return FindString(s, -1); - } + public int FindString(string s) => FindString(s, startIndex: -1); - /// /// - /// Finds the first item after the given index which starts with the given - /// string. The search is not case sensitive. + /// Finds the first item after the given index which starts with the given string. + /// The search is not case sensitive. /// - public int FindString(string s, int startIndex) { - if (s == null) { - return -1; - } - - if (itemsCollection == null || itemsCollection.Count == 0) { - return -1; - } - - // The last item in the list is still a valid starting point for a search. - if (startIndex < -1 || startIndex >= itemsCollection.Count) { - throw new ArgumentOutOfRangeException(nameof(startIndex)); - } - - // Always use the managed FindStringInternal instead of CB_FINDSTRING. - // The managed version correctly handles Turkish I. - // - return FindStringInternal(s, Items, startIndex, false); + public int FindString(string s, int startIndex) + { + return FindStringInternal(s, itemsCollection, startIndex, exact: false, ignoreCase: true); } - /// /// - /// Finds the first item in the combo box that matches the given string. - /// The strings must match exactly, except for differences in casing. + /// Finds the first item in the combo box that matches the given string. + /// The strings must match exactly, except for differences in casing. /// - public int FindStringExact(string s) { - return FindStringExact(s, -1, true); + public int FindStringExact(string s) + { + return FindStringExact(s, startIndex: -1, ignoreCase: true); } - /// /// - /// Finds the first item after the given index that matches the given - /// string. The strings must match exactly, except for differences in - /// casing. + /// Finds the first item after the given index that matches the given string. + /// The strings must match exactly, except for differences in casing. /// - public int FindStringExact(string s, int startIndex) { - return FindStringExact(s, startIndex, true); + public int FindStringExact(string s, int startIndex) + { + return FindStringExact(s, startIndex, ignoreCase: true); } - /// /// - /// Finds the first item after the given index that matches the given - /// string. The strings must match exactly, except for differences in - /// casing. + /// Finds the first item after the given index that matches the given string. + /// The strings must match exactly, except for differences in casing. /// - internal int FindStringExact(string s, int startIndex, bool ignorecase) { - if (s == null) return -1; - - if (itemsCollection == null || itemsCollection.Count == 0) { - return -1; - } - - // The last item in the list is still a valid starting point for a search. - if (startIndex < -1 || startIndex >= itemsCollection.Count) { - throw new ArgumentOutOfRangeException(nameof(startIndex)); - } - - // Always use the managed FindStringInternal instead of CB_FINDSTRINGEXACT. - // The managed version correctly handles Turkish I. - // - return FindStringInternal(s, Items, startIndex, true, ignorecase); + internal int FindStringExact(string s, int startIndex, bool ignoreCase) + { + return FindStringInternal(s, itemsCollection, startIndex, exact: true, ignoreCase); } // GetPreferredSize and SetBoundsCore call this method to allow controls to self impose @@ -2115,7 +2068,7 @@ public int GetItemHeight(int index) { } if (index < 0 || itemsCollection == null || index >= itemsCollection.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (IsHandleCreated) { @@ -2144,13 +2097,13 @@ internal int GetListNativeWindowRuntimeIdPart() { } internal override IntPtr InitializeDCForWmCtlColor(IntPtr dc, int msg) { - if ((msg == NativeMethods.WM_CTLCOLORSTATIC) && !ShouldSerializeBackColor()) { + if ((msg == Interop.WindowMessages.WM_CTLCOLORSTATIC) && !ShouldSerializeBackColor()) { // Let the Win32 Edit control handle background colors itself. // This is necessary because a disabled edit control will display a different // BackColor than when enabled. return IntPtr.Zero; } - else if ((msg == NativeMethods.WM_CTLCOLORLISTBOX) && GetStyle(ControlStyles.UserPaint)) { + else if ((msg == Interop.WindowMessages.WM_CTLCOLORLISTBOX) && GetStyle(ControlStyles.UserPaint)) { // Base class returns hollow brush when UserPaint style is set, to avoid flicker in // main control. But when returning colors for child dropdown list, return normal ForeColor/BackColor, // since hollow brush leaves the list background unpainted. @@ -2166,7 +2119,7 @@ internal override IntPtr InitializeDCForWmCtlColor(IntPtr dc, int msg) { // Returns true when the key processing needs to be intercepted to allow // auto-completion in DropDownList style. private bool InterceptAutoCompleteKeystroke(Message m) { - if (m.Msg == NativeMethods.WM_KEYDOWN) { + if (m.Msg == Interop.WindowMessages.WM_KEYDOWN) { Debug.Assert((ModifierKeys & Keys.Alt) == 0); // Keys.Delete only triggers a WM_KEYDOWN and WM_KEYUP, and no WM_CHAR. That's why it's treated separately. if ((Keys)unchecked( (int) (long)m.WParam) == Keys.Delete) { @@ -2179,7 +2132,7 @@ private bool InterceptAutoCompleteKeystroke(Message m) { return false; } } - else if (m.Msg == NativeMethods.WM_CHAR) { + else if (m.Msg == Interop.WindowMessages.WM_CHAR) { Debug.Assert((ModifierKeys & Keys.Alt) == 0); char keyChar = unchecked((char)(long)m.WParam); if (keyChar == (char)Keys.Back) { @@ -2402,7 +2355,7 @@ protected override void OnHandleCreated(EventArgs e) { // set the initial margin for combobox to be zero (this is also done whenever the font is changed). // - UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), NativeMethods.EM_SETMARGINS, + UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), Interop.EditMessages.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN, 0); } } @@ -2500,17 +2453,15 @@ protected virtual void OnDropDown(EventArgs e) { EventHandler handler = (EventHandler)Events[EVENT_DROPDOWN]; if (handler != null) handler(this, e); - if (AccessibilityImprovements.Level3) { - // Notify collapsed/expanded property change. - AccessibilityObject.RaiseAutomationPropertyChangedEvent( - NativeMethods.UIA_ExpandCollapseExpandCollapseStatePropertyId, - UnsafeNativeMethods.ExpandCollapseState.Collapsed, - UnsafeNativeMethods.ExpandCollapseState.Expanded); + // Notify collapsed/expanded property change. + AccessibilityObject.RaiseAutomationPropertyChangedEvent( + NativeMethods.UIA_ExpandCollapseExpandCollapseStatePropertyId, + UnsafeNativeMethods.ExpandCollapseState.Collapsed, + UnsafeNativeMethods.ExpandCollapseState.Expanded); - var accessibleObject = AccessibilityObject as ComboBoxUiaProvider; - if (accessibleObject != null) { - accessibleObject.SetComboBoxItemFocus(); - } + var accessibleObject = AccessibilityObject as ComboBoxAccessibleObject; + if (accessibleObject != null) { + accessibleObject.SetComboBoxItemFocus(); } } @@ -2643,8 +2594,8 @@ protected override void OnSelectedIndexChanged(EventArgs e) { // and reset the state to announce the selections later. dropDownWillBeClosed = false; } - else if (AccessibilityImprovements.Level3) { - var accessibleObject = AccessibilityObject as ComboBoxUiaProvider; + else { + var accessibleObject = AccessibilityObject as ComboBoxAccessibleObject; if (accessibleObject != null) { // Announce DropDown- and DropDownList-styled ComboBox item selection using keyboard @@ -2901,23 +2852,21 @@ protected virtual void OnDropDownClosed(EventArgs e) { EventHandler handler = (EventHandler)Events[EVENT_DROPDOWNCLOSED]; if (handler != null) handler(this, e); - if (AccessibilityImprovements.Level3) { - // Need to announce the focus on combo-box with new selected value on drop-down close. - // If do not do this focus in Level 3 stays on list item of unvisible list. - // This is necessary for DropDown style as edit should not take focus. - if (DropDownStyle == ComboBoxStyle.DropDown) { - AccessibilityObject.RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); - } + // Need to announce the focus on combo-box with new selected value on drop-down close. + // If do not do this focus in Level 3 stays on list item of unvisible list. + // This is necessary for DropDown style as edit should not take focus. + if (DropDownStyle == ComboBoxStyle.DropDown) { + AccessibilityObject.RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); + } - // Notify Collapsed/expanded property change. - AccessibilityObject.RaiseAutomationPropertyChangedEvent( - NativeMethods.UIA_ExpandCollapseExpandCollapseStatePropertyId, - UnsafeNativeMethods.ExpandCollapseState.Expanded, - UnsafeNativeMethods.ExpandCollapseState.Collapsed); + // Notify Collapsed/expanded property change. + AccessibilityObject.RaiseAutomationPropertyChangedEvent( + NativeMethods.UIA_ExpandCollapseExpandCollapseStatePropertyId, + UnsafeNativeMethods.ExpandCollapseState.Expanded, + UnsafeNativeMethods.ExpandCollapseState.Collapsed); - // Collapsing the DropDown, so reset the flag. - dropDownWillBeClosed = false; - } + // Collapsing the DropDown, so reset the flag. + dropDownWillBeClosed = false; } @@ -3033,9 +2982,7 @@ private void ReleaseChildWindow() { if (childListBox != null) { // Need to notify UI Automation that it can safely remove all map entries that refer to the specified window. - if (AccessibilityImprovements.Level3) { - ReleaseUiaProvider(childListBox.Handle); - } + ReleaseUiaProvider(childListBox.Handle); childListBox.ReleaseHandle(); childListBox = null; @@ -3044,9 +2991,7 @@ private void ReleaseChildWindow() { if (childDropDown != null) { // Need to notify UI Automation that it can safely remove all map entries that refer to the specified window. - if (AccessibilityImprovements.Level3) { - ReleaseUiaProvider(childDropDown.Handle); - } + ReleaseUiaProvider(childDropDown.Handle); childDropDown.ReleaseHandle(); childDropDown = null; @@ -3056,7 +3001,7 @@ private void ReleaseChildWindow() { internal override void ReleaseUiaProvider(IntPtr handle) { base.ReleaseUiaProvider(handle); - var uiaProvider = AccessibilityObject as ComboBoxUiaProvider; + var uiaProvider = AccessibilityObject as ComboBoxAccessibleObject; uiaProvider?.ResetListItemAccessibleObjects(); } @@ -3187,14 +3132,14 @@ private void SetAutoComplete(bool reset, bool recreate) { /// public void Select(int start, int length) { if (start < 0) { - throw new ArgumentOutOfRangeException(nameof(start), string.Format(SR.InvalidArgument, "start", start.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(start), start, string.Format(SR.InvalidArgument, nameof(start), start)); } // the Length can be negative to support Selecting in the "reverse" direction.. int end = start + length; // but end cannot be negative... this means Length is far negative... if (end < 0) { - throw new ArgumentOutOfRangeException(nameof(length), string.Format(SR.InvalidArgument, "length", length.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(length), length, string.Format(SR.InvalidArgument, nameof(length), length)); } SendMessage(NativeMethods.CB_SETEDITSEL, 0, NativeMethods.Util.MAKELPARAM(start, end)); @@ -3291,7 +3236,7 @@ internal override bool ShouldSerializeText() { public override string ToString() { string s = base.ToString(); - return s + ", Items.Count: " + ((itemsCollection == null) ? (0).ToString(CultureInfo.CurrentCulture) : itemsCollection.Count.ToString(CultureInfo.CurrentCulture)); + return s + ", Items.Count: " + ((itemsCollection == null) ? "0" : itemsCollection.Count.ToString(CultureInfo.CurrentCulture)); } /// @@ -3372,7 +3317,7 @@ private void UpdateText() { if (DropDownStyle == ComboBoxStyle.DropDown) { if (childEdit != null && childEdit.Handle != IntPtr.Zero) { - UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), NativeMethods.WM_SETTEXT, IntPtr.Zero, s); + UnsafeNativeMethods.SendMessage(new HandleRef(this, childEdit.Handle), Interop.WindowMessages.WM_SETTEXT, IntPtr.Zero, s); } } } @@ -3408,26 +3353,24 @@ private void WmEraseBkgnd(ref Message m) { /// private void WmParentNotify(ref Message m) { base.WndProc(ref m); - if (unchecked((int)(long)m.WParam) == (NativeMethods.WM_CREATE | 1000 << 16)) { + if (unchecked((int)(long)m.WParam) == (Interop.WindowMessages.WM_CREATE | 1000 << 16)) { dropDownHandle = m.LParam; - if (AccessibilityImprovements.Level3) { - // By some reason WmParentNotify with WM_DESTROY is not called before recreation. - // So release the old references here. - if (childDropDown != null) { - // Need to notify UI Automation that it can safely remove all map entries that refer to the specified window. - ReleaseUiaProvider(childListBox.Handle); + // By some reason WmParentNotify with WM_DESTROY is not called before recreation. + // So release the old references here. + if (childDropDown != null) { + // Need to notify UI Automation that it can safely remove all map entries that refer to the specified window. + ReleaseUiaProvider(childListBox.Handle); - childDropDown.ReleaseHandle(); - } + childDropDown.ReleaseHandle(); + } - childDropDown = new ComboBoxChildNativeWindow(this, ChildWindowType.DropDownList); - childDropDown.AssignHandle(dropDownHandle); + childDropDown = new ComboBoxChildNativeWindow(this, ChildWindowType.DropDownList); + childDropDown.AssignHandle(dropDownHandle); - // Reset the child list accessible object in case the the DDL is recreated. - // For instance when dialog window containging the ComboBox is reopened. - childListAccessibleObject = null; - } + // Reset the child list accessible object in case the the DDL is recreated. + // For instance when dialog window containging the ComboBox is reopened. + childListAccessibleObject = null; } } @@ -3589,7 +3532,7 @@ protected override void WndProc(ref Message m) { switch (m.Msg) { // We don't want to fire the focus events twice - // once in the combobox and once in the ChildWndProc. - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: try { fireSetFocus = false; base.WndProc(ref m); @@ -3599,7 +3542,7 @@ protected override void WndProc(ref Message m) { fireSetFocus = true; } break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: try { fireLostFocus = false; base.WndProc(ref m); @@ -3615,7 +3558,7 @@ protected override void WndProc(ref Message m) { // as with Theming on. if (!Application.RenderWithVisualStyles && GetStyle(ControlStyles.UserPaint) == false && this.DropDownStyle == ComboBoxStyle.DropDownList && (FlatStyle == FlatStyle.Flat || FlatStyle == FlatStyle.Popup)) { - UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), NativeMethods.WM_MOUSELEAVE, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_MOUSELEAVE, 0, 0); } } @@ -3623,30 +3566,30 @@ protected override void WndProc(ref Message m) { fireLostFocus = true; } break; - case NativeMethods.WM_CTLCOLOREDIT: - case NativeMethods.WM_CTLCOLORLISTBOX: + case Interop.WindowMessages.WM_CTLCOLOREDIT: + case Interop.WindowMessages.WM_CTLCOLORLISTBOX: m.Result = InitializeDCForWmCtlColor(m.WParam, m.Msg); break; - case NativeMethods.WM_ERASEBKGND: + case Interop.WindowMessages.WM_ERASEBKGND: WmEraseBkgnd(ref m); break; - case NativeMethods.WM_PARENTNOTIFY: + case Interop.WindowMessages.WM_PARENTNOTIFY: WmParentNotify(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_COMMAND: WmReflectCommand(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_DRAWITEM: WmReflectDrawItem(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_MEASUREITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_MEASUREITEM: WmReflectMeasureItem(ref m); break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: mouseEvents = true; base.WndProc(ref m); break; - case NativeMethods.WM_LBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: // Get the mouse location // NativeMethods.RECT r = new NativeMethods.RECT(); @@ -3677,12 +3620,12 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_MOUSELEAVE: + case Interop.WindowMessages.WM_MOUSELEAVE: DefWndProc(ref m); OnMouseLeaveInternal(EventArgs.Empty); break; - case NativeMethods.WM_PAINT: + case Interop.WindowMessages.WM_PAINT: if (GetStyle(ControlStyles.UserPaint) == false && (FlatStyle == FlatStyle.Flat || FlatStyle == FlatStyle.Popup)) { using (WindowsRegion dr = new WindowsRegion(FlatComboBoxAdapter.dropDownRect)) { @@ -3735,7 +3678,7 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); break; - case NativeMethods.WM_PRINTCLIENT: + case Interop.WindowMessages.WM_PRINTCLIENT: // all the fancy stuff we do in OnPaint has to happen again in OnPrint. if (GetStyle(ControlStyles.UserPaint) == false && FlatStyle == FlatStyle.Flat || FlatStyle == FlatStyle.Popup) { DefWndProc(ref m); @@ -3751,11 +3694,11 @@ protected override void WndProc(ref Message m) { } base.WndProc(ref m); return; - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: base.WndProc(ref m); break; - case NativeMethods.WM_SETFONT: + case Interop.WindowMessages.WM_SETFONT: //( if (Width == 0) { suppressNextWindosPos = true; @@ -3764,14 +3707,14 @@ protected override void WndProc(ref Message m) { break; - case NativeMethods.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: if (!suppressNextWindosPos) { base.WndProc(ref m); } suppressNextWindosPos = false; break; - case NativeMethods.WM_NCDESTROY: + case Interop.WindowMessages.WM_NCDESTROY: base.WndProc(ref m); ReleaseChildWindow(); break; @@ -3803,10 +3746,10 @@ public ComboBoxChildNativeWindow(ComboBox comboBox, ChildWindowType childWindowT protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_GETOBJECT: + case Interop.WindowMessages.WM_GETOBJECT: WmGetObject(ref m); return; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: if (_childWindowType == ChildWindowType.DropDownList) { // Need to track the selection change via mouse over to @@ -3817,7 +3760,7 @@ protected override void WndProc(ref Message m) { DefWndProc(ref m); object after = _owner.SelectedItem; if (before != after) { - (_owner.AccessibilityObject as ComboBoxUiaProvider).SetComboBoxItemFocus(); + (_owner.AccessibilityObject as ComboBoxAccessibleObject).SetComboBoxItemFocus(); } } break; @@ -3843,7 +3786,7 @@ private ChildAccessibleObject GetChildAccessibleObject(ChildWindowType childWind } private void WmGetObject(ref Message m) { - if (AccessibilityImprovements.Level3 && m.LParam == (IntPtr)NativeMethods.UiaRootObjectId && + if (m.LParam == (IntPtr)NativeMethods.UiaRootObjectId && // Managed UIAutomation providers are supplied for child list windows but not for the child edit window. // Child list accessibility object provides all necessary patterns and UIAutomation notifications, // so there is no need to native provider supplement. @@ -3881,9 +3824,7 @@ private void WmGetObject(ref Message m) { UnsafeNativeMethods.IAccessibleInternal iacc = null; if (_accessibilityObject == null) { - wfAccessibleObject = AccessibilityImprovements.Level3 - ? GetChildAccessibleObject(_childWindowType) - : new ChildAccessibleObject(_owner, Handle); + wfAccessibleObject = GetChildAccessibleObject(_childWindowType); _accessibilityObject = new InternalAccessibleObject(wfAccessibleObject); } iacc = (UnsafeNativeMethods.IAccessibleInternal)_accessibilityObject; @@ -4122,7 +4063,7 @@ internal void AddRangeInternal(IList items) { public virtual object this[int index] { get { if (index < 0 || index >= InnerList.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } return InnerList[index]; @@ -4210,7 +4151,7 @@ public void Insert(int index, object item) { } if (index < 0 || index > InnerList.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } // If the combo box is sorted, then nust treat this like an add @@ -4252,7 +4193,7 @@ public void RemoveAt(int index) { owner.CheckNoDataSource(); if (index < 0 || index >= InnerList.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (owner.IsHandleCreated) { @@ -4289,7 +4230,7 @@ internal void SetItemInternal(int index, object value) { } if (index < 0 || index >= InnerList.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } InnerList[index] = value; @@ -4347,136 +4288,6 @@ public override string Name { } } - /// - /// - [System.Runtime.InteropServices.ComVisible(true)] - internal class ComboBoxAccessibleObject : ControlAccessibleObject { - - private const int COMBOBOX_ACC_ITEM_INDEX = 1; - - public ComboBoxAccessibleObject(Control ownerControl) - : base(ownerControl) { - } - - internal override string get_accNameInternal(object childID) { - this.ValidateChildID(ref childID); - - if (childID != null && ((int)childID) == COMBOBOX_ACC_ITEM_INDEX) { - return this.Name; - } - else { - return base.get_accNameInternal(childID); - } - } - - internal override string get_accKeyboardShortcutInternal(object childID) { - this.ValidateChildID(ref childID); - if (childID != null && ((int)childID) == COMBOBOX_ACC_ITEM_INDEX) { - return this.KeyboardShortcut; - } else { - return base.get_accKeyboardShortcutInternal(childID); - } - } - } - - /// - /// - [ComVisible(true)] - internal class ComboBoxExAccessibleObject : ComboBoxAccessibleObject { - - private ComboBox ownerItem = null; - - private void ComboBoxDefaultAction(bool expand) { - if (ownerItem.DroppedDown != expand) { - ownerItem.DroppedDown = expand; - } - } - - public ComboBoxExAccessibleObject(ComboBox ownerControl) - : base(ownerControl) { - ownerItem = ownerControl; - } - - internal override bool IsIAccessibleExSupported() { - if (ownerItem != null) { - return true; - } - return base.IsIAccessibleExSupported(); - } - - internal override bool IsPatternSupported(int patternId) { - if (patternId == NativeMethods.UIA_ExpandCollapsePatternId) { - if (ownerItem.DropDownStyle == ComboBoxStyle.Simple) { - return false; - } - return true; - } - else { - if (patternId == NativeMethods.UIA_ValuePatternId) { - if (ownerItem.DropDownStyle == ComboBoxStyle.DropDownList) { - // NOTE: Initially the Value pattern is disabled for DropDownList in managed code, - // but despite of this MSAA provides true (when Level < 3). When UIA mode is enabled, - // Value pattern becomes disabled for the DropDownList and brings inconsistency. - // At this time keeping 'return false;' commented out and preserving Value pattern - // enabled in all cases: Level < 3 (by MSAA) and Level3 (by UIA). - // return false; - return AccessibilityImprovements.Level3; - } - return true; - } - } - return base.IsPatternSupported(patternId); - } - - internal override int[] RuntimeId { - get { - if (ownerItem != null) { - // we need to provide a unique ID - // others are implementing this in the same manner - // first item is static - 0x2a (RuntimeIDFirstItem) - // second item can be anything, but here it is a hash - - var runtimeId = new int[3]; - runtimeId[0] = RuntimeIDFirstItem; - runtimeId[1] = (int)(long)ownerItem.Handle; - runtimeId[2] = ownerItem.GetHashCode(); - return runtimeId; - } - - return base.RuntimeId; - } - } - - internal override object GetPropertyValue(int propertyID) { - - switch (propertyID) { - case NativeMethods.UIA_NamePropertyId: - return Name; - case NativeMethods.UIA_IsExpandCollapsePatternAvailablePropertyId: - return (object)this.IsPatternSupported(NativeMethods.UIA_ExpandCollapsePatternId); - case NativeMethods.UIA_IsValuePatternAvailablePropertyId: - return (object)this.IsPatternSupported(NativeMethods.UIA_ValuePatternId); - - default: - return base.GetPropertyValue(propertyID); - } - } - - internal override void Expand() { - ComboBoxDefaultAction(true); - } - - internal override void Collapse() { - ComboBoxDefaultAction(false); - } - - internal override UnsafeNativeMethods.ExpandCollapseState ExpandCollapseState { - get { - return ownerItem.DroppedDown == true ? UnsafeNativeMethods.ExpandCollapseState.Expanded : UnsafeNativeMethods.ExpandCollapseState.Collapsed; - } - } - } - /// /// Represents the ComboBox item accessible object. /// @@ -4744,24 +4555,133 @@ public override object this[object key] { } /// - /// ComboBox control accessible object for AccessibilityImprovements of Level 3 with UI Automation provider functionality. - /// This inherits from the base ComboBoxExAccessibleObject and ComboBoxAccessibleObject to have all base functionality. + /// ComboBox control accessible object with UI Automation provider functionality. + /// This inherits from the base ComboBoxExAccessibleObject and ComboBoxAccessibleObject + /// to have all base functionality. /// [ComVisible(true)] - internal class ComboBoxUiaProvider : ComboBoxExAccessibleObject { + internal class ComboBoxAccessibleObject : ControlAccessibleObject { + private const int COMBOBOX_ACC_ITEM_INDEX = 1; + private ComboBoxChildDropDownButtonUiaProvider _dropDownButtonUiaProvider; private ComboBoxItemAccessibleObjectCollection _itemAccessibleObjects; private ComboBox _owningComboBox; /// - /// Initializes new instance of ComboBoxUiaProvider. + /// Initializes new instance of ComboBoxAccessibleObject. /// /// The owning ComboBox control. - public ComboBoxUiaProvider(ComboBox owningComboBox) : base(owningComboBox) { + public ComboBoxAccessibleObject(ComboBox owningComboBox) : base(owningComboBox) + { _owningComboBox = owningComboBox; _itemAccessibleObjects = new ComboBoxItemAccessibleObjectCollection(owningComboBox); } + private void ComboBoxDefaultAction(bool expand) + { + if (_owningComboBox.DroppedDown != expand) + { + _owningComboBox.DroppedDown = expand; + } + } + + internal override bool IsIAccessibleExSupported() + { + if (_owningComboBox != null) + { + return true; + } + + return base.IsIAccessibleExSupported(); + } + + internal override bool IsPatternSupported(int patternId) + { + if (patternId == NativeMethods.UIA_ExpandCollapsePatternId) + { + if (_owningComboBox.DropDownStyle == ComboBoxStyle.Simple) + { + return false; + } + return true; + } + else + { + if (patternId == NativeMethods.UIA_ValuePatternId) + { + return true; + } + } + return base.IsPatternSupported(patternId); + } + + internal override int[] RuntimeId + { + get + { + if (_owningComboBox != null) + { + // we need to provide a unique ID + // others are implementing this in the same manner + // first item is static - 0x2a (RuntimeIDFirstItem) + // second item can be anything, but here it is a hash + + var runtimeId = new int[3]; + runtimeId[0] = RuntimeIDFirstItem; + runtimeId[1] = (int)(long)_owningComboBox.Handle; + runtimeId[2] = _owningComboBox.GetHashCode(); + return runtimeId; + } + + return base.RuntimeId; + } + } + + internal override void Expand() + { + ComboBoxDefaultAction(true); + } + + internal override void Collapse() + { + ComboBoxDefaultAction(false); + } + + internal override UnsafeNativeMethods.ExpandCollapseState ExpandCollapseState + { + get + { + return _owningComboBox.DroppedDown == true ? UnsafeNativeMethods.ExpandCollapseState.Expanded : UnsafeNativeMethods.ExpandCollapseState.Collapsed; + } + } + + internal override string get_accNameInternal(object childID) + { + this.ValidateChildID(ref childID); + + if (childID != null && ((int)childID) == COMBOBOX_ACC_ITEM_INDEX) + { + return this.Name; + } + else + { + return base.get_accNameInternal(childID); + } + } + + internal override string get_accKeyboardShortcutInternal(object childID) + { + this.ValidateChildID(ref childID); + if (childID != null && ((int)childID) == COMBOBOX_ACC_ITEM_INDEX) + { + return this.KeyboardShortcut; + } + else + { + return base.get_accKeyboardShortcutInternal(childID); + } + } + /// /// Gets the collection of item accessible objects. /// @@ -4877,10 +4797,16 @@ internal override object GetPropertyValue(int propertyID) { switch (propertyID) { case NativeMethods.UIA_ControlTypePropertyId: return NativeMethods.UIA_ComboBoxControlTypeId; + case NativeMethods.UIA_NamePropertyId: + return Name; case NativeMethods.UIA_HasKeyboardFocusPropertyId: return _owningComboBox.Focused; case NativeMethods.UIA_NativeWindowHandlePropertyId: return _owningComboBox.Handle; + case NativeMethods.UIA_IsExpandCollapsePatternAvailablePropertyId: + return IsPatternSupported(NativeMethods.UIA_ExpandCollapsePatternId); + case NativeMethods.UIA_IsValuePatternAvailablePropertyId: + return IsPatternSupported(NativeMethods.UIA_ValuePatternId); default: return base.GetPropertyValue(propertyID); @@ -4956,19 +4882,19 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga return null; } - var comboBoxUiaProvider = _owner.AccessibilityObject as ComboBoxUiaProvider; - if (comboBoxUiaProvider != null) { - int comboBoxChildFragmentCount = comboBoxUiaProvider.GetChildFragmentCount(); + var comboBoxAccessibleObject = _owner.AccessibilityObject as ComboBoxAccessibleObject; + if (comboBoxAccessibleObject != null) { + int comboBoxChildFragmentCount = comboBoxAccessibleObject.GetChildFragmentCount(); if (comboBoxChildFragmentCount > 1) { // DropDown button is next; - return comboBoxUiaProvider.GetChildFragment(comboBoxChildFragmentCount - 1); + return comboBoxAccessibleObject.GetChildFragment(comboBoxChildFragmentCount - 1); } } return null; case UnsafeNativeMethods.NavigateDirection.PreviousSibling: - comboBoxUiaProvider = _owner.AccessibilityObject as ComboBoxUiaProvider; - if (comboBoxUiaProvider != null) { - var firstComboBoxChildFragment = comboBoxUiaProvider.GetChildFragment(0); + comboBoxAccessibleObject = _owner.AccessibilityObject as ComboBoxAccessibleObject; + if (comboBoxAccessibleObject != null) { + var firstComboBoxChildFragment = comboBoxAccessibleObject.GetChildFragment(0); if (RuntimeId != firstComboBoxChildFragment.RuntimeId) { return firstComboBoxChildFragment; } @@ -5030,19 +4956,13 @@ internal override object GetPropertyValue(int propertyID) { internal override UnsafeNativeMethods.IRawElementProviderSimple HostRawElementProvider { get { - if (AccessibilityImprovements.Level3) { - UnsafeNativeMethods.IRawElementProviderSimple provider; - UnsafeNativeMethods.UiaHostProviderFromHwnd(new HandleRef(this, _handle), out provider); - return provider; - } - - return base.HostRawElementProvider; + UnsafeNativeMethods.IRawElementProviderSimple provider; + UnsafeNativeMethods.UiaHostProviderFromHwnd(new HandleRef(this, _handle), out provider); + return provider; } } - internal override bool IsIAccessibleExSupported() { - return true; - } + internal override bool IsIAccessibleExSupported() => true; /// /// Gets the runtime ID. @@ -5085,17 +5005,15 @@ public ComboBoxChildListUiaProvider(ComboBox owningComboBox, IntPtr childListCon /// Y coordinate. /// The accessible object of corresponding element in the provided coordinates. internal override UnsafeNativeMethods.IRawElementProviderFragment ElementProviderFromPoint(double x, double y) { - if (AccessibilityImprovements.Level3) { - var systemIAccessible = GetSystemIAccessibleInternal(); - if (systemIAccessible != null) { - object result = systemIAccessible.accHitTest((int)x, (int)y); - if (result is int) { - int childId = (int)result; - return GetChildFragment(childId - 1); - } - else { - return null; - } + var systemIAccessible = GetSystemIAccessibleInternal(); + if (systemIAccessible != null) { + object result = systemIAccessible.accHitTest((int)x, (int)y); + if (result is int) { + int childId = (int)result; + return GetChildFragment(childId - 1); + } + else { + return null; } } @@ -5138,8 +5056,8 @@ public AccessibleObject GetChildFragment(int index) { } var item = _owningComboBox.Items[index]; - var comboBoxUiaProvider = _owningComboBox.AccessibilityObject as ComboBoxUiaProvider; - return comboBoxUiaProvider.ItemAccessibleObjects[item] as AccessibleObject; + var comboBoxAccessibleObject = _owningComboBox.AccessibilityObject as ComboBoxAccessibleObject; + return comboBoxAccessibleObject.ItemAccessibleObjects[item] as AccessibleObject; } public int GetChildFragmentCount() { @@ -5242,13 +5160,9 @@ internal override bool IsPatternSupported(int patternId) internal override UnsafeNativeMethods.IRawElementProviderSimple HostRawElementProvider { get { - if (AccessibilityImprovements.Level3) { - UnsafeNativeMethods.IRawElementProviderSimple provider; - UnsafeNativeMethods.UiaHostProviderFromHwnd(new HandleRef(this, _childListControlhandle), out provider); - return provider; - } - - return base.HostRawElementProvider; + UnsafeNativeMethods.IRawElementProviderSimple provider; + UnsafeNativeMethods.UiaHostProviderFromHwnd(new HandleRef(this, _childListControlhandle), out provider); + return provider; } } @@ -5338,19 +5252,19 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga case UnsafeNativeMethods.NavigateDirection.Parent: return _owner.AccessibilityObject; case UnsafeNativeMethods.NavigateDirection.NextSibling: - var comboBoxUiaProvider = _owner.AccessibilityObject as ComboBoxUiaProvider; - if (comboBoxUiaProvider != null) { - int comboBoxChildFragmentCount = comboBoxUiaProvider.GetChildFragmentCount(); + var comboBoxAccessibleObject = _owner.AccessibilityObject as ComboBoxAccessibleObject; + if (comboBoxAccessibleObject != null) { + int comboBoxChildFragmentCount = comboBoxAccessibleObject.GetChildFragmentCount(); if (comboBoxChildFragmentCount > 1) { // DropDown button is next; - return comboBoxUiaProvider.GetChildFragment(comboBoxChildFragmentCount - 1); + return comboBoxAccessibleObject.GetChildFragment(comboBoxChildFragmentCount - 1); } } return null; case UnsafeNativeMethods.NavigateDirection.PreviousSibling: - comboBoxUiaProvider = _owner.AccessibilityObject as ComboBoxUiaProvider; - if (comboBoxUiaProvider != null) { - var firstComboBoxChildFragment = comboBoxUiaProvider.GetChildFragment(0); + comboBoxAccessibleObject = _owner.AccessibilityObject as ComboBoxAccessibleObject; + if (comboBoxAccessibleObject != null) { + var firstComboBoxChildFragment = comboBoxAccessibleObject.GetChildFragment(0); if (RuntimeId != firstComboBoxChildFragment.RuntimeId) { return firstComboBoxChildFragment; } @@ -5502,11 +5416,11 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga return _owner.AccessibilityObject; } else if (direction == UnsafeNativeMethods.NavigateDirection.PreviousSibling) { - var comboBoxUiaProvider = _owner.AccessibilityObject as ComboBoxUiaProvider; - if (comboBoxUiaProvider != null) { - int comboBoxChildFragmentCount = comboBoxUiaProvider.GetChildFragmentCount(); + var comboBoxAccessibleObject = _owner.AccessibilityObject as ComboBoxAccessibleObject; + if (comboBoxAccessibleObject != null) { + int comboBoxChildFragmentCount = comboBoxAccessibleObject.GetChildFragmentCount(); if (comboBoxChildFragmentCount > 1) { // Text or edit is previous; - return comboBoxUiaProvider.GetChildFragment(comboBoxChildFragmentCount - 1); + return comboBoxAccessibleObject.GetChildFragment(comboBoxChildFragmentCount - 1); } } @@ -5699,7 +5613,7 @@ protected override void WndProc(ref Message m) { inWndProcCnt--; } - if (m.Msg == NativeMethods.WM_NCDESTROY) { + if (m.Msg == Interop.WindowMessages.WM_NCDESTROY) { Debug.Assert(ACWindows.ContainsKey(this.Handle)); ACWindows.Remove(this.Handle); //so we do not leak ac windows. } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/CommonDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/CommonDialog.cs index 01f588d0c41..22ddfb55e41 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/CommonDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/CommonDialog.cs @@ -29,7 +29,7 @@ namespace System.Windows.Forms { ] public abstract class CommonDialog : Component { private static readonly object EventHelpRequest = new object(); - private const int CDM_SETDEFAULTFOCUS = NativeMethods.WM_USER + 0x51; + private const int CDM_SETDEFAULTFOCUS = Interop.WindowMessages.WM_USER + 0x51; private static int helpMsg; private IntPtr defOwnerWndProc; @@ -137,7 +137,7 @@ internal static string CommonDialogErrorToString(int error) { /// /// protected virtual IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { - if (msg == NativeMethods.WM_INITDIALOG) { + if (msg == Interop.WindowMessages.WM_INITDIALOG) { MoveToScreenCenter(hWnd); // Under some circumstances, the dialog @@ -147,7 +147,7 @@ protected virtual IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lp this.defaultControlHwnd = wparam; UnsafeNativeMethods.SetFocus(new HandleRef(null, wparam)); } - else if (msg == NativeMethods.WM_SETFOCUS) { + else if (msg == Interop.WindowMessages.WM_SETFOCUS) { UnsafeNativeMethods.PostMessage(new HandleRef(null, hWnd), CDM_SETDEFAULTFOCUS, 0, 0); } else if (msg == CDM_SETDEFAULTFOCUS) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2Properties.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2Properties.cs index c0008f3b2df..e6b7a0b4418 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2Properties.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2Properties.cs @@ -384,7 +384,7 @@ private static int CountMemberOffset { get { if (countOffset == -1) { - countOffset = Marshal.SizeOf(typeof(Guid)) + IntPtr.Size + 24; + countOffset = Marshal.SizeOf() + IntPtr.Size + 24; } return countOffset; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2PropertyDescriptor.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2PropertyDescriptor.cs index efbf680ae63..e82a291e59e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2PropertyDescriptor.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2PropertyDescriptor.cs @@ -1215,7 +1215,9 @@ public override void SetValue(object component, object value) { try { dp.rgdispidNamedArgs = Marshal.UnsafeAddrOfPinnedArrayElement(namedArgs, 0); - IntPtr mem = Marshal.AllocCoTaskMem( 16 /*Marshal.SizeOf(typeof(VARIANT)) */); + const int SizeOfVariant = 16; + Debug.Assert(SizeOfVariant == Marshal.SizeOf()); + IntPtr mem = Marshal.AllocCoTaskMem(SizeOfVariant); SafeNativeMethods.VariantInit(new HandleRef(null, mem)); Marshal.GetNativeVariantForObject(value, mem); dp.rgvarg = mem; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2TypeInfoProcessor.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2TypeInfoProcessor.cs index 1a301d7f55f..e7c86c10b24 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2TypeInfoProcessor.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ComponentModel/COM2Interop/COM2TypeInfoProcessor.cs @@ -288,9 +288,9 @@ private static Guid GetGuidForTypeInfo(UnsafeNativeMethods.ITypeInfo typeInfo, S typeAttr = new NativeMethods.tagTYPEATTR(); } else { - typeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR)); + typeAttr = structCache.GetStruct(); } - UnsafeNativeMethods.PtrToStructure(pTypeAttr, typeAttr); + Marshal.PtrToStructure(pTypeAttr, typeAttr); g = typeAttr.guid; if (versions != null) { versions[0] = typeAttr.wMajorVerNum; @@ -339,13 +339,12 @@ private static Type GetValueTypeFromTypeDesc(NativeMethods.tagTYPEDESC typeDesc, case NativeMethods.tagVT.VT_PTR: // we'll need to recurse into a user defined reference typeinfo Debug.Assert(typeDesc.unionMember != IntPtr.Zero, "typeDesc doesn't contain an refTypeDesc!"); - NativeMethods.tagTYPEDESC refTypeDesc = (NativeMethods.tagTYPEDESC)structCache.GetStruct(typeof(NativeMethods.tagTYPEDESC)); + NativeMethods.tagTYPEDESC refTypeDesc = structCache.GetStruct(); try { try { - //(tagTYPEDESC)Marshal.PtrToStructure(typeDesc.unionMember, typeof(tagTYPEDESC)); - UnsafeNativeMethods.PtrToStructure(typeDesc.unionMember, refTypeDesc); + Marshal.PtrToStructure(typeDesc.unionMember, refTypeDesc); } catch { // above is failing, why? @@ -387,8 +386,8 @@ private static Type GetValueTypeFromTypeDesc(NativeMethods.tagTYPEDESC typeDesc, throw new ExternalException(string.Format(SR.TYPEINFOPROCESSORGetTypeAttrFailed, hr), hr); } - NativeMethods.tagTYPEATTR refTypeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR));//(tagTYPEATTR)Marshal.PtrToStructure(pRefTypeAttr, typeof(tagTYPEATTR)); - UnsafeNativeMethods.PtrToStructure(pRefTypeAttr, refTypeAttr); + NativeMethods.tagTYPEATTR refTypeAttr = structCache.GetStruct(); + Marshal.PtrToStructure(pRefTypeAttr, refTypeAttr); try { Guid g = refTypeAttr.guid; @@ -618,17 +617,17 @@ private static void ProcessFunctions(UnsafeNativeMethods.ITypeInfo typeInfo, IDi throw new ExternalException(string.Format(SR.TYPEINFOPROCESSORGetTypeAttrFailed, hr), hr); } - NativeMethods.tagTYPEATTR typeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR));//(tagTYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(tagTYPEATTR)); - UnsafeNativeMethods.PtrToStructure(pTypeAttr, typeAttr); + NativeMethods.tagTYPEATTR typeAttr = structCache.GetStruct(); + Marshal.PtrToStructure(pTypeAttr, typeAttr); if (typeAttr == null) { return; } - NativeMethods.tagFUNCDESC funcDesc = null; - NativeMethods.tagELEMDESC ed = null; + NativeMethods.tagFUNCDESC funcDesc = null; + NativeMethods.tagELEMDESC ed = null; try { - funcDesc = (NativeMethods.tagFUNCDESC)structCache.GetStruct(typeof(NativeMethods.tagFUNCDESC)); - ed = (NativeMethods.tagELEMDESC)structCache.GetStruct(typeof(NativeMethods.tagELEMDESC)); + funcDesc = structCache.GetStruct(); + ed = structCache.GetStruct(); bool isPropGet; PropInfo pi; @@ -642,8 +641,7 @@ private static void ProcessFunctions(UnsafeNativeMethods.ITypeInfo typeInfo, IDi continue; } - //funcDesc = (tagFUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(tagFUNCDESC)); - UnsafeNativeMethods.PtrToStructure(pFuncDesc, funcDesc); + Marshal.PtrToStructure(pFuncDesc, funcDesc); try { if (funcDesc.invkind == (int)NativeMethods.tagINVOKEKIND.INVOKE_FUNC || (dispidToGet != NativeMethods.MEMBERID_NIL && funcDesc.memid != dispidToGet)) { @@ -723,8 +721,8 @@ private static Type ProcessTypeInfoEnum(UnsafeNativeMethods.ITypeInfo enumTypeIn throw new ExternalException(string.Format(SR.TYPEINFOPROCESSORGetTypeAttrFailed, hr), hr); } - NativeMethods.tagTYPEATTR typeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR));//(tagTYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(tagTYPEATTR)); - UnsafeNativeMethods.PtrToStructure(pTypeAttr, typeAttr); + NativeMethods.tagTYPEATTR typeAttr = structCache.GetStruct(); + Marshal.PtrToStructure(pTypeAttr, typeAttr); if (pTypeAttr == IntPtr.Zero) { Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: failed to get a typeAttr"); @@ -740,7 +738,7 @@ private static Type ProcessTypeInfoEnum(UnsafeNativeMethods.ITypeInfo enumTypeIn ArrayList strs = new ArrayList(); ArrayList vars = new ArrayList(); - NativeMethods.tagVARDESC varDesc = (NativeMethods.tagVARDESC)structCache.GetStruct(typeof(NativeMethods.tagVARDESC)); + NativeMethods.tagVARDESC varDesc = structCache.GetStruct(); object varValue = null; string enumName = null; string name = null; @@ -761,8 +759,7 @@ private static Type ProcessTypeInfoEnum(UnsafeNativeMethods.ITypeInfo enumTypeIn } try { - //varDesc = (tagVARDESC)Marshal.PtrToStructure(pVarDesc, typeof(tagVARDESC)); - UnsafeNativeMethods.PtrToStructure(pVarDesc, varDesc); + Marshal.PtrToStructure(pVarDesc, varDesc); if (varDesc == null || varDesc.varkind != (int)NativeMethods.tagVARKIND.VAR_CONST || @@ -787,19 +784,12 @@ private static Type ProcessTypeInfoEnum(UnsafeNativeMethods.ITypeInfo enumTypeIn // get the value try { - //varValue = (VARIANT)Marshal.PtrToStructure(varDesc.unionMember, typeof(VARIANT)); varValue = Marshal.GetObjectForNativeVariant(varDesc.unionMember); } catch (Exception ex) { Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: PtrtoStructFailed " + ex.GetType().Name + "," + ex.Message); } - /*if (varValue == null) { - Debug.Fail("Couldn't get VARIANT from VARIANTDESC"); - continue; - }*/ - - //variant v = varValue.ToVariant(); Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: adding variable value=" + Convert.ToString(varValue, CultureInfo.InvariantCulture)); vars.Add(varValue); @@ -881,14 +871,14 @@ private static void ProcessVariables(UnsafeNativeMethods.ITypeInfo typeInfo, IDi throw new ExternalException(string.Format(SR.TYPEINFOPROCESSORGetTypeAttrFailed, hr), hr); } - NativeMethods.tagTYPEATTR typeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR));//(tagTYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(tagTYPEATTR)); - UnsafeNativeMethods.PtrToStructure(pTypeAttr, typeAttr); + NativeMethods.tagTYPEATTR typeAttr = structCache.GetStruct(); + Marshal.PtrToStructure(pTypeAttr, typeAttr); try { if (typeAttr == null) { return; } - NativeMethods.tagVARDESC varDesc = (NativeMethods.tagVARDESC)structCache.GetStruct(typeof(NativeMethods.tagVARDESC)); + NativeMethods.tagVARDESC varDesc = structCache.GetStruct(); for (int i = 0; i < typeAttr.cVars; i++) { IntPtr pVarDesc = IntPtr.Zero; @@ -899,8 +889,7 @@ private static void ProcessVariables(UnsafeNativeMethods.ITypeInfo typeInfo, IDi continue; } - //varDesc = (tagVARDESC)Marshal.PtrToStructure(pVarDesc, typeof(tagVARDESC)); - UnsafeNativeMethods.PtrToStructure(pVarDesc, varDesc); + Marshal.PtrToStructure(pVarDesc, varDesc); try { @@ -1064,81 +1053,84 @@ private PropertyDescriptor[] ClonePropertyDescriptors(PropertyDescriptor[] props return retProps; } } - - /// - /// - /// This class manages a cache of structures that we can use - /// for passing into native so we don't have to create them every time. - /// for many objects, these can be used thousands of times. - /// - public class StructCache { - - private Hashtable queuedTypes = new Hashtable(); - + + /// + /// This class manages a cache of structures that we can use for passing into + /// native so we don't have to create them every time. For many objects, these + /// can be used thousands of times. + /// + public class StructCache + { + private static readonly Hashtable s_queuedTypes = new Hashtable(); + #if DEBUG - private Hashtable releaseCheck = new Hashtable(); + private static readonly Hashtable s_releaseCheck = new Hashtable(); - ~StructCache() { - IEnumerator enumRelease = releaseCheck.Keys.GetEnumerator(); - - while (enumRelease.MoveNext()) { + ~StructCache() + { + IEnumerator enumRelease = s_releaseCheck.Keys.GetEnumerator(); + while (enumRelease.MoveNext()) + { Type t = (Type)enumRelease.Current; - if ((int)releaseCheck[t] != 0) { - Debug.Assert(false, "Failed to release struct of type " + t.Name); - } - } - } - + Debug.Assert((int)s_releaseCheck[t] == 0, "Failed to release struct of type " + t.Name); + } + } #endif - - private Queue GetQueue(Type t, bool create) { - object queue = queuedTypes[t]; - - if (queue == null && create){ - queue = new Queue(); - queuedTypes[t] = queue; - #if DEBUG - releaseCheck[t] = 0; - #endif - } - - return (Queue)queue; - } - - public object GetStruct(Type t) { - Queue queue = GetQueue(t, true); - object str = null; - - if (queue.Count == 0) { - str = Activator.CreateInstance(t); - } - else { - str = queue.Dequeue(); - } - - #if DEBUG - int count = (int)releaseCheck[t]; - releaseCheck[t] = ++count; - #endif - - return str; - } - - public void ReleaseStruct(object str) { - Type t = str.GetType(); - Queue queue = GetQueue(t, false); - - if (queue != null) { - queue.Enqueue(str); - - #if DEBUG - int count = (int)releaseCheck[t]; - releaseCheck[t] = --count; - #endif - } - } - + private Queue GetQueue(Type t, bool create) + { + object queue = s_queuedTypes[t]; + + if (queue == null && create) + { + queue = new Queue(); + s_queuedTypes[t] = queue; +#if DEBUG + s_releaseCheck[t] = 0; +#endif + } + + return (Queue)queue; + } + + public T GetStruct() + { + Type t = typeof(T); + Queue queue = GetQueue(t, true); + + object str; + if (queue.Count == 0) + { + str = Activator.CreateInstance(t); + } + else + { + str = queue.Dequeue(); + } + +#if DEBUG + int count = (int)s_releaseCheck[t]; + s_releaseCheck[t] = ++count; +#endif + + return (T)str; + } + + public void ReleaseStruct(object str) + { + Type t = str.GetType(); + Queue queue = GetQueue(t, false); + + if (queue != null) + { + queue.Enqueue(str); + +#if DEBUG + int count = (int)s_releaseCheck[t]; + s_releaseCheck[t] = --count; +#endif + } + } } private class PropInfo { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs index abeb26bc8d7..3534310535f 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs @@ -85,7 +85,7 @@ public SizeF AutoScaleDimensions { ] set { if (value.Width < 0 || value.Height < 0) { - throw new ArgumentOutOfRangeException(SR.ContainerControlInvalidAutoScaleDimensions, "value"); + throw new ArgumentOutOfRangeException(nameof(value), value, SR.ContainerControlInvalidAutoScaleDimensions); } autoScaleDimensions = value; if (!autoScaleDimensions.IsEmpty) { @@ -197,7 +197,7 @@ public virtual AutoValidate AutoValidate { case AutoValidate.Inherit: break; default: - throw new InvalidEnumArgumentException(nameof(AutoValidate), (int) value, typeof(AutoValidate)); + throw new InvalidEnumArgumentException(nameof(value), (int) value, typeof(AutoValidate)); } if (autoValidate != value) { @@ -1331,13 +1331,13 @@ internal void SetActiveControlInternal(Control value) { Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::SetActiveControlInternal(" + (value == null ? "null" : value.Name) + ") - " + this.Name); if (activeControl != value || (value != null && !value.Focused)) { if (value != null && !Contains(value)) { - throw new ArgumentException(SR.CannotActivateControl); + throw new ArgumentException(SR.CannotActivateControl, nameof(value)); } bool ret; ContainerControl cc = this; - if (value != null && value.ParentInternal != null) + if (value != null) { cc = (value.ParentInternal.GetContainerControlInternal()) as ContainerControl; } @@ -1875,7 +1875,7 @@ private void WmSetFocus(ref Message m) { [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: WmSetFocus(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs index 52379575fb8..01ac0301b1a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs @@ -282,17 +282,15 @@ static Control() { internal static readonly object EventPaddingChanged = new object(); private static readonly object EventPreviewKeyDown = new object(); - #if WIN95_SUPPORT - private static int mouseWheelMessage = NativeMethods.WM_MOUSEWHEEL; + private static int mouseWheelMessage = Interop.WindowMessages.WM_MOUSEWHEEL; private static bool mouseWheelRoutingNeeded; private static bool mouseWheelInit; - #endif private static int threadCallbackMessage; // Initially check for illegal multithreading based on whether the // debugger is attached. - + private static bool checkForIllegalCrossThreadCalls = Debugger.IsAttached; private static ContextCallback invokeMarshaledCallbackHelperDelegate; @@ -494,9 +492,7 @@ internal Control(bool autoInstallSyncContext) : base() { ControlStyles.UseTextForAccessibility | ControlStyles.Selectable,true); -#if WIN95_SUPPORT InitMouseWheelSupport(); -#endif // We baked the "default default" margin and min size into CommonProperties // so that in the common case the PropertyStore would be empty. If, however, @@ -660,7 +656,7 @@ private AccessibleObject GetAccessibilityObject(int accObjId) { /// Returns a specific AccessibleObbject associated w/ the objectID /// protected virtual AccessibleObject GetAccessibilityObjectById(int objectId) { - if (AccessibilityImprovements.Level3 && this is IAutomationLiveRegion) { + if (this is IAutomationLiveRegion) { return this.AccessibilityObject; } @@ -2022,7 +2018,7 @@ public virtual Cursor Cursor { UnsafeNativeMethods.GetWindowRect(new HandleRef(this, Handle), ref r); if ((r.left <= p.x && p.x < r.right && r.top <= p.y && p.y < r.bottom) || UnsafeNativeMethods.GetCapture() == Handle) - SendMessage(NativeMethods.WM_SETCURSOR, Handle, (IntPtr)NativeMethods.HTCLIENT); + SendMessage(Interop.WindowMessages.WM_SETCURSOR, Handle, (IntPtr)NativeMethods.HTCLIENT); } if (!resolvedCursor.Equals(value)) { @@ -3649,7 +3645,7 @@ public virtual RightToLeft RightToLeft { set { //valid values are 0x0 to 0x2. if (!ClientUtils.IsEnumValid(value, (int)value, (int)RightToLeft.No, (int)RightToLeft.Inherit)){ - throw new InvalidEnumArgumentException(nameof(RightToLeft), (int)value, typeof(RightToLeft)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(RightToLeft)); } RightToLeft oldValue = RightToLeft; @@ -3811,7 +3807,7 @@ public int TabIndex { } set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(TabIndex), string.Format(SR.InvalidLowBoundArgumentEx, "TabIndex", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(TabIndex), value, 0)); } if (tabIndex != value) { @@ -4074,14 +4070,13 @@ protected internal virtual bool ShowKeyboardCues { else { // if we're in the hidden state, we need to manufacture an update message so everyone knows it. // - int actionMask = (NativeMethods.UISF_HIDEACCEL | - (AccessibilityImprovements.Level1 ? 0 : NativeMethods.UISF_HIDEFOCUS)) << 16; + int actionMask = NativeMethods.UISF_HIDEACCEL << 16; uiCuesState |= UISTATE_KEYBOARD_CUES_HIDDEN; // The side effect of this initial state is that adding new controls may clear the accelerator // state (has been this way forever) UnsafeNativeMethods.SendMessage(new HandleRef(TopMostParent, TopMostParent.Handle), - NativeMethods.WM_CHANGEUISTATE, + Interop.WindowMessages.WM_CHANGEUISTATE, (IntPtr)(actionMask | NativeMethods.UIS_SET), IntPtr.Zero); } @@ -4121,7 +4116,7 @@ protected internal virtual bool ShowFocusCues { // The side effect of this initial state is that adding new controls may clear the focus cue state // state (has been this way forever) UnsafeNativeMethods.SendMessage(new HandleRef(TopMostParent, TopMostParent.Handle), - NativeMethods.WM_CHANGEUISTATE, + Interop.WindowMessages.WM_CHANGEUISTATE, (IntPtr)(actionMask | NativeMethods.UIS_SET), IntPtr.Zero); @@ -5402,7 +5397,7 @@ internal void BeginUpdateInternal() { if (!IsHandleCreated) { return; } - if (updateCount == 0) SendMessage(NativeMethods.WM_SETREDRAW, 0, 0); + if (updateCount == 0) SendMessage(Interop.WindowMessages.WM_SETREDRAW, 0, 0); updateCount++; } @@ -5770,7 +5765,7 @@ protected virtual void DestroyHandle() { } if (0 != (NativeMethods.WS_EX_MDICHILD & (int)(long)UnsafeNativeMethods.GetWindowLong(new HandleRef(window, InternalHandle), NativeMethods.GWL_EXSTYLE))) { - UnsafeNativeMethods.DefMDIChildProc(InternalHandle, NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + UnsafeNativeMethods.DefMDIChildProc(InternalHandle, Interop.WindowMessages.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); } else { window.DestroyHandle(); @@ -5963,7 +5958,7 @@ public void DrawToBitmap(Bitmap bitmap, Rectangle targetBounds) { using (Graphics g = Graphics.FromImage(image)) { IntPtr hDc = g.GetHdc(); //send the actual wm_print message - UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), NativeMethods.WM_PRINT, (IntPtr)hDc, + UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), Interop.WindowMessages.WM_PRINT, (IntPtr)hDc, (IntPtr)(NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT)); //now BLT the result to the destination bitmap. @@ -6029,7 +6024,7 @@ internal bool EndUpdateInternal(bool invalidate) { Debug.Assert(IsHandleCreated, "Handle should be created by now"); updateCount--; if (updateCount == 0) { - SendMessage(NativeMethods.WM_SETREDRAW, -1, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, -1, 0); if (invalidate) { Invalidate(); } @@ -6262,16 +6257,6 @@ public Control GetChildAtPoint(Point pt, GetChildAtPointSkip skipValue) { IntPtr hwnd = UnsafeNativeMethods.ChildWindowFromPointEx(new HandleRef(null, Handle), pt.X, pt.Y, value); - // Security Reviewed - // While doing a security review it was noticed that GetChildAtPoint - // does work to ensure that you can only gain access to children of your own control, - // but the methods it uses to determine the children demand all window permission first, - // negating the extra check. - // It is OK to return child windows for children within your own control for semitrust. - - // Hence calling the Internal methods to ByPass the Security Demand... - // for IntSecurity.ControlFromHandleOrLocation == ALLWindows. - Control ctl = FromChildHandleInternal(hwnd); return(ctl == this) ? null : ctl; @@ -6804,7 +6789,7 @@ public Control GetNextControl(Control ctl, bool forward) { /// /// Return ((Control) window).Handle if window is a Control. - /// Otherwise, demands permission for AllWindows and returns window.Handle + /// Otherwise, returns window.Handle /// internal static IntPtr GetSafeHandle(IWin32Window window) { @@ -6912,7 +6897,6 @@ internal virtual IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg) { } } - #if WIN95_SUPPORT /// /// Initializes mouse wheel support. This may involve registering some windows /// messages on older operating systems. @@ -6949,7 +6933,6 @@ private void InitMouseWheelSupport() { mouseWheelInit = true; } } - #endif /// /// @@ -7371,7 +7354,7 @@ protected virtual bool IsInputChar(char charCode) { else { mask = NativeMethods.DLGC_WANTCHARS | NativeMethods.DLGC_WANTALLKEYS; } - return(unchecked( (int) (long)SendMessage(NativeMethods.WM_GETDLGCODE, 0, 0)) & mask) != 0; + return(unchecked( (int) (long)SendMessage(Interop.WindowMessages.WM_GETDLGCODE, 0, 0)) & mask) != 0; } /// @@ -7403,7 +7386,7 @@ protected virtual bool IsInputKey(Keys keyData) { } if (IsHandleCreated) { - return(unchecked( (int) (long)SendMessage(NativeMethods.WM_GETDLGCODE, 0, 0)) & mask) != 0; + return(unchecked( (int) (long)SendMessage(Interop.WindowMessages.WM_GETDLGCODE, 0, 0)) & mask) != 0; } else { return false; @@ -8176,7 +8159,7 @@ protected virtual void OnPrint(PaintEventArgs e) { hdc = e.Graphics.GetHdc(); releaseDC = true; } - m = Message.Create(this.Handle, NativeMethods.WM_PRINTCLIENT, hdc, flags); + m = Message.Create(this.Handle, Interop.WindowMessages.WM_PRINTCLIENT, hdc, flags); } else { m = ppev.Message; @@ -8456,11 +8439,11 @@ private void OnSetScrollPosition(object sender, EventArgs e) { internal virtual void OnInvokedSetScrollPosition(object sender, EventArgs e) { if (!(this is ScrollableControl) && !IsMirrored) { NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); - si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); + si.cbSize = Marshal.SizeOf(); si.fMask = NativeMethods.SIF_RANGE; if (UnsafeNativeMethods.GetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_HORZ,si) != false) { si.nPos = (RightToLeft == RightToLeft.Yes) ? si.nMax : si.nMin; - SendMessage(NativeMethods.WM_HSCROLL, NativeMethods.Util.MAKELPARAM(NativeMethods.SB_THUMBPOSITION, si.nPos), 0); + SendMessage(Interop.WindowMessages.WM_HSCROLL, NativeMethods.Util.MAKELPARAM(NativeMethods.SB_THUMBPOSITION, si.nPos), 0); } } } @@ -8623,9 +8606,7 @@ protected virtual void OnEnter(EventArgs e) { protected void InvokeGotFocus(Control toInvoke, EventArgs e) { if (toInvoke != null) { toInvoke.OnGotFocus(e); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(toInvoke); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(toInvoke); } } @@ -8648,25 +8629,28 @@ protected virtual void OnGotFocus(EventArgs e) { if (handler != null) handler(this,e); } - /// - /// - /// Inheriting classes should override this method to handle this event. - /// Call base.onHelp to send this event to any registered event listeners. - /// + /// + /// Inheriting classes should override this method to handle this event. + /// Call base.onHelp to send this event to any registered event listeners. + /// [EditorBrowsable(EditorBrowsableState.Advanced)] - protected virtual void OnHelpRequested(HelpEventArgs hevent) { - Contract.Requires(hevent != null); + protected virtual void OnHelpRequested(HelpEventArgs hevent) + { HelpEventHandler handler = (HelpEventHandler)Events[EventHelpRequested]; - if (handler != null) { + if (handler != null) + { handler(this,hevent); - // Set this to true so that multiple events aren't raised to the Form. - hevent.Handled = true; + // Mark the event as handled so that the event isn't raised for the + // control's parent. + if (hevent != null) + { + hevent.Handled = true; + } } - if (!hevent.Handled) { - if (ParentInternal != null) { - ParentInternal.OnHelpRequested(hevent); - } + if (hevent != null && !hevent.Handled) + { + ParentInternal?.OnHelpRequested(hevent); } } @@ -8792,9 +8776,7 @@ protected virtual void OnLeave(EventArgs e) { protected void InvokeLostFocus(Control toInvoke, EventArgs e) { if (toInvoke != null) { toInvoke.OnLostFocus(e); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(toInvoke); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(toInvoke); } } @@ -9742,7 +9724,7 @@ public virtual bool PreProcessMessage(ref Message msg) { bool ret; - if (msg.Msg == NativeMethods.WM_KEYDOWN || msg.Msg == NativeMethods.WM_SYSKEYDOWN) { + if (msg.Msg == Interop.WindowMessages.WM_KEYDOWN || msg.Msg == Interop.WindowMessages.WM_SYSKEYDOWN) { if (!GetState2(STATE2_UICUES)) { ProcessUICues(ref msg); } @@ -9759,8 +9741,8 @@ public virtual bool PreProcessMessage(ref Message msg) { ret = ProcessDialogKey(keyData); } } - else if (msg.Msg == NativeMethods.WM_CHAR || msg.Msg == NativeMethods.WM_SYSCHAR) { - if (msg.Msg == NativeMethods.WM_CHAR && IsInputChar((char)msg.WParam)) { + else if (msg.Msg == Interop.WindowMessages.WM_CHAR || msg.Msg == Interop.WindowMessages.WM_SYSCHAR) { + if (msg.Msg == Interop.WindowMessages.WM_CHAR && IsInputChar((char)msg.WParam)) { SetState2(STATE2_INPUTCHAR, true); ret = false; } @@ -9823,7 +9805,7 @@ internal static PreProcessControlState PreProcessControlMessageInternal(Control Keys keyData = (Keys)(unchecked((int)(long)msg.WParam) | (int)ModifierKeys); // Allow control to preview key down message. - if (msg.Msg == NativeMethods.WM_KEYDOWN || msg.Msg == NativeMethods.WM_SYSKEYDOWN) { + if (msg.Msg == Interop.WindowMessages.WM_KEYDOWN || msg.Msg == Interop.WindowMessages.WM_SYSKEYDOWN) { target.ProcessUICues(ref msg); PreviewKeyDownEventArgs args = new PreviewKeyDownEventArgs(keyData); @@ -9839,7 +9821,7 @@ internal static PreProcessControlState PreProcessControlMessageInternal(Control PreProcessControlState state = PreProcessControlState.MessageNotNeeded; if (!target.PreProcessMessage(ref msg)) { - if (msg.Msg == NativeMethods.WM_KEYDOWN || msg.Msg == NativeMethods.WM_SYSKEYDOWN) { + if (msg.Msg == Interop.WindowMessages.WM_KEYDOWN || msg.Msg == Interop.WindowMessages.WM_SYSKEYDOWN) { // check if IsInputKey has already procssed this message // or if it is safe to call - we only want it to be called once. @@ -9848,7 +9830,7 @@ internal static PreProcessControlState PreProcessControlMessageInternal(Control state = PreProcessControlState.MessageNeeded; } } - else if (msg.Msg == NativeMethods.WM_CHAR || msg.Msg == NativeMethods.WM_SYSCHAR) { + else if (msg.Msg == Interop.WindowMessages.WM_CHAR || msg.Msg == Interop.WindowMessages.WM_SYSCHAR) { // check if IsInputChar has already procssed this message // or if it is safe to call - we only want it to be called once. @@ -9976,7 +9958,7 @@ internal virtual void PrintToMetaFileRecursive(HandleRef hDC, IntPtr lParam, Rec private void PrintToMetaFile_SendPrintMessage(HandleRef hDC, IntPtr lParam) { if(GetStyle(ControlStyles.UserPaint)) { // We let user paint controls paint directly into the metafile - SendMessage(NativeMethods.WM_PRINT, hDC.Handle, lParam); + SendMessage(Interop.WindowMessages.WM_PRINT, hDC.Handle, lParam); } else { // If a system control has no children in the Controls collection we @@ -9991,7 +9973,7 @@ private void PrintToMetaFile_SendPrintMessage(HandleRef hDC, IntPtr lParam) { // which is then copied into the metafile. (Old GDI line drawing // is 1px thin, which causes borders to disappear, etc.) using (MetafileDCWrapper dcWrapper = new MetafileDCWrapper(hDC, this.Size)) { - SendMessage(NativeMethods.WM_PRINT, dcWrapper.HDC, lParam); + SendMessage(Interop.WindowMessages.WM_PRINT, dcWrapper.HDC, lParam); } } } @@ -10080,7 +10062,7 @@ protected virtual bool ProcessKeyEventArgs(ref Message m) { KeyPressEventArgs kpe = null; IntPtr newWParam = IntPtr.Zero; - if (m.Msg == NativeMethods.WM_CHAR || m.Msg == NativeMethods.WM_SYSCHAR) { + if (m.Msg == Interop.WindowMessages.WM_CHAR || m.Msg == Interop.WindowMessages.WM_SYSCHAR) { int charsToIgnore = this.ImeWmCharsToIgnore; if (charsToIgnore > 0) { @@ -10096,7 +10078,7 @@ protected virtual bool ProcessKeyEventArgs(ref Message m) { newWParam = (IntPtr) kpe.KeyChar; } } - else if (m.Msg == NativeMethods.WM_IME_CHAR) { + else if (m.Msg == Interop.WindowMessages.WM_IME_CHAR) { int charsToIgnore = this.ImeWmCharsToIgnore; charsToIgnore += (3 - sizeof(char)); @@ -10117,7 +10099,7 @@ protected virtual bool ProcessKeyEventArgs(ref Message m) { } else { ke = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys); - if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN) { + if (m.Msg == Interop.WindowMessages.WM_KEYDOWN || m.Msg == Interop.WindowMessages.WM_SYSKEYDOWN) { OnKeyDown(ke); } else { @@ -10133,9 +10115,9 @@ protected virtual bool ProcessKeyEventArgs(ref Message m) { else { Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, " processkeyeventarg returning: " + ke.Handled); if (ke.SuppressKeyPress) { - RemovePendingMessages(NativeMethods.WM_CHAR, NativeMethods.WM_CHAR); - RemovePendingMessages(NativeMethods.WM_SYSCHAR, NativeMethods.WM_SYSCHAR); - RemovePendingMessages(NativeMethods.WM_IME_CHAR, NativeMethods.WM_IME_CHAR); + RemovePendingMessages(Interop.WindowMessages.WM_CHAR, Interop.WindowMessages.WM_CHAR); + RemovePendingMessages(Interop.WindowMessages.WM_SYSCHAR, Interop.WindowMessages.WM_SYSCHAR); + RemovePendingMessages(Interop.WindowMessages.WM_IME_CHAR, Interop.WindowMessages.WM_IME_CHAR); } return ke.Handled; } @@ -10236,13 +10218,13 @@ internal void ProcessUICues(ref Message msg) { } Control topMostParent = null; - int current = unchecked( (int) (long)SendMessage(NativeMethods.WM_QUERYUISTATE, 0, 0)); + int current = unchecked( (int) (long)SendMessage(Interop.WindowMessages.WM_QUERYUISTATE, 0, 0)); // dont trust when a control says the accelerators are showing. // make sure the topmost parent agrees with this as we could be in a mismatched state. if (current == 0 /*accelerator and focus cues are showing*/) { topMostParent = this.TopMostParent; - current = (int)topMostParent.SendMessage(NativeMethods.WM_QUERYUISTATE, 0, 0); + current = (int)topMostParent.SendMessage(Interop.WindowMessages.WM_QUERYUISTATE, 0, 0); } int toClear = 0; @@ -10284,7 +10266,7 @@ internal void ProcessUICues(ref Message msg) { // (we're in charge here, we've got to change the state of the root window) UnsafeNativeMethods.SendMessage( new HandleRef(topMostParent, topMostParent.Handle), - UnsafeNativeMethods.GetParent(new HandleRef(null, topMostParent.Handle)) == IntPtr.Zero ? NativeMethods.WM_CHANGEUISTATE : NativeMethods.WM_UPDATEUISTATE, + UnsafeNativeMethods.GetParent(new HandleRef(null, topMostParent.Handle)) == IntPtr.Zero ? Interop.WindowMessages.WM_CHANGEUISTATE : Interop.WindowMessages.WM_UPDATEUISTATE, (IntPtr)(NativeMethods.UIS_CLEAR | (toClear << 16)), IntPtr.Zero); } @@ -10545,7 +10527,7 @@ protected static bool ReflectMessage(IntPtr hWnd, ref Message m) { internal static bool ReflectMessageInternal(IntPtr hWnd, ref Message m) { Control control = Control.FromHandleInternal(hWnd); if (control == null) return false; - m.Result = control.SendMessage(NativeMethods.WM_REFLECT + m.Msg, m.WParam, m.LParam); + m.Result = control.SendMessage(Interop.WindowMessages.WM_REFLECT + m.Msg, m.WParam, m.LParam); return true; } @@ -11116,7 +11098,7 @@ private Control GetNextSelectableControl(Control ctl, bool forward, bool tabStop && (!tabStopOnly || ctl.TabStop) && (nested || ctl.parent == this)) { - if (AccessibilityImprovements.Level3 && ctl.parent is ToolStrip) { + if (ctl.parent is ToolStrip) { continue; } return ctl; @@ -11794,7 +11776,7 @@ protected internal ContentAlignment RtlTranslateContent(ContentAlignment align) } private void SetWindowFont(){ - SendMessage(NativeMethods.WM_SETFONT, FontHandle, 0 /*redraw = false*/); + SendMessage(Interop.WindowMessages.WM_SETFONT, FontHandle, 0 /*redraw = false*/); } private void SetWindowStyle(int flag, bool value) { @@ -12184,7 +12166,7 @@ private void WmClose(ref Message m) { } if (lastParentHandle != IntPtr.Zero) { - UnsafeNativeMethods.PostMessage(new HandleRef(null, lastParentHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + UnsafeNativeMethods.PostMessage(new HandleRef(null, lastParentHandle), Interop.WindowMessages.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); } } @@ -12406,7 +12388,7 @@ private void WmGetObject(ref Message m) { InternalAccessibleObject intAccessibleObject = null; - if (m.Msg == NativeMethods.WM_GETOBJECT && m.LParam == (IntPtr)NativeMethods.UiaRootObjectId && this.SupportsUiaProviders) { + if (m.Msg == Interop.WindowMessages.WM_GETOBJECT && m.LParam == (IntPtr)NativeMethods.UiaRootObjectId && this.SupportsUiaProviders) { // If the requested object identifier is UiaRootObjectId, // we should return an UI Automation provider using the UiaReturnRawElementProvider function. intAccessibleObject = new InternalAccessibleObject(this.AccessibilityObject); @@ -12750,9 +12732,7 @@ private void WmMouseDown(ref Message m, MouseButtons button, int clicks) { /// private void WmMouseEnter(ref Message m) { DefWndProc(ref m); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutMouseEnter(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutMouseEnter(this); OnMouseEnter(EventArgs.Empty); } @@ -12849,7 +12829,7 @@ private void WmMouseUp(ref Message m, MouseButtons button, int clicks) { // (for a right button click), but since we're skipping DefWndProc // we have to do it ourselves. if (button == MouseButtons.Right) { - SendMessage(NativeMethods.WM_CONTEXTMENU, this.Handle, NativeMethods.Util.MAKELPARAM(pt.X, pt.Y)); + SendMessage(Interop.WindowMessages.WM_CONTEXTMENU, this.Handle, NativeMethods.Util.MAKELPARAM(pt.X, pt.Y)); } } @@ -12932,11 +12912,11 @@ private unsafe void WmNotify(ref Message m) { NativeMethods.NMHDR* nmhdr = (NativeMethods.NMHDR*)m.LParam; if (!ReflectMessageInternal(nmhdr->hwndFrom,ref m)) { if(nmhdr->code == NativeMethods.TTN_SHOW) { - m.Result = UnsafeNativeMethods.SendMessage(new HandleRef(null, nmhdr->hwndFrom), NativeMethods.WM_REFLECT + m.Msg, m.WParam, m.LParam); + m.Result = UnsafeNativeMethods.SendMessage(new HandleRef(null, nmhdr->hwndFrom), Interop.WindowMessages.WM_REFLECT + m.Msg, m.WParam, m.LParam); return; } if(nmhdr->code == NativeMethods.TTN_POP) { - UnsafeNativeMethods.SendMessage(new HandleRef(null, nmhdr->hwndFrom), NativeMethods.WM_REFLECT + m.Msg, m.WParam, m.LParam); + UnsafeNativeMethods.SendMessage(new HandleRef(null, nmhdr->hwndFrom), Interop.WindowMessages.WM_REFLECT + m.Msg, m.WParam, m.LParam); } DefWndProc(ref m); @@ -12975,7 +12955,7 @@ private void WmOwnerDraw(ref Message m) { if (handle != IntPtr.Zero) { Control control = Control.FromHandleInternal(handle); if (control != null) { - m.Result = control.SendMessage(NativeMethods.WM_REFLECT + m.Msg, handle, m.LParam); + m.Result = control.SendMessage(Interop.WindowMessages.WM_REFLECT + m.Msg, handle, m.LParam); reflectCalled = true; } } @@ -13211,10 +13191,10 @@ private void WmParentNotify(ref Message m) { int msg = NativeMethods.Util.LOWORD(m.WParam); IntPtr hWnd = IntPtr.Zero; switch (msg) { - case NativeMethods.WM_CREATE: + case Interop.WindowMessages.WM_CREATE: hWnd = m.LParam; break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: break; default: hWnd = UnsafeNativeMethods.GetDlgItem(new HandleRef(this, Handle), NativeMethods.Util.HIWORD(m.WParam)); @@ -13456,47 +13436,47 @@ protected virtual void WndProc(ref Message m) { * messages which the Ocx would own before passing them onto Control.wndProc. */ switch (m.Msg) { - case NativeMethods.WM_CAPTURECHANGED: + case Interop.WindowMessages.WM_CAPTURECHANGED: WmCaptureChanged(ref m); break; - case NativeMethods.WM_GETOBJECT: + case Interop.WindowMessages.WM_GETOBJECT: WmGetObject(ref m); break; - case NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_COMMAND: WmCommand(ref m); break; - case NativeMethods.WM_CLOSE: + case Interop.WindowMessages.WM_CLOSE: WmClose(ref m); break; - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_CONTEXTMENU: WmContextMenu(ref m); break; - case NativeMethods.WM_DISPLAYCHANGE: + case Interop.WindowMessages.WM_DISPLAYCHANGE: WmDisplayChange(ref m); break; - case NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_DRAWITEM: WmDrawItem(ref m); break; - case NativeMethods.WM_ERASEBKGND: + case Interop.WindowMessages.WM_ERASEBKGND: WmEraseBkgnd(ref m); break; - case NativeMethods.WM_EXITMENULOOP: + case Interop.WindowMessages.WM_EXITMENULOOP: WmExitMenuLoop(ref m); break; - case NativeMethods.WM_HELP: + case Interop.WindowMessages.WM_HELP: WmHelp(ref m); break; - case NativeMethods.WM_PAINT: + case Interop.WindowMessages.WM_PAINT: if (GetStyle(ControlStyles.UserPaint)) { WmPaint(ref m); } @@ -13505,7 +13485,7 @@ protected virtual void WndProc(ref Message m) { } break; - case NativeMethods.WM_PRINTCLIENT: + case Interop.WindowMessages.WM_PRINTCLIENT: if (GetStyle(ControlStyles.UserPaint)) { WmPrintClient(ref m); } @@ -13514,11 +13494,11 @@ protected virtual void WndProc(ref Message m) { } break; - case NativeMethods.WM_INITMENUPOPUP: + case Interop.WindowMessages.WM_INITMENUPOPUP: WmInitMenuPopup(ref m); break; - case NativeMethods.WM_SYSCOMMAND: + case Interop.WindowMessages.WM_SYSCOMMAND: if ((unchecked((int)(long)m.WParam) & 0xFFF0) == NativeMethods.SC_KEYMENU) { Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "Control.WndProc processing " + m.ToString()); @@ -13531,229 +13511,229 @@ protected virtual void WndProc(ref Message m) { DefWndProc(ref m); break; - case NativeMethods.WM_INPUTLANGCHANGE: + case Interop.WindowMessages.WM_INPUTLANGCHANGE: WmInputLangChange(ref m); break; - case NativeMethods.WM_INPUTLANGCHANGEREQUEST: + case Interop.WindowMessages.WM_INPUTLANGCHANGEREQUEST: WmInputLangChangeRequest(ref m); break; - case NativeMethods.WM_MEASUREITEM: + case Interop.WindowMessages.WM_MEASUREITEM: WmMeasureItem(ref m); break; - case NativeMethods.WM_MENUCHAR: + case Interop.WindowMessages.WM_MENUCHAR: WmMenuChar(ref m); break; - case NativeMethods.WM_MENUSELECT: + case Interop.WindowMessages.WM_MENUSELECT: WmMenuSelect(ref m); break; - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: WmSetCursor(ref m); break; - case NativeMethods.WM_WINDOWPOSCHANGING: + case Interop.WindowMessages.WM_WINDOWPOSCHANGING: WmWindowPosChanging(ref m); break; - case NativeMethods.WM_CHAR: - case NativeMethods.WM_KEYDOWN: - case NativeMethods.WM_SYSKEYDOWN: - case NativeMethods.WM_KEYUP: - case NativeMethods.WM_SYSKEYUP: + case Interop.WindowMessages.WM_CHAR: + case Interop.WindowMessages.WM_KEYDOWN: + case Interop.WindowMessages.WM_SYSKEYDOWN: + case Interop.WindowMessages.WM_KEYUP: + case Interop.WindowMessages.WM_SYSKEYUP: WmKeyChar(ref m); break; - case NativeMethods.WM_CREATE: + case Interop.WindowMessages.WM_CREATE: WmCreate(ref m); break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: WmDestroy(ref m); break; - case NativeMethods.WM_CTLCOLOR: - case NativeMethods.WM_CTLCOLORBTN: - case NativeMethods.WM_CTLCOLORDLG: - case NativeMethods.WM_CTLCOLORMSGBOX: - case NativeMethods.WM_CTLCOLORSCROLLBAR: - case NativeMethods.WM_CTLCOLOREDIT: - case NativeMethods.WM_CTLCOLORLISTBOX: - case NativeMethods.WM_CTLCOLORSTATIC: + case Interop.WindowMessages.WM_CTLCOLOR: + case Interop.WindowMessages.WM_CTLCOLORBTN: + case Interop.WindowMessages.WM_CTLCOLORDLG: + case Interop.WindowMessages.WM_CTLCOLORMSGBOX: + case Interop.WindowMessages.WM_CTLCOLORSCROLLBAR: + case Interop.WindowMessages.WM_CTLCOLOREDIT: + case Interop.WindowMessages.WM_CTLCOLORLISTBOX: + case Interop.WindowMessages.WM_CTLCOLORSTATIC: // this is for the trinity guys. The case is if you've got a windows // forms edit or something hosted as an AX control somewhere, there isn't anyone to reflect // these back. If they went ahead and just sent them back, some controls don't like that // and end up recursing. Our code handles it fine because we just pick the HWND out of the LPARAM. // - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLOR: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLORBTN: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLORDLG: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLORMSGBOX: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLORSCROLLBAR: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLOREDIT: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLORLISTBOX: - case NativeMethods.WM_REFLECT + NativeMethods.WM_CTLCOLORSTATIC: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLOR: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLORBTN: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLORDLG: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLORMSGBOX: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLORSCROLLBAR: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLOREDIT: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLORLISTBOX: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_CTLCOLORSTATIC: WmCtlColorControl(ref m); break; - case NativeMethods.WM_HSCROLL: - case NativeMethods.WM_VSCROLL: - case NativeMethods.WM_DELETEITEM: - case NativeMethods.WM_VKEYTOITEM: - case NativeMethods.WM_CHARTOITEM: - case NativeMethods.WM_COMPAREITEM: + case Interop.WindowMessages.WM_HSCROLL: + case Interop.WindowMessages.WM_VSCROLL: + case Interop.WindowMessages.WM_DELETEITEM: + case Interop.WindowMessages.WM_VKEYTOITEM: + case Interop.WindowMessages.WM_CHARTOITEM: + case Interop.WindowMessages.WM_COMPAREITEM: if (!ReflectMessageInternal(m.LParam, ref m)) { DefWndProc(ref m); } break; - case NativeMethods.WM_IME_CHAR: + case Interop.WindowMessages.WM_IME_CHAR: WmImeChar(ref m); break; - case NativeMethods.WM_IME_STARTCOMPOSITION: + case Interop.WindowMessages.WM_IME_STARTCOMPOSITION: WmImeStartComposition(ref m); break; - case NativeMethods.WM_IME_ENDCOMPOSITION: + case Interop.WindowMessages.WM_IME_ENDCOMPOSITION: WmImeEndComposition(ref m); break; - case NativeMethods.WM_IME_NOTIFY: + case Interop.WindowMessages.WM_IME_NOTIFY: WmImeNotify(ref m); break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: WmKillFocus(ref m); break; - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Left, 2); if (GetStyle(ControlStyles.StandardDoubleClick)) { SetState(STATE_DOUBLECLICKFIRED, true); } break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: WmMouseDown(ref m, MouseButtons.Left, 1); break; - case NativeMethods.WM_LBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: WmMouseUp(ref m, MouseButtons.Left, 1); break; - case NativeMethods.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Middle, 2); if (GetStyle(ControlStyles.StandardDoubleClick)) { SetState(STATE_DOUBLECLICKFIRED, true); } break; - case NativeMethods.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: WmMouseDown(ref m, MouseButtons.Middle, 1); break; - case NativeMethods.WM_MBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONUP: WmMouseUp(ref m, MouseButtons.Middle, 1); break; - case NativeMethods.WM_XBUTTONDOWN: + case Interop.WindowMessages.WM_XBUTTONDOWN: WmMouseDown(ref m, GetXButton(NativeMethods.Util.HIWORD(m.WParam)), 1); break; - case NativeMethods.WM_XBUTTONUP: + case Interop.WindowMessages.WM_XBUTTONUP: WmMouseUp(ref m, GetXButton(NativeMethods.Util.HIWORD(m.WParam)), 1); break; - case NativeMethods.WM_XBUTTONDBLCLK: + case Interop.WindowMessages.WM_XBUTTONDBLCLK: WmMouseDown(ref m, GetXButton(NativeMethods.Util.HIWORD(m.WParam)), 2); if (GetStyle(ControlStyles.StandardDoubleClick)) { SetState(STATE_DOUBLECLICKFIRED, true); } break; - case NativeMethods.WM_MOUSELEAVE: + case Interop.WindowMessages.WM_MOUSELEAVE: WmMouseLeave(ref m); break; - case NativeMethods.WM_DPICHANGED_BEFOREPARENT: + case Interop.WindowMessages.WM_DPICHANGED_BEFOREPARENT: WmDpiChangedBeforeParent(ref m); m.Result = IntPtr.Zero; break; - case NativeMethods.WM_DPICHANGED_AFTERPARENT: + case Interop.WindowMessages.WM_DPICHANGED_AFTERPARENT: WmDpiChangedAfterParent(ref m); m.Result = IntPtr.Zero; break; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: WmMouseMove(ref m); break; - case NativeMethods.WM_MOUSEWHEEL: + case Interop.WindowMessages.WM_MOUSEWHEEL: WmMouseWheel(ref m); break; - case NativeMethods.WM_MOVE: + case Interop.WindowMessages.WM_MOVE: WmMove(ref m); break; - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: WmNotify(ref m); break; - case NativeMethods.WM_NOTIFYFORMAT: + case Interop.WindowMessages.WM_NOTIFYFORMAT: WmNotifyFormat(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFYFORMAT: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFYFORMAT: m.Result = (IntPtr)(NativeMethods.NFR_UNICODE); break; - case NativeMethods.WM_SHOWWINDOW: + case Interop.WindowMessages.WM_SHOWWINDOW: WmShowWindow(ref m); break; - case NativeMethods.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Right, 2); if (GetStyle(ControlStyles.StandardDoubleClick)) { SetState(STATE_DOUBLECLICKFIRED, true); } break; - case NativeMethods.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: WmMouseDown(ref m, MouseButtons.Right, 1); break; - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: WmMouseUp(ref m, MouseButtons.Right, 1); break; - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: WmSetFocus(ref m); break; - case NativeMethods.WM_MOUSEHOVER: + case Interop.WindowMessages.WM_MOUSEHOVER: WmMouseHover(ref m); break; - case NativeMethods.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: WmWindowPosChanged(ref m); break; - case NativeMethods.WM_QUERYNEWPALETTE: + case Interop.WindowMessages.WM_QUERYNEWPALETTE: WmQueryNewPalette(ref m); break; - case NativeMethods.WM_UPDATEUISTATE: + case Interop.WindowMessages.WM_UPDATEUISTATE: WmUpdateUIState(ref m); break; - case NativeMethods.WM_PARENTNOTIFY: + case Interop.WindowMessages.WM_PARENTNOTIFY: WmParentNotify(ref m); break; @@ -13773,7 +13753,6 @@ protected virtual void WndProc(ref Message m) { return; } - #if WIN95_SUPPORT // If we have to route the mousewheel messages, do it (this logic was taken // from the MFC sources...) // @@ -13794,7 +13773,7 @@ protected virtual void WndProc(ref Message m) { while (result == IntPtr.Zero && hwndFocus != IntPtr.Zero && hwndFocus != hwndDesktop) { result = UnsafeNativeMethods.SendMessage(new HandleRef(null, hwndFocus), - NativeMethods.WM_MOUSEWHEEL, + Interop.WindowMessages.WM_MOUSEWHEEL, (unchecked((int)(long)m.WParam) << 16) | (int)keyState, m.LParam); hwndFocus = UnsafeNativeMethods.GetParent(new HandleRef(null, hwndFocus)); @@ -13802,7 +13781,6 @@ protected virtual void WndProc(ref Message m) { } } } - #endif if (m.Msg == NativeMethods.WM_MOUSEENTER) { WmMouseEnter(ref m); @@ -14004,11 +13982,11 @@ protected override void WndProc(ref Message m) { // to occur within control. // switch (m.Msg) { - case NativeMethods.WM_MOUSELEAVE: + case Interop.WindowMessages.WM_MOUSELEAVE: control.UnhookMouseEvent(); break; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: if (!control.GetState(Control.STATE_TRACKINGMOUSEEVENT)) { control.HookMouseEvent(); if (!control.GetState(Control.STATE_MOUSEENTERPENDING)) { @@ -14020,7 +13998,7 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_MOUSEWHEEL: + case Interop.WindowMessages.WM_MOUSEWHEEL: // TrackMouseEvent's mousehover implementation doesn't watch the wheel // correctly... // @@ -14623,7 +14601,7 @@ public object Current { int UnsafeNativeMethods.IOleControl.GetControlInfo(NativeMethods.tagCONTROLINFO pCI) { Debug.WriteLineIf(CompModSwitches.ActiveX.TraceInfo, "AxSource:GetControlInfo"); - pCI.cb = Marshal.SizeOf(typeof(NativeMethods.tagCONTROLINFO)); + pCI.cb = Marshal.SizeOf(); pCI.hAccel = IntPtr.Zero; pCI.cAccel = 0; pCI.dwFlags = 0; @@ -15826,8 +15804,8 @@ internal bool IsIE { Debug.WriteLineIf(CompModSwitches.ActiveX.TraceVerbose, "AxSource:IsIE running under IE"); } - if (container != null && UnsafeNativeMethods.IsComObject(container)) { - UnsafeNativeMethods.ReleaseComObject(container); + if (container != null && Marshal.IsComObject(container)) { + Marshal.ReleaseComObject(container); } } @@ -15902,10 +15880,10 @@ internal void DoVerb(int iVerb, IntPtr lpmsg, UnsafeNativeMethods.IOleClientSite // is valid. // if (lpmsg != IntPtr.Zero) { - NativeMethods.MSG msg = (NativeMethods.MSG)UnsafeNativeMethods.PtrToStructure(lpmsg, typeof(NativeMethods.MSG)); + NativeMethods.MSG msg = Marshal.PtrToStructure(lpmsg); Control target = control; - if (msg.hwnd != control.Handle && msg.message >= NativeMethods.WM_MOUSEFIRST && msg.message <= NativeMethods.WM_MOUSELAST) { + if (msg.hwnd != control.Handle && msg.message >= Interop.WindowMessages.WM_MOUSEFIRST && msg.message <= Interop.WindowMessages.WM_MOUSELAST) { // Must translate message coordniates over to our HWND. We first try // @@ -15935,7 +15913,7 @@ internal void DoVerb(int iVerb, IntPtr lpmsg, UnsafeNativeMethods.IOleClientSite } #endif // DEBUG - if (msg.message == NativeMethods.WM_KEYDOWN && msg.wParam == (IntPtr)NativeMethods.VK_TAB) { + if (msg.message == Interop.WindowMessages.WM_KEYDOWN && msg.wParam == (IntPtr)NativeMethods.VK_TAB) { target.SelectNextControl(null, Control.ModifierKeys != Keys.Shift, true, true, true); } else { @@ -16049,7 +16027,7 @@ internal void Draw(int dwDrawAspect, int lindex, IntPtr pvAspect, NativeMethods. //| NativeMethods.PRF_OWNED)); if(hdcType != NativeMethods.OBJ_ENHMETADC) { - control.SendMessage(NativeMethods.WM_PRINT, hdcDraw, flags); + control.SendMessage(Interop.WindowMessages.WM_PRINT, hdcDraw, flags); } else { control.PrintToMetaFile(new HandleRef(null, hdcDraw), flags); } @@ -16202,7 +16180,7 @@ internal int GetControlInfo(NativeMethods.tagCONTROLINFO pCI) { accelCount = (short)mnemonicList.Count; if (accelCount > 0) { - int accelSize = UnsafeNativeMethods.SizeOf(typeof(NativeMethods.ACCEL)); + int accelSize = Marshal.SizeOf(); // In the worst case we may have two accelerators per mnemonic: one lower case and // one upper case, hence the * 2 below. @@ -16393,7 +16371,7 @@ internal void InPlaceActivate(int verb) if (!activeXState[inPlaceVisible]) { Debug.WriteLineIf(CompModSwitches.ActiveX.TraceVerbose, "\tActiveXImpl:InPlaceActivate --> inplacevisible"); NativeMethods.tagOIFI inPlaceFrameInfo = new NativeMethods.tagOIFI(); - inPlaceFrameInfo.cb = UnsafeNativeMethods.SizeOf(typeof(NativeMethods.tagOIFI)); + inPlaceFrameInfo.cb = Marshal.SizeOf(); IntPtr hwndParent = IntPtr.Zero; // We are entering a secure context here. @@ -16405,13 +16383,13 @@ internal void InPlaceActivate(int verb) NativeMethods.COMRECT posRect = new NativeMethods.COMRECT(); NativeMethods.COMRECT clipRect = new NativeMethods.COMRECT(); - if (inPlaceUiWindow != null && UnsafeNativeMethods.IsComObject(inPlaceUiWindow)) { - UnsafeNativeMethods.ReleaseComObject(inPlaceUiWindow); + if (inPlaceUiWindow != null && Marshal.IsComObject(inPlaceUiWindow)) { + Marshal.ReleaseComObject(inPlaceUiWindow); inPlaceUiWindow = null; } - if (inPlaceFrame != null && UnsafeNativeMethods.IsComObject(inPlaceFrame)) { - UnsafeNativeMethods.ReleaseComObject(inPlaceFrame); + if (inPlaceFrame != null && Marshal.IsComObject(inPlaceFrame)) { + Marshal.ReleaseComObject(inPlaceFrame); inPlaceFrame = null; } @@ -16432,9 +16410,7 @@ internal void InPlaceActivate(int verb) this.hwndParent = hwndParent; UnsafeNativeMethods.SetParent(new HandleRef(control, control.Handle), new HandleRef(null, hwndParent)); - // Now create our handle if it hasn't already been done. Note that because - // this raises events to the user that it CANNOT be done with a security assertion - // in place! + // Now create our handle if it hasn't already been done. // control.CreateControl(); @@ -16478,14 +16454,14 @@ internal void InPlaceActivate(int verb) int hr = inPlaceFrame.SetBorderSpace(null); if (NativeMethods.Failed(hr) && hr != NativeMethods.OLE_E_INVALIDRECT && hr != NativeMethods.INPLACE_E_NOTOOLSPACE && hr != NativeMethods.E_NOTIMPL) { - UnsafeNativeMethods.ThrowExceptionForHR(hr); + Marshal.ThrowExceptionForHR(hr); } if (inPlaceUiWindow != null) { hr = inPlaceFrame.SetBorderSpace(null); if (NativeMethods.Failed(hr) && hr != NativeMethods.OLE_E_INVALIDRECT && hr != NativeMethods.INPLACE_E_NOTOOLSPACE && hr != NativeMethods.E_NOTIMPL) { - UnsafeNativeMethods.ThrowExceptionForHR(hr); + Marshal.ThrowExceptionForHR(hr); } } } @@ -16529,13 +16505,13 @@ internal void InPlaceDeactivate() { control.Visible = false; hwndParent = IntPtr.Zero; - if (inPlaceUiWindow != null && UnsafeNativeMethods.IsComObject(inPlaceUiWindow)) { - UnsafeNativeMethods.ReleaseComObject(inPlaceUiWindow); + if (inPlaceUiWindow != null && Marshal.IsComObject(inPlaceUiWindow)) { + Marshal.ReleaseComObject(inPlaceUiWindow); inPlaceUiWindow = null; } - if (inPlaceFrame != null && UnsafeNativeMethods.IsComObject(inPlaceFrame)) { - UnsafeNativeMethods.ReleaseComObject(inPlaceFrame); + if (inPlaceFrame != null && Marshal.IsComObject(inPlaceFrame)) { + Marshal.ReleaseComObject(inPlaceFrame); inPlaceFrame = null; } } @@ -16597,8 +16573,8 @@ internal void Load(UnsafeNativeMethods.IStorage stg) { Load(stream); stream = null; - if (UnsafeNativeMethods.IsComObject(stg)) { - UnsafeNativeMethods.ReleaseComObject(stg); + if (Marshal.IsComObject(stg)) { + Marshal.ReleaseComObject(stg); } } @@ -16614,8 +16590,8 @@ internal void Load(UnsafeNativeMethods.IStream stream) { bag.Read(stream); Load(bag, null); - if (UnsafeNativeMethods.IsComObject(stream)) { - UnsafeNativeMethods.ReleaseComObject(stream); + if (Marshal.IsComObject(stream)) { + Marshal.ReleaseComObject(stream); } } @@ -16717,8 +16693,8 @@ internal void Load(UnsafeNativeMethods.IPropertyBag pPropBag, UnsafeNativeMethod } } } - if (UnsafeNativeMethods.IsComObject(pPropBag)) { - UnsafeNativeMethods.ReleaseComObject(pPropBag); + if (Marshal.IsComObject(pPropBag)) { + Marshal.ReleaseComObject(pPropBag); } } @@ -16870,7 +16846,7 @@ internal void OnDocWindowActivate(int fActivate) { int hr = inPlaceFrame.SetBorderSpace(null); if (NativeMethods.Failed(hr) && hr != NativeMethods.INPLACE_E_NOTOOLSPACE && hr != NativeMethods.E_NOTIMPL) { - UnsafeNativeMethods.ThrowExceptionForHR(hr); + Marshal.ThrowExceptionForHR(hr); } } } @@ -16942,7 +16918,7 @@ internal void QuickActivate(UnsafeNativeMethods.tagQACONTAINER pQaContainer, Uns // int status; - pQaControl.cbSize = UnsafeNativeMethods.SizeOf(typeof(UnsafeNativeMethods.tagQACONTROL)); + pQaControl.cbSize = Marshal.SizeOf(); SetClientSite(pQaContainer.pClientSite); @@ -16981,12 +16957,12 @@ internal void QuickActivate(UnsafeNativeMethods.tagQACONTAINER pQaContainer, Uns } } - if (pQaContainer.pPropertyNotifySink != null && UnsafeNativeMethods.IsComObject(pQaContainer.pPropertyNotifySink)) { - UnsafeNativeMethods.ReleaseComObject(pQaContainer.pPropertyNotifySink); + if (pQaContainer.pPropertyNotifySink != null && Marshal.IsComObject(pQaContainer.pPropertyNotifySink)) { + Marshal.ReleaseComObject(pQaContainer.pPropertyNotifySink); } - if (pQaContainer.pUnkEventSink != null && UnsafeNativeMethods.IsComObject(pQaContainer.pUnkEventSink)) { - UnsafeNativeMethods.ReleaseComObject(pQaContainer.pUnkEventSink); + if (pQaContainer.pUnkEventSink != null && Marshal.IsComObject(pQaContainer.pUnkEventSink)) { + Marshal.ReleaseComObject(pQaContainer.pUnkEventSink); } } @@ -17141,7 +17117,7 @@ protected sealed override bool ReleaseHandle() { /// protected V LoadVtable() { IntPtr vtblptr = Marshal.ReadIntPtr(this.handle, 0); - return (V)Marshal.PtrToStructure(vtblptr, typeof(V)); + return Marshal.PtrToStructure(vtblptr); } } @@ -17264,7 +17240,7 @@ internal void Save(UnsafeNativeMethods.IStorage stg, bool fSameAsLoad) { UnsafeNativeMethods.IStream stream = stg.CreateStream(this.GetStreamName(), NativeMethods.STGM_WRITE | NativeMethods.STGM_SHARE_EXCLUSIVE | NativeMethods.STGM_CREATE, 0, 0); Debug.Assert(stream != null, "Stream should be non-null, or an exception should have been thrown."); Save(stream, true); - UnsafeNativeMethods.ReleaseComObject(stream); + Marshal.ReleaseComObject(stream); } /// @@ -17279,8 +17255,8 @@ internal void Save(UnsafeNativeMethods.IStream stream, bool fClearDirty) { Save(bag, fClearDirty, false); bag.Write(stream); - if (UnsafeNativeMethods.IsComObject(stream)) { - UnsafeNativeMethods.ReleaseComObject(stream); + if (Marshal.IsComObject(stream)) { + Marshal.ReleaseComObject(stream); } } @@ -17330,8 +17306,8 @@ internal void Save(UnsafeNativeMethods.IPropertyBag pPropBag, bool fClearDirty, } } - if (UnsafeNativeMethods.IsComObject(pPropBag)) { - UnsafeNativeMethods.ReleaseComObject(pPropBag); + if (Marshal.IsComObject(pPropBag)) { + Marshal.ReleaseComObject(pPropBag); } if (fClearDirty) { @@ -17369,8 +17345,8 @@ internal void SetAdvise(int aspects, int advf, IAdviseSink pAdvSink) { activeXState[viewAdvisePrimeFirst] = (advf & NativeMethods.ADVF_PRIMEFIRST) != 0 ? true : false; activeXState[viewAdviseOnlyOnce] = (advf & NativeMethods.ADVF_ONLYONCE) != 0 ? true : false; - if (viewAdviseSink != null && UnsafeNativeMethods.IsComObject(viewAdviseSink)) { - UnsafeNativeMethods.ReleaseComObject(viewAdviseSink); + if (viewAdviseSink != null && Marshal.IsComObject(viewAdviseSink)) { + Marshal.ReleaseComObject(viewAdviseSink); } viewAdviseSink = pAdvSink; @@ -17409,7 +17385,7 @@ internal void SetClientSite(UnsafeNativeMethods.IOleClientSite value) { } } - if (UnsafeNativeMethods.IsComObject(clientSite)) { + if (Marshal.IsComObject(clientSite)) { Marshal.FinalReleaseComObject(clientSite); } } @@ -17736,10 +17712,10 @@ internal int TranslateAccelerator(ref NativeMethods.MSG lpmsg) { bool needPreProcess = false; switch (lpmsg.message) { - case NativeMethods.WM_KEYDOWN: - case NativeMethods.WM_SYSKEYDOWN: - case NativeMethods.WM_CHAR: - case NativeMethods.WM_SYSCHAR: + case Interop.WindowMessages.WM_KEYDOWN: + case Interop.WindowMessages.WM_SYSKEYDOWN: + case Interop.WindowMessages.WM_CHAR: + case Interop.WindowMessages.WM_SYSCHAR: needPreProcess = true; break; } @@ -17840,8 +17816,8 @@ internal void Unadvise(int dwConnection) { IAdviseSink sink = (IAdviseSink)adviseList[dwConnection - 1]; adviseList.RemoveAt(dwConnection - 1); - if (sink != null && UnsafeNativeMethods.IsComObject(sink)) { - UnsafeNativeMethods.ReleaseComObject(sink); + if (sink != null && Marshal.IsComObject(sink)) { + Marshal.ReleaseComObject(sink); } } @@ -17936,8 +17912,8 @@ private void ViewChanged() { viewAdviseSink.OnViewChange(NativeMethods.DVASPECT_CONTENT, -1); if (activeXState[viewAdviseOnlyOnce]) { - if (UnsafeNativeMethods.IsComObject(viewAdviseSink)) { - UnsafeNativeMethods.ReleaseComObject(viewAdviseSink); + if (Marshal.IsComObject(viewAdviseSink)) { + Marshal.ReleaseComObject(viewAdviseSink); } viewAdviseSink = null; } @@ -17956,13 +17932,13 @@ void IWindowTarget.OnHandleChange(IntPtr newHandle) { /// void IWindowTarget.OnMessage(ref Message m) { if (activeXState[uiDead]) { - if (m.Msg >= NativeMethods.WM_MOUSEFIRST && m.Msg <= NativeMethods.WM_MOUSELAST) { + if (m.Msg >= Interop.WindowMessages.WM_MOUSEFIRST && m.Msg <= Interop.WindowMessages.WM_MOUSELAST) { return; } - if (m.Msg >= NativeMethods.WM_NCLBUTTONDOWN && m.Msg <= NativeMethods.WM_NCMBUTTONDBLCLK) { + if (m.Msg >= Interop.WindowMessages.WM_NCLBUTTONDOWN && m.Msg <= Interop.WindowMessages.WM_NCMBUTTONDBLCLK) { return; } - if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST) { + if (m.Msg >= Interop.WindowMessages.WM_KEYFIRST && m.Msg <= Interop.WindowMessages.WM_KEYLAST) { return; } } @@ -18260,7 +18236,7 @@ public void Clone(out UnsafeNativeMethods.IEnumOLEVERB ppenum) { } } - #if ACTIVEX_SOURCING +#if ACTIVEX_SOURCING // // This has been cut from the product. @@ -18290,10 +18266,7 @@ internal ActiveXPropPage(object component) { form.ControlBox = true; form.SizeGripStyle = SizeGripStyle.Show; form.DockPadding.Bottom = 16; // size grip size - - Bitmap bitmap = new Bitmap(grid.GetType(), "PropertyGrid.bmp"); - bitmap.MakeTransparent(); - form.Icon = Icon.FromHandle(bitmap.GetHicon()); + form.Icon = new Icon(grid.GetType(), "PropertyGrid"); grid.Dock = DockStyle.Fill; @@ -18312,7 +18285,7 @@ internal void Edit(object editingObject) { } } - #endif +#endif /// /// Contains a single ambient property, including DISPID, name and value. @@ -18490,7 +18463,7 @@ private unsafe bool DICopy(HandleRef hdcDest, HandleRef hdcSrc, NativeMethods.RE } NativeMethods.BITMAPINFO_FLAT lpbmi = new NativeMethods.BITMAPINFO_FLAT(); - lpbmi.bmiHeader_biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFOHEADER)); + lpbmi.bmiHeader_biSize = Marshal.SizeOf(); lpbmi.bmiHeader_biWidth = bmp.bmWidth; lpbmi.bmiHeader_biHeight = bmp.bmHeight; lpbmi.bmiHeader_biPlanes = 1; @@ -18507,7 +18480,7 @@ private unsafe bool DICopy(HandleRef hdcDest, HandleRef hdcSrc, NativeMethods.RE // Include the palette for 256 color bitmaps long iColors = 1 << (bmp.bmBitsPixel * bmp.bmPlanes); if (iColors <= 256) { - byte[] aj = new byte[Marshal.SizeOf(typeof(NativeMethods.PALETTEENTRY)) * 256]; + byte[] aj = new byte[Marshal.SizeOf() * 256]; SafeNativeMethods.GetSystemPaletteEntries(hdcSrc, 0, (int)iColors, aj); fixed (byte* pcolors = lpbmi.bmiColors) { @@ -18598,8 +18571,6 @@ public ControlAccessibleObject(Control ownerControl) { this.ownerControl = ownerControl; - // call get_Handle outside the UnmanagedCode permission because if the handle is not created yet, - // we will invoke 3rd party HandleCreated event handlers IntPtr handle = ownerControl.Handle; this.Handle = handle; @@ -19029,7 +19000,7 @@ public override bool RaiseLiveRegionChanged() { } internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3 && this.Owner is IAutomationLiveRegion) { + if (this.Owner is IAutomationLiveRegion) { return true; } @@ -19037,7 +19008,7 @@ internal override bool IsIAccessibleExSupported() { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_LiveSettingPropertyId && Owner is IAutomationLiveRegion) { + if (propertyID == NativeMethods.UIA_LiveSettingPropertyId && Owner is IAutomationLiveRegion) { return ((IAutomationLiveRegion)Owner).LiveSetting; } @@ -19051,8 +19022,7 @@ internal override object GetPropertyValue(int propertyID) { case NativeMethods.UIA_AccessKeyPropertyId: return string.Empty; case NativeMethods.UIA_HelpTextPropertyId: - var help = Help; - return AccessibilityImprovements.Level3 ? (help ?? string.Empty) : help; + return Help ?? string.Empty; } } @@ -19061,13 +19031,9 @@ internal override object GetPropertyValue(int propertyID) { internal override UnsafeNativeMethods.IRawElementProviderSimple HostRawElementProvider { get { - if (AccessibilityImprovements.Level3) { - UnsafeNativeMethods.IRawElementProviderSimple provider; - UnsafeNativeMethods.UiaHostProviderFromHwnd(new HandleRef(this, Handle), out provider); - return provider; - } - - return base.HostRawElementProvider; + UnsafeNativeMethods.IRawElementProviderSimple provider; + UnsafeNativeMethods.UiaHostProviderFromHwnd(new HandleRef(this, Handle), out provider); + return provider; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ControlPaint.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ControlPaint.cs index d50bdb68700..a05693be552 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ControlPaint.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ControlPaint.cs @@ -1205,7 +1205,7 @@ private static void DrawFlatCheckBox(Graphics graphics, Rectangle rectangle, But SystemBrushes.Control : SystemBrushes.Window; Color foreground = ((state & ButtonState.Inactive) == ButtonState.Inactive) ? - ((SystemInformation.HighContrast && AccessibilityImprovements.Level1) ? SystemColors.GrayText : SystemColors.ControlDark) : + (SystemInformation.HighContrast ? SystemColors.GrayText : SystemColors.ControlDark) : SystemColors.ControlText; DrawFlatCheckBox(graphics, rectangle, foreground, background, state); } @@ -1890,7 +1890,7 @@ public static void DrawStringDisabled(Graphics graphics, string s, Font font, throw new ArgumentNullException(nameof(graphics)); } - if (SystemInformation.HighContrast && AccessibilityImprovements.Level1) { + if (SystemInformation.HighContrast) { // Ignore the foreground color argument and don't do shading in high contrast, // as colors should match the OS-defined ones. graphics.DrawString(s, font, SystemBrushes.GrayText, layoutRectangle, format); @@ -1918,7 +1918,7 @@ public static void DrawStringDisabled(IDeviceContext dc, string s, Font font, throw new ArgumentNullException(nameof(dc)); } - if (SystemInformation.HighContrast && AccessibilityImprovements.Level1) { + if (SystemInformation.HighContrast) { TextRenderer.DrawText(dc, s, font, layoutRectangle, SystemColors.GrayText, format); } else { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/CreateParams.cs b/src/System.Windows.Forms/src/System/Windows/Forms/CreateParams.cs index c3a36c4819f..9a3d6c30a93 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/CreateParams.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/CreateParams.cs @@ -2,154 +2,96 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { +using System.Text; - using System.Diagnostics; - using System.Text; - using System; +namespace System.Windows.Forms +{ + public class CreateParams + { + /// + /// Name of the window class to subclass. The default value for this field + /// is null, indicating that the window is not a subclass of an existing + /// window class. To subclass an existing window class, store the window + /// class name in this field. For example, to subclass the standard edit + /// control, set this field to "EDIT". + /// + public string ClassName { get; set; } - /// - public class CreateParams { - string className; - string caption; - int style; - int exStyle; - int classStyle; - int x; - int y; - int width; - int height; - IntPtr parent; - object param; + /// + /// The initial caption your control will have. + /// + public string Caption { get; set; } - /// - /// - /// Name of the window class to subclass. The default value for this field - /// is null, indicating that the window is not a subclass of an existing - /// window class. To subclass an existing window class, store the window - /// class name in this field. For example, to subclass the standard edit - /// control, set this field to "EDIT". - /// - public string ClassName { - get { return className; } - set { className = value; } - } + /// + /// Window style bits. This must be a combination of WS_XXX style flags and + /// other control-specific style flags. + /// + public int Style { get; set; } - /// - /// - /// The initial caption your control will have. - /// - public string Caption { - get { return caption; } - set { caption = value; } - } + /// + /// Extended window style bits. This must be a combination of WS_EX_XXX + /// style flags. + /// + public int ExStyle { get; set; } - /// - /// - /// Window style bits. This must be a combination of WS_XXX style flags and - /// other control-specific style flags. - /// - public int Style { - get { return style; } - set { style = value; } - } + /// + /// Class style bits. This must be a combination of CS_XXX style flags. This + /// field is ignored if the className field is not null. + /// + public int ClassStyle { get; set; } - /// - /// - /// Extended window style bits. This must be a combination of WS_EX_XXX - /// style flags. - /// - public int ExStyle { - get { return exStyle; } - set { exStyle = value; } - } + /// + /// The left portion of the initial proposed location. + /// + public int X { get; set; } - /// - /// - /// Class style bits. This must be a combination of CS_XXX style flags. This - /// field is ignored if the className field is not null. - /// - public int ClassStyle { - get { return classStyle; } - set { classStyle = value; } - } + /// + /// The top portion of the initial proposed location. + /// + public int Y { get; set; } - /// - /// - /// The left portion of the initial proposed location. - /// - public int X { - get { return x; } - set { x = value; } - } + /// + /// The initially proposed width. + /// + public int Width { get; set; } - /// - /// - /// The top portion of the initial proposed location. - /// - public int Y { - get { return y; } - set { y = value; } - } + /// + /// The initially proposed height. + /// + public int Height { get; set; } - /// - /// - /// The initially proposed width. - /// - public int Width { - get { return width; } - set { width = value; } - } - - /// - /// - /// The initially proposed height. - /// - public int Height { - get { return height; } - set { height = value; } - } + /// + /// The controls parent. + /// + public IntPtr Parent { get; set; } - /// - /// - /// The controls parent. - /// - public IntPtr Parent { - get { return parent; } - set { parent = value; } - } - - /// - /// - /// Any extra information that the underlying handle might want. - /// - public object Param { - get { return param; } - set { param = value; } - } + /// + /// Any extra information that the underlying handle might want. + /// + public object Param { get; set; } - /// - public override string ToString() { - StringBuilder sb = new StringBuilder(64); - sb.Append("CreateParams {'"); - sb.Append(className); - sb.Append("', '"); - sb.Append(caption); - sb.Append("', 0x"); - sb.Append(Convert.ToString(style, 16)); - sb.Append(", 0x"); - sb.Append(Convert.ToString(exStyle, 16)); - sb.Append(", {"); - sb.Append(x); - sb.Append(", "); - sb.Append(y); - sb.Append(", "); - sb.Append(width); - sb.Append(", "); - sb.Append(height); - sb.Append("}"); - sb.Append("}"); - return sb.ToString(); + public override string ToString() + { + var builder = new StringBuilder(64); + builder.Append("CreateParams {'"); + builder.Append(ClassName); + builder.Append("', '"); + builder.Append(Caption); + builder.Append("', 0x"); + builder.Append(Convert.ToString(Style, 16)); + builder.Append(", 0x"); + builder.Append(Convert.ToString(ExStyle, 16)); + builder.Append(", {"); + builder.Append(X); + builder.Append(", "); + builder.Append(Y); + builder.Append(", "); + builder.Append(Width); + builder.Append(", "); + builder.Append(Height); + builder.Append("}"); + builder.Append("}"); + return builder.ToString(); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/CurrencyManager.cs b/src/System.Windows.Forms/src/System/Windows/Forms/CurrencyManager.cs index f76deff964c..23b66e722a6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/CurrencyManager.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/CurrencyManager.cs @@ -174,7 +174,7 @@ internal override object DataSource { } } - internal override void SetDataSource(object dataSource) { + private protected override void SetDataSource(object dataSource) { if (this.dataSource != dataSource) { Release(); this.dataSource = dataSource; @@ -795,14 +795,10 @@ internal protected override void OnCurrentChanged(EventArgs e) { // a. FindGoodRow actually found a good row, so it can't be the one before the user changed the position: fire the onCurrentChanged // b. FindGoodRow did not find a good row: we should have gotten an exception so we should not even execute this code if (!positionChanged ||(positionChanged && curLastGoodKnownRow != -1)) { - if (onCurrentChangedHandler != null) { - onCurrentChangedHandler(this, e); - } + onCurrentChangedHandler?.Invoke(this, e); // we fire OnCurrentItemChanged event every time we fire the CurrentChanged + when a property of the Current item changed - if (onCurrentItemChangedHandler != null) { - onCurrentItemChangedHandler(this, e); - } + _onCurrentItemChangedHandler?.Invoke(this, e); } } catch (Exception ex) { @@ -814,10 +810,8 @@ internal protected override void OnCurrentChanged(EventArgs e) { // this method should only be called when the currency manager receives the ListChangedType.ItemChanged event // and when the index of the ListChangedEventArgs == the position in the currency manager /// - internal protected override void OnCurrentItemChanged(EventArgs e) { - if (onCurrentItemChangedHandler != null) { - onCurrentItemChangedHandler(this, e); - } + protected internal override void OnCurrentItemChanged(EventArgs e) { + _onCurrentItemChangedHandler?.Invoke(this, e); } /// diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs index e3158d569f7..6eb79ab0f94 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs @@ -562,12 +562,12 @@ private Size GetIconSize(IntPtr iconHandle) { NativeMethods.BITMAP bmp = new NativeMethods.BITMAP(); if (info.hbmColor != IntPtr.Zero) { - UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(NativeMethods.BITMAP)), bmp); + UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(), bmp); SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor)); iconSize = new Size(bmp.bmWidth, bmp.bmHeight); } else if (info.hbmMask != IntPtr.Zero) { - UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmMask), Marshal.SizeOf(typeof(NativeMethods.BITMAP)), bmp); + UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmMask), Marshal.SizeOf(), bmp); iconSize = new Size(bmp.bmWidth, bmp.bmHeight / 2); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataFormats.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataFormats.cs index 57b01945dab..ada4033967b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataFormats.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataFormats.cs @@ -2,307 +2,269 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel; +using System.Text; +using System.Runtime.InteropServices; -namespace System.Windows.Forms { - using System.Text; - using System.Configuration.Assemblies; - using System.Diagnostics; - using System; - using System.ComponentModel; - using System.Runtime.InteropServices; - using System.Globalization; - - /// +namespace System.Windows.Forms +{ /// - /// Translates - /// between Win Forms text-based - /// formats and 32-bit signed integer-based - /// clipboard formats. Provides methods to create new formats and add - /// them to the Windows Registry. + /// Translates between WinForms text-based + /// formats and 32-bit signed integer-based clipboard + /// formats. Provides methods to create new + /// formats and add them to the Windows Registry. /// - public class DataFormats { - /// + public static class DataFormats + { /// - /// Specifies the standard ANSI text format. This - /// field is read-only. + /// Specifies the standard ANSI text format. This + /// field is read-only. /// - public static readonly string Text = "Text"; + public static readonly string Text = "Text"; - /// /// - /// Specifies the standard Windows Unicode text format. This - /// - /// field is read-only. + /// Specifies the standard Windows Unicode text format. + /// This field is read-only. /// - public static readonly string UnicodeText = "UnicodeText"; + public static readonly string UnicodeText = "UnicodeText"; - /// /// - /// Specifies the Windows Device Independent Bitmap (DIB) - /// format. This - /// field is read-only. + /// Specifies the Windows Device Independent Bitmap (DIB) format. + /// This field is read-only. /// - public static readonly string Dib = "DeviceIndependentBitmap"; + public static readonly string Dib = "DeviceIndependentBitmap"; - /// /// - /// Specifies a Windows bitmap format. This field is read-only. - /// - public static readonly string Bitmap = "Bitmap"; + /// Specifies a Windows bitmap format. + /// This field is read-only. + public static readonly string Bitmap = "Bitmap"; - /// /// - /// Specifies the Windows enhanced metafile format. This - /// field is read-only. + /// Specifies the Windows enhanced metafile format. + /// This field is read-only. /// - public static readonly string EnhancedMetafile = "EnhancedMetafile"; + public static readonly string EnhancedMetafile = "EnhancedMetafile"; - /// /// - /// Specifies the Windows metafile format, which Win Forms - /// does not directly use. This - /// field is read-only. + /// Specifies the Windows metafile format, which WinForms does not directly use. + /// This field is read-only. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] // Would be a breaking change to rename this - public static readonly string MetafilePict = "MetaFilePict"; + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Would be a breaking change to rename this")] + public static readonly string MetafilePict = "MetaFilePict"; - /// /// - /// Specifies the Windows symbolic link format, which Win - /// Forms does not directly use. This - /// field is read-only. + /// Specifies the Windows symbolic link format, which WinForms does not directly use. + /// This field is read-only. /// - public static readonly string SymbolicLink = "SymbolicLink"; + public static readonly string SymbolicLink = "SymbolicLink"; - /// /// - /// Specifies the Windows data interchange format, which Win - /// Forms does not directly use. This - /// field is read-only. + /// Specifies the Windows data interchange format, which WinForms does not directly use. + /// This field is read-only. /// - public static readonly string Dif = "DataInterchangeFormat"; + public static readonly string Dif = "DataInterchangeFormat"; - /// /// - /// Specifies the Tagged Image File Format (TIFF), which Win - /// Forms does not directly use. This - /// field is read-only. + /// Specifies the Tagged Image File Format (TIFF), which WinForms does not directly use. + /// This field is read-only. /// - public static readonly string Tiff = "TaggedImageFileFormat"; + public static readonly string Tiff = "TaggedImageFileFormat"; - /// /// - /// Specifies the standard Windows original equipment - /// manufacturer (OEM) text format. This field is read-only. + /// Specifies the standard Windows original equipment manufacturer (OEM) text format. + /// This field is read-only. /// - public static readonly string OemText = "OEMText"; - /// + public static readonly string OemText = "OEMText"; + /// - /// Specifies the Windows palette format. This - /// field is read-only. + /// Specifies the Windows palette format. + /// This field is read-only. /// - public static readonly string Palette = "Palette"; + public static readonly string Palette = "Palette"; - /// /// - /// Specifies the Windows pen data format, which consists of - /// pen strokes for handwriting software; Win Forms does not use this format. This - /// - /// field is read-only. + /// Specifies the Windows pen data format, which consists of pen strokes for handwriting + /// software; Win Formsdoes not use this format. + /// This field is read-only. /// - public static readonly string PenData = "PenData"; + public static readonly string PenData = "PenData"; - /// /// - /// Specifies the Resource Interchange File Format (RIFF) - /// audio format, which Win Forms does not directly use. This field is read-only. + /// Specifies the Resource Interchange File Format (RIFF) audio format, which WinForms + /// does not directly use. + /// This field is read-only. /// - public static readonly string Riff = "RiffAudio"; + public static readonly string Riff = "RiffAudio"; - /// /// - /// Specifies the wave audio format, which Win Forms does not - /// directly use. This field is read-only. + /// Specifies the wave audio format, which Win Forms does not + /// directly use. This field is read-only. /// - public static readonly string WaveAudio = "WaveAudio"; + public static readonly string WaveAudio = "WaveAudio"; - /// /// - /// Specifies the Windows file drop format, which Win Forms - /// does not directly use. This - /// field is read-only. + /// Specifies the Windows file drop format, which WinForms does not directly use. + /// This field is read-only. /// - public static readonly string FileDrop = "FileDrop"; + public static readonly string FileDrop = "FileDrop"; - /// /// - /// Specifies the Windows culture format, which Win Forms does - /// not directly use. This field is read-only. + /// Specifies the Windows culture format, which WinForms does not directly use. + /// This field is read-only. /// - public static readonly string Locale = "Locale"; + public static readonly string Locale = "Locale"; - /// /// - /// Specifies text consisting of HTML data. This - /// field is read-only. + /// Specifies text consisting of HTML data. + /// This field is read-only. /// - public static readonly string Html = "HTML Format"; + public static readonly string Html = "HTML Format"; - /// /// - /// Specifies text consisting of Rich Text Format (RTF) data. This - /// field is read-only. + /// Specifies text consisting of Rich Text Format (RTF) data. + /// This field is read-only. /// - public static readonly string Rtf = "Rich Text Format"; + public static readonly string Rtf = "Rich Text Format"; - /// /// - /// Specifies a comma-separated value (CSV) format, which is a - /// common interchange format used by spreadsheets. This format is not used directly - /// by Win Forms. This - /// field is read-only. + /// Specifies a comma-separated value (CSV) format, which is a common interchange format + /// used by spreadsheets. This format is not used directly by WinForms. + /// This field is read-only. /// - public static readonly string CommaSeparatedValue = "Csv"; + public static readonly string CommaSeparatedValue = "Csv"; - /// /// - /// Specifies the Win Forms string class format, which Win - /// Forms uses to store string objects. This - /// field is read-only. + /// Specifies the Win Forms string class format, which WinForms uses to store string + /// objects. + /// This field is read-only. /// - public static readonly string StringFormat = typeof(string).FullName; + public static readonly string StringFormat = typeof(string).FullName; - /// /// - /// Specifies a format that encapsulates any type of Win Forms - /// object. This field is read-only. + /// Specifies a format that encapsulates any type of WinForms object. + /// This field is read-only. /// - public static readonly string Serializable = Application.WindowsFormsVersion + "PersistentObject"; + public static readonly string Serializable = Application.WindowsFormsVersion + "PersistentObject"; - - private static Format[] formatList; - private static int formatCount = 0; - - private static object internalSyncObject = new object(); + private static Format[] s_formatList; + private static int s_formatCount = 0; - // not creatable... - // - private DataFormats() { - } + private static object s_internalSyncObject = new object(); - /// /// - /// Gets a with the Windows Clipboard numeric ID and name for the specified format. + /// Gets a with the Windows + /// Clipboard numeric ID and name for the specified format. /// - public static Format GetFormat(string format) { - lock(internalSyncObject) { + public static Format GetFormat(string format) + { + lock (s_internalSyncObject) + { EnsurePredefined(); - // It is much faster to do a case sensitive search here. So do - // the case sensitive compare first, then the expensive one. - // - for (int n = 0; n < formatCount; n++) { - if (formatList[n].Name.Equals(format)) - return formatList[n]; + // It is much faster to do a case sensitive search here. + // So do the case sensitive compare first, then the expensive one. + for (int n = 0; n < s_formatCount; n++) + { + if (s_formatList[n].Name.Equals(format)) + { + return s_formatList[n]; + } } - - for (int n = 0; n < formatCount; n++) { - if (string.Equals(formatList[n].Name, format, StringComparison.OrdinalIgnoreCase)) - return formatList[n]; + + for (int n = 0; n < s_formatCount; n++) + { + if (string.Equals(s_formatList[n].Name, format, StringComparison.OrdinalIgnoreCase)) + { + return s_formatList[n]; + } } - - // need to add this format string - // + + // Need to add this format string int formatId = SafeNativeMethods.RegisterClipboardFormat(format); - if (0 == formatId) { + if (formatId == 0) + { throw new Win32Exception(Marshal.GetLastWin32Error(), SR.RegisterCFFailed); } - EnsureFormatSpace(1); - formatList[formatCount] = new Format(format, formatId); - return formatList[formatCount++]; + s_formatList[s_formatCount] = new Format(format, formatId); + return s_formatList[s_formatCount++]; } } - /// /// - /// Gets a with the Windows Clipboard numeric - /// ID and name for the specified ID. + /// Gets a with the Windows + /// Clipboard numeric ID and name for the specified ID. /// - public static Format GetFormat(int id) { + public static Format GetFormat(int id) + { // Win32 uses an unsigned 16 bit type as a format ID, thus stripping off the leading bits. - // Registered format IDs are in the range 0xC000 through 0xFFFF, thus it's important - // to represent format as an unsigned type. - return InternalGetFormat( null, (ushort)(id & 0xFFFF)); - } + // Registered format IDs are in the range 0xC000 through 0xFFFF, thus it's important + // to represent format as an unsigned type. + ushort clampedId = (ushort)(id & 0xFFFF); - /// - /// - /// Allows a the new format name to be specified if the requested format is not - /// in the list - /// - /// - private static Format InternalGetFormat(string strName, ushort id) { - lock(internalSyncObject) { + lock (s_internalSyncObject) + { EnsurePredefined(); - for (int n = 0; n < formatCount; n++) { - if (formatList[n].Id == id) - return formatList[n]; + for (int n = 0; n < s_formatCount; n++) + { + if (s_formatList[n].Id == clampedId) + { + return s_formatList[n]; + } } - StringBuilder s = new StringBuilder(128); + // The max length of the name of clipboard formats is equal to the max length + // of a Win32 Atom of 255 chars. An additional null terminator character is added, + // giving a required capacity of 256 chars. + var nameBuilder = new StringBuilder(256); // This can happen if windows adds a standard format that we don't know about, // so we should play it safe. - // - if (0 == SafeNativeMethods.GetClipboardFormatName(id, s, s.Capacity)) { - s.Length = 0; - if (strName == null) { - s.Append( "Format" ).Append( id ); - } - else { - s.Append( strName ); - } + if (SafeNativeMethods.GetClipboardFormatName(clampedId, nameBuilder, nameBuilder.Capacity) == 0) + { + nameBuilder.Length = 0; + nameBuilder.Append("Format").Append(clampedId); } EnsureFormatSpace(1); - formatList[formatCount] = new Format(s.ToString(), id); + s_formatList[s_formatCount] = new Format(nameBuilder.ToString(), clampedId); - return formatList[formatCount++]; + return s_formatList[s_formatCount++]; } } - - /// /// - /// ensures that we have enough room in our format list + /// Ensures that we have enough room in our format list /// - /// - private static void EnsureFormatSpace(int size) { - if (null == formatList || formatList.Length <= formatCount + size) { - int newSize = formatCount + 20; + private static void EnsureFormatSpace(int size) + { + if (s_formatList == null || s_formatList.Length <= s_formatCount + size) + { + int newSize = s_formatCount + 20; Format[] newList = new Format[newSize]; - - for (int n = 0; n < formatCount; n++) { - newList[n] = formatList[n]; + for (int n = 0; n < s_formatCount; n++) + { + newList[n] = s_formatList[n]; } - formatList = newList; - } + + s_formatList = newList; + } } - /// /// - /// ensures that the Win32 predefined formats are setup in our format list. This - /// is called anytime we need to search the list + /// Ensures that the Win32 predefined formats are setup in our format list. + /// This is called anytime we need to search the list /// /// - private static void EnsurePredefined() { - - if (0 == formatCount) { - formatList = new Format [] { + private static void EnsurePredefined() + { + if (s_formatCount == 0) + { + s_formatList = new Format[] + { // Text name Win32 format ID Data stored as a Win32 handle? new Format(UnicodeText, NativeMethods.CF_UNICODETEXT), new Format(Text, NativeMethods.CF_TEXT), @@ -322,55 +284,34 @@ private static void EnsurePredefined() { new Format(Locale, NativeMethods.CF_LOCALE) }; - formatCount = formatList.Length; + s_formatCount = s_formatList.Length; } } - /// /// - /// Represents a format type. + /// Represents a format type. /// - public class Format { - readonly string name; - readonly int id; - - /// + public class Format + { /// - /// - /// Specifies the - /// name of this format. This field is read-only. - /// - /// + /// Initializes a new instance of the + /// class and specifies whether a handle is expected with this format. /// - public string Name { - get { - return name; - } + public Format(string name, int id) + { + Name = name; + Id = id; } - - /// + /// - /// - /// Specifies the ID - /// number for this format. This field is read-only. - /// + /// Specifies the name of this format. /// - public int Id { - get { - return id; - } - } + public string Name { get; } - /// /// - /// Initializes a new instance of the class and specifies whether a - /// - /// handle is expected with this format. + /// Specifies the ID number for this format. /// - public Format(string name, int id) { - this.name = name; - this.id = id; - } + public int Id { get; } } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGrid.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGrid.cs index 8ea64fb8d46..c9b1486d0b6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGrid.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGrid.cs @@ -8023,7 +8023,7 @@ protected bool ProcessGridKey(KeyEventArgs ke) { /// consumed. /// protected override bool ProcessKeyPreview(ref Message m) { - if (m.Msg == NativeMethods.WM_KEYDOWN) { + if (m.Msg == Interop.WindowMessages.WM_KEYDOWN) { KeyEventArgs ke = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys); switch (ke.KeyCode) { case Keys.Up: @@ -8049,7 +8049,7 @@ protected override bool ProcessKeyPreview(ref Message m) { } // Ctrl-Tab will be sent as a tab paired w/ a control on the KeyUp message // - } else if (m.Msg == NativeMethods.WM_KEYUP) { + } else if (m.Msg == Interop.WindowMessages.WM_KEYUP) { KeyEventArgs ke = new KeyEventArgs((Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys); if (ke.KeyCode == Keys.Tab) return ProcessGridKey(ke); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCaption.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCaption.cs index a37be21a3a1..357dace9fab 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCaption.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCaption.cs @@ -380,32 +380,30 @@ protected void OnDownClicked(EventArgs e) { } private Bitmap GetBitmap(string bitmapName) { - Bitmap b = null; try { - b = new Bitmap(typeof(DataGridCaption), bitmapName); - b.MakeTransparent(); + return DpiHelper.GetBitmapFromIcon(typeof(DataGridCaption), bitmapName); } catch (Exception e) { Debug.Fail("Failed to load bitmap: " + bitmapName, e.ToString()); + return null; } - return b; } private Bitmap GetBackButtonBmp(bool alignRight) { if (alignRight) { if (leftButtonBitmap_bidi == null) - leftButtonBitmap_bidi = GetBitmap("DataGridCaption.backarrow_bidi.bmp"); + leftButtonBitmap_bidi = GetBitmap("DataGridCaption.backarrow_bidi"); return leftButtonBitmap_bidi; } else { if (leftButtonBitmap == null) - leftButtonBitmap = GetBitmap("DataGridCaption.backarrow.bmp"); + leftButtonBitmap = GetBitmap("DataGridCaption.backarrow"); return leftButtonBitmap; } } private Bitmap GetDetailsBmp() { if (magnifyingGlassBitmap == null) - magnifyingGlassBitmap = GetBitmap("DataGridCaption.Details.bmp"); + magnifyingGlassBitmap = GetBitmap("DataGridCaption.Details"); return magnifyingGlassBitmap; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCell.cs index d76644e2046..417d87bc503 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridCell.cs @@ -2,98 +2,61 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { +using System.Diagnostics.CodeAnalysis; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System; - using System.Globalization; - - /// - /// - /// Identifies a cell in the grid. - /// +namespace System.Windows.Forms +{ + /// + /// Identifies a cell in the grid. + /// [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] - public struct DataGridCell { - private int rowNumber; - private int columnNumber; + public struct DataGridCell + { + /// + /// Gets or sets the number of a column in the control. + /// + public int ColumnNumber { get; set; } - /// - /// - /// Gets or sets the number of a column in the control. - /// - public int ColumnNumber { - get { - return columnNumber; - } - set { - columnNumber = value; - } - } - - /// - /// - /// Gets or sets the number of a row in the control. - /// - public int RowNumber { - get { - return rowNumber; - } - set { - rowNumber = value; - } - } - - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public DataGridCell(int r, int c) { - this.rowNumber = r; - this.columnNumber = c; + /// + /// Gets or sets the number of a row in the control. + /// + public int RowNumber { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public DataGridCell(int r, int c) + { + RowNumber = r; + ColumnNumber = c; } - - /// - /// - /// - /// Gets a value indicating whether the is identical to a second - /// . - /// - /// + + /// + /// Gets a value indicating whether the is + /// identical to a second . + /// [SuppressMessage("Microsoft.Usage", "CA2231:OverrideOperatorEqualsOnOverridingValueTypeEquals")] - public override bool Equals(object o) { - if (o is DataGridCell) { - DataGridCell rhs = (DataGridCell)o; - return (rhs.RowNumber == RowNumber && rhs.ColumnNumber == ColumnNumber); - } - else + public override bool Equals(object o) + { + if (!(o is DataGridCell rhs)) + { return false; + } + + return rhs.RowNumber == RowNumber && rhs.ColumnNumber == ColumnNumber; } - - /// - /// - /// - /// Gets - /// a hash value that uniquely identifies the cell. - /// - /// - public override int GetHashCode() { - return ((~rowNumber * (columnNumber+1)) & 0x00ffff00) >> 8; - } - /// - /// - /// - /// Gets the row number and column number of the cell. - /// - /// - public override string ToString() { - return "DataGridCell {RowNumber = " + RowNumber.ToString(CultureInfo.CurrentCulture) + - ", ColumnNumber = " + ColumnNumber.ToString(CultureInfo.CurrentCulture) + "}"; + /// + /// Gets a hash value that uniquely identifies the cell. + /// + public override int GetHashCode() => HashCode.Combine(RowNumber, ColumnNumber); + + /// + /// Gets the row number and column number of the cell. + /// + public override string ToString() + { + return "DataGridCell {RowNumber = " + RowNumber + ", ColumnNumber = " + ColumnNumber + "}"; } - } - } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridParentRows.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridParentRows.cs index 42411bbfe65..b6e6d533e05 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridParentRows.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridParentRows.cs @@ -728,29 +728,27 @@ private void PaintParentRows(Graphics g, Rectangle bounds, bool alignToRight) { } } - private Bitmap GetBitmap(string bitmapName, Color transparentColor) { - Bitmap b = null; + private Bitmap GetBitmap(string bitmapName) { try { - b = new Bitmap(typeof(DataGridParentRows), bitmapName); - b.MakeTransparent(transparentColor); + return DpiHelper.GetBitmapFromIcon(typeof(DataGridParentRows), bitmapName); } catch (Exception e) { Debug.Fail("Failed to load bitmap: " + bitmapName, e.ToString()); + return null; } - return b; } private Bitmap GetRightArrowBitmap() { if (rightArrow == null) - rightArrow = GetBitmap("DataGridParentRows.RightArrow.bmp", Color.White); + rightArrow = GetBitmap("DataGridParentRows.RightArrow"); return rightArrow; } private Bitmap GetLeftArrowBitmap() { if (leftArrow == null) - leftArrow = GetBitmap("DataGridParentRows.LeftArrow.bmp", Color.White); + leftArrow = GetBitmap("DataGridParentRows.LeftArrow"); return leftArrow; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridRow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridRow.cs index 6c6f51aa7d7..95821bfdaa0 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridRow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridRow.cs @@ -207,16 +207,13 @@ public virtual bool Selected { /// Gets the bitmap associated with the row. /// protected Bitmap GetBitmap(string bitmapName) { - Bitmap b = null; try { - b = new Bitmap(typeof(DataGridCaption), bitmapName); - b.MakeTransparent(); + return DpiHelper.GetBitmapFromIcon(typeof(DataGridCaption), bitmapName); } catch (Exception e) { Debug.Fail("Failed to load bitmap: " + bitmapName, e.ToString()); throw e; } - return b; } /// @@ -258,7 +255,7 @@ public virtual Rectangle GetNonScrollableArea() { /// protected Bitmap GetStarBitmap() { if (starBmp == null) - starBmp = GetBitmap("DataGridRow.star.bmp"); + starBmp = GetBitmap("DataGridRow.star"); return starBmp; } @@ -269,7 +266,7 @@ protected Bitmap GetStarBitmap() { /// protected Bitmap GetPencilBitmap() { if (pencilBmp == null) - pencilBmp = GetBitmap("DataGridRow.pencil.bmp"); + pencilBmp = GetBitmap("DataGridRow.pencil"); return pencilBmp; } @@ -279,20 +276,19 @@ protected Bitmap GetPencilBitmap() { /// protected Bitmap GetErrorBitmap() { if (errorBmp == null) - errorBmp = GetBitmap("DataGridRow.error.bmp"); - errorBmp.MakeTransparent(); + errorBmp = GetBitmap("DataGridRow.error"); return errorBmp; } protected Bitmap GetLeftArrowBitmap() { if (leftArrow == null) - leftArrow = GetBitmap("DataGridRow.left.bmp"); + leftArrow = GetBitmap("DataGridRow.left"); return leftArrow; } protected Bitmap GetRightArrowBitmap() { if (rightArrow == null) - rightArrow = GetBitmap("DataGridRow.right.bmp"); + rightArrow = GetBitmap("DataGridRow.right"); return rightArrow; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridTextBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridTextBox.cs index 40c47da13d5..3ad35c3fc58 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridTextBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridTextBox.cs @@ -47,7 +47,7 @@ public void SetDataGrid(DataGrid parentGrid) protected override void WndProc(ref Message m) { // but what if we get a CtrlV? // what about deleting from the menu? - if (m.Msg == NativeMethods.WM_PASTE || m.Msg == NativeMethods.WM_CUT || m.Msg == NativeMethods.WM_CLEAR) { + if (m.Msg == Interop.WindowMessages.WM_PASTE || m.Msg == Interop.WindowMessages.WM_CUT || m.Msg == Interop.WindowMessages.WM_CLEAR) { IsInEditOrNavigateMode = false; dataGrid.ColumnStartedEditing(Bounds); } @@ -97,12 +97,12 @@ protected internal override bool ProcessKeyMessage(ref Message m) // enter and escape keys are sent directly to the DataGrid // for those keys, eat the WM_CHAR part of the KeyMessage // - if (m.Msg == NativeMethods.WM_CHAR) + if (m.Msg == Interop.WindowMessages.WM_CHAR) return true; return ProcessKeyPreview(ref m); } - if (m.Msg == NativeMethods.WM_CHAR) { + if (m.Msg == Interop.WindowMessages.WM_CHAR) { if (key == Keys.LineFeed) // eat the LineFeed we get when the user presses Ctrl-Enter in a gridTextBox return true; return ProcessKeyEventArgs(ref m); @@ -111,7 +111,7 @@ protected internal override bool ProcessKeyMessage(ref Message m) // now the edit control will be always on top of the grid // we only want to process the WM_KEYUP message ( the same way the grid was doing when the grid was getting all // the keys ) - if (m.Msg == NativeMethods.WM_KEYUP) + if (m.Msg == Interop.WindowMessages.WM_KEYUP) return true; Keys keyData = key & Keys.KeyCode; @@ -180,7 +180,7 @@ protected internal override bool ProcessKeyMessage(ref Message m) if (IsInEditOrNavigateMode && (Control.ModifierKeys & Keys.Shift) == Keys.Shift) { // when we get a SHIFT-SPACEBAR message, disregard the WM_CHAR part of the message - if (m.Msg == NativeMethods.WM_CHAR) return true; + if (m.Msg == Interop.WindowMessages.WM_CHAR) return true; // if the user pressed the SHIFT key at the same time with // the space key, send the key message to the DataGrid @@ -191,7 +191,7 @@ protected internal override bool ProcessKeyMessage(ref Message m) if (IsInEditOrNavigateMode && (Control.ModifierKeys & Keys.Control) == Keys.Control) { // when we get a Control-A message, disregard the WM_CHAR part of the message - if (m.Msg == NativeMethods.WM_CHAR) return true; + if (m.Msg == Interop.WindowMessages.WM_CHAR) return true; // if the user pressed the Control key at the same time with // the space key, send the key message to the DataGrid diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs index f31a9a40dfe..3b5c250af7e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs @@ -1444,7 +1444,7 @@ public event EventHandler BorderStyleChanged } } - private int BorderWidth + internal int BorderWidth { get { @@ -1765,7 +1765,7 @@ public int ColumnCount { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(ColumnCount), string.Format(SR.InvalidLowBoundArgumentEx, "ColumnCount", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ColumnCount), value, 0)); } if (this.DataSource != null) { @@ -1989,11 +1989,11 @@ public int ColumnHeadersHeight { if (value < minimumColumnHeadersHeight) { - throw new ArgumentOutOfRangeException(nameof(ColumnHeadersHeight), string.Format(SR.InvalidLowBoundArgumentEx, "ColumnHeadersHeight", (value).ToString(CultureInfo.CurrentCulture), (minimumColumnHeadersHeight).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(ColumnHeadersHeight), value, minimumColumnHeadersHeight)); } if (value > maxHeadersThickness) { - throw new ArgumentOutOfRangeException(nameof(ColumnHeadersHeight), string.Format(SR.InvalidHighBoundArgumentEx, "ColumnHeadersHeight", (value).ToString(CultureInfo.CurrentCulture), (maxHeadersThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidHighBoundArgumentEx, nameof(ColumnHeadersHeight), value, maxHeadersThickness)); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { @@ -2832,7 +2832,7 @@ public Panel EditingPanel { if (this.editingPanel == null) { - this.editingPanel = AccessibilityImprovements.Level3 ? new DataGridViewEditingPanel(this) : new Panel(); + this.editingPanel = new DataGridViewEditingPanel(this); this.editingPanel.AccessibleName = string.Format(SR.DataGridView_AccEditingPanelAccName); } return this.editingPanel; @@ -3476,6 +3476,22 @@ protected ScrollBar HorizontalScrollBar } } + internal int HorizontalScrollBarHeight + { + get + { + return this.horizScrollBar.Height; + } + } + + internal bool HorizontalScrollBarVisible + { + get + { + return this.horizScrollBar.Visible; + } + } + /// [ Browsable(false), @@ -3492,7 +3508,7 @@ public int HorizontalScrollingOffset // int widthNotVisible = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - this.layout.Data.Width; if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(HorizontalScrollingOffset), string.Format(SR.InvalidLowBoundArgumentEx, "HorizontalScrollingOffset", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(HorizontalScrollingOffset), value, 0)); } // Intentionally ignoring the out of range situation. // else if (value > widthNotVisible && widthNotVisible > 0) @@ -4021,14 +4037,14 @@ public int RowCount { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(RowCount), string.Format(SR.InvalidLowBoundArgumentEx, "RowCount", value.ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(RowCount), value, 1)); } } else { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(RowCount), string.Format(SR.InvalidLowBoundArgumentEx, "RowCount", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(RowCount), value, 0)); } } if (this.DataSource != null) @@ -4279,12 +4295,13 @@ public int RowHeadersWidth { if (value < minimumRowHeadersWidth) { - throw new ArgumentOutOfRangeException(nameof(RowHeadersWidth), string.Format(SR.InvalidLowBoundArgumentEx, "RowHeadersWidth", (value).ToString(CultureInfo.CurrentCulture), (minimumRowHeadersWidth).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(RowHeadersWidth), value, minimumRowHeadersWidth)); } if (value > maxHeadersThickness) { - throw new ArgumentOutOfRangeException(nameof(RowHeadersWidth), string.Format(SR.InvalidHighBoundArgumentEx, "RowHeadersWidth", (value).ToString(CultureInfo.CurrentCulture), (maxHeadersThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(RowHeadersWidth), value, maxHeadersThickness)); } + if (this.RowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.RowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing) { @@ -5008,13 +5025,7 @@ public bool StandardTab } } - internal override bool SupportsUiaProviders - { - get - { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// [ @@ -7039,22 +7050,11 @@ public DataGridViewEditingPanel(DataGridView owningDataGridView) this.owningDataGridView = owningDataGridView; } - internal override bool SupportsUiaProviders - { - get - { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) - { - return new DataGridViewEditingPanelAccessibleObject(owningDataGridView, this); - } - - return base.CreateAccessibilityInstance(); + return new DataGridViewEditingPanelAccessibleObject(owningDataGridView, this); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewAccessibleObject.cs index d2c0d647fa6..1c8c6a7e825 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewAccessibleObject.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewAccessibleObject.cs @@ -260,75 +260,57 @@ internal override int[] RuntimeId } } - internal override bool IsIAccessibleExSupported() - { - if (AccessibilityImprovements.Level2) - { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) + switch (propertyID) { - switch (propertyID) - { - case NativeMethods.UIA_NamePropertyId: - return this.Name; - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - return false; // Only inner cell should be announced as focused by Narrator but not entire DGV. - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - return owner.CanFocus; - case NativeMethods.UIA_IsEnabledPropertyId: - return owner.Enabled; - case NativeMethods.UIA_IsControlElementPropertyId: - return true; - case NativeMethods.UIA_IsTablePatternAvailablePropertyId: - case NativeMethods.UIA_IsGridPatternAvailablePropertyId: - return true; - case NativeMethods.UIA_ControlTypePropertyId: - return NativeMethods.UIA_TableControlTypeId; - case NativeMethods.UIA_ItemStatusPropertyId: - // Whether the owner DataGridView can be sorted by some column. - // If so, provide not-sorted/sorted-by item status. - bool canSort = false; - for (int i = 0; i < owner.Columns.Count; i++) + case NativeMethods.UIA_NamePropertyId: + return this.Name; + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + return false; // Only inner cell should be announced as focused by Narrator but not entire DGV. + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + return owner.CanFocus; + case NativeMethods.UIA_IsEnabledPropertyId: + return owner.Enabled; + case NativeMethods.UIA_IsControlElementPropertyId: + return true; + case NativeMethods.UIA_IsTablePatternAvailablePropertyId: + return IsPatternSupported(NativeMethods.UIA_TablePatternId); + case NativeMethods.UIA_IsGridPatternAvailablePropertyId: + return IsPatternSupported(NativeMethods.UIA_GridPatternId); + case NativeMethods.UIA_ControlTypePropertyId: + return NativeMethods.UIA_TableControlTypeId; + case NativeMethods.UIA_ItemStatusPropertyId: + // Whether the owner DataGridView can be sorted by some column. + // If so, provide not-sorted/sorted-by item status. + bool canSort = false; + for (int i = 0; i < owner.Columns.Count; i++) + { + if (owner.CanSort(owner.Columns[i])) { - if (owner.CanSort(owner.Columns[i])) - { - canSort = true; - break; - } + canSort = true; + break; } + } - if (canSort) + if (canSort) + { + switch (owner.SortOrder) { - switch (owner.SortOrder) - { - case SortOrder.None: - return SR.NotSortedAccessibleStatus; - case SortOrder.Ascending: - return string.Format(SR.DataGridViewSortedAscendingAccessibleStatusFormat, owner.SortedColumn?.HeaderText); - case SortOrder.Descending: - return string.Format(SR.DataGridViewSortedDescendingAccessibleStatusFormat, owner.SortedColumn?.HeaderText); - } + case SortOrder.None: + return SR.NotSortedAccessibleStatus; + case SortOrder.Ascending: + return string.Format(SR.DataGridViewSortedAscendingAccessibleStatusFormat, owner.SortedColumn?.HeaderText); + case SortOrder.Descending: + return string.Format(SR.DataGridViewSortedDescendingAccessibleStatusFormat, owner.SortedColumn?.HeaderText); } + } - break; - } - } - - if (propertyID == NativeMethods.UIA_IsTablePatternAvailablePropertyId) - { - return IsPatternSupported(NativeMethods.UIA_TablePatternId); - } - else if (propertyID == NativeMethods.UIA_IsGridPatternAvailablePropertyId) - { - return IsPatternSupported(NativeMethods.UIA_GridPatternId); + break; } + return base.GetPropertyValue(propertyID); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewBand.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewBand.cs index 3f69bc33742..732a658b142 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewBand.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewBand.cs @@ -2,96 +2,70 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.Text; + namespace System.Windows.Forms { - using System.ComponentModel; - using System.Diagnostics; - using System.Drawing; - using System.Text; - using System; - using System.Globalization; - - /// /// - /// Identifies a band or column in the dataGridView. + /// Identifies a band or column in the dataGridView. /// public class DataGridViewBand : DataGridViewElement, ICloneable, IDisposable { - private static readonly int PropContextMenuStrip = PropertyStore.CreateKey(); - private static readonly int PropDefaultCellStyle = PropertyStore.CreateKey(); - private static readonly int PropDefaultHeaderCellType = PropertyStore.CreateKey(); - private static readonly int PropDividerThickness = PropertyStore.CreateKey(); - private static readonly int PropHeaderCell = PropertyStore.CreateKey(); - private static readonly int PropUserData = PropertyStore.CreateKey(); - - internal const int minBandThickness = 2; - internal const int maxBandThickness = 65536; - - private PropertyStore propertyStore; // Contains all properties that are not always set. - private int thickness, cachedThickness; - private int minimumThickness; - private int bandIndex; + private static readonly int s_propContextMenuStrip = PropertyStore.CreateKey(); + private static readonly int s_propDefaultCellStyle = PropertyStore.CreateKey(); + private static readonly int s_propDefaultHeaderCellType = PropertyStore.CreateKey(); + private static readonly int s_propDividerThickness = PropertyStore.CreateKey(); + private static readonly int s_propHeaderCell = PropertyStore.CreateKey(); + private static readonly int s_propUserData = PropertyStore.CreateKey(); + + internal const int MinBandThickness = 2; + internal const int MaxBandThickness = 65536; + + // Contains all properties that are not always set. + private PropertyStore _propertyStore; + private int _thickness; + private int _minimumThickness; + private int _bandIndex; internal bool _bandIsRow; - /// /// - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// internal DataGridViewBand() { - this.propertyStore = new PropertyStore(); - this.bandIndex = -1; - } - - /// - ~DataGridViewBand() - { - Dispose(false); + _propertyStore = new PropertyStore(); + _bandIndex = -1; } - internal int CachedThickness - { - get - { - return this.cachedThickness; - } - set - { - this.cachedThickness = value; - } - } + ~DataGridViewBand() => Dispose(false); + + internal int CachedThickness { get; set; } - /// - [ - DefaultValue(null) - ] + [DefaultValue(null)] public virtual ContextMenuStrip ContextMenuStrip { get { - if (this._bandIsRow) + if (_bandIsRow) { - return ((DataGridViewRow) this).GetContextMenuStrip(this.Index); + return ((DataGridViewRow)this).GetContextMenuStrip(Index); } - return this.ContextMenuStripInternal; - } - set - { - this.ContextMenuStripInternal = value; + + return ContextMenuStripInternal; } + set => ContextMenuStripInternal = value; } internal ContextMenuStrip ContextMenuStripInternal { - get - { - return (ContextMenuStrip)this.Properties.GetObject(PropContextMenuStrip); - } + get => (ContextMenuStrip)Properties.GetObject(s_propContextMenuStrip); set { - ContextMenuStrip oldValue = (ContextMenuStrip)this.Properties.GetObject(PropContextMenuStrip); + ContextMenuStrip oldValue = (ContextMenuStrip)Properties.GetObject(s_propContextMenuStrip); if (oldValue != value) { EventHandler disposedHandler = new EventHandler(DetachContextMenuStrip); @@ -99,115 +73,98 @@ internal ContextMenuStrip ContextMenuStripInternal { oldValue.Disposed -= disposedHandler; } - this.Properties.SetObject(PropContextMenuStrip, value); + + Properties.SetObject(s_propContextMenuStrip, value); if (value != null) { value.Disposed += disposedHandler; } - if (this.DataGridView != null) - { - this.DataGridView.OnBandContextMenuStripChanged(this); - } + + DataGridView?.OnBandContextMenuStripChanged(this); } } } - /// - [ - Browsable(false) - ] + [Browsable(false)] public virtual DataGridViewCellStyle DefaultCellStyle { get { - DataGridViewCellStyle dgvcs = (DataGridViewCellStyle)this.Properties.GetObject(PropDefaultCellStyle); - if (dgvcs == null) + DataGridViewCellStyle style = (DataGridViewCellStyle)Properties.GetObject(s_propDefaultCellStyle); + if (style == null) { - dgvcs = new DataGridViewCellStyle(); - dgvcs.AddScope(this.DataGridView, - this._bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); - this.Properties.SetObject(PropDefaultCellStyle, dgvcs); + style = new DataGridViewCellStyle(); + style.AddScope(DataGridView, _bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); + Properties.SetObject(s_propDefaultCellStyle, style); } - return dgvcs; + + return style; } set { - DataGridViewCellStyle dgvcs = null; - if (this.HasDefaultCellStyle) + DataGridViewCellStyle style = null; + if (HasDefaultCellStyle) { - dgvcs = this.DefaultCellStyle; - dgvcs.RemoveScope(this._bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); + style = DefaultCellStyle; + style.RemoveScope(_bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); } - if (value != null || this.Properties.ContainsObject(PropDefaultCellStyle)) + if (value != null || Properties.ContainsObject(s_propDefaultCellStyle)) { - if (value != null) - { - value.AddScope(this.DataGridView, - this._bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); - } - this.Properties.SetObject(PropDefaultCellStyle, value); + value?.AddScope(DataGridView, _bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); + Properties.SetObject(s_propDefaultCellStyle, value); } - if (((dgvcs != null && value == null) || - (dgvcs == null && value != null) || - (dgvcs != null && value != null && !dgvcs.Equals(this.DefaultCellStyle))) && this.DataGridView != null) + + if (DataGridView != null && + (style != null ^ value != null) || + (style != null && value != null && !style.Equals(DefaultCellStyle))) { - this.DataGridView.OnBandDefaultCellStyleChanged(this); + DataGridView.OnBandDefaultCellStyleChanged(this); } } } - /// - [ - Browsable(false) - ] + [Browsable(false)] public Type DefaultHeaderCellType { get { - Type dhct = (Type)this.Properties.GetObject(PropDefaultHeaderCellType); - if (dhct == null) + Type type = (Type)Properties.GetObject(s_propDefaultHeaderCellType); + if (type != null) { - if (this._bandIsRow) - { - dhct = typeof(System.Windows.Forms.DataGridViewRowHeaderCell); - } - else - { - dhct = typeof(System.Windows.Forms.DataGridViewColumnHeaderCell); - } + return type; + } + + if (_bandIsRow) + { + return typeof(DataGridViewRowHeaderCell); + } + else + { + return typeof(DataGridViewColumnHeaderCell); } - return dhct; } set { - if (value != null || this.Properties.ContainsObject(PropDefaultHeaderCellType)) + if (value != null || Properties.ContainsObject(s_propDefaultHeaderCellType)) { - if (Type.GetType("System.Windows.Forms.DataGridViewHeaderCell").IsAssignableFrom(value)) - { - this.Properties.SetObject(PropDefaultHeaderCellType, value); - } - else + if (!typeof(DataGridViewHeaderCell).IsAssignableFrom(value)) { - throw new ArgumentException(string.Format(SR.DataGridView_WrongType, "DefaultHeaderCellType", "System.Windows.Forms.DataGridViewHeaderCell")); + throw new ArgumentException(string.Format(SR.DataGridView_WrongType, nameof(DefaultHeaderCellType), "System.Windows.Forms.DataGridViewHeaderCell"), nameof(value)); } + + Properties.SetObject(s_propDefaultHeaderCellType, value); } } } - /// - [ - Browsable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) - ] + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual bool Displayed { get { - Debug.Assert(!this._bandIsRow); - bool displayed = (this.State & DataGridViewElementStates.Displayed) != 0; - // Only attached and visible columns can be displayed. - // Debug.Assert(!displayed || (this.DataGridView != null && this.DataGridView.Visible && this.Visible)); - return displayed; + Debug.Assert(!_bandIsRow); + return (State & DataGridViewElementStates.Displayed) != 0; } } @@ -215,16 +172,16 @@ internal bool DisplayedInternal { set { - Debug.Assert(value != this.Displayed); + Debug.Assert(value != Displayed); if (value) { - this.StateInternal = this.State | DataGridViewElementStates.Displayed; + StateInternal = State | DataGridViewElementStates.Displayed; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.Displayed; + StateInternal = State & ~DataGridViewElementStates.Displayed; } - if (this.DataGridView != null) + if (DataGridView != null) { OnStateChanged(DataGridViewElementStates.Displayed); } @@ -235,148 +192,128 @@ internal int DividerThickness { get { - bool found; - int dividerThickness = this.Properties.GetInteger(PropDividerThickness, out found); + int dividerThickness = Properties.GetInteger(s_propDividerThickness, out bool found); return found ? dividerThickness : 0; } set { if (value < 0) { - if (this._bandIsRow) + if (_bandIsRow) { - throw new ArgumentOutOfRangeException("DividerHeight", string.Format(SR.InvalidLowBoundArgumentEx, "DividerHeight", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(DataGridViewRow.DividerHeight), value, 0)); } else { - throw new ArgumentOutOfRangeException("DividerWidth", string.Format(SR.InvalidLowBoundArgumentEx, "DividerWidth", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(DataGridViewColumn.DividerWidth), value, 0)); } } - if (value > maxBandThickness) + if (value > MaxBandThickness) { - if (this._bandIsRow) + if (_bandIsRow) { - throw new ArgumentOutOfRangeException("DividerHeight", string.Format(SR.InvalidHighBoundArgumentEx, "DividerHeight", (value).ToString(CultureInfo.CurrentCulture), (maxBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidHighBoundArgumentEx, nameof(DataGridViewRow.DividerHeight), value, MaxBandThickness)); } else { - throw new ArgumentOutOfRangeException("DividerWidth", string.Format(SR.InvalidHighBoundArgumentEx, "DividerWidth", (value).ToString(CultureInfo.CurrentCulture), (maxBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidHighBoundArgumentEx, nameof(DataGridViewColumn.DividerWidth), value, MaxBandThickness)); } } - if (value != this.DividerThickness) + + if (value != DividerThickness) { - this.Properties.SetInteger(PropDividerThickness, (int)value); - if (this.DataGridView != null) - { - this.DataGridView.OnBandDividerThicknessChanged(this); - } + Properties.SetInteger(s_propDividerThickness, value); + DataGridView?.OnBandDividerThicknessChanged(this); } } } - /// - [ - DefaultValue(false), - ] + [DefaultValue(false)] public virtual bool Frozen { get { - Debug.Assert(!this._bandIsRow); - return (this.State & DataGridViewElementStates.Frozen) != 0; + Debug.Assert(!_bandIsRow); + return (State & DataGridViewElementStates.Frozen) != 0; } set { - if (((this.State & DataGridViewElementStates.Frozen) != 0) != value) + if (((State & DataGridViewElementStates.Frozen) != 0) != value) { OnStateChanging(DataGridViewElementStates.Frozen); if (value) { - this.StateInternal = this.State | DataGridViewElementStates.Frozen; + StateInternal = State | DataGridViewElementStates.Frozen; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.Frozen; + StateInternal = State & ~DataGridViewElementStates.Frozen; } OnStateChanged(DataGridViewElementStates.Frozen); } } } - /// - [ - Browsable(false) - ] + [Browsable(false)] public bool HasDefaultCellStyle { - get - { - return this.Properties.ContainsObject(PropDefaultCellStyle) && this.Properties.GetObject(PropDefaultCellStyle) != null; - } + get => Properties.ContainsObject(s_propDefaultCellStyle) && Properties.GetObject(s_propDefaultCellStyle) != null; } internal bool HasDefaultHeaderCellType { - get - { - return this.Properties.ContainsObject(PropDefaultHeaderCellType) && this.Properties.GetObject(PropDefaultHeaderCellType) != null; - } + get => Properties.ContainsObject(s_propDefaultHeaderCellType) && Properties.GetObject(s_propDefaultHeaderCellType) != null; } internal bool HasHeaderCell { - get - { - return this.Properties.ContainsObject(PropHeaderCell) && this.Properties.GetObject(PropHeaderCell) != null; - } + get => Properties.ContainsObject(s_propHeaderCell) && Properties.GetObject(s_propHeaderCell) != null; } - /// - [ - Browsable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) - ] + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] protected DataGridViewHeaderCell HeaderCellCore { get { - DataGridViewHeaderCell headerCell = (DataGridViewHeaderCell)this.Properties.GetObject(PropHeaderCell); + DataGridViewHeaderCell headerCell = (DataGridViewHeaderCell)Properties.GetObject(s_propHeaderCell); if (headerCell == null) { - Type cellType = this.DefaultHeaderCellType; + Type cellType = DefaultHeaderCellType; - headerCell = (DataGridViewHeaderCell) Activator.CreateInstance(cellType); - headerCell.DataGridViewInternal = this.DataGridView; - if (this._bandIsRow) + headerCell = (DataGridViewHeaderCell)Activator.CreateInstance(cellType); + headerCell.DataGridViewInternal = DataGridView; + if (_bandIsRow) { headerCell.OwningRowInternal = (DataGridViewRow)this; // may be a shared row - this.Properties.SetObject(PropHeaderCell, headerCell); + Properties.SetObject(s_propHeaderCell, headerCell); } else { DataGridViewColumn dataGridViewColumn = this as DataGridViewColumn; headerCell.OwningColumnInternal = dataGridViewColumn; // Set the headerCell in the property store before setting the SortOrder. - this.Properties.SetObject(PropHeaderCell, headerCell); - if (this.DataGridView != null && this.DataGridView.SortedColumn == dataGridViewColumn) + Properties.SetObject(s_propHeaderCell, headerCell); + if (DataGridView != null && DataGridView.SortedColumn == dataGridViewColumn) { DataGridViewColumnHeaderCell dataGridViewColumnHeaderCell = headerCell as DataGridViewColumnHeaderCell; Debug.Assert(dataGridViewColumnHeaderCell != null); - dataGridViewColumnHeaderCell.SortGlyphDirection = this.DataGridView.SortOrder; + dataGridViewColumnHeaderCell.SortGlyphDirection = DataGridView.SortOrder; } } } + return headerCell; } set { - DataGridViewHeaderCell headerCell = (DataGridViewHeaderCell)this.Properties.GetObject(PropHeaderCell); - if (value != null || this.Properties.ContainsObject(PropHeaderCell)) + DataGridViewHeaderCell headerCell = (DataGridViewHeaderCell)Properties.GetObject(s_propHeaderCell); + if (value != null || Properties.ContainsObject(s_propHeaderCell)) { if (headerCell != null) { headerCell.DataGridViewInternal = null; - if (this._bandIsRow) + if (_bandIsRow) { headerCell.OwningRowInternal = null; } @@ -389,12 +326,13 @@ protected DataGridViewHeaderCell HeaderCellCore if (value != null) { - if (this._bandIsRow) + if (_bandIsRow) { if (!(value is DataGridViewRowHeaderCell)) { - throw new ArgumentException(string.Format(SR.DataGridView_WrongType, "HeaderCell", "System.Windows.Forms.DataGridViewRowHeaderCell")); + throw new ArgumentException(string.Format(SR.DataGridView_WrongType, nameof(DataGridViewRow.HeaderCell), "System.Windows.Forms.DataGridViewRowHeaderCell"), nameof(value)); } + // A HeaderCell can only be used by one band. if (value.OwningRow != null) { @@ -408,8 +346,9 @@ protected DataGridViewHeaderCell HeaderCellCore DataGridViewColumnHeaderCell dataGridViewColumnHeaderCell = value as DataGridViewColumnHeaderCell; if (dataGridViewColumnHeaderCell == null) { - throw new ArgumentException(string.Format(SR.DataGridView_WrongType, "HeaderCell", "System.Windows.Forms.DataGridViewColumnHeaderCell")); + throw new ArgumentException(string.Format(SR.DataGridView_WrongType, nameof(DataGridViewColumn.HeaderCell), "System.Windows.Forms.DataGridViewColumnHeaderCell"), nameof(value)); } + // A HeaderCell can only be used by one band. if (value.OwningColumn != null) { @@ -420,132 +359,92 @@ protected DataGridViewHeaderCell HeaderCellCore value.OwningColumnInternal = (DataGridViewColumn)this; } Debug.Assert(value.DataGridView == null); - value.DataGridViewInternal = this.DataGridView; + value.DataGridViewInternal = DataGridView; } - this.Properties.SetObject(PropHeaderCell, value); + Properties.SetObject(s_propHeaderCell, value); } - if (((value == null && headerCell != null) || (value != null && headerCell == null) || (value != null && headerCell != null && !headerCell.Equals(value))) && this.DataGridView != null) + if (((value == null && headerCell != null) || (value != null && headerCell == null) || (value != null && headerCell != null && !headerCell.Equals(value))) && DataGridView != null) { - this.DataGridView.OnBandHeaderCellChanged(this); + DataGridView.OnBandHeaderCellChanged(this); } } } - /// - /// - /// - /// - [ - Browsable(false) - ] - public int Index - { - get - { - return this.bandIndex; - } - } + [Browsable(false)] + public int Index => _bandIndex; internal int IndexInternal { - set - { - this.bandIndex = value; - } + set => _bandIndex = value; } - /// - [ - Browsable(false) - ] - public virtual DataGridViewCellStyle InheritedStyle - { - get - { - return null; - } - } + [Browsable(false)] + public virtual DataGridViewCellStyle InheritedStyle => null; - /// - protected bool IsRow - { - get - { - return this._bandIsRow; - } - } + protected bool IsRow => _bandIsRow; internal int MinimumThickness { get { - if (this._bandIsRow && this.bandIndex > -1) + if (_bandIsRow && _bandIndex > -1) { - int height, minimumHeight; - GetHeightInfo(this.bandIndex, out height, out minimumHeight); + GetHeightInfo(_bandIndex, out int height, out int minimumHeight); return minimumHeight; } - return this.minimumThickness; + + return _minimumThickness; } set { - if (this.minimumThickness != value) + if (_minimumThickness != value) { - if (value < minBandThickness) + if (value < MinBandThickness) { - if (this._bandIsRow) + if (_bandIsRow) { - throw new ArgumentOutOfRangeException("MinimumHeight", value, string.Format(SR.DataGridViewBand_MinimumHeightSmallerThanOne, (DataGridViewBand.minBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.DataGridViewBand_MinimumHeightSmallerThanOne, DataGridViewBand.MinBandThickness)); } else { - throw new ArgumentOutOfRangeException("MinimumWidth", value, string.Format(SR.DataGridViewBand_MinimumWidthSmallerThanOne, (DataGridViewBand.minBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.DataGridViewBand_MinimumWidthSmallerThanOne, DataGridViewBand.MinBandThickness)); } } - if (this.Thickness < value) + + if (Thickness < value) { // Force the new minimum width on potential auto fill column. - if (this.DataGridView != null && !this._bandIsRow) + if (DataGridView != null && !_bandIsRow) { - this.DataGridView.OnColumnMinimumWidthChanging((DataGridViewColumn)this, value); + DataGridView.OnColumnMinimumWidthChanging((DataGridViewColumn)this, value); } - this.Thickness = value; - } - this.minimumThickness = value; - if (this.DataGridView != null) - { - this.DataGridView.OnBandMinimumThicknessChanged(this); + + Thickness = value; } + + _minimumThickness = value; + DataGridView?.OnBandMinimumThicknessChanged(this); } } } - internal PropertyStore Properties - { - get - { - return this.propertyStore; - } - } + internal PropertyStore Properties => _propertyStore; - /// - [ - DefaultValue(false) - ] + [DefaultValue(false)] public virtual bool ReadOnly { get { - Debug.Assert(!this._bandIsRow); - return ((this.State & DataGridViewElementStates.ReadOnly) != 0 || - (this.DataGridView != null && this.DataGridView.ReadOnly)); + Debug.Assert(!_bandIsRow); + return ((State & DataGridViewElementStates.ReadOnly) != 0 || + (DataGridView != null && DataGridView.ReadOnly)); } set { - if (this.DataGridView != null) + if (DataGridView != null) { - if (this.DataGridView.ReadOnly) + if (DataGridView.ReadOnly) { // if (!value): Trying to make a band read-write when the whole grid is read-only. // if (value): Trying to make a band read-only when the whole grid is read-only. @@ -554,31 +453,32 @@ public virtual bool ReadOnly } // this may trigger a call to set_ReadOnlyInternal - if (this._bandIsRow) + if (_bandIsRow) { - if (this.bandIndex == -1) + if (_bandIndex == -1) { - throw new InvalidOperationException(string.Format(SR.DataGridView_InvalidPropertySetOnSharedRow, "ReadOnly")); + throw new InvalidOperationException(string.Format(SR.DataGridView_InvalidPropertySetOnSharedRow, nameof(ReadOnly))); } + OnStateChanging(DataGridViewElementStates.ReadOnly); - this.DataGridView.SetReadOnlyRowCore(this.bandIndex, value); + DataGridView.SetReadOnlyRowCore(_bandIndex, value); } else { - Debug.Assert(this.bandIndex >= 0); + Debug.Assert(_bandIndex >= 0); OnStateChanging(DataGridViewElementStates.ReadOnly); - this.DataGridView.SetReadOnlyColumnCore(this.bandIndex, value); + DataGridView.SetReadOnlyColumnCore(_bandIndex, value); } } else { - if (((this.State & DataGridViewElementStates.ReadOnly) != 0) != value) + if (((State & DataGridViewElementStates.ReadOnly) != 0) != value) { if (value) { - if (this._bandIsRow) + if (_bandIsRow) { - foreach (DataGridViewCell dataGridViewCell in ((DataGridViewRow) this).Cells) + foreach (DataGridViewCell dataGridViewCell in ((DataGridViewRow)this).Cells) { if (dataGridViewCell.ReadOnly) { @@ -586,11 +486,11 @@ public virtual bool ReadOnly } } } - this.StateInternal = this.State | DataGridViewElementStates.ReadOnly; + StateInternal = State | DataGridViewElementStates.ReadOnly; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.ReadOnly; + StateInternal = State & ~DataGridViewElementStates.ReadOnly; } } } @@ -601,41 +501,37 @@ internal bool ReadOnlyInternal { set { - Debug.Assert(value != this.ReadOnly); + Debug.Assert(value != ReadOnly); if (value) { - this.StateInternal = this.State | DataGridViewElementStates.ReadOnly; + StateInternal = State | DataGridViewElementStates.ReadOnly; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.ReadOnly; + StateInternal = State & ~DataGridViewElementStates.ReadOnly; } - Debug.Assert(this.DataGridView != null); + + Debug.Assert(DataGridView != null); OnStateChanged(DataGridViewElementStates.ReadOnly); } } - /// - [ - Browsable(true) - ] + [Browsable(true)] public virtual DataGridViewTriState Resizable { get { - Debug.Assert(!this._bandIsRow); - if ((this.State & DataGridViewElementStates.ResizableSet) != 0) + Debug.Assert(!_bandIsRow); + if ((State & DataGridViewElementStates.ResizableSet) != 0) { - return ((this.State & DataGridViewElementStates.Resizable) != 0) ? DataGridViewTriState.True : DataGridViewTriState.False; + return ((State & DataGridViewElementStates.Resizable) != 0) ? DataGridViewTriState.True : DataGridViewTriState.False; } - if (this.DataGridView != null) - { - return this.DataGridView.AllowUserToResizeColumns ? DataGridViewTriState.True : DataGridViewTriState.False; - } - else + if (DataGridView == null) { return DataGridViewTriState.NotSet; } + + return DataGridView.AllowUserToResizeColumns ? DataGridViewTriState.True : DataGridViewTriState.False; } set { @@ -644,74 +540,72 @@ public virtual DataGridViewTriState Resizable throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(DataGridViewTriState)); } - DataGridViewTriState oldResizable = this.Resizable; + DataGridViewTriState oldResizable = Resizable; if (value == DataGridViewTriState.NotSet) { - this.StateInternal = this.State & ~DataGridViewElementStates.ResizableSet; + StateInternal = State & ~DataGridViewElementStates.ResizableSet; } else { - this.StateInternal = this.State | DataGridViewElementStates.ResizableSet; - if (((this.State & DataGridViewElementStates.Resizable) != 0) != (value == DataGridViewTriState.True)) + StateInternal = State | DataGridViewElementStates.ResizableSet; + if (((State & DataGridViewElementStates.Resizable) != 0) != (value == DataGridViewTriState.True)) { if (value == DataGridViewTriState.True) { - this.StateInternal = this.State | DataGridViewElementStates.Resizable; + StateInternal = State | DataGridViewElementStates.Resizable; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.Resizable; + StateInternal = State & ~DataGridViewElementStates.Resizable; } } } - if (oldResizable != this.Resizable) + + if (oldResizable != Resizable) { OnStateChanged(DataGridViewElementStates.Resizable); } } } - /// - [ - Browsable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) - ] + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual bool Selected { get { - Debug.Assert(!this._bandIsRow); - return (this.State & DataGridViewElementStates.Selected) != 0; + Debug.Assert(!_bandIsRow); + return (State & DataGridViewElementStates.Selected) != 0; } set { - if (this.DataGridView != null) + if (DataGridView != null) { // this may trigger a call to set_SelectedInternal - if (this._bandIsRow) + if (_bandIsRow) { - if (this.bandIndex == -1) + if (_bandIndex == -1) { - throw new InvalidOperationException(string.Format(SR.DataGridView_InvalidPropertySetOnSharedRow, "Selected")); + throw new InvalidOperationException(string.Format(SR.DataGridView_InvalidPropertySetOnSharedRow, nameof(Selected))); } - if (this.DataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect || this.DataGridView.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) + if (DataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect || DataGridView.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) { - this.DataGridView.SetSelectedRowCoreInternal(this.bandIndex, value); + DataGridView.SetSelectedRowCoreInternal(_bandIndex, value); } } else { - Debug.Assert(this.bandIndex >= 0); - if (this.DataGridView.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || this.DataGridView.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) + Debug.Assert(_bandIndex >= 0); + if (DataGridView.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || DataGridView.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) { - this.DataGridView.SetSelectedColumnCoreInternal(this.bandIndex, value); + DataGridView.SetSelectedColumnCoreInternal(_bandIndex, value); } } } else if (value) { // We do not allow the selection of a band before it gets added to the dataGridView. - throw new InvalidOperationException(string.Format(SR.DataGridViewBand_CannotSelect)); + throw new InvalidOperationException(SR.DataGridViewBand_CannotSelect); } } } @@ -720,38 +614,33 @@ internal bool SelectedInternal { set { - Debug.Assert(value != this.Selected); + Debug.Assert(value != Selected); if (value) { - this.StateInternal = this.State | DataGridViewElementStates.Selected; + StateInternal = State | DataGridViewElementStates.Selected; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.Selected; + StateInternal = State & ~DataGridViewElementStates.Selected; } - if (this.DataGridView != null) + + if (DataGridView != null) { OnStateChanged(DataGridViewElementStates.Selected); } } } - /// - [ - Browsable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) - ] + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public object Tag { - get - { - return Properties.GetObject(PropUserData); - } + get => Properties.GetObject(s_propUserData); set { - if (value != null || this.Properties.ContainsObject(PropUserData)) + if (value != null || Properties.ContainsObject(s_propUserData)) { - Properties.SetObject(PropUserData, value); + Properties.SetObject(s_propUserData, value); } } } @@ -760,189 +649,176 @@ internal int Thickness { get { - if (this._bandIsRow && this.bandIndex > -1) + if (_bandIsRow && _bandIndex > -1) { - int height, minimumHeight; - GetHeightInfo(this.bandIndex, out height, out minimumHeight); + GetHeightInfo(_bandIndex, out int height, out int minimumHeight); return height; } - return this.thickness; + + return _thickness; } set { - int minimumThickness = this.MinimumThickness; + int minimumThickness = MinimumThickness; if (value < minimumThickness) { value = minimumThickness; } - if (value > maxBandThickness) + if (value > MaxBandThickness) { - if (this._bandIsRow) + if (_bandIsRow) { - throw new ArgumentOutOfRangeException("Height", string.Format(SR.InvalidHighBoundArgumentEx, "Height", (value).ToString(CultureInfo.CurrentCulture), (maxBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidHighBoundArgumentEx, nameof(DataGridViewRow.Height), value, MaxBandThickness)); } else { - throw new ArgumentOutOfRangeException("Width", string.Format(SR.InvalidHighBoundArgumentEx, "Width", (value).ToString(CultureInfo.CurrentCulture), (maxBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidHighBoundArgumentEx, nameof(DataGridViewColumn.Width), value, MaxBandThickness)); } } + bool setThickness = true; - if (this._bandIsRow) + if (_bandIsRow) { - if (this.DataGridView != null && this.DataGridView.AutoSizeRowsMode != DataGridViewAutoSizeRowsMode.None) + if (DataGridView != null && DataGridView.AutoSizeRowsMode != DataGridViewAutoSizeRowsMode.None) { - this.cachedThickness = value; + CachedThickness = value; setThickness = false; } } else { - DataGridViewColumn dataGridViewColumn = (DataGridViewColumn) this; + DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)this; DataGridViewAutoSizeColumnMode inheritedAutoSizeMode = dataGridViewColumn.InheritedAutoSizeMode; if (inheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.Fill && inheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.None && inheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.NotSet) { - this.cachedThickness = value; + CachedThickness = value; setThickness = false; } - else if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && this.DataGridView != null) + else if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && DataGridView != null) { if (dataGridViewColumn.Visible) { - IntPtr handle = this.DataGridView.Handle; - this.DataGridView.AdjustFillingColumn(dataGridViewColumn, value); + IntPtr handle = DataGridView.Handle; + DataGridView.AdjustFillingColumn(dataGridViewColumn, value); setThickness = false; } } } - if (setThickness && this.thickness != value) + if (setThickness && _thickness != value) { - if (this.DataGridView != null) - { - this.DataGridView.OnBandThicknessChanging(); - } - this.ThicknessInternal = value; + DataGridView?.OnBandThicknessChanging(); + ThicknessInternal = value; } } } internal int ThicknessInternal { - get - { - return this.thickness; - } + get => _thickness; set { - Debug.Assert(this.thickness != value); - Debug.Assert(value >= this.minimumThickness); - Debug.Assert(value <= maxBandThickness); + Debug.Assert(_thickness != value); + Debug.Assert(value >= _minimumThickness); + Debug.Assert(value <= MaxBandThickness); - this.thickness = value; - if (this.DataGridView != null) - { - this.DataGridView.OnBandThicknessChanged(this); - } + _thickness = value; + DataGridView?.OnBandThicknessChanged(this); } } - /// - [ - DefaultValue(true), - ] + [DefaultValue(true)] public virtual bool Visible { get { - Debug.Assert(!this._bandIsRow); - return (this.State & DataGridViewElementStates.Visible) != 0; + Debug.Assert(!_bandIsRow); + return (State & DataGridViewElementStates.Visible) != 0; } set { - if (((this.State & DataGridViewElementStates.Visible) != 0) != value) + if (((State & DataGridViewElementStates.Visible) != 0) != value) { - if (this.DataGridView != null && - this._bandIsRow && - this.DataGridView.NewRowIndex != -1 && - this.DataGridView.NewRowIndex == this.bandIndex && + if (DataGridView != null && + _bandIsRow && + DataGridView.NewRowIndex != -1 && + DataGridView.NewRowIndex == _bandIndex && !value) { // the 'new' row cannot be made invisble. - throw new InvalidOperationException(string.Format(SR.DataGridViewBand_NewRowCannotBeInvisible)); + throw new InvalidOperationException(SR.DataGridViewBand_NewRowCannotBeInvisible); } + OnStateChanging(DataGridViewElementStates.Visible); if (value) { - this.StateInternal = this.State | DataGridViewElementStates.Visible; + StateInternal = State | DataGridViewElementStates.Visible; } else { - this.StateInternal = this.State & ~DataGridViewElementStates.Visible; + StateInternal = State & ~DataGridViewElementStates.Visible; } OnStateChanged(DataGridViewElementStates.Visible); } } } - /// public virtual object Clone() { - DataGridViewBand dataGridViewBand = (DataGridViewBand) System.Activator.CreateInstance(this.GetType()); - if (dataGridViewBand != null) + DataGridViewBand band = (DataGridViewBand)Activator.CreateInstance(GetType()); + if (band != null) { - CloneInternal(dataGridViewBand); + CloneInternal(band); } - return dataGridViewBand; + return band; } internal void CloneInternal(DataGridViewBand dataGridViewBand) { - dataGridViewBand.propertyStore = new PropertyStore(); - dataGridViewBand.bandIndex = -1; - dataGridViewBand._bandIsRow = this._bandIsRow; - if (!this._bandIsRow || this.bandIndex >= 0 || this.DataGridView == null) + dataGridViewBand._propertyStore = new PropertyStore(); + dataGridViewBand._bandIndex = -1; + dataGridViewBand._bandIsRow = _bandIsRow; + if (!_bandIsRow || _bandIndex >= 0 || DataGridView == null) { - dataGridViewBand.StateInternal = this.State & ~(DataGridViewElementStates.Selected | DataGridViewElementStates.Displayed); + dataGridViewBand.StateInternal = State & ~(DataGridViewElementStates.Selected | DataGridViewElementStates.Displayed); } - dataGridViewBand.thickness = this.Thickness; - dataGridViewBand.MinimumThickness = this.MinimumThickness; - dataGridViewBand.cachedThickness = this.CachedThickness; - dataGridViewBand.DividerThickness = this.DividerThickness; - dataGridViewBand.Tag = this.Tag; - if (this.HasDefaultCellStyle) + dataGridViewBand._thickness = Thickness; + dataGridViewBand.MinimumThickness = MinimumThickness; + dataGridViewBand.CachedThickness = CachedThickness; + dataGridViewBand.DividerThickness = DividerThickness; + dataGridViewBand.Tag = Tag; + if (HasDefaultCellStyle) { - dataGridViewBand.DefaultCellStyle = new DataGridViewCellStyle(this.DefaultCellStyle); + dataGridViewBand.DefaultCellStyle = new DataGridViewCellStyle(DefaultCellStyle); } - if (this.HasDefaultHeaderCellType) + if (HasDefaultHeaderCellType) { - dataGridViewBand.DefaultHeaderCellType = this.DefaultHeaderCellType; + dataGridViewBand.DefaultHeaderCellType = DefaultHeaderCellType; } - if (this.ContextMenuStripInternal != null) + if (ContextMenuStripInternal != null) { - dataGridViewBand.ContextMenuStrip = this.ContextMenuStripInternal.Clone(); + dataGridViewBand.ContextMenuStrip = ContextMenuStripInternal.Clone(); } } private void DetachContextMenuStrip(object sender, EventArgs e) { - this.ContextMenuStripInternal = null; + ContextMenuStripInternal = null; } - - /// + public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } - /// protected virtual void Dispose(bool disposing) { - if (disposing) + if (disposing) { - ContextMenuStrip contextMenuStrip = (ContextMenuStrip)this.ContextMenuStripInternal; + ContextMenuStrip contextMenuStrip = (ContextMenuStrip)ContextMenuStripInternal; if (contextMenuStrip != null) { contextMenuStrip.Disposed -= new EventHandler(DetachContextMenuStrip); @@ -952,105 +828,100 @@ protected virtual void Dispose(bool disposing) internal void GetHeightInfo(int rowIndex, out int height, out int minimumHeight) { - Debug.Assert(this._bandIsRow); - if (this.DataGridView != null && - (this.DataGridView.VirtualMode || this.DataGridView.DataSource != null) && - this.DataGridView.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) + Debug.Assert(_bandIsRow); + if (DataGridView != null && + (DataGridView.VirtualMode || DataGridView.DataSource != null) && + DataGridView.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { Debug.Assert(rowIndex > -1); - DataGridViewRowHeightInfoNeededEventArgs dgvrhine = this.DataGridView.OnRowHeightInfoNeeded(rowIndex, this.thickness, this.minimumThickness); - height = dgvrhine.Height; - minimumHeight = dgvrhine.MinimumHeight; + DataGridViewRowHeightInfoNeededEventArgs e = DataGridView.OnRowHeightInfoNeeded(rowIndex, _thickness, _minimumThickness); + height = e.Height; + minimumHeight = e.MinimumHeight; return; } - height = this.thickness; - minimumHeight = this.minimumThickness; + + height = _thickness; + minimumHeight = _minimumThickness; } internal void OnStateChanged(DataGridViewElementStates elementState) { - if (this.DataGridView != null) + if (DataGridView != null) { // maybe move this code into OnDataGridViewElementStateChanged - if (this._bandIsRow) + if (_bandIsRow) { // we could be smarter about what needs to be invalidated. - this.DataGridView.Rows.InvalidateCachedRowCount(elementState); - this.DataGridView.Rows.InvalidateCachedRowsHeight(elementState); - if (this.bandIndex != -1) + DataGridView.Rows.InvalidateCachedRowCount(elementState); + DataGridView.Rows.InvalidateCachedRowsHeight(elementState); + if (_bandIndex != -1) { - this.DataGridView.OnDataGridViewElementStateChanged(this, -1, elementState); + DataGridView.OnDataGridViewElementStateChanged(this, -1, elementState); } } else { // we could be smarter about what needs to be invalidated. - this.DataGridView.Columns.InvalidateCachedColumnCount(elementState); - this.DataGridView.Columns.InvalidateCachedColumnsWidth(elementState); - this.DataGridView.OnDataGridViewElementStateChanged(this, -1, elementState); + DataGridView.Columns.InvalidateCachedColumnCount(elementState); + DataGridView.Columns.InvalidateCachedColumnsWidth(elementState); + DataGridView.OnDataGridViewElementStateChanged(this, -1, elementState); } } } - private void OnStateChanging(DataGridViewElementStates elementState) + private void OnStateChanging(DataGridViewElementStates elementState) { - if (this.DataGridView != null) + if (DataGridView != null) { - if (this._bandIsRow) + if (_bandIsRow) { - if (this.bandIndex != -1) + if (_bandIndex != -1) { - this.DataGridView.OnDataGridViewElementStateChanging(this, -1, elementState); + DataGridView.OnDataGridViewElementStateChanging(this, -1, elementState); } } else { - this.DataGridView.OnDataGridViewElementStateChanging(this, -1, elementState); + DataGridView.OnDataGridViewElementStateChanging(this, -1, elementState); } } } - /// protected override void OnDataGridViewChanged() { - if (this.HasDefaultCellStyle) + if (HasDefaultCellStyle) { - if (this.DataGridView == null) + if (DataGridView == null) { - this.DefaultCellStyle.RemoveScope(this._bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); + DefaultCellStyle.RemoveScope(_bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); } else { - this.DefaultCellStyle.AddScope(this.DataGridView, - this._bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); + DefaultCellStyle.AddScope(DataGridView, _bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column); } } + base.OnDataGridViewChanged(); } - private bool ShouldSerializeDefaultHeaderCellType() + private bool ShouldSerializeDefaultHeaderCellType() { - Type dhct = (Type)this.Properties.GetObject(PropDefaultHeaderCellType); - return dhct != null; + return Properties.GetObject(s_propDefaultHeaderCellType) != null; } // internal because DataGridViewColumn needs to access it internal bool ShouldSerializeResizable() { - return (this.State & DataGridViewElementStates.ResizableSet) != 0; + return (State & DataGridViewElementStates.ResizableSet) != 0; } - /// - /// - /// - /// public override string ToString() { - StringBuilder sb = new StringBuilder(36); - sb.Append("DataGridViewBand { Index="); - sb.Append(this.Index.ToString(CultureInfo.CurrentCulture)); - sb.Append(" }"); - return sb.ToString(); + var builder = new StringBuilder(36); + builder.Append("DataGridViewBand { Index="); + builder.Append(Index); + builder.Append(" }"); + return builder.ToString(); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonCell.cs index 190ff03adea..637a5ec50d0 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonCell.cs @@ -1135,15 +1135,7 @@ public override int GetChildCount() return 0; } - internal override bool IsIAccessibleExSupported() - { - if (AccessibilityImprovements.Level2) - { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonColumn.cs index 68c72783f3c..abba3e2ba4a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewButtonColumn.cs @@ -13,7 +13,7 @@ namespace System.Windows.Forms using System.Diagnostics.CodeAnalysis; /// - [ToolboxBitmapAttribute(typeof(DataGridViewButtonColumn), "DataGridViewButtonColumn.bmp")] + [ToolboxBitmapAttribute(typeof(DataGridViewButtonColumn), "DataGridViewButtonColumn")] public class DataGridViewButtonColumn : DataGridViewColumn { private static Type columnType = typeof(DataGridViewButtonColumn); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCell.cs index 0f63350ecba..7fd6ff706ea 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCell.cs @@ -2,10 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// Code taken from ASP.NET file xsp\System\Web\httpserverutility.cs -// Don't entity encode high chars (160 to 256) -#define ENTITY_ENCODE_HIGH_ASCII_CHARS - namespace System.Windows.Forms { using System; @@ -76,8 +72,10 @@ public abstract class DataGridViewCell : DataGridViewElement, ICloneable, IDispo /// protected DataGridViewCell() : base() { - if (!isScalingInitialized) { - if (DpiHelper.IsScalingRequired) { + if (!isScalingInitialized) + { + if (DpiHelper.IsScalingRequired) + { iconsWidth = (byte)DpiHelper.LogicalToDeviceUnitsX(DATAGRIDVIEWCELL_iconsWidth); iconsHeight = (byte)DpiHelper.LogicalToDeviceUnitsY(DATAGRIDVIEWCELL_iconsHeight); } @@ -89,7 +87,7 @@ protected DataGridViewCell() : base() } /// - ~DataGridViewCell() + ~DataGridViewCell() { Dispose(false); } @@ -102,7 +100,7 @@ public AccessibleObject AccessibilityObject { get { - AccessibleObject result = (AccessibleObject) this.Properties.GetObject(PropCellAccessibilityObject); + AccessibleObject result = (AccessibleObject)this.Properties.GetObject(PropCellAccessibilityObject); if (result == null) { result = this.CreateAccessibilityInstance(); @@ -190,7 +188,7 @@ private byte CurrentMouseLocation { get { - return (byte) (this.flags & (DATAGRIDVIEWCELL_flagDataArea | DATAGRIDVIEWCELL_flagErrorArea)); + return (byte)(this.flags & (DATAGRIDVIEWCELL_flagDataArea | DATAGRIDVIEWCELL_flagErrorArea)); } set { @@ -275,7 +273,7 @@ private static Bitmap ErrorBitmap { if (errorBmp == null) { - errorBmp = GetBitmap("DataGridViewRow.error.bmp"); + errorBmp = GetBitmap("DataGridViewRow.error"); } return errorBmp; } @@ -482,7 +480,7 @@ public DataGridViewCellStyle InheritedStyle [ Browsable(false) ] - public bool IsInEditMode + public bool IsInEditMode { get { @@ -563,7 +561,7 @@ internal PropertyStore Properties return this.propertyStore; } } - + /// [ Browsable(false), @@ -641,7 +639,7 @@ internal bool ReadOnlyInternal } } } - + /// [ Browsable(false) @@ -685,7 +683,7 @@ public int RowIndex return this.owningRow.Index; } } - + /// [ Browsable(false), @@ -820,8 +818,8 @@ public DataGridViewCellStyle Style } this.Properties.SetObject(PropCellStyle, value); } - if (((dgvcs != null && value == null) || - (dgvcs == null && value != null) || + if (((dgvcs != null && value == null) || + (dgvcs == null && value != null) || (dgvcs != null && value != null && !dgvcs.Equals(this.Style))) && this.DataGridView != null) { this.DataGridView.OnCellStyleChanged(this); @@ -832,10 +830,10 @@ public DataGridViewCellStyle Style /// [ SRCategory(nameof(SR.CatData)), - Localizable(false), - Bindable(true), - SRDescription(nameof(SR.ControlTagDescr)), - DefaultValue(null), + Localizable(false), + Bindable(true), + SRDescription(nameof(SR.ControlTagDescr)), + DefaultValue(null), TypeConverter(typeof(StringConverter)) ] public object Tag @@ -852,7 +850,7 @@ public object Tag } } } - + /// [ Browsable(false), @@ -917,7 +915,7 @@ public virtual Type ValueType { get { - Type cellValueType = (Type) this.Properties.GetObject(PropCellValueType); + Type cellValueType = (Type)this.Properties.GetObject(PropCellValueType); if (cellValueType == null && this.OwningColumn != null) { cellValueType = this.OwningColumn.ValueType; @@ -1104,7 +1102,7 @@ internal DataGridViewElementStates CellStateFromColumnRowStates() Debug.Assert(this.RowIndex >= 0); return CellStateFromColumnRowStates(this.owningRow.State); }*/ - + internal DataGridViewElementStates CellStateFromColumnRowStates(DataGridViewElementStates rowState) { Debug.Assert(this.DataGridView != null); @@ -1160,7 +1158,7 @@ internal void CloneInternal(DataGridViewCell dataGridViewCell) /// public virtual object Clone() { - DataGridViewCell dataGridViewCell = (DataGridViewCell) System.Activator.CreateInstance(this.GetType()); + DataGridViewCell dataGridViewCell = (DataGridViewCell)System.Activator.CreateInstance(this.GetType()); CloneInternal(dataGridViewCell); return dataGridViewCell; } @@ -1203,9 +1201,9 @@ internal void ComputeBorderStyleCellStateAndCellBounds(int rowIndex, Debug.Assert(this is DataGridViewColumnHeaderCell, "if the row index == -1 and we have an owning column this should be a column header cell"); DataGridViewColumn dataGridViewColumn = this.DataGridView.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); bool isLastVisibleColumn = (dataGridViewColumn != null && dataGridViewColumn.Index == this.ColumnIndex); - dgvabsEffective = this.DataGridView.AdjustColumnHeaderBorderStyle(this.DataGridView.AdvancedColumnHeadersBorderStyle, + dgvabsEffective = this.DataGridView.AdjustColumnHeaderBorderStyle(this.DataGridView.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder, - this.ColumnIndex == this.DataGridView.FirstDisplayedColumnIndex, + this.ColumnIndex == this.DataGridView.FirstDisplayedColumnIndex, isLastVisibleColumn); cellState = this.OwningColumn.State | this.State; } @@ -1231,7 +1229,7 @@ internal void ComputeBorderStyleCellStateAndCellBounds(int rowIndex, cellState = this.State; } - cellBounds = new Rectangle(new Point(0, 0), GetSize(rowIndex)); + cellBounds = new Rectangle(new Point(0, 0), GetSize(rowIndex)); } internal Rectangle ComputeErrorIconBounds(Rectangle cellValueBounds) @@ -1325,23 +1323,20 @@ public virtual void DetachEditingControl() dgv.EditingPanel.Controls.Remove(dgv.EditingControl); Debug.Assert(dgv.EditingControl.ParentInternal == null); - if (AccessibilityImprovements.Level3) + if (dgv.EditingControl is DataGridViewTextBoxEditingControl) { - if (dgv.EditingControl is DataGridViewTextBoxEditingControl) - { - dgv.TextBoxControlWasDetached = true; - } + dgv.TextBoxControlWasDetached = true; + } - if (dgv.EditingControl is DataGridViewComboBoxEditingControl) - { - dgv.ComboBoxControlWasDetached = true; - } + if (dgv.EditingControl is DataGridViewComboBoxEditingControl) + { + dgv.ComboBoxControlWasDetached = true; + } - dgv.EditingControlAccessibleObject.SetParent(null); - AccessibilityObject.SetDetachableChild(null); + dgv.EditingControlAccessibleObject.SetParent(null); + AccessibilityObject.SetDetachableChild(null); - AccessibilityObject.RaiseStructureChangedEvent(UnsafeNativeMethods.StructureChangeType.ChildRemoved, dgv.EditingControlAccessibleObject.RuntimeId); - } + AccessibilityObject.RaiseStructureChangedEvent(UnsafeNativeMethods.StructureChangeType.ChildRemoved, dgv.EditingControlAccessibleObject.RuntimeId); } if (dgv.EditingPanel.ParentInternal != null) { @@ -1360,7 +1355,7 @@ public virtual void DetachEditingControl() // so that the tooltip appears again on mousemove after the editing. this.CurrentMouseLocation = DATAGRIDVIEWCELL_flagAreaNotSet; } - + /// public void Dispose() { @@ -1371,7 +1366,7 @@ public void Dispose() /// protected virtual void Dispose(bool disposing) { - if (disposing) + if (disposing) { ContextMenuStrip contextMenuStrip = (ContextMenuStrip)this.ContextMenuStripInternal; if (contextMenuStrip != null) @@ -1508,8 +1503,9 @@ internal static void FormatPlainTextAsHtml(string s, TextWriter output) break; // default: - #if ENTITY_ENCODE_HIGH_ASCII_CHARS // The seemingly arbitrary 160 comes from RFC + // Code taken from ASP.NET file xsp\System\Web\httpserverutility.cs + // Don't entity encode high chars (160 to 256) if (ch >= 160 && ch < 256) { output.Write("&#"); @@ -1517,7 +1513,6 @@ internal static void FormatPlainTextAsHtml(string s, TextWriter output) output.Write(';'); break; } - #endif // ENTITY_ENCODE_HIGH_ASCII_CHARS output.Write(ch); break; } @@ -1527,11 +1522,12 @@ internal static void FormatPlainTextAsHtml(string s, TextWriter output) private static Bitmap GetBitmap(string bitmapName) { - Bitmap b = new Bitmap(typeof(DataGridViewCell), bitmapName); - b.MakeTransparent(); - if (DpiHelper.IsScalingRequired) { + Bitmap b = DpiHelper.GetBitmapFromIcon(typeof(DataGridViewCell), bitmapName); + if (DpiHelper.IsScalingRequired) + { Bitmap scaledBitmap = DpiHelper.CreateResizedBitmap(b, new Size(iconsWidth, iconsHeight)); - if (scaledBitmap != null) { + if (scaledBitmap != null) + { b.Dispose(); b = scaledBitmap; } @@ -1643,11 +1639,11 @@ protected virtual object GetClipboardContent(int rowIndex, } } - internal object GetClipboardContentInternal(int rowIndex, - bool firstCell, - bool lastCell, - bool inFirstRow, - bool inLastRow, + internal object GetClipboardContentInternal(int rowIndex, + bool firstCell, + bool lastCell, + bool inFirstRow, + bool inLastRow, string format) { return GetClipboardContent(rowIndex, firstCell, lastCell, inFirstRow, inLastRow, format); @@ -1834,9 +1830,9 @@ protected internal virtual string GetErrorText(int rowIndex) object objErrorText = this.Properties.GetObject(PropCellErrorText); if (objErrorText != null) { - errorText = (string) objErrorText; + errorText = (string)objErrorText; } - else if (this.DataGridView != null && + else if (this.DataGridView != null && rowIndex != -1 && rowIndex != this.DataGridView.NewRowIndex && this.OwningColumn != null && @@ -1870,9 +1866,9 @@ internal object GetFormattedValue(int rowIndex, ref DataGridViewCellStyle cellSt [ SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference") // using ref is OK. ] - protected virtual object GetFormattedValue(object value, - int rowIndex, - ref DataGridViewCellStyle cellStyle, + protected virtual object GetFormattedValue(object value, + int rowIndex, + ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) @@ -1960,7 +1956,7 @@ static internal DataGridViewFreeDimension GetFreeDimensionFromConstraint(Size co { if (constraintSize.Width < 0 || constraintSize.Height < 0) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "constraintSize", constraintSize.ToString())); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(constraintSize), constraintSize)); } if (constraintSize.Width == 0) { @@ -1981,7 +1977,7 @@ static internal DataGridViewFreeDimension GetFreeDimensionFromConstraint(Size co } else { - throw new ArgumentException(string.Format(SR.InvalidArgument, "constraintSize", constraintSize.ToString())); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(constraintSize), constraintSize)); } } } @@ -2017,7 +2013,7 @@ public virtual ContextMenuStrip GetInheritedContextMenuStrip(int rowIndex) { return contextMenuStrip; } - + if (this.owningRow != null) { contextMenuStrip = this.owningRow.GetContextMenuStrip(rowIndex); @@ -2056,7 +2052,7 @@ public virtual DataGridViewElementStates GetInheritedState(int rowIndex) Debug.Assert(this.RowIndex == -1); if (rowIndex != -1) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "rowIndex", rowIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex)); } if (this.owningRow != null) { @@ -2081,7 +2077,7 @@ public virtual DataGridViewElementStates GetInheritedState(int rowIndex) if (this.DataGridView.Rows.SharedRow(rowIndex) != this.owningRow) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "rowIndex", rowIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex)); } DataGridViewElementStates rowEffectiveState = this.DataGridView.Rows.GetRowState(rowIndex); @@ -2200,7 +2196,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && !cellStyle.BackColor.IsEmpty) { inheritedCellStyleTmp.BackColor = cellStyle.BackColor; - } + } else if (rowStyle != null && !rowStyle.BackColor.IsEmpty) { inheritedCellStyleTmp.BackColor = rowStyle.BackColor; @@ -2226,7 +2222,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && !cellStyle.ForeColor.IsEmpty) { inheritedCellStyleTmp.ForeColor = cellStyle.ForeColor; - } + } else if (rowStyle != null && !rowStyle.ForeColor.IsEmpty) { inheritedCellStyleTmp.ForeColor = rowStyle.ForeColor; @@ -2252,7 +2248,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && !cellStyle.SelectionBackColor.IsEmpty) { inheritedCellStyleTmp.SelectionBackColor = cellStyle.SelectionBackColor; - } + } else if (rowStyle != null && !rowStyle.SelectionBackColor.IsEmpty) { inheritedCellStyleTmp.SelectionBackColor = rowStyle.SelectionBackColor; @@ -2278,7 +2274,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && !cellStyle.SelectionForeColor.IsEmpty) { inheritedCellStyleTmp.SelectionForeColor = cellStyle.SelectionForeColor; - } + } else if (rowStyle != null && !rowStyle.SelectionForeColor.IsEmpty) { inheritedCellStyleTmp.SelectionForeColor = rowStyle.SelectionForeColor; @@ -2305,7 +2301,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && cellStyle.Font != null) { inheritedCellStyleTmp.Font = cellStyle.Font; - } + } else if (rowStyle != null && rowStyle.Font != null) { inheritedCellStyleTmp.Font = rowStyle.Font; @@ -2385,12 +2381,12 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && cellStyle.Format.Length != 0) { inheritedCellStyleTmp.Format = cellStyle.Format; - } + } else if (rowStyle != null && rowStyle.Format.Length != 0) { inheritedCellStyleTmp.Format = rowStyle.Format; } - else if (this.DataGridView.RowsDefaultCellStyle.Format.Length != 0 && + else if (this.DataGridView.RowsDefaultCellStyle.Format.Length != 0 && (rowIndex % 2 == 0 || this.DataGridView.AlternatingRowsDefaultCellStyle.Format.Length == 0)) { inheritedCellStyleTmp.Format = this.DataGridView.RowsDefaultCellStyle.Format; @@ -2437,12 +2433,12 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && cellStyle.Alignment != DataGridViewContentAlignment.NotSet) { inheritedCellStyleTmp.AlignmentInternal = cellStyle.Alignment; - } + } else if (rowStyle != null && rowStyle.Alignment != DataGridViewContentAlignment.NotSet) { inheritedCellStyleTmp.AlignmentInternal = rowStyle.Alignment; } - else if (this.DataGridView.RowsDefaultCellStyle.Alignment != DataGridViewContentAlignment.NotSet && + else if (this.DataGridView.RowsDefaultCellStyle.Alignment != DataGridViewContentAlignment.NotSet && (rowIndex % 2 == 0 || this.DataGridView.AlternatingRowsDefaultCellStyle.Alignment == DataGridViewContentAlignment.NotSet)) { inheritedCellStyleTmp.AlignmentInternal = this.DataGridView.RowsDefaultCellStyle.Alignment; @@ -2464,12 +2460,12 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh if (cellStyle != null && cellStyle.WrapMode != DataGridViewTriState.NotSet) { inheritedCellStyleTmp.WrapModeInternal = cellStyle.WrapMode; - } + } else if (rowStyle != null && rowStyle.WrapMode != DataGridViewTriState.NotSet) { inheritedCellStyleTmp.WrapModeInternal = rowStyle.WrapMode; } - else if (this.DataGridView.RowsDefaultCellStyle.WrapMode != DataGridViewTriState.NotSet && + else if (this.DataGridView.RowsDefaultCellStyle.WrapMode != DataGridViewTriState.NotSet && (rowIndex % 2 == 0 || this.DataGridView.AlternatingRowsDefaultCellStyle.WrapMode == DataGridViewTriState.NotSet)) { inheritedCellStyleTmp.WrapModeInternal = this.DataGridView.RowsDefaultCellStyle.WrapMode; @@ -2496,7 +2492,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh { inheritedCellStyleTmp.Tag = rowStyle.Tag; } - else if (this.DataGridView.RowsDefaultCellStyle.Tag != null && + else if (this.DataGridView.RowsDefaultCellStyle.Tag != null && (rowIndex % 2 == 0 || this.DataGridView.AlternatingRowsDefaultCellStyle.Tag == null)) { inheritedCellStyleTmp.Tag = this.DataGridView.RowsDefaultCellStyle.Tag; @@ -2522,7 +2518,7 @@ public virtual DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle inh { inheritedCellStyleTmp.PaddingInternal = rowStyle.Padding; } - else if (this.DataGridView.RowsDefaultCellStyle.Padding != Padding.Empty && + else if (this.DataGridView.RowsDefaultCellStyle.Padding != Padding.Empty && (rowIndex % 2 == 0 || this.DataGridView.AlternatingRowsDefaultCellStyle.Padding == Padding.Empty)) { inheritedCellStyleTmp.PaddingInternal = this.DataGridView.RowsDefaultCellStyle.Padding; @@ -2558,7 +2554,7 @@ internal int GetPreferredHeight(int rowIndex, int width) } DataGridViewCellStyle dataGridViewCellStyle = GetInheritedStyle(null, rowIndex, false); - using( Graphics g = WindowsFormsUtils.CreateMeasurementGraphics()) + using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics()) { return GetPreferredSize(g, dataGridViewCellStyle, rowIndex, new Size(width, 0)).Height; } @@ -2730,23 +2726,20 @@ public virtual void InitializeEditingControl(int rowIndex, object initialFormatt Debug.Assert(dgv.EditingControl.ParentInternal == dgv.EditingPanel); Debug.Assert(dgv.EditingPanel.ParentInternal == dgv); - if (AccessibilityImprovements.Level3) + if ((dgv.ComboBoxControlWasDetached && dgv.EditingControl is DataGridViewComboBoxEditingControl) || + (dgv.TextBoxControlWasDetached && dgv.EditingControl is DataGridViewTextBoxEditingControl)) { - if ((dgv.ComboBoxControlWasDetached && dgv.EditingControl is DataGridViewComboBoxEditingControl) || - (dgv.TextBoxControlWasDetached && dgv.EditingControl is DataGridViewTextBoxEditingControl)) - { - // Recreate control handle is necessary for cases when the same control was detached and then - // reattached to clear accessible hierarchy cache and not announce previous editing cell. - dgv.EditingControl.RecreateHandleCore(); - - dgv.ComboBoxControlWasDetached = false; - dgv.TextBoxControlWasDetached = false; - } + // Recreate control handle is necessary for cases when the same control was detached and then + // reattached to clear accessible hierarchy cache and not announce previous editing cell. + dgv.EditingControl.RecreateHandleCore(); - dgv.EditingControlAccessibleObject.SetParent(AccessibilityObject); - AccessibilityObject.SetDetachableChild(dgv.EditingControl.AccessibilityObject); - AccessibilityObject.RaiseStructureChangedEvent(UnsafeNativeMethods.StructureChangeType.ChildAdded, dgv.EditingControlAccessibleObject.RuntimeId); + dgv.ComboBoxControlWasDetached = false; + dgv.TextBoxControlWasDetached = false; } + + dgv.EditingControlAccessibleObject.SetParent(AccessibilityObject); + AccessibilityObject.SetDetachableChild(dgv.EditingControl.AccessibilityObject); + AccessibilityObject.RaiseStructureChangedEvent(UnsafeNativeMethods.StructureChangeType.ChildAdded, dgv.EditingControlAccessibleObject.RuntimeId); } /// @@ -2841,12 +2834,12 @@ public static int MeasureTextHeight(Graphics graphics, string text, Font font, i if (maxWidth <= 0) { - throw new ArgumentOutOfRangeException(nameof(maxWidth), string.Format(SR.InvalidLowBoundArgument, "maxWidth", (maxWidth).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(maxWidth), string.Format(SR.InvalidLowBoundArgument, "maxWidth", (maxWidth).ToString(CultureInfo.CurrentCulture), 0)); } if (!DataGridViewUtilities.ValidTextFormatFlags(flags)) { - throw new InvalidEnumArgumentException(nameof(flags), (int) flags, typeof(TextFormatFlags)); + throw new InvalidEnumArgumentException(nameof(flags), (int)flags, typeof(TextFormatFlags)); } flags &= textFormatSupportedFlags; @@ -2879,7 +2872,7 @@ public static Size MeasureTextPreferredSize(Graphics graphics, string text, Font if (!DataGridViewUtilities.ValidTextFormatFlags(flags)) { - throw new InvalidEnumArgumentException(nameof(flags), (int) flags, typeof(TextFormatFlags)); + throw new InvalidEnumArgumentException(nameof(flags), (int)flags, typeof(TextFormatFlags)); } if (string.IsNullOrEmpty(text)) @@ -2894,7 +2887,7 @@ public static Size MeasureTextPreferredSize(Graphics graphics, string text, Font } flags &= textFormatSupportedFlags; - float maxWidth = (float) (textOneLineSize.Width * textOneLineSize.Width) / (float) textOneLineSize.Height / maxRatio * 1.1F; + float maxWidth = (float)(textOneLineSize.Width * textOneLineSize.Width) / (float)textOneLineSize.Height / maxRatio * 1.1F; Size textSize; do { @@ -2929,7 +2922,7 @@ public static Size MeasureTextSize(Graphics graphics, string text, Font font, Te if (!DataGridViewUtilities.ValidTextFormatFlags(flags)) { - throw new InvalidEnumArgumentException(nameof(flags), (int) flags, typeof(TextFormatFlags)); + throw new InvalidEnumArgumentException(nameof(flags), (int)flags, typeof(TextFormatFlags)); } flags &= textFormatSupportedFlags; @@ -2945,7 +2938,7 @@ public static int MeasureTextWidth(Graphics graphics, string text, Font font, in { if (maxHeight <= 0) { - throw new ArgumentOutOfRangeException(nameof(maxHeight), string.Format(SR.InvalidLowBoundArgument, "maxHeight", (maxHeight).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(maxHeight), string.Format(SR.InvalidLowBoundArgument, "maxHeight", (maxHeight).ToString(CultureInfo.CurrentCulture), 0)); } Size oneLineSize = DataGridViewCell.MeasureTextSize(graphics, text, font, flags); @@ -2957,7 +2950,7 @@ public static int MeasureTextWidth(Graphics graphics, string text, Font font, in { flags &= textFormatSupportedFlags; int lastFittingWidth = oneLineSize.Width; - float maxWidth = (float) lastFittingWidth * 0.9F; + float maxWidth = (float)lastFittingWidth * 0.9F; Size textSize; do { @@ -3095,7 +3088,7 @@ private void OnCellDataAreaMouseEnterInternal(int rowIndex) Debug.Assert(this.DataGridView.IsCurrentCellInEditMode); return; } - + // get the tool tip string string toolTipText = GetToolTipText(rowIndex); @@ -3545,7 +3538,7 @@ protected virtual void PaintBorder(Graphics graphics, // Using system colors for non-single grid colors for now int y1, y2; - + Pen penControlDark = null, penControlLightLight = null; Pen penBackColor = this.DataGridView.GetCachedPen(cellStyle.BackColor); Pen penGridColor = this.DataGridView.GridPen; @@ -3574,10 +3567,10 @@ protected virtual void PaintBorder(Graphics graphics, dividerWidthColor = SystemColors.ControlDark; break; } - graphics.FillRectangle(this.DataGridView.GetCachedBrush(dividerWidthColor), - this.DataGridView.RightToLeftInternal ? bounds.X : bounds.Right - dividerThickness, - bounds.Y, - dividerThickness, + graphics.FillRectangle(this.DataGridView.GetCachedBrush(dividerWidthColor), + this.DataGridView.RightToLeftInternal ? bounds.X : bounds.Right - dividerThickness, + bounds.Y, + dividerThickness, bounds.Height); if (this.DataGridView.RightToLeftInternal) { @@ -3721,7 +3714,7 @@ protected virtual void PaintBorder(Graphics graphics, case DataGridViewAdvancedCellBorderStyle.OutsetDouble: y1 = bounds.Y + 1; y2 = bounds.Bottom - 1; - if (advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.OutsetPartial || + if (advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.OutsetPartial || advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.None) { y1--; @@ -3737,7 +3730,7 @@ protected virtual void PaintBorder(Graphics graphics, case DataGridViewAdvancedCellBorderStyle.InsetDouble: y1 = bounds.Y + 1; y2 = bounds.Bottom - 1; - if (advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.OutsetPartial || + if (advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.OutsetPartial || advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.None) { y1--; @@ -3765,12 +3758,12 @@ protected virtual void PaintBorder(Graphics graphics, if (advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.OutsetDouble || advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.InsetDouble) { - x1++; + x1++; } if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.Inset || advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.Outset) { - x2--; + x2--; } graphics.DrawLine(penControlDark, x1, bounds.Y, x2, bounds.Y); break; @@ -3781,12 +3774,12 @@ protected virtual void PaintBorder(Graphics graphics, if (advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.OutsetDouble || advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.InsetDouble) { - x1++; + x1++; } if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.Inset || advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.Outset) { - x2--; + x2--; } graphics.DrawLine(penControlLightLight, x1, bounds.Y, x2, bounds.Y); break; @@ -3806,7 +3799,7 @@ protected virtual void PaintBorder(Graphics graphics, if (advancedBorderStyle.Right != DataGridViewAdvancedCellBorderStyle.None /* && advancedBorderStyle.Right != DataGridViewAdvancedCellBorderStyle.OutsetPartial*/) { x2--; - if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.OutsetDouble || + if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.OutsetDouble || advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.InsetDouble) { x2--; @@ -3869,7 +3862,7 @@ protected virtual void PaintBorder(Graphics graphics, case DataGridViewAdvancedCellBorderStyle.Outset: x1 = bounds.X; x2 = bounds.Right - 1; - if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.InsetDouble || + if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.InsetDouble || advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.OutsetDouble) { x2--; @@ -4283,7 +4276,7 @@ internal static bool PaintContentForeground(DataGridViewPaintParts paintParts) protected virtual void PaintErrorIcon(Graphics graphics, Rectangle clipBounds, Rectangle cellValueBounds, string errorText) { if (!string.IsNullOrEmpty(errorText) && - cellValueBounds.Width >= DATAGRIDVIEWCELL_iconMarginWidth*2+iconsWidth && + cellValueBounds.Width >= DATAGRIDVIEWCELL_iconMarginWidth * 2 + iconsWidth && cellValueBounds.Height >= DATAGRIDVIEWCELL_iconMarginHeight * 2 + iconsHeight) { PaintErrorIcon(graphics, ComputeErrorIconBounds(cellValueBounds)); @@ -4329,10 +4322,10 @@ internal static bool PaintFocus(DataGridViewPaintParts paintParts) return (paintParts & DataGridViewPaintParts.Focus) != 0; } - static internal void PaintPadding(Graphics graphics, - Rectangle bounds, - DataGridViewCellStyle cellStyle, - Brush br, + static internal void PaintPadding(Graphics graphics, + Rectangle bounds, + DataGridViewCellStyle cellStyle, + Brush br, bool rightToLeft) { Rectangle rectPadding; @@ -4368,9 +4361,9 @@ internal static bool PaintSelectionBackground(DataGridViewPaintParts paintParts) return (paintParts & DataGridViewPaintParts.SelectionBackground) != 0; } - internal void PaintWork(Graphics graphics, + internal void PaintWork(Graphics graphics, Rectangle clipBounds, - Rectangle cellBounds, + Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, @@ -4393,11 +4386,11 @@ internal void PaintWork(Graphics graphics, } DataGridViewCellPaintingEventArgs dgvcpe = dataGridView.CellPaintingEventArgs; - dgvcpe.SetProperties(graphics, + dgvcpe.SetProperties(graphics, clipBounds, - cellBounds, - rowIndex, - columnIndex, + cellBounds, + rowIndex, + columnIndex, cellState, value, formattedValue, @@ -4411,21 +4404,21 @@ internal void PaintWork(Graphics graphics, return; } - Paint(graphics, - clipBounds, - cellBounds, - rowIndex, + Paint(graphics, + clipBounds, + cellBounds, + rowIndex, cellState, value, formattedValue, - errorText, - cellStyle, + errorText, + cellStyle, advancedBorderStyle, paintParts); } /// - public virtual object ParseFormattedValue(object formattedValue, + public virtual object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter) @@ -4461,7 +4454,7 @@ internal object ParseFormattedValueInternal(Type valueType, this.FormattedValueType, valueTypeConverter == null ? this.ValueTypeConverter : valueTypeConverter /*sourceConverter*/, formattedValueTypeConverter == null ? this.FormattedValueTypeConverter : formattedValueTypeConverter /*targetConverter*/, - cellStyle.FormatProvider, + cellStyle.FormatProvider, cellStyle.NullValue, cellStyle.IsDataSourceNullValueDefault ? Formatter.GetDefaultDataSourceNullValue(valueType) : cellStyle.DataSourceNullValue); } @@ -4476,17 +4469,17 @@ public virtual void PositionEditingControl( Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, - bool singleVerticalBorderAdded, - bool singleHorizontalBorderAdded, - bool isFirstDisplayedColumn, + bool singleVerticalBorderAdded, + bool singleHorizontalBorderAdded, + bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { - Rectangle editingControlBounds = PositionEditingPanel(cellBounds, - cellClip, - cellStyle, - singleVerticalBorderAdded, - singleHorizontalBorderAdded, - isFirstDisplayedColumn, + Rectangle editingControlBounds = PositionEditingPanel(cellBounds, + cellClip, + cellStyle, + singleVerticalBorderAdded, + singleHorizontalBorderAdded, + isFirstDisplayedColumn, isFirstDisplayedRow); if (setLocation) { @@ -4504,12 +4497,12 @@ public virtual void PositionEditingControl( SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters") // singleVerticalBorderAdded/singleHorizontalBorderAdded names are OK ] // Positions the editing panel and returns the normal bounds of the editing control, within the editing panel. - public virtual Rectangle PositionEditingPanel(Rectangle cellBounds, - Rectangle cellClip, - DataGridViewCellStyle cellStyle, - bool singleVerticalBorderAdded, - bool singleHorizontalBorderAdded, - bool isFirstDisplayedColumn, + public virtual Rectangle PositionEditingPanel(Rectangle cellBounds, + Rectangle cellClip, + DataGridViewCellStyle cellStyle, + bool singleVerticalBorderAdded, + bool singleHorizontalBorderAdded, + bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { if (this.DataGridView == null) @@ -4521,9 +4514,9 @@ public virtual Rectangle PositionEditingPanel(Rectangle cellBounds, dgvabsEffective = AdjustCellBorderStyle(this.DataGridView.AdvancedCellBorderStyle, dataGridViewAdvancedBorderStylePlaceholder, - singleVerticalBorderAdded, - singleHorizontalBorderAdded, - isFirstDisplayedColumn, + singleVerticalBorderAdded, + singleHorizontalBorderAdded, + isFirstDisplayedColumn, isFirstDisplayedRow); Rectangle borderAndPaddingWidths = BorderWidths(dgvabsEffective); @@ -4770,20 +4763,6 @@ public override string DefaultAction } } - /// - public override string Help - { - get - { - if (AccessibilityImprovements.Level2) - { - return null; - } - - return this.owner.GetType().Name + "(" + owner.GetType().BaseType.Name + ")"; - } - } - /// public override string Name { @@ -4797,7 +4776,7 @@ public override string Name { string name = string.Format(SR.DataGridView_AccDataGridViewCellName, this.owner.OwningColumn.HeaderText, this.owner.OwningRow.Index); - if (AccessibilityImprovements.Level3 && owner.OwningColumn.SortMode != DataGridViewColumnSortMode.NotSortable) + if (owner.OwningColumn.SortMode != DataGridViewColumnSortMode.NotSortable) { DataGridViewCell dataGridViewCell = this.Owner; DataGridView dataGridView = dataGridViewCell.DataGridView; @@ -4899,7 +4878,7 @@ public override AccessibleStates State state |= AccessibleStates.Selected; } - if (AccessibilityImprovements.Level1 && this.owner.ReadOnly) + if (this.owner.ReadOnly) { state |= AccessibleStates.ReadOnly; } @@ -4943,7 +4922,7 @@ public override string Value object formattedValue = this.owner.FormattedValue; string formattedValueAsString = formattedValue as string; - if (formattedValue == null || (formattedValueAsString != null && string.IsNullOrEmpty(formattedValueAsString))) + if (formattedValue == null || (formattedValueAsString != null && string.IsNullOrEmpty(formattedValueAsString))) { return string.Format(SR.DataGridView_AccNullValue); } @@ -5073,71 +5052,45 @@ internal Rectangle GetAccessibleObjectBounds(AccessibleObject parentAccObject) return Rectangle.Empty; } - // use the accessibility bounds from the parent row acc obj Rectangle rowRect = parentAccObject.Bounds; - Rectangle columnRect; + Rectangle cellRect = rowRect; + Rectangle columnRect = this.owner.DataGridView.RectangleToScreen(this.owner.DataGridView.GetColumnDisplayRectangle(this.owner.ColumnIndex, false /*cutOverflow*/)); - int firstVisibleColumnIndex = this.owner.DataGridView.Columns.ColumnIndexToActualDisplayIndex(this.owner.DataGridView.FirstDisplayedScrollingColumnIndex, DataGridViewElementStates.Visible); - int visibleColumnIndex = this.owner.DataGridView.Columns.ColumnIndexToActualDisplayIndex(this.owner.ColumnIndex, DataGridViewElementStates.Visible); + var cellRight = columnRect.Left + columnRect.Width; + var cellLeft = columnRect.Left; - bool rowHeadersVisible = this.owner.DataGridView.RowHeadersVisible; - if (visibleColumnIndex < firstVisibleColumnIndex) + int rightToLeftRowHeadersWidth = 0; + int leftToRightRowHeadersWidth = 0; + if (this.owner.DataGridView.RowHeadersVisible) { - // Get the bounds for the cell to the RIGHT - columnRect = parentAccObject.GetChild(visibleColumnIndex - + 1 // + 1 for the next cell to the RIGHT - + (rowHeadersVisible ? 1 : 0)).Bounds; // + 1 but only if the row headers are visible - - // From the bounds of the cell to the RIGHT decrement the width of the owning column - if (this.Owner.DataGridView.RightToLeft == RightToLeft.No) + if (this.owner.DataGridView.RightToLeft == RightToLeft.Yes) { - columnRect.X -= this.owner.OwningColumn.Width; + rightToLeftRowHeadersWidth = this.owner.DataGridView.RowHeadersWidth; } else { - columnRect.X = columnRect.Right; + leftToRightRowHeadersWidth = this.owner.DataGridView.RowHeadersWidth; } - columnRect.Width = this.owner.OwningColumn.Width; } - else if (visibleColumnIndex == firstVisibleColumnIndex) - { - columnRect = this.owner.DataGridView.GetColumnDisplayRectangle(this.owner.ColumnIndex, false /*cutOverflow*/); - int negOffset = this.owner.DataGridView.FirstDisplayedScrollingColumnHiddenWidth; - if (negOffset != 0) - { - if (this.owner.DataGridView.RightToLeft == RightToLeft.No) - { - columnRect.X -= negOffset; - } - columnRect.Width += negOffset; - } - columnRect = this.owner.DataGridView.RectangleToScreen(columnRect); - } - else + if (cellLeft < rowRect.Left + leftToRightRowHeadersWidth) { - // Get the bounds for the cell to the LEFT - columnRect = parentAccObject.GetChild(visibleColumnIndex - - 1 // -1 because we want the previous cell to the LEFT - + (rowHeadersVisible ? 1 : 0)).Bounds; // +1 but only if the row headers are visible - - // From the bounds of the cell to the LEFT increment the width of the owning column - if (this.owner.DataGridView.RightToLeft == RightToLeft.No) - { - columnRect.X = columnRect.Right; - } - else - { - columnRect.X -= this.owner.OwningColumn.Width; - } - - columnRect.Width = this.owner.OwningColumn.Width; + cellLeft = rowRect.Left + leftToRightRowHeadersWidth; } + cellRect.X = cellLeft; - rowRect.X = columnRect.X; - rowRect.Width = columnRect.Width; - return rowRect; + if (cellRight > rowRect.Right - rightToLeftRowHeadersWidth) + { + cellRight = rowRect.Right - rightToLeftRowHeadersWidth; + } + + if ((cellRight - cellLeft) >= 0) + cellRect.Width = cellRight - cellLeft; + else + cellRect.Width = 0; + + return cellRect; } private AccessibleObject GetAccessibleObjectParent() @@ -5436,15 +5389,7 @@ private string AutomationId } } - internal override bool IsIAccessibleExSupported() - { - if (AccessibilityImprovements.Level2) - { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; #region IRawElementProviderFragment Implementation @@ -5506,8 +5451,6 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) - { switch (propertyID) { case NativeMethods.UIA_NamePropertyId: @@ -5530,33 +5473,26 @@ internal override object GetPropertyValue(int propertyID) return string.Empty; case NativeMethods.UIA_GridItemContainingGridPropertyId: return Owner.DataGridView.AccessibilityObject; + case NativeMethods.UIA_IsTableItemPatternAvailablePropertyId: + return IsPatternSupported(NativeMethods.UIA_TableItemPatternId); + case NativeMethods.UIA_IsGridItemPatternAvailablePropertyId: + return IsPatternSupported(NativeMethods.UIA_GridItemPatternId); } - } - - if (propertyID == NativeMethods.UIA_IsTableItemPatternAvailablePropertyId) - { - return IsPatternSupported(NativeMethods.UIA_TableItemPatternId); - } - else if (propertyID == NativeMethods.UIA_IsGridItemPatternAvailablePropertyId) - { - return IsPatternSupported(NativeMethods.UIA_GridItemPatternId); - } return base.GetPropertyValue(propertyID); } internal override bool IsPatternSupported(int patternId) { - if (AccessibilityImprovements.Level3 && - (patternId.Equals(NativeMethods.UIA_LegacyIAccessiblePatternId) || - patternId.Equals(NativeMethods.UIA_InvokePatternId) || - patternId.Equals(NativeMethods.UIA_ValuePatternId))) + if (patternId == NativeMethods.UIA_LegacyIAccessiblePatternId || + patternId == NativeMethods.UIA_InvokePatternId || + patternId == NativeMethods.UIA_ValuePatternId) { return true; } if ((patternId == NativeMethods.UIA_TableItemPatternId || - patternId == NativeMethods.UIA_GridItemPatternId) && + patternId == NativeMethods.UIA_GridItemPatternId) && // We don't want to implement patterns for header cells this.owner.ColumnIndex != -1 && this.owner.RowIndex != -1) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCellStyle.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCellStyle.cs index 1636b29a6f2..f3979c45c6e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCellStyle.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCellStyle.cs @@ -418,10 +418,7 @@ public object NullValue ] public Padding Padding { - get - { - return this.Properties.GetPadding(PropPadding); - } + get => Properties.GetPadding(PropPadding, out _); set { if (value.Left < 0 || value.Right < 0 || value.Top < 0 || value.Bottom < 0) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxCell.cs index de837aa14ac..8b966abdd4b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxCell.cs @@ -1884,14 +1884,7 @@ public override int GetChildCount() return 0; } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level1) { - return true; - } - else { - return false; - } - } + internal override bool IsIAccessibleExSupported() => true; internal override int[] RuntimeId { get { @@ -1909,8 +1902,7 @@ internal override object GetPropertyValue(int propertyID) { if (propertyID == NativeMethods.UIA_IsTogglePatternAvailablePropertyId) { return (object)IsPatternSupported(NativeMethods.UIA_TogglePatternId); } - else if (propertyID == NativeMethods.UIA_ControlTypePropertyId && AccessibilityImprovements.Level2) - { + else if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { return NativeMethods.UIA_CheckBoxControlTypeId; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxColumn.cs index 26bf7613a3a..d012ded1394 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewCheckBoxColumn.cs @@ -13,7 +13,7 @@ namespace System.Windows.Forms using System.Globalization; /// - [ToolboxBitmapAttribute(typeof(DataGridViewCheckBoxColumn), "DataGridViewCheckBoxColumn.bmp")] + [ToolboxBitmapAttribute(typeof(DataGridViewCheckBoxColumn), "DataGridViewCheckBoxColumn")] public class DataGridViewCheckBoxColumn : DataGridViewColumn { /// diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumn.cs index c77ecd5a04d..af984d71583 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumn.cs @@ -365,18 +365,19 @@ public int DisplayIndex { if (value == int.MaxValue) { - throw new ArgumentOutOfRangeException(nameof(DisplayIndex), value, string.Format(SR.DataGridViewColumn_DisplayIndexTooLarge, int.MaxValue.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.DataGridViewColumn_DisplayIndexTooLarge, int.MaxValue)); } - if (this.DataGridView != null) + if (DataGridView != null) { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(DisplayIndex), value, string.Format(SR.DataGridViewColumn_DisplayIndexNegative)); + throw new ArgumentOutOfRangeException(nameof(value), value, SR.DataGridViewColumn_DisplayIndexNegative); } if (value >= this.DataGridView.Columns.Count) { - throw new ArgumentOutOfRangeException(nameof(DisplayIndex), value, string.Format(SR.DataGridViewColumn_DisplayIndexExceedsColumnCount)); + throw new ArgumentOutOfRangeException(nameof(value), value, SR.DataGridViewColumn_DisplayIndexExceedsColumnCount); } + // Will throw an error if a visible frozen column is placed inside a non-frozen area or vice-versa. this.DataGridView.OnColumnDisplayIndexChanging(this, value); this.displayIndex = value; @@ -485,11 +486,11 @@ public float FillWeight { if (value <= 0) { - throw new ArgumentOutOfRangeException(nameof(FillWeight), string.Format(SR.InvalidLowBoundArgument, "FillWeight", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgument, nameof(FillWeight), value, 0)); } if (value > (float)ushort.MaxValue) { - throw new ArgumentOutOfRangeException(nameof(FillWeight), string.Format(SR.InvalidHighBoundArgumentEx, "FillWeight", (value).ToString(CultureInfo.CurrentCulture), (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(FillWeight), value, ushort.MaxValue)); } if (this.DataGridView != null) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnCollection.cs index e36bf6226c2..15b2c995093 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnCollection.cs @@ -524,7 +524,7 @@ public int GetColumnCount(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } // cache returned value and reuse it as long as none @@ -655,7 +655,7 @@ public int GetColumnsWidth(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } // cache returned value and reuse it as long as none @@ -703,7 +703,7 @@ public DataGridViewColumn GetFirstColumn(DataGridViewElementStates includeFilter if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if (this.itemsSorted == null) @@ -738,12 +738,12 @@ public DataGridViewColumn GetFirstColumn(DataGridViewElementStates includeFilter if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } if (this.itemsSorted == null) @@ -775,12 +775,12 @@ public DataGridViewColumn GetLastColumn(DataGridViewElementStates includeFilter, if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } if (this.itemsSorted == null) @@ -817,12 +817,12 @@ public DataGridViewColumn GetNextColumn(DataGridViewColumn dataGridViewColumnSta if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } if (this.itemsSorted == null) @@ -889,12 +889,12 @@ public DataGridViewColumn GetPreviousColumn(DataGridViewColumn dataGridViewColum if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } if (this.itemsSorted == null) @@ -1154,18 +1154,18 @@ public virtual void RemoveAt(int index) { if (index < 0 || index >= this.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (this.DataGridView.NoDimensionChangeAllowed) { - throw new InvalidOperationException(string.Format(SR.DataGridView_ForbiddenOperationInEventHandler)); + throw new InvalidOperationException(SR.DataGridView_ForbiddenOperationInEventHandler); } if (this.DataGridView.InDisplayIndexAdjustments) { // We are within columns display indexes adjustments. We do not allow changing the column collection while adjusting display indexes. - throw new InvalidOperationException(string.Format(SR.DataGridView_CannotAlterDisplayIndexWithinAdjustments)); + throw new InvalidOperationException(SR.DataGridView_CannotAlterDisplayIndexWithinAdjustments); } RemoveAtInternal(index, false /*force*/); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnHeaderCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnHeaderCell.cs index 192b9a44e47..a7a941408cb 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnHeaderCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewColumnHeaderCell.cs @@ -1190,8 +1190,7 @@ private bool IsHighlighted() { return this.DataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect && this.DataGridView.CurrentCell != null && this.DataGridView.CurrentCell.Selected && - this.DataGridView.CurrentCell.OwningColumn == this.OwningColumn && - AccessibilityImprovements.Level2; + this.DataGridView.CurrentCell.OwningColumn == this.OwningColumn; } /// @@ -1578,28 +1577,25 @@ internal override bool IsPatternSupported(int patternId) internal override object GetPropertyValue(int propertyId) { - if (AccessibilityImprovements.Level3) - { - switch (propertyId) - { - case NativeMethods.UIA_NamePropertyId: - return this.Name; - case NativeMethods.UIA_ControlTypePropertyId: - return NativeMethods.UIA_HeaderControlTypeId; - case NativeMethods.UIA_IsEnabledPropertyId: - return Owner.DataGridView.Enabled; - case NativeMethods.UIA_HelpTextPropertyId: - return this.Help ?? string.Empty; - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - return (this.State & AccessibleStates.Focusable) == AccessibleStates.Focusable; - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - case NativeMethods.UIA_IsPasswordPropertyId: - return false; - case NativeMethods.UIA_IsOffscreenPropertyId: - return (this.State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; - case NativeMethods.UIA_AccessKeyPropertyId: - return string.Empty; - } + switch (propertyId) + { + case NativeMethods.UIA_NamePropertyId: + return this.Name; + case NativeMethods.UIA_ControlTypePropertyId: + return NativeMethods.UIA_HeaderControlTypeId; + case NativeMethods.UIA_IsEnabledPropertyId: + return Owner.DataGridView.Enabled; + case NativeMethods.UIA_HelpTextPropertyId: + return this.Help ?? string.Empty; + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + return (this.State & AccessibleStates.Focusable) == AccessibleStates.Focusable; + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + case NativeMethods.UIA_IsPasswordPropertyId: + return false; + case NativeMethods.UIA_IsOffscreenPropertyId: + return (this.State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; + case NativeMethods.UIA_AccessKeyPropertyId: + return string.Empty; } return base.GetPropertyValue(propertyId); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxCell.cs index bca796f8908..b236d6e1337 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxCell.cs @@ -103,12 +103,7 @@ public DataGridViewComboBoxCell() /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level2) - { - return new DataGridViewComboBoxCellAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new DataGridViewComboBoxCellAccessibleObject(this); } /// @@ -445,7 +440,7 @@ public virtual int DropDownWidth //CheckNoSharedCell(); if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(DropDownWidth), value, string.Format(SR.DataGridViewComboBoxCell_DropDownWidthOutOfRange, (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(DropDownWidth), value, string.Format(SR.DataGridViewComboBoxCell_DropDownWidthOutOfRange, 1)); } this.Properties.SetInteger(PropComboBoxCellDropDownWidth, (int)value); if (OwnsEditingComboBox(this.RowIndex)) @@ -566,7 +561,7 @@ public virtual int MaxDropDownItems //CheckNoSharedCell(); if (value < 1 || value > 100) { - throw new ArgumentOutOfRangeException(nameof(MaxDropDownItems), value, string.Format(SR.DataGridViewComboBoxCell_MaxDropDownItemsOutOfRange, (1).ToString(CultureInfo.CurrentCulture), (100).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(MaxDropDownItems), value, string.Format(SR.DataGridViewComboBoxCell_MaxDropDownItemsOutOfRange, 1, 100)); } this.Properties.SetInteger(PropComboBoxCellMaxDropDownItems, (int)value); if (OwnsEditingComboBox(this.RowIndex)) @@ -2291,7 +2286,7 @@ private Rectangle PaintPrivate(Graphics g, DataGridViewComboBoxCellRenderer.DrawDropDownButton(g, dropRect, ComboBoxState.Normal); } - if (SystemInformation.HighContrast && AccessibilityImprovements.Level1) + if (SystemInformation.HighContrast) { // In the case of ComboBox style, background is not filled in, // in the case of DrawReadOnlyButton uses theming API to render CP_READONLY COMBOBOX part that renders the background, @@ -2941,7 +2936,7 @@ public virtual object this[int index] { if (index < 0 || index >= this.InnerArray.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } return this.InnerArray[index]; } @@ -2957,7 +2952,7 @@ public virtual object this[int index] if (index < 0 || index >= this.InnerArray.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } this.InnerArray[index] = value; @@ -3054,7 +3049,7 @@ public void Insert(int index, object item) if (index < 0 || index > this.InnerArray.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), nameof(index))); } // If the combo box is sorted, then just treat this like an add @@ -3096,7 +3091,7 @@ public void RemoveAt(int index) if (index < 0 || index >= this.InnerArray.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } this.InnerArray.RemoveAt(index); this.owner.OnItemsCollectionChanged(); @@ -3233,10 +3228,7 @@ public DataGridViewComboBoxCellAccessibleObject(DataGridViewCell owner) : base(o { } - internal override bool IsIAccessibleExSupported() - { - return true; - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxColumn.cs index 6ee62a161cf..046435a7d66 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxColumn.cs @@ -15,7 +15,7 @@ namespace System.Windows.Forms /// [ Designer("System.Windows.Forms.Design.DataGridViewComboBoxColumnDesigner, " + AssemblyRef.SystemDesign), - ToolboxBitmapAttribute(typeof(DataGridViewComboBoxColumn), "DataGridViewComboBoxColumn.bmp") + ToolboxBitmapAttribute(typeof(DataGridViewComboBoxColumn), "DataGridViewComboBoxColumn") ] public class DataGridViewComboBoxColumn : DataGridViewColumn { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxEditingControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxEditingControl.cs index 3487b997d09..5b78eba7914 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxEditingControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewComboBoxEditingControl.cs @@ -9,7 +9,6 @@ namespace System.Windows.Forms using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; - using Security.Permissions; /// [ @@ -31,16 +30,7 @@ public DataGridViewComboBoxEditingControl() : base() /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) - { - return new DataGridViewComboBoxEditingControlAccessibleObject(this); - } - else if (AccessibilityImprovements.Level2) - { - return new DataGridViewEditingControlAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new DataGridViewComboBoxEditingControlAccessibleObject(this); } // IDataGridViewEditingControl interface implementation @@ -188,10 +178,7 @@ protected override void OnSelectedIndexChanged(EventArgs e) /// /// Defines the DataGridView ComboBox EditingControl accessible object. /// - /// - /// This accessible object is only available in AccessibilityImprovements of Level 3. - /// - internal class DataGridViewComboBoxEditingControlAccessibleObject : ComboBox.ComboBoxUiaProvider + internal class DataGridViewComboBoxEditingControlAccessibleObject : ComboBox.ComboBoxAccessibleObject { private DataGridViewComboBoxEditingControl ownerControl; @@ -207,7 +194,6 @@ public DataGridViewComboBoxEditingControlAccessibleObject(DataGridViewComboBoxEd public override AccessibleObject Parent { - [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] get { return _parentAccessibleObject; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewEditingControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewEditingControl.cs index 9b52cb3d75d..a2a32460bc3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewEditingControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewEditingControl.cs @@ -65,73 +65,4 @@ bool RepositionEditingControlOnValueChange /// void PrepareEditingControlForEdit(bool selectAll); } - - /// - /// - /// Implements a custom AccessibleObject that fixes editing control's accessibility ancestor chain. - /// - [System.Runtime.InteropServices.ComVisible(true)] - internal class DataGridViewEditingControlAccessibleObject : Control.ControlAccessibleObject - { - public DataGridViewEditingControlAccessibleObject(Control ownerControl) : base(ownerControl) - { - Debug.Assert(ownerControl is IDataGridViewEditingControl, "ownerControl must implement IDataGridViewEditingControl"); - } - - internal override bool IsIAccessibleExSupported() - { - if (AccessibilityImprovements.Level3) - { - return true; - } - - return base.IsIAccessibleExSupported(); - } - - public override AccessibleObject Parent - { - get - { - return (Owner as IDataGridViewEditingControl)?.EditingControlDataGridView?.CurrentCell?.AccessibilityObject; - } - } - - internal override bool IsPatternSupported(int patternId) - { - if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_ExpandCollapsePatternId) - { - ComboBox ownerComboBoxControl = Owner as ComboBox; - if (ownerComboBoxControl != null) - { - return ownerComboBoxControl.DropDownStyle != ComboBoxStyle.Simple; - } - } - - return base.IsPatternSupported(patternId); - } - - internal override object GetPropertyValue(int propertyID) - { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_IsExpandCollapsePatternAvailablePropertyId) - { - return IsPatternSupported(NativeMethods.UIA_ExpandCollapsePatternId); - } - - return base.GetPropertyValue(propertyID); - } - - internal override UnsafeNativeMethods.ExpandCollapseState ExpandCollapseState - { - get - { - ComboBox ownerComboBoxControl = Owner as ComboBox; - if (ownerComboBoxControl != null) - { - return ownerComboBoxControl.DroppedDown == true ? UnsafeNativeMethods.ExpandCollapseState.Expanded : UnsafeNativeMethods.ExpandCollapseState.Collapsed; - } - - return base.ExpandCollapseState; - } - } - } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewHeaderCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewHeaderCell.cs index 5c3bf329d05..d5e3aff993d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewHeaderCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewHeaderCell.cs @@ -331,11 +331,11 @@ public override DataGridViewElementStates GetInheritedState(int rowIndex) if ((this.DataGridView == null && rowIndex != -1) || (this.DataGridView != null && (rowIndex < 0 || rowIndex >= this.DataGridView.Rows.Count))) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "rowIndex", rowIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex)); } if (this.DataGridView != null && this.DataGridView.Rows.SharedRow(rowIndex) != this.OwningRow) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "rowIndex", rowIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex)); } state |= (this.OwningRow.GetState(rowIndex) & DataGridViewElementStates.Frozen); if (this.OwningRow.GetResizable(rowIndex) == DataGridViewTriState.True || (this.DataGridView != null && this.DataGridView.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing)) @@ -460,7 +460,7 @@ protected override Size GetSize(int rowIndex) } if (this.DataGridView.Rows.SharedRow(rowIndex) != this.OwningRow) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "rowIndex", rowIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex)); } return new Size(this.DataGridView.RowHeadersWidth, this.OwningRow.GetHeight(rowIndex)); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageCell.cs index 70028a05652..a98d268e004 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageCell.cs @@ -105,7 +105,7 @@ static internal Bitmap ErrorBitmap { if (errorBmp == null) { - errorBmp = new Bitmap(typeof(DataGridView), "ImageInError.bmp"); + errorBmp = DpiHelper.GetBitmapFromIcon(typeof(DataGridView), "ImageInError"); } return errorBmp; } @@ -117,7 +117,7 @@ static internal Icon ErrorIcon { if (errorIco == null) { - errorIco = new Icon(typeof(DataGridView), "IconInError.ico"); + errorIco = new Icon(typeof(DataGridView), "IconInError"); } return errorIco; } @@ -1032,18 +1032,13 @@ public override string Value /// public override void DoDefaultAction() { - // do nothing if Level < 3 + DataGridViewImageCell dataGridViewCell = (DataGridViewImageCell)this.Owner; + DataGridView dataGridView = dataGridViewCell.DataGridView; - if (AccessibilityImprovements.Level3) + if (dataGridView != null && dataGridViewCell.RowIndex != -1 && + dataGridViewCell.OwningColumn != null && dataGridViewCell.OwningRow != null) { - DataGridViewImageCell dataGridViewCell = (DataGridViewImageCell)this.Owner; - DataGridView dataGridView = dataGridViewCell.DataGridView; - - if (dataGridView != null && dataGridViewCell.RowIndex != -1 && - dataGridViewCell.OwningColumn != null && dataGridViewCell.OwningRow != null) - { - dataGridView.OnCellContentClickInternal(new DataGridViewCellEventArgs(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex)); - } + dataGridView.OnCellContentClickInternal(new DataGridViewCellEventArgs(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex)); } } @@ -1053,15 +1048,7 @@ public override int GetChildCount() return 0; } - internal override bool IsIAccessibleExSupported() - { - if (AccessibilityImprovements.Level2) - { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { @@ -1070,7 +1057,7 @@ internal override object GetPropertyValue(int propertyID) return NativeMethods.UIA_ImageControlTypeId; } - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_IsInvokePatternAvailablePropertyId) + if (propertyID == NativeMethods.UIA_IsInvokePatternAvailablePropertyId) { return true; } @@ -1080,7 +1067,7 @@ internal override object GetPropertyValue(int propertyID) internal override bool IsPatternSupported(int patternId) { - if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_InvokePatternId) + if (patternId == NativeMethods.UIA_InvokePatternId) { return true; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageColumn.cs index 66bdb33cc60..4389ab1725e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewImageColumn.cs @@ -14,7 +14,7 @@ namespace System.Windows.Forms using System.Globalization; /// - [ToolboxBitmapAttribute(typeof(DataGridViewImageColumn), "DataGridViewImageColumn.bmp")] + [ToolboxBitmapAttribute(typeof(DataGridViewImageColumn), "DataGridViewImageColumn")] public class DataGridViewImageColumn : DataGridViewColumn { private static Type columnType = typeof(DataGridViewImageColumn); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkCell.cs index d13ccb5d258..e0d54e185be 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkCell.cs @@ -61,7 +61,7 @@ public Color ActiveLinkColor { return (Color)this.Properties.GetObject(PropLinkCellActiveLinkColor); } - else if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + else if (SystemInformation.HighContrast) { return this.HighContrastLinkColor; } @@ -104,7 +104,7 @@ internal Color ActiveLinkColorInternal private bool ShouldSerializeActiveLinkColor() { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + if (SystemInformation.HighContrast) { return !this.ActiveLinkColor.Equals(SystemColors.HotTrack); } @@ -194,7 +194,7 @@ public Color LinkColor { return (Color)this.Properties.GetObject(PropLinkCellLinkColor); } - else if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + else if (SystemInformation.HighContrast) { return this.HighContrastLinkColor; } @@ -237,7 +237,7 @@ internal Color LinkColorInternal private bool ShouldSerializeLinkColor() { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + if (SystemInformation.HighContrast) { return !this.LinkColor.Equals(SystemColors.HotTrack); } @@ -398,7 +398,7 @@ public Color VisitedLinkColor { return (Color)this.Properties.GetObject(PropLinkCellVisitedLinkColor); } - else if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + else if (SystemInformation.HighContrast) { return this.Selected ? SystemColors.HighlightText : LinkUtilities.GetVisitedLinkColor(); } @@ -441,7 +441,7 @@ internal Color VisitedLinkColorInternal private bool ShouldSerializeVisitedLinkColor() { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + if (SystemInformation.HighContrast) { return !this.VisitedLinkColor.Equals(SystemColors.HotTrack); } @@ -1207,15 +1207,7 @@ public override int GetChildCount() return 0; } - internal override bool IsIAccessibleExSupported() - { - if (AccessibilityImprovements.Level2) - { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkColumn.cs index 8e2dbb7778b..77a4dbbeb76 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewLinkColumn.cs @@ -12,7 +12,7 @@ namespace System.Windows.Forms using System.Globalization; /// - [ToolboxBitmapAttribute(typeof(DataGridViewLinkColumn), "DataGridViewLinkColumn.bmp")] + [ToolboxBitmapAttribute(typeof(DataGridViewLinkColumn), "DataGridViewLinkColumn")] public class DataGridViewLinkColumn : DataGridViewColumn { private static Type columnType = typeof(DataGridViewLinkColumn); @@ -65,7 +65,7 @@ public Color ActiveLinkColor private bool ShouldSerializeActiveLinkColor() { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + if (SystemInformation.HighContrast) { return !this.ActiveLinkColor.Equals(SystemColors.HotTrack); } @@ -175,7 +175,7 @@ public Color LinkColor private bool ShouldSerializeLinkColor() { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + if (SystemInformation.HighContrast) { return !this.LinkColor.Equals(SystemColors.HotTrack); } @@ -348,7 +348,7 @@ public Color VisitedLinkColor private bool ShouldSerializeVisitedLinkColor() { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level2) + if (SystemInformation.HighContrast) { return !this.VisitedLinkColor.Equals(SystemColors.HotTrack); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewMethods.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewMethods.cs index a3aea550e95..841f6b3c026 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewMethods.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewMethods.cs @@ -57,10 +57,7 @@ protected virtual void AccessibilityNotifyCurrentCellChanged(Point cellAddress) { this.AccessibilityNotifyClients(AccessibleEvents.Focus, objectID, childID); - if (AccessibilityImprovements.Level3) - { - CurrentCell?.AccessibilityObject.SetFocus(); - } + CurrentCell?.AccessibilityObject.SetFocus(); } this.AccessibilityNotifyClients(AccessibleEvents.Selection, objectID, childID); } @@ -325,9 +322,9 @@ private bool AdjustExpandingColumn(DataGridViewColumn dataGridViewColumn, int ro this.noAutoSizeCount++; DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); int preferredThickness = dataGridViewRow.Cells[dataGridViewColumn.Index].GetPreferredWidth(rowIndex, dataGridViewRow.GetHeight(rowIndex)); - if (preferredThickness > DataGridViewBand.maxBandThickness) + if (preferredThickness > DataGridViewBand.MaxBandThickness) { - preferredThickness = DataGridViewBand.maxBandThickness; + preferredThickness = DataGridViewBand.MaxBandThickness; } if (dataGridViewColumn.Width < preferredThickness) { @@ -415,9 +412,9 @@ private int AdjustExpandingRow(int rowIndex, int columnIndex, bool fixedWidth) preferredThickness = height; } Debug.Assert(preferredThickness >= minimumHeight); - if (preferredThickness > DataGridViewBand.maxBandThickness) + if (preferredThickness > DataGridViewBand.MaxBandThickness) { - preferredThickness = DataGridViewBand.maxBandThickness; + preferredThickness = DataGridViewBand.MaxBandThickness; } if (height != preferredThickness) { @@ -1883,9 +1880,9 @@ private bool AutoResizeColumnInternal(int columnIndex, DataGridViewAutoSizeColum { preferredColumnWidth = dataGridViewColumn.MinimumThickness; } - if (preferredColumnWidth > DataGridViewBand.maxBandThickness) + if (preferredColumnWidth > DataGridViewBand.MaxBandThickness) { - preferredColumnWidth = DataGridViewBand.maxBandThickness; + preferredColumnWidth = DataGridViewBand.MaxBandThickness; } if (preferredColumnWidth != dataGridViewColumn.Thickness) { @@ -2315,9 +2312,9 @@ private void AutoResizeRowInternal(int rowIndex, DataGridViewAutoSizeRowMode aut { preferredThickness = minimumHeight; } - if (preferredThickness > DataGridViewBand.maxBandThickness) + if (preferredThickness > DataGridViewBand.MaxBandThickness) { - preferredThickness = DataGridViewBand.maxBandThickness; + preferredThickness = DataGridViewBand.MaxBandThickness; } if (height != preferredThickness) { @@ -2561,7 +2558,7 @@ private Rectangle GetResizeClipRectangle(int columnIndex) { clip.X = this.layout.Data.X - this.mouseBarOffset - 1; clip.Width = leftEdge - this.Columns[columnIndex].MinimumThickness - this.layout.Data.X + 3; - int overflowWidth = leftEdge - this.mouseBarOffset - clip.Left - DataGridViewBand.maxBandThickness + 1; + int overflowWidth = leftEdge - this.mouseBarOffset - clip.Left - DataGridViewBand.MaxBandThickness + 1; if (overflowWidth > 0) { clip.X += overflowWidth; @@ -2572,7 +2569,7 @@ private Rectangle GetResizeClipRectangle(int columnIndex) { clip.X = leftEdge + this.Columns[columnIndex].MinimumThickness - this.mouseBarOffset - 1; clip.Width = this.layout.Data.Right - leftEdge - 1; - int overflowWidth = clip.Right + this.mouseBarOffset - leftEdge - DataGridViewBand.maxBandThickness; + int overflowWidth = clip.Right + this.mouseBarOffset - leftEdge - DataGridViewBand.MaxBandThickness; if (overflowWidth > 0) { clip.Width -= overflowWidth; @@ -3454,8 +3451,7 @@ public void ClearSelection() // Force repainting of the current collumn's header cell to remove highlighting if (this.ptCurrentCell.X != -1 && - this.SelectionMode == DataGridViewSelectionMode.FullRowSelect && - AccessibilityImprovements.Level2) + this.SelectionMode == DataGridViewSelectionMode.FullRowSelect) { InvalidateCellPrivate(this.ptCurrentCell.X, -1); } @@ -6139,7 +6135,7 @@ private void EndColumnResize(int x) { int proposed = this.Columns[this.trackColumn].Thickness + delta; Debug.Assert(proposed >= this.Columns[this.trackColumn].MinimumThickness); - Debug.Assert(proposed <= DataGridViewBand.maxBandThickness); + Debug.Assert(proposed <= DataGridViewBand.MaxBandThickness); this.Columns[this.trackColumn].Thickness = proposed; } } @@ -6424,7 +6420,7 @@ private void FlushDisplayedChanged() else { Rectangle rectScreen = Screen.FromControl(this).WorkingArea; - int maxDisplayedRows = (int) (rectScreen.Height / DataGridViewBand.minBandThickness); + int maxDisplayedRows = (int) (rectScreen.Height / DataGridViewBand.MinBandThickness); // Make sure all displayed scrolling rows have the Displayed state. int rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; @@ -6891,7 +6887,7 @@ public int GetCellCount(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } int cellCount = 0; @@ -10908,7 +10904,7 @@ internal void OnAddingColumn(DataGridViewColumn dataGridViewColumn) float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) + dataGridViewColumn.FillWeight; if (weightSum > (float)ushort.MaxValue) { - throw new InvalidOperationException(string.Format(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); + throw new InvalidOperationException(string.Format(SR.DataGridView_WeightSumCannotExceedLongMaxValue, ushort.MaxValue)); } // check for correctness of frozen state - throws exception if state is incorrect. @@ -11030,7 +11026,7 @@ internal void OnAddingColumns(DataGridViewColumn[] dataGridViewColumns) weightSum += dataGridViewColumn.FillWeight; if (weightSum > (float)ushort.MaxValue) { - throw new InvalidOperationException(string.Format(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); + throw new InvalidOperationException(string.Format(SR.DataGridView_WeightSumCannotExceedLongMaxValue, ushort.MaxValue)); } } @@ -11397,9 +11393,9 @@ protected virtual void OnAutoSizeColumnsModeChanged(DataGridViewAutoSizeColumnsM DataGridViewAutoSizeColumnMode[] previousModes = e.PreviousModes; if (previousModes == null) { - throw new ArgumentNullException("e.PreviousModes"); + throw new ArgumentNullException(nameof(e.PreviousModes)); } - if (previousModes.Length != this.Columns.Count) + if (previousModes.Length != Columns.Count) { throw new ArgumentException(string.Format(SR.DataGridView_PreviousModesHasWrongLength)); } @@ -13968,7 +13964,7 @@ internal void OnColumnFillWeightChanging(DataGridViewColumn dataGridViewColumn, float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) - dataGridViewColumn.FillWeight + fillWeight; if (weightSum > (float)ushort.MaxValue) { - throw new InvalidOperationException(string.Format(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); + throw new InvalidOperationException(string.Format(SR.DataGridView_WeightSumCannotExceedLongMaxValue, ushort.MaxValue)); } } @@ -15512,7 +15508,7 @@ protected override void OnEnter(EventArgs e) OnCellEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); // Force repainting of the current collumn's header cell to highlight it - if (this.SelectionMode == DataGridViewSelectionMode.FullRowSelect && AccessibilityImprovements.Level2) + if (this.SelectionMode == DataGridViewSelectionMode.FullRowSelect) { InvalidateCellPrivate(this.ptCurrentCell.X, -1); } @@ -16197,7 +16193,7 @@ protected override void OnKeyUp(KeyEventArgs e) return; } - if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackKeyboardColResize] && (e.KeyData & Keys.Alt) != Keys.Alt && AccessibilityImprovements.Level2) + if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackKeyboardColResize] && (e.KeyData & Keys.Alt) != Keys.Alt) { this.EndColumnResize(this.currentColSplitBar); this.ResetKeyboardTrackingState(); @@ -17153,7 +17149,7 @@ protected override void OnPaint(PaintEventArgs e) [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool IsGridFocusRectangleEnabled() { - return this.ShowFocusCues && this.CurrentCell == null && AccessibilityImprovements.Level2; + return this.ShowFocusCues && this.CurrentCell == null; } // Creates a rectangle by merging row headers, column headers @@ -21922,7 +21918,7 @@ protected bool ProcessF2Key(Keys keyData) /// protected bool ProcessF3Key(Keys keyData) { - if (this.ptCurrentCell.X != -1 && AccessibilityImprovements.Level2) + if (this.ptCurrentCell.X != -1) { DataGridViewColumn dataGridViewColumn = Columns[this.ptCurrentCell.X]; if (dataGridViewColumn != null && CanSort(dataGridViewColumn)) @@ -22234,7 +22230,7 @@ protected bool ProcessInsertKey(Keys keyData) /// protected override bool ProcessKeyEventArgs(ref Message m) { - if (m.Msg == NativeMethods.WM_SYSKEYDOWN || m.Msg == NativeMethods.WM_KEYDOWN) + if (m.Msg == Interop.WindowMessages.WM_SYSKEYDOWN || m.Msg == Interop.WindowMessages.WM_KEYDOWN) { if (this.ptCurrentCell.X != -1) { @@ -22279,7 +22275,7 @@ protected override bool ProcessKeyEventArgs(ref Message m) } } else if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] && - (m.Msg == NativeMethods.WM_SYSCHAR || m.Msg == NativeMethods.WM_CHAR || m.Msg == NativeMethods.WM_IME_CHAR)) + (m.Msg == Interop.WindowMessages.WM_SYSCHAR || m.Msg == Interop.WindowMessages.WM_CHAR || m.Msg == Interop.WindowMessages.WM_IME_CHAR)) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage] = false; if (this.editingControl != null) @@ -22302,7 +22298,7 @@ protected override bool ProcessKeyPreview(ref Message m) // 2. Other special keys do not exist in WM_CHAR message, and character code of WM_CHAR may have overlapped // w/ some of the key code. (Like character code of lowcase "q" is 0x71, it's overlapped w/ Keys.F2). This // may introduce problem when handling them. - if (m.Msg == NativeMethods.WM_CHAR) + if (m.Msg == Interop.WindowMessages.WM_CHAR) { switch (ke.KeyCode) { @@ -22344,7 +22340,7 @@ protected override bool ProcessKeyPreview(ref Message m) } } - if (this.editingControl != null && (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN)) + if (this.editingControl != null && (m.Msg == Interop.WindowMessages.WM_KEYDOWN || m.Msg == Interop.WindowMessages.WM_SYSKEYDOWN)) { this.dataGridViewState2[DATAGRIDVIEWSTATE2_currentCellWantsInputKey] = ((IDataGridViewEditingControl)this.editingControl).EditingControlWantsInputKey(ke.KeyData, dataGridViewWantsInputKey); } @@ -22356,7 +22352,7 @@ protected override bool ProcessKeyPreview(ref Message m) if (dataGridViewWantsInputKey) { - if (m.Msg == NativeMethods.WM_KEYDOWN || m.Msg == NativeMethods.WM_SYSKEYDOWN) + if (m.Msg == Interop.WindowMessages.WM_KEYDOWN || m.Msg == Interop.WindowMessages.WM_SYSKEYDOWN) { if (ProcessDataGridViewKey(ke)) { @@ -22378,7 +22374,7 @@ protected override bool ProcessKeyPreview(ref Message m) private bool? ProcessColumnResize(Keys keyData, int step) { - if (AccessibilityImprovements.Level2 && (keyData & Keys.Alt) == Keys.Alt && this.AllowUserToResizeColumns && this.ptCurrentCell.X != -1) + if ((keyData & Keys.Alt) == Keys.Alt && this.AllowUserToResizeColumns && this.ptCurrentCell.X != -1) { if (this.currentColSplitBar == -1) { @@ -26854,8 +26850,7 @@ protected virtual bool SetCurrentCellAddressCore(int columnIndex, // Force repainting of the current and previous collumns` header cells to update highlighting if (oldCurrentCellX != columnIndex && - this.SelectionMode == DataGridViewSelectionMode.FullRowSelect && - AccessibilityImprovements.Level2) + this.SelectionMode == DataGridViewSelectionMode.FullRowSelect) { if (oldCurrentCellX >= 0) { @@ -28227,11 +28222,8 @@ private void SortInternal(IComparer comparer, DataGridViewColumn dataGridViewCol ResetUIState(false /*useRowShortcut*/, false /*computeVisibleRows*/); OnSorted(EventArgs.Empty); - if (AccessibilityImprovements.Level3) - { - // RS4 narrator does not catch this event even though event is indeed raised. - AccessibilityNotifyClients(AccessibleEvents.Reorder, NativeMethods.OBJID_CLIENT, 0); - } + // RS4 narrator does not catch this event even though event is indeed raised. + AccessibilityNotifyClients(AccessibleEvents.Reorder, NativeMethods.OBJID_CLIENT, 0); } internal void SwapSortedRows(int rowIndex1, int rowIndex2) @@ -29847,11 +29839,11 @@ protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: WmGetDlgCode(ref m); return; - case NativeMethods.WM_LBUTTONDBLCLK: - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDOWN: // If the OnEnter procedure is called, it's because of a mouse down event, and not a TAB key. this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] = true; try @@ -29863,7 +29855,7 @@ protected override void WndProc(ref Message m) this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] = false; } return; - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: if (WmNotify(ref m)) { // we are done - skip default handling @@ -29871,8 +29863,8 @@ protected override void WndProc(ref Message m) } break; - case NativeMethods.WM_IME_STARTCOMPOSITION: - case NativeMethods.WM_IME_COMPOSITION: + case Interop.WindowMessages.WM_IME_STARTCOMPOSITION: + case Interop.WindowMessages.WM_IME_COMPOSITION: if (this.editingControl != null) { // Make sure that the first character is forwarded to the editing control. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRow.cs index dcc1ca2f132..edacae33684 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRow.cs @@ -1355,7 +1355,7 @@ public virtual DataGridViewElementStates GetState(int rowIndex) { if (rowIndex != Index) { - throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(rowIndex), rowIndex), nameof(rowIndex)); } return base.State; } @@ -1796,55 +1796,42 @@ public override Rectangle Bounds { get { - Rectangle rowRect; if (owner == null) { throw new InvalidOperationException(SR.DataGridViewRowAccessibleObject_OwnerNotSet); } - if (owner.Index < owner.DataGridView.FirstDisplayedScrollingRowIndex) + Rectangle rowRect = owner.DataGridView.RectangleToScreen(owner.DataGridView.GetRowDisplayRectangle(owner.Index, false /*cutOverflow*/)); + + int horizontalScrollBarHeight = 0; + if (this.owner.DataGridView.HorizontalScrollBarVisible) { - // the row is scrolled off the DataGridView - // get the Accessible bounds for the following visible row - int visibleRowIndex = owner.DataGridView.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, owner.Index); - rowRect = ParentPrivate.GetChild(visibleRowIndex - + 1 // + 1 because the first acc obj in the DataGridView is the top row header - + 1).Bounds; // + 1 because we want to get the bounds for the next visible row + horizontalScrollBarHeight = this.owner.DataGridView.HorizontalScrollBarHeight; + } - rowRect.Y -= owner.Height; - rowRect.Height = owner.Height; + Rectangle dataGridViewRect = ParentPrivate.Bounds; - } - else if (owner.Index >= owner.DataGridView.FirstDisplayedScrollingRowIndex && - owner.Index < owner.DataGridView.FirstDisplayedScrollingRowIndex + owner.DataGridView.DisplayedRowCount(true /*includePartialRow*/)) + int columnHeadersHeight = 0; + if (this.owner.DataGridView.ColumnHeadersVisible) { - rowRect = owner.DataGridView.GetRowDisplayRectangle(owner.Index, false /*cutOverflow*/); - rowRect = owner.DataGridView.RectangleToScreen(rowRect); + columnHeadersHeight = this.owner.DataGridView.ColumnHeadersHeight; } - else + + int rowRectBottom = rowRect.Bottom; + if ((dataGridViewRect.Bottom - horizontalScrollBarHeight) < rowRectBottom) { - // the row is scrolled off the DataGridView - // use the Accessible bounds for the previous visible row - int visibleRowIndex = owner.DataGridView.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, owner.Index); - - // This is a tricky scenario - // If Visible of Row 0 is false, then visibleRowIndex is not the previous visible row. - // It turns out to be the current row, this will cause a stack overflow. - // We have to prevent this. - if (!owner.DataGridView.Rows[0].Visible) - { - visibleRowIndex--; - } + rowRectBottom = dataGridViewRect.Bottom - owner.DataGridView.BorderWidth - horizontalScrollBarHeight; + } - // we don't have to decrement the visible row index if the first acc obj in the data grid view is the top column header - if (!owner.DataGridView.ColumnHeadersVisible) - { - visibleRowIndex--; - } + - rowRect = ParentPrivate.GetChild(visibleRowIndex).Bounds; - rowRect.Y += rowRect.Height; - rowRect.Height = owner.Height; + if ((dataGridViewRect.Top + columnHeadersHeight) > rowRect.Top) + { + rowRect.Height = 0; + } + else + { + rowRect.Height = rowRectBottom - rowRect.Top; } return rowRect; @@ -1895,7 +1882,7 @@ internal override int[] RuntimeId { get { - if (AccessibilityImprovements.Level3 && runtimeId == null) + if (runtimeId == null) { runtimeId = new int[] { @@ -2241,24 +2228,22 @@ internal override bool IsPatternSupported(int patternId) internal override object GetPropertyValue(int propertyId) { - if (AccessibilityImprovements.Level3) - { - switch (propertyId) - { - case NativeMethods.UIA_NamePropertyId: - return Name; - case NativeMethods.UIA_IsEnabledPropertyId: - return Owner.DataGridView.Enabled; - case NativeMethods.UIA_HelpTextPropertyId: - return Help ?? string.Empty; - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - case NativeMethods.UIA_IsPasswordPropertyId: - case NativeMethods.UIA_IsOffscreenPropertyId: - return false; - case NativeMethods.UIA_AccessKeyPropertyId: - return string.Empty; - } + switch (propertyId) + { + case NativeMethods.UIA_NamePropertyId: + return Name; + case NativeMethods.UIA_IsEnabledPropertyId: + return Owner.DataGridView.Enabled; + case NativeMethods.UIA_HelpTextPropertyId: + return Help ?? string.Empty; + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + case NativeMethods.UIA_IsPasswordPropertyId: + return false; + case NativeMethods.UIA_IsOffscreenPropertyId: + return (State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; + case NativeMethods.UIA_AccessKeyPropertyId: + return string.Empty; } return base.GetPropertyValue(propertyId); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowCollection.cs index e3638e699c9..9b58c7c73d3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowCollection.cs @@ -1025,7 +1025,7 @@ public int GetFirstRow(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } #if DEBUG Debug.Assert(this.cachedRowCountsAccessAllowed); @@ -1071,12 +1071,12 @@ public int GetFirstRow(DataGridViewElementStates includeFilter, if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } #if DEBUG Debug.Assert(this.cachedRowCountsAccessAllowed); @@ -1117,7 +1117,7 @@ public int GetLastRow(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } #if DEBUG Debug.Assert(this.cachedRowCountsAccessAllowed); @@ -1173,11 +1173,11 @@ public int GetNextRow(int indexStart, DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if (indexStart < -1) { - throw new ArgumentOutOfRangeException(nameof(indexStart), string.Format(SR.InvalidLowBoundArgumentEx, "indexStart", (indexStart).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(indexStart), indexStart, string.Format(SR.InvalidLowBoundArgumentEx, nameof(indexStart), indexStart, -1)); } int index = indexStart + 1; @@ -1200,16 +1200,16 @@ public int GetNextRow(int indexStart, if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } if (indexStart < -1) { - throw new ArgumentOutOfRangeException(nameof(indexStart), string.Format(SR.InvalidLowBoundArgumentEx, "indexStart", (indexStart).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(indexStart), indexStart, string.Format(SR.InvalidLowBoundArgumentEx, nameof(indexStart), indexStart, -1)); } int index = indexStart + 1; @@ -1226,11 +1226,11 @@ public int GetPreviousRow(int indexStart, DataGridViewElementStates includeFilte if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if (indexStart > this.items.Count) { - throw new ArgumentOutOfRangeException(nameof(indexStart), string.Format(SR.InvalidHighBoundArgumentEx, "indexStart", (indexStart).ToString(CultureInfo.CurrentCulture), (this.items.Count).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(indexStart), indexStart, string.Format(SR.InvalidHighBoundArgumentEx, nameof(indexStart), indexStart, items.Count)); } int index = indexStart - 1; @@ -1253,16 +1253,16 @@ public int GetPreviousRow(int indexStart, if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } if ((excludeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "excludeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(excludeFilter))); } if (indexStart > this.items.Count) { - throw new ArgumentOutOfRangeException(nameof(indexStart), string.Format(SR.InvalidHighBoundArgumentEx, "indexStart", (indexStart).ToString(CultureInfo.CurrentCulture), (this.items.Count).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(indexStart), indexStart, string.Format(SR.InvalidHighBoundArgumentEx, nameof(indexStart), indexStart, items.Count)); } int index = indexStart - 1; @@ -1279,7 +1279,7 @@ public int GetRowCount(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } #if DEBUG Debug.Assert(this.cachedRowCountsAccessAllowed); @@ -1355,7 +1355,7 @@ public int GetRowsHeight(DataGridViewElementStates includeFilter) if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { - throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); + throw new ArgumentException(string.Format(SR.DataGridView_InvalidDataGridViewElementStateCombination, nameof(includeFilter))); } #if DEBUG Debug.Assert(this.cachedRowHeightsAccessAllowed); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeaderCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeaderCell.cs index 6a67125689f..511b91281f9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeaderCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeaderCell.cs @@ -25,7 +25,7 @@ public class DataGridViewRowHeaderCell : DataGridViewHeaderCell private static readonly VisualStyleElement HeaderElement = VisualStyleElement.Header.Item.Normal; // ColorMap used to map the black color of the resource bitmaps to the fore color in use in the row header cell - private static ColorMap[] colorMap = new ColorMap[] {new ColorMap()}; + private static ColorMap[] colorMap = new ColorMap[] { new ColorMap() }; private static Bitmap rightArrowBmp = null; private static Bitmap leftArrowBmp = null; @@ -44,33 +44,19 @@ public class DataGridViewRowHeaderCell : DataGridViewHeaderCell private const byte DATAGRIDVIEWROWHEADERCELL_horizontalTextMarginLeft = 1; private const byte DATAGRIDVIEWROWHEADERCELL_horizontalTextMarginRight = 2; private const byte DATAGRIDVIEWROWHEADERCELL_verticalTextMargin = 1; - + /// public DataGridViewRowHeaderCell() { } - /* Unused for now. - private static Bitmap ErrorBitmap - { - get - { - if (errorBmp == null) - { - errorBmp = GetBitmap("DataGridViewRow.error.bmp"); - } - return errorBmp; - } - } - */ - private static Bitmap LeftArrowBitmap { get { if (leftArrowBmp == null) { - leftArrowBmp = GetBitmapFromIcon("DataGridViewRow.left.ico"); + leftArrowBmp = GetBitmapFromIcon("DataGridViewRow.left"); } return leftArrowBmp; } @@ -82,7 +68,7 @@ private static Bitmap LeftArrowStarBitmap { if (leftArrowStarBmp == null) { - leftArrowStarBmp = GetBitmapFromIcon("DataGridViewRow.leftstar.ico"); + leftArrowStarBmp = GetBitmapFromIcon("DataGridViewRow.leftstar"); } return leftArrowStarBmp; } @@ -94,7 +80,7 @@ private static Bitmap PencilLTRBitmap { if (pencilLTRBmp == null) { - pencilLTRBmp = GetBitmapFromIcon("DataGridViewRow.pencil_ltr.ico"); + pencilLTRBmp = GetBitmapFromIcon("DataGridViewRow.pencil_ltr"); } return pencilLTRBmp; } @@ -106,7 +92,7 @@ private static Bitmap PencilRTLBitmap { if (pencilRTLBmp == null) { - pencilRTLBmp = GetBitmapFromIcon("DataGridViewRow.pencil_rtl.ico"); + pencilRTLBmp = GetBitmapFromIcon("DataGridViewRow.pencil_rtl"); } return pencilRTLBmp; } @@ -118,7 +104,7 @@ private static Bitmap RightArrowBitmap { if (rightArrowBmp == null) { - rightArrowBmp = GetBitmapFromIcon("DataGridViewRow.right.ico"); + rightArrowBmp = GetBitmapFromIcon("DataGridViewRow.right"); } return rightArrowBmp; } @@ -130,7 +116,7 @@ private static Bitmap RightArrowStarBitmap { if (rightArrowStarBmp == null) { - rightArrowStarBmp = GetBitmapFromIcon("DataGridViewRow.rightstar.ico"); + rightArrowStarBmp = GetBitmapFromIcon("DataGridViewRow.rightstar"); } return rightArrowStarBmp; } @@ -142,7 +128,7 @@ private static Bitmap StarBitmap { if (starBmp == null) { - starBmp = GetBitmapFromIcon("DataGridViewRow.star.ico"); + starBmp = GetBitmapFromIcon("DataGridViewRow.star"); } return starBmp; } @@ -162,7 +148,7 @@ public override object Clone() { // - dataGridViewCell = (DataGridViewRowHeaderCell) System.Activator.CreateInstance(thisType); + dataGridViewCell = (DataGridViewRowHeaderCell)System.Activator.CreateInstance(thisType); } base.CloneInternal(dataGridViewCell); dataGridViewCell.Value = this.Value; @@ -185,12 +171,12 @@ private static Bitmap GetArrowStarBitmap(bool rightToLeft) return rightToLeft ? DataGridViewRowHeaderCell.LeftArrowStarBitmap : DataGridViewRowHeaderCell.RightArrowStarBitmap; } - - + + private static Bitmap GetBitmapFromIcon(string iconName) { Size desiredSize = new Size(iconsWidth, iconsHeight); - Icon icon = new Icon(BitmapSelector.GetResourceStream(typeof(DataGridViewRowHeaderCell), iconName), desiredSize); + Icon icon = new Icon(new Icon(typeof(DataGridViewHeaderCell), iconName), desiredSize); Bitmap b = icon.ToBitmap(); icon.Dispose(); @@ -280,13 +266,13 @@ protected override object GetClipboardContent(int rowIndex, { if (!inLastRow) { - sb.Append((char) Keys.Return); - sb.Append((char) Keys.LineFeed); + sb.Append((char)Keys.Return); + sb.Append((char)Keys.LineFeed); } } else { - sb.Append(csv ? ',' : (char) Keys.Tab); + sb.Append(csv ? ',' : (char)Keys.Tab); } return sb.ToString(); } @@ -461,7 +447,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && !cellStyle.BackColor.IsEmpty) { inheritedCellStyleTmp.BackColor = cellStyle.BackColor; - } + } else if (!rowHeadersStyle.BackColor.IsEmpty) { inheritedCellStyleTmp.BackColor = rowHeadersStyle.BackColor; @@ -474,7 +460,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && !cellStyle.ForeColor.IsEmpty) { inheritedCellStyleTmp.ForeColor = cellStyle.ForeColor; - } + } else if (!rowHeadersStyle.ForeColor.IsEmpty) { inheritedCellStyleTmp.ForeColor = rowHeadersStyle.ForeColor; @@ -487,7 +473,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && !cellStyle.SelectionBackColor.IsEmpty) { inheritedCellStyleTmp.SelectionBackColor = cellStyle.SelectionBackColor; - } + } else if (!rowHeadersStyle.SelectionBackColor.IsEmpty) { inheritedCellStyleTmp.SelectionBackColor = rowHeadersStyle.SelectionBackColor; @@ -500,7 +486,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && !cellStyle.SelectionForeColor.IsEmpty) { inheritedCellStyleTmp.SelectionForeColor = cellStyle.SelectionForeColor; - } + } else if (!rowHeadersStyle.SelectionForeColor.IsEmpty) { inheritedCellStyleTmp.SelectionForeColor = rowHeadersStyle.SelectionForeColor; @@ -514,7 +500,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && cellStyle.Font != null) { inheritedCellStyleTmp.Font = cellStyle.Font; - } + } else if (rowHeadersStyle.Font != null) { inheritedCellStyleTmp.Font = rowHeadersStyle.Font; @@ -553,7 +539,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && cellStyle.Format.Length != 0) { inheritedCellStyleTmp.Format = cellStyle.Format; - } + } else if (rowHeadersStyle.Format.Length != 0) { inheritedCellStyleTmp.Format = rowHeadersStyle.Format; @@ -579,7 +565,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && cellStyle.Alignment != DataGridViewContentAlignment.NotSet) { inheritedCellStyleTmp.AlignmentInternal = cellStyle.Alignment; - } + } else if (rowHeadersStyle.Alignment != DataGridViewContentAlignment.NotSet) { inheritedCellStyleTmp.AlignmentInternal = rowHeadersStyle.Alignment; @@ -593,7 +579,7 @@ public override DataGridViewCellStyle GetInheritedStyle(DataGridViewCellStyle in if (cellStyle != null && cellStyle.WrapMode != DataGridViewTriState.NotSet) { inheritedCellStyleTmp.WrapModeInternal = cellStyle.WrapMode; - } + } else if (rowHeadersStyle.WrapMode != DataGridViewTriState.NotSet) { inheritedCellStyleTmp.WrapModeInternal = rowHeadersStyle.WrapMode; @@ -681,13 +667,13 @@ protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyl val = null; } return DataGridViewUtilities.GetPreferredRowHeaderSize(graphics, - (string) val, - cellStyle, - borderAndPaddingWidths, + (string)val, + cellStyle, + borderAndPaddingWidths, borderAndPaddingHeights, this.DataGridView.ShowRowErrors, true /*showGlyph*/, - constraintSize, + constraintSize, flags); } @@ -828,15 +814,17 @@ private Rectangle PaintPrivate(Graphics graphics, } } // Flip the column header background - using (Bitmap bmFlipXPThemes = new Bitmap(backgroundBounds.Height, backgroundBounds.Width)) { - using (Graphics gFlip = Graphics.FromImage(bmFlipXPThemes)) { - DataGridViewRowHeaderCellRenderer.DrawHeader(gFlip, new Rectangle(0, 0, backgroundBounds.Height, backgroundBounds.Width), state); - bmFlipXPThemes.RotateFlip(this.DataGridView.RightToLeftInternal ? RotateFlipType.Rotate90FlipNone : RotateFlipType.Rotate270FlipY); - - graphics.DrawImage(bmFlipXPThemes, - backgroundBounds, - new Rectangle(0, 0, backgroundBounds.Width, backgroundBounds.Height), - GraphicsUnit.Pixel); + using (Bitmap bmFlipXPThemes = new Bitmap(backgroundBounds.Height, backgroundBounds.Width)) + { + using (Graphics gFlip = Graphics.FromImage(bmFlipXPThemes)) + { + DataGridViewRowHeaderCellRenderer.DrawHeader(gFlip, new Rectangle(0, 0, backgroundBounds.Height, backgroundBounds.Width), state); + bmFlipXPThemes.RotateFlip(this.DataGridView.RightToLeftInternal ? RotateFlipType.Rotate90FlipNone : RotateFlipType.Rotate270FlipY); + + graphics.DrawImage(bmFlipXPThemes, + backgroundBounds, + new Rectangle(0, 0, backgroundBounds.Width, backgroundBounds.Height), + GraphicsUnit.Pixel); } } } @@ -891,9 +879,9 @@ private Rectangle PaintPrivate(Graphics graphics, if (!string.IsNullOrEmpty(formattedString)) { // There is text to display - if (valBounds.Width >= iconsWidth + + if (valBounds.Width >= iconsWidth + 2 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth && - valBounds.Height >= iconsHeight + + valBounds.Height >= iconsHeight + 2 * DATAGRIDVIEWROWHEADERCELL_iconMarginHeight) { if (paint && DataGridViewCell.PaintContentBackground(paintParts)) @@ -1019,7 +1007,7 @@ private Rectangle PaintPrivate(Graphics graphics, } } // Third priority is the row error icon, which may be painted on top of text - if (errorBounds.Width >= 3 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth + + if (errorBounds.Width >= 3 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth + 2 * iconsWidth) { // There is enough horizontal room for the error icon and the glyph @@ -1039,7 +1027,7 @@ private Rectangle PaintPrivate(Graphics graphics, else { // There is no text to display - if (valBounds.Width >= iconsWidth + 2 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth && + if (valBounds.Width >= iconsWidth + 2 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth && valBounds.Height >= iconsHeight + 2 * DATAGRIDVIEWROWHEADERCELL_iconMarginHeight) { if (paint && DataGridViewCell.PaintContentBackground(paintParts)) @@ -1101,7 +1089,7 @@ private Rectangle PaintPrivate(Graphics graphics, } } - if (errorBounds.Width >= 3 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth + + if (errorBounds.Width >= 3 * DATAGRIDVIEWROWHEADERCELL_iconMarginWidth + 2 * iconsWidth) { // There is enough horizontal room for the error icon @@ -1126,10 +1114,10 @@ private Rectangle PaintPrivate(Graphics graphics, private void PaintIcon(Graphics g, Bitmap bmp, Rectangle bounds, Color foreColor) { - Rectangle bmpRect = new Rectangle(this.DataGridView.RightToLeftInternal ? + Rectangle bmpRect = new Rectangle(this.DataGridView.RightToLeftInternal ? bounds.Right - DATAGRIDVIEWROWHEADERCELL_iconMarginWidth - iconsWidth : bounds.Left + DATAGRIDVIEWROWHEADERCELL_iconMarginWidth, - bounds.Y + (bounds.Height - iconsHeight)/2, + bounds.Y + (bounds.Height - iconsHeight) / 2, iconsWidth, iconsHeight); colorMap[0].NewColor = foreColor; @@ -1145,7 +1133,7 @@ private void PaintIcon(Graphics g, Bitmap bmp, Rectangle bounds, Color foreColor protected override bool SetValue(int rowIndex, object value) { object originalValue = GetValue(rowIndex); - if (value != null || this.Properties.ContainsObject(PropCellValue)) + if (value != null || this.Properties.ContainsObject(PropCellValue)) { this.Properties.SetObject(PropCellValue, value); } @@ -1213,8 +1201,14 @@ public override Rectangle Bounds // use the parent row acc obj bounds Rectangle rowRect = this.ParentPrivate.Bounds; - rowRect.Width = this.Owner.DataGridView.RowHeadersWidth; - return rowRect; + Rectangle cellRect = rowRect; + cellRect.Width = this.Owner.DataGridView.RowHeadersWidth; + if (this.Owner.DataGridView.RightToLeft == RightToLeft.Yes) + { + cellRect.X = rowRect.Right - cellRect.Width; + } + + return cellRect; } } @@ -1324,7 +1318,7 @@ public override string Value public override void DoDefaultAction() { if ((this.Owner.DataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect || - this.Owner.DataGridView.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect ) && + this.Owner.DataGridView.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) && this.Owner.OwningRow != null) { this.Owner.OwningRow.Selected = true; @@ -1423,7 +1417,7 @@ public override void Select(AccessibleSelection flags) { throw new InvalidOperationException(string.Format(SR.DataGridViewCellAccessibleObject_OwnerNotSet)); } - + DataGridViewRowHeaderCell dataGridViewCell = (DataGridViewRowHeaderCell)this.Owner; DataGridView dataGridView = dataGridViewCell.DataGridView; @@ -1485,28 +1479,25 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga internal override object GetPropertyValue(int propertyId) { - if (AccessibilityImprovements.Level3) + switch (propertyId) { - switch (propertyId) - { - case NativeMethods.UIA_NamePropertyId: - return this.Name; - case NativeMethods.UIA_ControlTypePropertyId: - return NativeMethods.UIA_HeaderControlTypeId; - case NativeMethods.UIA_IsEnabledPropertyId: - return Owner.DataGridView.Enabled; - case NativeMethods.UIA_HelpTextPropertyId: - return this.Help ?? string.Empty; - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - return (this.State & AccessibleStates.Focusable) == AccessibleStates.Focusable; - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - case NativeMethods.UIA_IsPasswordPropertyId: - return false; - case NativeMethods.UIA_IsOffscreenPropertyId: - return (this.State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; - case NativeMethods.UIA_AccessKeyPropertyId: - return string.Empty; - } + case NativeMethods.UIA_NamePropertyId: + return this.Name; + case NativeMethods.UIA_ControlTypePropertyId: + return NativeMethods.UIA_HeaderControlTypeId; + case NativeMethods.UIA_IsEnabledPropertyId: + return Owner.DataGridView.Enabled; + case NativeMethods.UIA_HelpTextPropertyId: + return this.Help ?? string.Empty; + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + return (this.State & AccessibleStates.Focusable) == AccessibleStates.Focusable; + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + case NativeMethods.UIA_IsPasswordPropertyId: + return false; + case NativeMethods.UIA_IsOffscreenPropertyId: + return (this.State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; + case NativeMethods.UIA_AccessKeyPropertyId: + return string.Empty; } return base.GetPropertyValue(propertyId); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgs.cs index c11476d85aa..6b735e6407d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgs.cs @@ -30,9 +30,9 @@ public int Height { value = _minimumHeight; } - if (value > DataGridViewBand.maxBandThickness) + if (value > DataGridViewBand.MaxBandThickness) { - throw new ArgumentOutOfRangeException(nameof(Height), string.Format(SR.InvalidHighBoundArgumentEx, "Height", (value).ToString(CultureInfo.CurrentCulture), (DataGridViewBand.maxBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidHighBoundArgumentEx, nameof(Height), value, DataGridViewBand.MaxBandThickness)); } _height = value; @@ -44,9 +44,9 @@ public int MinimumHeight get => _minimumHeight; set { - if (value < DataGridViewBand.minBandThickness) + if (value < DataGridViewBand.MinBandThickness) { - throw new ArgumentOutOfRangeException(nameof(MinimumHeight), value, string.Format(SR.DataGridViewBand_MinimumHeightSmallerThanOne, (DataGridViewBand.minBandThickness).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.DataGridViewBand_MinimumHeightSmallerThanOne, DataGridViewBand.MinBandThickness)); } if (_height < value) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowsRemovedEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowsRemovedEventArgs.cs index a1bcb56c17d..a0f3c78d38a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowsRemovedEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewRowsRemovedEventArgs.cs @@ -12,11 +12,11 @@ public DataGridViewRowsRemovedEventArgs(int rowIndex, int rowCount) { if (rowIndex < 0) { - throw new ArgumentOutOfRangeException(nameof(rowIndex), string.Format(SR.InvalidLowBoundArgumentEx, nameof(rowIndex), rowIndex.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(rowIndex), string.Format(SR.InvalidLowBoundArgumentEx, nameof(rowIndex), rowIndex.ToString(CultureInfo.CurrentCulture), 0)); } if (rowCount < 1) { - throw new ArgumentOutOfRangeException(nameof(rowCount), string.Format(SR.InvalidLowBoundArgumentEx, nameof(rowCount), rowCount.ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(rowCount), string.Format(SR.InvalidLowBoundArgumentEx, nameof(rowCount), rowCount.ToString(CultureInfo.CurrentCulture), 1)); } RowIndex = rowIndex; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxCell.cs index c3184f84409..428e294400a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxCell.cs @@ -56,12 +56,7 @@ public DataGridViewTextBoxCell() /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level1) - { - return new DataGridViewTextBoxCellAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new DataGridViewTextBoxCellAccessibleObject(this); } private DataGridViewTextBoxEditingControl EditingTextBox @@ -105,14 +100,11 @@ public virtual int MaxInputLength } set { - //if (this.DataGridView != null && this.RowIndex == -1) - //{ - // throw new InvalidOperationException(string.Format(SR.DataGridView_InvalidOperationOnSharedCell)); - //} if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(MaxInputLength), string.Format(SR.InvalidLowBoundArgumentEx, "MaxInputLength", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(MaxInputLength), value, 0)); } + this.Properties.SetInteger(PropTextBoxCellMaxInputLength, value); if (OwnsEditingTextBox(this.RowIndex)) { @@ -834,10 +826,7 @@ public DataGridViewTextBoxCellAccessibleObject(DataGridViewCell owner) : base(ow { } - internal override bool IsIAccessibleExSupported() - { - return true; - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxColumn.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxColumn.cs index be4bd49f9bb..b18cf0b3d76 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxColumn.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxColumn.cs @@ -12,7 +12,7 @@ namespace System.Windows.Forms using System.Globalization; /// - [ToolboxBitmapAttribute(typeof(DataGridViewTextBoxColumn), "DataGridViewTextBoxColumn.bmp")] + [ToolboxBitmapAttribute(typeof(DataGridViewTextBoxColumn), "DataGridViewTextBoxColumn")] public class DataGridViewTextBoxColumn : DataGridViewColumn { private const int DATAGRIDVIEWTEXTBOXCOLUMN_maxInputLength = 32767; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxEditingControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxEditingControl.cs index abc66edac43..724cae196bb 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxEditingControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxEditingControl.cs @@ -34,16 +34,7 @@ public DataGridViewTextBoxEditingControl() : base() /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) - { - return new DataGridViewTextBoxEditingControlAccessibleObject(this); - } - else if (AccessibilityImprovements.Level2) - { - return new DataGridViewEditingControlAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new DataGridViewTextBoxEditingControlAccessibleObject(this); } /// @@ -116,13 +107,7 @@ public virtual bool RepositionEditingControlOnValueChange } } - internal override bool SupportsUiaProviders - { - get - { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// public virtual void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle) @@ -258,10 +243,7 @@ protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); - if (AccessibilityImprovements.Level3) - { - AccessibilityObject.RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); - } + AccessibilityObject.RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); } /// @@ -285,7 +267,7 @@ protected override bool ProcessKeyEventArgs(ref Message m) switch ((Keys)(int) m.WParam) { case Keys.Enter: - if (m.Msg == NativeMethods.WM_CHAR && + if (m.Msg == Interop.WindowMessages.WM_CHAR && !(ModifierKeys == Keys.Shift && this.Multiline && this.AcceptsReturn)) { // Ignore the Enter key and don't add it to the textbox content. This happens when failing validation brings @@ -296,7 +278,7 @@ protected override bool ProcessKeyEventArgs(ref Message m) break; case Keys.LineFeed: - if (m.Msg == NativeMethods.WM_CHAR && + if (m.Msg == Interop.WindowMessages.WM_CHAR && ModifierKeys == Keys.Control && this.Multiline && this.AcceptsReturn) { // Ignore linefeed character when user hits Ctrl-Enter to commit the cell. @@ -305,7 +287,7 @@ protected override bool ProcessKeyEventArgs(ref Message m) break; case Keys.A: - if (m.Msg == NativeMethods.WM_KEYDOWN && ModifierKeys == Keys.Control) + if (m.Msg == Interop.WindowMessages.WM_KEYDOWN && ModifierKeys == Keys.Control) { SelectAll(); return true; @@ -336,9 +318,6 @@ private static HorizontalAlignment TranslateAlignment(DataGridViewContentAlignme /// /// Defines the DataGridView TextBox EditingControl accessible object. /// - /// - /// This accessible object is only available in AccessibilityImprovements of Level 3. - /// internal class DataGridViewTextBoxEditingControlAccessibleObject : Control.ControlAccessibleObject { private DataGridViewTextBoxEditingControl ownerControl; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopLeftHeaderCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopLeftHeaderCell.cs index fa18a2563ec..910e65724e2 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopLeftHeaderCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopLeftHeaderCell.cs @@ -695,25 +695,22 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga internal override object GetPropertyValue(int propertyId) { - if (AccessibilityImprovements.Level3) + switch (propertyId) { - switch (propertyId) - { - case NativeMethods.UIA_NamePropertyId: - return this.Name; - case NativeMethods.UIA_ControlTypePropertyId: - return NativeMethods.UIA_HeaderControlTypeId; - case NativeMethods.UIA_IsEnabledPropertyId: - return Owner.DataGridView.Enabled; - case NativeMethods.UIA_HelpTextPropertyId: - return this.Help ?? string.Empty; - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - case NativeMethods.UIA_IsPasswordPropertyId: - case NativeMethods.UIA_IsOffscreenPropertyId: - return false; - case NativeMethods.UIA_AccessKeyPropertyId: - return string.Empty; - } + case NativeMethods.UIA_NamePropertyId: + return this.Name; + case NativeMethods.UIA_ControlTypePropertyId: + return NativeMethods.UIA_HeaderControlTypeId; + case NativeMethods.UIA_IsEnabledPropertyId: + return Owner.DataGridView.Enabled; + case NativeMethods.UIA_HelpTextPropertyId: + return this.Help ?? string.Empty; + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + case NativeMethods.UIA_IsPasswordPropertyId: + case NativeMethods.UIA_IsOffscreenPropertyId: + return false; + case NativeMethods.UIA_AccessKeyPropertyId: + return string.Empty; } return base.GetPropertyValue(propertyId); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopRowAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopRowAccessibleObject.cs index 4fb1289716a..2d31cdd20bf 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopRowAccessibleObject.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTopRowAccessibleObject.cs @@ -103,7 +103,7 @@ internal override int[] RuntimeId { get { - if (AccessibilityImprovements.Level3 && runtimeId == null) + if (runtimeId == null) { runtimeId = new int[3]; runtimeId[0] = RuntimeIDFirstItem; // first item is static - 0x2a @@ -260,7 +260,7 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga internal override bool IsPatternSupported(int patternId) { - if (AccessibilityImprovements.Level3 && patternId.Equals(NativeMethods.UIA_LegacyIAccessiblePatternId)) + if (patternId.Equals(NativeMethods.UIA_LegacyIAccessiblePatternId)) { return true; } @@ -270,29 +270,26 @@ internal override bool IsPatternSupported(int patternId) internal override object GetPropertyValue(int propertyId) { - if (AccessibilityImprovements.Level3) + switch (propertyId) { - switch (propertyId) - { - case NativeMethods.UIA_NamePropertyId: - return string.Format(SR.DataGridView_AccTopRow); - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - return false; - case NativeMethods.UIA_IsEnabledPropertyId: - return owner.Enabled; - case NativeMethods.UIA_IsOffscreenPropertyId: - return false; - case NativeMethods.UIA_IsContentElementPropertyId: - return true; - case NativeMethods.UIA_IsPasswordPropertyId: - return false; - case NativeMethods.UIA_AccessKeyPropertyId: - case NativeMethods.UIA_HelpTextPropertyId: - return string.Empty; - case NativeMethods.UIA_IsLegacyIAccessiblePatternAvailablePropertyId: - return true; - } + case NativeMethods.UIA_NamePropertyId: + return string.Format(SR.DataGridView_AccTopRow); + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + return false; + case NativeMethods.UIA_IsEnabledPropertyId: + return owner.Enabled; + case NativeMethods.UIA_IsOffscreenPropertyId: + return false; + case NativeMethods.UIA_IsContentElementPropertyId: + return true; + case NativeMethods.UIA_IsPasswordPropertyId: + return false; + case NativeMethods.UIA_AccessKeyPropertyId: + case NativeMethods.UIA_HelpTextPropertyId: + return string.Empty; + case NativeMethods.UIA_IsLegacyIAccessiblePatternAvailablePropertyId: + return true; } return base.GetPropertyValue(propertyId); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs index 054c8151f54..9d1d8671c38 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs @@ -1776,7 +1776,7 @@ private string[] ReadFileListFromHandle(IntPtr hdrop) { string[] files = null; - StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH); + StringBuilder sb = new StringBuilder(Interop.Kernel32.MAX_PATH); int count = UnsafeNativeMethods.DragQueryFile(new HandleRef(null, hdrop), unchecked((int)0xFFFFFFFF), null, 0); if (count > 0) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs index 590dd2d258b..b28d1002417 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs @@ -141,9 +141,7 @@ public DateTimePicker() // format = DateTimePickerFormat.Long; - if (AccessibilityImprovements.Level3) { - SetStyle(ControlStyles.UseTextForAccessibility, false); - } + SetStyle(ControlStyles.UseTextForAccessibility, false); } /// @@ -703,12 +701,11 @@ public DateTime MaxDate { if (value != max) { if (value < EffectiveMinDate(min)) { - throw new ArgumentOutOfRangeException(nameof(MaxDate), string.Format(SR.InvalidLowBoundArgumentEx, "MaxDate", FormatDateTime(value), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(MaxDate), FormatDateTime(value), nameof(MinDate))); } - - // If trying to set the maximum greater than MaxDateTime, throw. - if (value > MaximumDateTime) { - throw new ArgumentOutOfRangeException(nameof(MaxDate), string.Format(SR.DateTimePickerMaxDate, FormatDateTime(DateTimePicker.MaxDateTime))); + if (value > MaximumDateTime) + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.DateTimePickerMaxDate, FormatDateTime(DateTimePicker.MaxDateTime))); } max = value; @@ -757,13 +754,11 @@ public DateTime MinDate { { if (value > EffectiveMaxDate(max)) { - throw new ArgumentOutOfRangeException(nameof(MinDate), string.Format(SR.InvalidHighBoundArgument, "MinDate", FormatDateTime(value), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgument, nameof(MinDate), FormatDateTime(value), nameof(MaxDate))); } - - // If trying to set the minimum less than MinimumDateTime, throw. if (value < MinimumDateTime) { - throw new ArgumentOutOfRangeException(nameof(MinDate), string.Format(SR.DateTimePickerMinDate, FormatDateTime(DateTimePicker.MinimumDateTime))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.DateTimePickerMinDate, FormatDateTime(DateTimePicker.MinimumDateTime))); } min = value; @@ -993,7 +988,7 @@ public DateTime Value { // update anyway. if (!userHasSetValue || valueChanged) { if ((value < MinDate) || (value > MaxDate)) { - throw new ArgumentOutOfRangeException(nameof(Value), string.Format(SR.InvalidBoundArgument, "Value", FormatDateTime(value), "'MinDate'", "'MaxDate'")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(Value), FormatDateTime(value), $"'{nameof(MinDate)}'", $"'{nameof(MaxDate)}'")); } string oldText = this.Text; @@ -1648,17 +1643,17 @@ private void WmReflectCommand(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: FocusInternal(); if (!ValidationCancelled) { base.WndProc(ref m); } break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: WmReflectCommand(ref m); base.WndProc(ref m); break; - case NativeMethods.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: base.WndProc(ref m); UpdateUpDown(); break; @@ -1775,18 +1770,13 @@ public override AccessibleRole Role { if (role != AccessibleRole.Default) { return role; } - return AccessibilityImprovements.Level3 ? AccessibleRole.ComboBox : AccessibleRole.DropList; - } - } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3) { - return true; + return AccessibleRole.ComboBox; } - - return base.IsIAccessibleExSupported(); } + internal override bool IsIAccessibleExSupported() => true; + internal override object GetPropertyValue(int propertyID) { switch (propertyID) { case NativeMethods.UIA_IsTogglePatternAvailablePropertyId: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorForm.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorForm.cs index 158f386afbe..32f2f368fd8 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorForm.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorForm.cs @@ -839,7 +839,7 @@ private void FillRectDither(IntPtr dc, NativeMethods.RECT rc) { } protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY) { + if (m.Msg == Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY) { NativeMethods.NMHDR nmh = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR)); if (nmh.code == NativeMethods.NM_CUSTOMDRAW) { OnCustomDraw(ref m); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorPage.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorPage.cs index a859c05b042..40549affdac 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorPage.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Design/ComponentEditorPage.cs @@ -162,7 +162,7 @@ public Icon Icon { get { if (icon == null) { - icon = new Icon(typeof(ComponentEditorPage), "ComponentEditorPage.ico"); + icon = new Icon(typeof(ComponentEditorPage), "ComponentEditorPage"); } return icon; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Design/PropertyTab.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Design/PropertyTab.cs index 2346f00e8f3..4f3f92935c5 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Design/PropertyTab.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Design/PropertyTab.cs @@ -37,13 +37,11 @@ public virtual Bitmap Bitmap { get { if (!checkedBmp && bitmap == null) { - string bmpName = GetType().Name + ".bmp"; - try - { - bitmap = new Bitmap(GetType(), bmpName); + string bmpName = GetType().Name + ""; + try { + bitmap = DpiHelper.GetBitmapFromIcon(GetType(), bmpName); } - catch (Exception ex) - { + catch (Exception ex) { Debug.Fail("Failed to find bitmap '" + bmpName + "' for class " + GetType().FullName, ex.ToString()); } checkedBmp = true; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DisplayInformation.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DisplayInformation.cs index 0e87fb85169..c9bb8ac8044 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DisplayInformation.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DisplayInformation.cs @@ -7,7 +7,6 @@ namespace System.Windows.Forms { using Microsoft.Win32; using System.Security; - using System.Security.Permissions; internal class DisplayInformation { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DomainUpDown.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DomainUpDown.cs index 0709e062962..500da73186d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DomainUpDown.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DomainUpDown.cs @@ -139,7 +139,7 @@ public int SelectedIndex { set { if (value < -1 || value >= Items.Count) { - throw new ArgumentOutOfRangeException(nameof(SelectedIndex), string.Format(SR.InvalidArgument, "SelectedIndex", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SelectedIndex), value)); } if (value != SelectedIndex) { @@ -645,7 +645,7 @@ public override void Remove(object item) { int index = IndexOf(item); if (index == -1) { - throw new ArgumentOutOfRangeException(nameof(item), string.Format(SR.InvalidArgument, "item", item.ToString())); + throw new ArgumentOutOfRangeException(nameof(item), item, string.Format(SR.InvalidArgument, nameof(item), item)); } else { RemoveAt(index); @@ -741,12 +741,7 @@ public override AccessibleRole Role { return role; } else { - if (AccessibilityImprovements.Level1) { - return AccessibleRole.SpinButton; - } - else { - return AccessibleRole.ComboBox; - } + return AccessibleRole.SpinButton; } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DpiChangedEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DpiChangedEventArgs.cs index 9482c73f26e..2e96dbc7427 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DpiChangedEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DpiChangedEventArgs.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Drawing; +using System.Runtime.InteropServices; namespace System.Windows.Forms { @@ -21,7 +22,7 @@ internal DpiChangedEventArgs(int old, Message m) DeviceDpiOld = old; DeviceDpiNew = NativeMethods.Util.SignedLOWORD(m.WParam); Debug.Assert(NativeMethods.Util.SignedHIWORD(m.WParam) == DeviceDpiNew, "Non-square pixels!"); - NativeMethods.RECT suggestedRect = (NativeMethods.RECT)UnsafeNativeMethods.PtrToStructure(m.LParam, typeof(NativeMethods.RECT)); + NativeMethods.RECT suggestedRect = Marshal.PtrToStructure(m.LParam); SuggestedRectangle = Rectangle.FromLTRB(suggestedRect.left, suggestedRect.top, suggestedRect.right, suggestedRect.bottom); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DropTarget.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DropTarget.cs index 9ed78eb1a04..b98e1d96613 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DropTarget.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DropTarget.cs @@ -6,7 +6,6 @@ namespace System.Windows.Forms { using System; using System.Diagnostics; - using System.Security.Permissions; using System.Security; using System.ComponentModel; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ErrorProvider.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ErrorProvider.cs index cbeaab6a9d1..f9ea48461ad 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ErrorProvider.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ErrorProvider.cs @@ -555,7 +555,7 @@ static Icon DefaultIcon { if (defaultIcon == null) { lock (typeof(ErrorProvider)) { if (defaultIcon == null) { - defaultIcon = new Icon(typeof(ErrorProvider), "Error.ico"); + defaultIcon = new Icon(typeof(ErrorProvider), "Error"); } } } @@ -1253,16 +1253,16 @@ public void Update(bool timerCaused) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR)); if (nmhdr.code == NativeMethods.TTN_SHOW || nmhdr.code == NativeMethods.TTN_POP) { OnToolTipVisibilityChanging(nmhdr.idFrom, nmhdr.code == NativeMethods.TTN_SHOW); } break; - case NativeMethods.WM_ERASEBKGND: + case Interop.WindowMessages.WM_ERASEBKGND: break; - case NativeMethods.WM_PAINT: + case Interop.WindowMessages.WM_PAINT: OnPaint(ref m); break; default: @@ -1662,7 +1662,6 @@ public Region Region { try { Size size = icon.Size; Bitmap bitmap = icon.ToBitmap(); - bitmap.MakeTransparent(); mask = ControlPaint.CreateHBitmapTransparencyMask(bitmap); bitmap.Dispose(); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FeatureSupport.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FeatureSupport.cs index 58ad8b05e68..59610d98a0b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FeatureSupport.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FeatureSupport.cs @@ -2,133 +2,98 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Configuration.Assemblies; - - using System.Diagnostics; - - using System; - using System.Reflection; - - - /// - /// - /// Provides methods for retrieving feature information from the - /// current system. - /// - public abstract class FeatureSupport : IFeatureSupport { - - /// - /// - /// Determines whether any version of the specified feature - /// is installed in the system. This method is . - /// - public static bool IsPresent(string featureClassName, string featureConstName) { +using System.Reflection; + +namespace System.Windows.Forms +{ + /// + /// Provides methods for retrieving feature information from the + /// current system. + /// + public abstract class FeatureSupport : IFeatureSupport + { + /// + /// Determines whether any version of the specified feature is installed in the system. + /// This method is . + /// + public static bool IsPresent(string featureClassName, string featureConstName) + { return IsPresent(featureClassName, featureConstName, new Version(0, 0, 0, 0)); } - /// - /// - /// Determines whether the specified or newer version of the specified feature is - /// installed in the system. This method is . - /// - public static bool IsPresent(string featureClassName, string featureConstName, Version minimumVersion) + /// + /// Determines whether the specified or newer version of the specified feature is + /// installed in the system. This method is . + /// + public static bool IsPresent(string featureClassName, string featureConstName, Version minimumVersion) { - object featureId = null; - IFeatureSupport featureSupport = null; - - //APPCOMPAT: If Type.GetType() throws, we want to return - //null to preserve Everett behavior. Type c = null; - try { + try + { c = Type.GetType(featureClassName); } - catch (ArgumentException) {} - - if (c != null) { - FieldInfo fi = c.GetField(featureConstName); - - if (fi != null) { - featureId = fi.GetValue(null); - } + catch (ArgumentException) + { } - if (featureId != null && typeof(IFeatureSupport).IsAssignableFrom(c)) { - - featureSupport = (IFeatureSupport) Activator.CreateInstance(c); - - if (featureSupport != null) { - return featureSupport.IsPresent(featureId, minimumVersion); - } + object featureId = c?.GetField(featureConstName)?.GetValue(null); + if (featureId == null || !typeof(IFeatureSupport).IsAssignableFrom(c)) + { + return false; } - return false; - } - /// - /// - /// Gets the version of the specified feature that is available on the system. - /// - public static Version GetVersionPresent(string featureClassName, string featureConstName) { - object featureId = null; - IFeatureSupport featureSupport = null; + IFeatureSupport featureSupport = (IFeatureSupport)Activator.CreateInstance(c); + return featureSupport.IsPresent(featureId, minimumVersion); + } - //APPCOMPAT: If Type.GetType() throws, we want to return - //null to preserve Everett behavior. + /// + /// Gets the version of the specified feature that is available on the system. + /// + public static Version GetVersionPresent(string featureClassName, string featureConstName) + { Type c = null; - try { + try + { c = Type.GetType(featureClassName); } - catch (ArgumentException) {} - - if (c != null) { - FieldInfo fi = c.GetField(featureConstName); - - if (fi != null) { - featureId = fi.GetValue(null); - } + catch (ArgumentException) + { } - if (featureId != null) + object featureId = c?.GetField(featureConstName)?.GetValue(null); + if (featureId == null || !typeof(IFeatureSupport).IsAssignableFrom(c)) { - featureSupport = (IFeatureSupport) Activator.CreateInstance(c); - - if (featureSupport != null) { - return featureSupport.GetVersionPresent(featureId); - } + return null; } - return null; - } - /// - /// - /// Determines whether any version of the specified feature - /// is installed in the system. - /// - public virtual bool IsPresent(object feature) { - return IsPresent(feature, new Version(0, 0, 0, 0)); + IFeatureSupport featureSupport = (IFeatureSupport)Activator.CreateInstance(c); + return featureSupport.GetVersionPresent(featureId); } - /// - /// - /// Determines whether the specified or newer version of the - /// specified feature is installed in the system. - /// - public virtual bool IsPresent(object feature, Version minimumVersion) { - Version ver = GetVersionPresent(feature); + /// + /// Determines whether any version of the specified feature is installed in the system. + /// + public virtual bool IsPresent(object feature) => IsPresent(feature, new Version(0, 0, 0, 0)); - if (ver != null) { - return ver.CompareTo(minimumVersion) >= 0; + /// + /// Determines whether the specified or newer version of the specified feature is + /// installed in the system. + /// + public virtual bool IsPresent(object feature, Version minimumVersion) + { + Version ver = GetVersionPresent(feature); + if (ver == null) + { + return false; } - return false; + + return ver.CompareTo(minimumVersion) >= 0; } - /// - /// - /// When overridden in a derived class, gets the version of the specified - /// feature that is available on the system. - /// + /// + /// When overridden in a derived class, gets the version of the specified feature that + /// is available on the system. + /// public abstract Version GetVersionPresent(object feature); } - - } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FileDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FileDialog.cs index 0b53c24fd39..c9f42eec620 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FileDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FileDialog.cs @@ -391,10 +391,7 @@ public string InitialDirectory { /// Gets the Win32 instance handle for the application. /// /// - /* SECURITYUNDONE : should require EventQueue permission */ protected virtual IntPtr Instance { - - get { return UnsafeNativeMethods.GetModuleHandle(null); } } @@ -550,7 +547,7 @@ public event CancelEventHandler FileOk { /// Processes the CDN_FILEOK notification. /// private bool DoFileOk(IntPtr lpOFN) { - NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(lpOFN, typeof(NativeMethods.OPENFILENAME_I)); + NativeMethods.OPENFILENAME_I ofn = Marshal.PtrToStructure(lpOFN); int saveOptions = options; int saveFilterIndex = filterIndex; string[] saveFileNames = fileNames; @@ -663,17 +660,17 @@ internal bool GetOption(int option) { /// /// protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { - if (msg == NativeMethods.WM_NOTIFY) { + if (msg == Interop.WindowMessages.WM_NOTIFY) { dialogHWnd = UnsafeNativeMethods.GetParent(new HandleRef(null, hWnd)); try { - UnsafeNativeMethods.OFNOTIFY notify = (UnsafeNativeMethods.OFNOTIFY)UnsafeNativeMethods.PtrToStructure(lparam, typeof(UnsafeNativeMethods.OFNOTIFY)); + UnsafeNativeMethods.OFNOTIFY notify = Marshal.PtrToStructure(lparam); switch (notify.hdr_code) { case -601: /* CDN_INITDONE */ MoveToScreenCenter(dialogHWnd); break; case -602: /* CDN_SELCHANGE */ - NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(notify.lpOFN, typeof(NativeMethods.OPENFILENAME_I)); + NativeMethods.OPENFILENAME_I ofn = Marshal.PtrToStructure(notify.lpOFN); // Get the buffer size required to store the selected file names. int sizeNeeded = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, dialogHWnd), 1124 /*CDM_GETSPEC*/, System.IntPtr.Zero, System.IntPtr.Zero); if (sizeNeeded > ofn.nMaxFile) { @@ -919,7 +916,7 @@ private bool RunDialogOld(IntPtr hWndOwner) if (fileNames != null) { charBuffer.PutString(fileNames[0]); } - ofn.lStructSize = Marshal.SizeOf(typeof(NativeMethods.OPENFILENAME_I)); + ofn.lStructSize = Marshal.SizeOf(); // Degrade to the older style dialog if we're not on Win2K. // We do this by setting the struct size to a different value // diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FileDialogCustomPlace.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FileDialogCustomPlace.cs index 50afcf3ea15..c3129c0b60a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FileDialogCustomPlace.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FileDialogCustomPlace.cs @@ -5,7 +5,6 @@ using System; using System.IO; using System.Security; -using System.Security.Permissions; using System.Text; namespace System.Windows.Forms @@ -68,53 +67,24 @@ public override string ToString() internal FileDialogNative.IShellItem GetNativePath() { - //This can throw in a multitude of ways if the path or Guid doesn't correspond - //to an actual filesystem directory. Caller is responsible for handling these situations. - string filePathString = ""; - if (!string.IsNullOrEmpty(this._path)) + // This can throw in a multitude of ways if the path or Guid doesn't correspond + // to an actual filesystem directory. + // The Caller is responsible for handling these situations. + string filePathString; + if (!string.IsNullOrEmpty(_path)) { - filePathString = this._path; + filePathString = _path; } else { - filePathString = GetFolderLocation(this._knownFolderGuid); - } - - if (string.IsNullOrEmpty(filePathString)) - { - return null; - } - else - { - return FileDialog.GetShellItemForPath(filePathString); - } - } - - private static string GetFolderLocation(Guid folderGuid) - { - //returns a null string if the path can't be found - - //SECURITY: This exposes the filesystem path of the GUID. The returned value - // must not be made available to user code. - - if (!UnsafeNativeMethods.IsVista) - { - return null; + int result = Interop.Shell32.SHGetKnownFolderPath(ref _knownFolderGuid, 0, IntPtr.Zero, out filePathString); + if (result == 0) + { + return null; + } } - StringBuilder path = new StringBuilder(); - - int result = UnsafeNativeMethods.Shell32.SHGetFolderPathEx(ref folderGuid, 0, IntPtr.Zero, path); - if (NativeMethods.S_OK == result) - { - string ret = path.ToString(); - return ret; - } - else - { - // 0x80070002 is an explicit FileNotFound error. - return null; - } + return FileDialog.GetShellItemForPath(filePathString); } } } \ No newline at end of file diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FlatButtonAppearance.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FlatButtonAppearance.cs index 63296e844c7..716324628e2 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FlatButtonAppearance.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FlatButtonAppearance.cs @@ -46,7 +46,7 @@ public int BorderSize { } set { if (value < 0) - throw new ArgumentOutOfRangeException(nameof(BorderSize), value, string.Format(SR.InvalidLowBoundArgumentEx, "BorderSize", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(BorderSize), value, 0)); if (borderSize != value) { borderSize = value; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FolderBrowserDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FolderBrowserDialog.cs index 9abebc87b62..7aadefea080 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FolderBrowserDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FolderBrowserDialog.cs @@ -8,15 +8,16 @@ namespace System.Windows.Forms { using System; using System.IO; + using System.Buffers; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Diagnostics; using System.Runtime.InteropServices; - using System.Security.Permissions; using System.Diagnostics.CodeAnalysis; - + using Microsoft.Win32.SafeHandles; + /// /// /// @@ -44,9 +45,6 @@ public sealed class FolderBrowserDialog : CommonDialog // Show the 'New Folder' button? private bool showNewFolderButton; - // Callback function for the folder browser dialog - private UnsafeNativeMethods.BrowseCallbackProc callback; - /// /// /// @@ -216,16 +214,6 @@ internal bool UseVistaDialogInternal } } - /// - /// Helper function that returns the IMalloc interface used by the shell. - /// - private static UnsafeNativeMethods.IMalloc GetSHMalloc() - { - UnsafeNativeMethods.IMalloc[] malloc = new UnsafeNativeMethods.IMalloc[1]; - UnsafeNativeMethods.Shell32.SHGetMalloc(malloc); - return malloc[0]; - } - /// /// /// @@ -314,93 +302,73 @@ private void GetResult(FileDialogNative.IFileDialog dialog) item.GetDisplayName(FileDialogNative.SIGDN.SIGDN_FILESYSPATH, out selectedPath); } - private bool RunDialogOld(IntPtr hWndOwner) + private unsafe bool RunDialogOld(IntPtr hWndOwner) { - IntPtr pidlRoot = IntPtr.Zero; - bool returnValue = false; + CoTaskMemSafeHandle listHandle; - UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)rootFolder, ref pidlRoot); - if (pidlRoot == IntPtr.Zero) + Interop.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)rootFolder, out listHandle); + if (listHandle.IsInvalid) { - UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, NativeMethods.CSIDL_DESKTOP, ref pidlRoot); - if (pidlRoot == IntPtr.Zero) + Interop.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)Environment.SpecialFolder.Desktop, out listHandle); + if (listHandle.IsInvalid) { throw new InvalidOperationException(SR.FolderBrowserDialogNoRootFolder); } } - int mergedOptions = unchecked((int)(long)UnsafeNativeMethods.BrowseInfos.NewDialogStyle); - if (!showNewFolderButton) + using (listHandle) { - mergedOptions += unchecked((int)(long)UnsafeNativeMethods.BrowseInfos.HideNewFolderButton); - } - - // The SHBrowserForFolder dialog is OLE/COM based, and documented as only being safe to use under the STA - // threading model if the BIF_NEWDIALOGSTYLE flag has been requested (which we always do in mergedOptions - // above). So make sure OLE is initialized, and throw an exception if caller attempts to invoke dialog - // under the MTA threading model (...dialog does appear under MTA, but is totally non-functional). - if (Control.CheckForIllegalCrossThreadCalls && Application.OleRequired() != System.Threading.ApartmentState.STA) - { - throw new System.Threading.ThreadStateException(string.Format(SR.DebuggingExceptionOnly, SR.ThreadMustBeSTA)); - } - - IntPtr pidlRet = IntPtr.Zero; - IntPtr pszDisplayName = IntPtr.Zero; - IntPtr pszSelectedPath = IntPtr.Zero; - - try - { - // Construct a BROWSEINFO - UnsafeNativeMethods.BROWSEINFO bi = new UnsafeNativeMethods.BROWSEINFO(); - - pszDisplayName = Marshal.AllocHGlobal(NativeMethods.MAX_PATH * sizeof(char)); - pszSelectedPath = Marshal.AllocHGlobal((NativeMethods.MAX_PATH + 1) * sizeof(char)); - this.callback = new UnsafeNativeMethods.BrowseCallbackProc(this.FolderBrowserDialog_BrowseCallbackProc); - - bi.pidlRoot = pidlRoot; - bi.hwndOwner = hWndOwner; - bi.pszDisplayName = pszDisplayName; - bi.lpszTitle = descriptionText; - bi.ulFlags = mergedOptions; - bi.lpfn = callback; - bi.lParam = IntPtr.Zero; - bi.iImage = 0; - - // And show the dialog - pidlRet = UnsafeNativeMethods.Shell32.SHBrowseForFolder(bi); - - if (pidlRet != IntPtr.Zero) + uint mergedOptions = Interop.Shell32.BrowseInfoFlags.BIF_NEWDIALOGSTYLE; + if (!showNewFolderButton) { - // Then retrieve the path from the IDList - UnsafeNativeMethods.Shell32.SHGetPathFromIDListLongPath(pidlRet, ref pszSelectedPath); - - // Convert to a string - selectedPath = Marshal.PtrToStringAuto(pszSelectedPath); - - returnValue = true; + mergedOptions |= Interop.Shell32.BrowseInfoFlags.BIF_NONEWFOLDERBUTTON; } - } - finally - { - UnsafeNativeMethods.CoTaskMemFree(pidlRoot); - if (pidlRet != IntPtr.Zero) + + // The SHBrowserForFolder dialog is OLE/COM based, and documented as only being safe to use under the STA + // threading model if the BIF_NEWDIALOGSTYLE flag has been requested (which we always do in mergedOptions + // above). So make sure OLE is initialized, and throw an exception if caller attempts to invoke dialog + // under the MTA threading model (...dialog does appear under MTA, but is totally non-functional). + if (Control.CheckForIllegalCrossThreadCalls && Application.OleRequired() != System.Threading.ApartmentState.STA) { - UnsafeNativeMethods.CoTaskMemFree(pidlRet); + throw new System.Threading.ThreadStateException(string.Format(SR.DebuggingExceptionOnly, SR.ThreadMustBeSTA)); } - // Then free all the stuff we've allocated or the SH API gave us - if (pszSelectedPath != IntPtr.Zero) + var callback = new Interop.Shell32.BrowseCallbackProc(FolderBrowserDialog_BrowseCallbackProc); + char[] displayName = ArrayPool.Shared.Rent(Interop.Kernel32.MAX_PATH + 1); + try { - Marshal.FreeHGlobal(pszSelectedPath); + fixed (char *pDisplayName = displayName) + { + var bi = new Interop.Shell32.BROWSEINFO(); + bi.pidlRoot = listHandle; + bi.hwndOwner = hWndOwner; + bi.pszDisplayName = pDisplayName; + bi.lpszTitle = descriptionText; + bi.ulFlags = mergedOptions; + bi.lpfn = callback; + bi.lParam = IntPtr.Zero; + bi.iImage = 0; + + // Show the dialog + using (CoTaskMemSafeHandle browseHandle = Interop.Shell32.SHBrowseForFolderW(ref bi)) + { + if (browseHandle.IsInvalid) + { + return false; + } + + // Retrieve the path from the IDList. + Interop.Shell32.SHGetPathFromIDListLongPath(browseHandle.DangerousGetHandle(), out selectedPath); + GC.KeepAlive(callback); + return true; + } + } } - if (pszDisplayName != IntPtr.Zero) + finally { - Marshal.FreeHGlobal(pszDisplayName); + ArrayPool.Shared.Return(displayName); } - - this.callback = null; } - return returnValue; } /// @@ -427,10 +395,8 @@ private int FolderBrowserDialog_BrowseCallbackProc(IntPtr hwnd, IntPtr selectedPidl = lParam; if (selectedPidl != IntPtr.Zero) { - IntPtr pszSelectedPath = Marshal.AllocHGlobal((NativeMethods.MAX_PATH + 1) * sizeof(char)); // Try to retrieve the path from the IDList - bool isFileSystemFolder = UnsafeNativeMethods.Shell32.SHGetPathFromIDListLongPath(selectedPidl, ref pszSelectedPath); - Marshal.FreeHGlobal(pszSelectedPath); + bool isFileSystemFolder = Interop.Shell32.SHGetPathFromIDListLongPath(selectedPidl, out _); UnsafeNativeMethods.SendMessage(new HandleRef(null, hwnd), (int) NativeMethods.BFFM_ENABLEOK, 0, isFileSystemFolder ? 1 : 0); } break; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FontDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FontDialog.cs index 3262824d366..17f69b93812 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FontDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FontDialog.cs @@ -463,10 +463,10 @@ internal bool GetOption(int option) { protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { switch (msg) { - case NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_COMMAND: if ((int)wparam == 0x402) { NativeMethods.LOGFONT lf = new NativeMethods.LOGFONT(); - UnsafeNativeMethods.SendMessage(new HandleRef(null, hWnd), NativeMethods.WM_CHOOSEFONT_GETLOGFONT, 0, lf); + UnsafeNativeMethods.SendMessage(new HandleRef(null, hWnd), Interop.WindowMessages.WM_CHOOSEFONT_GETLOGFONT, 0, lf); UpdateFont(lf); int index = (int)UnsafeNativeMethods.SendDlgItemMessage(new HandleRef(null, hWnd), 0x473, NativeMethods.CB_GETCURSEL, IntPtr.Zero, IntPtr.Zero); if (index != NativeMethods.CB_ERR) { @@ -488,7 +488,7 @@ protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr l } } break; - case NativeMethods.WM_INITDIALOG: + case Interop.WindowMessages.WM_INITDIALOG: if (!showColor) { IntPtr hWndCtl = UnsafeNativeMethods.GetDlgItem(new HandleRef(null, hWnd), NativeMethods.cmb4); SafeNativeMethods.ShowWindow(new HandleRef(null, hWndCtl), NativeMethods.SW_HIDE); @@ -561,10 +561,10 @@ protected override bool RunDialog(IntPtr hWndOwner) { IntPtr logFontPtr = IntPtr.Zero; try { - logFontPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(NativeMethods.LOGFONT))); + logFontPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf()); Marshal.StructureToPtr(lf, logFontPtr, false); - cf.lStructSize = Marshal.SizeOf(typeof(NativeMethods.CHOOSEFONT)); + cf.lStructSize = Marshal.SizeOf(); cf.hwndOwner = hWndOwner; cf.hDC = IntPtr.Zero; cf.lpLogFont = logFontPtr; @@ -597,8 +597,7 @@ protected override bool RunDialog(IntPtr hWndOwner) { if (!SafeNativeMethods.ChooseFont(cf)) return false; - NativeMethods.LOGFONT lfReturned = null; - lfReturned = (NativeMethods.LOGFONT)UnsafeNativeMethods.PtrToStructure(logFontPtr, typeof(NativeMethods.LOGFONT)); + NativeMethods.LOGFONT lfReturned = Marshal.PtrToStructure(logFontPtr); if (lfReturned.lfFaceName != null && lfReturned.lfFaceName.Length > 0) { lf = lfReturned; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs index 49e4f511e06..33eadfc0ca6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Form.cs @@ -21,8 +21,6 @@ namespace System.Windows.Forms { using System.Runtime.Serialization.Formatters; using System.Runtime.Remoting; using System.Runtime.InteropServices; - using System.Security; - using System.Security.Policy; using System.Threading; using System.Windows.Forms.Design; using System.Windows.Forms.Layout; @@ -91,20 +89,12 @@ public class Form : ContainerControl { private static readonly BitVector32.Section FormStateMdiChildMax = BitVector32.CreateSection(1, FormStateSWCalled); private static readonly BitVector32.Section FormStateRenderSizeGrip = BitVector32.CreateSection(1, FormStateMdiChildMax); private static readonly BitVector32.Section FormStateSizeGripStyle = BitVector32.CreateSection(2, FormStateRenderSizeGrip); - private static readonly BitVector32.Section FormStateIsRestrictedWindow = BitVector32.CreateSection(1, FormStateSizeGripStyle); - private static readonly BitVector32.Section FormStateIsRestrictedWindowChecked = BitVector32.CreateSection(1, FormStateIsRestrictedWindow); - private static readonly BitVector32.Section FormStateIsWindowActivated = BitVector32.CreateSection(1, FormStateIsRestrictedWindowChecked); + private static readonly BitVector32.Section FormStateIsWindowActivated = BitVector32.CreateSection(1, FormStateSizeGripStyle); private static readonly BitVector32.Section FormStateIsTextEmpty = BitVector32.CreateSection(1, FormStateIsWindowActivated); private static readonly BitVector32.Section FormStateIsActive = BitVector32.CreateSection(1, FormStateIsTextEmpty); private static readonly BitVector32.Section FormStateIconSet = BitVector32.CreateSection(1, FormStateIsActive); -#if SECURITY_DIALOG - private static readonly BitVector32.Section FormStateAddedSecurityMenuItem = BitVector32.CreateSection(1, FormStateIconSet); -#endif - - // // The following flags should be used with formStateEx[...] not formState[..] - // private static readonly BitVector32.Section FormStateExCalledClosing = BitVector32.CreateSection(1); private static readonly BitVector32.Section FormStateExUpdateMenuHandlesSuspendCount = BitVector32.CreateSection(8, FormStateExCalledClosing); private static readonly BitVector32.Section FormStateExUpdateMenuHandlesDeferred = BitVector32.CreateSection(1, FormStateExUpdateMenuHandlesSuspendCount); @@ -126,7 +116,6 @@ public class Form : ContainerControl { private const int SizeGripSize = 16; private static Icon defaultIcon = null; - private static Icon defaultRestrictedIcon = null; #if MAGIC_PADDING private static Padding FormPadding = new Padding(9); // UI guideline #endif @@ -164,26 +153,14 @@ public class Form : ContainerControl { private static readonly int PropMainMenuStrip = PropertyStore.CreateKey(); private static readonly int PropMdiWindowListStrip = PropertyStore.CreateKey(); private static readonly int PropMdiControlStrip = PropertyStore.CreateKey(); - private static readonly int PropSecurityTip = PropertyStore.CreateKey(); - private static readonly int PropOpacity = PropertyStore.CreateKey(); + private static readonly int PropOpacity = PropertyStore.CreateKey(); private static readonly int PropTransparencyKey = PropertyStore.CreateKey(); -#if SECURITY_DIALOG - private static readonly int PropSecuritySystemMenuItem = PropertyStore.CreateKey(); -#endif - /////////////////////////////////////////////////////////////////////// // Form per instance members - // // Note: Do not add anything to this list unless absolutely neccessary. - // - // Begin Members { - - // List of properties that are generally set, so we keep them directly on - // Form. - // - private BitVector32 formState = new BitVector32(0x21338); // magic value... all the defaults... see the ctor for details... + private BitVector32 formState = new BitVector32(0x21338); // magic value... all the defaults... see the ctor for details... private BitVector32 formStateEx = new BitVector32(); @@ -193,43 +170,26 @@ public class Form : ContainerControl { private Size minAutoSize = Size.Empty; private Rectangle restoredWindowBounds = new Rectangle(-1, -1, -1, -1); private BoundsSpecified restoredWindowBoundsSpecified; - private DialogResult dialogResult; + private DialogResult dialogResult; private MdiClient ctlClient; private NativeWindow ownerWindow; - private string userWindowText; // Used to cache user's text in semi-trust since the window text is added security info. - private string securityZone; - private string securitySite; private bool rightToLeftLayout = false; - - //Whidbey RestoreBounds ... private Rectangle restoreBounds = new Rectangle(-1, -1, -1, -1); private CloseReason closeReason = CloseReason.None; private VisualStyleRenderer sizeGripRenderer; - // } End Members - /////////////////////////////////////////////////////////////////////// - - - /// /// - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// - public Form() - : base() { - - // we must setup the formState *before* calling Control's ctor... so we do that - // at the member variable... that magic number is generated by switching - // the line below to "true" and running a form. - // - // keep the "init" and "assert" sections always in sync! - // + public Form() : base() + { + // The magic number formState is generated by switching the line below to "true" + // and running a form. + // Keep the "init" and "assert" sections always in sync! #if false - // init section... - // + // Init section. formState[FormStateAllowTransparency] = 0; formState[FormStateBorderStyle] = (int)FormBorderStyle.Sizable; formState[FormStateTaskBar] = 1; @@ -249,25 +209,14 @@ public Form() formState[FormStateMdiChildMax] = 0; formState[FormStateRenderSizeGrip] = 0; formState[FormStateSizeGripStyle] = 0; - formState[FormStateIsRestrictedWindow] = 0; - formState[FormStateIsRestrictedWindowChecked] = 0; formState[FormStateIsWindowActivated] = 0; formState[FormStateIsTextEmpty] = 0; formState[FormStateIsActive] = 0; formState[FormStateIconSet] = 0; - -#if SECURITY_DIALOG - formState[FormStateAddedSecurityMenuItem] = 0; - -#endif - - - - Debug.WriteLine("initial formState: 0x" + formState.Data.ToString("X")); #endif - // assert section... - // + + // Assert section. Debug.Assert(formState[FormStateAllowTransparency] == 0, "Failed to set formState[FormStateAllowTransparency]"); Debug.Assert(formState[FormStateBorderStyle] == (int)FormBorderStyle.Sizable, "Failed to set formState[FormStateBorderStyle]"); Debug.Assert(formState[FormStateTaskBar] == 1, "Failed to set formState[FormStateTaskBar]"); @@ -287,26 +236,11 @@ public Form() Debug.Assert(formState[FormStateMdiChildMax] == 0, "Failed to set formState[FormStateMdiChildMax]"); Debug.Assert(formState[FormStateRenderSizeGrip] == 0, "Failed to set formState[FormStateRenderSizeGrip]"); Debug.Assert(formState[FormStateSizeGripStyle] == 0, "Failed to set formState[FormStateSizeGripStyle]"); - // can't check these... Control::.ctor may force the check - // of security... you can only assert these are 0 when running - // under full trust... - // - //Debug.Assert(formState[FormStateIsRestrictedWindow] == 0, "Failed to set formState[FormStateIsRestrictedWindow]"); - //Debug.Assert(formState[FormStateIsRestrictedWindowChecked] == 0, "Failed to set formState[FormStateIsRestrictedWindowChecked]"); Debug.Assert(formState[FormStateIsWindowActivated] == 0, "Failed to set formState[FormStateIsWindowActivated]"); Debug.Assert(formState[FormStateIsTextEmpty] == 0, "Failed to set formState[FormStateIsTextEmpty]"); Debug.Assert(formState[FormStateIsActive] == 0, "Failed to set formState[FormStateIsActive]"); Debug.Assert(formState[FormStateIconSet] == 0, "Failed to set formState[FormStateIconSet]"); - -#if SECURITY_DIALOG - Debug.Assert(formState[FormStateAddedSecurityMenuItem] == 0, "Failed to set formState[FormStateAddedSecurityMenuItem]"); -#endif - - // SECURITY NOTE: The IsRestrictedWindow check is done once and cached. We force it to happen here - // since we want to ensure the check is done on the code that constructs the form. - bool temp = IsRestrictedWindow; - formStateEx[FormStateExShowIcon] = 1; SetState(STATE_VISIBLE, false); @@ -357,58 +291,56 @@ public IButtonControl AcceptButton { } /// - /// Retrieves true if this form is currently active. + /// Retrieves true if this form is currently active. /// - internal bool Active { - get { + internal bool Active + { + get + { Form parentForm = ParentFormInternal; - if (parentForm == null) { + if (parentForm == null) + { return formState[FormStateIsActive] != 0; } - return(parentForm.ActiveControl == this && parentForm.Active); - } - set { + return parentForm.ActiveControl == this && parentForm.Active; + } + set + { Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "Form::set_Active - " + this.Name); - if ((formState[FormStateIsActive] != 0) != value) { - if (value) { - // There is a weird user32 - - - - if (!CanRecreateHandle()){ - //Debug.Fail("Setting Active window when not yet visible"); + if ((formState[FormStateIsActive] != 0) != value) + { + if (value) + { + if (!CanRecreateHandle()) + { return; } } formState[FormStateIsActive] = value ? 1 : 0; - if (value) { + if (value) + { formState[FormStateIsWindowActivated] = 1; - if (IsRestrictedWindow) { - WindowText = userWindowText; - } + // Check if validation has been cancelled to avoid raising Validation event multiple times. - if (!ValidationCancelled) { - if( ActiveControl == null ) { - // Security reviewed : This internal method is called from various places, all - // of which are OK. Since SelectNextControl (a public function) - // Demands ModifyFocus, we must call the internal version. - // - SelectNextControlInternal(null, true, true, true, false); + if (!ValidationCancelled) + { + if (ActiveControl == null) + { // If no control is selected focus will go to form + SelectNextControlInternal(null, true, true, true, false); } InnerMostActiveContainerControl.FocusActiveControlInternal(); } + OnActivated(EventArgs.Empty); - } - else { + } + else + { formState[FormStateIsWindowActivated] = 0; - if (IsRestrictedWindow) { - Text = userWindowText; - } OnDeactivate(EventArgs.Empty); } } @@ -456,7 +388,7 @@ public Form ActiveMdiChild { if( mdiChild == null ){ // If this.MdiClient != null it means this.IsMdiContainer == true. if( this.ctlClient != null && this.ctlClient.IsHandleCreated){ - IntPtr hwnd = this.ctlClient.SendMessage(NativeMethods.WM_MDIGETACTIVE, 0, 0); + IntPtr hwnd = this.ctlClient.SendMessage(Interop.WindowMessages.WM_MDIGETACTIVE, 0, 0); mdiChild = Control.FromHandleInternal( hwnd ) as Form; } } @@ -802,63 +734,26 @@ private bool CalledOnLoad { } } - - /// /// - /// - /// Gets or sets the border style of the form. - /// + /// Gets or sets the border style of the form. /// - [ - SRCategory(nameof(SR.CatAppearance)), - DefaultValue(FormBorderStyle.Sizable), - DispId(NativeMethods.ActiveX.DISPID_BORDERSTYLE), - SRDescription(nameof(SR.FormBorderStyleDescr)) - ] - public FormBorderStyle FormBorderStyle { - get { - return(FormBorderStyle)formState[FormStateBorderStyle]; - } - - set { - //validate FormBorderStyle enum - // - //valid values are 0x0 to 0x6 + [SRCategory(nameof(SR.CatAppearance))] + [DefaultValue(FormBorderStyle.Sizable)] + [DispId(NativeMethods.ActiveX.DISPID_BORDERSTYLE)] + [SRDescription(nameof(SR.FormBorderStyleDescr))] + public FormBorderStyle FormBorderStyle + { + get => (FormBorderStyle)formState[FormStateBorderStyle]; + set + { if (!ClientUtils.IsEnumValid(value, (int)value, (int)FormBorderStyle.None, (int)FormBorderStyle.SizableToolWindow)) { throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(FormBorderStyle)); } - // In rectricted mode we don't allow windows w/o min/max/close functionality. - if (IsRestrictedWindow) { - switch (value) { - case FormBorderStyle.None: - value = FormBorderStyle.FixedSingle; - break; - case FormBorderStyle.FixedSingle: - case FormBorderStyle.Fixed3D: - case FormBorderStyle.FixedDialog: - case FormBorderStyle.Sizable: - // nothing needed here, we can just let these stay - // - break; - case FormBorderStyle.FixedToolWindow: - value = FormBorderStyle.FixedSingle; - break; - case FormBorderStyle.SizableToolWindow: - value = FormBorderStyle.Sizable; - break; - default: - value = FormBorderStyle.Sizable; - break; - } - } - formState[FormStateBorderStyle] = (int)value; - - //( - - if (formState[FormStateSetClientSize] == 1 && !IsHandleCreated) { + if (formState[FormStateSetClientSize] == 1 && !IsHandleCreated) + { ClientSize = ClientSize; } @@ -870,7 +765,7 @@ public FormBorderStyle FormBorderStyle { // these existing values from being lost. Then, if the WindowState is something other than // FormWindowState.Normal after the call to UpdateFormStyles(), restore these cached values to // the restoredWindowBounds field. - Rectangle preClientUpdateRestoredWindowBounds = restoredWindowBounds; + Rectangle preClientUpdateRestoredWindowBounds = restoredWindowBounds; BoundsSpecified preClientUpdateRestoredWindowBoundsSpecified = restoredWindowBoundsSpecified; int preWindowBoundsWidthIsClientSize = formStateEx[FormStateExWindowBoundsWidthIsClientSize]; int preWindowBoundsHeightIsClientSize = formStateEx[FormStateExWindowBoundsHeightIsClientSize]; @@ -880,12 +775,14 @@ public FormBorderStyle FormBorderStyle { // In Windows XP Theme, the FixedDialog tend to have a small Icon. // So to make this behave uniformly with other styles, we need to make // the call to UpdateIcon after the the form styles have been updated. - if (formState[FormStateIconSet] == 0 && !IsRestrictedWindow) { + if (formState[FormStateIconSet] == 0) + { UpdateWindowIcon(false); } // Now restore the values cached above. - if (WindowState != FormWindowState.Normal) { + if (WindowState != FormWindowState.Normal) + { restoredWindowBounds = preClientUpdateRestoredWindowBounds; restoredWindowBoundsSpecified = preClientUpdateRestoredWindowBoundsSpecified; formStateEx[FormStateExWindowBoundsWidthIsClientSize] = preWindowBoundsWidthIsClientSize; @@ -937,33 +834,19 @@ public IButtonControl CancelButton { } } - /// /// - /// Gets or sets a value indicating whether a control box is displayed in the - /// caption bar of the form. + /// Gets or sets a value indicating whether a control box is displayed in the + /// caption bar of the form. /// - [ - SRCategory(nameof(SR.CatWindowStyle)), - DefaultValue(true), - SRDescription(nameof(SR.FormControlBoxDescr)) - ] - public bool ControlBox { - get { - return formState[FormStateControlBox] != 0; - } - - set { - // Window style in restricted mode must always have a control box. - if (IsRestrictedWindow) { - return; - } - - if (value) { - formState[FormStateControlBox] = 1; - } - else { - formState[FormStateControlBox] = 0; - } + [SRCategory(nameof(SR.CatWindowStyle))] + [DefaultValue(true)] + [SRDescription(nameof(SR.FormControlBoxDescr))] + public bool ControlBox + { + get => formState[FormStateControlBox] != 0; + set + { + formState[FormStateControlBox] = value ? 1 : 0; UpdateFormStyles(); } } @@ -1052,10 +935,6 @@ protected override CreateParams CreateParams { } } - if (IsRestrictedWindow) { - cp.Caption = RestrictedWindowText(cp.Caption); - } - if (RightToLeft == RightToLeft.Yes && RightToLeftLayout == true) { //We want to turn on mirroring for Form explicitly. cp.ExStyle |= NativeMethods.WS_EX_LAYOUTRTL | NativeMethods.WS_EX_NOINHERITLAYOUT; @@ -1083,7 +962,7 @@ internal static Icon DefaultIcon { // race condition. // if (defaultIcon == null) { - defaultIcon = new Icon(typeof(Form), "wfc.ico"); + defaultIcon = new Icon(typeof(Form), "wfc"); } } } @@ -1098,33 +977,6 @@ protected override ImeMode DefaultImeMode { } } - /// - /// The default icon used by the Form. This is the standard "windows forms" icon. - /// - private static Icon DefaultRestrictedIcon { - get { - // Note: We do this as a static property to allow delay - // loading of the resource. There are some issues with doing - // an OleInitialize from a static constructor... - // - - // Avoid locking if the value is filled in... - // - if (defaultRestrictedIcon == null) { - lock (internalSyncObject) - { - // Once we grab the lock, we re-check the value to avoid a - // race condition. - // - if (defaultRestrictedIcon == null) { - defaultRestrictedIcon = new Icon(typeof(Form), "wfsecurity.ico"); - } - } - } - return defaultRestrictedIcon; - } - } - /// /// /// Deriving classes can override this to configure a default size for their control. @@ -1269,49 +1121,41 @@ public event CancelEventHandler HelpButtonClicked { } } - /// /// - /// - /// Gets or sets the icon for the form. - /// + /// Gets or sets the icon for the form. /// - [ - AmbientValue(null), - Localizable(true), - SRCategory(nameof(SR.CatWindowStyle)), - SRDescription(nameof(SR.FormIconDescr)) - ] - public Icon Icon { - get { - if (formState[FormStateIconSet] == 0) { - // In restricted mode, the security icon cannot be changed. - if (IsRestrictedWindow) { - return DefaultRestrictedIcon; - } - else { - return DefaultIcon; - } + [AmbientValue(null)] + [Localizable(true)] + [SRCategory(nameof(SR.CatWindowStyle))] + [SRDescription(nameof(SR.FormIconDescr))] + public Icon Icon + { + get + { + if (formState[FormStateIconSet] == 0) + { + return DefaultIcon; } return icon; } - - set { - if (icon != value && !IsRestrictedWindow) { - - // If the user is poking the default back in, - // treat this as a null (reset). - // - if (value == defaultIcon) { + set + { + if (icon != value) + { + // If the user is setting the default back in, treat this + // as a reset. + if (value == defaultIcon) + { value = null; } - // And if null is passed, reset the icon. - // - formState[FormStateIconSet] = (value == null ? 0 : 1); - this.icon = value; + // If null is passed, reset the icon. + formState[FormStateIconSet] = value == null ? 0 : 1; + icon = value; - if (smallIcon != null) { + if (smallIcon != null) + { smallIcon.Dispose(); smallIcon = null; } @@ -1415,32 +1259,13 @@ public bool IsMdiContainer { } } - /// - /// /// - /// Determines if this form should display a warning banner - /// when the form is displayed in an unsecure mode. + /// Determines if this form should display a warning banner when the form is + /// displayed in an unsecure mode. /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)] - public bool IsRestrictedWindow { - get { - /// - if (formState[FormStateIsRestrictedWindowChecked] == 0) { - formState[FormStateIsRestrictedWindow] = 0; -#if DEBUG - if (AlwaysRestrictWindows.Enabled) { - formState[FormStateIsRestrictedWindow] = 1; - formState[FormStateIsRestrictedWindowChecked] = 1; - return true; - } -#endif - - formState[FormStateIsRestrictedWindowChecked] = 1; - } - - return formState[FormStateIsRestrictedWindow] != 0; - } - } + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Advanced)] + public bool IsRestrictedWindow => false; /// /// @@ -1493,7 +1318,7 @@ public bool KeyPreview { /// protected Rectangle MaximizedBounds { get { - return Properties.GetRectangle(PropMaximizedBounds); + return Properties.GetRectangle(PropMaximizedBounds, out _); } set { if (!value.Equals( MaximizedBounds )) { @@ -1673,62 +1498,63 @@ public MainMenu Menu { } } - /// /// - /// - /// Gets the minimum size the form can be resized to. - /// + /// Gets the minimum size the form can be resized to. /// - [ - SRCategory(nameof(SR.CatLayout)), - Localizable(true), - SRDescription(nameof(SR.FormMinimumSizeDescr)), - RefreshProperties(RefreshProperties.Repaint), - ] - public override Size MinimumSize { - get { - if (Properties.ContainsInteger(PropMinTrackSizeWidth)) { + [SRCategory(nameof(SR.CatLayout))] + [Localizable(true)] + [SRDescription(nameof(SR.FormMinimumSizeDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public override Size MinimumSize + { + get + { + if (Properties.ContainsInteger(PropMinTrackSizeWidth)) + { return new Size(Properties.GetInteger(PropMinTrackSizeWidth), Properties.GetInteger(PropMinTrackSizeHeight)); } + return DefaultMinimumSize; } - set { - if (!value.Equals( MinimumSize )) { - - if (value.Width < 0 || value.Height < 0 ) { + set + { + if (!value.Equals(MinimumSize)) + { + if (value.Width < 0 || value.Height < 0) + { throw new ArgumentOutOfRangeException(nameof(MinimumSize)); } - // ensure that the size we've applied fits into the screen - // when IsRestrictedWindow. Rectangle bounds = this.Bounds; - bounds.Size = value; + bounds.Size = value; value = WindowsFormsUtils.ConstrainToScreenWorkingAreaBounds(bounds).Size; Properties.SetInteger(PropMinTrackSizeWidth, value.Width); Properties.SetInteger(PropMinTrackSizeHeight, value.Height); // Bump maximum size if necessary - // - if (!MaximumSize.IsEmpty && !value.IsEmpty) { - - if (Properties.GetInteger(PropMaxTrackSizeWidth) < value.Width) { + if (!MaximumSize.IsEmpty && !value.IsEmpty) + { + if (Properties.GetInteger(PropMaxTrackSizeWidth) < value.Width) + { Properties.SetInteger(PropMaxTrackSizeWidth, value.Width); } - if (Properties.GetInteger(PropMaxTrackSizeHeight) < value.Height) { + if (Properties.GetInteger(PropMaxTrackSizeHeight) < value.Height) + { Properties.SetInteger(PropMaxTrackSizeHeight, value.Height); } } // Keep form size within new limits - // Size size = Size; - if (size.Width < value.Width || size.Height < value.Height) { + if (size.Width < value.Width || size.Height < value.Height) + { Size = new Size(Math.Max(size.Width, value.Width), Math.Max(size.Height, value.Height)); } - if (IsHandleCreated) { + if (IsHandleCreated) + { // "Move" the form to the same size and position to prevent windows from moving it // when the user tries to grab a resizing border. SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), NativeMethods.NullHandleRef, @@ -1839,41 +1665,47 @@ public Form MdiParent { } } - private Form MdiParentInternal { - get { - return (Form)Properties.GetObject(PropFormMdiParent); - } - set { + private Form MdiParentInternal + { + get => (Form)Properties.GetObject(PropFormMdiParent); + set + { Form formMdiParent = (Form)Properties.GetObject(PropFormMdiParent); - if (value == formMdiParent && (value != null || ParentInternal == null)) { + if (value == formMdiParent && (value != null || ParentInternal == null)) + { return; } - if (value != null && this.CreateThreadId != value.CreateThreadId) { - throw new ArgumentException(SR.AddDifferentThreads, "value"); + if (value != null && CreateThreadId != value.CreateThreadId) + { + throw new ArgumentException(SR.AddDifferentThreads, nameof(value)); } bool oldVisibleBit = GetState(STATE_VISIBLE); - // Visible = false; - try { - if (value == null) { + try + { + if (value == null) + { ParentInternal = null; - // Not calling SetTopLevelInternal so that IntSecurity.TopLevelWindow.Demand() isn't skipped. SetTopLevel(true); } - else { - if (IsMdiContainer) { - throw new ArgumentException(SR.FormMDIParentAndChild, "value"); + else + { + if (IsMdiContainer) + { + throw new ArgumentException(SR.FormMDIParentAndChild, nameof(value)); } - if (!value.IsMdiContainer) { - throw new ArgumentException(SR.MDIParentNotContainer, "value"); + if (!value.IsMdiContainer) + { + throw new ArgumentException(SR.MDIParentNotContainer, nameof(value)); } // Setting TopLevel forces a handle recreate before Parent is set, - // which causes problems because we try to assign an MDI child to the parking window, - // which can't take MDI children. So we explicitly destroy and create the handle here. + // which causes problems because we try to assign an MDI child to the + // parking window, which can't take MDI children. We explicitly destroy + // and create the handle here. Dock = DockStyle.None; Properties.SetObject(PropFormMdiParent, value); @@ -1886,15 +1718,18 @@ private Form MdiParentInternal { // when MdiChild's visibility is set to true (see // But if the handle has already been created, we need to destroy it - // so the form gets MDI-parented properly. See - if (ParentInternal.IsHandleCreated && IsMdiChild && IsHandleCreated) { + // so the form gets MDI-parented properly. + if (ParentInternal.IsHandleCreated && IsMdiChild && IsHandleCreated) + { DestroyHandle(); } } + InvalidateMergedMenu(); UpdateMenuHandles(); } - finally { + finally + { UpdateStyles(); Visible = oldVisibleBit; } @@ -1997,38 +1832,34 @@ public bool Modal { } } - /// /// - /// Determines the opacity of the form. This can only be set on top level - /// controls. Opacity requires Windows 2000 or later, and is ignored on earlier - /// operating systems. + /// Determines the opacity of the form. This can only be set on top level controls. + /// Opacity requires Windows 2000 or later, and is ignored on earlier operating systems. /// - [ - SRCategory(nameof(SR.CatWindowStyle)), - TypeConverterAttribute(typeof(OpacityConverter)), - SRDescription(nameof(SR.FormOpacityDescr)), - DefaultValue(1.0) - ] - public double Opacity { - get { + [SRCategory(nameof(SR.CatWindowStyle))] + [TypeConverterAttribute(typeof(OpacityConverter))] + [SRDescription(nameof(SR.FormOpacityDescr))] + [DefaultValue(1.0)] + public double Opacity + { + get + { object opacity = Properties.GetObject(PropOpacity); - if (opacity != null) { + if (opacity != null) + { return Convert.ToDouble(opacity, CultureInfo.InvariantCulture); } - else { - return 1.0f; - } + + return 1.0f; } - set { - // In restricted mode a form cannot be made less visible than 50% opacity. - if (IsRestrictedWindow) { - value = Math.Max(value, .50f); - } - - if (value > 1.0) { + set + { + if (value > 1.0) + { value = 1.0f; } - else if (value < 0.0) { + else if (value < 0.0) + { value = 0.0f; } @@ -2039,19 +1870,24 @@ public double Opacity { if (OpacityAsByte < 255 && OSFeature.Feature.IsPresent(OSFeature.LayeredWindows)) { AllowTransparency = true; - if (formState[FormStateLayered] != 1) { + if (formState[FormStateLayered] != 1) + { formState[FormStateLayered] = 1; - if (!oldLayered) { + if (!oldLayered) + { UpdateStyles(); } } } - else { + else + { formState[FormStateLayered] = (this.TransparencyKey != Color.Empty) ? 1 : 0; - if (oldLayered != (formState[FormStateLayered] != 0)) { + if (oldLayered != (formState[FormStateLayered] != 0)) + { int exStyle = unchecked((int)(long)UnsafeNativeMethods.GetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_EXSTYLE)); CreateParams cp = CreateParams; - if (exStyle != cp.ExStyle) { + if (exStyle != cp.ExStyle) + { UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_EXSTYLE, new HandleRef(null, (IntPtr)cp.ExStyle)); } } @@ -2203,34 +2039,22 @@ internal override Control ParentInternal { } } - /// /// - /// If ShowInTaskbar is true then the form will be displayed - /// in the Windows Taskbar. + /// If ShowInTaskbar is true then the form will be displayed in the Windows Taskbar. /// - [ - DefaultValue(true), - SRCategory(nameof(SR.CatWindowStyle)), - SRDescription(nameof(SR.FormShowInTaskbarDescr)) - ] - public bool ShowInTaskbar { - get { - return formState[FormStateTaskBar] != 0; - } - set { - // Restricted windows must always show in task bar. - if (IsRestrictedWindow) { - return; - } - - if (ShowInTaskbar != value) { - if (value) { - formState[FormStateTaskBar] = 1; - } - else { - formState[FormStateTaskBar] = 0; - } - if (IsHandleCreated) { + [DefaultValue(true)] + [SRCategory(nameof(SR.CatWindowStyle))] + [SRDescription(nameof(SR.FormShowInTaskbarDescr))] + public bool ShowInTaskbar + { + get => formState[FormStateTaskBar] != 0; + set + { + if (ShowInTaskbar != value) + { + formState[FormStateTaskBar] = value ? 1 : 0; + if (IsHandleCreated) + { RecreateHandle(); } } @@ -2238,33 +2062,25 @@ public bool ShowInTaskbar { } /// - /// Gets or sets a value indicating whether an icon is displayed in the - /// caption bar of the form. - /// If ControlBox == false, then the icon won't be shown no matter what - /// the value of ShowIcon is + /// Gets or sets a value indicating whether an icon is displayed in the + /// caption bar of the form. + /// If ControlBox == false, then the icon won't be shown no matter what + /// the value of ShowIcon is /// - [ - DefaultValue(true), - SRCategory(nameof(SR.CatWindowStyle)), - SRDescription(nameof(SR.FormShowIconDescr)) - ] - public bool ShowIcon { - get { - return formStateEx[FormStateExShowIcon] != 0; - } - - set { - if (value) { - formStateEx[FormStateExShowIcon] = 1; - } - else { - // The icon must always be shown for restricted forms. - if (IsRestrictedWindow) { - return; - } - formStateEx[FormStateExShowIcon] = 0; + [DefaultValue(true)] + [SRCategory(nameof(SR.CatWindowStyle))] + [SRDescription(nameof(SR.FormShowIconDescr))] + public bool ShowIcon + { + get => formStateEx[FormStateExShowIcon] != 0; + set + { + formStateEx[FormStateExShowIcon] = value ? 1 : 0; + if (value) + { UpdateStyles(); } + UpdateWindowIcon(true); } } @@ -2497,38 +2313,26 @@ public bool TopLevel { } } - /// /// - /// Gets or sets a value indicating whether the form should be displayed as the top-most - /// form of your application. + /// Gets or sets a value indicating whether the form should be displayed as the + /// top-most form of the application. /// - [ - DefaultValue(false), - SRCategory(nameof(SR.CatWindowStyle)), - SRDescription(nameof(SR.FormTopMostDescr)) - ] - public bool TopMost { - get { - return formState[FormStateTopMost] != 0; - } - set { - // Restricted windows cannot be top most to avoid DOS attack by obscuring other windows. - if (IsRestrictedWindow) { - return; - } - - if (IsHandleCreated && TopLevel) { + [DefaultValue(false)] + [SRCategory(nameof(SR.CatWindowStyle))] + [SRDescription(nameof(SR.FormTopMostDescr))] + public bool TopMost + { + get => formState[FormStateTopMost] != 0; + set + { + if (IsHandleCreated && TopLevel) + { HandleRef key = value ? NativeMethods.HWND_TOPMOST : NativeMethods.HWND_NOTOPMOST; SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), key, 0, 0, 0, 0, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE); } - if (value) { - formState[FormStateTopMost] = 1; - } - else { - formState[FormStateTopMost] = 0; - } + formState[FormStateTopMost] = value ? 1 : 0; } } @@ -2612,9 +2416,6 @@ protected override void SetVisibleCore(bool value) { } } } - else { - ResetSecurityTip(true /* modalOnly */); - } if (!IsMdiChild) { base.SetVisibleCore(value); @@ -2625,7 +2426,7 @@ protected override void SetVisibleCore(bool value) { // when WM_SHOWWINDOW gets called, we'll flip this bit to true // if (0==formState[FormStateSWCalled]) { - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.WM_SHOWWINDOW, value ? 1 : 0, 0); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_SHOWWINDOW, value ? 1 : 0, 0); } } else { @@ -2683,41 +2484,25 @@ protected override void SetVisibleCore(bool value) { } } - /// /// - /// Gets or sets the form's window state. - /// + /// Gets or sets the form's window state. /// - [ - SRCategory(nameof(SR.CatLayout)), - DefaultValue(FormWindowState.Normal), - SRDescription(nameof(SR.FormWindowStateDescr)) - ] - public FormWindowState WindowState { - get { - return(FormWindowState)formState[FormStateWindowState]; - } - set { - - //verify that 'value' is a valid enum type... - //valid values are 0x0 to 0x2 + [SRCategory(nameof(SR.CatLayout))] + [DefaultValue(FormWindowState.Normal)] + [SRDescription(nameof(SR.FormWindowStateDescr))] + public FormWindowState WindowState + { + get => (FormWindowState)formState[FormStateWindowState]; + set + { if (!ClientUtils.IsEnumValid(value, (int)value, (int)FormWindowState.Normal, (int)FormWindowState.Maximized)) { throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(FormWindowState)); } - if (TopLevel && IsRestrictedWindow) { - // We don't allow to minimize or maximze a top level window programatically if it is restricted. - // When maximized, the desktop is obscured by the window (DOS attack) and when minimize spoofing - // identity is the thread, the minimized window could steal the user's keystrokes and obtain a - // password for instance. - if (value != FormWindowState.Normal) { - return; - } - } - - switch (value) { - case FormWindowState.Normal: + switch (value) + { + case FormWindowState.Normal: SetState(STATE_SIZELOCKEDBYOS, false); break; case FormWindowState.Maximized: @@ -2726,9 +2511,11 @@ public FormWindowState WindowState { break; } - if (IsHandleCreated && Visible) { + if (IsHandleCreated && Visible) + { IntPtr hWnd = Handle; - switch (value) { + switch (value) + { case FormWindowState.Normal: SafeNativeMethods.ShowWindow(new HandleRef(this, hWnd), NativeMethods.SW_NORMAL); break; @@ -2748,48 +2535,26 @@ public FormWindowState WindowState { } } - /// /// - /// - /// Gets or sets the text to display in the caption bar of the form. - /// + /// Gets or sets the text to display in the caption bar of the form. /// - internal override string WindowText { - get { - // In restricted mode, the windows caption (Text) is modified to show the url of the window. - // The userWindowText is used to cache the user's text. - if (IsRestrictedWindow && formState[FormStateIsWindowActivated] == 1) { - if (userWindowText == null) { - return ""; - } - return userWindowText; - } - - return base.WindowText; - - } - - set { - string oldText = this.WindowText; - - userWindowText = value; - - if (IsRestrictedWindow && formState[FormStateIsWindowActivated] == 1) { - if (value == null) { - value = ""; - } - base.WindowText = RestrictedWindowText(value); - } - else { - base.WindowText = value; - } - - // For non-default FormBorderStyles, we do not set the WS_CAPTION style if the Text property is null or "". - // When we reload the form from code view, the text property is not set till the very end, and so we do not - // end up updating the CreateParams with WS_CAPTION. Fixed this by making sure we call UpdateStyles() when - // we transition from a non-null value to a null value or vice versa in Form.WindowText. - // - if (oldText == null || (oldText.Length == 0)|| value == null || (value.Length == 0)) { + internal override string WindowText + { + get => base.WindowText; + set + { + string oldText = WindowText; + base.WindowText = value; + + // For non-default FormBorderStyles, we do not set the WS_CAPTION style if + // the Text property is null or "". + // When we reload the form from code view, the text property is not set till + // the very end, and so we do not end up updating the CreateParams with + // WS_CAPTION. Fixed this by making sure we call UpdateStyles() when + // we transition from a non-null value to a null value or vice versa in + // Form.WindowText. + if (string.IsNullOrEmpty(oldText) || string.IsNullOrEmpty(value)) + { UpdateFormStyles(); } } @@ -3023,7 +2788,7 @@ public event EventHandler Shown { public void Activate() { if (Visible && IsHandleCreated) { if (IsMdiChild) { - MdiParentInternal.MdiClient.SendMessage(NativeMethods.WM_MDIACTIVATE, Handle, 0); + MdiParentInternal.MdiClient.SendMessage(Interop.WindowMessages.WM_MDIACTIVATE, Handle, 0); } else { UnsafeNativeMethods.SetForegroundWindow(new HandleRef(this, Handle)); @@ -3031,43 +2796,37 @@ public void Activate() { } } - /// - /// - /// - /// This function handles the activation of a MDI child form. If a subclass - /// overrides this function, it must call base.ActivateMdiChild. - /// From MSDN: This member supports the .NET Framework infrastructure and is not intended - /// to be used directly from your code. - /// - protected void ActivateMdiChild(Form form) { - ActivateMdiChildInternal(form); - } - - // SECURITY WARNING: This method bypasses a security demand. Use with caution! - private void ActivateMdiChildInternal(Form form) { - if (FormerlyActiveMdiChild != null && !FormerlyActiveMdiChild.IsClosing) { + protected void ActivateMdiChild(Form form) + { + if (FormerlyActiveMdiChild != null && !FormerlyActiveMdiChild.IsClosing) + { FormerlyActiveMdiChild.UpdateWindowIcon(true); FormerlyActiveMdiChild = null; } Form activeMdiChild = ActiveMdiChildInternal; - if (activeMdiChild == form) { + if (activeMdiChild == form) + { return; } - //Don't believe we ever hit this with non-null, but leaving it intact in case removing it would cause a problem. - if (null != activeMdiChild) { + // Don't believe we ever hit this with non-null, but leaving it intact in + // case removing it would cause a problem. + if (activeMdiChild != null) + { activeMdiChild.Active = false; } activeMdiChild = form; ActiveMdiChildInternal = form; - if (null != activeMdiChild) { + if (activeMdiChild != null) + { activeMdiChild.IsMdiChildFocusable = true; activeMdiChild.Active = true; } - else if (this.Active) { + else if (Active) + { ActivateControlInternal(this); } @@ -3218,56 +2977,8 @@ private void AdjustSystemMenu(IntPtr hmenu) { UnsafeNativeMethods.EnableMenuItem(new HandleRef(this, hmenu), NativeMethods.SC_SIZE, NativeMethods.MF_BYCOMMAND | NativeMethods.MF_ENABLED); } - -#if SECURITY_DIALOG - AdjustSystemMenuForSecurity(hmenu); -#endif } -#if SECURITY_DIALOG - private void AdjustSystemMenuForSecurity(IntPtr hmenu) { - if (formState[FormStateAddedSecurityMenuItem] == 0) { - formState[FormStateAddedSecurityMenuItem] = 1; - - SecurityMenuItem securitySystemMenuItem = new SecurityMenuItem(this); - Properties.SetObject(PropSecuritySystemMenuItem, securitySystemMenuItem); - - NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); - info.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | - NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE | NativeMethods.MIIM_DATA; - info.fType = 0; - info.fState = 0; - info.wID = securitySystemMenuItem.ID; - info.hbmpChecked = IntPtr.Zero; - info.hbmpUnchecked = IntPtr.Zero; - info.dwItemData = IntPtr.Zero; - - // Note: This code is not shipping in the final product. We do not want to measure the - // : performance hit of loading the localized resource for this at startup, so I - // : am hard-wiring the strings below. If you need to localize these, move them to - // : a SECONDARY resource file so we don't have to contend with our big error message - // : file on startup. - // - if (IsRestrictedWindow) { - info.dwTypeData = ".NET Restricted Window..."; - } - else { - info.dwTypeData = ".NET Window..."; - } - info.cch = 0; - UnsafeNativeMethods.InsertMenuItem(new HandleRef(this, hmenu), 0, true, info); - - - NativeMethods.MENUITEMINFO_T sep = new NativeMethods.MENUITEMINFO_T(); - sep.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | - NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE | NativeMethods.MIIM_DATA; - sep.fType = NativeMethods.MFT_MENUBREAK; - UnsafeNativeMethods.InsertMenuItem(new HandleRef(this, hmenu), 1, true, sep); - - } - } -#endif - /// /// This forces the SystemMenu to look like we want. /// @@ -3502,7 +3213,7 @@ public void Close() { if (IsHandleCreated) { closeReason = CloseReason.UserClosing; - SendMessage(NativeMethods.WM_CLOSE, 0, 0); + SendMessage(Interop.WindowMessages.WM_CLOSE, 0, 0); } else{ // MSDN: When a form is closed, all resources created within the object are closed and the form is disposed. @@ -3634,7 +3345,7 @@ protected override void CreateHandle() { // reflects the real icon of the application Icon icon = Icon; if (icon != null && TaskbarOwner.Handle != IntPtr.Zero) { - UnsafeNativeMethods.SendMessage(TaskbarOwner, NativeMethods.WM_SETICON, NativeMethods.ICON_BIG, icon.Handle); + UnsafeNativeMethods.SendMessage(TaskbarOwner, Interop.WindowMessages.WM_SETICON, NativeMethods.ICON_BIG, icon.Handle); } } @@ -3666,7 +3377,7 @@ private void DeactivateMdiChild() { if (!activeMdiChild.IsClosing) { FormerlyActiveMdiChild = activeMdiChild; } - // Enter/Leave events on child controls are raised from the ActivateMdiChildInternal method, usually when another + // Enter/Leave events on child controls are raised from the ActivateMdiChild method, usually when another // Mdi child is getting activated after deactivating this one; but if this is the only visible MDI child // we need to fake the activation call so MdiChildActivate and Leave events are raised properly. (We say // in the MSDN doc that the MdiChildActivate event is raised when an mdi child is activated or closed - @@ -3680,7 +3391,7 @@ private void DeactivateMdiChild() { } if( fakeActivation ){ - mdiParent.ActivateMdiChildInternal(null); + mdiParent.ActivateMdiChild(null); } ActiveMdiChildInternal = null; @@ -3771,8 +3482,6 @@ protected override void Dispose(bool disposing) { smallIcon = null; } - ResetSecurityTip(false /* modalOnly */); - base.Dispose(disposing); ctlClient = null; @@ -3812,65 +3521,67 @@ protected override void Dispose(bool disposing) { } /// - /// Adjusts the window style of the CreateParams to reflect the bordericons. + /// Adjusts the window style of the CreateParams to reflect the bordericons. /// - /// - private void FillInCreateParamsBorderIcons(CreateParams cp) { - if (FormBorderStyle != FormBorderStyle.None) { - if (Text != null && Text.Length != 0) { + private void FillInCreateParamsBorderIcons(CreateParams cp) + { + if (FormBorderStyle != FormBorderStyle.None) + { + if (!string.IsNullOrEmpty(Text)) + { cp.Style |= NativeMethods.WS_CAPTION; } - // In restricted mode, the form must have a system menu, caption and max/min/close boxes. - - if (ControlBox || IsRestrictedWindow) { + if (ControlBox) + { cp.Style |= NativeMethods.WS_SYSMENU | NativeMethods.WS_CAPTION; } - else { + else + { cp.Style &= (~NativeMethods.WS_SYSMENU); } - if (MaximizeBox || IsRestrictedWindow) { + if (MaximizeBox) + { cp.Style |= NativeMethods.WS_MAXIMIZEBOX; } - else { + else + { cp.Style &= ~NativeMethods.WS_MAXIMIZEBOX; } - if (MinimizeBox || IsRestrictedWindow) { + if (MinimizeBox) + { cp.Style |= NativeMethods.WS_MINIMIZEBOX; } - else { + else + { cp.Style &= ~NativeMethods.WS_MINIMIZEBOX; } - if (HelpButton && !MaximizeBox && !MinimizeBox && ControlBox) { + if (HelpButton && !MaximizeBox && !MinimizeBox && ControlBox) + { // Windows should ignore WS_EX_CONTEXTHELP unless all those conditions hold. // But someone must have failed the check, because Windows 2000 // will show a help button if either the maximize or // minimize button is disabled. cp.ExStyle |= NativeMethods.WS_EX_CONTEXTHELP; } - else { + else + { cp.ExStyle &= ~NativeMethods.WS_EX_CONTEXTHELP; } } } /// - /// Adjusts the window style of the CreateParams to reflect the borderstyle. + /// Adjusts the window style of the CreateParams to reflect the borderstyle. /// - private void FillInCreateParamsBorderStyles(CreateParams cp) { - switch ((FormBorderStyle)formState[FormStateBorderStyle]) { + private void FillInCreateParamsBorderStyles(CreateParams cp) + { + switch ((FormBorderStyle)formState[FormStateBorderStyle]) + { case FormBorderStyle.None: - // - - - - - if (IsRestrictedWindow) { - goto case FormBorderStyle.FixedSingle; - } break; case FormBorderStyle.FixedSingle: cp.Style |= NativeMethods.WS_BORDER; @@ -3898,26 +3609,23 @@ private void FillInCreateParamsBorderStyles(CreateParams cp) { } /// - /// Adjusts the CreateParams to reflect the window bounds and start position. + /// Adjusts the CreateParams to reflect the window bounds and start position. /// - private void FillInCreateParamsStartPosition(CreateParams cp) { - - if (formState[FormStateSetClientSize] != 0) { + private void FillInCreateParamsStartPosition(CreateParams cp) + { + if (formState[FormStateSetClientSize] != 0) + { // When computing the client window size, don't tell them that // we are going to be maximized! - // int maskedStyle = cp.Style & ~(NativeMethods.WS_MAXIMIZE | NativeMethods.WS_MINIMIZE); Size correct = ComputeWindowSize(ClientSize, maskedStyle, cp.ExStyle); - - if (IsRestrictedWindow) { - correct = ApplyBoundsConstraints(cp.X, cp.Y, correct.Width, correct.Height).Size; - } cp.Width = correct.Width; cp.Height = correct.Height; } - switch ((FormStartPosition)formState[FormStateStartPos]) { + switch ((FormStartPosition)formState[FormStateStartPos]) + { case FormStartPosition.WindowsDefaultBounds: cp.Width = NativeMethods.CW_USEDEFAULT; cp.Height = NativeMethods.CW_USEDEFAULT; @@ -3929,7 +3637,8 @@ private void FillInCreateParamsStartPosition(CreateParams cp) { // several times when a window is shown, we'll need to force the location // each time for MdiChild windows that are docked so that the window will // be created in the correct location and scroll bars will not be displayed. - if (IsMdiChild && DockStyle.None != Dock){ + if (IsMdiChild && DockStyle.None != Dock) + { break; } @@ -3937,49 +3646,48 @@ private void FillInCreateParamsStartPosition(CreateParams cp) { cp.Y = NativeMethods.CW_USEDEFAULT; break; case FormStartPosition.CenterScreen: - if (IsMdiChild) { + if (IsMdiChild) + { Control mdiclient = MdiParentInternal.MdiClient; Rectangle clientRect = mdiclient.ClientRectangle; - cp.X = Math.Max(clientRect.X,clientRect.X + (clientRect.Width - cp.Width)/2); - cp.Y = Math.Max(clientRect.Y,clientRect.Y + (clientRect.Height - cp.Height)/2); + cp.X = Math.Max(clientRect.X, clientRect.X + (clientRect.Width - cp.Width) / 2); + cp.Y = Math.Max(clientRect.Y, clientRect.Y + (clientRect.Height - cp.Height) / 2); } - else { + else + { Screen desktop = null; IWin32Window dialogOwner = (IWin32Window)Properties.GetObject(PropDialogOwner); - if ((OwnerInternal != null) || (dialogOwner != null)) { + if ((OwnerInternal != null) || (dialogOwner != null)) + { IntPtr ownerHandle = (dialogOwner != null) ? Control.GetSafeHandle(dialogOwner) : OwnerInternal.Handle; desktop = Screen.FromHandleInternal(ownerHandle); } - else { + else + { desktop = Screen.FromPoint(Control.MousePosition); } + Rectangle screenRect = desktop.WorkingArea; - //if, we're maximized, then don't set the x & y coordinates (they're @ (0,0) ) - if (WindowState != FormWindowState.Maximized) { - cp.X = Math.Max(screenRect.X,screenRect.X + (screenRect.Width - cp.Width)/2); - cp.Y = Math.Max(screenRect.Y,screenRect.Y + (screenRect.Height - cp.Height)/2); + // if, we're maximized, then don't set the x & y coordinates (they're @ (0,0) ) + if (WindowState != FormWindowState.Maximized) + { + cp.X = Math.Max(screenRect.X, screenRect.X + (screenRect.Width - cp.Width) / 2); + cp.Y = Math.Max(screenRect.Y, screenRect.Y + (screenRect.Height - cp.Height) / 2); } } + break; } } /// - /// Adjusts the Createparams to reflect the window state. + /// Adjusts the Createparams to reflect the window state. /// - private void FillInCreateParamsWindowState(CreateParams cp) { - // SECUNDONE: We don't need to check for restricted window here since the only way to set the WindowState - // programatically is by changing the property and we have a check for it in the property setter. - // We don't want to check it here again because it would not allow to set the CreateParams.Style - // to the current WindowState so the window will be set to its current Normal size - // (which in some cases is quite bogus) when Control.UpdateStylesCore is called. - // - // if( IsRestrictedWindow ){ - // return; - // } - - switch ((FormWindowState)formState[FormStateWindowState]) { + private void FillInCreateParamsWindowState(CreateParams cp) + { + switch ((FormWindowState)formState[FormStateWindowState]) + { case FormWindowState.Maximized: cp.Style |= NativeMethods.WS_MAXIMIZE; break; @@ -3990,16 +3698,16 @@ private void FillInCreateParamsWindowState(CreateParams cp) { } /// - /// Sets focus to the Form. - /// Attempts to set focus to this Form. + /// Attempts to set focus to this Form. /// - // SECURITY WARNING: This method bypasses a security demand. Use with caution! - internal override bool FocusInternal() { + internal override bool FocusInternal() + { Debug.Assert( IsHandleCreated, "Attempt to set focus to a form that has not yet created its handle." ); - //if this form is a MdiChild, then we need to set the focus in a different way... - // - if (IsMdiChild) { - MdiParentInternal.MdiClient.SendMessage(NativeMethods.WM_MDIACTIVATE, Handle, 0); + + // If this form is a MdiChild, then we need to set the focus differently. + if (IsMdiChild) + { + MdiParentInternal.MdiClient.SendMessage(Interop.WindowMessages.WM_MDIACTIVATE, Handle, 0); return Focused; } @@ -4046,213 +3754,49 @@ internal override Size GetPreferredSizeCore(Size proposedSize) { bool dialogFixRequired = false; - if (Padding == Padding.Empty) { - Padding paddingToAdd = Padding.Empty; - foreach (Control c in this.Controls) { - if (c.Dock == DockStyle.None) { - AnchorStyles anchor = c.Anchor; - if (anchor == AnchorStyles.None) { - break; - } - - // TOP - // if we are anchored to the top only add padding if the top edge is too far down - if ((paddingToAdd.Bottom == 0) && DefaultLayout.IsAnchored(anchor, AnchorStyles.Top)) { - if (c.Bottom > preferredSize.Height - FormPadding.Bottom) { - paddingToAdd.Bottom = FormPadding.Bottom; - - dialogFixRequired = true; - } - } - // BOTTOM - // if we are anchored to the bottom - // dont add any padding - it's way too confusing to be dragging a button up - // and have the form grow to the bottom. - - // LEFT - // if we are anchored to the left only add padding if the right edge is too far right - if ((paddingToAdd.Left == 0) && DefaultLayout.IsAnchored(anchor, AnchorStyles.Left)) { - if (c.Right > preferredSize.Width - FormPadding.Right) { - paddingToAdd.Right = FormPadding.Right; - dialogFixRequired = true; - } - } - // RIGHT - // if we are anchored to the bottom - // dont add any padding - it's way too confusing to be dragging a button left - // and have the form grow to the right - - } - } - Debug.Assert(!dialogFixRequired, "this dialog needs update: " + this.Name); - return preferredSize + paddingToAdd.Size; - } -#endif - return preferredSize; - } - - /// - /// This private method attempts to resolve security zone and site - /// information given a list of urls (sites). This list is supplied - /// by the runtime and will contain the paths of all loaded assemblies - /// on the stack. From here, we can examine zones and sites and - /// attempt to identify the unique and mixed scenarios for each. This - /// information will be displayed in the titlebar of the Form in a - /// semi-trust environment. - /// - private void ResolveZoneAndSiteNames(ArrayList sites, ref string securityZone, ref string securitySite) { - - //Start by defaulting to 'unknown zone' and 'unknown site' strings. We will return this - //information if anything goes wrong while trying to resolve this information. - // - securityZone = SR.SecurityRestrictedWindowTextUnknownZone; - securitySite = SR.SecurityRestrictedWindowTextUnknownSite; - - try - { - //these conditions must be met - // - if (sites == null || sites.Count == 0) - return; - - //create a new zone array list which has no duplicates and no - //instances of mycomputer - ArrayList zoneList = new ArrayList(); - foreach (object arrayElement in sites) - { - if (arrayElement == null) - return; - - string url = arrayElement.ToString(); - - if (url.Length == 0) - return; - - //into a zoneName - // - Zone currentZone = Zone.CreateFromUrl(url); - - //skip this if the zone is mycomputer - // - if (currentZone.SecurityZone.Equals(SecurityZone.MyComputer)) - continue; - - //add our unique zonename to our list of zones - // - string zoneName = currentZone.SecurityZone.ToString(); - - if (!zoneList.Contains(zoneName)) - { - zoneList.Add(zoneName); - } - } - - //now, we resolve the zone name based on the unique information - //left in the zoneList - // - if (zoneList.Count == 0) - { - //here, all the original zones were 'mycomputer' - //so we can just return that - securityZone = SecurityZone.MyComputer.ToString(); - } - else if (zoneList.Count == 1) - { - //we only found 1 unique zone other than - //mycomputer - securityZone = zoneList[0].ToString(); - } - else - { - //here, we found multiple zones - // - securityZone = SR.SecurityRestrictedWindowTextMixedZone; - } - - //generate a list of loaded assemblies that came from the gac, this - //way we can safely ignore these from the url list - ArrayList loadedAssembliesFromGac = new ArrayList(); - - foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) - { - if (asm.GlobalAssemblyCache) - { - loadedAssembliesFromGac.Add(asm.CodeBase.ToUpper(CultureInfo.InvariantCulture)); - } - } - - //now, build up a sitelist which contains a friendly string - //we've extracted via the uri class and omit any urls that reference - //our local gac - // - ArrayList siteList = new ArrayList(); - foreach (object arrayElement in sites) - { - //we know that each element is valid because of our - //first pass - Uri currentSite = new Uri(arrayElement.ToString()); - - //if we see a site that contains the path to our gac, - //we'll just skip it - - if (loadedAssembliesFromGac.Contains(currentSite.AbsoluteUri.ToUpper(CultureInfo.InvariantCulture))) - { - continue; - } - - //add the unique host name to our list - string hostName = currentSite.Host; - if (hostName.Length > 0 && !siteList.Contains(hostName)) - siteList.Add(hostName); - } - - - //resolve the site name from our list, if siteList.count == 0 - //then we have already set our securitySite to "unknown site" - // - if (siteList.Count == 0) { - //here, we'll set the local machine name to the site string - securitySite = Environment.MachineName; - } - else if (siteList.Count == 1) - { - //We found 1 unique site other than the info in the - //gac - securitySite = siteList[0].ToString(); - } - else - { - //multiple sites, we'll have to return 'mixed sites' - // - securitySite = SR.SecurityRestrictedWindowTextMultipleSites; - } - } - catch - { - //We'll do nothing here. The idea is that zone and security strings are set - //to "unkown" at the top of this method - if an exception is thrown, we'll - //stick with those values - } - } + if (Padding == Padding.Empty) { + Padding paddingToAdd = Padding.Empty; + foreach (Control c in this.Controls) { + if (c.Dock == DockStyle.None) { + AnchorStyles anchor = c.Anchor; + if (anchor == AnchorStyles.None) { + break; + } - /// - /// Sets the restricted window text (titlebar text of a form) when running - /// in a semi-trust environment. The format is: [zone info] - Form Text - [site info] - /// - private string RestrictedWindowText(string original) { - EnsureSecurityInformation(); - return string.Format(CultureInfo.CurrentCulture, Application.SafeTopLevelCaptionFormat, original, securityZone, securitySite); - } + // TOP + // if we are anchored to the top only add padding if the top edge is too far down + if ((paddingToAdd.Bottom == 0) && DefaultLayout.IsAnchored(anchor, AnchorStyles.Top)) { + if (c.Bottom > preferredSize.Height - FormPadding.Bottom) { + paddingToAdd.Bottom = FormPadding.Bottom; - private void EnsureSecurityInformation() { - if (securityZone == null || securitySite == null) { - ArrayList zones; - ArrayList sites; + dialogFixRequired = true; + } + } + // BOTTOM + // if we are anchored to the bottom + // dont add any padding - it's way too confusing to be dragging a button up + // and have the form grow to the bottom. - SecurityManager.GetZoneAndOrigin( out zones, out sites ); + // LEFT + // if we are anchored to the left only add padding if the right edge is too far right + if ((paddingToAdd.Left == 0) && DefaultLayout.IsAnchored(anchor, AnchorStyles.Left)) { + if (c.Right > preferredSize.Width - FormPadding.Right) { + paddingToAdd.Right = FormPadding.Right; + dialogFixRequired = true; + } + } + // RIGHT + // if we are anchored to the bottom + // dont add any padding - it's way too confusing to be dragging a button left + // and have the form grow to the right - ResolveZoneAndSiteNames(sites, ref securityZone, ref securitySite); + } + } + Debug.Assert(!dialogFixRequired, "this dialog needs update: " + this.Name); + return preferredSize + paddingToAdd.Size; } +#endif + return preferredSize; } private void CallShownEvent() @@ -4609,8 +4153,6 @@ protected override void OnEnabledChanged(EventArgs e) { // Make sure we activate the active control. Control activeControl = ActiveControl; - // Seems safe to call this here without demanding permissions, since we only - // get here if this form is enabled and active. if( activeControl == null ){ SelectNextControlInternal(this, true, true, true, true); } @@ -4652,27 +4194,19 @@ protected override void OnHandleCreated(EventArgs e) { UpdateLayered(); } - /// - /// /// - /// Inheriting classes should override this method to find out when the - /// handle is about to be destroyed. - /// Call base.OnHandleDestroyed last. + /// Inheriting classes should override this method to find out when the + /// handle is about to be destroyed. + /// Call base.OnHandleDestroyed last. /// [EditorBrowsable(EditorBrowsableState.Advanced)] - protected override void OnHandleDestroyed(EventArgs e) { + protected override void OnHandleDestroyed(EventArgs e) + { base.OnHandleDestroyed(e); formStateEx[FormStateExUseMdiChildProc] = 0; // just make sure we're no longer in the forms collection list Application.OpenFormsInternalRemove(this); - - // If the handle is being destroyed, and the security tip hasn't been dismissed - // then we remove it from the property bag. When we come back around and get - // an NCACTIVATE we will see that this is missing and recreate the security - // tip in it's default state. - // - ResetSecurityTip(true /* modalOnly */); } /// @@ -4891,19 +4425,14 @@ protected virtual void OnMdiChildActivate(EventArgs e) { if (handler != null) handler(this,e); } - /// /// - /// Raises the - /// event. + /// Raises the event. /// [EditorBrowsable(EditorBrowsableState.Advanced)] - protected virtual void OnMenuStart(EventArgs e) { - SecurityToolTip secTip = (SecurityToolTip)Properties.GetObject(PropSecurityTip); - if (secTip != null) { - secTip.Pop(true /*noLongerFirst*/); - } + protected virtual void OnMenuStart(EventArgs e) + { EventHandler handler = (EventHandler)Events[EVENT_MENUSTART]; - if (handler != null) handler(this,e); + handler?.Invoke(this,e); } /// @@ -5347,7 +4876,7 @@ internal override void RecreateHandleCore() { FormStartPosition oldStartPosition = FormStartPosition.Manual; if (!IsMdiChild && (WindowState == FormWindowState.Minimized || WindowState == FormWindowState.Maximized)) { - wp.length = Marshal.SizeOf(typeof(NativeMethods.WINDOWPLACEMENT)); + wp.length = Marshal.SizeOf(); UnsafeNativeMethods.GetWindowPlacement(new HandleRef(this, Handle), ref wp); } @@ -5448,17 +4977,6 @@ private void ResetIcon() { UpdateWindowIcon(true); } - void ResetSecurityTip(bool modalOnly) { - SecurityToolTip secTip = (SecurityToolTip)Properties.GetObject(PropSecurityTip); - if (secTip != null) { - if ((modalOnly && secTip.Modal) || !modalOnly) { - secTip.Dispose(); - secTip = null; - Properties.SetObject(PropSecurityTip, null); - } - } - } - /// /// Resets the TransparencyKey to Color.Empty. /// @@ -5529,34 +5047,6 @@ private void RestoreWindowBoundsIfNecessary() { } } - void RestrictedProcessNcActivate() { - Debug.Assert(IsRestrictedWindow, "This should only be called for restricted windows"); - - // Ignore if tearing down... - // - if (IsDisposed || Disposing) { - return; - } - - // Note that this.Handle does not get called when the handle hasn't been created yet - // - SecurityToolTip secTip = (SecurityToolTip)Properties.GetObject(PropSecurityTip); - if (secTip == null) { - if (IsHandleCreated && UnsafeNativeMethods.GetForegroundWindow() == this.Handle) { - secTip = new SecurityToolTip(this); - Properties.SetObject(PropSecurityTip, secTip); - } - } - else if (!IsHandleCreated || UnsafeNativeMethods.GetForegroundWindow() != this.Handle) - { - secTip.Pop(false /*noLongerFirst*/); - } - else - { - secTip.Show(); - } - } - /// /// Decrements updateMenuHandleSuspendCount. If updateMenuHandleSuspendCount /// becomes zero and updateMenuHandlesDeferred is true, updateMenuHandles @@ -5574,36 +5064,33 @@ private void ResumeUpdateMenuHandles() { } } - /// - /// - /// Selects this form, and optionally selects the next/previous control. - /// - protected override void Select(bool directed, bool forward) { - SelectInternal(directed, forward); - } - /// - /// Selects this form, and optionally selects the next/previous control. - /// Does the actual work without the security check. + /// Selects this form, and optionally selects the next/previous control. /// - // SECURITY WARNING: This method bypasses a security demand. Use with caution! - private void SelectInternal(bool directed, bool forward) { - if (directed) { + protected override void Select(bool directed, bool forward) + { + if (directed) + { SelectNextControl(null, forward, true, true, false); } - if (TopLevel) { + if (TopLevel) + { UnsafeNativeMethods.SetActiveWindow(new HandleRef(this, Handle)); } - else if (IsMdiChild) { + else if (IsMdiChild) + { UnsafeNativeMethods.SetActiveWindow(new HandleRef(MdiParentInternal, MdiParentInternal.Handle)); - MdiParentInternal.MdiClient.SendMessage(NativeMethods.WM_MDIACTIVATE, Handle, 0); + MdiParentInternal.MdiClient.SendMessage(Interop.WindowMessages.WM_MDIACTIVATE, Handle, 0); } - else { + else + { Form form = ParentFormInternal; - if (form != null) form.ActiveControl = this; + if (form != null) + { + form.ActiveControl = this; + } } - } /// @@ -5681,157 +5168,94 @@ protected override void ScaleControl(SizeF factor, BoundsSpecified specified) { } } - - /// - /// - /// [EditorBrowsable(EditorBrowsableState.Advanced)] - protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) { - - if (WindowState != FormWindowState.Normal) { + protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) + { + if (WindowState != FormWindowState.Normal) + { // See RestoreWindowBoundsIfNecessary for an explanation of this // Only restore position when x,y is not -1,-1 if (x != -1 || y != -1) { restoredWindowBoundsSpecified |= (specified & (BoundsSpecified.X | BoundsSpecified.Y)); } + restoredWindowBoundsSpecified |= (specified & (BoundsSpecified.Width | BoundsSpecified.Height)); if ((specified & BoundsSpecified.X) != 0) + { restoredWindowBounds.X = x; + } if ((specified & BoundsSpecified.Y) != 0) + { restoredWindowBounds.Y = y; - if ((specified & BoundsSpecified.Width) != 0) { + } + if ((specified & BoundsSpecified.Width) != 0) + { restoredWindowBounds.Width = width; formStateEx[FormStateExWindowBoundsWidthIsClientSize] = 0; } - if ((specified & BoundsSpecified.Height) != 0) { + if ((specified & BoundsSpecified.Height) != 0) + { restoredWindowBounds.Height = height; formStateEx[FormStateExWindowBoundsHeightIsClientSize] = 0; } } - //Update RestoreBounds + // Update RestoreBounds if ((specified & BoundsSpecified.X) != 0) + { restoreBounds.X = x; + } if ((specified & BoundsSpecified.Y) != 0) + { restoreBounds.Y = y; + } if ((specified & BoundsSpecified.Width) != 0 || restoreBounds.Width == -1) + { restoreBounds.Width = width; + } if ((specified & BoundsSpecified.Height) != 0 || restoreBounds.Height == -1) + { restoreBounds.Height = height; + } // Enforce maximum size... - // - if (WindowState == FormWindowState.Normal - && (this.Height != height || this.Width != width)) { - + if (WindowState == FormWindowState.Normal && (this.Height != height || this.Width != width)) + { Size max = SystemInformation.MaxWindowTrackSize; - if (height > max.Height) { + if (height > max.Height) + { height = max.Height; } - if (width > max.Width) { + if (width > max.Width) + { width = max.Width; } } // Only enforce the minimum size if the form has a border and is a top // level form. - // FormBorderStyle borderStyle = FormBorderStyle; if (borderStyle != FormBorderStyle.None && borderStyle != FormBorderStyle.FixedToolWindow && borderStyle != FormBorderStyle.SizableToolWindow - && ParentInternal == null) { - + && ParentInternal == null) + { Size min = SystemInformation.MinWindowTrackSize; - if (height < min.Height) { + if (height < min.Height) + { height = min.Height; } - if (width < min.Width) { + if (width < min.Width) + { width = min.Width; } } - if (IsRestrictedWindow) { - // Check to ensure that the title bar, and all corners of the window, are visible on a monitor - // - - Rectangle adjustedBounds = ApplyBoundsConstraints(x,y,width,height); - if (adjustedBounds != new Rectangle(x,y,width,height)) { - - // - - - - - base.SetBoundsCore(adjustedBounds.X, adjustedBounds.Y, adjustedBounds.Width, adjustedBounds.Height, BoundsSpecified.All); - return; - } - } - base.SetBoundsCore(x, y, width, height, specified); } - internal override Rectangle ApplyBoundsConstraints(int suggestedX, int suggestedY, int proposedWidth, int proposedHeight) { - // apply min/max size constraints - Rectangle adjustedBounds = base.ApplyBoundsConstraints(suggestedX, suggestedY, proposedWidth, proposedHeight); - // run through size restrictions in Internet. - if (IsRestrictedWindow) { - // Check to ensure that the title bar, and all corners of the window, are visible on a monitor - // - - Screen[] screens = Screen.AllScreens; - bool topLeft = false; - bool topRight = false; - bool bottomLeft = false; - bool bottomRight = false; - - for (int i=0; i /// Sets the defaultButton for the form. The defaultButton is "clicked" when /// the user presses Enter. @@ -5997,7 +5421,7 @@ public DialogResult ShowDialog(IWin32Window owner) { IntPtr hWndCapture = UnsafeNativeMethods.GetCapture(); if (hWndCapture != IntPtr.Zero) { - UnsafeNativeMethods.SendMessage(new HandleRef(null, hWndCapture), NativeMethods.WM_CANCELMODE, IntPtr.Zero, IntPtr.Zero); + UnsafeNativeMethods.SendMessage(new HandleRef(null, hWndCapture), Interop.WindowMessages.WM_CANCELMODE, IntPtr.Zero, IntPtr.Zero); SafeNativeMethods.ReleaseCapture(); } IntPtr hWndActive = UnsafeNativeMethods.GetActiveWindow(); @@ -6372,13 +5796,13 @@ private void UpdateMenuHandles(MainMenu menu, bool forceRedraw) { dummyMenu.ownerForm = this; Properties.SetObject(PropDummyMenu, dummyMenu); } - UnsafeNativeMethods.SendMessage(new HandleRef(ctlClient, ctlClient.Handle), NativeMethods.WM_MDISETMENU, dummyMenu.Handle, IntPtr.Zero); + UnsafeNativeMethods.SendMessage(new HandleRef(ctlClient, ctlClient.Handle), Interop.WindowMessages.WM_MDISETMENU, dummyMenu.Handle, IntPtr.Zero); if (menu != null) { // Microsoft, 5/2/1998 - don't use Win32 native Mdi lists... // - UnsafeNativeMethods.SendMessage(new HandleRef(ctlClient, ctlClient.Handle), NativeMethods.WM_MDISETMENU, menu.Handle, IntPtr.Zero); + UnsafeNativeMethods.SendMessage(new HandleRef(ctlClient, ctlClient.Handle), Interop.WindowMessages.WM_MDISETMENU, menu.Handle, IntPtr.Zero); } } @@ -6614,44 +6038,52 @@ protected override void OnStyleChanged(EventArgs e) { } /// - /// Updates the window icon. + /// Updates the window icon. /// - /// - private void UpdateWindowIcon(bool redrawFrame) { - if (IsHandleCreated) { + private void UpdateWindowIcon(bool redrawFrame) + { + if (IsHandleCreated) + { Icon icon; // Preserve Win32 behavior by keeping the icon we set NULL if // the user hasn't specified an icon and we are a dialog frame. - // - if ((FormBorderStyle == FormBorderStyle.FixedDialog && formState[FormStateIconSet] == 0 && !IsRestrictedWindow) || !ShowIcon) { + if ((FormBorderStyle == FormBorderStyle.FixedDialog && formState[FormStateIconSet] == 0) || !ShowIcon) + { icon = null; } else { icon = Icon; } - if (icon != null) { - if (smallIcon == null) { - try { + if (icon != null) + { + if (smallIcon == null) + { + try + { smallIcon = new Icon(icon, SystemInformation.SmallIconSize); } - catch { + catch + { } } - if (smallIcon != null) { - SendMessage(NativeMethods.WM_SETICON,NativeMethods.ICON_SMALL,smallIcon.Handle); + if (smallIcon != null) + { + SendMessage(Interop.WindowMessages.WM_SETICON,NativeMethods.ICON_SMALL,smallIcon.Handle); } - SendMessage(NativeMethods.WM_SETICON,NativeMethods.ICON_BIG,icon.Handle); - } - else { - SendMessage(NativeMethods.WM_SETICON,NativeMethods.ICON_SMALL,0); - SendMessage(NativeMethods.WM_SETICON,NativeMethods.ICON_BIG,0); + SendMessage(Interop.WindowMessages.WM_SETICON,NativeMethods.ICON_BIG,icon.Handle); + } + else + { + SendMessage(Interop.WindowMessages.WM_SETICON,NativeMethods.ICON_SMALL,0); + SendMessage(Interop.WindowMessages.WM_SETICON,NativeMethods.ICON_BIG,0); } - if (redrawFrame) { + if (redrawFrame) + { SafeNativeMethods.RedrawWindow(new HandleRef(this, Handle), null, NativeMethods.NullHandleRef, NativeMethods.RDW_INVALIDATE | NativeMethods.RDW_FRAME); } } @@ -6669,7 +6101,7 @@ private void UpdateWindowState() { if (IsHandleCreated) { FormWindowState oldState = WindowState; NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT(); - wp.length = Marshal.SizeOf(typeof(NativeMethods.WINDOWPLACEMENT)); + wp.length = Marshal.SizeOf(); UnsafeNativeMethods.GetWindowPlacement(new HandleRef(this, Handle), ref wp); switch (wp.showCmd) { @@ -6823,7 +6255,7 @@ private void WmClose(ref Message m) { // Pass 1 (WM_CLOSE & WM_QUERYENDSESSION)... Closing // - if (m.Msg != NativeMethods.WM_ENDSESSION) { + if (m.Msg != Interop.WindowMessages.WM_ENDSESSION) { if (Modal) { if (dialogResult == DialogResult.None) { dialogResult = DialogResult.Cancel; @@ -6886,7 +6318,7 @@ private void WmClose(ref Message m) { OnFormClosing(e); } - if (m.Msg == NativeMethods.WM_QUERYENDSESSION) { + if (m.Msg == Interop.WindowMessages.WM_QUERYENDSESSION) { m.Result = (IntPtr)(e.Cancel ? 0 : 1); } else if (e.Cancel && (MdiParent != null)) { @@ -6905,7 +6337,7 @@ private void WmClose(ref Message m) { // Pass 2 (WM_CLOSE & WM_ENDSESSION)... Fire closed // event on all mdi children and ourselves // - if (m.Msg != NativeMethods.WM_QUERYENDSESSION) { + if (m.Msg != Interop.WindowMessages.WM_QUERYENDSESSION) { FormClosedEventArgs fc; if (!e.Cancel) { IsClosing = true; @@ -6968,44 +6400,38 @@ private void WmExitMenuLoop(ref Message m) { OnMenuComplete(EventArgs.Empty); base.WndProc(ref m); } - + /// - /// WM_GETMINMAXINFO handler + /// WM_GETMINMAXINFO handler /// - /// - private void WmGetMinMaxInfo(ref Message m) { - + private void WmGetMinMaxInfo(ref Message m) + { // Form should gracefully stop at the minimum preferred size. // When we're set to AutoSize true, we should take a look at minAutoSize - which is snapped in onlayout. // as the form contracts, we should not let it size past here as we're just going to readjust the size // back to it later. Size minTrack = (AutoSize && formStateEx[FormStateExInModalSizingLoop] == 1) ? LayoutUtils.UnionSizes(minAutoSize, MinimumSize) : MinimumSize; - + Size maxTrack = MaximumSize; Rectangle maximizedBounds = MaximizedBounds; - if (!minTrack.IsEmpty - || !maxTrack.IsEmpty - || !maximizedBounds.IsEmpty - || IsRestrictedWindow) { - + if (!minTrack.IsEmpty || !maxTrack.IsEmpty || !maximizedBounds.IsEmpty) + { WmGetMinMaxInfoHelper(ref m, minTrack, maxTrack, maximizedBounds); } - if (IsMdiChild) { + + if (IsMdiChild) + { base.WndProc(ref m); - return; } } - // PERFTRACK : Microsoft, 2/22/2000 - Refer to MINMAXINFO in a separate method - // : to avoid loading the class in the common case. - // - private void WmGetMinMaxInfoHelper(ref Message m, Size minTrack, Size maxTrack, Rectangle maximizedBounds) { - + private void WmGetMinMaxInfoHelper(ref Message m, Size minTrack, Size maxTrack, Rectangle maximizedBounds) + { NativeMethods.MINMAXINFO mmi = (NativeMethods.MINMAXINFO)m.GetLParam(typeof(NativeMethods.MINMAXINFO)); - if (!minTrack.IsEmpty) { - + if (!minTrack.IsEmpty) + { mmi.ptMinTrackSize.x = minTrack.Width; mmi.ptMinTrackSize.y = minTrack.Height; @@ -7017,39 +6443,38 @@ private void WmGetMinMaxInfoHelper(ref Message m, Size minTrack, Size maxTrack, // So, the workaround to prevent this problem is to set the MaxTrackSize to something // whenever the MinTrackSize is set to a value larger than the respective dimension // of the virtual screen. - - if (maxTrack.IsEmpty) { - + if (maxTrack.IsEmpty) + { // Only set the max track size dimensions if the min track size dimensions // are larger than the VirtualScreen dimensions. Size virtualScreen = SystemInformation.VirtualScreen.Size; - if (minTrack.Height > virtualScreen.Height) { + if (minTrack.Height > virtualScreen.Height) + { mmi.ptMaxTrackSize.y = int.MaxValue; } - if (minTrack.Width > virtualScreen.Width) { + if (minTrack.Width > virtualScreen.Width) + { mmi.ptMaxTrackSize.x = int.MaxValue; } } } - if (!maxTrack.IsEmpty) { + + if (!maxTrack.IsEmpty) + { // Is the specified MaxTrackSize smaller than the smallest allowable Window size? Size minTrackWindowSize = SystemInformation.MinWindowTrackSize; mmi.ptMaxTrackSize.x = Math.Max(maxTrack.Width, minTrackWindowSize.Width); mmi.ptMaxTrackSize.y = Math.Max(maxTrack.Height, minTrackWindowSize.Height); } - if (!maximizedBounds.IsEmpty && !IsRestrictedWindow) { + if (!maximizedBounds.IsEmpty) + { mmi.ptMaxPosition.x = maximizedBounds.X; mmi.ptMaxPosition.y = maximizedBounds.Y; mmi.ptMaxSize.x = maximizedBounds.Width; mmi.ptMaxSize.y = maximizedBounds.Height; } - if (IsRestrictedWindow) { - mmi.ptMinTrackSize.x = Math.Max(mmi.ptMinTrackSize.x, 100); - mmi.ptMinTrackSize.y = Math.Max(mmi.ptMinTrackSize.y, SystemInformation.CaptionButtonSize.Height * 3); - } - Marshal.StructureToPtr(mmi, m.LParam, false); m.Result = IntPtr.Zero; } @@ -7081,7 +6506,7 @@ private void WmMenuChar(ref Message m) { Form formMdiParent = (Form)Properties.GetObject(PropFormMdiParent); if (formMdiParent != null && formMdiParent.Menu != null) { - UnsafeNativeMethods.PostMessage(new HandleRef(formMdiParent, formMdiParent.Handle), NativeMethods.WM_SYSCOMMAND, new IntPtr(NativeMethods.SC_KEYMENU), m.WParam); + UnsafeNativeMethods.PostMessage(new HandleRef(formMdiParent, formMdiParent.Handle), Interop.WindowMessages.WM_SYSCOMMAND, new IntPtr(NativeMethods.SC_KEYMENU), m.WParam); m.Result = (IntPtr)NativeMethods.Util.MAKELONG(0, 1); return; } @@ -7115,7 +6540,7 @@ private void WmMdiActivate(ref Message m) { formMdiParent.DeactivateMdiChild(); } else if (Handle == m.LParam) { - formMdiParent.ActivateMdiChildInternal(this); + formMdiParent.ActivateMdiChild(this); } } } @@ -7322,91 +6747,88 @@ private void WmWindowPosChanged(ref Message m) { [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_NCACTIVATE: - if (IsRestrictedWindow) { - BeginInvoke(new MethodInvoker(RestrictedProcessNcActivate)); - } + case Interop.WindowMessages.WM_NCACTIVATE: base.WndProc(ref m); break; - case NativeMethods.WM_NCLBUTTONDOWN: - case NativeMethods.WM_NCRBUTTONDOWN: - case NativeMethods.WM_NCMBUTTONDOWN: - case NativeMethods.WM_NCXBUTTONDOWN: + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + case Interop.WindowMessages.WM_NCMBUTTONDOWN: + case Interop.WindowMessages.WM_NCXBUTTONDOWN: WmNcButtonDown(ref m); break; - case NativeMethods.WM_ACTIVATE: + case Interop.WindowMessages.WM_ACTIVATE: WmActivate(ref m); break; - case NativeMethods.WM_MDIACTIVATE: + case Interop.WindowMessages.WM_MDIACTIVATE: WmMdiActivate(ref m); break; - case NativeMethods.WM_CLOSE: + case Interop.WindowMessages.WM_CLOSE: if (CloseReason == CloseReason.None) { CloseReason = CloseReason.TaskManagerClosing; } WmClose(ref m); break; - case NativeMethods.WM_QUERYENDSESSION: - case NativeMethods.WM_ENDSESSION: + case Interop.WindowMessages.WM_QUERYENDSESSION: + case Interop.WindowMessages.WM_ENDSESSION: CloseReason = CloseReason.WindowsShutDown; WmClose(ref m); break; - case NativeMethods.WM_ENTERSIZEMOVE: + case Interop.WindowMessages.WM_ENTERSIZEMOVE: WmEnterSizeMove(ref m); DefWndProc(ref m); break; - case NativeMethods.WM_EXITSIZEMOVE: + case Interop.WindowMessages.WM_EXITSIZEMOVE: WmExitSizeMove(ref m); DefWndProc(ref m); break; - case NativeMethods.WM_CREATE: + case Interop.WindowMessages.WM_CREATE: WmCreate(ref m); break; - case NativeMethods.WM_ERASEBKGND: + case Interop.WindowMessages.WM_ERASEBKGND: WmEraseBkgnd(ref m); break; - case NativeMethods.WM_INITMENUPOPUP: + case Interop.WindowMessages.WM_INITMENUPOPUP: WmInitMenuPopup(ref m); break; - case NativeMethods.WM_UNINITMENUPOPUP: + case Interop.WindowMessages.WM_UNINITMENUPOPUP: WmUnInitMenuPopup(ref m); break; - case NativeMethods.WM_MENUCHAR: + case Interop.WindowMessages.WM_MENUCHAR: WmMenuChar(ref m); break; - case NativeMethods.WM_NCDESTROY: + case Interop.WindowMessages.WM_NCDESTROY: WmNCDestroy(ref m); break; - case NativeMethods.WM_NCHITTEST: + case Interop.WindowMessages.WM_NCHITTEST: WmNCHitTest(ref m); break; - case NativeMethods.WM_SHOWWINDOW: + case Interop.WindowMessages.WM_SHOWWINDOW: WmShowWindow(ref m); break; - case NativeMethods.WM_SIZE: + case Interop.WindowMessages.WM_SIZE: WmSize(ref m); break; - case NativeMethods.WM_SYSCOMMAND: + case Interop.WindowMessages.WM_SYSCOMMAND: WmSysCommand(ref m); break; - case NativeMethods.WM_GETMINMAXINFO: + case Interop.WindowMessages.WM_GETMINMAXINFO: WmGetMinMaxInfo(ref m); break; - case NativeMethods.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: WmWindowPosChanged(ref m); break; - //case NativeMethods.WM_WINDOWPOSCHANGING: + //case Interop.WindowMessages.WM_WINDOWPOSCHANGING: // WmWindowPosChanging(ref m); // break; - case NativeMethods.WM_ENTERMENULOOP: + case Interop.WindowMessages.WM_ENTERMENULOOP: WmEnterMenuLoop(ref m); break; - case NativeMethods.WM_EXITMENULOOP: + case Interop.WindowMessages.WM_EXITMENULOOP: WmExitMenuLoop(ref m); break; - case NativeMethods.WM_CAPTURECHANGED: + case Interop.WindowMessages.WM_CAPTURECHANGED: base.WndProc(ref m); // This is a work-around for the Win32 scroll bar; it // doesn't release it's capture in response to a CAPTURECHANGED @@ -7416,11 +6838,11 @@ protected override void WndProc(ref Message m) { CaptureInternal = false; } break; - case NativeMethods.WM_GETDPISCALEDSIZE: + case Interop.WindowMessages.WM_GETDPISCALEDSIZE: Debug.Assert(NativeMethods.Util.SignedLOWORD(m.WParam) == NativeMethods.Util.SignedHIWORD(m.WParam), "Non-square pixels!"); WmGetDpiScaledSize(ref m); break; - case NativeMethods.WM_DPICHANGED: + case Interop.WindowMessages.WM_DPICHANGED: WmDpiChanged(ref m); break; default: @@ -7545,183 +6967,6 @@ internal void SetOwners(HandleRef hRefOwner) } } } - - private class SecurityToolTip : IDisposable { - Form owner; - string toolTipText; - bool first = true; - ToolTipNativeWindow window; - - internal SecurityToolTip(Form owner) { - this.owner = owner; - SetupText(); - window = new ToolTipNativeWindow(this); - SetupToolTip(); - owner.LocationChanged += new EventHandler(FormLocationChanged); - owner.HandleCreated += new EventHandler(FormHandleCreated); - } - - CreateParams CreateParams { - get { - NativeMethods.INITCOMMONCONTROLSEX icc = new NativeMethods.INITCOMMONCONTROLSEX(); - icc.dwICC = NativeMethods.ICC_TAB_CLASSES; - SafeNativeMethods.InitCommonControlsEx(icc); - - CreateParams cp = new CreateParams(); - cp.Parent = owner.Handle; - cp.ClassName = NativeMethods.TOOLTIPS_CLASS; - cp.Style |= NativeMethods.TTS_ALWAYSTIP | NativeMethods.TTS_BALLOON; - cp.ExStyle = 0; - cp.Caption = null; - return cp; - } - } - - internal bool Modal { - get { - return first; - } - } - - public void Dispose() { - if (owner != null) { - owner.LocationChanged -= new EventHandler(FormLocationChanged); - } - if (window.Handle != IntPtr.Zero) { - window.DestroyHandle(); - window = null; - } - } - - private NativeMethods.TOOLINFO_T GetTOOLINFO() { - NativeMethods.TOOLINFO_T toolInfo; - toolInfo = new NativeMethods.TOOLINFO_T(); - toolInfo.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); - toolInfo.uFlags |= NativeMethods.TTF_SUBCLASS; - toolInfo.lpszText = this.toolTipText; - if (owner.RightToLeft == RightToLeft.Yes) { - toolInfo.uFlags |= NativeMethods.TTF_RTLREADING; - } - if (!first) { - toolInfo.uFlags |= NativeMethods.TTF_TRANSPARENT; - toolInfo.hwnd = owner.Handle; - Size s = SystemInformation.CaptionButtonSize; - Rectangle r = new Rectangle(owner.Left, owner.Top, s.Width, SystemInformation.CaptionHeight); - r = owner.RectangleToClient(r); - r.Width -= r.X; - r.Y += 1; - toolInfo.rect = NativeMethods.RECT.FromXYWH(r.X, r.Y, r.Width, r.Height); - toolInfo.uId = IntPtr.Zero; - } - else { - toolInfo.uFlags |= NativeMethods.TTF_IDISHWND | NativeMethods.TTF_TRACK; - toolInfo.hwnd = IntPtr.Zero; - toolInfo.uId = owner.Handle; - } - return toolInfo; - } - - private void SetupText() { - owner.EnsureSecurityInformation(); - string mainText = SR.SecurityToolTipMainText; - string sourceInfo = string.Format(SR.SecurityToolTipSourceInformation, owner.securitySite); - this.toolTipText = string.Format(SR.SecurityToolTipTextFormat, mainText, sourceInfo); - } - - private void SetupToolTip() { - window.CreateHandle(CreateParams); - - SafeNativeMethods.SetWindowPos(new HandleRef(window, window.Handle), NativeMethods.HWND_TOPMOST, - 0, 0, 0, 0, - NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | - NativeMethods.SWP_NOACTIVATE); - - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_SETMAXTIPWIDTH, 0, owner.Width); - - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_SETTITLE, NativeMethods.TTI_WARNING, SR.SecurityToolTipCaption); - - if (0 == (int)UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_ADDTOOL, 0, GetTOOLINFO())) { - Debug.Fail("TTM_ADDTOOL failed for security tip"); - } - - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_ACTIVATE, 1, 0); - Show(); - } - - private void RecreateHandle() { - if (window != null) - { - if (window.Handle != IntPtr.Zero) { - window.DestroyHandle(); - } - SetupToolTip(); - } - } - - private void FormHandleCreated(object sender, EventArgs e) { - RecreateHandle(); - } - - private void FormLocationChanged(object sender, EventArgs e) { - if (window != null && first) { - Size s = SystemInformation.CaptionButtonSize; - - if (owner.WindowState == FormWindowState.Minimized) { - Pop(true /*noLongerFirst*/); - } - else { - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_TRACKPOSITION, 0, NativeMethods.Util.MAKELONG(owner.Left + s.Width / 2, owner.Top + SystemInformation.CaptionHeight)); - } - } - else { - Pop(true /*noLongerFirst*/); - } - } - - internal void Pop(bool noLongerFirst) { - if (noLongerFirst) { - first = false; - } - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_TRACKACTIVATE, 0, GetTOOLINFO()); - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_DELTOOL, 0, GetTOOLINFO()); - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_ADDTOOL, 0, GetTOOLINFO()); - } - - internal void Show() { - if (first) { - Size s = SystemInformation.CaptionButtonSize; - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_TRACKPOSITION, 0, NativeMethods.Util.MAKELONG(owner.Left + s.Width / 2, owner.Top + SystemInformation.CaptionHeight)); - UnsafeNativeMethods.SendMessage(new HandleRef(window, window.Handle), NativeMethods.TTM_TRACKACTIVATE, 1, GetTOOLINFO()); - } - } - - private void WndProc(ref Message msg) { - if (first) { - if (msg.Msg == NativeMethods.WM_LBUTTONDOWN - || msg.Msg == NativeMethods.WM_RBUTTONDOWN - || msg.Msg == NativeMethods.WM_MBUTTONDOWN - || msg.Msg == NativeMethods.WM_XBUTTONDOWN) { - - Pop(true /*noLongerFirst*/); - } - } - window.DefWndProc(ref msg); - } - - private sealed class ToolTipNativeWindow : NativeWindow { - SecurityToolTip control; - - internal ToolTipNativeWindow(SecurityToolTip control) { - this.control = control; - } - - protected override void WndProc(ref Message m) { - if (control != null) { - control.WndProc(ref m); - } - } - } - } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/FxCopSuppression.cs b/src/System.Windows.Forms/src/System/Windows/Forms/FxCopSuppression.cs index 68271f34c68..22ebcb18c08 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/FxCopSuppression.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/FxCopSuppression.cs @@ -121,66 +121,6 @@ [assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="System.Windows.Forms.resources", MessageId="Lresult")] [assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="System.Windows.Forms.resources", MessageId="Dn")] -// - -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Application.EnableVisualStyles():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Application.GetAppFileVersionInfo():System.Diagnostics.FileVersionInfo")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.get_ParkingWindow():System.Windows.Forms.Application+ParkingWindow")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.OnThreadException(System.Exception):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.ContainerControl.AfterControlRemoved(System.Windows.Forms.Control):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Control+ControlVersionInfo.GetFileVersionInfo():System.Diagnostics.FileVersionInfo")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Control+ControlAccessibleObject..ctor(System.Windows.Forms.Control)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Control+ControlAccessibleObject.get_PreviousLabel():System.Windows.Forms.Label")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Label.ProcessMnemonic(System.Char):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.FontDialog.RunDialog(System.IntPtr):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.FontDialog.UpdateFont(System.Windows.Forms.NativeMethods+LOGFONT):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.ImageList+NativeImageList..ctor(System.IntPtr)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGridView+DataGridViewToolTip.ComputeToolTipPosition():System.Drawing.Point")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.InputLanguage.get_LayoutName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.TabControl.WmSelChanging():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.TabControl.UpdateTabSelection(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.GroupBox.ProcessMnemonic(System.Char):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Form.OnVisibleChanged(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Form.get_DefaultIcon():System.Drawing.Icon")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window):System.Windows.Forms.DialogResult")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Form.SetVisibleCore(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Form.get_DefaultRestrictedIcon():System.Drawing.Icon")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Form.set_Active(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Help.Resolve(System.String):System.Uri")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Splitter.SplitBegin(System.Int32,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.ImageList.GetBitmap(System.Int32):System.Drawing.Bitmap")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Cursor.get_HotSpot():System.Drawing.Point")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Cursor.LoadPicture(System.Windows.Forms.UnsafeNativeMethods+IStream):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Cursor.get_CurrentInternal():System.Windows.Forms.Cursor")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.LinkUtilities.GetIEColor(System.String):System.Drawing.Color")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.LinkUtilities.GetIELinkBehavior():System.Windows.Forms.LinkBehavior")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.ListView.SetBackgroundImage():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.ListView.Dispose(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.ListView.DeleteFileName(System.String):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGrid.CreateScrollableRegion(System.Drawing.Rectangle):System.Windows.Forms.NativeMethods+RECT[]")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.InstallWindowsFormsSyncContextIfNeeded():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.SystemInformation.get_MenuFont():System.Drawing.Font")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.SplitContainer.SplitBegin(System.Int32,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Control.OnHandleCreated(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Control.UpdateReflectParent(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope = "member", Target = "System.Windows.Forms.Control.SelectNextIfFocused():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope = "member", Target = "System.Windows.Forms.Control.SelectNextControlInternal(System.Windows.Forms.Control,System.Boolean,System.Boolean,System.Boolean,System.Boolean):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGridView.CreateScrollableRegion(System.Drawing.Rectangle):System.Windows.Forms.NativeMethods+RECT[]")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.ComponentModel.WeakDelegateHolder.DynamicInvoke(System.Object[]):System.Object")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetFont(System.Drawing.IDeviceContext,System.Windows.Forms.VisualStyles.FontProperty):System.Drawing.Font")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.PtrToStructure(System.IntPtr,System.Type):System.Object")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGrid.RowResizeBegin(System.Windows.Forms.MouseEventArgs,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGrid.ColResizeBegin(System.Windows.Forms.MouseEventArgs,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGridView.CaptureMouse(System.Drawing.Rectangle):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.Control+ActiveXImpl.OnFocus(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataObject.SaveObjectToHandleSerializer(System.IO.Stream,System.Object):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.DataGridView+DataGridViewToolTip.Activate(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.FileDialog.RunDialogVista(System.IntPtr):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Windows.Forms.FileDialogCustomPlacesCollection.Apply(System.Windows.Forms.FileDialogNative+IFileDialog):System.Void")] - -// - - [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.Internal.IntSafeNativeMethods.ExtTextOut(System.Runtime.InteropServices.HandleRef,System.Int32,System.Int32,System.Int32,System.Windows.Forms.Internal.IntNativeMethods+RECT&,System.String,System.Int32,System.Int32[]):System.Boolean")] [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.Internal.IntSafeNativeMethods.FormatMessage(System.Int32,System.Runtime.InteropServices.HandleRef,System.Int32,System.Int32,System.Text.StringBuilder,System.Int32,System.Runtime.InteropServices.HandleRef):System.Int32")] @@ -257,7 +197,6 @@ [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.SystemParametersInfo(System.Int32,System.Int32,System.Windows.Forms.NativeMethods+LOGFONT,System.Int32):System.Boolean")] [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.SystemParametersInfo(System.Int32,System.Int32,System.Windows.Forms.NativeMethods+NONCLIENTMETRICS,System.Int32):System.Boolean")] [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.UnregisterClass(System.String,System.Runtime.InteropServices.HandleRef):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods+Shell32.SHBrowseForFolder(System.Windows.Forms.UnsafeNativeMethods+BROWSEINFO):System.IntPtr")] [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.OleCreateFontIndirect(System.Windows.Forms.NativeMethods+tagFONTDESC,System.Guid&):System.Windows.Forms.UnsafeNativeMethods+IFont")] [assembly: SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.OleCreateIFontIndirect(System.Windows.Forms.NativeMethods+FONTDESC,System.Guid&):System.Windows.Forms.UnsafeNativeMethods+IFont")] @@ -531,242 +470,6 @@ [assembly: SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources", Scope="member", Target="System.Windows.Forms.ComponentModel.Com2Interop.Com2PictureConverter.lastPalette")] //LinkDemands reviewed as part of security push -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Design.WindowsFormsComponentEditor.EditComponent(System.ComponentModel.ITypeDescriptorContext,System.Object,System.Windows.Forms.IWin32Window):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Design.ComponentEditorPage.IsPageMessage(System.Windows.Forms.Message&):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetBackgroundRegion(System.Drawing.IDeviceContext,System.Drawing.Rectangle):System.Drawing.Region")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetMargins(System.Drawing.IDeviceContext,System.Windows.Forms.VisualStyles.MarginProperty):System.Windows.Forms.Padding")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.HitTestBackground(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.IntPtr,System.Drawing.Point,System.Windows.Forms.VisualStyles.HitTestOptions):System.Windows.Forms.VisualStyles.HitTestCode")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetPartSize(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.Windows.Forms.VisualStyles.ThemeSizeType):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.DrawText(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.String,System.Boolean,System.Windows.Forms.TextFormatFlags):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.DrawBackground(System.Drawing.IDeviceContext,System.Drawing.Rectangle):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetTextExtent(System.Drawing.IDeviceContext,System.String,System.Windows.Forms.TextFormatFlags):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetTextExtent(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.String,System.Windows.Forms.TextFormatFlags):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetBackgroundContentRectangle(System.Drawing.IDeviceContext,System.Drawing.Rectangle):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetBackgroundExtent(System.Drawing.IDeviceContext,System.Drawing.Rectangle):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetFont(System.Drawing.IDeviceContext,System.Windows.Forms.VisualStyles.FontProperty):System.Drawing.Font")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetPartSize(System.Drawing.IDeviceContext,System.Windows.Forms.VisualStyles.ThemeSizeType):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.GetTextMetrics(System.Drawing.IDeviceContext):System.Windows.Forms.VisualStyles.TextMetrics")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.DrawParentBackground(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.Windows.Forms.Control):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.DrawBackground(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.Drawing.Rectangle):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.HitTestBackground(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.Drawing.Point,System.Windows.Forms.VisualStyles.HitTestOptions):System.Windows.Forms.VisualStyles.HitTestCode")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.VisualStyles.VisualStyleRenderer.DrawEdge(System.Drawing.IDeviceContext,System.Drawing.Rectangle,System.Windows.Forms.VisualStyles.Edges,System.Windows.Forms.VisualStyles.EdgeStyle,System.Windows.Forms.VisualStyles.EdgeEffects):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Internal.DeviceContext.Dispose(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Internal.DeviceContext.get_Hdc():System.IntPtr")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Internal.IntNativeMethods+DRAWTEXTPARAMS..ctor(System.Int32,System.Int32)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Internal.IntUnsafeNativeMethods.GetObject(System.Runtime.InteropServices.HandleRef,System.Windows.Forms.Internal.IntNativeMethods+LOGFONT):System.Int32")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Internal.WindowsGraphics.FromGraphics(System.Drawing.Graphics,System.Windows.Forms.Internal.ApplyGraphicsProperties):System.Windows.Forms.Internal.WindowsGraphics")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolBarButton.GetTBBUTTONINFO(System.Boolean,System.Int32):System.Windows.Forms.NativeMethods+TBBUTTONINFO")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ControlVersionInfo.get_ProductName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ControlVersionInfo.GetFileVersionInfo():System.Diagnostics.FileVersionInfo")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ControlVersionInfo.get_ProductVersion():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ControlVersionInfo.get_CompanyName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WindowsGraphicsWrapper..ctor(System.Drawing.IDeviceContext,System.Windows.Forms.TextFormatFlags)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.LinkLabel.PaintLink(System.Drawing.Graphics,System.Windows.Forms.LinkLabel+Link,System.Drawing.SolidBrush,System.Drawing.SolidBrush,System.Boolean,System.Drawing.RectangleF):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.LinkLabel.OnPaint(System.Windows.Forms.PaintEventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+PARAFORMAT..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Label.OnPaint(System.Windows.Forms.PaintEventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ControlNativeWindow..ctor(System.Windows.Forms.Control)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ControlNativeWindow.LockReference(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application.get_ProductName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application.GetAppFileVersionInfo():System.Diagnostics.FileVersionInfo")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application.get_ProductVersion():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application.get_CompanyName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.FontDialog.RunDialog(System.IntPtr):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Timer+TimerNativeWindow.StartTimer(System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Timer+TimerNativeWindow.get_IsTimerRunning():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Timer+TimerNativeWindow..ctor(System.Windows.Forms.Timer)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Timer+TimerNativeWindow.StopTimer(System.Boolean,System.IntPtr):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Timer+TimerNativeWindow.EnsureHandle():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NotifyIcon.Dispose(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.PrintPreviewControl.ComputeLayout():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.StatusBar.OnHandleDestroyed(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.StatusBar.get_SizeGripWidth():System.Int32")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.StatusBar.UpdateTooltip(System.Windows.Forms.StatusBarPanel):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.StatusBar.set_ShowPanels(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.get_Focused():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.EndUpdate():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.UpdateText():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.ReleaseChildWindow():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.SetAutoComplete(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.set_SelectedText(System.String):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox.OnHandleCreated(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+HH_AKLINK..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ControlBindingsCollection.RemoveCore(System.Windows.Forms.Binding):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ControlBindingsCollection.AddCore(System.Windows.Forms.Binding):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+LVINSERTMARK..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control+ActiveXImpl..ctor(System.Windows.Forms.Control)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.FolderBrowserDialog.RunDialog(System.IntPtr):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridViewCheckBoxCell.PaintPrivate(System.Drawing.Graphics,System.Drawing.Rectangle,System.Drawing.Rectangle,System.Int32,System.Windows.Forms.DataGridViewElementStates,System.Object,System.String,System.Windows.Forms.DataGridViewCellStyle,System.Windows.Forms.DataGridViewAdvancedBorderStyle,System.Windows.Forms.DataGridViewPaintParts,System.Boolean,System.Boolean,System.Boolean):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MonthCalendar.HitTest(System.Int32,System.Int32):System.Windows.Forms.MonthCalendar+HitTestInfo")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MonthCalendar.Dispose(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox+ACNativeWindow.get_Visible():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TabControl.OnHandleDestroyed(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TabControl.OnHandleCreated(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ImageList+ImageCollection.set_Item(System.Int32,System.Drawing.Image):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ControlPaint.DrawFlatCheckBox(System.Drawing.Graphics,System.Drawing.Rectangle,System.Drawing.Color,System.Drawing.Brush,System.Windows.Forms.ButtonState):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ControlPaint.CopyPixels(System.IntPtr,System.Drawing.IDeviceContext,System.Drawing.Point,System.Drawing.Point,System.Drawing.Size,System.Drawing.CopyPixelOperation):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.SetVisibleCore(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.get_TaskbarOwner():System.Runtime.InteropServices.HandleRef")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.UpdateWindowState():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window):System.Windows.Forms.DialogResult")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.ComputeWindowSize(System.Drawing.Size):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.set_MdiParentInternal(System.Windows.Forms.Form):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form.CheckCloseDialog(System.Boolean):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TreeNode.Realize(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TreeNode.UpdateNode(System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+HH_FTS_QUERY..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WebBrowserNavigatedEventArgs.get_Url():System.Uri")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolStripDropDownMenu.CalculateInternalLayoutMetrics():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+MENUITEMINFO_T..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form+SecurityToolTip.Dispose():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form+SecurityToolTip.Pop():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Form+SecurityToolTip.GetTOOLINFO():System.Windows.Forms.NativeMethods+TOOLINFO_T")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Help.ShowPopup(System.Windows.Forms.Control,System.String,System.Drawing.Point):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+MENUITEMINFO_T_RW..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MenuItem.CreateMenuItem():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MenuItem.UpdateMenuItem(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MenuItem.UpdateItemRtl(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MenuItem.AllocMsaaMenuInfo():System.IntPtr")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MenuItem.FreeMsaaMenuInfo():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolStrip.OnPaint(System.Windows.Forms.PaintEventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolStrip.get_DropDownOwnerWindow():System.Windows.Forms.NativeWindow")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+TOOLINFO_T..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ContainerControl.UpdateFocusedControl():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+MCHITTESTINFO..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ColorDialog.RunDialog(System.IntPtr):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.CreateHandle():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control..ctor(System.Boolean)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.FromHandleInternal(System.IntPtr):System.Windows.Forms.Control")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.get_HandleInternal():System.IntPtr")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.InvokeMarshaledCallbacks():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.ScaleControl(System.Drawing.SizeF,System.Windows.Forms.BoundsSpecified):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.SizeFromClientSize(System.Int32,System.Int32):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.InvokeMarshaledCallback(System.Windows.Forms.Control+ThreadMethodEntry):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.Dispose(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(System.Object):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.UpdateBounds(System.Int32,System.Int32,System.Int32,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.PerformControlValidation(System.Boolean):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.PaintTransparentBackground(System.Windows.Forms.PaintEventArgs,System.Drawing.Rectangle,System.Drawing.Region):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.get_IsMirrored():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.ProcessUICues(System.Windows.Forms.Message&):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.CreateGraphicsInternal():System.Drawing.Graphics")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.UpdateStylesCore():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.RecreateHandleCore():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.get_IsHandleCreated():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.OnPrint(System.Windows.Forms.PaintEventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Control.GetScaledBounds(System.Drawing.Rectangle,System.Drawing.SizeF,System.Windows.Forms.BoundsSpecified):System.Drawing.Rectangle")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+CHARFORMAT2A..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WebBrowserNavigatingEventArgs.get_Url():System.Uri")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WebBrowserNavigatingEventArgs.get_TargetFrameName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.BindingContext.CheckPropertyBindingCycles(System.Windows.Forms.BindingContext,System.Windows.Forms.Binding):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ComboBox+ComboBoxChildNativeWindow..ctor(System.Windows.Forms.ComboBox)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataObject..ctor(System.Object)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.ReleaseComObject(System.Object):System.Int32")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.PtrToStructure(System.IntPtr,System.Type):System.Object")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.GetRectsFromRegion(System.IntPtr):System.Windows.Forms.NativeMethods+RECT[]")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.IsComObject(System.Object):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods.SizeOf(System.Type):System.Int32")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolBar.RealizeButtons():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolBar.OnHandleCreated(System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolBar.InternalSetButton(System.Int32,System.Windows.Forms.ToolBarButton,System.Boolean,System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolBar.ForceButtonWidths():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridToolTip.Destroy():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridToolTip.RemoveToolTip(System.IntPtr):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridToolTip.AddToolTip(System.String,System.IntPtr,System.Drawing.Rectangle):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridToolTip.CreateToolTipHandle():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ParkingWindow.CheckDestroy():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ParkingWindow.Destroy():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NotifyIcon+NotifyIconNativeWindow..ctor(System.Windows.Forms.NotifyIcon)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.FileDialog.RunDialog(System.IntPtr):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ImageList.GetBitmap(System.Int32):System.Drawing.Bitmap")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ImageList.set_ImageStream(System.Windows.Forms.ImageListStreamer):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ImageList.AddToHandle(System.Windows.Forms.ImageList+Original,System.Drawing.Bitmap):System.Int32")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ImageList.Draw(System.Drawing.Graphics,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip+ToolTipNativeWindow..ctor(System.Windows.Forms.ToolTip)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.SystemInformation.get_HighContrast():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.SystemInformation.get_UserInteractive():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.SystemInformation.get_ScreenOrientation():System.Windows.Forms.ScreenOrientation")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TextRenderer.DrawText(System.Drawing.IDeviceContext,System.String,System.Drawing.Font,System.Drawing.Point,System.Drawing.Color,System.Drawing.Color):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TextRenderer.DrawText(System.Drawing.IDeviceContext,System.String,System.Drawing.Font,System.Drawing.Point,System.Drawing.Color):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TextRenderer.MeasureText(System.Drawing.IDeviceContext,System.String,System.Drawing.Font,System.Drawing.Size):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TextRenderer.DrawText(System.Drawing.IDeviceContext,System.String,System.Drawing.Font,System.Drawing.Rectangle,System.Drawing.Color,System.Drawing.Color):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TextRenderer.DrawText(System.Drawing.IDeviceContext,System.String,System.Drawing.Font,System.Drawing.Rectangle,System.Drawing.Color):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.TextRenderer.MeasureText(System.Drawing.IDeviceContext,System.String,System.Drawing.Font):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Cursor.DrawImageCore(System.Drawing.Graphics,System.Drawing.Rectangle,System.Drawing.Rectangle,System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Cursor.GetIconSize(System.IntPtr):System.Drawing.Size")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Cursor.LoadPicture(System.Windows.Forms.UnsafeNativeMethods+IStream):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ListView.InsertItemsNative(System.Int32,System.Windows.Forms.ListViewItem[]):System.Int32")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ListView.SetColumnInfo(System.Int32,System.Windows.Forms.ColumnHeader):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ListView.DestroyLVGROUP(System.Windows.Forms.NativeMethods+LVGROUP):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ListView.GetLVGROUP(System.Windows.Forms.ListViewGroup):System.Windows.Forms.NativeMethods+LVGROUP")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ListView.GenerateRandomName():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ListView.PositionHeader():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+IconRegion.get_Region():System.Drawing.Region")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Timer.set_Enabled(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+MSOCRINFOSTRUCT..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ScrollBar.UpdateScrollInfo():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ScrollBar..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MdiClient.SetWindowRgn():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.MdiClient.SetBoundsCore(System.Int32,System.Int32,System.Int32,System.Int32,System.Windows.Forms.BoundsSpecified):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+CHOOSEFONT..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolStripMenuItem.GetNativeMenuItemTextAndShortcut():System.String")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolStripMenuItem.GetNativeMenuItemEnabled():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+SCROLLINFO..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+MONITORINFOEX..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WindowsFormsUtils+DCMapping.get_Graphics():System.Drawing.Graphics")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGrid.OnKeyDown(System.Windows.Forms.KeyEventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataFormats.GetFormat(System.String):System.Windows.Forms.DataFormats+Format")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.AxHost+AxContainer.ListAxControls(System.Collections.ArrayList,System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.AxHost+AxContainer.FormCreated():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.get_ComponentManager():System.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.ProcessFilters(System.Windows.Forms.NativeMethods+MSG&,System.Boolean&):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.InstallWindowsFormsSyncContextIfNeeded():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.RevokeComponent():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.PreTranslateMessage(System.Windows.Forms.NativeMethods+MSG&):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(System.Int32,System.Windows.Forms.ApplicationContext):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.UnsafeNativeMethods+ThemingScope.CreateActivationContext(System.String,System.Int32):System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+TOOLINFO_TOOLTIP..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ScrollProperties.UpdateScrollInfo():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.HtmlElementCollection.GetElementsByName(System.String):System.Windows.Forms.HtmlElementCollection")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.HtmlElementCollection.get_Item(System.String):System.Windows.Forms.HtmlElement")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WebBrowserSiteBase.StopEvents():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+ErrorWindow.EnsureDestroyed():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+ErrorWindow.Update(System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+ErrorWindow.Remove(System.Windows.Forms.ErrorProvider+ControlItem):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+ErrorWindow.EnsureCreated():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+ErrorWindow.Add(System.Windows.Forms.ErrorProvider+ControlItem):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider+ErrorWindow..ctor(System.Windows.Forms.ErrorProvider,System.Windows.Forms.Control)")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.GetMinTOOLINFO(System.Windows.Forms.Control):System.Windows.Forms.NativeMethods+TOOLINFO_TOOLTIP")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.SetToolInfo(System.Windows.Forms.Control,System.String):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.GetHandleCreated():System.Boolean")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.SetTool(System.Windows.Forms.IWin32Window,System.String,System.Windows.Forms.ToolTip+TipInfo+Type,System.Drawing.Point):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.GetWinTOOLINFO(System.IntPtr):System.Windows.Forms.NativeMethods+TOOLINFO_TOOLTIP")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.DestroyHandle():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.CreateHandle():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.GetTOOLINFO(System.Windows.Forms.Control,System.String):System.Windows.Forms.NativeMethods+TOOLINFO_TOOLTIP")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolTip.get_Handle():System.IntPtr")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+LVGROUP..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ErrorProvider.ErrorManager_CurrentChanged(System.Object,System.EventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+TRACKMOUSEEVENT..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ToolStripDropDown.ReparentToDropDownOwnerWindow():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+LVTILEVIEWINFO..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+CHARFORMATA..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.BindToObject.CheckBinding():System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+CHARFORMATW..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+CHOOSECOLOR..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.WindowsFormsUtils.CreateMeasurementGraphics():System.Drawing.Graphics")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.PaintEventArgs.get_Graphics():System.Drawing.Graphics")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+NONCLIENTMETRICS..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridView.OnKeyDown(System.Windows.Forms.KeyEventArgs):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.DataGridView.DrawColHeaderShadow(System.Drawing.Graphics,System.Int32):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+HH_POPUP..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.NativeMethods+OPENFILENAME_I..ctor()")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ButtonInternal.CheckBoxBaseAdapter.GetCheckBoxImage(System.Drawing.Color,System.Drawing.Rectangle,System.Drawing.Color&,System.Drawing.Bitmap&):System.Drawing.Bitmap")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ButtonInternal.ButtonBaseAdapter+ColorOptions.Calculate():System.Windows.Forms.ButtonInternal.ButtonBaseAdapter+ColorData")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ButtonInternal.ButtonBaseAdapter.Draw3DLiteBorder(System.Drawing.Graphics,System.Drawing.Rectangle,System.Windows.Forms.ButtonInternal.ButtonBaseAdapter+ColorData,System.Boolean):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ButtonInternal.ButtonBaseAdapter.DrawFlatFocus(System.Drawing.Graphics,System.Drawing.Rectangle,System.Drawing.Color):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.ButtonInternal.ButtonBaseAdapter.PaintButtonBackground(System.Drawing.Graphics,System.Drawing.Rectangle,System.Windows.Forms.Internal.WindowsBrush):System.Void")] -[assembly: SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Windows.Forms.FileDialog.RunDialogOld(System.IntPtr):System.Boolean")] [assembly: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Windows.Forms.ToolStripDropDownMenu..ctor(System.Windows.Forms.ToolStripItem)")] [assembly: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Windows.Forms.ToolStripDropDownMenu.ShortcutToText(System.Windows.Forms.Keys,System.String):System.String")] @@ -777,15 +480,6 @@ // InProc SxS Supperssions: Methods wich consume but not expose resources [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Resources.AssemblyNamesTypeResolutionService.#GetType(System.String,System.Boolean,System.Boolean)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Resources.ResXResourceReader.#EnsureResData()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManager.#GetZonePromptingLevel(System.String)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManager.#get_DefaultBrowserExePath()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerMoreInformation.#.ctor(System.Security.Policy.TrustManagerPromptOptions,System.String)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerMoreInformation.#LoadWarningBitmap(System.Security.Policy.TrustManagerWarningLevel,System.Windows.Forms.PictureBox)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerMoreInformation.#OnUserPreferenceChanged(System.Object,Microsoft.Win32.UserPreferenceChangedEventArgs)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerPromptUI.#LoadGlobeBitmap()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerPromptUI.#LoadWarningBitmap(System.Security.Policy.TrustManagerWarningLevel)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerPromptUI.#TrustManagerPromptUI_ShowSupportPage(System.Object,System.Windows.Forms.LinkLabelLinkClickedEventArgs)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Security.Policy.TrustManagerPromptUI.#UpdateFonts()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Application+ComponentManager.#System.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoop(System.Int32,System.Int32,System.Int32)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Application+ModalApplicationContext.#DisableThreadWindows(System.Boolean,System.Boolean)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Application+ParkingWindow.#CheckDestroy()")] @@ -1186,19 +880,10 @@ [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.FontDialog.#ShouldSerializeFont()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.FontDialog.#ToString()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.FontDialog.#UpdateFont(System.Windows.Forms.NativeMethods+LOGFONT)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form+SecurityToolTip.#Dispose()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form+SecurityToolTip.#FormLocationChanged(System.Object,System.EventArgs)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form+SecurityToolTip.#Pop(System.Boolean)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form+SecurityToolTip.#RecreateHandle()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form+SecurityToolTip.#SetupToolTip()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form+SecurityToolTip.#Show()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#CreateHandle()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#GetAutoScaleSize(System.Drawing.Font)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#get_ActiveForm()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#get_TaskbarOwner()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#ResolveZoneAndSiteNames(System.Collections.ArrayList,System.String&,System.String&)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#RestrictedProcessNcActivate()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#SelectInternal(System.Boolean,System.Boolean)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#Show(System.Windows.Forms.IWin32Window)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#ShowDialog(System.Windows.Forms.IWin32Window)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#UpdateMenuHandles(System.Windows.Forms.MainMenu,System.Boolean)")] @@ -1257,7 +942,6 @@ [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Internal.WindowsGraphics.#GetTextExtent(System.String,System.Windows.Forms.Internal.WindowsFont)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Internal.WindowsGraphics.#GetTextMetrics()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Internal.WindowsGraphics.#MeasureText(System.String,System.Windows.Forms.Internal.WindowsFont,System.Drawing.Size,System.Windows.Forms.Internal.IntTextFormatFlags)")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.IntSecurity.#DemandFileIO(System.Security.Permissions.FileIOPermissionAccess,System.String)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Label.#Dispose(System.Boolean)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Label.#GetLeadingTextPaddingFromTextFormatFlags()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Label.#GetPreferredSizeCore(System.Drawing.Size)")] @@ -1637,7 +1321,6 @@ [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.DataGridViewImageCell.#get_ErrorIcon()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.ErrorProvider.#get_DefaultIcon()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#get_DefaultIcon()")] -[module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Form.#get_DefaultRestrictedIcon()")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Internal.DeviceContext.#SelectFont(System.Windows.Forms.Internal.WindowsFont)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Internal.DeviceContext.#SelectObject(System.IntPtr,System.Windows.Forms.Internal.GdiObjectType)")] [module: SuppressMessage("Microsoft.SideBySide", "CA710:ExposedResourcesMustBeConsumed", Scope = "member", Target = "System.Windows.Forms.Internal.WindowsPen.#get_HPen()")] diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/GDI/TextRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/GDI/TextRenderer.cs index 445f4debe62..20b018d649d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/GDI/TextRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/GDI/TextRenderer.cs @@ -335,7 +335,7 @@ public static Size MeasureText(IDeviceContext dc, string text, Font font, Size p internal static Color DisabledTextColor(Color backColor) { - if (SystemInformation.HighContrast && AccessibilityImprovements.Level1) { + if (SystemInformation.HighContrast) { return SystemColors.GrayText; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/GroupBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/GroupBox.cs index 121e957f1f7..9d3a126cdb1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/GroupBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/GroupBox.cs @@ -314,13 +314,13 @@ public override string Text { bool suspendRedraw = this.Visible; try { if (suspendRedraw && IsHandleCreated) { - SendMessage(NativeMethods.WM_SETREDRAW, 0, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, 0, 0); } base.Text = value; } finally { if (suspendRedraw && IsHandleCreated) { - SendMessage(NativeMethods.WM_SETREDRAW, 1, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, 1, 0); } } Invalidate(true); @@ -616,7 +616,7 @@ private void DrawGroupBox(PaintEventArgs e) { int boxTop = FontHeight / 2; - if (SystemInformation.HighContrast && AccessibilityImprovements.Level1) { + if (SystemInformation.HighContrast) { Color boxColor; if (Enabled) { boxColor = ForeColor; @@ -727,11 +727,7 @@ protected override void ScaleControl(SizeF factor, BoundsSpecified specified) { base.ScaleControl(factor, specified); } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// /// @@ -771,11 +767,11 @@ protected override void WndProc(ref Message m) { } switch (m.Msg) { - case NativeMethods.WM_ERASEBKGND: - case NativeMethods.WM_PRINTCLIENT: + case Interop.WindowMessages.WM_ERASEBKGND: + case Interop.WindowMessages.WM_PRINTCLIENT: WmEraseBkgnd(ref m); break; - case NativeMethods.WM_GETOBJECT: + case Interop.WindowMessages.WM_GETOBJECT: base.WndProc(ref m); // Force MSAA to always treat a group box as a custom window. This ensures its child controls @@ -813,13 +809,7 @@ public override AccessibleRole Role { } } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3) { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { switch (propertyID) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/GroupBoxRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/GroupBoxRenderer.cs index 42695d46bb5..604468b7e9a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/GroupBoxRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/GroupBoxRenderer.cs @@ -318,8 +318,7 @@ private static Color DefaultTextColor(GroupBoxState state) { private static void InitializeRenderer(int state) { int part = GroupBoxElement.Part; - if (AccessibilityImprovements.Level2 - && SystemInformation.HighContrast + if (SystemInformation.HighContrast && ((GroupBoxState)state == GroupBoxState.Disabled) && VisualStyleRenderer.IsCombinationDefined(GroupBoxElement.ClassName, VisualStyleElement.Button.GroupBox.HighContrastDisabledPart)) { part = VisualStyleElement.Button.GroupBox.HighContrastDisabledPart; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HScrollBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HScrollBar.cs index 32f5f374a0f..943cb53f98c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HScrollBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HScrollBar.cs @@ -2,56 +2,33 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; - using System.Diagnostics; - - using System; - using System.Windows.Forms; - using System.Drawing; - using Microsoft.Win32; - using System.Runtime.InteropServices; - - /// - /// - /// - /// Represents - /// a standard Windows horizontal scroll bar. - /// - /// - [ComVisible(true), - ClassInterface(ClassInterfaceType.AutoDispatch), - SRDescription(nameof(SR.DescriptionHScrollBar)) - ] - public class HScrollBar : ScrollBar { - - /// - /// - /// - /// - /// Returns the parameters needed to create the handle. Inheriting classes - /// can override this to provide extra functionality. They should not, - /// however, forget to call base.getCreateParams() first to get the struct - /// filled up with the basic info. - /// - /// - protected override CreateParams CreateParams { - get { +namespace System.Windows.Forms +{ + /// + /// Represents a standard Windows horizontal scroll bar. + /// + [ComVisible(true)] + [ClassInterface(ClassInterfaceType.AutoDispatch)] + [SRDescription(nameof(SR.DescriptionHScrollBar))] + public class HScrollBar : ScrollBar + { + protected override CreateParams CreateParams + { + get + { CreateParams cp = base.CreateParams; cp.Style |= NativeMethods.SBS_HORZ; return cp; } } - - /// - /// - /// Deriving classes can override this to configure a default size for their control. - /// This is more efficient than setting the size in the control's constructor. - /// - protected override Size DefaultSize { - get { - return new Size(80, SystemInformation.HorizontalScrollBarHeight); - } + + protected override Size DefaultSize + { + get => new Size(80, SystemInformation.HorizontalScrollBarHeight); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HScrollProperties.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HScrollProperties.cs index 9540020099c..61cef33f440 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HScrollProperties.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HScrollProperties.cs @@ -2,54 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Runtime.InteropServices; - using System.Diagnostics; - using System; - using System.Security.Permissions; - using System.Runtime.Serialization.Formatters; - using System.ComponentModel; - using System.Drawing; - using Microsoft.Win32; - using System.Windows.Forms; - - - - - /// +namespace System.Windows.Forms +{ /// - /// - /// Basic Properties for VScroll. - /// + /// Basic Properties for VScroll. /// - public class HScrollProperties : ScrollProperties { + public class HScrollProperties : ScrollProperties + { - /// - public HScrollProperties(ScrollableControl container) : base(container) { + public HScrollProperties(ScrollableControl container) : base(container) + { } - internal override int PageSize { - get { - return ParentControl.ClientRectangle.Width; - } - } + internal override int PageSize => ParentControl.ClientRectangle.Width; - internal override int Orientation { - get { - return NativeMethods.SB_HORZ; - } - } + internal override int Orientation => NativeMethods.SB_HORZ; - internal override int HorizontalDisplayPosition { - get { - return -this.value; - } - } + internal override int HorizontalDisplayPosition => -_value; - internal override int VerticalDisplayPosition { - get { - return ParentControl.DisplayRectangle.Y; - } - } + internal override int VerticalDisplayPosition => ParentControl.DisplayRectangle.Y; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Help.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Help.cs index cb2acc30878..3e3bd4f2e32 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Help.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Help.cs @@ -247,7 +247,7 @@ private static void ShowHTML10Help(Control parent, string url, HelpNavigator com SafeNativeMethods.HtmlHelp(handle, pathAndFileName, HH_DISPLAY_TEXT_POPUP, (NativeMethods.HH_POPUP)param); } else if (param.GetType() == typeof(int)) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "param", "Integer")); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(param), "Integer"), nameof(param)); } } @@ -308,12 +308,7 @@ private static Uri Resolve(string partialUri) { file = new Uri(partialUri); } catch (UriFormatException) { - // eat URI parse exceptions... - // - } - catch (ArgumentNullException) { - // Catch specific exceptions - // Shouldnt get here... + // Ignore invalid uris. } } @@ -337,13 +332,7 @@ private static Uri Resolve(string partialUri) { partialUri); } catch (UriFormatException) { - // Catch specific exceptions - // eat URI parse exceptions... - // - } - catch (ArgumentNullException) { - // Catch specific exceptions - // Shouldnt get here... + // Ignore invalid uris. } if (file != null && file.Scheme == "file") { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HelpInfo.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HelpInfo.cs index e9f817dc4dd..83e019f165d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HelpInfo.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HelpInfo.cs @@ -2,88 +2,61 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Diagnostics; - using System; - - - internal class HelpInfo { - - private string helpFilePath; - private string keyword; - private HelpNavigator navigator; - private object param; - private int option; - - public HelpInfo(string helpfilepath) { - this.helpFilePath= helpfilepath; - this.keyword = ""; - this.navigator = HelpNavigator.TableOfContents; - this.param = null; - this.option = NativeMethods.HLP_FILE; +namespace System.Windows.Forms +{ + internal class HelpInfo + { + public HelpInfo(string helpfilepath) + { + HelpFilePath = helpfilepath; + Keyword = string.Empty; + Navigator = HelpNavigator.TableOfContents; + Param = null; + Option = NativeMethods.HLP_FILE; } - public HelpInfo(string helpfilepath, string keyword) { - this.helpFilePath= helpfilepath; - this.keyword = keyword; - this.navigator = HelpNavigator.TableOfContents; - this.param = null; - this.option = NativeMethods.HLP_KEYWORD; + public HelpInfo(string helpfilepath, string keyword) + { + HelpFilePath = helpfilepath; + Keyword = keyword; + Navigator = HelpNavigator.TableOfContents; + Param = null; + Option = NativeMethods.HLP_KEYWORD; } - public HelpInfo(string helpfilepath, HelpNavigator navigator) { - this.helpFilePath= helpfilepath; - this.keyword = ""; - this.navigator = navigator; - this.param = null; - this.option = NativeMethods.HLP_NAVIGATOR; + public HelpInfo(string helpfilepath, HelpNavigator navigator) + { + HelpFilePath = helpfilepath; + Keyword = string.Empty; + Navigator = navigator; + Param = null; + Option = NativeMethods.HLP_NAVIGATOR; } - public HelpInfo(string helpfilepath, HelpNavigator navigator, object param) { - this.helpFilePath= helpfilepath; - this.keyword = ""; - this.navigator = navigator; - this.param = param; - this.option = NativeMethods.HLP_OBJECT; + public HelpInfo(string helpfilepath, HelpNavigator navigator, object param) + { + HelpFilePath = helpfilepath; + Keyword = string.Empty; + Navigator = navigator; + Param = param; + Option = NativeMethods.HLP_OBJECT; } - public int Option { - get { - return option; - } - } + public int Option { get; } - public string HelpFilePath { - get { - return helpFilePath; - } - } - - public string Keyword { - get { - return keyword; - } - } + public string HelpFilePath { get; } - public HelpNavigator Navigator { - get { - return navigator; - } - } + public string Keyword { get; } - public object Param { - get { - return param; - } - } - - - public override string ToString() { - return "{HelpFilePath=" + helpFilePath + ", keyword =" + keyword + ", navigator=" + navigator.ToString() + "}"; - } + public HelpNavigator Navigator { get; } + public object Param { get; } + public override string ToString() + { + return "{HelpFilePath=" + HelpFilePath + ", keyword =" + Keyword + ", navigator=" + Navigator.ToString() + "}"; + } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HelpProvider.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HelpProvider.cs index 4500cb07c10..30fd4772d6c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HelpProvider.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HelpProvider.cs @@ -2,362 +2,253 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -namespace System.Windows.Forms { - using System; - using System.ComponentModel; - using System.ComponentModel.Design; - using Microsoft.Win32; - using Hashtable = System.Collections.Hashtable; - using System.Windows.Forms; - using System.Windows.Forms.Design; - using System.Diagnostics; - using System.Drawing; - using System.Drawing.Design; - - - /// - /// - /// - /// Provides pop-up or online Help for controls. - /// - /// - [ - ProvideProperty("HelpString", typeof(Control)), - ProvideProperty("HelpKeyword", typeof(Control)), - ProvideProperty("HelpNavigator", typeof(Control)), - ProvideProperty("ShowHelp", typeof(Control)), - ToolboxItemFilter("System.Windows.Forms"), - SRDescription(nameof(SR.DescriptionHelpProvider)) - ] - public class HelpProvider : Component, IExtenderProvider { - - private string helpNamespace = null; - private Hashtable helpStrings = new Hashtable(); - private Hashtable showHelp = new Hashtable(); - private Hashtable boundControls = new Hashtable(); - private Hashtable keywords = new Hashtable(); - private Hashtable navigators = new Hashtable(); - - private object userData; - - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - public HelpProvider() { - } - - /// - /// - /// - /// Gets or sets a string indicating the name of the Help - /// file associated with this object. - /// - /// - [ - Localizable(true), - DefaultValue(null), - Editor("System.Windows.Forms.Design.HelpNamespaceEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), - SRDescription(nameof(SR.HelpProviderHelpNamespaceDescr)) - ] - public virtual string HelpNamespace { - get { - return helpNamespace; - } - - set { - this.helpNamespace = value; - } - } - - /// - [ - SRCategory(nameof(SR.CatData)), - Localizable(false), - Bindable(true), - SRDescription(nameof(SR.ControlTagDescr)), - DefaultValue(null), - TypeConverter(typeof(StringConverter)), - ] - public object Tag { - get { - return userData; - } - set { - userData = value; - } - } - - /// - /// - /// - /// Determines if the help provider can offer it's extender properties - /// to the specified target object. - /// - /// - public virtual bool CanExtend(object target) { - return(target is Control); - } - - /// - /// - /// - /// Retrieves the Help Keyword displayed when the - /// user invokes Help for the specified control. - /// - /// - [ - DefaultValue(null), - Localizable(true), - SRDescription(nameof(SR.HelpProviderHelpKeywordDescr)) - ] - public virtual string GetHelpKeyword(Control ctl) { - return(string)keywords[ctl]; - } - - /// - /// - /// - /// Retrieves the contents of the pop-up help window for the specified - /// control. - /// - /// - [ - DefaultValue(HelpNavigator.AssociateIndex), - Localizable(true), - SRDescription(nameof(SR.HelpProviderNavigatorDescr)) - ] - public virtual HelpNavigator GetHelpNavigator(Control ctl) { - object nav = navigators[ctl]; - return (nav == null) ? HelpNavigator.AssociateIndex : (HelpNavigator)nav; - } - - /// - /// - /// - /// Retrieves the contents of the pop-up help window for the specified - /// control. - /// - /// - [ - DefaultValue(null), - Localizable(true), - SRDescription(nameof(SR.HelpProviderHelpStringDescr)) - ] - public virtual string GetHelpString(Control ctl) { - return(string)helpStrings[ctl]; - } - - /// - /// - /// - /// Retrieves a value indicating whether Help displays for - /// the specified control. - /// - /// - [ - Localizable(true), - SRDescription(nameof(SR.HelpProviderShowHelpDescr)) - ] - public virtual bool GetShowHelp(Control ctl) { - object b = showHelp[ctl]; - if (b == null) { - return false; - } - else { - return(bool) b; - } - } - - /// - /// - /// Handles the help event for any bound controls. - /// - /// - private void OnControlHelp(object sender, HelpEventArgs hevent) { +using System.Collections; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing.Design; + +namespace System.Windows.Forms +{ + /// + /// Provides pop-up or online Help for controls. + /// + [ProvideProperty("HelpString", typeof(Control))] + [ProvideProperty("HelpKeyword", typeof(Control))] + [ProvideProperty("HelpNavigator", typeof(Control))] + [ProvideProperty("ShowHelp", typeof(Control))] + [ToolboxItemFilter("System.Windows.Forms")] + [SRDescription(nameof(SR.DescriptionHelpProvider))] + public class HelpProvider : Component, IExtenderProvider + { + private readonly Hashtable _helpStrings = new Hashtable(); + private readonly Hashtable _showHelp = new Hashtable(); + private readonly Hashtable _boundControls = new Hashtable(); + private readonly Hashtable _keywords = new Hashtable(); + private readonly Hashtable _navigators = new Hashtable(); + + /// + /// Initializes a new instance of the class. + /// + public HelpProvider() + { + } + + /// + /// Gets or sets a string indicating the name of the Help file associated with this + /// object. + /// + [Localizable(true)] + [DefaultValue(null)] + [Editor("System.Windows.Forms.Design.HelpNamespaceEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] + [SRDescription(nameof(SR.HelpProviderHelpNamespaceDescr))] + public virtual string HelpNamespace { get; set; } + + [SRCategory(nameof(SR.CatData))] + [Localizable(false)] + [Bindable(true)] + [SRDescription(nameof(SR.ControlTagDescr))] + [DefaultValue(null)] + [TypeConverter(typeof(StringConverter))] + + public object Tag { get; set; } + + /// + /// Determines if the help provider can offer it's extender properties to the + /// specified target object. + /// + public virtual bool CanExtend(object target) + { + return (target is Control); + } + + /// + /// Retrieves the Help Keyword displayed when the user invokes Help for the + /// specified control. + /// + [DefaultValue(null)] + [Localizable(true)] + [SRDescription(nameof(SR.HelpProviderHelpKeywordDescr))] + public virtual string GetHelpKeyword(Control ctl) => (string)_keywords[ctl]; + + /// + /// Retrieves the contents of the pop-up help window for the specified + /// control. + /// + [DefaultValue(HelpNavigator.AssociateIndex)] + [Localizable(true)] + [SRDescription(nameof(SR.HelpProviderNavigatorDescr))] + public virtual HelpNavigator GetHelpNavigator(Control ctl) + { + object nav = _navigators[ctl]; + return nav == null ? HelpNavigator.AssociateIndex : (HelpNavigator)nav; + } + + /// + /// Retrieves the contents of the pop-up help window for the specified control. + /// + [DefaultValue(null)] + [Localizable(true)] + [SRDescription(nameof(SR.HelpProviderHelpStringDescr))] + public virtual string GetHelpString(Control ctl) => (string)_helpStrings[ctl]; + + /// + /// Retrieves a value indicating whether Help displays for the specified control. + /// + [Localizable(true)] + [SRDescription(nameof(SR.HelpProviderShowHelpDescr))] + public virtual bool GetShowHelp(Control ctl) + { + object b = _showHelp[ctl]; + return b == null ? false : (bool)b; + } + + /// + /// Handles the help event for any bound controls. + /// + private void OnControlHelp(object sender, HelpEventArgs hevent) + { Control ctl = (Control)sender; string helpString = GetHelpString(ctl); string keyword = GetHelpKeyword(ctl); HelpNavigator navigator = GetHelpNavigator(ctl); - bool show = GetShowHelp(ctl); - if (!show) { + if (!GetShowHelp(ctl) || hevent == null) + { return; } - // If the mouse was down, we first try whats this help - // - if (Control.MouseButtons != MouseButtons.None && helpString != null) { + if (Control.MouseButtons != MouseButtons.None && !string.IsNullOrEmpty(helpString)) + { Debug.WriteLineIf(Help.WindowsFormsHelpTrace.TraceVerbose, "HelpProvider:: Mouse down w/ helpstring"); - - if (helpString.Length > 0) { - Help.ShowPopup(ctl, helpString, hevent.MousePos); - hevent.Handled = true; - } + Help.ShowPopup(ctl, helpString, hevent.MousePos); + hevent.Handled = true; + return; } // If we have a help file, and help keyword we try F1 help next - // - if (!hevent.Handled && helpNamespace != null) { + if (HelpNamespace != null) + { Debug.WriteLineIf(Help.WindowsFormsHelpTrace.TraceVerbose, "HelpProvider:: F1 help"); - if (keyword != null) { - if (keyword.Length > 0) { - Help.ShowHelp(ctl, helpNamespace, navigator, keyword); - hevent.Handled = true; - } + if (!string.IsNullOrEmpty(keyword)) + { + Help.ShowHelp(ctl, HelpNamespace, navigator, keyword); } - - if (!hevent.Handled) { - Help.ShowHelp(ctl, helpNamespace, navigator); - hevent.Handled = true; + else + { + Help.ShowHelp(ctl, HelpNamespace, navigator); } + + hevent.Handled = true; + return; } // So at this point we don't have a help keyword, so try to display // the whats this help - // - if (!hevent.Handled && helpString != null) { + if (!string.IsNullOrEmpty(helpString)) + { Debug.WriteLineIf(Help.WindowsFormsHelpTrace.TraceVerbose, "HelpProvider:: back to helpstring"); - - if (helpString.Length > 0) { - Help.ShowPopup(ctl, helpString, hevent.MousePos); - hevent.Handled = true; - } - } - - // As a last resort, just popup the contents page of the help file... - // - if (!hevent.Handled && helpNamespace != null) { - Debug.WriteLineIf(Help.WindowsFormsHelpTrace.TraceVerbose, "HelpProvider:: contents"); - - Help.ShowHelp(ctl, helpNamespace); + Help.ShowPopup(ctl, helpString, hevent.MousePos); hevent.Handled = true; + return; } } - - /// - /// - /// Handles the help event for any bound controls. - /// - /// - private void OnQueryAccessibilityHelp(object sender, QueryAccessibilityHelpEventArgs e) { + + /// + /// Handles the help event for any bound controls. + /// + private void OnQueryAccessibilityHelp(object sender, QueryAccessibilityHelpEventArgs e) + { Control ctl = (Control)sender; - + e.HelpString = GetHelpString(ctl); e.HelpKeyword = GetHelpKeyword(ctl); e.HelpNamespace = HelpNamespace; - } + } - /// - /// - /// - /// Specifies - /// a Help string associated with a control. - /// - /// - public virtual void SetHelpString(Control ctl, string helpString) { - helpStrings[ctl] = helpString; - if (helpString != null) { - if (helpString.Length > 0) { - SetShowHelp(ctl, true); - } + /// + /// Specifies a Help string associated with a control. + /// + public virtual void SetHelpString(Control ctl, string helpString) + { + _helpStrings[ctl] = helpString; + if (!string.IsNullOrEmpty(helpString)) + { + SetShowHelp(ctl, true); } + UpdateEventBinding(ctl); } - /// - /// - /// - /// Specifies the Help keyword to display when - /// the user invokes Help for a control. - /// - /// - public virtual void SetHelpKeyword(Control ctl, string keyword) { - keywords[ctl] = keyword; - if (keyword != null) { - if (keyword.Length > 0) { - SetShowHelp(ctl, true); - } + /// + /// Specifies the Help keyword to display when the user invokes Help for a control. + /// + public virtual void SetHelpKeyword(Control ctl, string keyword) + { + _keywords[ctl] = keyword; + if (!string.IsNullOrEmpty(keyword)) + { + SetShowHelp(ctl, true); } + UpdateEventBinding(ctl); } - /// - /// - /// - /// Specifies the Help keyword to display when - /// the user invokes Help for a control. - /// - /// - public virtual void SetHelpNavigator(Control ctl, HelpNavigator navigator) { - //valid values are 0x80000001 to 0x80000007 - if (!ClientUtils.IsEnumValid(navigator, (int)navigator, (int)HelpNavigator.Topic, (int)HelpNavigator.TopicId)){ - //validate the HelpNavigator enum + /// + /// Specifies the Help keyword to display when the user invokes Help for a control. + /// + public virtual void SetHelpNavigator(Control ctl, HelpNavigator navigator) + { + if (!ClientUtils.IsEnumValid(navigator, (int)navigator, (int)HelpNavigator.Topic, (int)HelpNavigator.TopicId)) + { throw new InvalidEnumArgumentException(nameof(navigator), (int)navigator, typeof(HelpNavigator)); } - navigators[ctl] = navigator; + _navigators[ctl] = navigator; SetShowHelp(ctl, true); UpdateEventBinding(ctl); } - /// - /// - /// - /// Specifies whether Help is displayed for a given control. - /// - /// - public virtual void SetShowHelp(Control ctl, bool value) { - showHelp[ ctl] = value ; + + /// + /// Specifies whether Help is displayed for a given control. + /// + public virtual void SetShowHelp(Control ctl, bool value) + { + _showHelp[ctl] = value; UpdateEventBinding(ctl); } - /// - /// - /// Used by the designer - /// - /// - internal virtual bool ShouldSerializeShowHelp(Control ctl) { - return showHelp.ContainsKey(ctl); - } + /// + /// Used by the designer + /// + internal virtual bool ShouldSerializeShowHelp(Control ctl) => _showHelp.ContainsKey(ctl); - /// - /// - /// Used by the designer - /// - /// - public virtual void ResetShowHelp(Control ctl) { - showHelp.Remove(ctl); - } + /// + /// Used by the designer + /// + public virtual void ResetShowHelp(Control ctl) => _showHelp.Remove(ctl); - /// - /// - /// Binds/unbinds event handlers to ctl - /// - /// - private void UpdateEventBinding(Control ctl) { - if (GetShowHelp(ctl) && !boundControls.ContainsKey(ctl)) { + /// + /// Binds/unbinds event handlers to ctl + /// + private void UpdateEventBinding(Control ctl) + { + if (GetShowHelp(ctl) && !_boundControls.ContainsKey(ctl)) + { ctl.HelpRequested += new HelpEventHandler(this.OnControlHelp); ctl.QueryAccessibilityHelp += new QueryAccessibilityHelpEventHandler(this.OnQueryAccessibilityHelp); - boundControls[ctl] = ctl; + _boundControls[ctl] = ctl; } - else if (!GetShowHelp(ctl) && boundControls.ContainsKey(ctl)) { + else if (!GetShowHelp(ctl) && _boundControls.ContainsKey(ctl)) + { ctl.HelpRequested -= new HelpEventHandler(this.OnControlHelp); ctl.QueryAccessibilityHelp -= new QueryAccessibilityHelpEventHandler(this.OnQueryAccessibilityHelp); - boundControls.Remove(ctl); + _boundControls.Remove(ctl); } } - /// - /// - /// Returns a string representation for this control. - /// - /// - public override string ToString() { - string s = base.ToString(); - return s + ", HelpNamespace: " + HelpNamespace; - } + /// + /// Returns a string representation for this control. + /// + public override string ToString() => base.ToString() + ", HelpNamespace: " + HelpNamespace; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlElementCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlElementCollection.cs index 9901d60f52b..e45f73defd1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlElementCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlElementCollection.cs @@ -9,7 +9,6 @@ using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; -using System.Security.Permissions; using System.Security; using System.Runtime.InteropServices; using System.Net; @@ -52,8 +51,8 @@ private UnsafeNativeMethods.IHTMLElementCollection NativeHtmlElementCollection { public HtmlElement this[int index] { get { //do some bounds checking here... - if (index < 0 || index >= this.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidBoundArgument, "index", index, 0, this.Count - 1)); + if (index < 0 || index >= Count) { + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidBoundArgument, nameof(index), index, 0, Count - 1)); } if (this.NativeHtmlElementCollection != null) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlHistory.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlHistory.cs index 3aeb718e3bc..893d2d001c4 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlHistory.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlHistory.cs @@ -53,7 +53,7 @@ public int Length { /// public void Back(int numberBack) { if (numberBack < 0) { - throw new ArgumentOutOfRangeException(nameof(numberBack), string.Format(SR.InvalidLowBoundArgumentEx, "numberBack", numberBack.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(numberBack), numberBack, string.Format(SR.InvalidLowBoundArgumentEx, nameof(numberBack), numberBack, 0)); } else if (numberBack > 0) { object oNumForward = (object)(-numberBack); @@ -64,7 +64,7 @@ public void Back(int numberBack) { /// public void Forward(int numberForward) { if (numberForward < 0) { - throw new ArgumentOutOfRangeException(nameof(numberForward), string.Format(SR.InvalidLowBoundArgumentEx, "numberForward", numberForward.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(numberForward), numberForward, string.Format(SR.InvalidLowBoundArgumentEx, nameof(numberForward), numberForward, 0)); } else if (numberForward > 0) { object oNumForward = (object)numberForward; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlToClrEventProxy.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlToClrEventProxy.cs index 5a400b65825..715816c867b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlToClrEventProxy.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlToClrEventProxy.cs @@ -9,7 +9,6 @@ using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; -using System.Security.Permissions; using System.Security; using System.Runtime.InteropServices; using System.Net; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlWindowCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlWindowCollection.cs index fa4163f783c..56823b69024 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/HtmlWindowCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/HtmlWindowCollection.cs @@ -9,7 +9,6 @@ using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; -using System.Security.Permissions; using System.Security; using System.Runtime.InteropServices; using System.Net; @@ -38,8 +37,8 @@ private UnsafeNativeMethods.IHTMLFramesCollection2 NativeHTMLFramesCollection2 { /// public HtmlWindow this[int index] { get { - if (index < 0 || index >= this.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidBoundArgument, "index", index, 0, this.Count - 1)); + if (index < 0 || index >= Count) { + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidBoundArgument, nameof(index), index, 0, Count - 1)); } object oIndex = (object)index; @@ -59,7 +58,7 @@ public HtmlWindow this[string windowId] { as UnsafeNativeMethods.IHTMLWindow2; } catch (COMException) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "windowId", windowId)); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(windowId), windowId), nameof(windowId)); } return (htmlWindow2 != null) ? new HtmlWindow(shimManager, htmlWindow2) : null; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ImageIndexConverter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ImageIndexConverter.cs index f76dfded7d3..51becdbe049 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ImageIndexConverter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ImageIndexConverter.cs @@ -32,8 +32,8 @@ protected virtual bool IncludeNoneAsStandardValue { /// /// this is the property to look at when there is no ImageList property /// on the current object. For example, in ToolBarButton - the ImageList is - /// on the ToolBarButton.Parent property. In WinBarItem, the ImageList is on - /// the WinBarItem.Owner property. + /// on the ToolBarButton.Parent property. In ToolStripItem, the ImageList is on + /// the ToolStripItem.Owner property. /// internal string ParentImageListProperty { get { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ImageKeyConverter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ImageKeyConverter.cs index 3e1987d30b6..5ad8a328ab7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ImageKeyConverter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ImageKeyConverter.cs @@ -33,8 +33,8 @@ protected virtual bool IncludeNoneAsStandardValue { /// /// this is the property to look at when there is no ImageList property /// on the current object. For example, in ToolBarButton - the ImageList is - /// on the ToolBarButton.Parent property. In WinBarItem, the ImageList is on - /// the WinBarItem.Owner property. + /// on the ToolBarButton.Parent property. In ToolStripItem, the ImageList is on + /// the ToolStripItem.Owner property. /// internal string ParentImageListProperty { get { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ImageList.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ImageList.cs index 18e94789dbe..8ebbadd755a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ImageList.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ImageList.cs @@ -258,11 +258,11 @@ public Size ImageSize { // to keep people's systems from crashing. // if (value.Width <= 0 || value.Width > maxImageWidth) { - throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidBoundArgument, "ImageSize.Width", value.Width.ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture), maxImageWidth.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, "ImageSize.Width", value.Width, 1, maxImageWidth)); } if (value.Height <= 0 || value.Height > maxImageHeight) { - throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidBoundArgument, "ImageSize.Height", value.Height.ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture), maxImageHeight.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, "ImageSize.Height", value.Height, 1, maxImageHeight)); } if (imageSize.Width != value.Width || imageSize.Height != value.Height) { @@ -611,7 +611,7 @@ public void Draw(Graphics g, int x, int y, int index) { /// public void Draw(Graphics g, int x, int y, int width, int height, int index) { if (index < 0 || index >= Images.Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); IntPtr dc = g.GetHdc(); try { SafeNativeMethods.ImageList_DrawEx(new HandleRef(this, Handle), index, new HandleRef(g, dc), x, y, @@ -677,7 +677,7 @@ private static bool BitmapHasAlpha(BitmapData bmpData) { private Bitmap GetBitmap(int index) { if (index < 0 || index >= Images.Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); Bitmap result=null; @@ -746,7 +746,9 @@ private Bitmap GetBitmap(int index) { } // gpr: See Icon for description of fakeTransparencyColor - result.MakeTransparent(fakeTransparencyColor); + if (result.RawFormat.Guid != ImageFormat.Icon.Guid) { + result.MakeTransparent(fakeTransparencyColor); + } return result; } @@ -802,7 +804,7 @@ private void PutImageInTempBitmap(int index, bool useSnapshot) { int count = SafeNativeMethods.ImageList_GetImageCount(handleUse); if (index < 0 || index >= count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString())); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); if (temp != null) { Size size = temp.Size; @@ -1098,12 +1100,12 @@ public Image this[int index] { get { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return owner.GetBitmap(index); } set { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); if (value == null) { throw new ArgumentNullException(nameof(value)); @@ -1116,7 +1118,7 @@ public Image this[int index] { Bitmap bitmap = (Bitmap)value; bool ownsImage = false; - if (owner.UseTransparentColor) { + if (owner.UseTransparentColor && bitmap.RawFormat.Guid != ImageFormat.Icon.Guid) { // Since there's no ImageList_ReplaceMasked, we need to generate // a transparent bitmap Bitmap source = bitmap; @@ -1513,7 +1515,7 @@ void IList.Remove(object image) { /// public void RemoveAt(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); AssertInvariant(); bool ok = SafeNativeMethods.ImageList_Remove(new HandleRef(owner, owner.Handle), index); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/KeyboardToolTipStateMachine.cs b/src/System.Windows.Forms/src/System/Windows/Forms/KeyboardToolTipStateMachine.cs index bc86b7cd7e3..d3640218833 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/KeyboardToolTipStateMachine.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/KeyboardToolTipStateMachine.cs @@ -307,10 +307,9 @@ public override int GetHashCode() { } } - private sealed class InternalStateMachineTimer : Timer { - public void ClearTimerTickHandlers() { - this.onTimer = null; - } + private sealed class InternalStateMachineTimer : Timer + { + public void ClearTimerTickHandlers() => _onTimer = null; } private sealed class ToolToTipDictionary { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Label.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Label.cs index 6747eed64f7..696985d88fc 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Label.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Label.cs @@ -511,7 +511,7 @@ public int ImageIndex { } set { if (value < -1) { - throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "ImageIndex", (value).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); } if (ImageIndex != value) { if (value != -1) { @@ -1455,7 +1455,7 @@ protected override void OnTextChanged(EventArgs e) { Invalidate(); } - if (AccessibilityImprovements.Level3 && LiveSetting != AutomationLiveSetting.Off) { + if (LiveSetting != AutomationLiveSetting.Off) { AccessibilityObject.RaiseLiveRegionChanged(); } } @@ -1488,7 +1488,7 @@ protected override void OnPaint(PaintEventArgs e) { } Color color; - if (AccessibilityImprovements.Level3 && Enabled && SystemInformation.HighContrast) { + if (Enabled && SystemInformation.HighContrast) { color = SystemColors.WindowText; } else { @@ -1658,11 +1658,7 @@ internal void SetToolTip(ToolTip toolTip) { } } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// /// @@ -1684,7 +1680,7 @@ public override string ToString() { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_NCHITTEST: + case Interop.WindowMessages.WM_NCHITTEST: // label returns HT_TRANSPARENT for everything, so all messages get // routed to the parent. Change this so we can tell what's going on. // @@ -1715,13 +1711,7 @@ public override AccessibleRole Role { } } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3) { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/ArrangedElementCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/ArrangedElementCollection.cs index 01cff25945a..05f439e73ed 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/ArrangedElementCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/ArrangedElementCollection.cs @@ -5,7 +5,6 @@ namespace System.Windows.Forms.Layout { using System.Collections; - using System.Security.Permissions; /// public class ArrangedElementCollection : IList diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/PropertyNames.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/PropertyNames.cs index 224eb1b5d84..6009fd039e3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/PropertyNames.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/PropertyNames.cs @@ -71,7 +71,7 @@ internal class PropertyNames { [SuppressMessage("Microsoft.Performance", "CA1802:UseLiteralsWhereAppropriate")] public static readonly string Image= "Image"; [SuppressMessage("Microsoft.Performance", "CA1802:UseLiteralsWhereAppropriate")] - public static readonly string ImageIndex= "ImageIndex"; + public static readonly string ImageIndex= nameof(ImageIndex); [SuppressMessage("Microsoft.Performance", "CA1802:UseLiteralsWhereAppropriate")] public static readonly string ImageScaling= "ImageScaling"; [SuppressMessage("Microsoft.Performance", "CA1802:UseLiteralsWhereAppropriate")] diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/TableLayout.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/TableLayout.cs index 7741c10f805..a92e1bfc0a0 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/TableLayout.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/TableLayout.cs @@ -1241,10 +1241,10 @@ private void SetElementBounds(ContainerInfo containerInfo, RectangleF displayRec internal IArrangedElement GetControlFromPosition (IArrangedElement container, int column, int row) { if (row < 0) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "RowPosition", row.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(row), row, string.Format(SR.InvalidArgument, "RowPosition", row)); } if (column < 0) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "ColumnPosition", column.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(column), column, string.Format(SR.InvalidArgument, "ColumnPosition", column)); } ArrangedElementCollection children = container.Children; ContainerInfo containerInfo = GetContainerInfo(container); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/LinkArea.cs b/src/System.Windows.Forms/src/System/Windows/Forms/LinkArea.cs index 2491b9201e1..9950aff869e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/LinkArea.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/LinkArea.cs @@ -2,240 +2,232 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System; - using System.Reflection; - using System.ComponentModel; - using System.ComponentModel.Design; - using System.ComponentModel.Design.Serialization; - using System.Globalization; - using System.Collections; - - /// - [ - TypeConverterAttribute(typeof(LinkArea.LinkAreaConverter)), - Serializable - ] - public struct LinkArea { - int start; - int length; - - /// - public LinkArea(int start, int length) { +using System.Reflection; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Globalization; +using System.Collections; + +namespace System.Windows.Forms +{ + [TypeConverterAttribute(typeof(LinkArea.LinkAreaConverter))] + [Serializable] + public struct LinkArea + { + private int start; // Do not rename (binary serialization) + private int length; // Do not rename (binary serialization) + + public LinkArea(int start, int length) + { this.start = start; this.length = length; } - - /// - public int Start { - get { - return start; - } - set { - start = value; - } + public int Start + { + get => start; + set => start = value; } - /// - public int Length { - get { - return length; - } - set { - length = value; - } - } - - /// - [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool IsEmpty { - get { - return length == start && start == 0; - } + public int Length + { + get => length; + set => length = value; } - /// - public override bool Equals(object o) { - if (!(o is LinkArea)) { + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool IsEmpty => length == start && start == 0; + + public override bool Equals(object o) + { + if (!(o is LinkArea a)) + { return false; } - - LinkArea a = (LinkArea)o; + return this == a; } - public override string ToString() { - return "{Start=" + Start.ToString(CultureInfo.CurrentCulture) + ", Length=" + Length.ToString(CultureInfo.CurrentCulture) + "}"; + public override string ToString() + { + return "{Start=" + Start + ", Length=" + Length + "}"; } - public static bool operator == (LinkArea linkArea1, LinkArea linkArea2){ - return (linkArea1.start == linkArea2.start) && (linkArea1.length == linkArea2.length); + public static bool operator ==(LinkArea linkArea1, LinkArea linkArea2) + { + return linkArea1.start == linkArea2.start && linkArea1.length == linkArea2.length; } - public static bool operator != (LinkArea linkArea1, LinkArea linkArea2) { + public static bool operator !=(LinkArea linkArea1, LinkArea linkArea2) + { return !(linkArea1 == linkArea2); } - /// - public override int GetHashCode() { - return start << 4 | length; - } - - /// - /// - /// LinkAreaConverter is a class that can be used to convert - /// LinkArea from one data type to another. Access this - /// class through the TypeDescriptor. - /// - public class LinkAreaConverter : TypeConverter { - - /// - /// - /// Determines if this converter can convert an object in the given source - /// type to the native type of the converter. - /// - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { - if (sourceType == typeof(string)) { + public override int GetHashCode() => start << 4 | length; + + /// + /// LinkAreaConverter is a class that can be used to convert LinkArea from one data type + /// to another. Access this class through the TypeDescriptor. + /// + public class LinkAreaConverter : TypeConverter + { + /// + /// Determines if this converter can convert an object in the given source + /// type to the native type of the converter. + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { return true; } + return base.CanConvertFrom(context, sourceType); } - /// - /// - /// Gets a value indicating whether this converter can - /// convert an object to the given destination type using the context. - /// - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { - if (destinationType == typeof(InstanceDescriptor)) { + /// + /// Gets a value indicating whether this converter can convert an object to the + /// given destination type using the context. + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { return true; } + return base.CanConvertTo(context, destinationType); } - /// - /// - /// Converts the given object to the converter's native type. - /// - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - - if (value is string) { - - string text = ((string)value).Trim(); - - if (text.Length == 0) { + /// + /// Converts the given object to the converter's native type. + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string valueStr) + { + string text = valueStr.Trim(); + if (text.Length == 0) + { return null; } - else { - // Parse 2 integer values. - // - if (culture == null) { - culture = CultureInfo.CurrentCulture; - } - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(new char[] {sep}); - int[] values = new int[tokens.Length]; - TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); - for (int i = 0; i < values.Length; i++) { - values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i]); - } + // Parse 2 integer values. + if (culture == null) + { + culture = CultureInfo.CurrentCulture; + } - if (values.Length == 2) { - return new LinkArea(values[0], values[1]); - } - else { - throw new ArgumentException(string.Format(SR.TextParseFailedFormat, - text, - "start, length")); - } + char sep = culture.TextInfo.ListSeparator[0]; + string[] tokens = text.Split(new char[] { sep }); + int[] values = new int[tokens.Length]; + TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); + for (int i = 0; i < values.Length; i++) + { + values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i]); + } + + if (values.Length != 2) + { + throw new ArgumentException(string.Format(SR.TextParseFailedFormat, + text, + "start, length")); } + + return new LinkArea(values[0], values[1]); } return base.ConvertFrom(context, culture, value); } - /// - /// - /// Converts the given object to another type. The most common types to convert - /// are to and from a string object. The default implementation will make a call - /// to ToString on the object if the object is valid and if the destination - /// type is string. If this cannot convert to the desitnation type, this will - /// throw a NotSupportedException. - /// - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - if (destinationType == null) { - throw new ArgumentNullException(nameof(destinationType)); - } - - if (destinationType == typeof(string) && value is LinkArea) { - LinkArea pt = (LinkArea)value; + /// + /// Converts the given object to another type. The most common types to convert + /// are to and from a string object. The default implementation will make a call + /// to ToString on the object if the object is valid and if the destination + /// type is string. If this cannot convert to the desitnation type, this will + /// throw a NotSupportedException. + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (value is LinkArea pt) + { + if (destinationType == typeof(string)) + { + if (culture == null) + { + culture = CultureInfo.CurrentCulture; + } - if (culture == null) { - culture = CultureInfo.CurrentCulture; + string sep = culture.TextInfo.ListSeparator + " "; + TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); + string[] args = new string[] + { + intConverter.ConvertToString(context, culture, pt.Start), + intConverter.ConvertToString(context, culture, pt.Length) + }; + return string.Join(sep, args); } - string sep = culture.TextInfo.ListSeparator + " "; - TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); - string[] args = new string[2]; - int nArg = 0; - - args[nArg++] = intConverter.ConvertToString(context, culture, pt.Start); - args[nArg++] = intConverter.ConvertToString(context, culture, pt.Length); - - return string.Join(sep, args); - } - if (destinationType == typeof(InstanceDescriptor) && value is LinkArea) { - LinkArea pt = (LinkArea)value; - - ConstructorInfo ctor = typeof(LinkArea).GetConstructor(new Type[] {typeof(int), typeof(int)}); - if (ctor != null) { - return new InstanceDescriptor(ctor, new object[] {pt.Start, pt.Length}); + else if (destinationType == typeof(InstanceDescriptor)) + { + return new InstanceDescriptor( + typeof(LinkArea).GetConstructor(new Type[] { typeof(int), typeof(int) }), + new object[] { pt.Start, pt.Length } + ); } } return base.ConvertTo(context, culture, value, destinationType); } - /// - /// - /// Creates an instance of this type given a set of property values - /// for the object. This is useful for objects that are immutable, but still - /// want to provide changable properties. - /// - public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) { - return new LinkArea((int)propertyValues["Start"], - (int)propertyValues["Length"]); - } + /// + /// Creates an instance of this type given a set of property values + /// for the object. This is useful for objects that are immutable, but still + /// want to provide changable properties. + /// + public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) + { + if (propertyValues == null) + { + throw new ArgumentNullException(nameof(propertyValues)); + } - /// - /// - /// Determines if changing a value on this object should require a call to - /// CreateInstance to create a new value. - /// - public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) { - return true; + try + { + return new LinkArea((int)propertyValues[nameof(LinkArea.Start)], + (int)propertyValues[nameof(LinkArea.Length)]); + } + catch (InvalidCastException invalidCast) + { + throw new ArgumentException(SR.PropertyValueInvalidEntry, nameof(propertyValues), invalidCast); + } + catch (NullReferenceException nullRef) + { + throw new ArgumentException(SR.PropertyValueInvalidEntry, nameof(propertyValues), nullRef); + } } - /// - /// - /// Retrieves the set of properties for this type. By default, a type has - /// does not return any properties. An easy implementation of this method - /// can just call TypeDescriptor.GetProperties for the correct data type. - /// - public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { + /// + /// Determines if changing a value on this object should require a call to + /// CreateInstance to create a new value. + /// + public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) => true; + + /// + /// Retrieves the set of properties for this type. By default, a type has + /// does not return any properties. An easy implementation of this method + /// can just call TypeDescriptor.GetProperties for the correct data type. + /// + public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) + { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(LinkArea), attributes); - return props.Sort(new string[] {"Start", "Length"}); + return props.Sort(new string[] { nameof(LinkArea.Start), nameof(LinkArea.Length) }); } - /// - /// - /// Determines if this object supports properties. By default, this - /// is false. - /// - public override bool GetPropertiesSupported(ITypeDescriptorContext context) { - return true; - } - + /// + /// Determines if this object supports properties. By default, this is false. + /// + public override bool GetPropertiesSupported(ITypeDescriptorContext context) => true; } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/LinkConverter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/LinkConverter.cs index 58362605767..57706d155a3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/LinkConverter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/LinkConverter.cs @@ -2,143 +2,134 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Globalization; +using System.Reflection; -namespace System.Windows.Forms { - using System.Runtime.Serialization.Formatters; - using System.Runtime.Remoting; - using System.Runtime.InteropServices; - - using Microsoft.Win32; - using System.Collections; - using System.ComponentModel; - using System.ComponentModel.Design.Serialization; - using System.Drawing; - using System.Diagnostics; - using System.Globalization; - using System.Reflection; - - /// - /// - /// A TypeConverter for LinkLabel.Link objects. Access this - /// class through the TypeDescriptor. - /// - public class LinkConverter : TypeConverter { - - /// - /// - /// Determines if this converter can convert an object in the given source - /// type to the native type of the converter. - /// - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { - if (sourceType == typeof(string)) { +namespace System.Windows.Forms +{ + /// + /// A TypeConverter for LinkLabel.Link objects. Access this class through the TypeDescriptor. + /// + public class LinkConverter : TypeConverter + { + /// + /// Determines if this converter can convert an object in the given source + /// type to the native type of the converter. + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { return true; } + return base.CanConvertFrom(context, sourceType); } - - /// - /// - /// Gets a value indicating whether this converter can - /// convert an object to the given destination type using the context. - /// - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { - if (destinationType == typeof(InstanceDescriptor) || destinationType == typeof(string)) { + + /// + /// Gets a value indicating whether this converter can convert an object to the given + /// destination type using the context. + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor) || destinationType == typeof(string)) + { return true; } + return base.CanConvertTo(context, destinationType); } - /// - /// - /// Converts the given object to the converter's native type. - /// - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - - if (value is string) { - - string text = ((string)value).Trim(); - - if (text.Length == 0) { + /// + /// Converts the given object to the converter's native type. + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string valueStr) + { + string text = valueStr.Trim(); + if (text.Length == 0) + { return null; } - else { - - // Parse 2 integer values - Start & Length of the Link. - // - if (culture == null) { - culture = CultureInfo.CurrentCulture; - } - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(new char[] {sep}); - int[] values = new int[tokens.Length]; - TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); - for (int i = 0; i < values.Length; i++) { - values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i]); - } - - if (values.Length == 2) { - return new LinkLabel.Link(values[0], values[1]); - } - else { - throw new ArgumentException(string.Format(SR.TextParseFailedFormat, - text, - "Start, Length")); - } + + // Parse 2 integer values. + if (culture == null) + { + culture = CultureInfo.CurrentCulture; + } + + char sep = culture.TextInfo.ListSeparator[0]; + string[] tokens = text.Split(new char[] { sep }); + int[] values = new int[tokens.Length]; + TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); + for (int i = 0; i < values.Length; i++) + { + values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i]); } + + if (values.Length != 2) + { + throw new ArgumentException(string.Format(SR.TextParseFailedFormat, + text, + "Start, Length")); + } + + return new LinkLabel.Link(values[0], values[1]); } - + return base.ConvertFrom(context, culture, value); } - - /// - /// - /// Converts the given object to another type. The most common types to convert - /// are to and from a string object. The default implementation will make a call - /// to ToString on the object if the object is valid and if the destination - /// type is string. If this cannot convert to the desitnation type, this will - /// throw a NotSupportedException. - /// - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - if (destinationType == null) { - throw new ArgumentNullException(nameof(destinationType)); - } - if (value is LinkLabel.Link) { - if (destinationType == typeof(string)) { - LinkLabel.Link link = (LinkLabel.Link)value; - - if (culture == null) { + /// + /// Converts the given object to another type. The most common types to convert + /// are to and from a string object. The default implementation will make a call + /// to ToString on the object if the object is valid and if the destination + /// type is string. If this cannot convert to the desitnation type, this will + /// throw a NotSupportedException. + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (value is LinkLabel.Link link) + { + if (destinationType == typeof(string)) + { + if (culture == null) + { culture = CultureInfo.CurrentCulture; } + string sep = culture.TextInfo.ListSeparator + " "; TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); - string[] args = new string[2]; - int nArg = 0; - - args[nArg++] = intConverter.ConvertToString(context, culture, link.Start); - args[nArg++] = intConverter.ConvertToString(context, culture, link.Length); - + string[] args = new string[] + { + intConverter.ConvertToString(context, culture, link.Start), + intConverter.ConvertToString(context, culture, link.Length) + }; return string.Join(sep, args); } - - if (destinationType == typeof(InstanceDescriptor)) { - LinkLabel.Link link = (LinkLabel.Link)value; - MemberInfo info; - if (link.LinkData == null) { - info = typeof(LinkLabel.Link).GetConstructor(new Type[] {typeof(int), typeof(int)}); - if (info != null) { - return new InstanceDescriptor(info, new object[] {link.Start, link.Length}, true); - } - } - else { - info = typeof(LinkLabel.Link).GetConstructor(new Type[] {typeof(int), typeof(int), typeof(object)}); - if (info != null) { - return new InstanceDescriptor(info, new object[] {link.Start, link.Length, link.LinkData}, true); - } + + if (destinationType == typeof(InstanceDescriptor)) + { + if (link.LinkData == null) + { + return new InstanceDescriptor( + typeof(LinkLabel.Link).GetConstructor(new Type[] { typeof(int), typeof(int) }), + new object[] { link.Start, link.Length }, + true + ); } + + return new InstanceDescriptor( + typeof(LinkLabel.Link).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(object) }), + new object[] { link.Start, link.Length, link.LinkData }, + true + ); } } - + return base.ConvertTo(context, culture, value, destinationType); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/LinkLabel.cs b/src/System.Windows.Forms/src/System/Windows/Forms/LinkLabel.cs index 06bdcf039b8..9f334106828 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/LinkLabel.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/LinkLabel.cs @@ -25,9 +25,9 @@ namespace System.Windows.Forms { /// /// - /// - /// Displays text that can contain a hyperlink. - /// + /// + /// Displays text that can contain a hyperlink. + /// /// [ ComVisible(true), @@ -45,8 +45,8 @@ public class LinkLabel : Label, IButtonControl { /// /// - /// The dialog result that will be sent to the parent dialog form when - /// we are clicked. + /// The dialog result that will be sent to the parent dialog form when + /// we are clicked. /// DialogResult dialogResult; @@ -74,9 +74,9 @@ public class LinkLabel : Label, IButtonControl { /// /// - /// - /// Initializes a new default instance of the class. - /// + /// + /// Initializes a new default instance of the class. + /// /// public LinkLabel() : base() { SetStyle(ControlStyles.AllPaintingInWmPaint @@ -90,9 +90,9 @@ public LinkLabel() : base() { /// /// - /// - /// Gets or sets the color used to display active links. - /// + /// + /// Gets or sets the color used to display active links. + /// /// [ SRCategory(nameof(SR.CatAppearance)), @@ -117,9 +117,9 @@ public Color ActiveLinkColor { /// /// - /// - /// Gets or sets the color used to display disabled links. - /// + /// + /// Gets or sets the color used to display disabled links. + /// /// [ SRCategory(nameof(SR.CatAppearance)), @@ -212,9 +212,9 @@ private Rectangle ClientRectWithPadding { /// /// - /// - /// Gets or sets the range in the text that is treated as a link. - /// + /// + /// Gets or sets the range in the text that is treated as a link. + /// /// [ Editor("System.Windows.Forms.Design.LinkAreaEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), @@ -266,9 +266,9 @@ public LinkArea LinkArea { /// /// - /// - /// Gets ir sets a value that represents how the link will be underlined. - /// + /// + /// Gets ir sets a value that represents how the link will be underlined. + /// /// [ DefaultValue(LinkBehavior.SystemDefault), @@ -294,9 +294,9 @@ public LinkBehavior LinkBehavior { /// /// - /// - /// Gets or sets the color used to display links in normal cases. - /// + /// + /// Gets or sets the color used to display links in normal cases. + /// /// [ SRCategory(nameof(SR.CatAppearance)), @@ -324,9 +324,9 @@ public Color LinkColor { /// /// - /// - /// Gets the collection of links used in a . - /// + /// + /// Gets the collection of links used in a . + /// /// [ Browsable(false), @@ -343,9 +343,9 @@ public LinkCollection Links { /// /// - /// - /// Gets or sets a value indicating whether the link should be displayed as if it was visited. - /// + /// + /// Gets or sets a value indicating whether the link should be displayed as if it was visited. + /// /// [ DefaultValue(false), @@ -400,7 +400,7 @@ protected Cursor OverrideCursor { // if ((r.left <= p.x && p.x < r.right && r.top <= p.y && p.y < r.bottom) || UnsafeNativeMethods.GetCapture() == Handle) - SendMessage(NativeMethods.WM_SETCURSOR, Handle, NativeMethods.HTCLIENT); + SendMessage(Interop.WindowMessages.WM_SETCURSOR, Handle, NativeMethods.HTCLIENT); } } } @@ -450,9 +450,9 @@ public override string Text { /// /// - /// - /// Gets or sets the color used to display the link once it has been visited. - /// + /// + /// Gets or sets the color used to display the link once it has been visited. + /// /// [ SRCategory(nameof(SR.CatAppearance)), @@ -480,9 +480,9 @@ public Color VisitedLinkColor { /// /// - /// - /// Occurs when the link is clicked. - /// + /// + /// Occurs when the link is clicked. + /// /// [WinCategory("Action"), SRDescription(nameof(SR.LinkLabelLinkClickedDescr))] public event LinkLabelLinkClickedEventHandler LinkClicked { @@ -534,8 +534,8 @@ internal static Rectangle CalcTextRenderBounds(Rectangle textRect, Rectangle cli /// /// /// - /// Constructs the new instance of the accessibility object for this control. Subclasses - /// should not call base.CreateAccessibilityObject. + /// Constructs the new instance of the accessibility object for this control. Subclasses + /// should not call base.CreateAccessibilityObject. /// protected override AccessibleObject CreateAccessibilityInstance() { return new LinkLabelAccessibleObject(this); @@ -543,11 +543,11 @@ protected override AccessibleObject CreateAccessibilityInstance() { /// /// - /// - /// Creates a handle for this control. This method is called by the .NET Framework, - /// this should not be called. Inheriting classes should always call - /// base.createHandle when overriding this method. - /// + /// + /// Creates a handle for this control. This method is called by the .NET Framework, + /// this should not be called. Inheriting classes should always call + /// base.createHandle when overriding this method. + /// /// protected override void CreateHandle() { base.CreateHandle(); @@ -555,12 +555,12 @@ protected override void CreateHandle() { } /// - /// Determines whether the current state of the control allows for rendering text using - /// TextRenderer (GDI). - /// The Gdi library doesn't currently have a way to calculate character ranges so we cannot - /// use it for painting link(s) within the text, but if the link are is null or covers the - /// entire text we are ok since it is just one area with the same size of the text binding - /// area. + /// Determines whether the current state of the control allows for rendering text using + /// TextRenderer (GDI). + /// The Gdi library doesn't currently have a way to calculate character ranges so we cannot + /// use it for painting link(s) within the text, but if the link are is null or covers the + /// entire text we are ok since it is just one area with the same size of the text binding + /// area. /// internal override bool CanUseTextRenderer { get{ @@ -576,13 +576,13 @@ internal override bool UseGDIMeasuring() { } /// - /// Converts the character index into char index of the string - /// This method is copied in LinkCollectionEditor.cs. Update the other - /// one as well if you change this method. - /// This method mainly deal with surrogate. Suppose we - /// have a string consisting of 3 surrogates, and we want the - /// second character, then the index we need should be 2 instead of - /// 1, and this method returns the correct index. + /// Converts the character index into char index of the string + /// This method is copied in LinkCollectionEditor.cs. Update the other + /// one as well if you change this method. + /// This method mainly deal with surrogate. Suppose we + /// have a string consisting of 3 surrogates, and we want the + /// second character, then the index we need should be 2 instead of + /// 1, and this method returns the correct index. /// private static int ConvertToCharIndex(int index, string text) { if (index <= 0) { @@ -612,8 +612,8 @@ private static int ConvertToCharIndex(int index, string text) { /// /// - /// Ensures that we have analyzed the text run so that we can render each segment - /// and link. + /// Ensures that we have analyzed the text run so that we can render each segment + /// and link. /// private void EnsureRun(Graphics g) { @@ -738,7 +738,7 @@ internal override StringFormat CreateStringFormat() { } /// - /// Calculate character ranges taking into account the locale. Provided for surrogate chars support. + /// Calculate character ranges taking into account the locale. Provided for surrogate chars support. /// private CharacterRange[] AdjustCharacterRangesForSurrogateChars(){ string text = Text; @@ -768,8 +768,8 @@ private CharacterRange[] AdjustCharacterRangesForSurrogateChars(){ } /// - /// Determines whether the whole link label contains only one link, - /// and the link runs from the beginning of the label to the end of it + /// Determines whether the whole link label contains only one link, + /// and the link runs from the beginning of the label to the end of it /// private bool IsOneLink() { if (links == null || links.Count != 1 || Text == null) { @@ -784,8 +784,8 @@ private bool IsOneLink() { /// /// - /// Determines if the given client coordinates is contained within a portion - /// of a link area. + /// Determines if the given client coordinates is contained within a portion + /// of a link area. /// protected Link PointInLink(int x, int y) { Graphics g = CreateGraphicsInternal(); @@ -808,9 +808,9 @@ protected Link PointInLink(int x, int y) { /// /// - /// Invalidates only the portions of the text that is linked to - /// the specified link. If link is null, then all linked text - /// is invalidated. + /// Invalidates only the portions of the text that is linked to + /// the specified link. If link is null, then all linked text + /// is invalidated. /// private void InvalidateLink(Link link) { if (IsHandleCreated) { @@ -825,8 +825,8 @@ private void InvalidateLink(Link link) { /// /// - /// Invalidates the current set of fonts we use when painting - /// links. The fonts will be recreated when needed. + /// Invalidates the current set of fonts we use when painting + /// links. The fonts will be recreated when needed. /// private void InvalidateLinkFonts() { @@ -882,10 +882,10 @@ void IButtonControl.NotifyDefault(bool value) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts")] protected override void OnGotFocus(EventArgs e) { @@ -915,10 +915,10 @@ protected override void OnGotFocus(EventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); @@ -930,10 +930,10 @@ protected override void OnLostFocus(EventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); @@ -947,10 +947,10 @@ protected override void OnKeyDown(KeyEventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); @@ -975,10 +975,10 @@ protected override void OnMouseLeave(EventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); @@ -1005,10 +1005,10 @@ protected override void OnMouseDown(MouseEventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnMouseUp(MouseEventArgs e) { @@ -1041,10 +1041,10 @@ protected override void OnMouseUp(MouseEventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); @@ -1090,9 +1090,9 @@ protected override void OnMouseMove(MouseEventArgs e) { /// /// - /// - /// Raises the event. - /// + /// + /// Raises the event. + /// /// protected virtual void OnLinkClicked(LinkLabelLinkClickedEventArgs e) { LinkLabelLinkClickedEventHandler handler = (LinkLabelLinkClickedEventHandler)Events[EventLinkClicked]; @@ -1108,10 +1108,10 @@ protected override void OnPaddingChanged(EventArgs e) { /// /// - /// - /// Raises the - /// event. - /// + /// + /// Raises the + /// event. + /// /// protected override void OnPaint(PaintEventArgs e) { RectangleF finalrect = RectangleF.Empty; //the focus rectangle if there is only one link @@ -1309,7 +1309,7 @@ protected override void OnAutoSizeChanged(EventArgs e) { } /// - /// Overriden by LinkLabel. + /// Overriden by LinkLabel. /// internal override void OnAutoEllipsisChanged(/*EventArgs e*/) { base.OnAutoEllipsisChanged(/*e*/); @@ -1506,18 +1506,18 @@ void IButtonControl.PerformClick() { /// /// - /// - /// Processes a dialog key. This method is called during message pre-processing - /// to handle dialog characters, such as TAB, RETURN, ESCAPE, and arrow keys. This - /// method is called only if the isInputKey() method indicates that the control - /// isn't interested in the key. processDialogKey() simply sends the character to - /// the parent's processDialogKey() method, or returns false if the control has no - /// parent. The Form class overrides this method to perform actual processing - /// of dialog keys. When overriding processDialogKey(), a control should return true - /// to indicate that it has processed the key. For keys that aren't processed by the - /// control, the result of "base.processDialogChar()" should be returned. Controls - /// will seldom, if ever, need to override this method. - /// + /// + /// Processes a dialog key. This method is called during message pre-processing + /// to handle dialog characters, such as TAB, RETURN, ESCAPE, and arrow keys. This + /// method is called only if the isInputKey() method indicates that the control + /// isn't interested in the key. processDialogKey() simply sends the character to + /// the parent's processDialogKey() method, or returns false if the control has no + /// parent. The Form class overrides this method to perform actual processing + /// of dialog keys. When overriding processDialogKey(), a control should return true + /// to indicate that it has processed the key. For keys that aren't processed by the + /// control, the result of "base.processDialogChar()" should be returned. Controls + /// will seldom, if ever, need to override this method. + /// /// protected override bool ProcessDialogKey(Keys keyData) { if ((keyData & (Keys.Alt | Keys.Control)) != Keys.Alt) { @@ -1641,11 +1641,11 @@ private void ResetVisitedLinkColor() { /// /// - /// - /// Performs the work of setting the bounds of this control. Inheriting classes - /// can overide this function to add size restrictions. Inheriting classes must call - /// base.setBoundsCore to actually cause the bounds of the control to change. - /// + /// + /// Performs the work of setting the bounds of this control. Inheriting classes + /// can overide this function to add size restrictions. Inheriting classes must call + /// base.setBoundsCore to actually cause the bounds of the control to change. + /// /// protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) { @@ -1709,9 +1709,9 @@ protected override void Select(bool directed, bool forward) { /// /// - /// - /// Determines if the color for active links should remain the same. - /// + /// + /// Determines if the color for active links should remain the same. + /// /// internal bool ShouldSerializeActiveLinkColor() { return !activeLinkColor.IsEmpty; @@ -1719,9 +1719,9 @@ internal bool ShouldSerializeActiveLinkColor() { /// /// - /// - /// Determines if the color for disabled links should remain the same. - /// + /// + /// Determines if the color for disabled links should remain the same. + /// /// internal bool ShouldSerializeDisabledLinkColor() { return !disabledLinkColor.IsEmpty; @@ -1729,15 +1729,15 @@ internal bool ShouldSerializeDisabledLinkColor() { /// /// - /// - /// Determines if the range in text that is treated as a - /// link should remain the same. - /// + /// + /// Determines if the range in text that is treated as a + /// link should remain the same. + /// /// private bool ShouldSerializeLinkArea() { if (links.Count == 1) { // use field access to find out if "length" is really -1 - return Links[0].Start != 0 || Links[0].length != -1; + return Links[0].Start != 0 || Links[0]._length != -1; } return true; @@ -1745,17 +1745,17 @@ private bool ShouldSerializeLinkArea() { /// /// - /// - /// Determines if the color of links in normal cases should remain the same. - /// + /// + /// Determines if the color of links in normal cases should remain the same. + /// /// internal bool ShouldSerializeLinkColor() { return !linkColor.IsEmpty; } /// - /// Determines whether designer should generate code for setting the UseCompatibleTextRendering or not. - /// DefaultValue(false) + /// Determines whether designer should generate code for setting the UseCompatibleTextRendering or not. + /// DefaultValue(false) /// private bool ShouldSerializeUseCompatibleTextRendering() { // Serialize code if LinkLabel cannot support the feature or the property's value is not the default. @@ -1764,9 +1764,9 @@ private bool ShouldSerializeUseCompatibleTextRendering() { /// /// - /// - /// Determines if the color of links that have been visited should remain the same. - /// + /// + /// Determines if the color of links that have been visited should remain the same. + /// /// private bool ShouldSerializeVisitedLinkColor() { return !visitedLinkColor.IsEmpty; @@ -1775,9 +1775,9 @@ private bool ShouldSerializeVisitedLinkColor() { /// - /// - /// Update accessibility with the currently focused link. - /// + /// + /// Update accessibility with the currently focused link. + /// /// private void UpdateAccessibilityLink(Link focusLink) { @@ -1797,8 +1797,8 @@ private void UpdateAccessibilityLink(Link focusLink) { /// /// - /// Validates that no links overlap. This will throw an exception if - /// they do. + /// Validates that no links overlap. This will throw an exception if + /// they do. /// private void ValidateNoOverlappingLinks() { for (int x=0; x /// - /// Updates the label's ability to get focus. If there are - /// any links in the label, then the label can get focus, - /// else it can't. + /// Updates the label's ability to get focus. If there are + /// any links in the label, then the label can get focus, + /// else it can't. /// private void UpdateSelectability() { LinkArea pt = LinkArea; @@ -1851,7 +1851,7 @@ private void UpdateSelectability() { } /// - /// Determines whether to use compatible text rendering engine (GDI+) or not (GDI). + /// Determines whether to use compatible text rendering engine (GDI+) or not (GDI). /// [ // DefaultValue(false), - // See ShouldSerailizeUseCompatibleTextRendering method. @@ -1873,15 +1873,11 @@ private void UpdateSelectability() { } } - internal override bool SupportsUiaProviders { - get { - return false; - } - } + internal override bool SupportsUiaProviders => false; /// /// - /// Handles the WM_SETCURSOR message + /// Handles the WM_SETCURSOR message /// /// private void WmSetCursor(ref Message m) { @@ -1909,7 +1905,7 @@ private void WmSetCursor(ref Message m) { /// protected override void WndProc(ref Message msg) { switch (msg.Msg) { - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: WmSetCursor(ref msg); break; default: @@ -1969,7 +1965,7 @@ object IList.this[int index] { /// /// - /// Retrieves the child control with the specified key. + /// Retrieves the child control with the specified key. /// public virtual Link this[string key] { get { @@ -2000,7 +1996,7 @@ public int Count { } /// - /// whether we have added a non-trivial link to the collection + /// whether we have added a non-trivial link to the collection /// public bool LinksAdded { @@ -2059,7 +2055,7 @@ public Link Add(int start, int length, object linkData) { // if (owner.links.Count == 1 && this[0].Start == 0 - && this[0].length == -1) { + && this[0]._length == -1) { owner.links.Clear(); owner.FocusLink = null; @@ -2084,7 +2080,7 @@ public int Add(Link value) { // if (owner.links.Count == 1 && this[0].Start == 0 - && this[0].length == -1) { + && this[0]._length == -1) { owner.links.Clear(); owner.FocusLink = null; @@ -2147,7 +2143,7 @@ public bool Contains(Link link) { /// /// - /// Returns true if the collection contains an item with the specified key, false otherwise. + /// Returns true if the collection contains an item with the specified key, false otherwise. /// public virtual bool ContainsKey(string key) { return IsValidIndex(IndexOfKey(key)); @@ -2182,7 +2178,7 @@ int IList.IndexOf(object link) { /// /// - /// The zero-based index of the first occurrence of value within the entire CollectionBase, if found; otherwise, -1. + /// The zero-based index of the first occurrence of value within the entire CollectionBase, if found; otherwise, -1. /// public virtual int IndexOfKey(string key) { // Step 0 - Arg validation @@ -2213,7 +2209,7 @@ public virtual int IndexOfKey(string key) { /// /// - /// Determines if the index is valid for the collection. + /// Determines if the index is valid for the collection. /// /// private bool IsValidIndex(int index) { @@ -2223,7 +2219,7 @@ private bool IsValidIndex(int index) { /// /// - /// Remove all links from the linkLabel. + /// Remove all links from the linkLabel. /// public virtual void Clear() { bool doLayout = this.owner.links.Count > 0 && this.owner.AutoSize; @@ -2290,7 +2286,7 @@ public void RemoveAt(int index) { /// /// - /// Removes the child control with the specified key. + /// Removes the child control with the specified key. /// public virtual void RemoveByKey(string key) { int index = IndexOfKey(key); @@ -2308,241 +2304,186 @@ void IList.Remove(object value) { } } - /// - [ - TypeConverter(typeof(LinkConverter)) - ] - public class Link { - private int start = 0; - private object linkData = null; - private LinkState state = LinkState.Normal; - private bool enabled = true; - private Region visualRegion; - internal int length = 0; - private LinkLabel owner = null; - private string name = null; - private string description = null; - - private object userData; + [TypeConverter(typeof(LinkConverter))] + public class Link + { + private int _start = 0; + private bool _enabled = true; + internal int _length = 0; + private string _name = null; - /// - public Link() { + public Link() + { } - /// - public Link(int start, int length) { - this.start = start; - this.length = length; + public Link(int start, int length) + { + _start = start; + _length = length; } - /// - public Link(int start, int length, object linkData) { - this.start = start; - this.length = length; - this.linkData = linkData; + public Link(int start, int length, object linkData) + { + _start = start; + _length = length; + LinkData = linkData; } - internal Link(LinkLabel owner) { - this.owner = owner; + internal Link(LinkLabel owner) + { + Owner = owner; } - /// - /// Description for accessibility - /// - public string Description { - get { - return description; - } - set { - description = value; - } - } + /// + /// Description for accessibility + /// + public string Description { get; set; } - /// [DefaultValue(true)] - public bool Enabled { - get { - return enabled; - } - set { - if (enabled != value) { - enabled = value; - - if ((int)(state & (LinkState.Hover | LinkState.Active)) != 0) { - state &= ~(LinkState.Hover | LinkState.Active); - if (owner != null) { - owner.OverrideCursor = null; + public bool Enabled + { + get => _enabled; + set + { + if (_enabled != value) + { + _enabled = value; + + if ((int)(State & (LinkState.Hover | LinkState.Active)) != 0) + { + State &= ~(LinkState.Hover | LinkState.Active); + if (Owner != null) + { + Owner.OverrideCursor = null; } } - if (owner != null) { - owner.InvalidateLink(this); - } + Owner?.InvalidateLink(this); } } } - /// - public int Length { - get { - if (length == -1) { - if (owner != null && !string.IsNullOrEmpty(owner.Text)) { - StringInfo stringInfo = new StringInfo(owner.Text); + public int Length + { + get + { + if (_length == -1) + { + if (Owner != null && !string.IsNullOrEmpty(Owner.Text)) + { + StringInfo stringInfo = new StringInfo(Owner.Text); return stringInfo.LengthInTextElements - Start; } - else { + else + { return 0; } } - return length; + + return _length; } - set { - if (length != value) { - length = value; - if (owner != null) { - owner.InvalidateTextLayout(); - owner.Invalidate(); + set + { + if (_length != value) + { + _length = value; + if (Owner != null) + { + Owner.InvalidateTextLayout(); + Owner.Invalidate(); } } } } - /// [DefaultValue(null)] - public object LinkData { - get { - return linkData; - } - set { - linkData = value; - } - } - - /// - /// - /// The LinkLabel object that owns this link. - /// - internal LinkLabel Owner { - get { - return owner; - } - set { - owner = value; - } - } - - internal LinkState State { - get { - return state; - } - set { - state = value; - } - } - /// - /// - /// The name for the link - useful for indexing by key. - /// - [ - DefaultValue(""), - SRCategory(nameof(SR.CatAppearance)), - SRDescription(nameof(SR.TreeNodeNodeNameDescr)) - ] - public string Name { - get { - return name == null ? "" : name; - } - set { - this.name = value; - } + public object LinkData { get; set; } + + /// + /// The LinkLabel object that owns this link. + /// + internal LinkLabel Owner { get; set; } + + internal LinkState State { get; set; } = LinkState.Normal; + + /// + /// The name for the link - useful for indexing by key. + /// + [DefaultValue("")] + [SRCategory(nameof(SR.CatAppearance))] + [SRDescription(nameof(SR.TreeNodeNodeNameDescr))] + public string Name + { + get => _name ?? string.Empty; + set => _name = value; } - /// - public int Start { - get { - return start; - } - set { - if (start != value) { - start = value; - - if (owner != null) { - owner.links.Sort(LinkLabel.linkComparer); - owner.InvalidateTextLayout(); - owner.Invalidate(); + public int Start + { + get => _start; + set + { + if (_start != value) + { + _start = value; + + if (Owner != null) + { + Owner.links.Sort(LinkLabel.linkComparer); + Owner.InvalidateTextLayout(); + Owner.Invalidate(); } } } } - /// - [ - SRCategory(nameof(SR.CatData)), - Localizable(false), - Bindable(true), - SRDescription(nameof(SR.ControlTagDescr)), - DefaultValue(null), - TypeConverter(typeof(StringConverter)), - ] - public object Tag { - get { - return userData; - } - set { - userData = value; - } - } + [SRCategory(nameof(SR.CatData))] + [Localizable(false)] + [Bindable(true)] + [SRDescription(nameof(SR.ControlTagDescr))] + [DefaultValue(null)] + [TypeConverter(typeof(StringConverter))] + public object Tag { get; set; } - /// [DefaultValue(false)] - public bool Visited { - get { - return(State & LinkState.Visited) == LinkState.Visited; - } - set { - bool old = Visited; - - if (value) { - State |= LinkState.Visited; - } - else { - State &= ~LinkState.Visited; - } + public bool Visited + { + get => (State & LinkState.Visited) == LinkState.Visited; + set + { + if (value != Visited) + { + if (value) + { + State |= LinkState.Visited; + } + else + { + State &= ~LinkState.Visited; + } - if (old != Visited && owner != null) { - owner.InvalidateLink(this); + Owner?.InvalidateLink(this); } } } - internal Region VisualRegion { - get { - return visualRegion; - } - set { - visualRegion = value; - } - } + internal Region VisualRegion { get; set; } } - /// - private class LinkComparer : IComparer { - int IComparer.Compare(object link1, object link2) { - + private class LinkComparer : IComparer + { + int IComparer.Compare(object link1, object link2) + { Debug.Assert(link1 != null && link2 != null, "Null objects sent for comparison"); int pos1 = ((Link)link1).Start; int pos2 = ((Link)link2).Start; - return pos1 - pos2; + return pos1 - pos2; } } - /// - /// - /// - /// - [System.Runtime.InteropServices.ComVisible(true)] + [ComVisible(true)] internal class LinkLabelAccessibleObject : LabelAccessibleObject { /// /// @@ -2550,13 +2491,7 @@ internal class LinkLabelAccessibleObject : LabelAccessibleObject { public LinkLabelAccessibleObject(LinkLabel owner) : base(owner) { } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3) { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; /// /// @@ -2660,22 +2595,13 @@ public override string Name { get { string text = link.Owner.Text; string name; - if (AccessibilityImprovements.Level3) { - // return the full name of the link label for AI.Level3 - // as sometimes the link name in isolation is unusable - // to a customer using a screen reader - name = text; - if (link.Owner.UseMnemonic) { - name = WindowsFormsUtils.TextWithoutMnemonics(name); - } - } else { - int charStart = LinkLabel.ConvertToCharIndex(link.Start, text); - int charEnd = LinkLabel.ConvertToCharIndex(link.Start + link.Length, text); - name = text.Substring(charStart, charEnd - charStart); - if (AccessibilityImprovements.Level1 && link.Owner.UseMnemonic) { - // return the same value as the tooltip shows. - name = WindowsFormsUtils.TextWithoutMnemonics(name); - } + + // return the full name of the link label + // as sometimes the link name in isolation + // is unusable when using a screen reader + name = text; + if (link.Owner.UseMnemonic) { + name = WindowsFormsUtils.TextWithoutMnemonics(name); } return name; @@ -2714,12 +2640,9 @@ public override AccessibleStates State { public override string Value { get { - if (AccessibilityImprovements.Level1) { - // Narrator announces Link's text twice, once as a Name property and once as a Value, thus removing value. - // Value is optional for this role (Link). - return string.Empty; - } - return Name; + // Narrator announces Link's text twice, once as a Name property and once as a Value, thus removing value. + // Value is optional for this role (Link). + return string.Empty; } } @@ -2727,13 +2650,7 @@ public override void DoDefaultAction() { link.Owner.OnLinkClicked(new LinkLabelLinkClickedEventArgs(link)); } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3) { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override object GetPropertyValue(int propertyID) { if (propertyID == NativeMethods.UIA_IsEnabledPropertyId) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ListBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ListBox.cs index 473af5eee8f..e08307786e1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ListBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ListBox.cs @@ -288,10 +288,11 @@ public int ColumnWidth { } set { - if (value < 0) { - throw new ArgumentException(string.Format(SR.InvalidLowBoundArgumentEx, "value", - (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(value), value, 0)); } + if (columnWidth != value) { columnWidth = value; // if it's zero, we need to reset, and only way to do @@ -610,7 +611,7 @@ public virtual int ItemHeight { set { if (value < 1 || value > 255) { - throw new ArgumentOutOfRangeException(nameof(ItemHeight), string.Format(SR.InvalidExBoundArgument, "ItemHeight", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture), "256")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidExBoundArgument, nameof(ItemHeight), value, 0, 256)); } if (itemHeight != value) { itemHeight = value; @@ -868,11 +869,11 @@ public override int SelectedIndex { int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count; if (value < -1 || value >= itemCount) { - throw new ArgumentOutOfRangeException(nameof(SelectedIndex), string.Format(SR.InvalidArgument, "SelectedIndex", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SelectedIndex), value)); } if (selectionMode == SelectionMode.None) { - throw new ArgumentException(SR.ListBoxInvalidSelectionMode, "SelectedIndex"); + throw new ArgumentException(SR.ListBoxInvalidSelectionMode, nameof(value)); } if (selectionMode == SelectionMode.One && value != -1) { @@ -1364,72 +1365,34 @@ public void EndUpdate() { --updateCount; } - /// /// - /// Finds the first item in the list box that starts with the given string. - /// The search is not case sensitive. + /// Finds the first item in the list box that starts with the given string. + /// The search is not case sensitive. /// - public int FindString(string s) { - return FindString(s, -1); - } + public int FindString(string s) => FindString(s, startIndex: -1); - /// /// - /// Finds the first item after the given index which starts with the given - /// string. The search is not case sensitive. + /// Finds the first item after the given index which starts with the given string. + /// The search is not case sensitive. /// - public int FindString(string s, int startIndex) { - if (s == null) return -1; - - int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count; - - if (itemCount == 0) { - return -1; - } - - // The last item in the list is still a valid starting point for a search. - if (startIndex < -1 || startIndex >= itemCount) { - throw new ArgumentOutOfRangeException(nameof(startIndex)); - } - - // Always use the managed FindStringInternal instead of LB_FINDSTRING. - // The managed version correctly handles Turkish I. - return FindStringInternal(s, Items, startIndex, false); + public int FindString(string s, int startIndex) + { + return FindStringInternal(s, itemsCollection, startIndex, exact: false, ignoreCase: true); } - /// /// - /// Finds the first item in the list box that matches the given string. - /// The strings must match exactly, except for differences in casing. + /// Finds the first item in the list box that matches the given string. + /// The strings must match exactly, except for differences in casing. /// - public int FindStringExact(string s) { - return FindStringExact(s, -1); - } + public int FindStringExact(string s) => FindStringExact(s, startIndex: -1); - /// /// - /// Finds the first item after the given index that matches the given - /// string. The strings must match excatly, except for differences in - /// casing. + /// Finds the first item after the given index that matches the given string. + /// The strings must match excatly, except for differences in casing. /// - public int FindStringExact(string s, int startIndex) { - if (s == null) return -1; - - int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count; - - if (itemCount == 0) { - return -1; - } - - // The last item in the list is still a valid starting point for a search. - if (startIndex < -1 || startIndex >= itemCount) { - throw new ArgumentOutOfRangeException(nameof(startIndex)); - } - - // Always use the managed FindStringInternal instead of LB_FINDSTRING. - // The managed version correctly handles Turkish I. - // - return FindStringInternal(s, Items, startIndex, true); + public int FindStringExact(string s, int startIndex) + { + return FindStringInternal(s, itemsCollection, startIndex, exact: true, ignoreCase: true); } /// @@ -1444,7 +1407,7 @@ public int GetItemHeight(int index) { // no items. // if (index < 0 || (index > 0 && index >= itemCount)) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); if (drawMode != DrawMode.OwnerDrawVariable) index = 0; @@ -2080,7 +2043,7 @@ protected override void SetItemCore(int index, object value) { public void SetSelected(int index, bool value) { int itemCount = (itemsCollection == null) ? 0: itemsCollection.Count; if (index < 0 || index >= itemCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); if (selectionMode == SelectionMode.None) throw new InvalidOperationException(SR.ListBoxInvalidSelectionMode); @@ -2329,25 +2292,25 @@ private void WmReflectMeasureItem(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_COMMAND: WmReflectCommand(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_DRAWITEM: WmReflectDrawItem(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_MEASUREITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_MEASUREITEM: WmReflectMeasureItem(ref m); break; - case NativeMethods.WM_PRINT: + case Interop.WindowMessages.WM_PRINT: WmPrint(ref m); break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: if (selectedItems != null) { selectedItems.Dirty(); } base.WndProc(ref m); break; - case NativeMethods.WM_LBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: // Get the mouse location // int x = NativeMethods.Util.SignedLOWORD(m.LParam); @@ -2394,7 +2357,7 @@ protected override void WndProc(ref Message m) { doubleClickFired = false; break; - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: // Get the mouse location // int rx = NativeMethods.Util.SignedLOWORD(m.LParam); @@ -2410,7 +2373,7 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); break; - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: //the Listbox gets WM_LBUTTONDOWN - WM_LBUTTONUP -WM_LBUTTONDBLCLK - WM_LBUTTONUP... //sequence for doubleclick... //the first WM_LBUTTONUP, resets the flag for Doubleclick @@ -2419,7 +2382,7 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); break; - case NativeMethods.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: base.WndProc(ref m); if (integralHeight && fontIsChanged) { Height = Math.Max(Height,ItemHeight); @@ -3089,7 +3052,7 @@ internal void AddRangeInternal(ICollection items) { public virtual object this[int index] { get { if (index < 0 || index >= InnerArray.GetCount(0)) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } return InnerArray.GetItem(index, 0); @@ -3197,7 +3160,7 @@ public void Insert(int index, object item) { owner.CheckNoDataSource(); if (index < 0 || index > InnerArray.GetCount(0)) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (item == null) { @@ -3253,7 +3216,7 @@ public void RemoveAt(int index) { owner.CheckNoDataSource(); if (index < 0 || index >= InnerArray.GetCount(0)) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } owner.UpdateMaxItemWidth(InnerArray.GetItem(index, 0), true); @@ -3275,7 +3238,7 @@ internal void SetItemInternal(int index, object value) { } if (index < 0 || index >= InnerArray.GetCount(0)) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } owner.UpdateMaxItemWidth(InnerArray.GetItem(index, 0), true); @@ -3569,7 +3532,7 @@ public void Remove(int item) { /// public void RemoveAt(int index) { if (index < 0 || index >= count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } count--; @@ -3597,7 +3560,7 @@ public int this[int index] { set { if (index < 0 || index >= count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } innerArray[index] = (int)value; owner.UpdateCustomTabOffsets(); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ListControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ListControl.cs index 9ef1c87ab29..05c0c7d4865 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ListControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ListControl.cs @@ -2,308 +2,313 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Runtime.Serialization.Formatters; - using System.Runtime.Remoting; - using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Drawing.Design; +using System.Collections; +using System.ComponentModel; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms +{ + [ComVisible(true)] + [ClassInterface(ClassInterfaceType.AutoDispatch)] + [LookupBindingProperties(nameof(ListControl.DataSource), nameof(ListControl.DisplayMember), nameof(ListControl.ValueMember), nameof(ListControl.SelectedValue))] + public abstract class ListControl : Control + { + private static readonly object s_dataSourceChangedEvent = new object(); + private static readonly object s_displayMemberChangedEvent = new object(); + private static readonly object s_valueMemberChangedEvent = new object(); + private static readonly object s_selectedValueChangedEvent = new object(); + private static readonly object s_formatInfoChangedEvent = new object(); + private static readonly object s_formatStringChangedEvent = new object(); + private static readonly object s_formattingEnabledChangedEvent = new object(); + private static readonly object s_formatEvent = new object(); + + private object _dataSource; + private CurrencyManager _dataManager; + private BindingMemberInfo _displayMember; + private BindingMemberInfo _valueMember; + + private string _formatString = string.Empty; + private IFormatProvider _formatInfo = null; + private bool _formattingEnabled = false; + private TypeConverter _displayMemberConverter = null; + private static TypeConverter _stringTypeConverter = null; + + private bool _isDataSourceInitialized; + private bool _isDataSourceInitEventHooked; + private bool _inSetDataConnection = false; - using System.Diagnostics; - - using System; - using System.Security.Permissions; - using System.Globalization; - using System.Windows.Forms; - - using System.Drawing.Design; - using System.ComponentModel; - using System.Windows.Forms.ComponentModel; - - using System.Collections; - using System.Drawing; - using Microsoft.Win32; - using System.Text; - - /// - [ - ComVisible(true), - ClassInterface(ClassInterfaceType.AutoDispatch), - LookupBindingProperties("DataSource", "DisplayMember", "ValueMember", "SelectedValue") - ] - public abstract class ListControl : Control { - - private static readonly object EVENT_DATASOURCECHANGED = new object(); - private static readonly object EVENT_DISPLAYMEMBERCHANGED = new object(); - private static readonly object EVENT_VALUEMEMBERCHANGED = new object(); - private static readonly object EVENT_SELECTEDVALUECHANGED = new object(); - private static readonly object EVENT_FORMATINFOCHANGED = new object(); - private static readonly object EVENT_FORMATSTRINGCHANGED = new object(); - private static readonly object EVENT_FORMATTINGENABLEDCHANGED = new object(); - - private object dataSource; - private CurrencyManager dataManager; - private BindingMemberInfo displayMember; - private BindingMemberInfo valueMember; - - // Formatting stuff - private string formatString = string.Empty; - private IFormatProvider formatInfo = null; - private bool formattingEnabled = false; - private static readonly object EVENT_FORMAT = new object(); - private TypeConverter displayMemberConverter = null; - private static TypeConverter stringTypeConverter = null; - - private bool isDataSourceInitialized; - private bool isDataSourceInitEventHooked; - private bool inSetDataConnection = false; - - /// /// - /// The ListSource to consume as this ListBox's source of data. - /// When set, a user can not modify the Items collection. + /// The ListSource to consume as this ListBox's source of data. + /// When set, a user can not modify the Items collection. /// - [ - SRCategory(nameof(SR.CatData)), - DefaultValue(null), - RefreshProperties(RefreshProperties.Repaint), - AttributeProvider(typeof(IListSource)), - SRDescription(nameof(SR.ListControlDataSourceDescr)) - ] - public object DataSource { - get { - return dataSource; - } - set { + [SRCategory(nameof(SR.CatData))] + [DefaultValue(null)] + [RefreshProperties(RefreshProperties.Repaint)] + [AttributeProvider(typeof(IListSource))] + [SRDescription(nameof(SR.ListControlDataSourceDescr))] + public object DataSource + { + get => _dataSource; + set + { if (value != null && !(value is IList || value is IListSource)) - throw new ArgumentException(SR.BadDataSourceForComplexBinding); - if (dataSource == value) + { + throw new ArgumentException(SR.BadDataSourceForComplexBinding, nameof(value)); + } + + if (_dataSource == value) + { return; + } + // When we change the dataSource to null, we should reset // the displayMember to "". - try { - SetDataConnection(value, displayMember, false); - } catch { + try + { + SetDataConnection(value, _displayMember, force: false); + } + catch + { // There are several possibilities why setting the data source throws an exception: // 1. the app throws an exception in the events that fire when we change the data source: DataSourceChanged, // 2. we get an exception when we set the data source and populate the list controls (say,something went wrong while formatting the data) // 3. the DisplayMember does not fit w/ the new data source (this could happen if the user resets the data source but did not reset the DisplayMember) // in all cases ListControl should reset the DisplayMember to String.Empty // the ListControl should also eat the exception - this is the RTM behavior and doing anything else is a breaking change - DisplayMember = ""; + DisplayMember = string.Empty; } if (value == null) - DisplayMember = ""; + { + DisplayMember = string.Empty; + } } } - /// - [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.ListControlOnDataSourceChangedDescr))] - public event EventHandler DataSourceChanged { - add { - Events.AddHandler(EVENT_DATASOURCECHANGED, value); + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlOnDataSourceChangedDescr))] + public event EventHandler DataSourceChanged + { + add + { + Events.AddHandler(s_dataSourceChangedEvent, value); } - remove { - Events.RemoveHandler(EVENT_DATASOURCECHANGED, value); + remove + { + Events.RemoveHandler(s_dataSourceChangedEvent, value); } } - /// - protected CurrencyManager DataManager { - get { - return this.dataManager; - } - } + protected CurrencyManager DataManager => _dataManager; - /// /// - /// If the ListBox contains objects that support properties, this indicates - /// which property of the object to show. If "", the object shows it's ToString(). + /// If the ListBox contains objects that support properties, this indicates + /// which property of the object to show. If "", the object shows it's ToString(). /// - [ - SRCategory(nameof(SR.CatData)), - DefaultValue(""), - TypeConverterAttribute("System.Windows.Forms.Design.DataMemberFieldConverter, " + AssemblyRef.SystemDesign), - Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + AssemblyRef.SystemDesign, typeof(System.Drawing.Design.UITypeEditor)), - SRDescription(nameof(SR.ListControlDisplayMemberDescr)) - ] - public string DisplayMember { - get { - return displayMember.BindingMember; - } - set { - BindingMemberInfo oldDisplayMember = displayMember; - try { - SetDataConnection(dataSource, new BindingMemberInfo(value), false); - } catch { - displayMember = oldDisplayMember; - } - } - } - - /// - [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.ListControlOnDisplayMemberChangedDescr))] - public event EventHandler DisplayMemberChanged { - add { - Events.AddHandler(EVENT_DISPLAYMEMBERCHANGED, value); - } - remove { - Events.RemoveHandler(EVENT_DISPLAYMEMBERCHANGED, value); - } - } - - // Cached type converter of the property associated with the display member - private TypeConverter DisplayMemberConverter { - get { - if (this.displayMemberConverter == null && - this.DataManager != null && - this.displayMember != null) { - PropertyDescriptorCollection props = this.DataManager.GetItemProperties(); - if (props != null) { - PropertyDescriptor displayMemberProperty = props.Find(this.displayMember.BindingField, true); + [SRCategory(nameof(SR.CatData))] + [DefaultValue("")] + [TypeConverterAttribute("System.Windows.Forms.Design.DataMemberFieldConverter, " + AssemblyRef.SystemDesign)] + [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] + [SRDescription(nameof(SR.ListControlDisplayMemberDescr))] + public string DisplayMember + { + get => _displayMember.BindingMember; + set + { + BindingMemberInfo oldDisplayMember = _displayMember; + try + { + SetDataConnection(_dataSource, new BindingMemberInfo(value), force: false); + } + catch + { + _displayMember = oldDisplayMember; + } + } + } + + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlOnDisplayMemberChangedDescr))] + public event EventHandler DisplayMemberChanged + { + add + { + Events.AddHandler(s_displayMemberChangedEvent, value); + } + remove + { + Events.RemoveHandler(s_displayMemberChangedEvent, value); + } + } + + /// + /// Cached type converter of the property associated with the display member + /// + private TypeConverter DisplayMemberConverter + { + get + { + if (_displayMemberConverter == null) + { + PropertyDescriptorCollection props = DataManager?.GetItemProperties(); + if (props != null) + { + PropertyDescriptor displayMemberProperty = props.Find(_displayMember.BindingField, true); if (displayMemberProperty != null) { - this.displayMemberConverter = displayMemberProperty.Converter; + _displayMemberConverter = displayMemberProperty.Converter; } } } - return this.displayMemberConverter; + + return _displayMemberConverter; } } - /// - [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.ListControlFormatDescr))] + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlFormatDescr))] public event ListControlConvertEventHandler Format { - add { - Events.AddHandler(EVENT_FORMAT, value); + add + { + Events.AddHandler(s_formatEvent, value); RefreshItems(); } - remove { - Events.RemoveHandler(EVENT_FORMAT, value); + remove + { + Events.RemoveHandler(s_formatEvent, value); RefreshItems(); } } - /// - [ - Browsable(false), - EditorBrowsable(EditorBrowsableState.Advanced), - DefaultValue(null) - ] - public IFormatProvider FormatInfo { - get { - return this.formatInfo; - } - set { - if (value != formatInfo) { - formatInfo = value; + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Advanced)] + [DefaultValue(null)] + public IFormatProvider FormatInfo + { + get => _formatInfo; + set + { + if (value != _formatInfo) + { + _formatInfo = value; RefreshItems(); OnFormatInfoChanged(EventArgs.Empty); } } } - /// - [ - Browsable(false), - EditorBrowsable(EditorBrowsableState.Advanced), - SRCategory(nameof(SR.CatPropertyChanged)), - SRDescription(nameof(SR.ListControlFormatInfoChangedDescr)) - ] - public event EventHandler FormatInfoChanged { - add { - Events.AddHandler(EVENT_FORMATINFOCHANGED, value); + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Advanced)] + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlFormatInfoChangedDescr))] + public event EventHandler FormatInfoChanged + { + add + { + Events.AddHandler(s_formatInfoChangedEvent, value); } - remove { - Events.RemoveHandler(EVENT_FORMATINFOCHANGED, value); + remove + { + Events.RemoveHandler(s_formatInfoChangedEvent, value); } } - [ - DefaultValue(""), - SRDescription(nameof(SR.ListControlFormatStringDescr)), - EditorAttribute("System.Windows.Forms.Design.FormatStringEditor, " + AssemblyRef.SystemDesign, typeof(System.Drawing.Design.UITypeEditor)), - MergableProperty(false) - ] - /// - public string FormatString { - get { - return formatString; - } - set { + [DefaultValue("")] + [SRDescription(nameof(SR.ListControlFormatStringDescr))] + [EditorAttribute("System.Windows.Forms.Design.FormatStringEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] + [MergableProperty(false)] + public string FormatString + { + get => _formatString; + set + { if (value == null) + { value = string.Empty; - if (!value.Equals(formatString)) { - formatString = value; + } + + if (!value.Equals(_formatString)) + { + _formatString = value; RefreshItems(); OnFormatStringChanged(EventArgs.Empty); } } } - - /// - [ - SRCategory(nameof(SR.CatPropertyChanged)), - SRDescription(nameof(SR.ListControlFormatStringChangedDescr)) - ] - public event EventHandler FormatStringChanged { - add { - Events.AddHandler(EVENT_FORMATSTRINGCHANGED, value); + + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlFormatStringChangedDescr))] + public event EventHandler FormatStringChanged + { + add + { + Events.AddHandler(s_formatStringChangedEvent, value); } - remove { - Events.RemoveHandler(EVENT_FORMATSTRINGCHANGED, value); + remove + { + Events.RemoveHandler(s_formatStringChangedEvent, value); } } - /// - [ - DefaultValue(false), - SRDescription(nameof(SR.ListControlFormattingEnabledDescr)) - ] - public bool FormattingEnabled { - get { - return formattingEnabled; - } - set { - if (value != formattingEnabled) { - formattingEnabled = value; + [DefaultValue(false)] + [SRDescription(nameof(SR.ListControlFormattingEnabledDescr))] + public bool FormattingEnabled + { + get => _formattingEnabled; + set + { + if (value != _formattingEnabled) + { + _formattingEnabled = value; RefreshItems(); OnFormattingEnabledChanged(EventArgs.Empty); } } } - /// - [ - SRCategory(nameof(SR.CatPropertyChanged)), - SRDescription(nameof(SR.ListControlFormattingEnabledChangedDescr)) - ] - public event EventHandler FormattingEnabledChanged { - add { - Events.AddHandler(EVENT_FORMATTINGENABLEDCHANGED, value); + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlFormattingEnabledChangedDescr))] + public event EventHandler FormattingEnabledChanged + { + add + { + Events.AddHandler(s_formattingEnabledChangedEvent, value); } - remove { - Events.RemoveHandler(EVENT_FORMATTINGENABLEDCHANGED, value); + remove + { + Events.RemoveHandler(s_formattingEnabledChangedEvent, value); } } - private bool BindingMemberInfoInDataManager(BindingMemberInfo bindingMemberInfo) { - if (dataManager == null) - return false; + private static bool BindingMemberInfoInDataManager(CurrencyManager dataManager, BindingMemberInfo bindingMemberInfo) + { + Debug.Assert(dataManager != null); + PropertyDescriptorCollection props = dataManager.GetItemProperties(); - int propsCount = props.Count; - for (int i = 0; i < propsCount; i++) { + for (int i = 0; i < props.Count; i++) + { if (typeof(IList).IsAssignableFrom(props[i].PropertyType)) + { continue; - if (props[i].Name.Equals(bindingMemberInfo.BindingField)) { + } + if (props[i].Name.Equals(bindingMemberInfo.BindingField)) + { return true; } } - for (int i = 0; i < propsCount; i++) { + for (int i = 0; i < props.Count; i++) + { if (typeof(IList).IsAssignableFrom(props[i].PropertyType)) + { continue; - if (string.Compare(props[i].Name, bindingMemberInfo.BindingField, true, CultureInfo.CurrentCulture) == 0) { + } + if (string.Equals(props[i].Name, bindingMemberInfo.BindingField, StringComparison.CurrentCultureIgnoreCase)) + { return true; } } @@ -311,506 +316,525 @@ private bool BindingMemberInfoInDataManager(BindingMemberInfo bindingMemberInfo) return false; } - /// - [ - SRCategory(nameof(SR.CatData)), - DefaultValue(""), - Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + AssemblyRef.SystemDesign, typeof(System.Drawing.Design.UITypeEditor)), - SRDescription(nameof(SR.ListControlValueMemberDescr)) - ] - public string ValueMember { - get { - return valueMember.BindingMember; - } - set { + [SRCategory(nameof(SR.CatData))] + [DefaultValue("")] + [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] + [SRDescription(nameof(SR.ListControlValueMemberDescr))] + public string ValueMember + { + get => _valueMember.BindingMember; + set + { if (value == null) - value = ""; + { + value = string.Empty; + } + BindingMemberInfo newValueMember = new BindingMemberInfo(value); - BindingMemberInfo oldValueMember = valueMember; - if (!newValueMember.Equals(valueMember)) { + BindingMemberInfo oldValueMember = _valueMember; + if (!newValueMember.Equals(_valueMember)) + { // If the displayMember is set to the EmptyString, then recreate the dataConnection - // if (DisplayMember.Length == 0) - SetDataConnection(DataSource, newValueMember, false); + { + SetDataConnection(DataSource, newValueMember, force: false); + } + // See if the valueMember is a member of // the properties in the dataManager - if (this.dataManager != null && value != null && value.Length != 0) - if (!BindingMemberInfoInDataManager(newValueMember)) { - throw new ArgumentException(SR.ListControlWrongValueMember, "value"); + if (DataManager != null && !string.IsNullOrEmpty(value)) + { + if (!BindingMemberInfoInDataManager(DataManager, newValueMember)) + { + throw new ArgumentException(SR.ListControlWrongValueMember, nameof(value)); } + } - valueMember = newValueMember; + _valueMember = newValueMember; OnValueMemberChanged(EventArgs.Empty); OnSelectedValueChanged(EventArgs.Empty); } } - } + } - /// - [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.ListControlOnValueMemberChangedDescr))] - public event EventHandler ValueMemberChanged { - add { - Events.AddHandler(EVENT_VALUEMEMBERCHANGED, value); + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlOnValueMemberChangedDescr))] + public event EventHandler ValueMemberChanged + { + add + { + Events.AddHandler(s_valueMemberChangedEvent, value); } - remove { - Events.RemoveHandler(EVENT_VALUEMEMBERCHANGED, value); + remove + { + Events.RemoveHandler(s_valueMemberChangedEvent, value); } } - /// /// - /// Indicates whether list currently allows selection of list items. + /// Indicates whether list currently allows selection of list items. /// - protected virtual bool AllowSelection { - get { - return true; - } - } - - /// - public abstract int SelectedIndex { - get; - set; - } - - /// - [ - SRCategory(nameof(SR.CatData)), - DefaultValue(null), - Browsable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - SRDescription(nameof(SR.ListControlSelectedValueDescr)), - Bindable(true) - ] - public object SelectedValue { - get { - if (SelectedIndex != -1 && dataManager != null ) { - object currentItem = dataManager[SelectedIndex]; - object filteredItem = FilterItemOnProperty(currentItem, valueMember.BindingField); - return filteredItem; + protected virtual bool AllowSelection => true; + + public abstract int SelectedIndex { get; set; } + + [SRCategory(nameof(SR.CatData))] + [DefaultValue(null)] + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [SRDescription(nameof(SR.ListControlSelectedValueDescr))] + [Bindable(true)] + public object SelectedValue + { + get + { + if (SelectedIndex != -1 && _dataManager != null) + { + object currentItem = _dataManager[SelectedIndex]; + return FilterItemOnProperty(currentItem, _valueMember.BindingField); } + return null; } - set { - if (dataManager != null) { - string propertyName = valueMember.BindingField; - // we can't set the SelectedValue property when the listManager does not + set + { + if (_dataManager != null) + { + string propertyName = _valueMember.BindingField; + // We can't set the SelectedValue property when the listManager does not // have a ValueMember set. if (string.IsNullOrEmpty(propertyName)) + { throw new InvalidOperationException(SR.ListControlEmptyValueMemberInSettingSelectedValue); - PropertyDescriptorCollection props = dataManager.GetItemProperties(); + } + + PropertyDescriptorCollection props = _dataManager.GetItemProperties(); PropertyDescriptor property = props.Find(propertyName, true); - int index = dataManager.Find(property, value, true); - this.SelectedIndex = index; + int index = _dataManager.Find(property, value, true); + SelectedIndex = index; } } } - - /// - [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.ListControlOnSelectedValueChangedDescr))] - public event EventHandler SelectedValueChanged { - add { - Events.AddHandler(EVENT_SELECTEDVALUECHANGED, value); + + [SRCategory(nameof(SR.CatPropertyChanged))] + [SRDescription(nameof(SR.ListControlOnSelectedValueChangedDescr))] + public event EventHandler SelectedValueChanged + { + add + { + Events.AddHandler(s_selectedValueChangedEvent, value); } - remove { - Events.RemoveHandler(EVENT_SELECTEDVALUECHANGED, value); + remove + { + Events.RemoveHandler(s_selectedValueChangedEvent, value); } } - private void DataManager_PositionChanged(object sender, EventArgs e) { - if (this.dataManager != null) { - if (AllowSelection) { - this.SelectedIndex = dataManager.Position; + private void DataManager_PositionChanged(object sender, EventArgs e) + { + if (DataManager != null) + { + if (AllowSelection) + { + SelectedIndex = _dataManager.Position; } } } - private void DataManager_ItemChanged(object sender, ItemChangedEventArgs e) { + private void DataManager_ItemChanged(object sender, ItemChangedEventArgs e) + { // Note this is being called internally with a null event. - if (dataManager != null) { - if (e.Index == -1) { - SetItemsCore(dataManager.List); - if (AllowSelection) { - this.SelectedIndex = this.dataManager.Position; + if (_dataManager != null) + { + if (e.Index == -1) + { + SetItemsCore(_dataManager.List); + if (AllowSelection) + { + SelectedIndex = DataManager.Position; } } - else { - SetItemCore(e.Index, dataManager[e.Index]); + else + { + SetItemCore(e.Index, _dataManager[e.Index]); } } } - /// - /// - protected object FilterItemOnProperty(object item) { - return FilterItemOnProperty(item, displayMember.BindingField); + protected object FilterItemOnProperty(object item) + { + return FilterItemOnProperty(item, _displayMember.BindingField); } - - /// - /// - protected object FilterItemOnProperty(object item, string field) { - if (item != null && field.Length > 0) { - try { + + protected object FilterItemOnProperty(object item, string field) + { + if (item != null && !string.IsNullOrEmpty(field)) + { + try + { // if we have a dataSource, then use that to display the string PropertyDescriptor descriptor; - if (this.dataManager != null) - descriptor = this.dataManager.GetItemProperties().Find(field, true); + if (DataManager != null) + { + descriptor = DataManager.GetItemProperties().Find(field, true); + } else + { descriptor = TypeDescriptor.GetProperties(item).Find(field, true); - if (descriptor != null) { + } + if (descriptor != null) + { item = descriptor.GetValue(item); } } - catch { + catch + { } } - return item; - } - - //We use this to prevent getting the selected item when mouse is hovering over the dropdown. - // - internal bool BindingFieldEmpty { - get { - return (displayMember.BindingField.Length > 0 ? false : true); - } + return item; } - internal int FindStringInternal(string str, IList items, int startIndex, bool exact) { - return FindStringInternal(str, items, startIndex, exact, true); - } + /// + /// We use this to prevent getting the selected item when mouse is hovering + /// over the dropdown. + /// + private protected bool BindingFieldEmpty => _displayMember.BindingField.Length == 0; - internal int FindStringInternal(string str, IList items, int startIndex, bool exact, bool ignorecase) { - - // Sanity check parameters - // - if (str == null || items == null) { + private protected int FindStringInternal(string str, IList items, int startIndex, bool exact, bool ignoreCase) + { + if (str == null) + { return -1; } - // The last item in the list is still a valid place to start looking! - if (startIndex < -1 || startIndex >= items.Count) { + if (items == null || items.Count == 0) + { return -1; } - - bool found = false; - int length = str.Length; + if (startIndex < -1 || startIndex >= items.Count) + { + throw new ArgumentOutOfRangeException(nameof(startIndex)); + } // Start from the start index and wrap around until we find the string - // in question. Use a separate counter to ensure that we arent cycling through the list infinitely. + // in question. Use a separate counter to ensure that we arent cycling through the list infinitely. int numberOfTimesThroughLoop = 0; // this API is really Find NEXT String... - for (int index = (startIndex+1) % items.Count; numberOfTimesThroughLoop < items.Count; index = (index+1) % items.Count) { + for (int index = (startIndex + 1) % items.Count; numberOfTimesThroughLoop < items.Count; index = (index + 1) % items.Count) + { numberOfTimesThroughLoop++; - if (exact) { - found = string.Compare(str, GetItemText(items[index]), ignorecase, CultureInfo.CurrentCulture) == 0; + + bool found; + if (exact) + { + found = string.Compare(str, GetItemText(items[index]), ignoreCase, CultureInfo.CurrentCulture) == 0; } - else { - found = string.Compare(str, 0, GetItemText(items[index]), 0, length, ignorecase, CultureInfo.CurrentCulture) == 0; + else + { + found = string.Compare(str, 0, GetItemText(items[index]), 0, str.Length, ignoreCase, CultureInfo.CurrentCulture) == 0; } - - if (found) { + + if (found) + { return index; } - } - + return -1; } - /// public string GetItemText(object item) { + if (!_formattingEnabled) + { + if (item == null) + { + return string.Empty; + } - // !formattingEnabled == RTM behaviour - if (!formattingEnabled) { - - if (item == null) { + item = FilterItemOnProperty(item, _displayMember.BindingField); + if (item == null) + { return string.Empty; } - item = FilterItemOnProperty(item, displayMember.BindingField); - return (item != null) ? Convert.ToString(item, CultureInfo.CurrentCulture) : ""; + return Convert.ToString(item, CultureInfo.CurrentCulture); } - // - // Whidbey formatting features - // + object filteredItem = FilterItemOnProperty(item, _displayMember.BindingField); - object filteredItem = FilterItemOnProperty(item, displayMember.BindingField); - - // first try: the OnFormat event - ListControlConvertEventArgs e = new ListControlConvertEventArgs(filteredItem, typeof(string), item); + // First try the OnFormat event + var e = new ListControlConvertEventArgs(filteredItem, typeof(string), item); OnFormat(e); - - // Microsoft: we need a better check. Should add the Handled property on the ListControlConvertEventArgs? - if (e.Value != item && e.Value is string) { - return (string) e.Value; + if (e.Value != item && e.Value is string stringValue) + { + return stringValue; } - // try Formatter::FormatObject - if (stringTypeConverter == null) - { - stringTypeConverter = TypeDescriptor.GetConverter(typeof(string)); - } + // Try Formatter.FormatObject + if (_stringTypeConverter == null) + { + _stringTypeConverter = TypeDescriptor.GetConverter(typeof(string)); + } try { - return (string) Formatter.FormatObject(filteredItem, typeof(string), this.DisplayMemberConverter, stringTypeConverter, formatString, formatInfo, null, System.DBNull.Value); + return (string)Formatter.FormatObject(filteredItem, typeof(string), DisplayMemberConverter, _stringTypeConverter, _formatString, _formatInfo, null, DBNull.Value); } - catch (Exception exception) + catch (Exception exception) when (!ClientUtils.IsSecurityOrCriticalException(exception)) { - if (ClientUtils.IsSecurityOrCriticalException(exception)) - { - throw; - } // if we did not do any work then return the old ItemText - return (filteredItem != null) ? Convert.ToString(item, CultureInfo.CurrentCulture) : ""; + return Convert.ToString(item, CultureInfo.CurrentCulture); } } - /// /// - /// Handling special input keys, such as pgup, pgdown, home, end, etc... + /// Handling special input keys, such as PageUp, PageDown, Home, End, etc... /// - protected override bool IsInputKey(Keys keyData) { - if ((keyData & Keys.Alt) == Keys.Alt) return false; - switch (keyData & Keys.KeyCode) { + protected override bool IsInputKey(Keys keyData) + { + if ((keyData & Keys.Alt) == Keys.Alt) + { + return false; + } + + switch (keyData & Keys.KeyCode) + { case Keys.PageUp: case Keys.PageDown: case Keys.Home: case Keys.End: return true; } + return base.IsInputKey(keyData); } - - /// - protected override void OnBindingContextChanged(EventArgs e) { - SetDataConnection(dataSource, displayMember, true); - + + protected override void OnBindingContextChanged(EventArgs e) + { + SetDataConnection(_dataSource, _displayMember, force: true); base.OnBindingContextChanged(e); } - - /// - protected virtual void OnDataSourceChanged(EventArgs e) { - EventHandler eh = Events[EVENT_DATASOURCECHANGED] as EventHandler; - if (eh != null) { - eh(this, e); - } + protected virtual void OnDataSourceChanged(EventArgs e) + { + EventHandler eh = Events[s_dataSourceChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - /// - protected virtual void OnDisplayMemberChanged(EventArgs e) { - EventHandler eh = Events[EVENT_DISPLAYMEMBERCHANGED] as EventHandler; - if (eh != null) { - eh(this, e); - } + protected virtual void OnDisplayMemberChanged(EventArgs e) + { + EventHandler eh = Events[s_displayMemberChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - /// - protected virtual void OnFormat(ListControlConvertEventArgs e) { - ListControlConvertEventHandler eh = Events[EVENT_FORMAT] as ListControlConvertEventHandler; - if (eh != null) - eh(this, e); + protected virtual void OnFormat(ListControlConvertEventArgs e) + { + ListControlConvertEventHandler eh = Events[s_formatEvent] as ListControlConvertEventHandler; + eh?.Invoke(this, e); } - /// - protected virtual void OnFormatInfoChanged(EventArgs e) { - EventHandler eh = Events[EVENT_FORMATINFOCHANGED] as EventHandler; - if (eh != null) - eh(this,e); + protected virtual void OnFormatInfoChanged(EventArgs e) + { + EventHandler eh = Events[s_formatInfoChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - /// - protected virtual void OnFormatStringChanged(EventArgs e) { - EventHandler eh = Events[EVENT_FORMATSTRINGCHANGED] as EventHandler; - if (eh != null) - eh(this,e); + protected virtual void OnFormatStringChanged(EventArgs e) + { + EventHandler eh = Events[s_formatStringChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - - /// - protected virtual void OnFormattingEnabledChanged(EventArgs e) { - EventHandler eh = Events[EVENT_FORMATTINGENABLEDCHANGED] as EventHandler; - if (eh != null) - eh(this,e); + + protected virtual void OnFormattingEnabledChanged(EventArgs e) + { + EventHandler eh = Events[s_formattingEnabledChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - - /// + /// - /// Actually goes and fires the selectedIndexChanged event. Inheriting controls - /// should use this to know when the event is fired [this is preferable to - /// adding an event handler on yourself for this event]. They should, - /// however, remember to call base.OnSelectedIndexChanged(e); to ensure the event is - /// still fired to external listeners + /// Actually goes and fires the selectedIndexChanged event. Inheriting controls + /// should use this to know when the event is fired [this is preferable to + /// adding an event handler on yourself for this event]. They should, + /// however, remember to call base.OnSelectedIndexChanged(e); to ensure the event is + /// still fired to external listeners /// - protected virtual void OnSelectedIndexChanged(EventArgs e) { - OnSelectedValueChanged(EventArgs.Empty); + protected virtual void OnSelectedIndexChanged(EventArgs e) + { + OnSelectedValueChanged(e); } - /// - protected virtual void OnValueMemberChanged(EventArgs e) { - EventHandler eh = Events[EVENT_VALUEMEMBERCHANGED] as EventHandler; - if (eh != null) { - eh(this, e); - } + protected virtual void OnValueMemberChanged(EventArgs e) + { + EventHandler eh = Events[s_valueMemberChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - /// - protected virtual void OnSelectedValueChanged(EventArgs e) { - EventHandler eh = Events[EVENT_SELECTEDVALUECHANGED] as EventHandler; - if (eh != null) { - eh(this, e); - } + protected virtual void OnSelectedValueChanged(EventArgs e) + { + EventHandler eh = Events[s_selectedValueChangedEvent] as EventHandler; + eh?.Invoke(this, e); } - /// protected abstract void RefreshItem(int index); - - /// - protected virtual void RefreshItems() { + + protected virtual void RefreshItems() + { } - - private void DataSourceDisposed(object sender, EventArgs e) { - Debug.Assert(sender == this.dataSource, "how can we get dispose notification for anything other than our dataSource?"); - SetDataConnection(null, new BindingMemberInfo(""), true); + + private void DataSourceDisposed(object sender, EventArgs e) + { + SetDataConnection(null, new BindingMemberInfo(string.Empty), true); } - private void DataSourceInitialized(object sender, EventArgs e) { - ISupportInitializeNotification dsInit = (this.dataSource as ISupportInitializeNotification); - Debug.Assert(dsInit != null, "ListControl: ISupportInitializeNotification.Initialized event received, but current DataSource does not support ISupportInitializeNotification!"); - Debug.Assert(dsInit.IsInitialized, "ListControl: DataSource sent ISupportInitializeNotification.Initialized event but before it had finished initializing."); - SetDataConnection(this.dataSource, this.displayMember, true); + private void DataSourceInitialized(object sender, EventArgs e) + { + SetDataConnection(_dataSource, _displayMember, true); } - private void SetDataConnection(object newDataSource, BindingMemberInfo newDisplayMember, bool force) { - bool dataSourceChanged = dataSource != newDataSource; - bool displayMemberChanged = !displayMember.Equals(newDisplayMember); + private void SetDataConnection(object newDataSource, BindingMemberInfo newDisplayMember, bool force) + { + bool dataSourceChanged = _dataSource != newDataSource; + bool displayMemberChanged = !_displayMember.Equals(newDisplayMember); - // make sure something interesting is happening... - // - //force = force && (dataSource != null || newDataSource != null); - if (inSetDataConnection) { + if (_inSetDataConnection) + { return; } - try { - if (force || dataSourceChanged || displayMemberChanged) { - inSetDataConnection = true; - IList currentList = this.DataManager != null ? this.DataManager.List : null; - bool currentManagerIsNull = this.DataManager == null; + try + { + if (force || dataSourceChanged || displayMemberChanged) + { + _inSetDataConnection = true; + IList currentList = DataManager?.List; + bool currentManagerIsNull = DataManager == null; UnwireDataSource(); - dataSource = newDataSource; - displayMember = newDisplayMember; + _dataSource = newDataSource; + _displayMember = newDisplayMember; WireDataSource(); // Provided the data source has been fully initialized, start listening to change events on its // currency manager and refresh our list. If the data source has not yet been initialized, we will // skip this step for now, and try again later (once the data source has fired its Initialized event). - // - if (isDataSourceInitialized) { - + if (_isDataSourceInitialized) + { CurrencyManager newDataManager = null; - if (newDataSource != null && BindingContext != null && !(newDataSource == Convert.DBNull)) { + if (newDataSource != null && BindingContext != null && newDataSource != Convert.DBNull) + { newDataManager = (CurrencyManager)BindingContext[newDataSource, newDisplayMember.BindingPath]; } - if (dataManager != newDataManager) { - if (dataManager != null) { - dataManager.ItemChanged -= new ItemChangedEventHandler(DataManager_ItemChanged); - dataManager.PositionChanged -= new EventHandler(DataManager_PositionChanged); + if (_dataManager != newDataManager) + { + if (_dataManager != null) + { + _dataManager.ItemChanged -= new ItemChangedEventHandler(DataManager_ItemChanged); + _dataManager.PositionChanged -= new EventHandler(DataManager_PositionChanged); } - dataManager = newDataManager; + _dataManager = newDataManager; - if (dataManager != null) { - dataManager.ItemChanged += new ItemChangedEventHandler(DataManager_ItemChanged); - dataManager.PositionChanged += new EventHandler(DataManager_PositionChanged); + if (_dataManager != null) + { + _dataManager.ItemChanged += new ItemChangedEventHandler(DataManager_ItemChanged); + _dataManager.PositionChanged += new EventHandler(DataManager_PositionChanged); } } // See if the BindingField in the newDisplayMember is valid // The same thing if dataSource Changed // "" is a good value for displayMember - if (dataManager != null && (displayMemberChanged || dataSourceChanged) && displayMember.BindingMember != null && displayMember.BindingMember.Length != 0) { - - if (!BindingMemberInfoInDataManager(displayMember)) - throw new ArgumentException(SR.ListControlWrongDisplayMember, "newDisplayMember"); + if (_dataManager != null && (displayMemberChanged || dataSourceChanged) && !string.IsNullOrEmpty(_displayMember.BindingMember)) + { + if (!BindingMemberInfoInDataManager(_dataManager, _displayMember)) + { + throw new ArgumentException(SR.ListControlWrongDisplayMember, nameof(newDisplayMember)); + } } - if (dataManager != null && (dataSourceChanged || displayMemberChanged || force)) { - // if we force a new data manager, then change the items in the list control + if (_dataManager != null && (dataSourceChanged || displayMemberChanged || force)) + { + // If we force a new data manager, then change the items in the list control // only if the list changed or if we go from a null dataManager to a full fledged one // or if the DisplayMember changed - if (displayMemberChanged || (force && (currentList != this.dataManager.List || currentManagerIsNull))) { - DataManager_ItemChanged(dataManager, new ItemChangedEventArgs(-1)); + if (displayMemberChanged || (force && (currentList != DataManager.List || currentManagerIsNull))) + { + DataManager_ItemChanged(_dataManager, new ItemChangedEventArgs(-1)); } } } - this.displayMemberConverter = null; + + _displayMemberConverter = null; } - if (dataSourceChanged) { + if (dataSourceChanged) + { OnDataSourceChanged(EventArgs.Empty); } - if (displayMemberChanged) { + if (displayMemberChanged) + { OnDisplayMemberChanged(EventArgs.Empty); } } - finally { - inSetDataConnection = false; + finally + { + _inSetDataConnection = false; } } - private void UnwireDataSource() { - // If the source is a component, then unhook the Disposed event - if (this.dataSource is IComponent) { - ((IComponent) this.dataSource).Disposed -= new EventHandler(DataSourceDisposed); - } - - ISupportInitializeNotification dsInit = (this.dataSource as ISupportInitializeNotification); + private void UnwireDataSource() + { + // If the source is a component, then unhook the Disposed event + if (_dataSource is IComponent componentDataSource) + { + componentDataSource.Disposed -= new EventHandler(DataSourceDisposed); + } - if (dsInit != null && isDataSourceInitEventHooked) { - // If we previously hooked the data source's ISupportInitializeNotification - // Initialized event, then unhook it now (we don't always hook this event, - // only if we needed to because the data source was previously uninitialized) - dsInit.Initialized -= new EventHandler(DataSourceInitialized); - isDataSourceInitEventHooked = false; - } + if (_dataSource is ISupportInitializeNotification dsInit && _isDataSourceInitEventHooked) + { + // If we previously hooked the data source's ISupportInitializeNotification + // Initialized event, then unhook it now (we don't always hook this event, + // only if we needed to because the data source was previously uninitialized) + dsInit.Initialized -= new EventHandler(DataSourceInitialized); + _isDataSourceInitEventHooked = false; + } } - private void WireDataSource() { - // If the source is a component, then hook the Disposed event, - // so we know when the component is deleted from the form - if (this.dataSource is IComponent) { - ((IComponent) this.dataSource).Disposed += new EventHandler(DataSourceDisposed); - } - - ISupportInitializeNotification dsInit = (this.dataSource as ISupportInitializeNotification); + private void WireDataSource() + { + // If the source is a component, then hook the Disposed event, + // so we know when the component is deleted from the form + if (_dataSource is IComponent componentDataSource) + { + componentDataSource.Disposed += new EventHandler(DataSourceDisposed); + } - if (dsInit != null && !dsInit.IsInitialized) { - // If the source provides initialization notification, and is not yet - // fully initialized, then hook the Initialized event, so that we can - // delay connecting to it until it *is* initialized. - dsInit.Initialized += new EventHandler(DataSourceInitialized); - isDataSourceInitEventHooked = true; - isDataSourceInitialized = false; - } - else { - // Otherwise either the data source says it *is* initialized, or it - // does not support the capability to report whether its initialized, - // in which case we have to just assume it that is initialized. - isDataSourceInitialized = true; - } + if (_dataSource is ISupportInitializeNotification dsInit && !dsInit.IsInitialized) + { + // If the source provides initialization notification, and is not yet + // fully initialized, then hook the Initialized event, so that we can + // delay connecting to it until it *is* initialized. + dsInit.Initialized += new EventHandler(DataSourceInitialized); + _isDataSourceInitEventHooked = true; + _isDataSourceInitialized = false; + } + else + { + // Otherwise either the data source says it *is* initialized, or it + // does not support the capability to report whether its initialized, + // in which case we have to just assume it that is initialized. + _isDataSourceInitialized = true; + } } - /// protected abstract void SetItemsCore(IList items); - /// - protected virtual void SetItemCore(int index, object value) {} + protected virtual void SetItemCore(int index, object value) + { + } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ListView.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ListView.cs index 3fc3393a163..ce166ab9877 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ListView.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ListView.cs @@ -228,10 +228,6 @@ public ListView() : base() { LISTVIEWSTATE_labelWrap | LISTVIEWSTATE_autoArrange | LISTVIEWSTATE_showGroups; - if (!AccessibilityImprovements.Level3) { - // Show grey rectangle around the selected list item if the list view is out of focus. - listViewStateFlags |= LISTVIEWSTATE_hideSelection; - } listViewState = new System.Collections.Specialized.BitVector32(listViewStateFlags); @@ -1768,7 +1764,7 @@ public int VirtualListSize { } set { if (value < 0) - throw new System.ArgumentException(string.Format(SR.ListViewVirtualListSizeInvalidArgument, "value", (value.ToString(CultureInfo.CurrentCulture)))); + throw new System.ArgumentException(string.Format(SR.ListViewVirtualListSizeInvalidArgument, "value", (value))); if (value == virtualListSize) return; bool keepTopItem = this.IsHandleCreated && VirtualMode && this.View == View.Details && !this.DesignMode; @@ -2149,9 +2145,7 @@ public void ArrangeIcons(ListViewAlignment value) { break; default: - throw new ArgumentException(string.Format(SR.InvalidArgument, - "value", - ((value).ToString()))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(value), value), nameof(value)); } if (!VirtualMode && sorting != SortOrder.None) { @@ -2773,8 +2767,6 @@ unsafe void CustomDraw(ref Message m) { private void DeleteFileName(string fileName) { if (!string.IsNullOrEmpty(fileName)) { - // the list view needs the FileIOPermission when the app runs on an UNC share - // and the list view creates / destroys temporary files for its background image System.IO.FileInfo fi = new System.IO.FileInfo(fileName); if (fi.Exists) { @@ -2867,9 +2859,7 @@ protected override void Dispose(bool disposing) { } if (!string.IsNullOrEmpty(this.backgroundImageFileName) || this.bkImgFileNames != null) { - // we need the fileIoPermission when the app runs on an UNC share and - // the list view creates/deletes temporary files for its background image - + System.IO.FileInfo fi; if (!string.IsNullOrEmpty(this.backgroundImageFileName)) { fi = new System.IO.FileInfo(this.backgroundImageFileName); @@ -2937,7 +2927,7 @@ private void EnsureDefaultGroup() { /// public void EnsureVisible(int index) { if (index < 0 || index >= Items.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (IsHandleCreated) UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.LVM_ENSUREVISIBLE, index, 0); @@ -2968,7 +2958,7 @@ public ListViewItem FindItemWithText(string text, bool includeSubItemsInSearch, public ListViewItem FindItemWithText(string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch) { if (startIndex < 0 || startIndex >= this.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(startIndex), string.Format(SR.InvalidArgument, "startIndex", (startIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex, string.Format(SR.InvalidArgument, nameof(startIndex), startIndex)); } return FindItem(true, text, isPrefixSearch, new Point(0,0), SearchDirectionHint.Down, startIndex, includeSubItemsInSearch); } @@ -2990,7 +2980,7 @@ public ListViewItem FindNearestItem(SearchDirectionHint searchDirection, int x, } if ( searchDirection < SearchDirectionHint.Left || searchDirection > SearchDirectionHint.Down) { - throw new ArgumentOutOfRangeException(nameof(searchDirection), string.Format(SR.InvalidArgument, "searchDirection", (searchDirection).ToString())); + throw new ArgumentOutOfRangeException(nameof(searchDirection), searchDirection, string.Format(SR.InvalidArgument, nameof(searchDirection), searchDirection)); } // the win32 ListView::FindNearestItem does some pretty weird things to determine the nearest item. @@ -3267,7 +3257,7 @@ internal int GetItemState(int index) { internal int GetItemState(int index, int mask) { if (index < 0 || ((this.VirtualMode && index >= this.VirtualListSize) || (!this.VirtualMode && index >= itemCount))) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } Debug.Assert(IsHandleCreated, "How did we add items without a handle?"); @@ -3288,7 +3278,7 @@ public Rectangle GetItemRect(int index) { /// public Rectangle GetItemRect(int index, ItemBoundsPortion portion) { if (index < 0 || index >= this.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } //valid values are 0x0 to 0x3 if (!ClientUtils.IsEnumValid(portion, (int)portion, (int)ItemBoundsPortion.Entire, (int)ItemBoundsPortion.ItemOnly)){ @@ -3303,9 +3293,7 @@ public Rectangle GetItemRect(int index, ItemBoundsPortion portion) { NativeMethods.RECT itemrect = new NativeMethods.RECT(); itemrect.left = (int)portion; if (unchecked( (int) (long)SendMessage(NativeMethods.LVM_GETITEMRECT, index, ref itemrect)) == 0) - throw new ArgumentException(string.Format(SR.InvalidArgument, - "index", - (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return Rectangle.FromLTRB(itemrect.left, itemrect.top, itemrect.right, itemrect.bottom); } @@ -3376,12 +3364,12 @@ internal Rectangle GetSubItemRect(int itemIndex, int subItemIndex, ItemBoundsPor return Rectangle.Empty; } if (itemIndex < 0 || itemIndex >= this.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(itemIndex), string.Format(SR.InvalidArgument, "itemIndex", (itemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(itemIndex), itemIndex, string.Format(SR.InvalidArgument, nameof(itemIndex), itemIndex)); } int subItemCount = Items[itemIndex].SubItems.Count; if (subItemIndex < 0 || subItemIndex >= subItemCount) { - throw new ArgumentOutOfRangeException(nameof(subItemIndex), string.Format(SR.InvalidArgument, "subItemIndex", (subItemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(subItemIndex), subItemIndex, string.Format(SR.InvalidArgument, nameof(subItemIndex), subItemIndex)); } //valid values are 0x0 to 0x3 if (!ClientUtils.IsEnumValid(portion, (int)portion, (int)ItemBoundsPortion.Entire, (int)ItemBoundsPortion.ItemOnly)) @@ -3397,9 +3385,7 @@ internal Rectangle GetSubItemRect(int itemIndex, int subItemIndex, ItemBoundsPor itemrect.left = (int)portion; itemrect.top = subItemIndex; if (unchecked( (int) (long)SendMessage(NativeMethods.LVM_GETSUBITEMRECT, itemIndex, ref itemrect)) == 0) - throw new ArgumentException(string.Format(SR.InvalidArgument, - "itemIndex", - (itemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(itemIndex), itemIndex, string.Format(SR.InvalidArgument, nameof(itemIndex), itemIndex)); Rectangle result = Rectangle.FromLTRB(itemrect.left, itemrect.top, itemrect.right, itemrect.bottom); @@ -3787,7 +3773,7 @@ private int InsertItemsNative(int index, ListViewItem[] items) { if (hGlobalColumns != IntPtr.Zero) { Marshal.FreeHGlobal(hGlobalColumns); } - hGlobalColumns = Marshal.AllocHGlobal(lvItem.cColumns * Marshal.SizeOf(typeof(int))); + hGlobalColumns = Marshal.AllocHGlobal(lvItem.cColumns * sizeof(int)); maxColumns = lvItem.cColumns; } @@ -4431,13 +4417,13 @@ private unsafe void PositionHeader() { IntPtr prc = IntPtr.Zero; IntPtr pwpos = IntPtr.Zero; - prc = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.RECT))); + prc = Marshal.AllocHGlobal(Marshal.SizeOf()); if (prc == IntPtr.Zero) { return; } try { - pwpos = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.WINDOWPOS))); + pwpos = Marshal.AllocHGlobal(Marshal.SizeOf()); if (prc == IntPtr.Zero) { // we could not allocate memory. @@ -4455,7 +4441,7 @@ private unsafe void PositionHeader() { UnsafeNativeMethods.SendMessage(new HandleRef(this, hdrHWND), NativeMethods.HDM_LAYOUT, 0, ref hd); // now take the information from the native wpos struct and put it into a managed WINDOWPOS - NativeMethods.WINDOWPOS wpos = (NativeMethods.WINDOWPOS) Marshal.PtrToStructure(pwpos, typeof(NativeMethods.WINDOWPOS)); + NativeMethods.WINDOWPOS wpos = Marshal.PtrToStructure(pwpos); // position the header control SafeNativeMethods.SetWindowPos(new HandleRef(this, hdrHWND), @@ -4531,22 +4517,22 @@ public void RedrawItems(int startIndex, int endIndex, bool invalidateOnly) { if (startIndex < 0 || startIndex >= this.VirtualListSize) { - throw new ArgumentOutOfRangeException(nameof(startIndex), string.Format(SR.InvalidArgument, "startIndex", (startIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex, string.Format(SR.InvalidArgument, nameof(startIndex), startIndex)); } if (endIndex < 0 || endIndex >= this.VirtualListSize) { - throw new ArgumentOutOfRangeException(nameof(endIndex), string.Format(SR.InvalidArgument, "endIndex", (endIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(endIndex), endIndex, string.Format(SR.InvalidArgument, nameof(endIndex), endIndex)); } } else { if (startIndex < 0 || startIndex >= this.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(startIndex), string.Format(SR.InvalidArgument, "startIndex", (startIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex, string.Format(SR.InvalidArgument, nameof(startIndex), startIndex)); } if (endIndex < 0 || endIndex >= this.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(endIndex), string.Format(SR.InvalidArgument, "endIndex", (endIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(endIndex), endIndex, string.Format(SR.InvalidArgument, nameof(endIndex), endIndex)); } } if (startIndex > endIndex) @@ -4644,9 +4630,6 @@ private void SetBackgroundImage() { if (this.BackgroundImage != null) { - // the list view needs these permissions when the app runs on an UNC share - // and the list view creates / destroys temporary files for its background image - // save the image to a temporary file name string tempDirName = System.IO.Path.GetTempPath(); System.Text.StringBuilder sb = new System.Text.StringBuilder(1024); @@ -4761,7 +4744,7 @@ internal void SetColumnWidth(int columnIndex, ColumnHeaderAutoResizeStyle header if ((columnIndex < 0) || (columnIndex >= 0 && this.columnHeaders == null) || (columnIndex >= this.columnHeaders.Length)) { - throw new ArgumentOutOfRangeException(nameof(columnIndex), string.Format(SR.InvalidArgument, "columnIndex", (columnIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(columnIndex), columnIndex, string.Format(SR.InvalidArgument, nameof(columnIndex), columnIndex)); } //valid values are 0x0 to 0x2 @@ -4894,7 +4877,7 @@ internal void SetToolTip(ToolTip toolTip, string toolTipCaption) { internal void SetItemImage(int index, int image) { if (index < 0 || ((this.VirtualMode && index >= this.VirtualListSize) || (!this.VirtualMode && index >= itemCount))) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (this.IsHandleCreated) { NativeMethods.LVITEM lvItem = new NativeMethods.LVITEM(); @@ -4907,7 +4890,7 @@ internal void SetItemImage(int index, int image) { internal void SetItemIndentCount(int index, int indentCount) { if (index < 0 || ((this.VirtualMode && index >= this.VirtualListSize) || (!this.VirtualMode && index >= itemCount))) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (this.IsHandleCreated) { NativeMethods.LVITEM lvItem = new NativeMethods.LVITEM(); @@ -4922,7 +4905,7 @@ internal void SetItemPosition(int index, int x, int y) { if (VirtualMode) return; if (index < 0 || index >= itemCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); Debug.Assert(IsHandleCreated, "How did we add items without a handle?"); @@ -4934,7 +4917,7 @@ internal void SetItemPosition(int index, int x, int y) { internal void SetItemState(int index, int state, int mask) { if (index < -1 || ((this.VirtualMode && index >= this.VirtualListSize) || (!this.VirtualMode && index >= itemCount))) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } Debug.Assert(index == -1 || this.IsHandleCreated, "How did we add items without a handle?"); @@ -5276,7 +5259,7 @@ private void WmMouseDown(ref Message m, MouseButtons button, int clicks) { } else { // When a user clicks on the state image, focus the item. - if (AccessibilityImprovements.Level2 && lvhti.Item != null && lvhti.Location == ListViewHitTestLocations.StateImage) { + if (lvhti.Item != null && lvhti.Location == ListViewHitTestLocations.StateImage) { lvhti.Item.Focused = true; } DefWndProc(ref m); @@ -5388,7 +5371,7 @@ private unsafe bool WmNotify(ref Message m) { - NativeMethods.HDITEM2 hdItem = (NativeMethods.HDITEM2) UnsafeNativeMethods.PtrToStructure((IntPtr) nmheader.pItem, typeof(NativeMethods.HDITEM2)); + NativeMethods.HDITEM2 hdItem = Marshal.PtrToStructure((IntPtr) nmheader.pItem); int newColumnWidth = ((hdItem.mask & NativeMethods.HDI_WIDTH) != 0) ? hdItem.cxy : -1; ColumnWidthChangingEventArgs colWidthChanging = new ColumnWidthChangingEventArgs(nmheader.iItem, newColumnWidth); OnColumnWidthChanging(colWidthChanging); @@ -5486,7 +5469,7 @@ private unsafe bool WmNotify(ref Message m) { NativeMethods.NMHEADER header = (NativeMethods.NMHEADER) m.GetLParam(typeof(NativeMethods.NMHEADER)); if (header.pItem != IntPtr.Zero) { - NativeMethods.HDITEM2 hdItem = (NativeMethods.HDITEM2) UnsafeNativeMethods.PtrToStructure((IntPtr) header.pItem, typeof(NativeMethods.HDITEM2)); + NativeMethods.HDITEM2 hdItem = Marshal.PtrToStructure((IntPtr) header.pItem); if ((hdItem.mask & NativeMethods.HDI_ORDER) == NativeMethods.HDI_ORDER) { int from = this.Columns[header.iItem].DisplayIndex; @@ -5603,7 +5586,7 @@ private unsafe bool WmNotify(ref Message m) { private Font GetListHeaderFont(){ IntPtr hwndHdr = UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.LVM_GETHEADER, 0, 0); - IntPtr hFont = UnsafeNativeMethods.SendMessage(new HandleRef(this, hwndHdr), NativeMethods.WM_GETFONT, 0, 0); + IntPtr hFont = UnsafeNativeMethods.SendMessage(new HandleRef(this, hwndHdr), Interop.WindowMessages.WM_GETFONT, 0, 0); return Font.FromHfont(hFont); } @@ -5736,10 +5719,9 @@ private unsafe void WmReflectNotify(ref Message m) { if (newValue != oldValue) { ItemCheckedEventArgs e = new ItemCheckedEventArgs(Items[nmlv->iItem]); OnItemChecked(e); - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.StateChange, nmlv->iItem); - AccessibilityNotifyClients(AccessibleEvents.NameChange, nmlv->iItem); - } + + AccessibilityNotifyClients(AccessibleEvents.StateChange, nmlv->iItem); + AccessibilityNotifyClients(AccessibleEvents.NameChange, nmlv->iItem); } int oldState = nmlv->uOldState & NativeMethods.LVIS_SELECTED; @@ -5903,35 +5885,6 @@ private unsafe void WmReflectNotify(ref Message m) { dispInfo.item.iIndent = lvItem.IndentCount; } - /* Microsoft: Couldn't make this work. The dispInfo.item.iSubItem received for the subitems' text - are invalid - if ((dispInfo.item.mask & NativeMethods.LVIF_COLUMNS) != 0) { - int cColumns = this.columnHeaders != null ? this.columnHeaders.Length : 0; - dispInfo.item.cColumns = cColumns; - if (cColumns > 0) { - dispInfo.item.puColumns = Marshal.AllocHGlobal(cColumns * Marshal.SizeOf(typeof(int))); - int[] columns = new int[cColumns]; - for (int c = 0; c < cColumns; c++) { - columns[c] = c + 1; - } - Marshal.Copy(columns, 0, dispInfo.item.puColumns, cColumns); - } - } - */ - - /* Microsoft: VirtualMode and grouping seem to be incompatible. - dispInfo.item.mask never includes NativeMethods.LVIF_GROUPID. - Besides, trying to send LVM_ENABLEGROUPVIEW to the listview fails in virtual mode. - if (this.GroupsEnabled && (dispInfo.item.mask & NativeMethods.LVIF_GROUPID) != 0) - { - dispInfo.item.iGroupId = GetNativeGroupId(lvItem); - #if DEBUG - Debug.Assert(SendMessage(NativeMethods.LVM_ISGROUPVIEWENABLED, 0, 0) != IntPtr.Zero, "Groups not enabled"); - Debug.Assert(SendMessage(NativeMethods.LVM_HASGROUP, dispInfo.item.iGroupId, 0) != IntPtr.Zero, "Doesn't contain group id: " + dispInfo.item.iGroupId.ToString(CultureInfo.InvariantCulture)); - #endif - } - */ - if ((dispInfo.item.stateMask & NativeMethods.LVIS_STATEIMAGEMASK) != 0) { dispInfo.item.state |= lvItem.RawStateImageIndex; } @@ -6055,10 +6008,10 @@ private void WmPrint(ref Message m) { protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: WmReflectNotify(ref m); break; - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: // Ensure that the itemCollectionChangedInMouseDown is not set // before processing the mousedown event. @@ -6067,7 +6020,7 @@ protected override void WndProc(ref Message m) { WmMouseDown(ref m, MouseButtons.Left, 2); break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: // Ensure that the itemCollectionChangedInMouseDown is not set // before processing the mousedown event. @@ -6076,9 +6029,9 @@ protected override void WndProc(ref Message m) { downButton = MouseButtons.Left; break; - case NativeMethods.WM_LBUTTONUP: - case NativeMethods.WM_RBUTTONUP: - case NativeMethods.WM_MBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONUP: // see the mouse is on item // @@ -6101,21 +6054,21 @@ protected override void WndProc(ref Message m) { listViewState[LISTVIEWSTATE_mouseUpFired] = true; CaptureInternal = false; break; - case NativeMethods.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Middle, 2); break; - case NativeMethods.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: WmMouseDown(ref m, MouseButtons.Middle, 1); downButton = MouseButtons.Middle; break; - case NativeMethods.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Right, 2); break; - case NativeMethods.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: WmMouseDown(ref m, MouseButtons.Right, 1); downButton = MouseButtons.Right; break; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: if (listViewState[LISTVIEWSTATE_expectingMouseUp] && !listViewState[LISTVIEWSTATE_mouseUpFired] && MouseButtons == MouseButtons.None) { OnMouseUp(new MouseEventArgs(downButton, 1, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0)); @@ -6124,14 +6077,14 @@ protected override void WndProc(ref Message m) { CaptureInternal = false; base.WndProc(ref m); break; - case NativeMethods.WM_MOUSEHOVER: + case Interop.WindowMessages.WM_MOUSEHOVER: if (HoverSelection) { base.WndProc(ref m); } else OnMouseHover(EventArgs.Empty); break; - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: if(WmNotify(ref m)) { break; // we are done - skip default handling @@ -6140,7 +6093,7 @@ protected override void WndProc(ref Message m) { { goto default; //default handling needed } - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: base.WndProc(ref m); if (!this.RecreatingHandle && !this.ListViewHandleDestroyed) { @@ -6156,23 +6109,23 @@ protected override void WndProc(ref Message m) { } } break; - case NativeMethods.WM_MOUSELEAVE: + case Interop.WindowMessages.WM_MOUSELEAVE: // if the mouse leaves and then re-enters the ListView // ItemHovered events should be raised. prevHoveredItem = null; base.WndProc(ref m); break; - case NativeMethods.WM_PAINT: + case Interop.WindowMessages.WM_PAINT: base.WndProc(ref m); // win32 ListView BeginInvoke(new MethodInvoker(this.CleanPreviousBackgroundImageFiles)); break; - case NativeMethods.WM_PRINT: + case Interop.WindowMessages.WM_PRINT: WmPrint(ref m); break; - case NativeMethods.WM_TIMER: + case Interop.WindowMessages.WM_TIMER: if (unchecked( (int) (long)m.WParam) != LVTOOLTIPTRACKING || !ComctlSupportsVisualStyles) { base.WndProc(ref m); } @@ -6267,7 +6220,7 @@ public int this[int index] { get { if (index < 0) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } // Loop through the main collection until we find the right index. @@ -6286,7 +6239,7 @@ public int this[int index] { } // Should never get to this point. - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } } @@ -6799,7 +6752,7 @@ public int this[int index] { get { if (index < 0 || index >= Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (owner.IsHandleCreated) { @@ -6912,7 +6865,7 @@ int IList.Add(object value) } else { - throw new ArgumentException(string.Format(SR.InvalidArgument, "value", ((value).ToString()))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(value), value), nameof(value)); } } @@ -6938,7 +6891,7 @@ void IList.Remove(object value) } else { - throw new ArgumentException(string.Format(SR.InvalidArgument, "value", ((value).ToString()))); + throw new ArgumentException(string.Format(SR.InvalidArgument, nameof(value), value), nameof(value)); } } @@ -6955,7 +6908,7 @@ public int Add(int itemIndex) { if (itemIndex < 0 || itemIndex >= this.owner.VirtualListSize) { - throw new ArgumentOutOfRangeException(nameof(itemIndex), string.Format(SR.InvalidArgument, "itemIndex", (itemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(itemIndex), itemIndex, string.Format(SR.InvalidArgument, nameof(itemIndex), itemIndex)); } if (this.owner.IsHandleCreated) { @@ -6971,7 +6924,7 @@ public int Add(int itemIndex) { if (itemIndex < 0 || itemIndex >= this.owner.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(itemIndex), string.Format(SR.InvalidArgument, "itemIndex", (itemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(itemIndex), itemIndex, string.Format(SR.InvalidArgument, nameof(itemIndex), itemIndex)); } this.owner.Items[itemIndex].Selected = true; return this.Count; @@ -7016,7 +6969,7 @@ public void Remove(int itemIndex) { if (itemIndex < 0 || itemIndex >= this.owner.VirtualListSize) { - throw new ArgumentOutOfRangeException(nameof(itemIndex), string.Format(SR.InvalidArgument, "itemIndex", (itemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(itemIndex), itemIndex, string.Format(SR.InvalidArgument, nameof(itemIndex), itemIndex)); } if (this.owner.IsHandleCreated) { @@ -7027,7 +6980,7 @@ public void Remove(int itemIndex) { if (itemIndex < 0 || itemIndex >= this.owner.Items.Count) { - throw new ArgumentOutOfRangeException(nameof(itemIndex), string.Format(SR.InvalidArgument, "itemIndex", (itemIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(itemIndex), itemIndex, string.Format(SR.InvalidArgument, nameof(itemIndex), itemIndex)); } this.owner.Items[itemIndex].Selected = false; } @@ -7123,7 +7076,7 @@ public ListViewItem this[int index] { } if (index < 0 || index >= Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (owner.IsHandleCreated) { @@ -7419,7 +7372,7 @@ public ColumnHeaderCollection(ListView owner) { public virtual ColumnHeader this[int index] { get { if (owner.columnHeaders == null || index < 0 || index >= owner.columnHeaders.Length) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return owner.columnHeaders[index]; } } @@ -7764,7 +7717,7 @@ int IList.IndexOf(object value) { /// public void Insert(int index, ColumnHeader value) { if (index < 0 || index > Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } owner.InsertColumn(index, value); } @@ -7849,7 +7802,7 @@ public void Insert(int index, string key, string text, int width, HorizontalAlig /// public virtual void RemoveAt(int index) { if (owner.columnHeaders == null || index < 0 || index >= owner.columnHeaders.Length) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); int w = owner.columnHeaders[index].Width; // Update width before detaching from ListView @@ -7858,9 +7811,7 @@ public virtual void RemoveAt(int index) { int retval = unchecked( (int) (long)owner.SendMessage(NativeMethods.LVM_DELETECOLUMN, index, 0)); if (0 == retval) - throw new ArgumentException(string.Format(SR.InvalidArgument, - "index", - (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } // we need to update the display indices @@ -8031,14 +7982,14 @@ public bool IsReadOnly { public virtual ListViewItem this[int index] { get { if (index < 0 || index >= InnerList.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } return InnerList[index]; } set { if (index < 0 || index >= InnerList.Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } InnerList[index] = value; @@ -8349,7 +8300,7 @@ private bool IsValidIndex(int index) { /// public ListViewItem Insert(int index, ListViewItem item) { if (index < 0 || index > Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } InnerList.Insert(index, item); return item; @@ -8413,7 +8364,7 @@ public virtual void Remove(ListViewItem item) { /// public virtual void RemoveAt(int index) { if (index < 0 || index >= Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } InnerList.RemoveAt(index); @@ -8489,7 +8440,7 @@ public ListViewItem this[int displayIndex] { } else { if (displayIndex < 0 || displayIndex >= owner.itemCount) - throw new ArgumentOutOfRangeException(nameof(displayIndex), string.Format(SR.InvalidArgument, "displayIndex", (displayIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(displayIndex), displayIndex, string.Format(SR.InvalidArgument, nameof(displayIndex), displayIndex)); if (owner.IsHandleCreated && !owner.ListViewHandleDestroyed) { return (ListViewItem)owner.listItemsTable[DisplayIndexToID(displayIndex)]; @@ -8507,7 +8458,7 @@ public ListViewItem this[int displayIndex] { } if (displayIndex < 0 || displayIndex >= owner.itemCount) - throw new ArgumentOutOfRangeException(nameof(displayIndex), string.Format(SR.InvalidArgument, "displayIndex", (displayIndex).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(displayIndex), displayIndex, string.Format(SR.InvalidArgument, nameof(displayIndex), displayIndex)); if (this.owner.ExpectingMouseUp) { this.owner.ItemCollectionChangedInMouseDown = true; @@ -8710,7 +8661,7 @@ public ListViewItem Insert(int index, ListViewItem item) { } if (index < 0 || index > count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (owner.VirtualMode) { @@ -8767,7 +8718,7 @@ public void RemoveAt(int index) { } if (index < 0 || index >= owner.itemCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); Debug.Assert(!this.owner.FlipViewToLargeIconAndSmallIcon || this.Count == 0, "the FlipView... bit is turned off after adding 1 item."); @@ -8785,9 +8736,7 @@ public void RemoveAt(int index) { int retval = unchecked( (int) (long)owner.SendMessage(NativeMethods.LVM_DELETEITEM, index, 0)); if (0 == retval) - throw new ArgumentException(string.Format(SR.InvalidArgument, - "index", - (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } else { Debug.Assert(owner.listItemsArray != null, "listItemsArray is null, but the handle isn't created"); @@ -8829,11 +8778,7 @@ public IEnumerator GetEnumerator() { /// The AccessibleObject for this ListView instance. /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ListViewAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ListViewAccessibleObject(this); } internal class ListViewAccessibleObject : ControlAccessibleObject { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ListViewGroupItemCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ListViewGroupItemCollection.cs index c3d8f3187db..f24a5e4fc45 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ListViewGroupItemCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ListViewGroupItemCollection.cs @@ -5,7 +5,6 @@ using System.ComponentModel; using System.Diagnostics; using System; -using System.Security.Permissions; using System.Drawing; using System.Windows.Forms; using System.ComponentModel.Design; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ListViewItem.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ListViewItem.cs index b7cf6c6b50e..a2cece0c629 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ListViewItem.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ListViewItem.cs @@ -472,8 +472,9 @@ public int ImageIndex { return this.ImageIndexer.Index; } set { - if (value < -1) { - throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "ImageIndex", value.ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + if (value < -1) + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); } ImageIndexer.Index = value; @@ -725,7 +726,7 @@ public int StateImageIndex { } set { if (value < -1 || value > 14) - throw new ArgumentOutOfRangeException(nameof(StateImageIndex), string.Format(SR.InvalidArgument, "StateImageIndex", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(StateImageIndex), value)); if (listView != null && listView.IsHandleCreated) { this.state[StateImageMaskSet] = (value == -1 ? 0 : 1); @@ -1177,7 +1178,7 @@ protected virtual void Deserialize(SerializationInfo info, StreamingContext cont if (entry.Name == "Text") { Text = info.GetString(entry.Name); } - else if (entry.Name == "ImageIndex") { + else if (entry.Name == nameof(ImageIndex)) { imageIndex = info.GetInt32(entry.Name); } else if (entry.Name == "ImageKey") { @@ -1239,7 +1240,7 @@ protected virtual void Deserialize(SerializationInfo info, StreamingContext cont /// protected virtual void Serialize(SerializationInfo info, StreamingContext context) { info.AddValue("Text", Text); - info.AddValue("ImageIndex", ImageIndexer.Index); + info.AddValue(nameof(ImageIndex), ImageIndexer.Index); if (!string.IsNullOrEmpty(ImageIndexer.Key)) { info.AddValue("ImageKey", ImageIndexer.Key); } @@ -1404,19 +1405,22 @@ public Rectangle Bounds { internal bool CustomBackColor { get { - return style != null && !style.backColor.IsEmpty; + Debug.Assert(style != null, "Should have checked CustomStyle"); + return !style.backColor.IsEmpty; } } internal bool CustomFont { get { - return style != null && style.font != null; + Debug.Assert(style != null, "Should have checked CustomStyle"); + return style.font != null; } } internal bool CustomForeColor { get { - return style != null && !style.foreColor.IsEmpty; + Debug.Assert(style != null, "Should have checked CustomStyle"); + return !style.foreColor.IsEmpty; } } @@ -1650,14 +1654,14 @@ public bool IsReadOnly { public ListViewSubItem this[int index] { get { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return owner.subItems[index]; } set { if (index < 0 || index >= Count) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (value == null) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MDIClient.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MDIClient.cs index e723126e597..829b90dc657 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MDIClient.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MDIClient.cs @@ -158,16 +158,16 @@ public void LayoutMdi(MdiLayout value) { switch (value) { case MdiLayout.Cascade: - SendMessage(NativeMethods.WM_MDICASCADE, 0, 0); + SendMessage(Interop.WindowMessages.WM_MDICASCADE, 0, 0); break; case MdiLayout.TileVertical: - SendMessage(NativeMethods.WM_MDITILE, NativeMethods.MDITILE_VERTICAL, 0); + SendMessage(Interop.WindowMessages.WM_MDITILE, NativeMethods.MDITILE_VERTICAL, 0); break; case MdiLayout.TileHorizontal: - SendMessage(NativeMethods.WM_MDITILE, NativeMethods.MDITILE_HORIZONTAL, 0); + SendMessage(Interop.WindowMessages.WM_MDITILE, NativeMethods.MDITILE_HORIZONTAL, 0); break; case MdiLayout.ArrangeIcons: - SendMessage(NativeMethods.WM_MDIICONARRANGE, 0, 0); + SendMessage(Interop.WindowMessages.WM_MDIICONARRANGE, 0, 0); break; } } @@ -235,7 +235,7 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound // to the top right which just looks wierd! // NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT(); - wp.length = Marshal.SizeOf(typeof(NativeMethods.WINDOWPLACEMENT)); + wp.length = Marshal.SizeOf(); for (int i=0; i < Controls.Count; i++) { Control ctl = Controls[i]; @@ -338,13 +338,13 @@ internal override bool ShouldSerializeSize() { protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_CREATE: + case Interop.WindowMessages.WM_CREATE: if (ParentInternal != null && ParentInternal.Site != null && ParentInternal.Site.DesignMode && Handle != IntPtr.Zero) { SetWindowRgn(); } break; - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: InvokeGotFocus(ParentInternal, EventArgs.Empty); Form childForm = null; if (ParentInternal is Form) { @@ -363,7 +363,7 @@ protected override void WndProc(ref Message m) { DefWndProc(ref m); InvokeGotFocus(this, EventArgs.Empty); return; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: InvokeLostFocus(ParentInternal, EventArgs.Empty); break; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MDIControlStrip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MDIControlStrip.cs index 45b1084741c..66559bbb475 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MDIControlStrip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MDIControlStrip.cs @@ -124,7 +124,7 @@ protected override Size GetPreferredSize(Size proposedSize) { private Image GetTargetWindowIcon() { Image systemIcon = null; - IntPtr hIcon = UnsafeNativeMethods.SendMessage(new HandleRef(this, Control.GetSafeHandle(target)), NativeMethods.WM_GETICON, NativeMethods.ICON_SMALL, 0); + IntPtr hIcon = UnsafeNativeMethods.SendMessage(new HandleRef(this, Control.GetSafeHandle(target)), Interop.WindowMessages.WM_GETICON, NativeMethods.ICON_SMALL, 0); Icon icon = (hIcon != IntPtr.Zero) ? Icon.FromHandle(hIcon) : Form.DefaultIcon; Icon smallIcon = new Icon(icon, SystemInformation.SmallIconSize); @@ -219,9 +219,7 @@ internal override bool CanKeyboardSelect { // when the system menu item shortcut is evaluated - pop the dropdown internal class SystemMenuItem : ToolStripMenuItem { public SystemMenuItem(){ - if (AccessibilityImprovements.Level1) { - AccessibleName = SR.MDIChildSystemMenuItemAccessibleName; - } + AccessibleName = SR.MDIChildSystemMenuItemAccessibleName; } protected internal override bool ProcessCmdKey(ref Message m, Keys keyData) { if (Visible && ShortcutKeys == keyData) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MaskedTextBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MaskedTextBox.cs index 0da03156a3d..b19b83ba886 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MaskedTextBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MaskedTextBox.cs @@ -1222,7 +1222,7 @@ private void SetEditControlPasswordChar( char pwdChar ) if (this.IsHandleCreated) { // This message does not return a value. - SendMessage(NativeMethods.EM_SETPASSWORDCHAR, pwdChar, 0); + SendMessage(Interop.EditMessages.EM_SETPASSWORDCHAR, pwdChar, 0); Invalidate(); } } @@ -1263,10 +1263,6 @@ private char SystemPasswordChar throw; } } - finally - { - CodeAccessPermission.RevertAssert(); - } MaskedTextBox.systemPwdChar = foundRsc ? (char) int.Parse(charVal.ToString()) : MaskedTextProvider.DefaultPasswordChar; */ @@ -2710,7 +2706,7 @@ protected internal override bool ProcessKeyMessage(ref Message m) // If this WM_CHAR message is sent after WM_IME_CHAR, we ignore it since we already processed // the corresponding WM_IME_CHAR message. - if( m.Msg == NativeMethods.WM_CHAR && base.ImeWmCharsToIgnore > 0 ) { + if( m.Msg == Interop.WindowMessages.WM_CHAR && base.ImeWmCharsToIgnore > 0 ) { return true; // meaning, we handled the message so it is not passed to the default WndProc. } @@ -3179,19 +3175,19 @@ protected override void WndProc(ref Message m) // Handle messages for special cases (unsupported operations or cases where mask doesn not matter). switch (m.Msg) { - case NativeMethods.WM_PRINT: + case Interop.WindowMessages.WM_PRINT: WmPrint(ref m); return; - case NativeMethods.WM_CONTEXTMENU: - case NativeMethods.EM_CANUNDO: + case Interop.WindowMessages.WM_CONTEXTMENU: + case Interop.EditMessages.EM_CANUNDO: base.ClearUndo(); // resets undo buffer. base.WndProc(ref m); return; - case NativeMethods.EM_SCROLLCARET: // No scroll for single-line control. - case NativeMethods.EM_LIMITTEXT: // Max/Min text is defined by the mask. - case NativeMethods.EM_UNDO: - case NativeMethods.WM_UNDO: + case Interop.EditMessages.EM_SCROLLCARET: // No scroll for single-line control. + case Interop.EditMessages.EM_LIMITTEXT: // Max/Min text is defined by the mask. + case Interop.EditMessages.EM_UNDO: + case Interop.WindowMessages.WM_UNDO: return; default: @@ -3206,49 +3202,49 @@ protected override void WndProc(ref Message m) switch (m.Msg) { - case NativeMethods.WM_IME_STARTCOMPOSITION: + case Interop.WindowMessages.WM_IME_STARTCOMPOSITION: if( WmImeStartComposition() ) { break; } goto default; - case NativeMethods.WM_IME_ENDCOMPOSITION: + case Interop.WindowMessages.WM_IME_ENDCOMPOSITION: this.flagState[IME_ENDING_COMPOSITION] = true; goto default; - case NativeMethods.WM_IME_COMPOSITION: + case Interop.WindowMessages.WM_IME_COMPOSITION: if( WmImeComposition( ref m ) ) { break; } goto default; - case NativeMethods.WM_CUT: + case Interop.WindowMessages.WM_CUT: if (!this.ReadOnly && WmCopy()) { WmClear(); } break; - case NativeMethods.WM_COPY: + case Interop.WindowMessages.WM_COPY: WmCopy(); break; - case NativeMethods.WM_PASTE: + case Interop.WindowMessages.WM_PASTE: WmPaste(); break; - case NativeMethods.WM_CLEAR: + case Interop.WindowMessages.WM_CLEAR: WmClear(); break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: base.WndProc(ref m); WmKillFocus(); break; - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: WmSetFocus(); base.WndProc(ref m); break; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Menu.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Menu.cs index 19d084b2409..aa7b144ad59 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Menu.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Menu.cs @@ -300,7 +300,7 @@ protected override void Dispose(bool disposing) { item.Site.Container.Remove(item); } - item.Menu = null; + item.Parent = null; item.Dispose(); } items = null; @@ -315,15 +315,7 @@ protected override void Dispose(bool disposing) { base.Dispose(disposing); } - /// - /// - /// - /// public MenuItem FindMenuItem(int type, IntPtr value) { - return FindMenuItemInternal(type, value); - } - - private MenuItem FindMenuItemInternal(int type, IntPtr value) { for (int i = 0; i < ItemCount; i++) { MenuItem item = items[i]; switch (type) { @@ -334,7 +326,7 @@ private MenuItem FindMenuItemInternal(int type, IntPtr value) { if (item.Shortcut == (Shortcut)(int)value) return item; break; } - item = item.FindMenuItemInternal(type, value); + item = item.FindMenuItem(type, value); if (item != null) return item; } return null; @@ -412,7 +404,7 @@ public ContextMenu GetContextMenu() { Menu menuT; for (menuT = this; !(menuT is ContextMenu);) { if (!(menuT is MenuItem)) return null; - menuT = ((MenuItem)menuT).Menu; + menuT = ((MenuItem)menuT).Parent; } return(ContextMenu)menuT; @@ -430,7 +422,7 @@ public MainMenu GetMainMenu() { Menu menuT; for (menuT = this; !(menuT is MainMenu);) { if (!(menuT is MenuItem)) return null; - menuT = ((MenuItem)menuT).Menu; + menuT = ((MenuItem)menuT).Parent; } return(MainMenu)menuT; } @@ -568,9 +560,9 @@ public virtual void MergeMenu(Menu menuSrc) { /// /// internal virtual bool ProcessInitMenuPopup(IntPtr handle) { - MenuItem item = FindMenuItemInternal(FindHandle, handle); + MenuItem item = FindMenuItem(FindHandle, handle); if (item != null) { - item._OnInitMenuPopup(EventArgs.Empty); + item.OnInitMenuPopup(EventArgs.Empty); item.CreateMenuItems(); return true; } @@ -582,7 +574,7 @@ internal virtual bool ProcessInitMenuPopup(IntPtr handle) { /// /// protected internal virtual bool ProcessCmdKey(ref Message msg, Keys keyData) { - MenuItem item = FindMenuItemInternal(FindShortcut, (IntPtr)(int)keyData); + MenuItem item = FindMenuItem(FindShortcut, (IntPtr)(int)keyData); return item != null? item.ShortcutClick(): false; } @@ -622,7 +614,7 @@ public override string ToString() { /// /// internal void WmMenuChar(ref Message m) { - Menu menu = (m.LParam == handle) ? this : FindMenuItemInternal(FindHandle, m.LParam); + Menu menu = (m.LParam == handle) ? this : FindMenuItem(FindHandle, m.LParam); if (menu == null) return; @@ -686,7 +678,7 @@ public MenuItemCollection(Menu owner) { public virtual MenuItem this[int index] { get { if (index < 0 || index >= owner.ItemCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return owner.items[index]; } // set not supported @@ -821,7 +813,7 @@ public virtual int Add(int index, MenuItem item) { } // MenuItems can only belong to one menu at a time - if (item.Menu != null) { + if (item.Parent != null) { // First check that we're not adding ourself, i.e. walk // the parent chain for equality @@ -841,16 +833,16 @@ public virtual int Add(int index, MenuItem item) { //if we're re-adding an item back to the same collection //the target index needs to be decremented since we're //removing an item from the collection - if (item.Menu.Equals(owner) && index > 0) { + if (item.Parent.Equals(owner) && index > 0) { index--; } - item.Menu.MenuItems.Remove(item); + item.Parent.MenuItems.Remove(item); } // Validate our index if (index < 0 || index > owner.ItemCount) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument,"index",(index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (owner.items == null || owner.items.Length == owner.ItemCount) { @@ -861,7 +853,7 @@ public virtual int Add(int index, MenuItem item) { System.Array.Copy(owner.items, index, owner.items, index + 1, owner.ItemCount - index); owner.items[index] = item; owner._itemCount++; - item.Menu = owner; + item.Parent = owner; owner.ItemsChanged(CHANGE_ITEMS); if (owner is MenuItem) { ((MenuItem) owner).ItemsChanged(CHANGE_ITEMADDED, item); @@ -1060,7 +1052,7 @@ public virtual void Clear() { if (owner.ItemCount > 0) { for (int i = 0; i < owner.ItemCount; i++) { - owner.items[i].Menu = null; + owner.items[i].Parent = null; } owner._itemCount = 0; @@ -1093,11 +1085,11 @@ public IEnumerator GetEnumerator() { /// public virtual void RemoveAt(int index) { if (index < 0 || index >= owner.ItemCount) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument,"index",(index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } MenuItem item = owner.items[index]; - item.Menu = null; + item.Parent = null; owner._itemCount--; System.Array.Copy(owner.items, index + 1, owner.items, index, owner.ItemCount - index); owner.items[owner.ItemCount] = null; @@ -1128,7 +1120,7 @@ public virtual void RemoveByKey(string key) { /// items are moved down one slot. /// public virtual void Remove(MenuItem item) { - if (item.Menu == owner) { + if (item.Parent == owner) { RemoveAt(item.Index); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MenuItem.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MenuItem.cs index 7b754ab1e72..0d0050fba11 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MenuItem.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MenuItem.cs @@ -2,363 +2,305 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Configuration.Assemblies; - using System.Runtime.Remoting; - using System.Runtime.InteropServices; - - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - - using System; - using System.Collections; - - using System.ComponentModel; - using System.Windows.Forms.Design; - using System.Windows.Forms; - using System.Windows.Forms.VisualStyles; - using System.Drawing; - using System.Windows.Forms.Internal; - using System.Drawing.Design; - using System.Drawing.Text; - using System.Drawing.Imaging; - using Microsoft.Win32; - using System.Globalization; - using System.Threading; - - /// +using System.Collections; +using System.ComponentModel; +using System.Globalization; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Threading; + +namespace System.Windows.Forms +{ /// - /// - /// Represents an individual item that is displayed within - /// a or . - /// + /// Represents an individual item that is displayed within a + /// or . /// - [ - ToolboxItem(false), - DesignTimeVisible(false), - DefaultEvent(nameof(Click)), - DefaultProperty(nameof(Text)) - ] - public class MenuItem : Menu { - internal const int STATE_BARBREAK = 0x00000020; - internal const int STATE_BREAK = 0x00000040; - internal const int STATE_CHECKED = 0x00000008; - internal const int STATE_DEFAULT = 0x00001000; - internal const int STATE_DISABLED = 0x00000003; - internal const int STATE_RADIOCHECK = 0x00000200; - internal const int STATE_HIDDEN = 0x00010000; - internal const int STATE_MDILIST = 0x00020000; - internal const int STATE_CLONE_MASK = 0x0003136B; - internal const int STATE_OWNERDRAW = 0x00000100; - internal const int STATE_INMDIPOPUP = 0x00000200; - internal const int STATE_HILITE = 0x00000080; - - private Menu menu; - private bool hasHandle; - private MenuItemData data; - private int dataVersion; - private MenuItem nextLinkedItem; // Next item linked to the same MenuItemData. - + [ToolboxItem(false)] + [DesignTimeVisible(false)] + [DefaultEvent(nameof(Click))] + [DefaultProperty(nameof(Text))] + public class MenuItem : Menu + { + private const int StateBarBreak = 0x00000020; + private const int StateBreak = 0x00000040; + private const int StateChecked = 0x00000008; + private const int StateDefault = 0x00001000; + private const int StateDisabled = 0x00000003; + private const int StateRadioCheck = 0x00000200; + private const int StateHidden = 0x00010000; + private const int StateMdiList = 0x00020000; + private const int StateCloneMask = 0x0003136B; + private const int StateOwnerDraw = 0x00000100; + private const int StateInMdiPopup = 0x00000200; + private const int StateHiLite = 0x00000080; + + private bool _hasHandle; + private MenuItemData _data; + private int _dataVersion; + private MenuItem _nextLinkedItem; // Next item linked to the same MenuItemData. + // We need to store a table of all created menuitems, so that other objects // such as ContainerControl can get a reference to a particular menuitem, // given a unique ID. - private static Hashtable allCreatedMenuItems = new Hashtable(); - private const uint firstUniqueID = 0xC0000000; - private static long nextUniqueID = firstUniqueID; - private uint uniqueID = 0; - private IntPtr msaaMenuInfoPtr = IntPtr.Zero; - private bool menuItemIsCreated = false; - - /// + private static Hashtable s_allCreatedMenuItems = new Hashtable(); + private const uint FirstUniqueID = 0xC0000000; + private static long s_nextUniqueID = FirstUniqueID; + private uint _uniqueID = 0; + private IntPtr _msaaMenuInfoPtr = IntPtr.Zero; + private bool _menuItemIsCreated = false; + +#if DEBUG + private string _debugText; + private int _creationNumber; + private static int CreateCount; +#endif + /// - /// - /// Initializes a with - /// a blank caption. - /// + /// Initializes a with a blank caption. /// - public MenuItem() : this(MenuMerge.Add, 0, 0, null, null, null, null, null) { + public MenuItem() : this(MenuMerge.Add, 0, 0, null, null, null, null, null) + { } - /// /// - /// - /// Initializes a new instance of the - /// class with a specified caption for - /// the menu item. - /// + /// Initializes a new instance of the class + /// with a specified caption for the menu item. /// - public MenuItem(string text) : this(MenuMerge.Add, 0, 0, text, null, null, null, null) { + public MenuItem(string text) : this(MenuMerge.Add, 0, 0, text, null, null, null, null) + { } - /// /// - /// - /// Initializes a new instance of the - /// class with a - /// specified caption and - /// event handler for the menu item. - /// + /// Initializes a new instance of the class with a specified caption and event handler + /// for the menu item. /// - public MenuItem(string text, EventHandler onClick) : this(MenuMerge.Add, 0, 0, text, onClick, null, null, null) { + public MenuItem(string text, EventHandler onClick) : this(MenuMerge.Add, 0, 0, text, onClick, null, null, null) + { } - /// /// - /// - /// Initializes a new instance of the - /// class with a - /// specified caption, event handler, and associated - /// shorcut key for the menu item. - /// + /// Initializes a new instance of the class with a specified caption, event handler, + /// and associated shorcut key for the menu item. /// - public MenuItem(string text, EventHandler onClick, Shortcut shortcut) : this(MenuMerge.Add, 0, shortcut, text, onClick, null, null, null) { + public MenuItem(string text, EventHandler onClick, Shortcut shortcut) : this(MenuMerge.Add, 0, shortcut, text, onClick, null, null, null) + { } - /// /// - /// - /// Initializes a new instance of the - /// class with a - /// specified caption and an array of - /// submenu items defined for the menu item. - /// + /// Initializes a new instance of the class with a specified caption and an array of + /// submenu items defined for the menu item. /// - public MenuItem(string text, MenuItem[] items) : this(MenuMerge.Add, 0, 0, text, null, null, null, items) { + public MenuItem(string text, MenuItem[] items) : this(MenuMerge.Add, 0, 0, text, null, null, null, items) + { } - internal MenuItem(MenuItemData data) - : base(null) { + internal MenuItem(MenuItemData data) : base(null) + { data.AddItem(this); - - #if DEBUG - _debugText = data.caption; - #endif + +#if DEBUG + _debugText = data._caption; +#endif } - /// /// - /// - /// Initializes a new instance of the class with a specified - /// caption, defined event-handlers for the Click, Select and - /// Popup events, a shortcut key, - /// a merge type, and order specified for the menu item. - /// + /// Initializes a new instance of the class with a specified caption, defined + /// event-handlers for the Click, Select and Popup events, a shortcut key, + /// a merge type, and order specified for the menu item. /// [SuppressMessage("Microsoft.Performance", "CA1806:DoNotIgnoreMethodResults")] public MenuItem(MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text, EventHandler onClick, EventHandler onPopup, - EventHandler onSelect, MenuItem[] items) - - : base(items) { - + EventHandler onSelect, MenuItem[] items) : base(items) + { new MenuItemData(this, mergeType, mergeOrder, shortcut, true, text, onClick, onPopup, onSelect, null, null); - #if DEBUG - _debugText = text; - _creationNumber = CreateCount++; - #endif +#if DEBUG + _debugText = text; + _creationNumber = CreateCount++; +#endif } - #if DEBUG - private string _debugText; - private int _creationNumber; - private Menu _debugParentMenu; - private static int CreateCount; - #endif - - /// /// - /// - /// Gets or sets a value indicating whether the item is - /// placed on a new line (for a menu item added to a object) or in a new - /// column (for a submenu or menu displayed in a - /// ). - /// + /// Gets or sets a value indicating whether the item is placed on a new line (for a + /// menu item added to a object) or in a + /// new column (for a submenu or menu displayed in a ). /// - [ - Browsable(false), - DefaultValue(false) - ] - public bool BarBreak { - get { + [Browsable(false)] + [DefaultValue(false)] + public bool BarBreak + { + get + { CheckIfDisposed(); - return(data.State & STATE_BARBREAK) != 0; + return (_data.State & StateBarBreak) != 0; } - - set { + set + { CheckIfDisposed(); - data.SetState(STATE_BARBREAK, value); + _data.SetState(StateBarBreak, value); } } - /// /// - /// - /// Gets or sets a value indicating whether the item is - /// placed on a new line (for a menu item added to a object) or in a new column (for a - /// submenu or menu displayed in a ). - /// + /// Gets or sets a value indicating whether the item is placed on a new line (for a + /// menu item added to a object) or in a + /// new column (for a submenu or menu displayed in a ). /// - [ - Browsable(false), - DefaultValue(false) - ] - public bool Break { - get { + [Browsable(false)] + [DefaultValue(false)] + public bool Break + { + get + { CheckIfDisposed(); - return(data.State & STATE_BREAK) != 0; + return (_data.State & StateBreak) != 0; } - - set { + set + { CheckIfDisposed(); - data.SetState(STATE_BREAK, value); + _data.SetState(StateBreak, value); } } - /// /// - /// - /// Gets or sets a value indicating whether a checkmark - /// appears beside the text of the menu item. - /// + /// Gets or sets a value indicating whether a checkmark appears beside the text of + /// the menu item. /// - [ - DefaultValue(false), - SRDescription(nameof(SR.MenuItemCheckedDescr)) - ] - public bool Checked { - get { + [DefaultValue(false)] + [SRDescription(nameof(SR.MenuItemCheckedDescr))] + public bool Checked + { + get + { CheckIfDisposed(); - return(data.State & STATE_CHECKED) != 0; + return (_data.State & StateChecked) != 0; } - - set { + set + { CheckIfDisposed(); - //if trying to set checked=true - if we're a top-level item (from a mainmenu) or have children, don't do this... - if (value == true && (ItemCount != 0 || (Parent != null && (Parent is MainMenu)))) { - throw new ArgumentException(SR.MenuItemInvalidCheckProperty); + if (value && (ItemCount != 0 || Parent is MainMenu)) + { + throw new ArgumentException(SR.MenuItemInvalidCheckProperty, nameof(value)); } - data.SetState(STATE_CHECKED, value); + _data.SetState(StateChecked, value); } } - /// /// - /// - /// Gets or sets a value indicating - /// whether the menu item is the default. - /// + /// Gets or sets a value indicating whether the menu item is the default. /// - [ - DefaultValue(false), - SRDescription(nameof(SR.MenuItemDefaultDescr)) - ] - public bool DefaultItem { - get { + [DefaultValue(false)] + [SRDescription(nameof(SR.MenuItemDefaultDescr))] + public bool DefaultItem + { + get + { CheckIfDisposed(); - return(data.State & STATE_DEFAULT) != 0; + return (_data.State & StateDefault) != 0; } - set { + set + { CheckIfDisposed(); - if (menu != null) { - if (value) { - UnsafeNativeMethods.SetMenuDefaultItem(new HandleRef(menu, menu.handle), MenuID, false); + if (Parent != null) + { + if (value) + { + UnsafeNativeMethods.SetMenuDefaultItem(new HandleRef(Parent, Parent.handle), MenuID, false); } - else if (DefaultItem) { - UnsafeNativeMethods.SetMenuDefaultItem(new HandleRef(menu, menu.handle), -1, false); + else if (DefaultItem) + { + UnsafeNativeMethods.SetMenuDefaultItem(new HandleRef(Parent, Parent.handle), -1, false); } } - data.SetState(STATE_DEFAULT, value); + + _data.SetState(StateDefault, value); } } - /// /// - /// - /// Gets or sets a value indicating whether code - /// that you provide draws the menu item or Windows draws the - /// menu item. - /// + /// Gets or sets a value indicating whether code that you provide draws the menu + /// item or Windows draws the menu item. /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(false), - SRDescription(nameof(SR.MenuItemOwnerDrawDescr)) - ] - public bool OwnerDraw { - get { + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(false)] + [SRDescription(nameof(SR.MenuItemOwnerDrawDescr))] + public bool OwnerDraw + { + get + { CheckIfDisposed(); - return((data.State & STATE_OWNERDRAW) != 0); + return ((_data.State & StateOwnerDraw) != 0); } - set { + set + { CheckIfDisposed(); - data.SetState(STATE_OWNERDRAW, value); + _data.SetState(StateOwnerDraw, value); } - } - /// /// - /// - /// Gets or sets a value indicating whether the menu - /// item is enabled. - /// + /// Gets or sets a value indicating whether the menu item is enabled. /// - [ - Localizable(true), - DefaultValue(true), - SRDescription(nameof(SR.MenuItemEnabledDescr)) - ] - public bool Enabled { - get { + [Localizable(true)] + [DefaultValue(true)] + [SRDescription(nameof(SR.MenuItemEnabledDescr))] + public bool Enabled + { + get + { CheckIfDisposed(); - return(data.State & STATE_DISABLED) == 0; + return (_data.State & StateDisabled) == 0; } - - set { + set + { CheckIfDisposed(); - data.SetState(STATE_DISABLED, !value); + _data.SetState(StateDisabled, !value); } } - /// /// - /// - /// Gets or sets the menu item's position in its parent menu. - /// + /// Gets or sets the menu item's position in its parent menu. /// - [ - Browsable(false), - ] - public int Index { - get { - if (menu != null) { - for (int i = 0; i < menu.ItemCount; i++) { - if (menu.items[i] == this) return i; + [Browsable(false)] + public int Index + { + get + { + if (Parent != null) + { + for (int i = 0; i < Parent.ItemCount; i++) + { + if (Parent.items[i] == this) + { + return i; + } } } + return -1; } - - set { + set + { int oldIndex = Index; - if (oldIndex >= 0) { - if (value < 0 || value >= menu.ItemCount) { - throw new ArgumentOutOfRangeException(nameof(Index), string.Format(SR.InvalidArgument, "Index", (value).ToString(CultureInfo.CurrentCulture))); + if (oldIndex >= 0) + { + if (value < 0 || value >= Parent.ItemCount) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidArgument, nameof(Index), value)); } - if (value != oldIndex) { - // this.menu reverts to null when we're removed, so hold onto it in a local variable - Menu parent = menu; + if (value != oldIndex) + { + // The menu reverts to null when we're removed, so hold onto it in a + // local variable + Menu parent = Parent; parent.MenuItems.RemoveAt(oldIndex); parent.MenuItems.Add(value, this); } @@ -366,839 +308,801 @@ public int Index { } } - /// /// - /// - /// Gets a value indicating whether the menu item contains - /// child menu items. - /// + /// Gets a value indicating whether the menu item contains child menu items. /// - [ - Browsable(false), - ] - public override bool IsParent { - get { - bool parent = false; - if (data != null && MdiList) { - for (int i=0; i 0) { - parent = true; - } + + if (FindMdiForms().Length > 0) + { + return true; } - if (!parent) { - if (menu != null && !(menu is MenuItem)) { - parent = true; - } + + if (Parent != null && !(Parent is MenuItem)) + { + return true; } + + return false; } - else { - parent = base.IsParent; - } - return parent; + + return base.IsParent; } } - /// /// - /// - /// Gets or sets - /// a value indicating whether the menu item will be populated - /// with a list of the MDI child windows that are displayed within the - /// associated form. - /// - /// - [ - DefaultValue(false), - SRDescription(nameof(SR.MenuItemMDIListDescr)) - ] - public bool MdiList { - get { + /// Gets or sets a value indicating whether the menu item will be populated with a + /// list of the MDI child windows that are displayed within the associated form. + /// + [DefaultValue(false)] + [SRDescription(nameof(SR.MenuItemMDIListDescr))] + public bool MdiList + { + get + { CheckIfDisposed(); - return(data.State & STATE_MDILIST) != 0; + return (_data.State & StateMdiList) != 0; } - set { + set + { CheckIfDisposed(); - data.MdiList = value; + _data.MdiList = value; CleanListItems(this); } } - internal Menu Menu { - get { - return menu; - } - set { - menu = value; - #if DEBUG - _debugParentMenu = value; - #endif - } - } - - /// /// - /// - /// Gets the Windows identifier for this menu item. - /// - /// - protected int MenuID { + /// Gets the Windows identifier for this menu item. + /// + protected int MenuID + { get { CheckIfDisposed(); - return data.GetMenuID(); + return _data.GetMenuID(); } } - /// /// - /// Is this menu item currently selected (highlighted) by the user? - /// - internal bool Selected { - get { - if (menu == null) + /// Is this menu item currently selected (highlighted) by the user? + /// + internal bool Selected + { + get + { + if (Parent == null) + { return false; + } - NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); + var info = new NativeMethods.MENUITEMINFO_T(); + info.cbSize = Marshal.SizeOf(); info.fMask = NativeMethods.MIIM_STATE; - UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); + UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, info); - return (info.fState & STATE_HILITE) != 0; + return (info.fState & StateHiLite) != 0; } } - - /// /// - /// - /// Gets the zero-based index of this menu - /// item in the parent menu, or -1 if this - /// menu item is not associated with a - /// parent menu. - /// - /// - internal int MenuIndex { - get { - if (menu == null) return -1; - - int count = UnsafeNativeMethods.GetMenuItemCount(new HandleRef(menu, menu.Handle)); + /// Gets the zero-based index of this menu item in the parent menu, or -1 if this + /// menu item is not associated with a parent menu. + /// + internal int MenuIndex + { + get + { + if (Parent == null) + { + return -1; + } + + int count = UnsafeNativeMethods.GetMenuItemCount(new HandleRef(Parent, Parent.Handle)); int id = MenuID; NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); + info.cbSize = Marshal.SizeOf(); info.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_SUBMENU; - - for(int i = 0; i < count; i++) { - UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), i, true, info); - - // For sub menus, the handle is always valid. For - // items, however, it is always zero. - // - if ((info.hSubMenu == IntPtr.Zero || info.hSubMenu == Handle) && info.wID == id) { + + for (int i = 0; i < count; i++) + { + UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(Parent, Parent.handle), i, true, info); + + // For sub menus, the handle is always valid. + // For items, however, it is always zero. + if ((info.hSubMenu == IntPtr.Zero || info.hSubMenu == Handle) && info.wID == id) + { return i; } } + return -1; } } - /// /// - /// - /// Gets or sets a value that indicates the behavior of this - /// menu item when its menu is merged with another. - /// - /// + /// Gets or sets a value that indicates the behavior of this + /// menu item when its menu is merged with another. /// - [ - DefaultValue(MenuMerge.Add), - SRDescription(nameof(SR.MenuItemMergeTypeDescr)) - ] - public MenuMerge MergeType { - get { + [DefaultValue(MenuMerge.Add)] + [SRDescription(nameof(SR.MenuItemMergeTypeDescr))] + public MenuMerge MergeType + { + get + { CheckIfDisposed(); - return data.mergeType; + return _data._mergeType; } - set { + set + { CheckIfDisposed(); - - //valid values are 0x0 to 0x3 - if (!ClientUtils.IsEnumValid(value, (int)value, (int)MenuMerge.Add, (int)MenuMerge.Remove)){ + if (!ClientUtils.IsEnumValid(value, (int)value, (int)MenuMerge.Add, (int)MenuMerge.Remove)) + { throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(MenuMerge)); } - data.MergeType = value; + _data.MergeType = value; } } - /// /// - /// - /// Gets or sets the relative position the menu item when its - /// menu is merged with another. - /// - /// + /// Gets or sets the relative position the menu item when its + /// menu is merged with another. /// - [ - DefaultValue(0), - SRDescription(nameof(SR.MenuItemMergeOrderDescr)) - ] - public int MergeOrder { - get { + [DefaultValue(0)] + [SRDescription(nameof(SR.MenuItemMergeOrderDescr))] + public int MergeOrder + { + get + { CheckIfDisposed(); - return data.mergeOrder; + return _data._mergeOrder; } - set { + set + { CheckIfDisposed(); - data.MergeOrder = value; + _data.MergeOrder = value; } } - /// /// - /// - /// Retrieves the hotkey mnemonic that is associated with this menu item. - /// The mnemonic is the first character after an ampersand symbol in the menu's text - /// that is not itself an ampersand symbol. If no such mnemonic is defined this - /// will return zero. - /// + /// Retrieves the hotkey mnemonic that is associated with this menu item. + /// The mnemonic is the first character after an ampersand symbol in the menu's text + /// that is not itself an ampersand symbol. If no such mnemonic is defined this + /// will return zero. /// [Browsable(false)] - public char Mnemonic { - get { + public char Mnemonic + { + get + { CheckIfDisposed(); - return data.Mnemonic; + return _data.Mnemonic; } } - /// /// - /// - /// Gets the menu in which this menu item - /// appears. - /// - /// + /// Gets the menu in which this menu item appears. + /// [Browsable(false)] - public Menu Parent { - get {return menu;} - } + public Menu Parent { get; internal set; } - /// /// - /// - /// Gets or sets a value that indicates whether the menu item, - /// if checked, displays a radio-button mark instead of a check mark. - /// + /// Gets or sets a value that indicates whether the menu item, if checked, + /// displays a radio-button mark instead of a check mark. /// - [ - DefaultValue(false), - SRDescription(nameof(SR.MenuItemRadioCheckDescr)) - ] - public bool RadioCheck { - get { + [DefaultValue(false)] + [SRDescription(nameof(SR.MenuItemRadioCheckDescr))] + public bool RadioCheck + { + get + { CheckIfDisposed(); - return(data.State & STATE_RADIOCHECK) != 0; + return (_data.State & StateRadioCheck) != 0; } - set { + set + { CheckIfDisposed(); - data.SetState(STATE_RADIOCHECK, value); - } - } - - internal override bool RenderIsRightToLeft { - get { - if(Parent == null) - return false; - else - return Parent.RenderIsRightToLeft; + _data.SetState(StateRadioCheck, value); } } - /// + internal override bool RenderIsRightToLeft => Parent != null && Parent.RenderIsRightToLeft; + /// - /// - /// Gets or sets the text of the menu item. - /// - /// - [ - Localizable(true), - SRDescription(nameof(SR.MenuItemTextDescr)) - ] - public string Text { - get { + /// Gets or sets the text of the menu item. + /// + [Localizable(true)] + [SRDescription(nameof(SR.MenuItemTextDescr))] + public string Text + { + get + { CheckIfDisposed(); - return data.caption; + return _data._caption; } - set { + set + { CheckIfDisposed(); - data.SetCaption(value); + _data.SetCaption(value); } } - /// /// - /// - /// Gets or sets the shortcut key associated with the menu - /// item. - /// + /// Gets or sets the shortcut key associated with the menu item. /// - [ - Localizable(true), - DefaultValue(Shortcut.None), - SRDescription(nameof(SR.MenuItemShortCutDescr)) - ] - public Shortcut Shortcut { - get { + [Localizable(true)] + [DefaultValue(Shortcut.None)] + [SRDescription(nameof(SR.MenuItemShortCutDescr))] + public Shortcut Shortcut + { + get + { CheckIfDisposed(); - return data.shortcut; + return _data._shortcut; } [SuppressMessage("Microsoft.Performance", "CA1803:AvoidCostlyCallsWherePossible")] - set { + set + { CheckIfDisposed(); - - if (!Enum.IsDefined(typeof(Shortcut), value)) { + if (!Enum.IsDefined(typeof(Shortcut), value)) + { throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(Shortcut)); } - data.shortcut = value; - UpdateMenuItem(true); + _data._shortcut = value; + UpdateMenuItem(force: true); } } - /// /// - /// - /// Gets or sets a value that indicates whether the shortcut - /// key that is assocaited - /// with the menu item is displayed next to the menu item - /// caption. - /// + /// Gets or sets a value that indicates whether the shortcut key that is associated + /// with the menu item is displayed next to the menu item caption. /// - [ - DefaultValue(true), - Localizable(true), - SRDescription(nameof(SR.MenuItemShowShortCutDescr)) - ] - public bool ShowShortcut { - get { + [DefaultValue(true), + Localizable(true)] + [SRDescription(nameof(SR.MenuItemShowShortCutDescr))] + public bool ShowShortcut + { + get + { CheckIfDisposed(); - return data.showShortcut; + return _data._showShortcut; } - set { + set + { CheckIfDisposed(); - if (value != data.showShortcut) { - data.showShortcut = value; - UpdateMenuItem(true); + if (value != _data._showShortcut) + { + _data._showShortcut = value; + UpdateMenuItem(force: true); } } } - /// /// - /// - /// Gets or sets a value that indicates - /// whether the menu item is visible on its parent menu. - /// + /// Gets or sets a value that indicates whether the menu item is visible on its + /// parent menu. /// - [ - Localizable(true), - DefaultValue(true), - SRDescription(nameof(SR.MenuItemVisibleDescr)) - ] - public bool Visible { - get { + [Localizable(true)] + [DefaultValue(true)] + [SRDescription(nameof(SR.MenuItemVisibleDescr))] + public bool Visible + { + get + { CheckIfDisposed(); - return(data.State & STATE_HIDDEN) == 0; + return (_data.State & StateHidden) == 0; } - set { + set + { CheckIfDisposed(); - data.Visible = value; + _data.Visible = value; } } - /// /// - /// - /// Occurs when the menu item is clicked or selected using a - /// shortcut key defined for the menu item. - /// + /// Occurs when the menu item is clicked or selected using a shortcut key defined + /// for the menu item. /// [SRDescription(nameof(SR.MenuItemOnClickDescr))] - public event EventHandler Click { - add { + public event EventHandler Click + { + add + { CheckIfDisposed(); - data.onClick += value; + _data._onClick += value; } - remove { + remove + { CheckIfDisposed(); - data.onClick -= value; + _data._onClick -= value; } } - /// /// - /// - /// Occurs when when the property of a menu item is set - /// to - /// - /// and a request is made to draw the menu item. - /// + /// Occurs when when the property of a menu item is set to and + /// a request is made to draw the menu item. /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.drawItemEventDescr))] - public event DrawItemEventHandler DrawItem { - add { + public event DrawItemEventHandler DrawItem + { + add + { CheckIfDisposed(); - data.onDrawItem += value; + _data._onDrawItem += value; } - remove { + remove + { CheckIfDisposed(); - data.onDrawItem -= value; + _data._onDrawItem -= value; } } - /// /// - /// - /// Occurs when when the menu needs to know the size of a - /// menu item before drawing it. - /// + /// Occurs when when the menu needs to know the size of a menu item before drawing it. /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.measureItemEventDescr))] - public event MeasureItemEventHandler MeasureItem { - add { + public event MeasureItemEventHandler MeasureItem + { + add + { CheckIfDisposed(); - data.onMeasureItem += value; + _data._onMeasureItem += value; } - remove { + remove + { CheckIfDisposed(); - data.onMeasureItem -= value; + _data._onMeasureItem -= value; } } - /* - private bool ParentIsRightToLeft { - get { - Menu parent = GetMainMenu(); - if (parent != null) { - if (parent is MenuItem && ((MainMenu)parent).RightToLeft == RightToLeft.Inherit) { - // recursivly go up the chain - return ((MenuItem)parent).ParentIsRightToLeft; - } else { - - return((MainMenu)parent).RightToLeft == RightToLeft.Yes; - } - } - else { - parent = GetContextMenu(); - if (parent != null) { - if (parent is MenuItem && ((ContextMenu)parent).RightToLeft == RightToLeft.Inherit) { - // recursivly go up the chain - return ((MenuItem)parent).ParentIsRightToLeft; - } else { - return((ContextMenu)parent).RightToLeft == RightToLeft.Yes; - } - } - } - - return false; - } - } */ - - /// /// - /// - /// Occurs before a menu item's list of menu items is - /// displayed. - /// + /// Occurs before a menu item's list of menu items is displayed. /// [SRDescription(nameof(SR.MenuItemOnInitDescr))] - public event EventHandler Popup { - add { + public event EventHandler Popup + { + add + { CheckIfDisposed(); - data.onPopup += value; + _data._onPopup += value; } - remove { + remove + { CheckIfDisposed(); - data.onPopup -= value; + _data._onPopup -= value; } } - /// /// - /// - /// Occurs when the user hovers their mouse over a menu - /// item - /// or selects it with the keyboard but has not activated it. - /// + /// Occurs when the user hovers their mouse over a menu item or selects it with the + /// keyboard but has not activated it. /// [SRDescription(nameof(SR.MenuItemOnSelectDescr))] - public event EventHandler Select { - add { + public event EventHandler Select + { + add + { CheckIfDisposed(); - data.onSelect += value; + _data._onSelect += value; } - remove { + remove + { CheckIfDisposed(); - data.onSelect -= value; + _data._onSelect -= value; } } - private static void CleanListItems(MenuItem senderMenu) { - - // remove dynamic items. - - for (int i = senderMenu.MenuItems.Count - 1; i >= 0; i--) { + private static void CleanListItems(MenuItem senderMenu) + { + // Remove dynamic items. + for (int i = senderMenu.MenuItems.Count - 1; i >= 0; i--) + { MenuItem item = senderMenu.MenuItems[i]; - if (item.data.UserData is MdiListUserData) { - // this is a dynamic item. clean it up! - // + if (item._data.UserData is MdiListUserData) + { item.Dispose(); continue; } } } - /// /// - /// - /// Creates and returns an identical copy of this menu item. - /// + /// Creates and returns an identical copy of this menu item. /// - public virtual MenuItem CloneMenu() { - MenuItem newItem = new MenuItem(); + public virtual MenuItem CloneMenu() + { + var newItem = new MenuItem(); newItem.CloneMenu(this); return newItem; } - /// /// - /// - /// Creates a copy of the specified menu item. - /// + /// Creates a copy of the specified menu item. /// [SuppressMessage("Microsoft.Performance", "CA1806:DoNotIgnoreMethodResults")] - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] // Shipped in Everett - protected void CloneMenu(MenuItem itemSrc) { + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Already shipped as public API")] + protected void CloneMenu(MenuItem itemSrc) + { base.CloneMenu(itemSrc); - int state = itemSrc.data.State; + int state = itemSrc._data.State; new MenuItemData(this, itemSrc.MergeType, itemSrc.MergeOrder, itemSrc.Shortcut, itemSrc.ShowShortcut, - itemSrc.Text, itemSrc.data.onClick, itemSrc.data.onPopup, itemSrc.data.onSelect, - itemSrc.data.onDrawItem, itemSrc.data.onMeasureItem); - data.SetState(state & STATE_CLONE_MASK, true); + itemSrc.Text, itemSrc._data._onClick, itemSrc._data._onPopup, itemSrc._data._onSelect, + itemSrc._data._onDrawItem, itemSrc._data._onMeasureItem); + _data.SetState(state & StateCloneMask, true); } - internal virtual void CreateMenuItem() { - if ((data.State & STATE_HIDDEN) == 0) { + internal virtual void CreateMenuItem() + { + if ((_data.State & StateHidden) == 0) + { NativeMethods.MENUITEMINFO_T info = CreateMenuItemInfo(); - UnsafeNativeMethods.InsertMenuItem(new HandleRef(menu, menu.handle), -1, true, info); + UnsafeNativeMethods.InsertMenuItem(new HandleRef(Parent, Parent.handle), -1, true, info); - hasHandle = info.hSubMenu != IntPtr.Zero; - dataVersion = data.version; + _hasHandle = info.hSubMenu != IntPtr.Zero; + _dataVersion = _data._version; - menuItemIsCreated = true; - if(RenderIsRightToLeft) { - Menu.UpdateRtl(true); + _menuItemIsCreated = true; + if (RenderIsRightToLeft) + { + Parent.UpdateRtl(true); } #if DEBUG NativeMethods.MENUITEMINFO_T infoVerify = new NativeMethods.MENUITEMINFO_T(); - infoVerify.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); + infoVerify.cbSize = Marshal.SizeOf(); infoVerify.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE; - UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, infoVerify); + UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, infoVerify); #endif } } - private NativeMethods.MENUITEMINFO_T CreateMenuItemInfo() { - NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); + private NativeMethods.MENUITEMINFO_T CreateMenuItemInfo() + { + var info = new NativeMethods.MENUITEMINFO_T(); info.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE | NativeMethods.MIIM_DATA; - info.fType = data.State & (STATE_BARBREAK | STATE_BREAK | STATE_RADIOCHECK | STATE_OWNERDRAW); + info.fType = _data.State & (StateBarBreak | StateBreak | StateRadioCheck | StateOwnerDraw); - // V7#646 - Top level menu items shouldn't have barbreak or break - // bits set on them... - // - bool isTopLevel = false; - if (menu == GetMainMenu()) { - isTopLevel = true; - } + // Top level menu items shouldn't have barbreak or break bits set on them. + bool isTopLevel = Parent == GetMainMenu(); - if (data.caption.Equals("-")) { - if (isTopLevel) { - data.caption = " "; + if (_data._caption.Equals("-")) + { + if (isTopLevel) + { + _data._caption = " "; info.fType |= NativeMethods.MFT_MENUBREAK; } - else { + else + { info.fType |= NativeMethods.MFT_SEPARATOR; } } - - info.fState = data.State & (STATE_CHECKED | STATE_DEFAULT | STATE_DISABLED); + info.fState = _data.State & (StateChecked | StateDefault | StateDisabled); info.wID = MenuID; - if (IsParent) { + if (IsParent) + { info.hSubMenu = Handle; } + info.hbmpChecked = IntPtr.Zero; info.hbmpUnchecked = IntPtr.Zero; - // Assign a unique ID to this menu item object... - // The ID is stored in the dwItemData of the corresponding Win32 menu item, so that when we get Win32 - // messages about the item later, we can delegate to the original object menu item object. A static - // hash table is used to map IDs to menu item objects. - // - if (uniqueID == 0) { - lock(allCreatedMenuItems) { - uniqueID = (uint)Interlocked.Increment(ref nextUniqueID); - Debug.Assert(uniqueID >= firstUniqueID); // ...check for ID range exhaustion (unlikely!) - // We add a weak ref wrapping a MenuItem to the static hash table, as supposed to adding the item - // ref itself, to allow the item to be finalized in case it is not disposed and no longer referenced - // anywhere else, hence preventing leaks. See - allCreatedMenuItems.Add(uniqueID, new WeakReference(this)); + // Assign a unique ID to this menu item object. + // The ID is stored in the dwItemData of the corresponding Win32 menu item, so + // that when we get Win32 messages about the item later, we can delegate to the + // original object menu item object. A static hash table is used to map IDs to + // menu item objects. + if (_uniqueID == 0) + { + lock (s_allCreatedMenuItems) + { + _uniqueID = (uint)Interlocked.Increment(ref s_nextUniqueID); + Debug.Assert(_uniqueID >= FirstUniqueID); // ...check for ID range exhaustion (unlikely!) + // We add a weak ref wrapping a MenuItem to the static hash table, as + // supposed to adding the item ref itself, to allow the item to be finalized + // in case it is not disposed and no longer referenced anywhere else, hence + // preventing leaks. + s_allCreatedMenuItems.Add(_uniqueID, new WeakReference(this)); } } - // To check it's 32-bit OS or 64-bit OS. - if (IntPtr.Size == 4) { - // Store the unique ID in the dwItemData... - // For simple menu items, we can just put the unique ID in the dwItemData. But for owner-draw items, - // we need to point the dwItemData at an MSAAMENUINFO structure so that MSAA can get the item text. - // To allow us to reliably distinguish between IDs and structure pointers later on, we keep IDs in - // the 0xC0000000-0xFFFFFFFF range. This is the top 1Gb of unmananged process memory, where an app's - // heap allocations should never come from. So that we can still get the ID from the dwItemData for - // an owner-draw item later on, a copy of the ID is tacked onto the end of the MSAAMENUINFO structure. - // - if (data.OwnerDraw) + if (IntPtr.Size == 4) + { + // Store the unique ID in the dwItemData.. + // For simple menu items, we can just put the unique ID in the dwItemData. + // But for owner-draw items, we need to point the dwItemData at an MSAAMENUINFO + // structure so that MSAA can get the item text. + // To allow us to reliably distinguish between IDs and structure pointers later + // on, we keep IDs in the 0xC0000000-0xFFFFFFFF range. This is the top 1Gb of + // unmananged process memory, where an app's heap allocations should never come + // from. So that we can still get the ID from the dwItemData for an owner-draw + // item later on, a copy of the ID is tacked onto the end of the MSAAMENUINFO + // structure. + if (_data.OwnerDraw) + { info.dwItemData = AllocMsaaMenuInfo(); + } else - info.dwItemData = (IntPtr) unchecked((int) uniqueID); + { + info.dwItemData = (IntPtr)unchecked((int)_uniqueID); + } } - else { + else + { // On Win64, there are no reserved address ranges we can use for menu item IDs. So instead we will // have to allocate an MSAMENUINFO heap structure for all menu items, not just owner-drawn ones. info.dwItemData = AllocMsaaMenuInfo(); } - + // We won't render the shortcut if: 1) it's not set, 2) we're a parent, 3) we're toplevel - // - if (data.showShortcut && data.shortcut != 0 && !IsParent && !isTopLevel) { - info.dwTypeData = data.caption + "\t" + TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString((Keys)(int)data.shortcut); + if (_data._showShortcut && _data._shortcut != 0 && !IsParent && !isTopLevel) + { + info.dwTypeData = _data._caption + "\t" + TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString((Keys)(int)_data._shortcut); } - else { + else + { // Windows issue: Items with empty captions sometimes block keyboard // access to other items in same menu. - info.dwTypeData = (data.caption.Length == 0 ? " " : data.caption); + info.dwTypeData = (_data._caption.Length == 0 ? " " : _data._caption); } info.cch = 0; return info; } - /// /// - /// - /// Disposes the . - /// + /// Disposes the . /// - protected override void Dispose(bool disposing) { - - if (disposing) { - if (menu != null) { - menu.MenuItems.Remove(this); - } - - if (data != null) { - data.RemoveItem(this); - } - lock(allCreatedMenuItems) { - allCreatedMenuItems.Remove(uniqueID); + protected override void Dispose(bool disposing) + { + if (disposing) + { + Parent?.MenuItems.Remove(this); + _data?.RemoveItem(this); + lock (s_allCreatedMenuItems) + { + s_allCreatedMenuItems.Remove(_uniqueID); } - this.uniqueID = 0; - + + _uniqueID = 0; + } + FreeMsaaMenuInfo(); base.Dispose(disposing); } - - // Given a unique menu item ID, find the corresponding MenuItem - // object, using the master lookup table of all created MenuItems. - internal static MenuItem GetMenuItemFromUniqueID(uint uniqueID) { - WeakReference weakRef = (WeakReference)allCreatedMenuItems[uniqueID]; - if (weakRef != null && weakRef.IsAlive) { - return (MenuItem)weakRef.Target; - } - Debug.Fail("Weakref for menu item has expired or has been removed! Who is trying to access this ID?"); - return null; + /// + /// Given a unique menu item ID, find the corresponding MenuItem + /// object, using the master lookup table of all created MenuItems. + /// + internal static MenuItem GetMenuItemFromUniqueID(uint uniqueID) + { + WeakReference weakRef = (WeakReference)s_allCreatedMenuItems[uniqueID]; + if (weakRef != null && weakRef.IsAlive) + { + return (MenuItem)weakRef.Target; + } + Debug.Fail("Weakref for menu item has expired or has been removed! Who is trying to access this ID?"); + return null; } - // Given the "item data" value of a Win32 menu item, find the corresponding MenuItem object (using - // the master lookup table of all created MenuItems). The item data may be either the unique menu - // item ID, or a pointer to an MSAAMENUINFO structure with a copy of the unique ID tacked to the end. - // To reliably tell IDs and structure addresses apart, IDs live in the 0xC0000000-0xFFFFFFFF range. - // This is the top 1Gb of unmananged process memory, where an app's heap allocations should never be. + /// + /// Given the "item data" value of a Win32 menu item, find the corresponding MenuItem object (using + /// the master lookup table of all created MenuItems). The item data may be either the unique menu + /// item ID, or a pointer to an MSAAMENUINFO structure with a copy of the unique ID tacked to the end. + /// To reliably tell IDs and structure addresses apart, IDs live in the 0xC0000000-0xFFFFFFFF range. + /// This is the top 1Gb of unmananged process memory, where an app's heap allocations should never be. + /// [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")] - internal static MenuItem GetMenuItemFromItemData(IntPtr itemData) { - uint uniqueID = (uint) (ulong) itemData; - + internal static MenuItem GetMenuItemFromItemData(IntPtr itemData) + { + uint uniqueID = (uint)(ulong)itemData; if (uniqueID == 0) + { return null; + } - // To check it's 32-bit OS or 64-bit OS. - if (IntPtr.Size == 4) { - if (uniqueID < firstUniqueID) { - MsaaMenuInfoWithId msaaMenuInfo = (MsaaMenuInfoWithId) Marshal.PtrToStructure(itemData, typeof(MsaaMenuInfoWithId)); - uniqueID = msaaMenuInfo.uniqueID; + if (IntPtr.Size == 4) + { + if (uniqueID < FirstUniqueID) + { + MsaaMenuInfoWithId msaaMenuInfo = Marshal.PtrToStructure(itemData); + uniqueID = msaaMenuInfo._uniqueID; } } - else { - // ...its always a pointer on Win64 (see CreateMenuItemInfo) - MsaaMenuInfoWithId msaaMenuInfo = (MsaaMenuInfoWithId) Marshal.PtrToStructure(itemData, typeof(MsaaMenuInfoWithId)); - uniqueID = msaaMenuInfo.uniqueID; + else + { + // Its always a pointer on Win64 (see CreateMenuItemInfo) + MsaaMenuInfoWithId msaaMenuInfo = Marshal.PtrToStructure(itemData); + uniqueID = msaaMenuInfo._uniqueID; } return GetMenuItemFromUniqueID(uniqueID); } - // MsaaMenuInfoWithId is an MSAAMENUINFO structure with a menu item ID field tacked onto the - // end. This allows us to pass the data we need to Win32 / MSAA, and still be able to get the ID - // out again later on, so we can delegate Win32 menu messages back to the correct MenuItem object. + /// + /// MsaaMenuInfoWithId is an MSAAMENUINFO structure with a menu item ID field tacked onto the + /// end. This allows us to pass the data we need to Win32 / MSAA, and still be able to get the ID + /// out again later on, so we can delegate Win32 menu messages back to the correct MenuItem object. + /// [StructLayout(LayoutKind.Sequential)] - private struct MsaaMenuInfoWithId { - public NativeMethods.MSAAMENUINFO msaaMenuInfo; - public uint uniqueID; - - public MsaaMenuInfoWithId(string text, uint uniqueID) { - msaaMenuInfo = new NativeMethods.MSAAMENUINFO(text); - this.uniqueID = uniqueID; + private struct MsaaMenuInfoWithId + { + public readonly NativeMethods.MSAAMENUINFO _msaaMenuInfo; + public readonly uint _uniqueID; + + public MsaaMenuInfoWithId(string text, uint uniqueID) + { + _msaaMenuInfo = new NativeMethods.MSAAMENUINFO(text); + _uniqueID = uniqueID; } } - // Creates an MSAAMENUINFO structure (in the unmanaged heap) based on the current state - // of this MenuItem object. Address of this structure is cached in the object so we can - // free it later on using FreeMsaaMenuInfo(). If structure has already been allocated, - // it is destroyed and a new one created. - private IntPtr AllocMsaaMenuInfo() { + /// + /// Creates an MSAAMENUINFO structure (in the unmanaged heap) based on the current state + /// of this MenuItem object. Address of this structure is cached in the object so we can + /// free it later on using FreeMsaaMenuInfo(). If structure has already been allocated, + /// it is destroyed and a new one created. + /// + private IntPtr AllocMsaaMenuInfo() + { FreeMsaaMenuInfo(); - msaaMenuInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MsaaMenuInfoWithId))); + _msaaMenuInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf()); - // To check it's 32-bit OS or 64-bit OS. - if (IntPtr.Size == 4) { + if (IntPtr.Size == 4) + { // We only check this on Win32, irrelevant on Win64 (see CreateMenuItemInfo) - Debug.Assert(((uint) (ulong) msaaMenuInfoPtr) < firstUniqueID); // ...check for incursion into menu item ID range (unlikely!) + // Check for incursion into menu item ID range (unlikely!) + Debug.Assert(((uint)(ulong)_msaaMenuInfoPtr) < FirstUniqueID); } - MsaaMenuInfoWithId msaaMenuInfoStruct = new MsaaMenuInfoWithId(data.caption, uniqueID); - Marshal.StructureToPtr(msaaMenuInfoStruct, msaaMenuInfoPtr, false); - Debug.Assert(msaaMenuInfoPtr != IntPtr.Zero); - return msaaMenuInfoPtr; + MsaaMenuInfoWithId msaaMenuInfoStruct = new MsaaMenuInfoWithId(_data._caption, _uniqueID); + Marshal.StructureToPtr(msaaMenuInfoStruct, _msaaMenuInfoPtr, false); + Debug.Assert(_msaaMenuInfoPtr != IntPtr.Zero); + return _msaaMenuInfoPtr; } - // Frees the MSAAMENUINFO structure (in the unmanaged heap) for the current MenuObject object, - // if one has previously been allocated. Takes care to free sub-structures too, to avoid leaks! - private void FreeMsaaMenuInfo() { - if (msaaMenuInfoPtr != IntPtr.Zero) { - Marshal.DestroyStructure(msaaMenuInfoPtr, typeof(MsaaMenuInfoWithId)); - Marshal.FreeHGlobal(msaaMenuInfoPtr); - msaaMenuInfoPtr = IntPtr.Zero; + /// + /// Frees the MSAAMENUINFO structure (in the unmanaged heap) for the current MenuObject + /// object, if one has previously been allocated. Takes care to free sub-structures too, + /// to avoid leaks! + /// + private void FreeMsaaMenuInfo() + { + if (_msaaMenuInfoPtr != IntPtr.Zero) + { + Marshal.DestroyStructure(_msaaMenuInfoPtr, typeof(MsaaMenuInfoWithId)); + Marshal.FreeHGlobal(_msaaMenuInfoPtr); + _msaaMenuInfoPtr = IntPtr.Zero; } } - internal override void ItemsChanged(int change) { + internal override void ItemsChanged(int change) + { base.ItemsChanged(change); - if (change == CHANGE_ITEMS) { - // when the menu collection changes deal w/ it locally - Debug.Assert(!this.created, "base.ItemsChanged should have wiped out our handles"); - if (menu != null && menu.created) { - UpdateMenuItem(true); + if (change == CHANGE_ITEMS) + { + // when the menu collection changes deal with it locally + Debug.Assert(!created, "base.ItemsChanged should have wiped out our handles"); + if (Parent != null && Parent.created) + { + UpdateMenuItem(force: true); CreateMenuItems(); } - } else { - if (!hasHandle && IsParent) - UpdateMenuItem(true); + } + else + { + if (!_hasHandle && IsParent) + { + UpdateMenuItem(force: true); + } MainMenu main = GetMainMenu(); - if (main != null && ((data.State & STATE_INMDIPOPUP) == 0)) { + if (main != null && ((_data.State & StateInMdiPopup) == 0)) + { main.ItemsChanged(change, this); } } } - internal void ItemsChanged(int change, MenuItem item) { + internal void ItemsChanged(int change, MenuItem item) + { if (change == CHANGE_ITEMADDED && - this.data != null && - this.data.baseItem != null && - this.data.baseItem.MenuItems.Contains(item)) { - if (menu != null && menu.created) { - UpdateMenuItem(true); + _data != null && + _data.baseItem != null && + _data.baseItem.MenuItems.Contains(item)) + { + if (Parent != null && Parent.created) + { + UpdateMenuItem(force: true); CreateMenuItems(); - } else if (this.data != null) { - MenuItem currentMenuItem = this.data.firstItem; - while (currentMenuItem != null) { - if (currentMenuItem.created) { + } + else if (_data != null) + { + MenuItem currentMenuItem = _data.firstItem; + while (currentMenuItem != null) + { + if (currentMenuItem.created) + { MenuItem newItem = item.CloneMenu(); - item.data.AddItem(newItem); + item._data.AddItem(newItem); currentMenuItem.MenuItems.Add(newItem); - // newItem.menu = currentMenuItem; - // newItem.CreateMenuItem(); break; } - currentMenuItem = currentMenuItem.nextLinkedItem; + currentMenuItem = currentMenuItem._nextLinkedItem; } } } } - internal Form[] FindMdiForms() { + internal Form[] FindMdiForms() + { Form[] forms = null; MainMenu main = GetMainMenu(); Form menuForm = null; - if (main != null) { + if (main != null) + { menuForm = main.GetFormUnsafe(); } - if (menuForm != null) { + if (menuForm != null) + { forms = menuForm.MdiChildren; } - if (forms == null) { + if (forms == null) + { forms = new Form[0]; } + return forms; } - /// - /// See the similar code in MdiWindowListStripcs::PopulateItems(), which is - /// unfortunately just different enough in its working environment that we - /// can't readily combine the two. But if you're fixing something here, chances - /// are that the same issue will need scrutiny over there. + /// + /// See the similar code in MdiWindowListStrip.PopulateItems, which is + /// unfortunately just different enough in its working environment that we + /// can't readily combine the two. But if you're fixing something here, chances + /// are that the same issue will need scrutiny over there. /// [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] // "-" is OK - private void PopulateMdiList() { + private void PopulateMdiList() + { MenuItem senderMenu = this; - data.SetState(STATE_INMDIPOPUP, true); - try { + _data.SetState(StateInMdiPopup, true); + try + { CleanListItems(this); - // add new items - // + // Add new items Form[] forms = FindMdiForms(); - if (forms != null && forms.Length > 0) { + if (forms != null && forms.Length > 0) + { Form activeMdiChild = GetMainMenu().GetFormUnsafe().ActiveMdiChild; - if (senderMenu.MenuItems.Count > 0) { - // - - MenuItem sep = (MenuItem)Activator.CreateInstance(this.GetType()); - sep.data.UserData = new MdiListUserData(); + if (senderMenu.MenuItems.Count > 0) + { + MenuItem sep = (MenuItem)Activator.CreateInstance(GetType()); + sep._data.UserData = new MdiListUserData(); sep.Text = "-"; senderMenu.MenuItems.Add(sep); } @@ -1211,26 +1115,30 @@ private void PopulateMdiList() { // in forms[], and make the active form the last one on the menu. // Don't count nonvisible forms against the limit on Window menu items. - const int maxMenuForms = 9; // Max number of Window menu items for forms + const int MaxMenuForms = 9; // Max number of Window menu items for forms int visibleChildren = 0; // the number of visible child forms (so we know to show More Windows...) int accel = 1; // prefix the form name with this digit, underlined, as an accelerator int formsAddedToMenu = 0; bool activeFormAdded = false; - for (int i = 0; i < forms.Length; i++) { - if (forms[i].Visible) { + for (int i = 0; i < forms.Length; i++) + { + if (forms[i].Visible) + { visibleChildren++; - if ((activeFormAdded && (formsAddedToMenu < maxMenuForms)) || // don't exceed max - (!activeFormAdded && (formsAddedToMenu < (maxMenuForms-1)) || // save room for active if it's not in yet - (forms[i].Equals(activeMdiChild)))){ // there's always room for activeMdiChild - // - - MenuItem windowItem = (MenuItem)Activator.CreateInstance(this.GetType()); - windowItem.data.UserData = new MdiListFormData(this, i); - - if (forms[i].Equals(activeMdiChild)) { + if ((activeFormAdded && (formsAddedToMenu < MaxMenuForms)) || // don't exceed max + (!activeFormAdded && (formsAddedToMenu < (MaxMenuForms - 1)) || // save room for active if it's not in yet + (forms[i].Equals(activeMdiChild)))) + { + // there's always room for activeMdiChild + MenuItem windowItem = (MenuItem)Activator.CreateInstance(GetType()); + windowItem._data.UserData = new MdiListFormData(this, i); + + if (forms[i].Equals(activeMdiChild)) + { windowItem.Checked = true; activeFormAdded = true; } + windowItem.Text = string.Format(CultureInfo.CurrentUICulture, "&{0} {1}", accel, forms[i].Text); accel++; formsAddedToMenu++; @@ -1242,319 +1150,303 @@ private void PopulateMdiList() { // Display the More Windows menu option when there are more than 9 MDI // Child menu items to be displayed. This is necessary because we're managing our own // MDI lists, rather than letting Windows do this for us. - if (visibleChildren > maxMenuForms) { - // - - MenuItem moreWindows = (MenuItem)Activator.CreateInstance(this.GetType()); - moreWindows.data.UserData = new MdiListMoreWindowsData(this); + if (visibleChildren > MaxMenuForms) + { + MenuItem moreWindows = (MenuItem)Activator.CreateInstance(GetType()); + moreWindows._data.UserData = new MdiListMoreWindowsData(this); moreWindows.Text = SR.MDIMenuMoreWindows; senderMenu.MenuItems.Add(moreWindows); } } } - finally { - data.SetState(STATE_INMDIPOPUP, false); + finally + { + _data.SetState(StateInMdiPopup, false); } } - /// /// - /// - /// Merges this menu item with another menu item and returns - /// the resulting merged . - /// + /// Merges this menu item with another menu item and returns the resulting merged + /// . /// - public virtual MenuItem MergeMenu() { + public virtual MenuItem MergeMenu() + { CheckIfDisposed(); - MenuItem newItem = (MenuItem)Activator.CreateInstance(this.GetType()); - data.AddItem(newItem); + MenuItem newItem = (MenuItem)Activator.CreateInstance(GetType()); + _data.AddItem(newItem); newItem.MergeMenu(this); return newItem; } - /// /// - /// - /// Merges another menu item with this menu item. - /// + /// Merges another menu item with this menu item. /// - [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // Shipped in Everett - public void MergeMenu(MenuItem itemSrc) { + [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Already shipped as public API")] + public void MergeMenu(MenuItem itemSrc) + { base.MergeMenu(itemSrc); - itemSrc.data.AddItem(this); + itemSrc._data.AddItem(this); } - /// /// - /// - /// Raises the - /// event. - /// + /// Raises the event. /// - protected virtual void OnClick(EventArgs e) { + protected virtual void OnClick(EventArgs e) + { CheckIfDisposed(); - if (data.UserData is MdiListUserData) { - ((MdiListUserData)data.UserData).OnClick(e); + if (_data.UserData is MdiListUserData) + { + ((MdiListUserData)_data.UserData).OnClick(e); } - else if (data.baseItem != this) { - data.baseItem.OnClick(e); + else if (_data.baseItem != this) + { + _data.baseItem.OnClick(e); } - else if (data.onClick != null) { - data.onClick(this, e); + else if (_data._onClick != null) + { + _data._onClick(this, e); } } - /// /// - /// - /// Raises the - /// event. - /// + /// Raises the event. /// - protected virtual void OnDrawItem(DrawItemEventArgs e) { + protected virtual void OnDrawItem(DrawItemEventArgs e) + { CheckIfDisposed(); - if (data.baseItem != this) { - data.baseItem.OnDrawItem(e); + if (_data.baseItem != this) + { + _data.baseItem.OnDrawItem(e); } - else if (data.onDrawItem != null) { - data.onDrawItem(this, e); + else if (_data._onDrawItem != null) + { + _data._onDrawItem(this, e); } } - /// /// - /// - /// Raises the - /// event. - /// + /// Raises the event. /// - protected virtual void OnMeasureItem(MeasureItemEventArgs e) { + protected virtual void OnMeasureItem(MeasureItemEventArgs e) + { CheckIfDisposed(); - if (data.baseItem != this) { - data.baseItem.OnMeasureItem(e); + if (_data.baseItem != this) + { + _data.baseItem.OnMeasureItem(e); } - else if (data.onMeasureItem != null) { - data.onMeasureItem(this, e); + else if (_data._onMeasureItem != null) + { + _data._onMeasureItem(this, e); } - } - /// /// - /// - /// Raises the - /// event. - /// + /// Raises the event. /// - protected virtual void OnPopup(EventArgs e) { + protected virtual void OnPopup(EventArgs e) + { CheckIfDisposed(); bool recreate = false; - for (int i=0; i /// - /// - /// Raises the - /// event. - /// + /// Raises the event. /// - protected virtual void OnSelect(EventArgs e) { + protected virtual void OnSelect(EventArgs e) + { CheckIfDisposed(); - if (data.baseItem != this) { - data.baseItem.OnSelect(e); + if (_data.baseItem != this) + { + _data.baseItem.OnSelect(e); } - else if (data.onSelect != null) { - data.onSelect(this, e); + else if (_data._onSelect != null) + { + _data._onSelect(this, e); } } - /// - /// - protected virtual void OnInitMenuPopup(EventArgs e) { - OnPopup(e); - } - - // C#r - internal virtual void _OnInitMenuPopup( EventArgs e ) { - OnInitMenuPopup( e ); - } + protected internal virtual void OnInitMenuPopup(EventArgs e) => OnPopup(e); - /// /// - /// - /// Generates a - /// event for the MenuItem, simulating a click by a - /// user. - /// + /// Generates a event for the MenuItem, + /// simulating a click by a user. /// - public void PerformClick() { - OnClick(EventArgs.Empty); - } + public void PerformClick() => OnClick(EventArgs.Empty); - /// /// - /// - /// Raises the - /// event for this menu item. - /// + /// Raises the event for this menu item. /// - public virtual void PerformSelect() { - OnSelect(EventArgs.Empty); - } + public virtual void PerformSelect() => OnSelect(EventArgs.Empty); - internal virtual bool ShortcutClick() { - if (menu is MenuItem) { - MenuItem parent = (MenuItem)menu; - if (!parent.ShortcutClick() || menu != parent) return false; + internal virtual bool ShortcutClick() + { + if (Parent is MenuItem parent) + { + if (!parent.ShortcutClick() || Parent != parent) + { + return false; + } + } + if ((_data.State & StateDisabled) != 0) + { + return false; } - if ((data.State & STATE_DISABLED) != 0) return false; if (ItemCount > 0) + { OnPopup(EventArgs.Empty); + } else + { OnClick(EventArgs.Empty); + } + return true; } - - /// - /// - /// - /// - /// Returns a string representation for this control. - /// - /// - public override string ToString() { - + public override string ToString() + { string s = base.ToString(); - - string menuItemText = string.Empty; - - if (data != null && data.caption != null) - menuItemText = data.caption; - + string menuItemText = _data?._caption ?? string.Empty;; return s + ", Text: " + menuItemText; } - internal void UpdateMenuItemIfDirty() { - if (dataVersion != data.version) - UpdateMenuItem(true); - } - - internal void UpdateItemRtl(bool setRightToLeftBit) { - if(!menuItemIsCreated) { + internal void UpdateItemRtl(bool setRightToLeftBit) + { + if (!_menuItemIsCreated) + { return; } - - NativeMethods.MENUITEMINFO_T info = new NativeMethods.MENUITEMINFO_T(); - info.fMask = NativeMethods.MIIM_TYPE | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU; - info.dwTypeData = new string('\0', Text.Length + 2); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); - info.cch = info.dwTypeData.Length - 1; - UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); - if(setRightToLeftBit) { + + var info = new NativeMethods.MENUITEMINFO_T(); + info.fMask = NativeMethods.MIIM_TYPE | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU; + info.dwTypeData = new string('\0', Text.Length + 2); + info.cbSize = Marshal.SizeOf(); + info.cch = info.dwTypeData.Length - 1; + UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, info); + if (setRightToLeftBit) + { info.fType |= NativeMethods.MFT_RIGHTJUSTIFY | NativeMethods.MFT_RIGHTORDER; - } else { + } + else + { info.fType &= ~(NativeMethods.MFT_RIGHTJUSTIFY | NativeMethods.MFT_RIGHTORDER); - } - UnsafeNativeMethods.SetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); + } + + UnsafeNativeMethods.SetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, info); #if DEBUG info.fMask = NativeMethods.MIIM_TYPE | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU; info.dwTypeData = new string('\0', 256); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); + info.cbSize = Marshal.SizeOf(); info.cch = info.dwTypeData.Length - 1; - UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); + UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, info); Debug.Assert(((info.fType & NativeMethods.MFT_RIGHTORDER) != 0) == setRightToLeftBit, "Failed to set bit!"); - + #endif } - - internal void UpdateMenuItem(bool force) { - if (menu == null || !menu.created) { + internal void UpdateMenuItem(bool force) + { + if (Parent == null || !Parent.created) + { return; } - if (force || menu is MainMenu || menu is ContextMenu) { + if (force || Parent is MainMenu || Parent is ContextMenu) + { NativeMethods.MENUITEMINFO_T info = CreateMenuItemInfo(); - UnsafeNativeMethods.SetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, info); + UnsafeNativeMethods.SetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, info); #if DEBUG - NativeMethods.MENUITEMINFO_T infoVerify = new NativeMethods.MENUITEMINFO_T(); - infoVerify.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T)); + var infoVerify = new NativeMethods.MENUITEMINFO_T(); + infoVerify.cbSize = Marshal.SizeOf(); infoVerify.fMask = NativeMethods.MIIM_ID | NativeMethods.MIIM_STATE | NativeMethods.MIIM_SUBMENU | NativeMethods.MIIM_TYPE; - UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(menu, menu.handle), MenuID, false, infoVerify); + UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(Parent, Parent.handle), MenuID, false, infoVerify); #endif - if (hasHandle && info.hSubMenu == IntPtr.Zero) { + if (_hasHandle && info.hSubMenu == IntPtr.Zero) + { ClearHandles(); } - hasHandle = info.hSubMenu != IntPtr.Zero; - dataVersion = data.version; - if (menu is MainMenu) { - Form f = ((MainMenu)menu).GetFormUnsafe(); - if (f != null) { + + _hasHandle = info.hSubMenu != IntPtr.Zero; + _dataVersion = _data._version; + if (Parent is MainMenu mainMenu) + { + Form f = mainMenu.GetFormUnsafe(); + if (f != null) + { SafeNativeMethods.DrawMenuBar(new HandleRef(f, f.Handle)); } } } } - /// - /// - /// - /// - internal void WmDrawItem(ref Message m) { - + internal void WmDrawItem(ref Message m) + { // Handles the OnDrawItem message sent from ContainerControl - NativeMethods.DRAWITEMSTRUCT dis = (NativeMethods.DRAWITEMSTRUCT)m.GetLParam(typeof(NativeMethods.DRAWITEMSTRUCT)); Debug.WriteLineIf(Control.PaletteTracing.TraceVerbose, Handle + ": Force set palette in MenuItem drawitem"); IntPtr oldPal = Control.SetUpPalette(dis.hDC, false /*force*/, false); - try { + try + { Graphics g = Graphics.FromHdcInternal(dis.hDC); - try { - OnDrawItem(new DrawItemEventArgs(g, SystemInformation.MenuFont, Rectangle.FromLTRB(dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom), Index, (DrawItemState)dis.itemState)); + try + { + OnDrawItem(new DrawItemEventArgs(g, SystemInformation.MenuFont, Rectangle.FromLTRB(dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom), Index, (DrawItemState)dis.itemState)); } - finally { + finally + { g.Dispose(); } } - finally { - if (oldPal != IntPtr.Zero) { + finally + { + if (oldPal != IntPtr.Zero) + { SafeNativeMethods.SelectPalette(new HandleRef(null, dis.hDC), new HandleRef(null, oldPal), 0); } } @@ -1562,27 +1454,26 @@ internal void WmDrawItem(ref Message m) { m.Result = (IntPtr)1; } - /// - /// - /// - /// - internal void WmMeasureItem(ref Message m) { - + internal void WmMeasureItem(ref Message m) + { // Handles the OnMeasureItem message sent from ContainerControl // Obtain the measure item struct NativeMethods.MEASUREITEMSTRUCT mis = (NativeMethods.MEASUREITEMSTRUCT)m.GetLParam(typeof(NativeMethods.MEASUREITEMSTRUCT)); - // The OnMeasureItem handler now determines the height and width of the item + // The OnMeasureItem handler now determines the height and width of the item IntPtr screendc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); Graphics graphics = Graphics.FromHdcInternal(screendc); MeasureItemEventArgs mie = new MeasureItemEventArgs(graphics, Index); - try { - OnMeasureItem(mie); + try + { + OnMeasureItem(mie); } - finally { + finally + { graphics.Dispose(); } + UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, screendc)); // Update the measure item struct with the new width and height @@ -1595,268 +1486,290 @@ internal void WmMeasureItem(ref Message m) { private void CheckIfDisposed() { - if (data == null) + if (_data == null) { throw new ObjectDisposedException(GetType().FullName); } } - - /// - /// - /// - internal class MenuItemData : ICommandExecutor { + internal class MenuItemData : ICommandExecutor + { internal MenuItem baseItem; internal MenuItem firstItem; - private int state; - internal int version; - internal MenuMerge mergeType; - internal int mergeOrder; - internal string caption; - internal short mnemonic; - internal Shortcut shortcut; - internal bool showShortcut; - internal EventHandler onClick; - internal EventHandler onPopup; - internal EventHandler onSelect; - internal DrawItemEventHandler onDrawItem; - internal MeasureItemEventHandler onMeasureItem; - - private object userData = null; - internal Command cmd; + private int _state; + internal int _version; + internal MenuMerge _mergeType; + internal int _mergeOrder; + internal string _caption; + internal short _mnemonic; + internal Shortcut _shortcut; + internal bool _showShortcut; + internal EventHandler _onClick; + internal EventHandler _onPopup; + internal EventHandler _onSelect; + internal DrawItemEventHandler _onDrawItem; + internal MeasureItemEventHandler _onMeasureItem; + + private Command _cmd; internal MenuItemData(MenuItem baseItem, MenuMerge mergeType, int mergeOrder, Shortcut shortcut, bool showShortcut, - string caption, EventHandler onClick, EventHandler onPopup, EventHandler onSelect, - DrawItemEventHandler onDrawItem, MeasureItemEventHandler onMeasureItem) { + string caption, EventHandler onClick, EventHandler onPopup, EventHandler onSelect, + DrawItemEventHandler onDrawItem, MeasureItemEventHandler onMeasureItem) + { AddItem(baseItem); - this.mergeType = mergeType; - this.mergeOrder = mergeOrder; - this.shortcut = shortcut; - this.showShortcut = showShortcut; - this.caption = caption == null? "": caption; - this.onClick = onClick; - this.onPopup = onPopup; - this.onSelect = onSelect; - this.onDrawItem = onDrawItem; - this.onMeasureItem = onMeasureItem; - this.version = 1; - this.mnemonic = -1; - } - - - internal bool OwnerDraw { - get { - return ((State & STATE_OWNERDRAW) != 0); - } - set { - SetState(STATE_OWNERDRAW, value); - } + _mergeType = mergeType; + _mergeOrder = mergeOrder; + _shortcut = shortcut; + _showShortcut = showShortcut; + _caption = caption ?? string.Empty; + _onClick = onClick; + _onPopup = onPopup; + _onSelect = onSelect; + _onDrawItem = onDrawItem; + _onMeasureItem = onMeasureItem; + _version = 1; + _mnemonic = -1; + } + + + internal bool OwnerDraw + { + get => ((State & StateOwnerDraw) != 0); + set => SetState(StateOwnerDraw, value); } - internal bool MdiList { - get { - return HasState(STATE_MDILIST); - } - set { - if (((state & STATE_MDILIST) != 0) != value) { - SetState(STATE_MDILIST, value); - for (MenuItem item = firstItem; item != null; item = item.nextLinkedItem) { + internal bool MdiList + { + get => ((State & StateMdiList) == StateMdiList); + set + { + if (((_state & StateMdiList) != 0) != value) + { + SetState(StateMdiList, value); + for (MenuItem item = firstItem; item != null; item = item._nextLinkedItem) + { item.ItemsChanged(Menu.CHANGE_MDI); } } } } - internal MenuMerge MergeType { - get { - return mergeType; - } - set { - if (mergeType != value) { - mergeType = value; + internal MenuMerge MergeType + { + get => _mergeType; + set + { + if (_mergeType != value) + { + _mergeType = value; ItemsChanged(Menu.CHANGE_MERGE); } } } - internal int MergeOrder { - get { - return mergeOrder; - } - set { - if (mergeOrder != value) { - mergeOrder = value; + internal int MergeOrder + { + get => _mergeOrder; + set + { + if (_mergeOrder != value) + { + _mergeOrder = value; ItemsChanged(Menu.CHANGE_MERGE); } } } - internal char Mnemonic { - get { - if (mnemonic == -1) { - mnemonic = (short) WindowsFormsUtils.GetMnemonic(caption, true); + internal char Mnemonic + { + get + { + if (_mnemonic == -1) + { + _mnemonic = (short)WindowsFormsUtils.GetMnemonic(_caption, true); } - return(char)mnemonic; - } - } - internal int State { - get { - return state; + return (char)_mnemonic; } } - internal bool Visible { - get { - return(state & MenuItem.STATE_HIDDEN) == 0; - } - set { - if (((state & MenuItem.STATE_HIDDEN) == 0) != value) { - state = value? state & ~MenuItem.STATE_HIDDEN: state | MenuItem.STATE_HIDDEN; + internal int State => _state; + + internal bool Visible + { + get => (_state & MenuItem.StateHidden) == 0; + set + { + if (((_state & MenuItem.StateHidden) == 0) != value) + { + _state = value ? _state & ~MenuItem.StateHidden : _state | MenuItem.StateHidden; ItemsChanged(Menu.CHANGE_VISIBLE); } } } - internal object UserData { - get { - return userData; - } - set { - userData = value; - } - } + internal object UserData { get; set; } - internal void AddItem(MenuItem item) { - if (item.data != this) { - if (item.data != null) { - item.data.RemoveItem(item); - } - - item.nextLinkedItem = firstItem; + internal void AddItem(MenuItem item) + { + if (item._data != this) + { + item._data?.RemoveItem(item); + + item._nextLinkedItem = firstItem; firstItem = item; - if (baseItem == null) baseItem = item; - item.data = this; - item.dataVersion = 0; + if (baseItem == null) + { + baseItem = item; + } + + item._data = this; + item._dataVersion = 0; item.UpdateMenuItem(false); } } - public void Execute() { - if (baseItem != null) { - baseItem.OnClick(EventArgs.Empty); - } + public void Execute() + { + baseItem?.OnClick(EventArgs.Empty); } - internal int GetMenuID() { - if (null == cmd) - cmd = new Command(this); - return cmd.ID; + internal int GetMenuID() + { + if (_cmd == null) + { + _cmd = new Command(this); + } + + return _cmd.ID; } - internal void ItemsChanged(int change) { - for (MenuItem item = firstItem; item != null; item = item.nextLinkedItem) { - if (item.menu != null) - item.menu.ItemsChanged(change); + internal void ItemsChanged(int change) + { + for (MenuItem item = firstItem; item != null; item = item._nextLinkedItem) + { + item.Parent?.ItemsChanged(change); } } - internal void RemoveItem(MenuItem item) { - Debug.Assert(item.data == this, "bad item passed to MenuItemData.removeItem"); + internal void RemoveItem(MenuItem item) + { + Debug.Assert(item._data == this, "bad item passed to MenuItemData.removeItem"); - if (item == firstItem) { - firstItem = item.nextLinkedItem; + if (item == firstItem) + { + firstItem = item._nextLinkedItem; } - else { + else + { MenuItem itemT; - for (itemT = firstItem; item != itemT.nextLinkedItem;) - itemT = itemT.nextLinkedItem; - itemT.nextLinkedItem = item.nextLinkedItem; + for (itemT = firstItem; item != itemT._nextLinkedItem;) + { + itemT = itemT._nextLinkedItem; + } + + itemT._nextLinkedItem = item._nextLinkedItem; } - item.nextLinkedItem = null; - item.data = null; - item.dataVersion = 0; + item._nextLinkedItem = null; + item._data = null; + item._dataVersion = 0; - if (item == baseItem) { + if (item == baseItem) + { baseItem = firstItem; } - if (firstItem == null) { + if (firstItem == null) + { // No longer needed. Toss all references and the Command object. Debug.Assert(baseItem == null, "why isn't baseItem null?"); - onClick = null; - onPopup = null; - onSelect = null; - onDrawItem = null; - onMeasureItem = null; - if (cmd != null) { - cmd.Dispose(); - cmd = null; + _onClick = null; + _onPopup = null; + _onSelect = null; + _onDrawItem = null; + _onMeasureItem = null; + if (_cmd != null) + { + _cmd.Dispose(); + _cmd = null; } } } - - internal void SetCaption(string value) { + + internal void SetCaption(string value) + { if (value == null) - value = ""; - if (!caption.Equals(value)) { - caption = value; - UpdateMenuItems(); + { + value = string.Empty; } - #if DEBUG - if (value.Length > 0) { - baseItem._debugText = value; - } - #endif - } + if (!_caption.Equals(value)) + { + _caption = value; + UpdateMenuItems(); + } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal bool HasState(int flag) { - return((State & flag) == flag); +#if DEBUG + if (value.Length > 0) + { + baseItem._debugText = value; + } +#endif } - internal void SetState(int flag, bool value) { - if (((state & flag) != 0) != value) { - state = value? state | flag: state & ~flag; + internal void SetState(int flag, bool value) + { + if (((_state & flag) != 0) != value) + { + _state = value ? _state | flag : _state & ~flag; UpdateMenuItems(); } } - internal void UpdateMenuItems() { - version++; - for (MenuItem item = firstItem; item != null; item = item.nextLinkedItem) { - item.UpdateMenuItem(true); + internal void UpdateMenuItems() + { + _version++; + for (MenuItem item = firstItem; item != null; item = item._nextLinkedItem) + { + item.UpdateMenuItem(force: true); } } - + } - private class MdiListUserData { - public virtual void OnClick(EventArgs e) { + private class MdiListUserData + { + public virtual void OnClick(EventArgs e) + { } } - private class MdiListFormData : MdiListUserData { - private MenuItem parent; - private int boundIndex; + private class MdiListFormData : MdiListUserData + { + private readonly MenuItem _parent; + private readonly int _boundIndex; - public MdiListFormData(MenuItem parentItem, int boundFormIndex) { - boundIndex = boundFormIndex; - parent = parentItem; + public MdiListFormData(MenuItem parentItem, int boundFormIndex) + { + _boundIndex = boundFormIndex; + _parent = parentItem; } - public override void OnClick(EventArgs e) { - if (boundIndex != -1) { - Form[] forms = parent.FindMdiForms(); + public override void OnClick(EventArgs e) + { + if (_boundIndex != -1) + { + Form[] forms = _parent.FindMdiForms(); Debug.Assert(forms != null, "Didn't get a list of the MDI Forms."); - - if (forms != null && forms.Length > boundIndex) { - Form boundForm = forms[boundIndex]; + + if (forms != null && forms.Length > _boundIndex) + { + Form boundForm = forms[_boundIndex]; boundForm.Activate(); - if (boundForm.ActiveControl != null && !boundForm.ActiveControl.Focused) { + if (boundForm.ActiveControl != null && !boundForm.ActiveControl.Focused) + { boundForm.ActiveControl.Focus(); } } @@ -1864,29 +1777,32 @@ public override void OnClick(EventArgs e) { } } - private class MdiListMoreWindowsData : MdiListUserData { + private class MdiListMoreWindowsData : MdiListUserData + { + private MenuItem _parent; - private MenuItem parent; - - public MdiListMoreWindowsData(MenuItem parent) { - this.parent = parent; + public MdiListMoreWindowsData(MenuItem parent) + { + _parent = parent; } - public override void OnClick(EventArgs e) { - Form[] forms = parent.FindMdiForms(); + public override void OnClick(EventArgs e) + { + Form[] forms = _parent.FindMdiForms(); Debug.Assert(forms != null, "Didn't get a list of the MDI Forms."); - Form active = parent.GetMainMenu().GetFormUnsafe().ActiveMdiChild; + Form active = _parent.GetMainMenu().GetFormUnsafe().ActiveMdiChild; Debug.Assert(active != null, "Didn't get the active MDI child"); - if (forms != null && forms.Length > 0 && active != null) { - using (MdiWindowDialog dialog = new MdiWindowDialog()) { + if (forms != null && forms.Length > 0 && active != null) + { + using (var dialog = new MdiWindowDialog()) + { dialog.SetItems(active, forms); DialogResult result = dialog.ShowDialog(); - if (result == DialogResult.OK) { - - // AllWindows Assert above allows this... - // + if (result == DialogResult.OK) + { dialog.ActiveChildForm.Activate(); - if (dialog.ActiveChildForm.ActiveControl != null && !dialog.ActiveChildForm.ActiveControl.Focused) { + if (dialog.ActiveChildForm.ActiveControl != null && !dialog.ActiveChildForm.ActiveControl.Focused) + { dialog.ActiveChildForm.ActiveControl.Focus(); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MenuStrip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MenuStrip.cs index f229e1c21c0..1c223f1835a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MenuStrip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MenuStrip.cs @@ -178,7 +178,7 @@ protected internal override ToolStripItem CreateDefaultItem(string text, Image i internal override ToolStripItem GetNextItem(ToolStripItem start, ArrowDirection direction, bool rtlAware) { ToolStripItem nextItem = base.GetNextItem(start, direction, rtlAware); - if (nextItem is MdiControlStrip.SystemMenuItem && AccessibilityImprovements.Level2) { + if (nextItem is MdiControlStrip.SystemMenuItem) { nextItem = base.GetNextItem(nextItem, direction, rtlAware); } return nextItem; @@ -236,7 +236,7 @@ protected override bool ProcessCmdKey(ref Message m, Keys keyData) { Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[MenuStrip.ProcessCmdKey] Rolling up the menu and invoking the system menu"); ToolStripManager.ModalMenuFilter.ExitMenuMode(); // send a WM_SYSCOMMAND SC_KEYMENU + Space to activate the system menu. - UnsafeNativeMethods.PostMessage(WindowsFormsUtils.GetRootHWnd(this), NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_KEYMENU, (int)Keys.Space); + UnsafeNativeMethods.PostMessage(WindowsFormsUtils.GetRootHWnd(this), Interop.WindowMessages.WM_SYSCOMMAND, NativeMethods.SC_KEYMENU, (int)Keys.Space); return true; } } @@ -252,7 +252,7 @@ protected override bool ProcessCmdKey(ref Message m, Keys keyData) { /// protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_MOUSEACTIVATE && (ActiveDropDowns.Count == 0)) { + if (m.Msg == Interop.WindowMessages.WM_MOUSEACTIVATE && (ActiveDropDowns.Count == 0)) { // call menu activate before we actually take focus. Point pt = PointToClient(WindowsFormsUtils.LastCursorPoint); ToolStripItem item = GetItemAt(pt); @@ -284,7 +284,7 @@ public override AccessibleRole Role { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_ControlTypePropertyId) { + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { return NativeMethods.UIA_MenuBarControlTypeId; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Message.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Message.cs index fb957fdd874..85edc3cd903 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Message.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Message.cs @@ -2,142 +2,84 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -namespace System.Windows.Forms { - using System.Text; - using System.Runtime.InteropServices; - using System.Runtime.Remoting; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System; - using System.Windows.Forms; - - - /// - /// - /// - /// Implements a Windows message. - /// - [SuppressMessage("Microsoft.Security", "CA2108:ReviewDeclarativeSecurityOnValueTypes")] - public struct Message { +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms +{ + /// + /// Implements a Windows message. + /// + public struct Message + { #if DEBUG - static TraceSwitch AllWinMessages = new TraceSwitch("AllWinMessages", "Output every received message"); + private static TraceSwitch s_allWinMessages = new TraceSwitch("AllWinMessages", "Output every received message"); #endif - IntPtr hWnd; - int msg; - IntPtr wparam; - IntPtr lparam; - IntPtr result; - - /// - /// - /// Specifies the window handle of the message. - /// - - public IntPtr HWnd { - get { return hWnd; } - set { hWnd = value; } - } - - /// - /// - /// Specifies the ID number for the message. - /// - public int Msg { - get { return msg; } - set { msg = value; } - } - - /// - /// - /// Specifies the of the message. - /// - public IntPtr WParam { - get { return wparam; } - set { wparam = value; } - } - - /// - /// - /// Specifies the of the message. - /// - public IntPtr LParam { - get { return lparam; } - set { lparam = value; } - } - - /// - /// - /// Specifies the return value of the message. - /// - public IntPtr Result { - get { return result; } - set { result = value; } - } + public IntPtr HWnd { get; set; } + + public int Msg { get; set; } + + /// + /// Specifies the of the message. + /// + public IntPtr WParam { get; set; } + + /// + /// Specifies the of the message. + /// + public IntPtr LParam { get; set; } + + /// + /// + public IntPtr Result { get; set; } + + /// + /// Gets the value, and converts the value to an object. + /// + public object GetLParam(Type cls) => Marshal.PtrToStructure(LParam, cls); + + /// + /// Creates a new object. + /// + public static Message Create(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) + { + var m = new Message(); + m.HWnd = hWnd; + m.Msg = msg; + m.WParam = wparam; + m.LParam = lparam; + m.Result = IntPtr.Zero; - /// - /// - /// Gets the value, and converts the value to an object. - /// - public object GetLParam(Type cls) { - return UnsafeNativeMethods.PtrToStructure(lparam, cls); - } - - /// - /// - /// Creates a new object. - /// - public static Message Create(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { - Message m = new Message(); - m.hWnd = hWnd; - m.msg = msg; - m.wparam = wparam; - m.lparam = lparam; - m.result = IntPtr.Zero; - #if DEBUG - if(AllWinMessages.TraceVerbose) { + if(s_allWinMessages.TraceVerbose) + { Debug.WriteLine(m.ToString()); } #endif return m; } - - /// - public override bool Equals(object o) { - if (!(o is Message)) { + + public override bool Equals(object o) + { + if (!(o is Message m)) + { return false; } - - Message m = (Message)o; - return hWnd == m.hWnd && - msg == m.msg && - wparam == m.wparam && - lparam == m.lparam && - result == m.result; - } - public static bool operator !=(Message a, Message b) { - return !a.Equals(b); + return HWnd == m.HWnd && + Msg == m.Msg && + WParam == m.WParam && + LParam == m.LParam && + Result == m.Result; } - public static bool operator ==(Message a, Message b) { - return a.Equals(b); - } + public static bool operator ==(Message a, Message b) => a.Equals(b); - /// - public override int GetHashCode() { - return (int)hWnd << 4 | msg; - } + public static bool operator !=(Message a, Message b) => !a.Equals(b); - /// - /// - /// - /// - public override string ToString() { - return MessageDecoder.ToString(this); - } + public override int GetHashCode() => HashCode.Combine(HWnd, Msg); + + public override string ToString() => MessageDecoder.ToString(this); } } - diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MessageBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MessageBox.cs index c0fdcd0fa4a..27812e1275e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MessageBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MessageBox.cs @@ -481,7 +481,7 @@ private static DialogResult ShowCore(IWin32Window owner, string text, string cap // but since we have disabled this thread main window the message is lost. So we have to send it again after // we enable the main window. // - UnsafeNativeMethods.SendMessage(new HandleRef(owner, handle), NativeMethods.WM_SETFOCUS, 0, 0); + UnsafeNativeMethods.SendMessage(new HandleRef(owner, handle), Interop.WindowMessages.WM_SETFOCUS, 0, 0); return result; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MessageDecoder.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MessageDecoder.cs index 436123ed542..7ea19c3f8cc 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MessageDecoder.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MessageDecoder.cs @@ -3,371 +3,870 @@ // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Runtime.Serialization.Formatters; - using System.Text; - using System.Runtime.Remoting; - using System.Diagnostics; - - using System; - using System.Windows.Forms; - - - /// - /// - /// Decodes Windows messages. This is in a separate class from Message - /// so we can avoid loading it in the 99% case where we don't need it. - /// - internal static class MessageDecoder { - - /// - /// - /// Returns the symbolic name of the msg value, or null if it - /// isn't one of the existing constants. - /// - private static string MsgToString(int msg) { +namespace System.Windows.Forms +{ + /// + /// Decodes Windows messages. This is in a separate class from Message so we can avoid + /// loading it in the 99% case where we don't need it. + /// + internal static class MessageDecoder + { + /// + /// Returns the symbolic name of the msg value, or null if it isn't one of the + /// existing constants. + /// + private static string MsgToString(int msg) + { string text; - switch (msg) { - case NativeMethods.WM_NULL: text = "WM_NULL"; break; - case NativeMethods.WM_CREATE: text = "WM_CREATE"; break; - case NativeMethods.WM_DESTROY: text = "WM_DESTROY"; break; - case NativeMethods.WM_MOVE: text = "WM_MOVE"; break; - case NativeMethods.WM_SIZE: text = "WM_SIZE"; break; - case NativeMethods.WM_ACTIVATE: text = "WM_ACTIVATE"; break; - //case NativeMethods.WA_INACTIVE: text = "WA_INACTIVE"; break; - //case NativeMethods.WA_ACTIVE: text = "WA_ACTIVE"; break; - //case NativeMethods.WA_CLICKACTIVE: text = "WA_CLICKACTIVE"; break; - case NativeMethods.WM_SETFOCUS: text = "WM_SETFOCUS"; break; - case NativeMethods.WM_KILLFOCUS: text = "WM_KILLFOCUS"; break; - case NativeMethods.WM_ENABLE: text = "WM_ENABLE"; break; - case NativeMethods.WM_SETREDRAW: text = "WM_SETREDRAW"; break; - case NativeMethods.WM_SETTEXT: text = "WM_SETTEXT"; break; - case NativeMethods.WM_GETTEXT: text = "WM_GETTEXT"; break; - case NativeMethods.WM_GETTEXTLENGTH: text = "WM_GETTEXTLENGTH"; break; - case NativeMethods.WM_PAINT: text = "WM_PAINT"; break; - case NativeMethods.WM_CLOSE: text = "WM_CLOSE"; break; - case NativeMethods.WM_QUERYENDSESSION: text = "WM_QUERYENDSESSION"; break; - case NativeMethods.WM_QUIT: text = "WM_QUIT"; break; - case NativeMethods.WM_QUERYOPEN: text = "WM_QUERYOPEN"; break; - case NativeMethods.WM_ERASEBKGND: text = "WM_ERASEBKGND"; break; - case NativeMethods.WM_SYSCOLORCHANGE: text = "WM_SYSCOLORCHANGE"; break; - case NativeMethods.WM_ENDSESSION: text = "WM_ENDSESSION"; break; - case NativeMethods.WM_SHOWWINDOW: text = "WM_SHOWWINDOW"; break; - case NativeMethods.WM_WININICHANGE: text = "WM_WININICHANGE"; break; - //case NativeMethods.WM_SETTINGCHANGE: text = "WM_SETTINGCHANGE"; break; - case NativeMethods.WM_DEVMODECHANGE: text = "WM_DEVMODECHANGE"; break; - case NativeMethods.WM_ACTIVATEAPP: text = "WM_ACTIVATEAPP"; break; - case NativeMethods.WM_FONTCHANGE: text = "WM_FONTCHANGE"; break; - case NativeMethods.WM_TIMECHANGE: text = "WM_TIMECHANGE"; break; - case NativeMethods.WM_CANCELMODE: text = "WM_CANCELMODE"; break; - case NativeMethods.WM_SETCURSOR: text = "WM_SETCURSOR"; break; - case NativeMethods.WM_MOUSEACTIVATE: text = "WM_MOUSEACTIVATE"; break; - case NativeMethods.WM_CHILDACTIVATE: text = "WM_CHILDACTIVATE"; break; - case NativeMethods.WM_QUEUESYNC: text = "WM_QUEUESYNC"; break; - case NativeMethods.WM_GETMINMAXINFO: text = "WM_GETMINMAXINFO"; break; - case NativeMethods.WM_PAINTICON: text = "WM_PAINTICON"; break; - case NativeMethods.WM_ICONERASEBKGND: text = "WM_ICONERASEBKGND"; break; - case NativeMethods.WM_NEXTDLGCTL: text = "WM_NEXTDLGCTL"; break; - case NativeMethods.WM_SPOOLERSTATUS: text = "WM_SPOOLERSTATUS"; break; - case NativeMethods.WM_DRAWITEM: text = "WM_DRAWITEM"; break; - case NativeMethods.WM_MEASUREITEM: text = "WM_MEASUREITEM"; break; - case NativeMethods.WM_DELETEITEM: text = "WM_DELETEITEM"; break; - case NativeMethods.WM_VKEYTOITEM: text = "WM_VKEYTOITEM"; break; - case NativeMethods.WM_CHARTOITEM: text = "WM_CHARTOITEM"; break; - case NativeMethods.WM_SETFONT: text = "WM_SETFONT"; break; - case NativeMethods.WM_GETFONT: text = "WM_GETFONT"; break; - case NativeMethods.WM_SETHOTKEY: text = "WM_SETHOTKEY"; break; - case NativeMethods.WM_GETHOTKEY: text = "WM_GETHOTKEY"; break; - case NativeMethods.WM_QUERYDRAGICON: text = "WM_QUERYDRAGICON"; break; - case NativeMethods.WM_COMPAREITEM: text = "WM_COMPAREITEM"; break; - case NativeMethods.WM_GETOBJECT: text = "WM_GETOBJECT"; break; - case NativeMethods.WM_COMPACTING: text = "WM_COMPACTING"; break; - case NativeMethods.WM_COMMNOTIFY: text = "WM_COMMNOTIFY"; break; - case NativeMethods.WM_WINDOWPOSCHANGING: text = "WM_WINDOWPOSCHANGING"; break; - case NativeMethods.WM_WINDOWPOSCHANGED: text = "WM_WINDOWPOSCHANGED"; break; - case NativeMethods.WM_POWER: text = "WM_POWER"; break; - case NativeMethods.WM_COPYDATA: text = "WM_COPYDATA"; break; - case NativeMethods.WM_CANCELJOURNAL: text = "WM_CANCELJOURNAL"; break; - case NativeMethods.WM_NOTIFY: text = "WM_NOTIFY"; break; - case NativeMethods.WM_INPUTLANGCHANGEREQUEST: text = "WM_INPUTLANGCHANGEREQUEST"; break; - case NativeMethods.WM_INPUTLANGCHANGE: text = "WM_INPUTLANGCHANGE"; break; - case NativeMethods.WM_TCARD: text = "WM_TCARD"; break; - case NativeMethods.WM_HELP: text = "WM_HELP"; break; - case NativeMethods.WM_USERCHANGED: text = "WM_USERCHANGED"; break; - case NativeMethods.WM_NOTIFYFORMAT: text = "WM_NOTIFYFORMAT"; break; - case NativeMethods.WM_CONTEXTMENU: text = "WM_CONTEXTMENU"; break; - case NativeMethods.WM_STYLECHANGING: text = "WM_STYLECHANGING"; break; - case NativeMethods.WM_STYLECHANGED: text = "WM_STYLECHANGED"; break; - case NativeMethods.WM_DISPLAYCHANGE: text = "WM_DISPLAYCHANGE"; break; - case NativeMethods.WM_GETICON: text = "WM_GETICON"; break; - case NativeMethods.WM_SETICON: text = "WM_SETICON"; break; - case NativeMethods.WM_NCCREATE: text = "WM_NCCREATE"; break; - case NativeMethods.WM_NCDESTROY: text = "WM_NCDESTROY"; break; - case NativeMethods.WM_NCCALCSIZE: text = "WM_NCCALCSIZE"; break; - case NativeMethods.WM_NCHITTEST: text = "WM_NCHITTEST"; break; - case NativeMethods.WM_NCPAINT: text = "WM_NCPAINT"; break; - case NativeMethods.WM_NCACTIVATE: text = "WM_NCACTIVATE"; break; - case NativeMethods.WM_GETDLGCODE: text = "WM_GETDLGCODE"; break; - case NativeMethods.WM_NCMOUSEMOVE: text = "WM_NCMOUSEMOVE"; break; - case NativeMethods.WM_NCLBUTTONDOWN: text = "WM_NCLBUTTONDOWN"; break; - case NativeMethods.WM_NCLBUTTONUP: text = "WM_NCLBUTTONUP"; break; - case NativeMethods.WM_NCLBUTTONDBLCLK: text = "WM_NCLBUTTONDBLCLK"; break; - case NativeMethods.WM_NCRBUTTONDOWN: text = "WM_NCRBUTTONDOWN"; break; - case NativeMethods.WM_NCRBUTTONUP: text = "WM_NCRBUTTONUP"; break; - case NativeMethods.WM_NCRBUTTONDBLCLK: text = "WM_NCRBUTTONDBLCLK"; break; - case NativeMethods.WM_NCMBUTTONDOWN: text = "WM_NCMBUTTONDOWN"; break; - case NativeMethods.WM_NCMBUTTONUP: text = "WM_NCMBUTTONUP"; break; - case NativeMethods.WM_NCMBUTTONDBLCLK: text = "WM_NCMBUTTONDBLCLK"; break; - //case NativeMethods.WM_KEYFIRST: text = "WM_KEYFIRST"; break; - case NativeMethods.WM_KEYDOWN: text = "WM_KEYDOWN"; break; - case NativeMethods.WM_KEYUP: text = "WM_KEYUP"; break; - case NativeMethods.WM_CHAR: text = "WM_CHAR"; break; - case NativeMethods.WM_DEADCHAR: text = "WM_DEADCHAR"; break; - case NativeMethods.WM_SYSKEYDOWN: text = "WM_SYSKEYDOWN"; break; - case NativeMethods.WM_SYSKEYUP: text = "WM_SYSKEYUP"; break; - case NativeMethods.WM_SYSCHAR: text = "WM_SYSCHAR"; break; - case NativeMethods.WM_SYSDEADCHAR: text = "WM_SYSDEADCHAR"; break; - case NativeMethods.WM_KEYLAST: text = "WM_KEYLAST"; break; - case NativeMethods.WM_IME_STARTCOMPOSITION: text = "WM_IME_STARTCOMPOSITION"; break; - case NativeMethods.WM_IME_ENDCOMPOSITION: text = "WM_IME_ENDCOMPOSITION"; break; - case NativeMethods.WM_IME_COMPOSITION: text = "WM_IME_COMPOSITION"; break; - //case NativeMethods.WM_IME_KEYLAST: text = "WM_IME_KEYLAST"; break; - case NativeMethods.WM_INITDIALOG: text = "WM_INITDIALOG"; break; - case NativeMethods.WM_COMMAND: text = "WM_COMMAND"; break; - case NativeMethods.WM_SYSCOMMAND: text = "WM_SYSCOMMAND"; break; - case NativeMethods.WM_TIMER: text = "WM_TIMER"; break; - case NativeMethods.WM_HSCROLL: text = "WM_HSCROLL"; break; - case NativeMethods.WM_VSCROLL: text = "WM_VSCROLL"; break; - case NativeMethods.WM_INITMENU: text = "WM_INITMENU"; break; - case NativeMethods.WM_INITMENUPOPUP: text = "WM_INITMENUPOPUP"; break; - case NativeMethods.WM_MENUSELECT: text = "WM_MENUSELECT"; break; - case NativeMethods.WM_MENUCHAR: text = "WM_MENUCHAR"; break; - case NativeMethods.WM_ENTERIDLE: text = "WM_ENTERIDLE"; break; - case NativeMethods.WM_CTLCOLORMSGBOX: text = "WM_CTLCOLORMSGBOX"; break; - case NativeMethods.WM_CTLCOLOREDIT: text = "WM_CTLCOLOREDIT"; break; - case NativeMethods.WM_CTLCOLORLISTBOX: text = "WM_CTLCOLORLISTBOX"; break; - case NativeMethods.WM_CTLCOLORBTN: text = "WM_CTLCOLORBTN"; break; - case NativeMethods.WM_CTLCOLORDLG: text = "WM_CTLCOLORDLG"; break; - case NativeMethods.WM_CTLCOLORSCROLLBAR: text = "WM_CTLCOLORSCROLLBAR"; break; - case NativeMethods.WM_CTLCOLORSTATIC: text = "WM_CTLCOLORSTATIC"; break; - //case NativeMethods.WM_MOUSEFIRST: text = "WM_MOUSEFIRST"; break; - case NativeMethods.WM_MOUSEMOVE: text = "WM_MOUSEMOVE"; break; - case NativeMethods.WM_LBUTTONDOWN: text = "WM_LBUTTONDOWN"; break; - case NativeMethods.WM_LBUTTONUP: text = "WM_LBUTTONUP"; break; - case NativeMethods.WM_LBUTTONDBLCLK: text = "WM_LBUTTONDBLCLK"; break; - case NativeMethods.WM_RBUTTONDOWN: text = "WM_RBUTTONDOWN"; break; - case NativeMethods.WM_RBUTTONUP: text = "WM_RBUTTONUP"; break; - case NativeMethods.WM_RBUTTONDBLCLK: text = "WM_RBUTTONDBLCLK"; break; - case NativeMethods.WM_MBUTTONDOWN: text = "WM_MBUTTONDOWN"; break; - case NativeMethods.WM_MBUTTONUP: text = "WM_MBUTTONUP"; break; - case NativeMethods.WM_MBUTTONDBLCLK: text = "WM_MBUTTONDBLCLK"; break; - case NativeMethods.WM_MOUSEWHEEL: text = "WM_MOUSEWHEEL"; break; - //case NativeMethods.WM_MOUSELAST: text = "WM_MOUSELAST"; break; - case NativeMethods.WM_PARENTNOTIFY: text = "WM_PARENTNOTIFY"; break; - case NativeMethods.WM_ENTERMENULOOP: text = "WM_ENTERMENULOOP"; break; - case NativeMethods.WM_EXITMENULOOP: text = "WM_EXITMENULOOP"; break; - case NativeMethods.WM_NEXTMENU: text = "WM_NEXTMENU"; break; - case NativeMethods.WM_SIZING: text = "WM_SIZING"; break; - case NativeMethods.WM_CAPTURECHANGED: text = "WM_CAPTURECHANGED"; break; - case NativeMethods.WM_MOVING: text = "WM_MOVING"; break; - case NativeMethods.WM_POWERBROADCAST: text = "WM_POWERBROADCAST"; break; - case NativeMethods.WM_DEVICECHANGE: text = "WM_DEVICECHANGE"; break; - case NativeMethods.WM_IME_SETCONTEXT: text = "WM_IME_SETCONTEXT"; break; - case NativeMethods.WM_IME_NOTIFY: text = "WM_IME_NOTIFY"; break; - case NativeMethods.WM_IME_CONTROL: text = "WM_IME_CONTROL"; break; - case NativeMethods.WM_IME_COMPOSITIONFULL: text = "WM_IME_COMPOSITIONFULL"; break; - case NativeMethods.WM_IME_SELECT: text = "WM_IME_SELECT"; break; - case NativeMethods.WM_IME_CHAR: text = "WM_IME_CHAR"; break; - case NativeMethods.WM_IME_KEYDOWN: text = "WM_IME_KEYDOWN"; break; - case NativeMethods.WM_IME_KEYUP: text = "WM_IME_KEYUP"; break; - case NativeMethods.WM_MDICREATE: text = "WM_MDICREATE"; break; - case NativeMethods.WM_MDIDESTROY: text = "WM_MDIDESTROY"; break; - case NativeMethods.WM_MDIACTIVATE: text = "WM_MDIACTIVATE"; break; - case NativeMethods.WM_MDIRESTORE: text = "WM_MDIRESTORE"; break; - case NativeMethods.WM_MDINEXT: text = "WM_MDINEXT"; break; - case NativeMethods.WM_MDIMAXIMIZE: text = "WM_MDIMAXIMIZE"; break; - case NativeMethods.WM_MDITILE: text = "WM_MDITILE"; break; - case NativeMethods.WM_MDICASCADE: text = "WM_MDICASCADE"; break; - case NativeMethods.WM_MDIICONARRANGE: text = "WM_MDIICONARRANGE"; break; - case NativeMethods.WM_MDIGETACTIVE: text = "WM_MDIGETACTIVE"; break; - case NativeMethods.WM_MDISETMENU: text = "WM_MDISETMENU"; break; - case NativeMethods.WM_ENTERSIZEMOVE: text = "WM_ENTERSIZEMOVE"; break; - case NativeMethods.WM_EXITSIZEMOVE: text = "WM_EXITSIZEMOVE"; break; - case NativeMethods.WM_DROPFILES: text = "WM_DROPFILES"; break; - case NativeMethods.WM_MDIREFRESHMENU: text = "WM_MDIREFRESHMENU"; break; - case NativeMethods.WM_MOUSEHOVER: text = "WM_MOUSEHOVER"; break; - case NativeMethods.WM_MOUSELEAVE: text = "WM_MOUSELEAVE"; break; - case NativeMethods.WM_CUT: text = "WM_CUT"; break; - case NativeMethods.WM_COPY: text = "WM_COPY"; break; - case NativeMethods.WM_PASTE: text = "WM_PASTE"; break; - case NativeMethods.WM_CLEAR: text = "WM_CLEAR"; break; - case NativeMethods.WM_UNDO: text = "WM_UNDO"; break; - case NativeMethods.WM_RENDERFORMAT: text = "WM_RENDERFORMAT"; break; - case NativeMethods.WM_RENDERALLFORMATS: text = "WM_RENDERALLFORMATS"; break; - case NativeMethods.WM_DESTROYCLIPBOARD: text = "WM_DESTROYCLIPBOARD"; break; - case NativeMethods.WM_DRAWCLIPBOARD: text = "WM_DRAWCLIPBOARD"; break; - case NativeMethods.WM_PAINTCLIPBOARD: text = "WM_PAINTCLIPBOARD"; break; - case NativeMethods.WM_VSCROLLCLIPBOARD: text = "WM_VSCROLLCLIPBOARD"; break; - case NativeMethods.WM_SIZECLIPBOARD: text = "WM_SIZECLIPBOARD"; break; - case NativeMethods.WM_ASKCBFORMATNAME: text = "WM_ASKCBFORMATNAME"; break; - case NativeMethods.WM_CHANGECBCHAIN: text = "WM_CHANGECBCHAIN"; break; - case NativeMethods.WM_HSCROLLCLIPBOARD: text = "WM_HSCROLLCLIPBOARD"; break; - case NativeMethods.WM_QUERYNEWPALETTE: text = "WM_QUERYNEWPALETTE"; break; - case NativeMethods.WM_PALETTEISCHANGING: text = "WM_PALETTEISCHANGING"; break; - case NativeMethods.WM_PALETTECHANGED: text = "WM_PALETTECHANGED"; break; - case NativeMethods.WM_HOTKEY: text = "WM_HOTKEY"; break; - case NativeMethods.WM_PRINT: text = "WM_PRINT"; break; - case NativeMethods.WM_PRINTCLIENT: text = "WM_PRINTCLIENT"; break; - case NativeMethods.WM_HANDHELDFIRST: text = "WM_HANDHELDFIRST"; break; - case NativeMethods.WM_HANDHELDLAST: text = "WM_HANDHELDLAST"; break; - case NativeMethods.WM_AFXFIRST: text = "WM_AFXFIRST"; break; - case NativeMethods.WM_AFXLAST: text = "WM_AFXLAST"; break; - case NativeMethods.WM_PENWINFIRST: text = "WM_PENWINFIRST"; break; - case NativeMethods.WM_PENWINLAST: text = "WM_PENWINLAST"; break; - case NativeMethods.WM_APP: text = "WM_APP"; break; - case NativeMethods.WM_USER: text = "WM_USER"; break; - - case NativeMethods.WM_CTLCOLOR: text = "WM_CTLCOLOR"; break; - - // RichEdit messages - //case RichTextBoxConstants.WM_CONTEXTMENU: text = "WM_CONTEXTMENU"; break; - - //case RichTextBoxConstants.WM_PRINTCLIENT: text = "WM_PRINTCLIENT"; break; - - case RichTextBoxConstants.EM_GETLIMITTEXT: text = "EM_GETLIMITTEXT"; break; - - case RichTextBoxConstants.EM_POSFROMCHAR: text = "EM_POSFROMCHAR"; break; - case RichTextBoxConstants.EM_CHARFROMPOS: text = "EM_CHARFROMPOS"; break; + switch (msg) + { + case Interop.WindowMessages.WM_NULL: + text = "WM_NULL"; + break; + case Interop.WindowMessages.WM_CREATE: + text = "WM_CREATE"; + break; + case Interop.WindowMessages.WM_DESTROY: + text = "WM_DESTROY"; + break; + case Interop.WindowMessages.WM_MOVE: + text = "WM_MOVE"; + break; + case Interop.WindowMessages.WM_SIZE: + text = "WM_SIZE"; + break; + case Interop.WindowMessages.WM_ACTIVATE: + text = "WM_ACTIVATE"; + break; + case Interop.WindowMessages.WM_SETFOCUS: + text = "WM_SETFOCUS"; + break; + case Interop.WindowMessages.WM_KILLFOCUS: + text = "WM_KILLFOCUS"; + break; + case Interop.WindowMessages.WM_ENABLE: + text = "WM_ENABLE"; + break; + case Interop.WindowMessages.WM_SETREDRAW: + text = "WM_SETREDRAW"; + break; + case Interop.WindowMessages.WM_SETTEXT: + text = "WM_SETTEXT"; + break; + case Interop.WindowMessages.WM_GETTEXT: + text = "WM_GETTEXT"; + break; + case Interop.WindowMessages.WM_GETTEXTLENGTH: + text = "WM_GETTEXTLENGTH"; + break; + case Interop.WindowMessages.WM_PAINT: + text = "WM_PAINT"; + break; + case Interop.WindowMessages.WM_CLOSE: + text = "WM_CLOSE"; + break; + case Interop.WindowMessages.WM_QUERYENDSESSION: + text = "WM_QUERYENDSESSION"; + break; + case Interop.WindowMessages.WM_QUIT: + text = "WM_QUIT"; + break; + case Interop.WindowMessages.WM_QUERYOPEN: + text = "WM_QUERYOPEN"; + break; + case Interop.WindowMessages.WM_ERASEBKGND: + text = "WM_ERASEBKGND"; + break; + case Interop.WindowMessages.WM_SYSCOLORCHANGE: + text = "WM_SYSCOLORCHANGE"; + break; + case Interop.WindowMessages.WM_ENDSESSION: + text = "WM_ENDSESSION"; + break; + case Interop.WindowMessages.WM_SHOWWINDOW: + text = "WM_SHOWWINDOW"; + break; + case Interop.WindowMessages.WM_WININICHANGE: + text = "WM_WININICHANGE"; + break; + case Interop.WindowMessages.WM_DEVMODECHANGE: + text = "WM_DEVMODECHANGE"; + break; + case Interop.WindowMessages.WM_ACTIVATEAPP: + text = "WM_ACTIVATEAPP"; + break; + case Interop.WindowMessages.WM_FONTCHANGE: + text = "WM_FONTCHANGE"; + break; + case Interop.WindowMessages.WM_TIMECHANGE: + text = "WM_TIMECHANGE"; + break; + case Interop.WindowMessages.WM_CANCELMODE: + text = "WM_CANCELMODE"; + break; + case Interop.WindowMessages.WM_SETCURSOR: + text = "WM_SETCURSOR"; + break; + case Interop.WindowMessages.WM_MOUSEACTIVATE: + text = "WM_MOUSEACTIVATE"; + break; + case Interop.WindowMessages.WM_CHILDACTIVATE: + text = "WM_CHILDACTIVATE"; + break; + case Interop.WindowMessages.WM_QUEUESYNC: + text = "WM_QUEUESYNC"; + break; + case Interop.WindowMessages.WM_GETMINMAXINFO: + text = "WM_GETMINMAXINFO"; + break; + case Interop.WindowMessages.WM_PAINTICON: + text = "WM_PAINTICON"; + break; + case Interop.WindowMessages.WM_ICONERASEBKGND: + text = "WM_ICONERASEBKGND"; + break; + case Interop.WindowMessages.WM_NEXTDLGCTL: + text = "WM_NEXTDLGCTL"; + break; + case Interop.WindowMessages.WM_SPOOLERSTATUS: + text = "WM_SPOOLERSTATUS"; + break; + case Interop.WindowMessages.WM_DRAWITEM: + text = "WM_DRAWITEM"; + break; + case Interop.WindowMessages.WM_MEASUREITEM: + text = "WM_MEASUREITEM"; + break; + case Interop.WindowMessages.WM_DELETEITEM: + text = "WM_DELETEITEM"; + break; + case Interop.WindowMessages.WM_VKEYTOITEM: + text = "WM_VKEYTOITEM"; + break; + case Interop.WindowMessages.WM_CHARTOITEM: + text = "WM_CHARTOITEM"; + break; + case Interop.WindowMessages.WM_SETFONT: + text = "WM_SETFONT"; + break; + case Interop.WindowMessages.WM_GETFONT: + text = "WM_GETFONT"; + break; + case Interop.WindowMessages.WM_SETHOTKEY: + text = "WM_SETHOTKEY"; + break; + case Interop.WindowMessages.WM_GETHOTKEY: + text = "WM_GETHOTKEY"; + break; + case Interop.WindowMessages.WM_QUERYDRAGICON: + text = "WM_QUERYDRAGICON"; + break; + case Interop.WindowMessages.WM_COMPAREITEM: + text = "WM_COMPAREITEM"; + break; + case Interop.WindowMessages.WM_GETOBJECT: + text = "WM_GETOBJECT"; + break; + case Interop.WindowMessages.WM_COMPACTING: + text = "WM_COMPACTING"; + break; + case Interop.WindowMessages.WM_COMMNOTIFY: + text = "WM_COMMNOTIFY"; + break; + case Interop.WindowMessages.WM_WINDOWPOSCHANGING: + text = "WM_WINDOWPOSCHANGING"; + break; + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: + text = "WM_WINDOWPOSCHANGED"; + break; + case Interop.WindowMessages.WM_POWER: + text = "WM_POWER"; + break; + case Interop.WindowMessages.WM_COPYDATA: + text = "WM_COPYDATA"; + break; + case Interop.WindowMessages.WM_CANCELJOURNAL: + text = "WM_CANCELJOURNAL"; + break; + case Interop.WindowMessages.WM_NOTIFY: + text = "WM_NOTIFY"; + break; + case Interop.WindowMessages.WM_INPUTLANGCHANGEREQUEST: + text = "WM_INPUTLANGCHANGEREQUEST"; + break; + case Interop.WindowMessages.WM_INPUTLANGCHANGE: + text = "WM_INPUTLANGCHANGE"; + break; + case Interop.WindowMessages.WM_TCARD: + text = "WM_TCARD"; + break; + case Interop.WindowMessages.WM_HELP: + text = "WM_HELP"; + break; + case Interop.WindowMessages.WM_USERCHANGED: + text = "WM_USERCHANGED"; + break; + case Interop.WindowMessages.WM_NOTIFYFORMAT: + text = "WM_NOTIFYFORMAT"; + break; + case Interop.WindowMessages.WM_CONTEXTMENU: + text = "WM_CONTEXTMENU"; + break; + case Interop.WindowMessages.WM_STYLECHANGING: + text = "WM_STYLECHANGING"; + break; + case Interop.WindowMessages.WM_STYLECHANGED: + text = "WM_STYLECHANGED"; + break; + case Interop.WindowMessages.WM_DISPLAYCHANGE: + text = "WM_DISPLAYCHANGE"; + break; + case Interop.WindowMessages.WM_GETICON: + text = "WM_GETICON"; + break; + case Interop.WindowMessages.WM_SETICON: + text = "WM_SETICON"; + break; + case Interop.WindowMessages.WM_NCCREATE: + text = "WM_NCCREATE"; + break; + case Interop.WindowMessages.WM_NCDESTROY: + text = "WM_NCDESTROY"; + break; + case Interop.WindowMessages.WM_NCCALCSIZE: + text = "WM_NCCALCSIZE"; + break; + case Interop.WindowMessages.WM_NCHITTEST: + text = "WM_NCHITTEST"; + break; + case Interop.WindowMessages.WM_NCPAINT: + text = "WM_NCPAINT"; + break; + case Interop.WindowMessages.WM_NCACTIVATE: + text = "WM_NCACTIVATE"; + break; + case Interop.WindowMessages.WM_GETDLGCODE: + text = "WM_GETDLGCODE"; + break; + case Interop.WindowMessages.WM_NCMOUSEMOVE: + text = "WM_NCMOUSEMOVE"; + break; + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + text = "WM_NCLBUTTONDOWN"; + break; + case Interop.WindowMessages.WM_NCLBUTTONUP: + text = "WM_NCLBUTTONUP"; + break; + case Interop.WindowMessages.WM_NCLBUTTONDBLCLK: + text = "WM_NCLBUTTONDBLCLK"; + break; + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + text = "WM_NCRBUTTONDOWN"; + break; + case Interop.WindowMessages.WM_NCRBUTTONUP: + text = "WM_NCRBUTTONUP"; + break; + case Interop.WindowMessages.WM_NCRBUTTONDBLCLK: + text = "WM_NCRBUTTONDBLCLK"; + break; + case Interop.WindowMessages.WM_NCMBUTTONDOWN: + text = "WM_NCMBUTTONDOWN"; + break; + case Interop.WindowMessages.WM_NCMBUTTONUP: + text = "WM_NCMBUTTONUP"; + break; + case Interop.WindowMessages.WM_NCMBUTTONDBLCLK: + text = "WM_NCMBUTTONDBLCLK"; + break; + case Interop.WindowMessages.WM_KEYDOWN: + text = "WM_KEYDOWN"; + break; + case Interop.WindowMessages.WM_KEYUP: + text = "WM_KEYUP"; + break; + case Interop.WindowMessages.WM_CHAR: + text = "WM_CHAR"; + break; + case Interop.WindowMessages.WM_DEADCHAR: + text = "WM_DEADCHAR"; + break; + case Interop.WindowMessages.WM_SYSKEYDOWN: + text = "WM_SYSKEYDOWN"; + break; + case Interop.WindowMessages.WM_SYSKEYUP: + text = "WM_SYSKEYUP"; + break; + case Interop.WindowMessages.WM_SYSCHAR: + text = "WM_SYSCHAR"; + break; + case Interop.WindowMessages.WM_SYSDEADCHAR: + text = "WM_SYSDEADCHAR"; + break; + case Interop.WindowMessages.WM_KEYLAST: + text = "WM_KEYLAST"; + break; + case Interop.WindowMessages.WM_IME_STARTCOMPOSITION: + text = "WM_IME_STARTCOMPOSITION"; + break; + case Interop.WindowMessages.WM_IME_ENDCOMPOSITION: + text = "WM_IME_ENDCOMPOSITION"; + break; + case Interop.WindowMessages.WM_IME_COMPOSITION: + text = "WM_IME_COMPOSITION"; + break; + case Interop.WindowMessages.WM_INITDIALOG: + text = "WM_INITDIALOG"; + break; + case Interop.WindowMessages.WM_COMMAND: + text = "WM_COMMAND"; + break; + case Interop.WindowMessages.WM_SYSCOMMAND: + text = "WM_SYSCOMMAND"; + break; + case Interop.WindowMessages.WM_TIMER: + text = "WM_TIMER"; + break; + case Interop.WindowMessages.WM_HSCROLL: + text = "WM_HSCROLL"; + break; + case Interop.WindowMessages.WM_VSCROLL: + text = "WM_VSCROLL"; + break; + case Interop.WindowMessages.WM_INITMENU: + text = "WM_INITMENU"; + break; + case Interop.WindowMessages.WM_INITMENUPOPUP: + text = "WM_INITMENUPOPUP"; + break; + case Interop.WindowMessages.WM_MENUSELECT: + text = "WM_MENUSELECT"; + break; + case Interop.WindowMessages.WM_MENUCHAR: + text = "WM_MENUCHAR"; + break; + case Interop.WindowMessages.WM_ENTERIDLE: + text = "WM_ENTERIDLE"; + break; + case Interop.WindowMessages.WM_CTLCOLORMSGBOX: + text = "WM_CTLCOLORMSGBOX"; + break; + case Interop.WindowMessages.WM_CTLCOLOREDIT: + text = "WM_CTLCOLOREDIT"; + break; + case Interop.WindowMessages.WM_CTLCOLORLISTBOX: + text = "WM_CTLCOLORLISTBOX"; + break; + case Interop.WindowMessages.WM_CTLCOLORBTN: + text = "WM_CTLCOLORBTN"; + break; + case Interop.WindowMessages.WM_CTLCOLORDLG: + text = "WM_CTLCOLORDLG"; + break; + case Interop.WindowMessages.WM_CTLCOLORSCROLLBAR: + text = "WM_CTLCOLORSCROLLBAR"; + break; + case Interop.WindowMessages.WM_CTLCOLORSTATIC: + text = "WM_CTLCOLORSTATIC"; + break; + case Interop.WindowMessages.WM_MOUSEMOVE: + text = "WM_MOUSEMOVE"; + break; + case Interop.WindowMessages.WM_LBUTTONDOWN: + text = "WM_LBUTTONDOWN"; + break; + case Interop.WindowMessages.WM_LBUTTONUP: + text = "WM_LBUTTONUP"; + break; + case Interop.WindowMessages.WM_LBUTTONDBLCLK: + text = "WM_LBUTTONDBLCLK"; + break; + case Interop.WindowMessages.WM_RBUTTONDOWN: + text = "WM_RBUTTONDOWN"; + break; + case Interop.WindowMessages.WM_RBUTTONUP: + text = "WM_RBUTTONUP"; + break; + case Interop.WindowMessages.WM_RBUTTONDBLCLK: + text = "WM_RBUTTONDBLCLK"; + break; + case Interop.WindowMessages.WM_MBUTTONDOWN: + text = "WM_MBUTTONDOWN"; + break; + case Interop.WindowMessages.WM_MBUTTONUP: + text = "WM_MBUTTONUP"; + break; + case Interop.WindowMessages.WM_MBUTTONDBLCLK: + text = "WM_MBUTTONDBLCLK"; + break; + case Interop.WindowMessages.WM_MOUSEWHEEL: + text = "WM_MOUSEWHEEL"; + break; + case Interop.WindowMessages.WM_PARENTNOTIFY: + text = "WM_PARENTNOTIFY"; + break; + case Interop.WindowMessages.WM_ENTERMENULOOP: + text = "WM_ENTERMENULOOP"; + break; + case Interop.WindowMessages.WM_EXITMENULOOP: + text = "WM_EXITMENULOOP"; + break; + case Interop.WindowMessages.WM_NEXTMENU: + text = "WM_NEXTMENU"; + break; + case Interop.WindowMessages.WM_SIZING: + text = "WM_SIZING"; + break; + case Interop.WindowMessages.WM_CAPTURECHANGED: + text = "WM_CAPTURECHANGED"; + break; + case Interop.WindowMessages.WM_MOVING: + text = "WM_MOVING"; + break; + case Interop.WindowMessages.WM_POWERBROADCAST: + text = "WM_POWERBROADCAST"; + break; + case Interop.WindowMessages.WM_DEVICECHANGE: + text = "WM_DEVICECHANGE"; + break; + case Interop.WindowMessages.WM_IME_SETCONTEXT: + text = "WM_IME_SETCONTEXT"; + break; + case Interop.WindowMessages.WM_IME_NOTIFY: + text = "WM_IME_NOTIFY"; + break; + case Interop.WindowMessages.WM_IME_CONTROL: + text = "WM_IME_CONTROL"; + break; + case Interop.WindowMessages.WM_IME_COMPOSITIONFULL: + text = "WM_IME_COMPOSITIONFULL"; + break; + case Interop.WindowMessages.WM_IME_SELECT: + text = "WM_IME_SELECT"; + break; + case Interop.WindowMessages.WM_IME_CHAR: + text = "WM_IME_CHAR"; + break; + case Interop.WindowMessages.WM_IME_KEYDOWN: + text = "WM_IME_KEYDOWN"; + break; + case Interop.WindowMessages.WM_IME_KEYUP: + text = "WM_IME_KEYUP"; + break; + case Interop.WindowMessages.WM_MDICREATE: + text = "WM_MDICREATE"; + break; + case Interop.WindowMessages.WM_MDIDESTROY: + text = "WM_MDIDESTROY"; + break; + case Interop.WindowMessages.WM_MDIACTIVATE: + text = "WM_MDIACTIVATE"; + break; + case Interop.WindowMessages.WM_MDIRESTORE: + text = "WM_MDIRESTORE"; + break; + case Interop.WindowMessages.WM_MDINEXT: + text = "WM_MDINEXT"; + break; + case Interop.WindowMessages.WM_MDIMAXIMIZE: + text = "WM_MDIMAXIMIZE"; + break; + case Interop.WindowMessages.WM_MDITILE: + text = "WM_MDITILE"; + break; + case Interop.WindowMessages.WM_MDICASCADE: + text = "WM_MDICASCADE"; + break; + case Interop.WindowMessages.WM_MDIICONARRANGE: + text = "WM_MDIICONARRANGE"; + break; + case Interop.WindowMessages.WM_MDIGETACTIVE: + text = "WM_MDIGETACTIVE"; + break; + case Interop.WindowMessages.WM_MDISETMENU: + text = "WM_MDISETMENU"; + break; + case Interop.WindowMessages.WM_ENTERSIZEMOVE: + text = "WM_ENTERSIZEMOVE"; + break; + case Interop.WindowMessages.WM_EXITSIZEMOVE: + text = "WM_EXITSIZEMOVE"; + break; + case Interop.WindowMessages.WM_DROPFILES: + text = "WM_DROPFILES"; + break; + case Interop.WindowMessages.WM_MDIREFRESHMENU: + text = "WM_MDIREFRESHMENU"; + break; + case Interop.WindowMessages.WM_MOUSEHOVER: + text = "WM_MOUSEHOVER"; + break; + case Interop.WindowMessages.WM_MOUSELEAVE: + text = "WM_MOUSELEAVE"; + break; + case Interop.WindowMessages.WM_CUT: + text = "WM_CUT"; + break; + case Interop.WindowMessages.WM_COPY: + text = "WM_COPY"; + break; + case Interop.WindowMessages.WM_PASTE: + text = "WM_PASTE"; + break; + case Interop.WindowMessages.WM_CLEAR: + text = "WM_CLEAR"; + break; + case Interop.WindowMessages.WM_UNDO: + text = "WM_UNDO"; + break; + case Interop.WindowMessages.WM_RENDERFORMAT: + text = "WM_RENDERFORMAT"; + break; + case Interop.WindowMessages.WM_RENDERALLFORMATS: + text = "WM_RENDERALLFORMATS"; + break; + case Interop.WindowMessages.WM_DESTROYCLIPBOARD: + text = "WM_DESTROYCLIPBOARD"; + break; + case Interop.WindowMessages.WM_DRAWCLIPBOARD: + text = "WM_DRAWCLIPBOARD"; + break; + case Interop.WindowMessages.WM_PAINTCLIPBOARD: + text = "WM_PAINTCLIPBOARD"; + break; + case Interop.WindowMessages.WM_VSCROLLCLIPBOARD: + text = "WM_VSCROLLCLIPBOARD"; + break; + case Interop.WindowMessages.WM_SIZECLIPBOARD: + text = "WM_SIZECLIPBOARD"; + break; + case Interop.WindowMessages.WM_ASKCBFORMATNAME: + text = "WM_ASKCBFORMATNAME"; + break; + case Interop.WindowMessages.WM_CHANGECBCHAIN: + text = "WM_CHANGECBCHAIN"; + break; + case Interop.WindowMessages.WM_HSCROLLCLIPBOARD: + text = "WM_HSCROLLCLIPBOARD"; + break; + case Interop.WindowMessages.WM_QUERYNEWPALETTE: + text = "WM_QUERYNEWPALETTE"; + break; + case Interop.WindowMessages.WM_PALETTEISCHANGING: + text = "WM_PALETTEISCHANGING"; + break; + case Interop.WindowMessages.WM_PALETTECHANGED: + text = "WM_PALETTECHANGED"; + break; + case Interop.WindowMessages.WM_HOTKEY: + text = "WM_HOTKEY"; + break; + case Interop.WindowMessages.WM_PRINT: + text = "WM_PRINT"; + break; + case Interop.WindowMessages.WM_PRINTCLIENT: + text = "WM_PRINTCLIENT"; + break; + case Interop.WindowMessages.WM_HANDHELDFIRST: + text = "WM_HANDHELDFIRST"; + break; + case Interop.WindowMessages.WM_HANDHELDLAST: + text = "WM_HANDHELDLAST"; + break; + case Interop.WindowMessages.WM_AFXFIRST: + text = "WM_AFXFIRST"; + break; + case Interop.WindowMessages.WM_AFXLAST: + text = "WM_AFXLAST"; + break; + case Interop.WindowMessages.WM_PENWINFIRST: + text = "WM_PENWINFIRST"; + break; + case Interop.WindowMessages.WM_PENWINLAST: + text = "WM_PENWINLAST"; + break; + case Interop.WindowMessages.WM_APP: + text = "WM_APP"; + break; + case Interop.WindowMessages.WM_USER: + text = "WM_USER"; + break; + case Interop.WindowMessages.WM_CTLCOLOR: + text = "WM_CTLCOLOR"; + break; - case RichTextBoxConstants.EM_SCROLLCARET: text = "EM_SCROLLCARET"; break; - case RichTextBoxConstants.EM_CANPASTE: text = "EM_CANPASTE"; break; - case RichTextBoxConstants.EM_DISPLAYBAND: text = "EM_DISPLAYBAND"; break; - case RichTextBoxConstants.EM_EXGETSEL: text = "EM_EXGETSEL"; break; - case RichTextBoxConstants.EM_EXLIMITTEXT: text = "EM_EXLIMITTEXT"; break; - case RichTextBoxConstants.EM_EXLINEFROMCHAR: text = "EM_EXLINEFROMCHAR"; break; - case RichTextBoxConstants.EM_EXSETSEL: text = "EM_EXSETSEL"; break; - case RichTextBoxConstants.EM_FINDTEXT: text = "EM_FINDTEXT"; break; - case RichTextBoxConstants.EM_FORMATRANGE: text = "EM_FORMATRANGE"; break; - case RichTextBoxConstants.EM_GETCHARFORMAT: text = "EM_GETCHARFORMAT"; break; - case RichTextBoxConstants.EM_GETEVENTMASK: text = "EM_GETEVENTMASK"; break; - case RichTextBoxConstants.EM_GETOLEINTERFACE: text = "EM_GETOLEINTERFACE"; break; - case RichTextBoxConstants.EM_GETPARAFORMAT: text = "EM_GETPARAFORMAT"; break; - case RichTextBoxConstants.EM_GETSELTEXT: text = "EM_GETSELTEXT"; break; - case RichTextBoxConstants.EM_HIDESELECTION: text = "EM_HIDESELECTION"; break; - case RichTextBoxConstants.EM_PASTESPECIAL: text = "EM_PASTESPECIAL"; break; - case RichTextBoxConstants.EM_REQUESTRESIZE: text = "EM_REQUESTRESIZE"; break; - case RichTextBoxConstants.EM_SELECTIONTYPE: text = "EM_SELECTIONTYPE"; break; - case RichTextBoxConstants.EM_SETBKGNDCOLOR: text = "EM_SETBKGNDCOLOR"; break; - case RichTextBoxConstants.EM_SETCHARFORMAT: text = "EM_SETCHARFORMAT"; break; - case RichTextBoxConstants.EM_SETEVENTMASK: text = "EM_SETEVENTMASK"; break; - case RichTextBoxConstants.EM_SETOLECALLBACK: text = "EM_SETOLECALLBACK"; break; - case RichTextBoxConstants.EM_SETPARAFORMAT: text = "EM_SETPARAFORMAT"; break; - case RichTextBoxConstants.EM_SETTARGETDEVICE: text = "EM_SETTARGETDEVICE"; break; - case RichTextBoxConstants.EM_STREAMIN: text = "EM_STREAMIN"; break; - case RichTextBoxConstants.EM_STREAMOUT: text = "EM_STREAMOUT"; break; - case RichTextBoxConstants.EM_GETTEXTRANGE: text = "EM_GETTEXTRANGE"; break; - case RichTextBoxConstants.EM_FINDWORDBREAK: text = "EM_FINDWORDBREAK"; break; - case RichTextBoxConstants.EM_SETOPTIONS: text = "EM_SETOPTIONS"; break; - case RichTextBoxConstants.EM_GETOPTIONS: text = "EM_GETOPTIONS"; break; - case RichTextBoxConstants.EM_FINDTEXTEX: text = "EM_FINDTEXTEX"; break; - case RichTextBoxConstants.EM_GETWORDBREAKPROCEX: text = "EM_GETWORDBREAKPROCEX"; break; - case RichTextBoxConstants.EM_SETWORDBREAKPROCEX: text = "EM_SETWORDBREAKPROCEX"; break; + // RichEdit messages + case Interop.EditMessages.EM_GETLIMITTEXT: + text = "EM_GETLIMITTEXT"; + break; + case Interop.EditMessages.EM_POSFROMCHAR: + text = "EM_POSFROMCHAR"; + break; + case Interop.EditMessages.EM_CHARFROMPOS: + text = "EM_CHARFROMPOS"; + break; + case Interop.EditMessages.EM_SCROLLCARET: + text = "EM_SCROLLCARET"; + break; + case Interop.EditMessages.EM_CANPASTE: + text = "EM_CANPASTE"; + break; + case Interop.EditMessages.EM_DISPLAYBAND: + text = "EM_DISPLAYBAND"; + break; + case Interop.EditMessages.EM_EXGETSEL: + text = "EM_EXGETSEL"; + break; + case Interop.EditMessages.EM_EXLIMITTEXT: + text = "EM_EXLIMITTEXT"; + break; + case Interop.EditMessages.EM_EXLINEFROMCHAR: + text = "EM_EXLINEFROMCHAR"; + break; + case Interop.EditMessages.EM_EXSETSEL: + text = "EM_EXSETSEL"; + break; + case Interop.EditMessages.EM_FINDTEXT: + text = "EM_FINDTEXT"; + break; + case Interop.EditMessages.EM_FORMATRANGE: + text = "EM_FORMATRANGE"; + break; + case Interop.EditMessages.EM_GETCHARFORMAT: + text = "EM_GETCHARFORMAT"; + break; + case Interop.EditMessages.EM_GETEVENTMASK: + text = "EM_GETEVENTMASK"; + break; + case Interop.EditMessages.EM_GETOLEINTERFACE: + text = "EM_GETOLEINTERFACE"; + break; + case Interop.EditMessages.EM_GETPARAFORMAT: + text = "EM_GETPARAFORMAT"; + break; + case Interop.EditMessages.EM_GETSELTEXT: + text = "EM_GETSELTEXT"; + break; + case Interop.EditMessages.EM_HIDESELECTION: + text = "EM_HIDESELECTION"; + break; + case Interop.EditMessages.EM_PASTESPECIAL: + text = "EM_PASTESPECIAL"; + break; + case Interop.EditMessages.EM_REQUESTRESIZE: + text = "EM_REQUESTRESIZE"; + break; + case Interop.EditMessages.EM_SELECTIONTYPE: + text = "EM_SELECTIONTYPE"; + break; + case Interop.EditMessages.EM_SETBKGNDCOLOR: + text = "EM_SETBKGNDCOLOR"; + break; + case Interop.EditMessages.EM_SETCHARFORMAT: + text = "EM_SETCHARFORMAT"; + break; + case Interop.EditMessages.EM_SETEVENTMASK: + text = "EM_SETEVENTMASK"; + break; + case Interop.EditMessages.EM_SETOLECALLBACK: + text = "EM_SETOLECALLBACK"; + break; + case Interop.EditMessages.EM_SETPARAFORMAT: + text = "EM_SETPARAFORMAT"; + break; + case Interop.EditMessages.EM_SETTARGETDEVICE: + text = "EM_SETTARGETDEVICE"; + break; + case Interop.EditMessages.EM_STREAMIN: + text = "EM_STREAMIN"; + break; + case Interop.EditMessages.EM_STREAMOUT: + text = "EM_STREAMOUT"; + break; + case Interop.EditMessages.EM_GETTEXTRANGE: + text = "EM_GETTEXTRANGE"; + break; + case Interop.EditMessages.EM_FINDWORDBREAK: + text = "EM_FINDWORDBREAK"; + break; + case Interop.EditMessages.EM_SETOPTIONS: + text = "EM_SETOPTIONS"; + break; + case Interop.EditMessages.EM_GETOPTIONS: + text = "EM_GETOPTIONS"; + break; + case Interop.EditMessages.EM_FINDTEXTEX: + text = "EM_FINDTEXTEX"; + break; + case Interop.EditMessages.EM_GETWORDBREAKPROCEX: + text = "EM_GETWORDBREAKPROCEX"; + break; + case Interop.EditMessages.EM_SETWORDBREAKPROCEX: + text = "EM_SETWORDBREAKPROCEX"; + break; - // Richedit v2.0 messages - case RichTextBoxConstants.EM_SETUNDOLIMIT: text = "EM_SETUNDOLIMIT"; break; - case RichTextBoxConstants.EM_REDO: text = "EM_REDO"; break; - case RichTextBoxConstants.EM_CANREDO: text = "EM_CANREDO"; break; - case RichTextBoxConstants.EM_GETUNDONAME: text = "EM_GETUNDONAME"; break; - case RichTextBoxConstants.EM_GETREDONAME: text = "EM_GETREDONAME"; break; - case RichTextBoxConstants.EM_STOPGROUPTYPING: text = "EM_STOPGROUPTYPING"; break; + // Richedit v2.0 messages + case Interop.EditMessages.EM_SETUNDOLIMIT: + text = "EM_SETUNDOLIMIT"; + break; + case Interop.EditMessages.EM_REDO: + text = "EM_REDO"; + break; + case Interop.EditMessages.EM_CANREDO: + text = "EM_CANREDO"; + break; + case Interop.EditMessages.EM_GETUNDONAME: + text = "EM_GETUNDONAME"; + break; + case Interop.EditMessages.EM_GETREDONAME: + text = "EM_GETREDONAME"; + break; + case Interop.EditMessages.EM_STOPGROUPTYPING: + text = "EM_STOPGROUPTYPING"; + break; + case Interop.EditMessages.EM_SETTEXTMODE: + text = "EM_SETTEXTMODE"; + break; + case Interop.EditMessages.EM_GETTEXTMODE: + text = "EM_GETTEXTMODE"; + break; + case Interop.EditMessages.EM_AUTOURLDETECT: + text = "EM_AUTOURLDETECT"; + break; + case Interop.EditMessages.EM_GETAUTOURLDETECT: + text = "EM_GETAUTOURLDETECT"; + break; + case Interop.EditMessages.EM_SETPALETTE: + text = "EM_SETPALETTE"; + break; + case Interop.EditMessages.EM_GETTEXTEX: + text = "EM_GETTEXTEX"; + break; + case Interop.EditMessages.EM_GETTEXTLENGTHEX: + text = "EM_GETTEXTLENGTHEX"; + break; - case RichTextBoxConstants.EM_SETTEXTMODE: text = "EM_SETTEXTMODE"; break; - case RichTextBoxConstants.EM_GETTEXTMODE: text = "EM_GETTEXTMODE"; break; + // Asia specific messages + case Interop.EditMessages.EM_SETPUNCTUATION: + text = "EM_SETPUNCTUATION"; + break; + case Interop.EditMessages.EM_GETPUNCTUATION: + text = "EM_GETPUNCTUATION"; + break; + case Interop.EditMessages.EM_SETWORDWRAPMODE: + text = "EM_SETWORDWRAPMODE"; + break; + case Interop.EditMessages.EM_GETWORDWRAPMODE: + text = "EM_GETWORDWRAPMODE"; + break; + case Interop.EditMessages.EM_SETIMECOLOR: + text = "EM_SETIMECOLOR"; + break; + case Interop.EditMessages.EM_GETIMECOLOR: + text = "EM_GETIMECOLOR"; + break; + case Interop.EditMessages.EM_SETIMEOPTIONS: + text = "EM_SETIMEOPTIONS"; + break; + case Interop.EditMessages.EM_GETIMEOPTIONS: + text = "EM_GETIMEOPTIONS"; + break; + case Interop.EditMessages.EM_CONVPOSITION: + text = "EM_CONVPOSITION"; + break; + case Interop.EditMessages.EM_SETLANGOPTIONS: + text = "EM_SETLANGOPTIONS"; + break; + case Interop.EditMessages.EM_GETLANGOPTIONS: + text = "EM_GETLANGOPTIONS"; + break; + case Interop.EditMessages.EM_GETIMECOMPMODE: + text = "EM_GETIMECOMPMODE"; + break; + case Interop.EditMessages.EM_FINDTEXTW: + text = "EM_FINDTEXTW"; + break; + case Interop.EditMessages.EM_FINDTEXTEXW: + text = "EM_FINDTEXTEXW"; + break; - case RichTextBoxConstants.EM_AUTOURLDETECT: text = "EM_AUTOURLDETECT"; break; - case RichTextBoxConstants.EM_GETAUTOURLDETECT: text = "EM_GETAUTOURLDETECT"; break; - case RichTextBoxConstants.EM_SETPALETTE: text = "EM_SETPALETTE"; break; - case RichTextBoxConstants.EM_GETTEXTEX: text = "EM_GETTEXTEX"; break; - case RichTextBoxConstants.EM_GETTEXTLENGTHEX: text = "EM_GETTEXTLENGTHEX"; break; + // Rich Edit 3.0 Asia msgs + case Interop.EditMessages.EM_RECONVERSION: + text = "EM_RECONVERSION"; + break; + case Interop.EditMessages.EM_SETIMEMODEBIAS: + text = "EM_SETIMEMODEBIAS"; + break; + case Interop.EditMessages.EM_GETIMEMODEBIAS: + text = "EM_GETIMEMODEBIAS"; + break; - // Asia specific messages - case RichTextBoxConstants.EM_SETPUNCTUATION: text = "EM_SETPUNCTUATION"; break; - case RichTextBoxConstants.EM_GETPUNCTUATION: text = "EM_GETPUNCTUATION"; break; - case RichTextBoxConstants.EM_SETWORDWRAPMODE: text = "EM_SETWORDWRAPMODE"; break; - case RichTextBoxConstants.EM_GETWORDWRAPMODE: text = "EM_GETWORDWRAPMODE"; break; - case RichTextBoxConstants.EM_SETIMECOLOR: text = "EM_SETIMECOLOR"; break; - case RichTextBoxConstants.EM_GETIMECOLOR: text = "EM_GETIMECOLOR"; break; - case RichTextBoxConstants.EM_SETIMEOPTIONS: text = "EM_SETIMEOPTIONS"; break; - case RichTextBoxConstants.EM_GETIMEOPTIONS: text = "EM_GETIMEOPTIONS"; break; - case RichTextBoxConstants.EM_CONVPOSITION: text = "EM_CONVPOSITION"; break; + // BiDi Specific messages + case Interop.EditMessages.EM_SETBIDIOPTIONS: + text = "EM_SETBIDIOPTIONS"; + break; + case Interop.EditMessages.EM_GETBIDIOPTIONS: + text = "EM_GETBIDIOPTIONS"; + break; + case Interop.EditMessages.EM_SETTYPOGRAPHYOPTIONS: + text = "EM_SETTYPOGRAPHYOPTIONS"; + break; + case Interop.EditMessages.EM_GETTYPOGRAPHYOPTIONS: + text = "EM_GETTYPOGRAPHYOPTIONS"; + break; - case RichTextBoxConstants.EM_SETLANGOPTIONS: text = "EM_SETLANGOPTIONS"; break; - case RichTextBoxConstants.EM_GETLANGOPTIONS: text = "EM_GETLANGOPTIONS"; break; - case RichTextBoxConstants.EM_GETIMECOMPMODE: text = "EM_GETIMECOMPMODE"; break; + // Extended Edit style specific messages + case Interop.EditMessages.EM_SETEDITSTYLE: + text = "EM_SETEDITSTYLE"; + break; + case Interop.EditMessages.EM_GETEDITSTYLE: + text = "EM_GETEDITSTYLE"; + break; - case RichTextBoxConstants.EM_FINDTEXTW: text = "EM_FINDTEXTW"; break; - case RichTextBoxConstants.EM_FINDTEXTEXW: text = "EM_FINDTEXTEXW"; break; - - //Rich Edit 3.0 Asia msgs - case RichTextBoxConstants.EM_RECONVERSION: text = "EM_RECONVERSION"; break; - case RichTextBoxConstants.EM_SETIMEMODEBIAS: text = "EM_SETIMEMODEBIAS"; break; - case RichTextBoxConstants.EM_GETIMEMODEBIAS: text = "EM_GETIMEMODEBIAS"; break; - - // BiDi Specific messages - case RichTextBoxConstants.EM_SETBIDIOPTIONS: text = "EM_SETBIDIOPTIONS"; break; - case RichTextBoxConstants.EM_GETBIDIOPTIONS: text = "EM_GETBIDIOPTIONS"; break; - - case RichTextBoxConstants.EM_SETTYPOGRAPHYOPTIONS: text = "EM_SETTYPOGRAPHYOPTIONS"; break; - case RichTextBoxConstants.EM_GETTYPOGRAPHYOPTIONS: text = "EM_GETTYPOGRAPHYOPTIONS"; break; - - // Extended Edit style specific messages - case RichTextBoxConstants.EM_SETEDITSTYLE: text = "EM_SETEDITSTYLE"; break; - case RichTextBoxConstants.EM_GETEDITSTYLE: text = "EM_GETEDITSTYLE"; break; - - default: text = null; break; + default: + text = null; break; } - if (text == null && ((msg & NativeMethods.WM_REFLECT) == NativeMethods.WM_REFLECT)) { - string subtext = MsgToString(msg - NativeMethods.WM_REFLECT); - if (subtext == null) subtext = "???"; + if (text == null && ((msg & Interop.WindowMessages.WM_REFLECT) == Interop.WindowMessages.WM_REFLECT)) + { + string subtext = MsgToString(msg - Interop.WindowMessages.WM_REFLECT) ?? "???"; + text = "WM_REFLECT + " + subtext; } return text; } - private static string Parenthesize(string input) { + private static string Parenthesize(string input) + { if (input == null) - return ""; - else - return " (" + input + ")"; + { + return string.Empty; + } + + return " (" + input + ")"; } -#if FALSE - // If you want to use MessageDecoder.ToString(int msg) for debugging uncomment this block. - // Don't forget to comment it back before checking in or else you will have an FxCop error. - public static string ToString(int msg) { - string ID = Parenthesize(MsgToString(msg)); - return "msg=0x" + Convert.ToString(msg, 16) + ID; - } -#endif //FALSE - - public static string ToString(Message message) { + public static string ToString(Message message) + { return ToString(message.HWnd, message.Msg, message.WParam, message.LParam, message.Result); } - public static string ToString(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam, IntPtr result) { - string ID = Parenthesize(MsgToString(msg)); + public static string ToString(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam, IntPtr result) + { + string id = Parenthesize(MsgToString(msg)); - string lDescription = ""; - if (msg == NativeMethods.WM_PARENTNOTIFY) + string lDescription = string.Empty; + if (msg == Interop.WindowMessages.WM_PARENTNOTIFY) + { lDescription = Parenthesize(MsgToString(NativeMethods.Util.LOWORD(wparam))); + } - return "msg=0x" + Convert.ToString(msg, 16) + ID - + " hwnd=0x" + Convert.ToString((long)hWnd, 16) - + " wparam=0x" + Convert.ToString((long)wparam, 16) - + " lparam=0x" + Convert.ToString((long)lparam, 16) + lDescription - + " result=0x" + Convert.ToString((long)result, 16); + return + "msg=0x" + Convert.ToString(msg, 16) + id + + " hwnd=0x" + Convert.ToString((long)hWnd, 16) + + " wparam=0x" + Convert.ToString((long)wparam, 16) + + " lparam=0x" + Convert.ToString((long)lparam, 16) + lDescription + + " result=0x" + Convert.ToString((long)result, 16); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs index 76576ae8df7..29b56feabbb 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs @@ -185,12 +185,7 @@ public MonthCalendar() /// /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level1) { - return new MonthCalendarAccessibleObject(this); - } - else { - return base.CreateAccessibilityInstance(); - } + return new MonthCalendarAccessibleObject(this); } protected override void RescaleConstantsForDpi(int deviceDpiOld, int deviceDpiNew) { @@ -517,7 +512,7 @@ public DateTime MaxDate { set { if (value != maxDate) { if (value < DateTimePicker.EffectiveMinDate(minDate)) { - throw new ArgumentOutOfRangeException(nameof(MaxDate), string.Format(SR.InvalidLowBoundArgumentEx, "MaxDate", FormatDate(value), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(MaxDate), FormatDate(value), nameof(MinDate))); } maxDate = value; SetRange(); @@ -542,13 +537,13 @@ public int MaxSelectionCount { } set { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(MaxSelectionCount), string.Format(SR.InvalidLowBoundArgumentEx, "MaxSelectionCount", (value).ToString("D", CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(MaxSelectionCount), value.ToString("D"), 1)); } if (value != maxSelectionCount) { if (IsHandleCreated) { if (unchecked( (int) (long)SendMessage(NativeMethods.MCM_SETMAXSELCOUNT, value, 0)) == 0) - throw new ArgumentException(string.Format(SR.MonthCalendarMaxSelCount, (value).ToString("D", CultureInfo.CurrentCulture)), "MaxSelectionCount"); + throw new ArgumentException(string.Format(SR.MonthCalendarMaxSelCount, value.ToString("D")), nameof(value)); } maxSelectionCount = value; } @@ -572,13 +567,13 @@ public DateTime MinDate { set { if (value != minDate) { if (value > DateTimePicker.EffectiveMaxDate(maxDate)) { - throw new ArgumentOutOfRangeException(nameof(MinDate), string.Format(SR.InvalidHighBoundArgument, "MinDate", FormatDate(value), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgument, nameof(MinDate), FormatDate(value), nameof(MaxDate))); } // If trying to set the minimum less than DateTimePicker.MinimumDateTime, throw // an exception. if (value < DateTimePicker.MinimumDateTime) { - throw new ArgumentOutOfRangeException(nameof(MinDate), string.Format(SR.InvalidLowBoundArgumentEx, "MinDate", FormatDate(value), FormatDate(DateTimePicker.MinimumDateTime))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(MinDate), FormatDate(value), FormatDate(DateTimePicker.MinimumDateTime))); } minDate = value; @@ -708,10 +703,10 @@ public int ScrollChange { if (scrollChange != value) { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(ScrollChange), string.Format(SR.InvalidLowBoundArgumentEx, "ScrollChange", (value).ToString("D", CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ScrollChange), value.ToString("D"), 0)); } if (value > MaxScrollChange) { - throw new ArgumentOutOfRangeException(nameof(ScrollChange), string.Format(SR.InvalidHighBoundArgumentEx, "ScrollChange", (value).ToString("D", CultureInfo.CurrentCulture), (MaxScrollChange).ToString("D", CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(ScrollChange), value.ToString("D"), MaxScrollChange.ToString("D"))); } if (IsHandleCreated) { @@ -742,10 +737,10 @@ public DateTime SelectionEnd { // Keep SelectionEnd within min and max if (value < MinDate) { - throw new ArgumentOutOfRangeException(nameof(SelectionEnd), string.Format(SR.InvalidLowBoundArgumentEx, "SelectionEnd", FormatDate(value), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectionEnd), FormatDate(value), nameof(MinDate))); } if (value > MaxDate) { - throw new ArgumentOutOfRangeException(nameof(SelectionEnd), string.Format(SR.InvalidHighBoundArgumentEx, "SelectionEnd", FormatDate(value), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(SelectionEnd), FormatDate(value), nameof(MaxDate))); } // If we've moved SelectionEnd before SelectionStart, move SelectionStart back @@ -786,10 +781,10 @@ public DateTime SelectionStart { // Keep SelectionStart within min and max // if (value < minDate) { - throw new ArgumentOutOfRangeException(nameof(SelectionStart), string.Format(SR.InvalidLowBoundArgumentEx, "SelectionStart", FormatDate(value), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectionStart), FormatDate(value), nameof(MinDate))); } if (value > maxDate) { - throw new ArgumentOutOfRangeException(nameof(SelectionStart), string.Format(SR.InvalidHighBoundArgumentEx, "SelectionStart", FormatDate(value), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(SelectionStart), FormatDate(value), nameof(MaxDate))); } // If we've moved SelectionStart beyond SelectionEnd, move SelectionEnd forward @@ -994,12 +989,12 @@ public DateTime TodayDate { // throw if trying to set the TodayDate to a value greater than MaxDate if (DateTime.Compare(value, maxDate) > 0) { - throw new ArgumentOutOfRangeException(nameof(TodayDate), string.Format(SR.InvalidHighBoundArgumentEx, "TodayDate", FormatDate(value), FormatDate(maxDate))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(TodayDate), FormatDate(value), FormatDate(maxDate))); } // throw if trying to set the TodayDate to a value less than MinDate if (DateTime.Compare(value, minDate) < 0) { - throw new ArgumentOutOfRangeException(nameof(TodayDate), string.Format(SR.InvalidLowBoundArgument, "TodayDate", FormatDate(value), FormatDate(minDate))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgument, nameof(TodayDate), FormatDate(value), FormatDate(minDate))); } todayDate = value.Date; @@ -1489,7 +1484,7 @@ public HitTestInfo HitTest(int x, int y) { NativeMethods.MCHITTESTINFO mchi = new NativeMethods.MCHITTESTINFO(); mchi.pt_x = x; mchi.pt_y = y; - mchi.cbSize = Marshal.SizeOf(typeof(NativeMethods.MCHITTESTINFO)); + mchi.cbSize = Marshal.SizeOf(); UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.MCM_HITTEST, 0, mchi); // If the hit area has an associated valid date, get it @@ -1976,10 +1971,10 @@ public void SetCalendarDimensions(int x, int y) { public void SetDate(DateTime date) { if (date.Ticks < minDate.Ticks) { - throw new ArgumentOutOfRangeException(nameof(date), string.Format(SR.InvalidLowBoundArgumentEx, "date", FormatDate(date), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(date), date, string.Format(SR.InvalidLowBoundArgumentEx, nameof(date), FormatDate(date), nameof(MinDate))); } if (date.Ticks > maxDate.Ticks) { - throw new ArgumentOutOfRangeException(nameof(date), string.Format(SR.InvalidHighBoundArgumentEx, "date", FormatDate(date), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(date), date, string.Format(SR.InvalidHighBoundArgumentEx, nameof(date), FormatDate(date), nameof(MaxDate))); } SetSelectionRange(date, date); @@ -1995,16 +1990,16 @@ public void SetSelectionRange(DateTime date1, DateTime date2) { // Keep the dates within the min and max dates if (date1.Ticks < minDate.Ticks) { - throw new ArgumentOutOfRangeException(nameof(date1), string.Format(SR.InvalidLowBoundArgumentEx, "SelectionStart", FormatDate(date1), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(date1), date1, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectionStart), FormatDate(date1), nameof(MinDate))); } if (date1.Ticks > maxDate.Ticks) { - throw new ArgumentOutOfRangeException(nameof(date1), string.Format(SR.InvalidHighBoundArgumentEx, "SelectionEnd", FormatDate(date1), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(date1), date1, string.Format(SR.InvalidHighBoundArgumentEx, nameof(SelectionEnd), FormatDate(date1), nameof(MaxDate))); } if (date2.Ticks < minDate.Ticks) { - throw new ArgumentOutOfRangeException(nameof(date2), string.Format(SR.InvalidLowBoundArgumentEx, "SelectionStart", FormatDate(date2), "MinDate")); + throw new ArgumentOutOfRangeException(nameof(date2), date2, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectionStart), FormatDate(date2), nameof(MinDate))); } if (date2.Ticks > maxDate.Ticks) { - throw new ArgumentOutOfRangeException(nameof(date2), string.Format(SR.InvalidHighBoundArgumentEx, "SelectionEnd", FormatDate(date2), "MaxDate")); + throw new ArgumentOutOfRangeException(nameof(date2), date2, string.Format(SR.InvalidHighBoundArgumentEx, nameof(SelectionEnd), FormatDate(date2), nameof(MaxDate))); } // If date1 > date2, we just select date2 (compat) @@ -2197,10 +2192,8 @@ private void WmDateChanged(ref Message m) { DateTime start = selectionStart = DateTimePicker.SysTimeToDateTime(nmmcsc.stSelStart); DateTime end = selectionEnd = DateTimePicker.SysTimeToDateTime(nmmcsc.stSelEnd); - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); - AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); - } + AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); + AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); //subhag if (start.Ticks < minDate.Ticks || end.Ticks < minDate.Ticks) @@ -2241,10 +2234,9 @@ private void WmCalViewChanged (ref Message m) { if (mcCurView != (NativeMethods.MONTCALENDAR_VIEW_MODE)nmmcvm.uNewView) { mcOldView = mcCurView; mcCurView = (NativeMethods.MONTCALENDAR_VIEW_MODE)nmmcvm.uNewView; - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); - AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); - } + + AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); + AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); } } /// @@ -2257,10 +2249,8 @@ private void WmDateSelected(ref Message m) { DateTime start = selectionStart = DateTimePicker.SysTimeToDateTime(nmmcsc.stSelStart); DateTime end = selectionEnd = DateTimePicker.SysTimeToDateTime(nmmcsc.stSelEnd); - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); - AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); - } + AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); + AccessibilityNotifyClients(AccessibleEvents.ValueChange, -1); //subhag if (start.Ticks < minDate.Ticks || end.Ticks < minDate.Ticks) @@ -2302,9 +2292,7 @@ private void WmReflectCommand(ref Message m) { WmDateBold(ref m); break; case NativeMethods.MCN_VIEWCHANGE: - if (AccessibilityImprovements.Level1) { - WmCalViewChanged(ref m); - } + WmCalViewChanged(ref m); break; } } @@ -2317,20 +2305,20 @@ private void WmReflectCommand(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: FocusInternal(); if (!ValidationCancelled) { base.WndProc(ref m); } break; - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: WmGetDlgCode(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: WmReflectCommand(ref m); base.WndProc(ref m); break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: base.WndProc(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/NativeWindow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/NativeWindow.cs index dc56c70391a..37fe8968def 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/NativeWindow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/NativeWindow.cs @@ -192,7 +192,7 @@ internal void ForceExitMessageLoop() { // If we owned the handle, post a // WM_CLOSE to get rid of it. // - UnsafeNativeMethods.PostMessage(new HandleRef(this, h), NativeMethods.WM_CLOSE, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(this, h), Interop.WindowMessages.WM_CLOSE, 0, 0); } } @@ -643,7 +643,7 @@ private IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { OnThreadException(e); } finally { - if (msg == NativeMethods.WM_NCDESTROY) ReleaseHandle(false); + if (msg == Interop.WindowMessages.WM_NCDESTROY) ReleaseHandle(false); if (msg == NativeMethods.WM_UIUNSUBCLASS) ReleaseHandle(true); } @@ -759,7 +759,7 @@ private IntPtr DebuggableCallback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lp } } finally { - if (msg == NativeMethods.WM_NCDESTROY) ReleaseHandle(false); + if (msg == Interop.WindowMessages.WM_NCDESTROY) ReleaseHandle(false); if (msg == NativeMethods.WM_UIUNSUBCLASS) ReleaseHandle(true); } @@ -807,7 +807,7 @@ public virtual void DestroyHandle() { if (!UnsafeNativeMethods.DestroyWindow(new HandleRef(this, handle))) { UnSubclass(); //then post a close and let it do whatever it needs to do on its own. - UnsafeNativeMethods.PostMessage(new HandleRef(this, handle), NativeMethods.WM_CLOSE, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(this, handle), Interop.WindowMessages.WM_CLOSE, 0, 0); } handle = IntPtr.Zero; ownHandle = false; @@ -1031,7 +1031,7 @@ private static void OnShutdown(object sender, EventArgs e) { HandleRef href = new HandleRef(b, b.handle); UnsafeNativeMethods.SetWindowLong(href, NativeMethods.GWL_WNDPROC, new HandleRef(null, userDefWindowProc)); UnsafeNativeMethods.SetClassLong(href, NativeMethods.GCL_WNDPROC, userDefWindowProc); - UnsafeNativeMethods.PostMessage(href, NativeMethods.WM_CLOSE, 0, 0); + UnsafeNativeMethods.PostMessage(href, Interop.WindowMessages.WM_CLOSE, 0, 0); // Fish out the Window object, if it is valid, and NULL the handle pointer. This // way the rest of WinForms won't think the handle is still valid here. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/NotifyIcon.cs b/src/System.Windows.Forms/src/System/Windows/Forms/NotifyIcon.cs index f37ae90ad51..0bc70298c30 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/NotifyIcon.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/NotifyIcon.cs @@ -41,7 +41,7 @@ public sealed class NotifyIcon : Component { private static readonly object EVENT_BALLOONTIPCLICKED = new object(); private static readonly object EVENT_BALLOONTIPCLOSED = new object(); - private const int WM_TRAYMOUSEMESSAGE = NativeMethods.WM_USER + 1024; + private const int WM_TRAYMOUSEMESSAGE = Interop.WindowMessages.WM_USER + 1024; private static int WM_TASKBARCREATED = SafeNativeMethods.RegisterWindowMessage("TaskbarCreated"); private object syncObj = new object(); @@ -480,7 +480,7 @@ protected override void Dispose(bool disposing) { // it, change it there too. // if (window != null && window.Handle != IntPtr.Zero) { - UnsafeNativeMethods.PostMessage(new HandleRef(window, window.Handle), NativeMethods.WM_CLOSE, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(window, window.Handle), Interop.WindowMessages.WM_CLOSE, 0, 0); window.ReleaseHandle(); } } @@ -667,7 +667,7 @@ public void ShowBalloonTip(int timeout) { public void ShowBalloonTip(int timeout, string tipTitle, string tipText, ToolTipIcon tipIcon) { if (timeout < 0) { - throw new ArgumentOutOfRangeException(nameof(timeout), string.Format(SR.InvalidArgument, "timeout", (timeout).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(timeout), timeout, string.Format(SR.InvalidArgument, nameof(timeout), timeout)); } if (string.IsNullOrEmpty(tipText)) @@ -734,7 +734,7 @@ private void ShowContextMenu() { null); // Force task switch (see above) - UnsafeNativeMethods.PostMessage(new HandleRef(window, window.Handle), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero); + UnsafeNativeMethods.PostMessage(new HandleRef(window, window.Handle), Interop.WindowMessages.WM_NULL, IntPtr.Zero, IntPtr.Zero); } else if (contextMenuStrip != null) { // this will set the context menu strip to be toplevel @@ -843,34 +843,34 @@ private void WndProc(ref Message msg) { switch (msg.Msg) { case WM_TRAYMOUSEMESSAGE: switch ((int)msg.LParam) { - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: WmMouseDown(ref msg, MouseButtons.Left, 2); break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: WmMouseDown(ref msg, MouseButtons.Left, 1); break; - case NativeMethods.WM_LBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: WmMouseUp(ref msg, MouseButtons.Left); break; - case NativeMethods.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: WmMouseDown(ref msg, MouseButtons.Middle, 2); break; - case NativeMethods.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: WmMouseDown(ref msg, MouseButtons.Middle, 1); break; - case NativeMethods.WM_MBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONUP: WmMouseUp(ref msg, MouseButtons.Middle); break; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: WmMouseMove(ref msg); break; - case NativeMethods.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: WmMouseDown(ref msg, MouseButtons.Right, 2); break; - case NativeMethods.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: WmMouseDown(ref msg, MouseButtons.Right, 1); break; - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: if (contextMenu != null || contextMenuStrip != null) { ShowContextMenu(); } @@ -890,7 +890,7 @@ private void WndProc(ref Message msg) { break; } break; - case NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_COMMAND: if (IntPtr.Zero == msg.LParam) { if (Command.DispatchID((int)msg.WParam & 0xFFFF)) return; } @@ -898,25 +898,25 @@ private void WndProc(ref Message msg) { window.DefWndProc(ref msg); } break; - case NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_DRAWITEM: // If the wparam is zero, then the message was sent by a menu. // See WM_DRAWITEM in MSDN. if (msg.WParam == IntPtr.Zero) { WmDrawItemMenuItem(ref msg); } break; - case NativeMethods.WM_MEASUREITEM: + case Interop.WindowMessages.WM_MEASUREITEM: // If the wparam is zero, then the message was sent by a menu. if (msg.WParam == IntPtr.Zero) { WmMeasureMenuItem(ref msg); } break; - case NativeMethods.WM_INITMENUPOPUP: + case Interop.WindowMessages.WM_INITMENUPOPUP: WmInitMenuPopup(ref msg); break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: // Remove the icon from the taskbar UpdateIcon(false); break; @@ -996,7 +996,7 @@ internal NotifyIconNativeWindow(NotifyIcon component) { // it, change it there too. // if (Handle != IntPtr.Zero) { - UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), NativeMethods.WM_CLOSE, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_CLOSE, 0, 0); } // This releases the handle from our window proc, re-routing it back to diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/NumericUpDown.cs b/src/System.Windows.Forms/src/System/Windows/Forms/NumericUpDown.cs index c21157084bf..b89302b5c16 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/NumericUpDown.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/NumericUpDown.cs @@ -13,7 +13,6 @@ namespace System.Windows.Forms { using System.Windows.Forms.Internal; using System.Globalization; using System.Runtime.InteropServices; - using System.Security.Permissions; using System.Windows.Forms.Layout; /// @@ -135,7 +134,7 @@ public int DecimalPlaces { set { if (value < 0 || value > 99) { - throw new ArgumentOutOfRangeException(nameof(DecimalPlaces), string.Format(SR.InvalidBoundArgument, "DecimalPlaces", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture), "99")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(DecimalPlaces), value, 0, 99)); } decimalPlaces = value; UpdateEditText(); @@ -186,8 +185,8 @@ public decimal Increment { } set { - if (value < (decimal)0.0) { - throw new ArgumentOutOfRangeException(nameof(Increment), string.Format(SR.InvalidArgument, "Increment", value.ToString(CultureInfo.CurrentCulture))); + if (value < 0.0m) { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(Increment), value)); } else { this.increment = value; @@ -362,7 +361,7 @@ public decimal Value { if (value != currentValue) { if (!initializing && ((value < minimum) || (value > maximum))) { - throw new ArgumentOutOfRangeException(nameof(Value), string.Format(SR.InvalidBoundArgument, "Value", value.ToString(CultureInfo.CurrentCulture), "'Minimum'", "'Maximum'")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(Value), value, $"'{nameof(Minimum)}'", $"'{nameof(Maximum)}'")); } else { currentValue = value; @@ -912,12 +911,7 @@ public override AccessibleRole Role { return role; } else { - if (AccessibilityImprovements.Level1) { - return AccessibleRole.SpinButton; - } - else { - return AccessibleRole.ComboBox; - } + return AccessibleRole.SpinButton; } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/OSFeature.cs b/src/System.Windows.Forms/src/System/Windows/Forms/OSFeature.cs index 4c5125811d4..1fb2ecd0a61 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/OSFeature.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/OSFeature.cs @@ -2,119 +2,110 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Configuration.Assemblies; - using System.Diagnostics; - using System; - using System.Security; - using System.Security.Permissions; - - /// - /// - /// Provides operating-system specific feature queries. - /// - public class OSFeature : FeatureSupport { - - /// - /// - /// Represents the layered, top-level windows feature. This - /// field is read-only. - /// +namespace System.Windows.Forms +{ + /// + /// Provides operating-system specific feature queries. + /// + public class OSFeature : FeatureSupport + { + /// + /// Represents the layered, top-level windows feature. This field + /// is read-only. + /// public static readonly object LayeredWindows = new object(); - - /// - /// - /// Determines if the OS supports themes - /// + + /// + /// Determines if the OS supports themes + /// public static readonly object Themes = new object(); - private static OSFeature feature = null; + private static OSFeature _feature = null; - private static bool themeSupportTested = false; - private static bool themeSupport = false; + private static bool _themeSupportTested = false; + private static bool _themeSupport = false; - /// - /// - /// - /// - /// Initializes a new instance of the class. - /// - /// - /// - protected OSFeature() { + /// + /// Initializes a new instance of the class. + /// + protected OSFeature() + { } - /// - /// - /// Represents the instance of to use for feature queries. This property is read-only. - /// - public static OSFeature Feature { - get { - if (feature == null) - feature = new OSFeature(); - - return feature; - } - } - - /// - /// - /// Retrieves the version of the specified feature currently available on the system. - /// - public override Version GetVersionPresent(object feature) { - Version featureVersion = null; - if (feature == LayeredWindows) { - if (Environment.OSVersion.Platform == System.PlatformID.Win32NT - && Environment.OSVersion.Version.CompareTo(new Version(5, 0, 0, 0)) >= 0) { - - featureVersion = new Version(0, 0, 0, 0); - } + /// + /// Represents the instance of + // to use for feature queries. This property is read-only. + /// + public static OSFeature Feature => _feature ?? (_feature = new OSFeature()); + + /// + /// Retrieves the version of the specified feature currently available on the system. + /// + public override Version GetVersionPresent(object feature) + { + if (feature == LayeredWindows) + { + return new Version(0, 0, 0, 0); } - else if (feature == Themes) { - if (!themeSupportTested) { - try { + else if (feature == Themes) + { + if (!_themeSupportTested) + { + try + { SafeNativeMethods.IsAppThemed(); - themeSupport = true; + _themeSupport = true; } - catch { - themeSupport = false; + catch + { + _themeSupport = false; } - themeSupportTested = true; + + _themeSupportTested = true; } - if (themeSupport) { - featureVersion = new Version(0, 0, 0, 0); + if (_themeSupport) + { + return new Version(0, 0, 0, 0); } } - return featureVersion; + + return null; } - internal bool OnXp { - get { + internal bool OnXp + { + get + { bool onXp = false; - if (Environment.OSVersion.Platform == System.PlatformID.Win32NT) { - onXp = Environment.OSVersion.Version.CompareTo(new Version(5, 1, 0, 0)) >= 0; + if (Environment.OSVersion.Platform == System.PlatformID.Win32NT) + { + onXp = Environment.OSVersion.Version.CompareTo(new Version(5, 1, 0, 0)) >= 0; } return onXp; } } - internal bool OnWin2k { - get { + internal bool OnWin2k + { + get + { bool onWin2k = false; - if (Environment.OSVersion.Platform == System.PlatformID.Win32NT) { - onWin2k = Environment.OSVersion.Version.CompareTo(new Version(5, 0, 0, 0)) >= 0; + if (Environment.OSVersion.Platform == System.PlatformID.Win32NT) + { + onWin2k = Environment.OSVersion.Version.CompareTo(new Version(5, 0, 0, 0)) >= 0; } return onWin2k; } } - /// - /// - /// Retrieves whether SystemParameterType is supported on the Current OS version. - /// - public static bool IsPresent(SystemParameter enumVal) { - switch (enumVal) { + /// + /// Retrieves whether SystemParameterType is supported on the Current OS version. + /// + public static bool IsPresent(SystemParameter enumVal) + { + switch (enumVal) + { case SystemParameter.DropShadow: return Feature.OnXp; @@ -158,8 +149,8 @@ public static bool IsPresent(SystemParameter enumVal) { case SystemParameter.HorizontalFocusThicknessMetric: return Feature.OnXp; } + return false; } - } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/OwnerDrawPropertyBag.cs b/src/System.Windows.Forms/src/System/Windows/Forms/OwnerDrawPropertyBag.cs index 9e8d1419c11..0f4e2c52ba1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/OwnerDrawPropertyBag.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/OwnerDrawPropertyBag.cs @@ -2,127 +2,95 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters; - using System.Diagnostics; - using System; - using System.Drawing; - using System.Diagnostics.CodeAnalysis; - using System.Windows.Forms.Internal; - using System.Windows.Forms; - using Microsoft.Win32; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Formatters; - - - /// - /// - /// - /// Class used to pass new font/color information around for "partial" ownerdraw list/treeview items. - /// - /// - // - [SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")] +namespace System.Windows.Forms +{ + /// + /// Class used to pass new font/color information around for "partial" ownerdraw list/treeview items. + /// + [SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")] [Serializable] - public class OwnerDrawPropertyBag : MarshalByRefObject, ISerializable { - Font font = null; - Color foreColor = Color.Empty; - Color backColor = Color.Empty; - Control.FontHandleWrapper fontWrapper = null; - private static object internalSyncObject = new object(); - /** - * Constructor used in deserialization - * Has to be protected because OwnerDrawPropertyBag is not sealed. FxCop Rule CA2229. - */ - protected OwnerDrawPropertyBag(SerializationInfo info, StreamingContext context) { - foreach (SerializationEntry entry in info) { - if (entry.Name == "Font") { - font = (Font) entry.Value; + public class OwnerDrawPropertyBag : MarshalByRefObject, ISerializable + { + private Control.FontHandleWrapper _fontWrapper = null; + private static object s_internalSyncObject = new object(); + + protected OwnerDrawPropertyBag(SerializationInfo info, StreamingContext context) + { + foreach (SerializationEntry entry in info) + { + if (entry.Name == "Font") + { + Font = (Font)entry.Value; } - else if (entry.Name =="ForeColor") { - foreColor =(Color)entry.Value; + else if (entry.Name == "ForeColor") + { + ForeColor = (Color)entry.Value; } - else if (entry.Name =="BackColor") { - backColor = (Color)entry.Value; + else if (entry.Name == "BackColor") + { + BackColor = (Color)entry.Value; } } } - internal OwnerDrawPropertyBag(){ + internal OwnerDrawPropertyBag() + { } - /// - public Font Font { - get { - return font; - } - set { - font = value; - } - } + public Font Font { get; set; } - /// - public Color ForeColor { - get { - return foreColor; - } - set { - foreColor = value; - } - } + public Color ForeColor { get; set; } - /// - public Color BackColor { - get { - return backColor; - } - set { - backColor = value; - } - } + public Color BackColor { get; set; } - internal IntPtr FontHandle { - get { - if (fontWrapper == null) { - fontWrapper = new Control.FontHandleWrapper(Font); + internal IntPtr FontHandle + { + get + { + if (_fontWrapper == null) + { + _fontWrapper = new Control.FontHandleWrapper(Font); } - return fontWrapper.Handle; + + return _fontWrapper.Handle; } } - /// - /// - /// Returns whether or not this property bag contains all default values (is empty) - /// - public virtual bool IsEmpty() { - return (Font == null && foreColor.IsEmpty && backColor.IsEmpty); - } + /// + /// Returns whether or not this property bag contains all default values (is empty) + /// + public virtual bool IsEmpty() => Font == null && ForeColor.IsEmpty && BackColor.IsEmpty; + + /// + /// Copies the bag. Always returns a valid ODPB object + /// + public static OwnerDrawPropertyBag Copy(OwnerDrawPropertyBag value) + { + lock (s_internalSyncObject) + { + var result = new OwnerDrawPropertyBag(); + if (value == null) + { + return result; + } - /// - /// - /// Copies the bag. Always returns a valid ODPB object - /// - public static OwnerDrawPropertyBag Copy(OwnerDrawPropertyBag value) { - lock(internalSyncObject) { - OwnerDrawPropertyBag ret = new OwnerDrawPropertyBag(); - if (value == null) return ret; - ret.backColor = value.backColor; - ret.foreColor = value.foreColor; - ret.Font = value.font; - return ret; + result.BackColor = value.BackColor; + result.ForeColor = value.ForeColor; + result.Font = value.Font; + return result; } } - /// - /// - /// ISerializable private implementation - /// - /// - void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) { + void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) + { si.AddValue("BackColor", BackColor); si.AddValue("ForeColor", ForeColor); si.AddValue("Font", Font); } - } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Padding.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Padding.cs index 9ddedd808a3..070434d9ef7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Padding.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Padding.cs @@ -2,39 +2,34 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System; - using System.Collections; - using System.ComponentModel; - using System.ComponentModel.Design; - using System.ComponentModel.Design.Serialization; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Drawing; - using System.Globalization; - - /// +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; + +namespace System.Windows.Forms +{ [TypeConverterAttribute(typeof(PaddingConverter))] [Serializable] - public struct Padding { + public struct Padding + { private bool _all; private int _top; private int _left; private int _right; private int _bottom; - /// public static readonly Padding Empty = new Padding(0); - /// - public Padding(int all) { + public Padding(int all) + { _all = true; _top = _left = _right = _bottom = all; Debug_SanityCheck(); } - /// - public Padding(int left, int top, int right, int bottom) { + public Padding(int left, int top, int right, int bottom) + { _top = top; _left = left; _right = right; @@ -43,224 +38,177 @@ public Padding(int left, int top, int right, int bottom) { Debug_SanityCheck(); } - /// [RefreshProperties(RefreshProperties.All)] - public int All { - get { - return _all ? _top : -1; - } - set { - if (_all != true || _top != value) { + public int All + { + get => _all ? _top : -1; + set + { + if (_all != true || _top != value) + { _all = true; _top = _left = _right = _bottom = value; } + Debug_SanityCheck(); } } - /// [RefreshProperties(RefreshProperties.All)] - public int Bottom { - get { - if (_all) { - return _top; - } - return _bottom; - } - set { - if (_all || _bottom != value) { + public int Bottom + { + get => _all ? _top : _bottom; + set + { + if (_all || _bottom != value) + { _all = false; _bottom = value; } + Debug_SanityCheck(); } } - /// [RefreshProperties(RefreshProperties.All)] - public int Left { - get { - if (_all) { - return _top; - } - return _left; - } - set { - if (_all || _left != value) { + public int Left + { + get => _all ? _top : _left; + set + { + if (_all || _left != value) + { _all = false; _left = value; } + Debug_SanityCheck(); } } - /// [RefreshProperties(RefreshProperties.All)] - public int Right { - get { - if (_all) { - return _top; - } - return _right; - } - set { - if (_all || _right != value) { + public int Right + { + get => _all ? _top : _right; + set + { + if (_all || _right != value) + { _all = false; _right = value; } + Debug_SanityCheck(); } } - /// [RefreshProperties(RefreshProperties.All)] - public int Top { - get { - return _top; - } - set { - if (_all || _top != value) { + public int Top + { + get => _top; + set + { + if (_all || _top != value) + { _all = false; _top = value; } + Debug_SanityCheck(); } } - /// [Browsable(false)] - public int Horizontal { - get { - return Left + Right; - } - } + public int Horizontal => Left + Right; - /// [Browsable(false)] - public int Vertical { - get { - return Top + Bottom; - } - } + public int Vertical => Top + Bottom; - /// [Browsable(false)] - public Size Size { - get { - return new Size(Horizontal, Vertical); - } - } + public Size Size => new Size(Horizontal, Vertical); - public static Padding Add(Padding p1, Padding p2) { - // added for FXCop rule: Provide a friendly-name version of the Addition operator - return p1 + p2; - } + public static Padding Add(Padding p1, Padding p2) => p1 + p2; - public static Padding Subtract(Padding p1, Padding p2) { - // added for FXCop rule: Provide a friendly-name version of the Subtraction operator - return p1 - p2; - } + public static Padding Subtract(Padding p1, Padding p2) => p1 - p2; - /// - public override bool Equals(object other) { - if(other is Padding) { - return ((Padding)other) == this; + public override bool Equals(object other) + { + if (!(other is Padding otherPadding)) + { + return false; } - return false; + + return this == otherPadding; } - - - /// - /// - /// - /// Performs vector addition of two objects. - /// - /// - public static Padding operator +(Padding p1, Padding p2) { - return new Padding(p1.Left + p2.Left, p1.Top + p2.Top, p1.Right + p2.Right, p1.Bottom + p2.Bottom ); - + /// + /// Performs vector addition of two objects. + /// + public static Padding operator +(Padding p1, Padding p2) + { + return new Padding(p1.Left + p2.Left, p1.Top + p2.Top, p1.Right + p2.Right, p1.Bottom + p2.Bottom); } - /// - /// - /// - /// Contracts a by another - /// . - /// - /// - public static Padding operator -(Padding p1, Padding p2) { - return new Padding(p1.Left - p2.Left, p1.Top - p2.Top, p1.Right - p2.Right, p1.Bottom - p2.Bottom ); + /// + /// Contracts a by another . + /// + public static Padding operator -(Padding p1, Padding p2) + { + return new Padding(p1.Left - p2.Left, p1.Top - p2.Top, p1.Right - p2.Right, p1.Bottom - p2.Bottom); } - /// - /// - /// Tests whether two objects - /// are identical. - /// - public static bool operator ==(Padding p1, Padding p2) { - return p1.Left == p2.Left && p1.Top == p2.Top && p1.Right == p2.Right && p1.Bottom == p2.Bottom; - } - - /// - /// - /// - /// Tests whether two objects are different. - /// - /// - public static bool operator !=(Padding p1, Padding p2) { - return !(p1 == p2); + /// + /// Tests whether two objects are identical. + /// + public static bool operator ==(Padding p1, Padding p2) + { + return p1.Left == p2.Left && p1.Top == p2.Top && p1.Right == p2.Right && p1.Bottom == p2.Bottom; } - + + /// + /// Tests whether two objects are different. + /// + public static bool operator !=(Padding p1, Padding p2) => !(p1 == p2); + public override int GetHashCode() => HashCode.Combine(Left, Top, Right, Bottom); - /// - public override string ToString() { - return "{Left=" + Left.ToString(CultureInfo.CurrentCulture) + ",Top=" + Top.ToString(CultureInfo.CurrentCulture) + ",Right=" + Right.ToString(CultureInfo.CurrentCulture) + ",Bottom=" + Bottom.ToString(CultureInfo.CurrentCulture) + "}"; + public override string ToString() + { + return "{Left=" + Left + ",Top=" + Top + ",Right=" + Right + ",Bottom=" + Bottom + "}"; } - private void ResetAll() { - All = 0; - } + private void ResetAll() => All = 0; - private void ResetBottom() { - Bottom = 0; - } + private void ResetBottom() => Bottom = 0; - private void ResetLeft() { - Left = 0; - } + private void ResetLeft() => Left = 0; - private void ResetRight() { - Right = 0; - } + private void ResetRight() => Right = 0; - private void ResetTop() { - Top = 0; - } + private void ResetTop() => Top = 0; - internal void Scale(float dx, float dy) { + internal void Scale(float dx, float dy) + { _top = (int)((float)_top * dy); _left = (int)((float)_left * dx); _right = (int)((float)_right * dx); _bottom = (int)((float)_bottom * dy); } - internal bool ShouldSerializeAll() { - return _all; - } + internal bool ShouldSerializeAll() => _all; [Conditional("DEBUG")] - private void Debug_SanityCheck() { - if(_all) { + private void Debug_SanityCheck() + { + if (_all) + { Debug.Assert(ShouldSerializeAll(), "_all is true, but ShouldSerializeAll() is false."); Debug.Assert(All == Left && Left == Top && Top == Right && Right == Bottom, "_all is true, but All/Left/Top/Right/Bottom inconsistent."); - } else { + } + else + { Debug.Assert(All == -1, "_all is false, but All != -1."); Debug.Assert(!ShouldSerializeAll(), "ShouldSerializeAll() should not be true when all flag is not set."); - - // The below assert is not true with the current implementation of DockPaddingEdges. - // Debug.Assert(Left != Top || Top != Right || Right != Bottom, "_all is not set, but Left/Top/Right/Bottom are all the same"); } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PaddingConverter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PaddingConverter.cs index 915f8d225fb..12cafdc877c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PaddingConverter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PaddingConverter.cs @@ -42,10 +42,10 @@ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinati [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes", Justification = "ConvertFromString returns an object")] public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - if (value is string valueStr) + if (value is string stringValue) { - valueStr = valueStr.Trim(); - if (valueStr.Length == 0) + stringValue = stringValue.Trim(); + if (stringValue.Length == 0) { return null; } @@ -56,8 +56,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c culture = CultureInfo.CurrentCulture; } - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = valueStr.Split(new char[] { sep }); + string[] tokens = stringValue.Split(new char[] { culture.TextInfo.ListSeparator[0] }); int[] values = new int[tokens.Length]; TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); for (int i = 0; i < values.Length; i++) @@ -68,10 +67,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c if (values.Length != 4) { - throw new ArgumentException(string.Format(SR.TextParseFailedFormat, - nameof(value), - valueStr, - "left, top, right, bottom")); + throw new ArgumentException(string.Format(SR.TextParseFailedFormat, stringValue, "left, top, right, bottom"), nameof(value)); } return new Padding(values[0], values[1], values[2], values[3]); @@ -139,7 +135,7 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar Padding original = (Padding)context.PropertyDescriptor.GetValue(context.Instance); try { - int all = (int)propertyValues["All"]; + int all = (int)propertyValues[nameof(Padding.All)]; if (original.All != all) { return new Padding(all); @@ -147,10 +143,10 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar else { return new Padding( - (int)propertyValues["Left"], - (int)propertyValues["Top"], - (int)propertyValues["Right"], - (int)propertyValues["Bottom"] + (int)propertyValues[nameof(Padding.Left)], + (int)propertyValues[nameof(Padding.Top)], + (int)propertyValues[nameof(Padding.Right)], + (int)propertyValues[nameof(Padding.Bottom)] ); } } @@ -169,7 +165,7 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(Padding), attributes); - return props.Sort(new string[] { "All", "Left", "Top", "Right", "Bottom" }); + return props.Sort(new string[] { nameof(Padding.All), nameof(Padding.Left), nameof(Padding.Top), nameof(Padding.Right), nameof(Padding.Bottom) }); } public override bool GetPropertiesSupported(ITypeDescriptorContext context) => true; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PictureBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PictureBox.cs index 9b240f4c79e..9ff91456c89 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PictureBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PictureBox.cs @@ -292,9 +292,7 @@ public Image ErrorImage { // Can't share images across threads. if (defaultErrorImageForThread == null) { - defaultErrorImageForThread = - new Bitmap(typeof(PictureBox), - "ImageInError.bmp"); + defaultErrorImageForThread = DpiHelper.GetBitmapFromIcon(typeof(PictureBox), "ImageInError"); } defaultErrorImage = defaultErrorImageForThread; } @@ -493,9 +491,7 @@ public Image InitialImage { // Can't share images across threads. if (defaultInitialImageForThread == null) { - defaultInitialImageForThread = - new Bitmap(typeof(PictureBox), - "PictureBox.Loading.bmp"); + defaultInitialImageForThread = DpiHelper.GetBitmapFromIcon(typeof(PictureBox), "PictureBox.Loading"); } defaultInitialImage = defaultInitialImageForThread; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PageSetupDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PageSetupDialog.cs index ea164ad6cae..c8cba113167 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PageSetupDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PageSetupDialog.cs @@ -313,7 +313,6 @@ private bool ShouldSerializeMinMargins() { private static void UpdateSettings(NativeMethods.PAGESETUPDLG data, PageSettings pageSettings, PrinterSettings printerSettings) { - // SetHDevMode demands AllPrintingAndUnmanagedCode Permission : Since we are calling that function we should Assert the permision, pageSettings.SetHdevmode(data.hDevMode); if (printerSettings != null) { printerSettings.SetHdevmode(data.hDevMode); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs index f9143d4bc2a..209ae9dc23d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs @@ -327,7 +327,7 @@ internal static NativeMethods.PRINTDLGEX CreatePRINTDLGEX() { data.nPageRanges = 0; data.nMaxPageRanges = 1; data.pageRanges = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GPTR, - data.nMaxPageRanges * Marshal.SizeOf(typeof(NativeMethods.PRINTPAGERANGE))); + data.nMaxPageRanges * Marshal.SizeOf()); data.nMinPage = 0; data.nMaxPage = 9999; data.nCopies = 1; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewControl.cs index dde328530ac..67d0fa3daa2 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewControl.cs @@ -145,7 +145,7 @@ public int Columns { get { return columns;} set { if (value < 1 ) { - throw new ArgumentOutOfRangeException(nameof(Columns), string.Format(SR.InvalidLowBoundArgumentEx, "Columns", value.ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(Columns), value, 1)); } columns = value; @@ -206,7 +206,7 @@ public int Rows { set { if (value < 1 ) { - throw new ArgumentOutOfRangeException(nameof(Rows), string.Format(SR.InvalidLowBoundArgumentEx, "Rows", value.ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(Rows), value, 1)); } rows = value; @@ -287,7 +287,7 @@ public int StartPage { } set { if (value < 0 ) { - throw new ArgumentOutOfRangeException(nameof(StartPage), string.Format(SR.InvalidLowBoundArgumentEx, "StartPage", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(StartPage), value, 0)); } int oldValue = StartPage; startPage = value; @@ -356,7 +356,7 @@ private int AdjustScroll(Message m, int pos, int maxPos, bool horizontal) { case NativeMethods.SB_THUMBPOSITION: case NativeMethods.SB_THUMBTRACK: NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); - si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); + si.cbSize = Marshal.SizeOf(); si.fMask = NativeMethods.SIF_TRACKPOS; int direction = horizontal ? NativeMethods.SB_HORZ : NativeMethods.SB_VERT; if (SafeNativeMethods.GetScrollInfo(new HandleRef(this, m.HWnd), direction, si)) @@ -451,7 +451,6 @@ private void ComputePreview() { document.PrintController = new PrintControllerWithStatusDialog(previewController, string.Format(SR.PrintControllerWithStatusDialog_DialogTitlePreview)); - // Want to make sure we've reverted any security asserts before we call Print -- that calls into user code document.Print(); pageInfo = previewController.GetPreviewPageInfo(); Debug.Assert(pageInfo != null, "ReviewPrintController did not give us preview info"); @@ -906,15 +905,15 @@ private void WmKeyDown(ref Message msg) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_VSCROLL: + case Interop.WindowMessages.WM_VSCROLL: WmVScroll(ref m); break; - case NativeMethods.WM_HSCROLL: + case Interop.WindowMessages.WM_HSCROLL: WmHScroll(ref m); break; //added case to handle keyboard events // - case NativeMethods.WM_KEYDOWN: + case Interop.WindowMessages.WM_KEYDOWN: WmKeyDown(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewDialog.cs index 07e68bc7019..aa592a61bba 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintPreviewDialog.cs @@ -63,24 +63,15 @@ public class PrintPreviewDialog : Form { /// Initializes a new instance of the class. /// public PrintPreviewDialog() { - #pragma warning disable 618 base.AutoScaleBaseSize = new Size(5, 13); #pragma warning restore 618 - - this.previewControl = new PrintPreviewControl(); this.imageList = new ImageList(); - - Bitmap bitmaps = new Bitmap(typeof(PrintPreviewDialog), "PrintPreviewStrip.bmp"); - bitmaps.MakeTransparent(); - imageList.Images.AddStrip(bitmaps); - + imageList.Images.AddStrip(DpiHelper.GetBitmapFromIcon(typeof(PrintPreviewDialog), "PrintPreviewStrip")); InitForm(); - - } //subhag addition diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ProgressBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ProgressBar.cs index 7691d2d2b3b..1d9e0c8bc55 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ProgressBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ProgressBar.cs @@ -387,7 +387,7 @@ public int Maximum { // Message: '%1' is not a valid value for '%0'. '%0' must be greater than %2. // Should this set a boundary for the top end too? if (value < 0) - throw new ArgumentOutOfRangeException(nameof(Maximum), string.Format(SR.InvalidLowBoundArgumentEx, "Maximum", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(Maximum), value, 0)); if (minimum > value) minimum = value; @@ -425,7 +425,7 @@ public int Minimum { // Message: '%1' is not a valid value for '%0'. '%0' must be greater than %2. // Should this set a boundary for the top end too? if (value < 0) - throw new ArgumentOutOfRangeException(nameof(Minimum), string.Format(SR.InvalidLowBoundArgumentEx, "Minimum", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(Minimum), value, 0)); if (maximum < value) maximum = value; minimum = value; @@ -612,7 +612,7 @@ public int Value { set { if (this.value != value) { if ((value < minimum) || (value > maximum)) - throw new ArgumentOutOfRangeException(nameof(Value), string.Format(SR.InvalidBoundArgument, "Value", value.ToString(CultureInfo.CurrentCulture), "'minimum'", "'maximum'")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(Value), value, "'minimum'", "'maximum'")); this.value = value; UpdatePos() ; } @@ -841,11 +841,7 @@ internal override bool ShouldSerializeForeColor() { return ForeColor != defaultForeColor; } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// /// @@ -855,7 +851,7 @@ internal override bool SupportsUiaProviders { public override string ToString() { string s = base.ToString(); - return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + Value.ToString(CultureInfo.CurrentCulture); + return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + value; } /// @@ -889,11 +885,7 @@ private void UserPreferenceChangedHandler(object o, UserPreferenceChangedEventAr /// AccessibleObject for this ProgressBar instance. /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ProgressBarAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ProgressBarAccessibleObject(this); } [ComVisible(true)] @@ -910,13 +902,7 @@ private ProgressBar OwningProgressBar } } - internal override bool IsIAccessibleExSupported() { - if (AccessibilityImprovements.Level3) { - return true; - } - - return base.IsIAccessibleExSupported(); - } + internal override bool IsIAccessibleExSupported() => true; internal override bool IsPatternSupported(int patternId) { if (patternId == NativeMethods.UIA_ValuePatternId || diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGrid.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGrid.cs index aa0d60271e9..1af10070a3c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGrid.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGrid.cs @@ -12,6 +12,7 @@ namespace System.Windows.Forms { using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Drawing.Design; + using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Reflection; @@ -81,8 +82,7 @@ public class PropertyGrid : ContainerControl, IComPropertyBrowser, UnsafeNativeM private object[] currentObjects; private int paintFrozen; - private Color lineColor = SystemInformation.HighContrast ? (AccessibilityImprovements.Level1 ? SystemColors.ControlDarkDark : SystemColors.ControlDark ) - : SystemColors.InactiveBorder; + private Color lineColor = SystemInformation.HighContrast ? SystemColors.ControlDarkDark : SystemColors.InactiveBorder; internal bool developerOverride = false; internal Brush lineBrush = null; private Color categoryForeColor = SystemColors.ControlText; @@ -202,7 +202,7 @@ public PropertyGrid() { separator1 = CreateSeparatorButton(); separator2 = CreateSeparatorButton(); - toolStrip = AccessibilityImprovements.Level3 ? new PropertyGridToolStrip(this) : new ToolStrip(); + toolStrip = new PropertyGridToolStrip(this); toolStrip.SuspendLayout(); toolStrip.ShowItemToolTips = true; toolStrip.AccessibleName = SR.PropertyGridToolbarAccessibleName; @@ -699,7 +699,7 @@ protected bool DrawFlatToolbar { SetToolStripRenderer(); } - SetHotCommandColors(value && !AccessibilityImprovements.Level2); + SetHotCommandColors(false); } } @@ -734,7 +734,7 @@ private bool FreezePainting { if (value && IsHandleCreated && this.Visible) { if (0 == paintFrozen++) { - SendMessage(NativeMethods.WM_SETREDRAW, 0, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, 0, 0); } } if (!value) { @@ -743,7 +743,7 @@ private bool FreezePainting { } if (0 == --paintFrozen) { - SendMessage(NativeMethods.WM_SETREDRAW, 1, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, 1, 0); Invalidate(true); } @@ -1589,8 +1589,9 @@ public Color ViewBorderColor { } private int AddImage(Bitmap image) { - - image.MakeTransparent(); + if (image.RawFormat.Guid != ImageFormat.Icon.Guid) { + image.MakeTransparent(); + } // Resize bitmap only if resizing is needed in order to avoid image distortion. if (DpiHelper.IsScalingRequired && (image.Size.Width != normalButtonSize.Width || image.Size.Height != normalButtonSize.Height)) { image = DpiHelper.CreateResizedBitmap(image, normalButtonSize); @@ -1920,11 +1921,7 @@ internal void ClearTabs(PropertyTabScope tabScope) { /// /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new PropertyGridAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new PropertyGridAccessibleObject(this); } private /*protected virtual*/ PropertyGridView CreateGridView(IServiceProvider sp) { @@ -2029,10 +2026,8 @@ private ToolStripButton CreatePushButton(string toolTipText, int imageIndex, Eve button.Click += eventHandler; button.ImageScaling = ToolStripItemImageScaling.SizeToFit; - if (AccessibilityImprovements.Level1) { - if (useCheckButtonRole) { - button.AccessibleRole = AccessibleRole.CheckButton; - } + if (useCheckButtonRole) { + button.AccessibleRole = AccessibleRole.CheckButton; } return button; @@ -2393,7 +2388,6 @@ private void AddLargeImage(Bitmap originalBitmap) { Bitmap largeBitmap = null; try { Bitmap transparentBitmap = new Bitmap(originalBitmap); - transparentBitmap.MakeTransparent(); largeBitmap = DpiHelper.CreateResizedBitmap(transparentBitmap, largeButtonSize); transparentBitmap.Dispose(); @@ -3236,27 +3230,25 @@ protected virtual void OnPropertyValueChanged(PropertyValueChangedEventArgs e) { internal void OnPropertyValueSet(GridItem changedItem, object oldValue) { OnPropertyValueChanged(new PropertyValueChangedEventArgs(changedItem, oldValue)); - // In Level 3 announce the property value change like standalone combobox control do: "[something] selected". - if (AccessibilityImprovements.Level3) { - bool dropDown = false; - Type propertyType = changedItem.PropertyDescriptor.PropertyType; - UITypeEditor editor = (UITypeEditor)TypeDescriptor.GetEditor(propertyType, typeof(UITypeEditor)); - if (editor != null) { - dropDown = editor.GetEditStyle() == UITypeEditorEditStyle.DropDown; - } - else { - var gridEntry = changedItem as GridEntry; - if (gridEntry != null && gridEntry.Enumerable) { - dropDown = true; - } + // Announce the property value change like standalone combobox control do: "[something] selected". + bool dropDown = false; + Type propertyType = changedItem.PropertyDescriptor.PropertyType; + UITypeEditor editor = (UITypeEditor)TypeDescriptor.GetEditor(propertyType, typeof(UITypeEditor)); + if (editor != null) { + dropDown = editor.GetEditStyle() == UITypeEditorEditStyle.DropDown; + } + else { + var gridEntry = changedItem as GridEntry; + if (gridEntry != null && gridEntry.Enumerable) { + dropDown = true; } + } - if (dropDown && !gridView.DropDownVisible) { - this.AccessibilityObject.RaiseAutomationNotification( - Automation.AutomationNotificationKind.ActionCompleted, - Automation.AutomationNotificationProcessing.All, - string.Format(SR.PropertyGridPropertyValueSelectedFormat, changedItem.Value)); - } + if (dropDown && !gridView.DropDownVisible) { + this.AccessibilityObject.RaiseAutomationNotification( + Automation.AutomationNotificationKind.ActionCompleted, + Automation.AutomationNotificationProcessing.All, + string.Format(SR.PropertyGridPropertyValueSelectedFormat, changedItem.Value)); } } @@ -3618,11 +3610,10 @@ protected override bool ProcessDialogKey(Keys keyData) else if (gridView.FocusInside) { if (toolStrip.Visible) { toolStrip.FocusInternal(); - if (AccessibilityImprovements.Level1) { - // we need to select first ToolStrip item, otherwise, ToolStrip container has the focus - if (toolStrip.Items.Count > 0) { - toolStrip.SelectNextToolStripItem(null, /*forward =*/ true); - } + + // we need to select first ToolStrip item, otherwise, ToolStrip container has the focus + if (toolStrip.Items.Count > 0) { + toolStrip.SelectNextToolStripItem(null, /*forward =*/ true); } } else { @@ -4199,7 +4190,7 @@ private void SetSelectState(int state) { } private void SetToolStripRenderer() { - if (DrawFlatToolbar || (SystemInformation.HighContrast && AccessibilityImprovements.Level1)) { + if (DrawFlatToolbar || SystemInformation.HighContrast) { // use an office look and feel with system colors ProfessionalColorTable colorTable = new ProfessionalColorTable(); colorTable.UseSystemColors = true; @@ -4413,7 +4404,7 @@ protected void ShowEventsButton(bool value) { ] protected virtual Bitmap SortByPropertyImage { get { - return new Bitmap(typeof(PropertyGrid), "PBAlpha.bmp"); + return DpiHelper.GetBitmapFromIcon(typeof(PropertyGrid), "PBAlpha"); } } @@ -4428,7 +4419,7 @@ protected virtual Bitmap SortByPropertyImage { ] protected virtual Bitmap SortByCategoryImage { get { - return new Bitmap(typeof(PropertyGrid), "PBCatego.bmp"); + return DpiHelper.GetBitmapFromIcon(typeof(PropertyGrid), "PBCatego"); } } @@ -4443,7 +4434,7 @@ protected virtual Bitmap SortByCategoryImage { ] protected virtual Bitmap ShowPropertyPageImage { get { - return new Bitmap(typeof(PropertyGrid), "PBPPage.bmp"); + return DpiHelper.GetBitmapFromIcon(typeof(PropertyGrid), "PBPPage"); } } @@ -4620,11 +4611,7 @@ public bool UseCompatibleTextRendering { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces. /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// /// Determines whether the control supports rendering text using GDI+ and GDI. @@ -4656,7 +4643,7 @@ internal bool WantsTab(bool forward) { private int dwMsg; private void GetDataFromCopyData(IntPtr lparam) { - NativeMethods.COPYDATASTRUCT cds = (NativeMethods.COPYDATASTRUCT)UnsafeNativeMethods.PtrToStructure(lparam, typeof(NativeMethods.COPYDATASTRUCT)); + NativeMethods.COPYDATASTRUCT cds = Marshal.PtrToStructure(lparam); if (cds != null && cds.lpData != IntPtr.Zero) { propName = Marshal.PtrToStringAuto(cds.lpData); @@ -4712,7 +4699,7 @@ protected override void RescaleConstantsForDpi(int deviceDpiOld, int deviceDpiNe protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_UNDO: + case Interop.WindowMessages.WM_UNDO: if ((long)m.LParam == 0) { gridView.DoUndoCommand(); } @@ -4720,7 +4707,7 @@ protected override void WndProc(ref Message m) { m.Result = CanUndo ? (IntPtr)1 : (IntPtr)0; } return; - case NativeMethods.WM_CUT: + case Interop.WindowMessages.WM_CUT: if ((long)m.LParam == 0) { gridView.DoCutCommand(); } @@ -4729,7 +4716,7 @@ protected override void WndProc(ref Message m) { } return; - case NativeMethods.WM_COPY: + case Interop.WindowMessages.WM_COPY: if ((long)m.LParam == 0) { gridView.DoCopyCommand(); } @@ -4738,7 +4725,7 @@ protected override void WndProc(ref Message m) { } return; - case NativeMethods.WM_PASTE: + case Interop.WindowMessages.WM_PASTE: if ((long)m.LParam == 0) { gridView.DoPasteCommand(); } @@ -4747,7 +4734,7 @@ protected override void WndProc(ref Message m) { } return; - case NativeMethods.WM_COPYDATA: + case Interop.WindowMessages.WM_COPYDATA: GetDataFromCopyData(m.LParam); m.Result = (IntPtr)1; return; @@ -5125,17 +5112,16 @@ public static TextFormatFlags GetTextRendererFlags(){ } internal static class AutomationMessages { - private const int WM_USER = NativeMethods.WM_USER; - internal const int PGM_GETBUTTONCOUNT = WM_USER + 0x50; - internal const int PGM_GETBUTTONSTATE = WM_USER + 0x52; - internal const int PGM_SETBUTTONSTATE = WM_USER + 0x51; - internal const int PGM_GETBUTTONTEXT = WM_USER + 0x53; - internal const int PGM_GETBUTTONTOOLTIPTEXT = WM_USER + 0x54; - internal const int PGM_GETROWCOORDS = WM_USER + 0x55; - internal const int PGM_GETVISIBLEROWCOUNT = WM_USER + 0x56; - internal const int PGM_GETSELECTEDROW = WM_USER + 0x57; - internal const int PGM_SETSELECTEDTAB = WM_USER + 0x58; // DO NOT CHANGE THIS : VC uses it! - internal const int PGM_GETTESTINGINFO = WM_USER + 0x59; + internal const int PGM_GETBUTTONCOUNT = Interop.WindowMessages.WM_USER + 0x50; + internal const int PGM_GETBUTTONSTATE = Interop.WindowMessages.WM_USER + 0x52; + internal const int PGM_SETBUTTONSTATE = Interop.WindowMessages.WM_USER + 0x51; + internal const int PGM_GETBUTTONTEXT = Interop.WindowMessages.WM_USER + 0x53; + internal const int PGM_GETBUTTONTOOLTIPTEXT = Interop.WindowMessages.WM_USER + 0x54; + internal const int PGM_GETROWCOORDS = Interop.WindowMessages.WM_USER + 0x55; + internal const int PGM_GETVISIBLEROWCOUNT = Interop.WindowMessages.WM_USER + 0x56; + internal const int PGM_GETSELECTEDROW = Interop.WindowMessages.WM_USER + 0x57; + internal const int PGM_SETSELECTEDTAB = Interop.WindowMessages.WM_USER + 0x58; // DO NOT CHANGE THIS : VC uses it! + internal const int PGM_GETTESTINGINFO = Interop.WindowMessages.WM_USER + 0x59; /// /// Writes the specified text into a temporary file of the form %TEMP%\"Maui.[file id].log", where @@ -5448,11 +5434,7 @@ public PropertyGridToolStrip(PropertyGrid parentPropertyGrid) { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces. /// - internal override bool SupportsUiaProviders { - get { - return true; - } - } + internal override bool SupportsUiaProviders => true; /// /// Constructs the new instance of the accessibility object for this control. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/CategoryGridEntry.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/CategoryGridEntry.cs index 8a5fe4be997..c7cde0f28bb 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/CategoryGridEntry.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/CategoryGridEntry.cs @@ -108,11 +108,7 @@ public override int PropertyDepth { /// /// protected override GridEntryAccessibleObject GetAccessibilityObject() { - if (AccessibilityImprovements.Level3) { - return new CategoryGridEntryAccessibleObject(this); - } - - return base.GetAccessibilityObject(); + return new CategoryGridEntryAccessibleObject(this); } protected override Brush GetBackgroundBrush(Graphics g) { @@ -210,7 +206,7 @@ public override void PaintLabel(System.Drawing.Graphics g, Rectangle rect, Recta int indent = PropertyLabelIndent-2; Rectangle focusRect = new Rectangle(indent, rect.Y, labelWidth+3, rect.Height-1); - if (SystemInformation.HighContrast && !OwnerGrid.developerOverride && AccessibilityImprovements.Level1) { + if (SystemInformation.HighContrast && !OwnerGrid.developerOverride) { // we changed line color to SystemColors.ControlDarkDark in high contrast mode ControlPaint.DrawFocusRectangle(g, focusRect, SystemColors.ControlText, OwnerGrid.LineColor); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DocComment.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DocComment.cs index 6a36664e4c8..ae2b25b0214 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DocComment.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DocComment.cs @@ -197,22 +197,14 @@ public override int SnapHeightRequest(int cyNew) { /// /// The accessibility object for this control. protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new DocCommentAccessibleObject(this, ownerGrid); - } - - return base.CreateAccessibilityInstance(); + return new DocCommentAccessibleObject(this, ownerGrid); } /// /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces. /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; internal void UpdateTextRenderingEngine() { m_labelTitle.UseCompatibleTextRendering = this.ownerGrid.UseCompatibleTextRendering; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DropDownButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DropDownButton.cs index 9196c64cf24..09635aeee26 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DropDownButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/DropDownButton.cs @@ -42,19 +42,14 @@ public bool IgnoreMouse { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces. /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; public bool UseComboBoxTheme { set { if (useComboBoxTheme != value) { useComboBoxTheme = value; - if (AccessibilityImprovements.Level1) { - SetAccessibleName(); - } + SetAccessibleName(); + Invalidate(); } } @@ -103,14 +98,12 @@ protected override void OnPaint(PaintEventArgs pevent) { ComboBoxRenderer.DrawDropDownButtonForHandle(pevent.Graphics, dropDownButtonRect, cbState, this.HandleInternal); } - if (AccessibilityImprovements.Level1) { - // Redraw focus cues - // For consistency with other PropertyGrid buttons, i.e. those opening system dialogs ("..."), that always show visual cues when focused, - // we need to do the same for this custom button, painted as ComboBox control part (drop-down). - if (Focused) { - dropDownButtonRect.Inflate(-1, -1); - ControlPaint.DrawFocusRectangle(pevent.Graphics, dropDownButtonRect, ForeColor, BackColor); - } + // Redraw focus cues + // For consistency with other PropertyGrid buttons, i.e. those opening system dialogs ("..."), that always show visual cues when focused, + // we need to do the same for this custom button, painted as ComboBox control part (drop-down). + if (Focused) { + dropDownButtonRect.Inflate(-1, -1); + ControlPaint.DrawFocusRectangle(pevent.Graphics, dropDownButtonRect, ForeColor, BackColor); } } } @@ -122,7 +115,7 @@ internal void PerformButtonClick() { } private void SetAccessibleName() { - if (AccessibilityImprovements.Level1 && useComboBoxTheme) { + if (useComboBoxTheme) { this.AccessibleName = SR.PropertyGridDropDownButtonComboBoxAccessibleName; } else { @@ -135,11 +128,7 @@ private void SetAccessibleName() { /// /// The accessibility object for this control. protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new DropDownButtonAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new DropDownButtonAccessibleObject(this); } internal override ButtonBaseAdapter CreateStandardAdapter() { @@ -209,7 +198,7 @@ internal override void PaintUp(PaintEventArgs pevent, CheckState state) { } internal override void DrawImageCore(Graphics graphics, Image image, Rectangle imageBounds, Point imageStart, ButtonBaseAdapter.LayoutData layout) { - ControlPaint.DrawImageReplaceColor(graphics, image, imageBounds, Color.Black, this.IsHighContrastHighlighted3() && !this.Control.MouseIsDown ? SystemColors.HighlightText : Control.ForeColor); + ControlPaint.DrawImageReplaceColor(graphics, image, imageBounds, Color.Black, this.IsHighContrastHighlighted() && !this.Control.MouseIsDown ? SystemColors.HighlightText : Control.ForeColor); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridEntry.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridEntry.cs index 02ef1525b01..2f89e6b7816 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridEntry.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridEntry.cs @@ -172,7 +172,7 @@ private int OutlineIconPadding { private bool colorInversionNeededInHC { get { - return SystemInformation.HighContrast && !OwnerGrid.developerOverride && AccessibilityImprovements.Level1; + return SystemInformation.HighContrast && !OwnerGrid.developerOverride; } } @@ -450,20 +450,18 @@ internal virtual bool InternalExpanded { } } - if (AccessibilityImprovements.Level1) { - // Notify accessibility clients of expanded state change - // StateChange requires NameChange, too - accessible clients won't see this, unless both events are raised + // Notify accessibility clients of expanded state change + // StateChange requires NameChange, too - accessible clients won't see this, unless both events are raised - // Root item is hidden and should not raise events - if (GridItemType != GridItemType.Root) { - int id = ((PropertyGridView)GridEntryHost).AccessibilityGetGridEntryChildID(this); - if (id >= 0) { - PropertyGridView.PropertyGridViewAccessibleObject gridAccObj = - (PropertyGridView.PropertyGridViewAccessibleObject)((PropertyGridView)GridEntryHost).AccessibilityObject; + // Root item is hidden and should not raise events + if (GridItemType != GridItemType.Root) { + int id = ((PropertyGridView)GridEntryHost).AccessibilityGetGridEntryChildID(this); + if (id >= 0) { + PropertyGridView.PropertyGridViewAccessibleObject gridAccObj = + (PropertyGridView.PropertyGridViewAccessibleObject)((PropertyGridView)GridEntryHost).AccessibilityObject; - gridAccObj.NotifyClients(AccessibleEvents.StateChange, id); - gridAccObj.NotifyClients(AccessibleEvents.NameChange, id); - } + gridAccObj.NotifyClients(AccessibleEvents.StateChange, id); + gridAccObj.NotifyClients(AccessibleEvents.NameChange, id); } } } @@ -586,9 +584,7 @@ public bool Focus { gridAccObj.NotifyClients(AccessibleEvents.Focus, id); gridAccObj.NotifyClients(AccessibleEvents.Selection, id); - if (AccessibilityImprovements.Level3) { - AccessibilityObject.SetFocus(); - } + AccessibilityObject.SetFocus(); } } } @@ -2757,12 +2753,7 @@ public override string Description { public override string Help { get { - if (AccessibilityImprovements.Level1) { - return owner.PropertyDescription; - } - else { - return base.Help; - } + return owner.PropertyDescription; } } @@ -2772,25 +2763,23 @@ public override string Help { /// Indicates the direction in which to navigate. /// Returns the element in the specified direction. internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) { - if (AccessibilityImprovements.Level3) { - switch(direction) { - case UnsafeNativeMethods.NavigateDirection.Parent: - var parentGridEntry = owner.ParentGridEntry; - if (parentGridEntry != null) { - if (parentGridEntry is SingleSelectRootGridEntry) { - return owner.OwnerGrid.GridViewAccessibleObject; - } - else { - return parentGridEntry.AccessibilityObject; - } + switch(direction) { + case UnsafeNativeMethods.NavigateDirection.Parent: + var parentGridEntry = owner.ParentGridEntry; + if (parentGridEntry != null) { + if (parentGridEntry is SingleSelectRootGridEntry) { + return owner.OwnerGrid.GridViewAccessibleObject; + } + else { + return parentGridEntry.AccessibilityObject; } + } - return Parent; - case UnsafeNativeMethods.NavigateDirection.PreviousSibling: - return Navigate(AccessibleNavigation.Previous); - case UnsafeNativeMethods.NavigateDirection.NextSibling: - return Navigate(AccessibleNavigation.Next); - } + return Parent; + case UnsafeNativeMethods.NavigateDirection.PreviousSibling: + return Navigate(AccessibleNavigation.Previous); + case UnsafeNativeMethods.NavigateDirection.NextSibling: + return Navigate(AccessibleNavigation.Next); } return base.FragmentNavigate(direction); @@ -2801,18 +2790,14 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga /// internal override UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRoot { get { - if (AccessibilityImprovements.Level3) { - return (PropertyGridView.PropertyGridViewAccessibleObject)Parent; - } - - return base.FragmentRoot; + return (PropertyGridView.PropertyGridViewAccessibleObject)Parent; } } #region IAccessibleEx - patterns and properties internal override bool IsIAccessibleExSupported() { - if (owner.Expandable && AccessibilityImprovements.Level1) { + if (owner.Expandable) { return true; } else { @@ -2845,47 +2830,39 @@ internal override object GetPropertyValue(int propertyID) { case NativeMethods.UIA_NamePropertyId: return Name; case NativeMethods.UIA_ControlTypePropertyId: - if (AccessibilityImprovements.Level3) { - // In Level 3 the accessible hierarchy is changed so we cannot use Button type - // for the grid items to not break automation logic that searches for the first - // button in the PropertyGridView to show dialog/drop-down. In Level < 3 action - // button is one of the first children of PropertyGridView. - return NativeMethods.UIA_DataItemControlTypeId; - } - - return NativeMethods.UIA_ButtonControlTypeId; + // The accessible hierarchy is changed so we cannot use Button type + // for the grid items to not break automation logic that searches for the first + // button in the PropertyGridView to show dialog/drop-down. In Level < 3 action + // button is one of the first children of PropertyGridView. + return NativeMethods.UIA_DataItemControlTypeId; case NativeMethods.UIA_IsExpandCollapsePatternAvailablePropertyId: return (Object)IsPatternSupported(NativeMethods.UIA_ExpandCollapsePatternId); } - if (AccessibilityImprovements.Level3) { - switch (propertyID) { - case NativeMethods.UIA_AccessKeyPropertyId: - return string.Empty; - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - return owner.hasFocus; - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - return (this.State & AccessibleStates.Focusable) == AccessibleStates.Focusable; - case NativeMethods.UIA_IsEnabledPropertyId: - return true; - case NativeMethods.UIA_AutomationIdPropertyId: - return GetHashCode().ToString(); - case NativeMethods.UIA_HelpTextPropertyId: - return Help ?? string.Empty; - case NativeMethods.UIA_IsPasswordPropertyId: - return false; - case NativeMethods.UIA_IsOffscreenPropertyId: - return (this.State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; - case NativeMethods.UIA_LegacyIAccessibleRolePropertyId: - return Role; - case NativeMethods.UIA_LegacyIAccessibleDefaultActionPropertyId: - return DefaultAction; - default: - return base.GetPropertyValue(propertyID); - } + switch (propertyID) { + case NativeMethods.UIA_AccessKeyPropertyId: + return string.Empty; + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + return owner.hasFocus; + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + return (this.State & AccessibleStates.Focusable) == AccessibleStates.Focusable; + case NativeMethods.UIA_IsEnabledPropertyId: + return true; + case NativeMethods.UIA_AutomationIdPropertyId: + return GetHashCode().ToString(); + case NativeMethods.UIA_HelpTextPropertyId: + return Help ?? string.Empty; + case NativeMethods.UIA_IsPasswordPropertyId: + return false; + case NativeMethods.UIA_IsOffscreenPropertyId: + return (this.State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen; + case NativeMethods.UIA_LegacyIAccessibleRolePropertyId: + return Role; + case NativeMethods.UIA_LegacyIAccessibleDefaultActionPropertyId: + return DefaultAction; + default: + return base.GetPropertyValue(propertyID); } - - return null; } internal override bool IsPatternSupported(int patternId) { @@ -2894,9 +2871,8 @@ internal override bool IsPatternSupported(int patternId) { return true; } - if (AccessibilityImprovements.Level3 && ( - patternId == NativeMethods.UIA_InvokePatternId || - patternId == NativeMethods.UIA_LegacyIAccessiblePatternId)) { + if (patternId == NativeMethods.UIA_InvokePatternId || + patternId == NativeMethods.UIA_LegacyIAccessiblePatternId) { return true; } @@ -2952,19 +2928,7 @@ private PropertyGridView PropertyGridView { public override AccessibleRole Role { get { - if (AccessibilityImprovements.Level3) { - return AccessibleRole.Cell; - } - else if (AccessibilityImprovements.Level1) { - if (owner.Expandable) { - return AccessibleRole.ButtonDropDownGrid; - } - else { - return AccessibleRole.Cell; - } - } - - return AccessibleRole.Row; + return AccessibleRole.Cell; } } @@ -3095,9 +3059,7 @@ public override void Select(AccessibleSelection flags) { internal override void SetFocus() { base.SetFocus(); - if (AccessibilityImprovements.Level3) { - RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); - } + RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridErrorDlg.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridErrorDlg.cs index ef4e2a7ce9e..320b738caab 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridErrorDlg.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridErrorDlg.cs @@ -73,13 +73,11 @@ public string Message { ] public GridErrorDlg(PropertyGrid owner) { ownerGrid = owner; - expandImage = new Bitmap(typeof(ThreadExceptionDialog), "down.bmp"); - expandImage.MakeTransparent(); + expandImage = DpiHelper.GetBitmapFromIcon(typeof(ThreadExceptionDialog), "down"); if (DpiHelper.IsScalingRequired) { DpiHelper.ScaleBitmapLogicalToDevice(ref expandImage); } - collapseImage = new Bitmap(typeof(ThreadExceptionDialog), "up.bmp"); - collapseImage.MakeTransparent(); + collapseImage = DpiHelper.GetBitmapFromIcon(typeof(ThreadExceptionDialog), "up"); if (DpiHelper.IsScalingRequired) { DpiHelper.ScaleBitmapLogicalToDevice(ref collapseImage); } @@ -123,14 +121,12 @@ private void DetailsClick(object sender, EventArgs devent) { details.Visible = !details.Visible; - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.StateChange, -1); - AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); - details.TabStop = !details.TabStop; + AccessibilityNotifyClients(AccessibleEvents.StateChange, -1); + AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); + details.TabStop = !details.TabStop; - if (details.Visible) { - details.Focus(); - } + if (details.Visible) { + details.Focus(); } } @@ -358,12 +354,7 @@ public bool Expanded { } } protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level1) { - return new DetailsButtonAccessibleObject(this); - } - else { - return base.CreateAccessibilityInstance(); - } + return new DetailsButtonAccessibleObject(this); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridToolTip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridToolTip.cs index ac3d847e2be..e5ecbb30481 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridToolTip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/GridToolTip.cs @@ -114,7 +114,7 @@ private NativeMethods.TOOLINFO_T GetTOOLINFO(Control c) { if (toolInfos[index] == null){ toolInfos[index] = new NativeMethods.TOOLINFO_T(); - toolInfos[index].cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); + toolInfos[index].cbSize = Marshal.SizeOf(); toolInfos[index].uFlags |= NativeMethods.TTF_IDISHWND | NativeMethods.TTF_TRANSPARENT | NativeMethods.TTF_SUBCLASS; } toolInfos[index].lpszText = this.toolTipText; @@ -196,12 +196,12 @@ public void Reset(){ protected override void WndProc(ref Message msg) { switch (msg.Msg) { - case NativeMethods.WM_SHOWWINDOW: + case Interop.WindowMessages.WM_SHOWWINDOW: if (unchecked( (int) (long)msg.WParam) != 0 && dontShow){ msg.WParam = IntPtr.Zero; } break; - case NativeMethods.WM_NCHITTEST: + case Interop.WindowMessages.WM_NCHITTEST: // When using v6 common controls, the native // tooltip does not end up returning HTTRANSPARENT all the time, so its TTF_TRANSPARENT // behavior does not work, ie. mouse events do not fall thru to controls underneath. This diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/HotCommands.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/HotCommands.cs index 78f8a7bb3a5..fe9b04e7f32 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/HotCommands.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/HotCommands.cs @@ -52,11 +52,7 @@ public virtual bool AllowVisible { /// /// The accessibility object for this control. protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new HotCommandsAccessibleObject(this, ownerGrid); - } - - return base.CreateAccessibilityInstance(); + return new HotCommandsAccessibleObject(this, ownerGrid); } public override Rectangle DisplayRectangle { @@ -108,11 +104,7 @@ public override int SnapHeightRequest(int request) { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces. /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; private void LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { try diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyDescriptorGridEntry.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyDescriptorGridEntry.cs index 6bf99411b52..03a0cb74bbb 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyDescriptorGridEntry.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyDescriptorGridEntry.cs @@ -1019,11 +1019,7 @@ static private void ShowCodeIdle(object sender, EventArgs e) { /// AccessibleObject for this PropertyDescriptorGridEntry instance. /// protected override GridEntryAccessibleObject GetAccessibilityObject() { - if (AccessibilityImprovements.Level2) { - return new PropertyDescriptorGridEntryAccessibleObject(this); - } - - return base.GetAccessibilityObject(); + return new PropertyDescriptorGridEntryAccessibleObject(this); } [ComVisible(true)] @@ -1035,9 +1031,7 @@ public PropertyDescriptorGridEntryAccessibleObject(PropertyDescriptorGridEntry o _owningPropertyDescriptorGridEntry = owner; } - internal override bool IsIAccessibleExSupported() { - return true; - } + internal override bool IsIAccessibleExSupported() => true; /// /// Returns the element in the specified direction. @@ -1045,23 +1039,21 @@ internal override bool IsIAccessibleExSupported() { /// Indicates the direction in which to navigate. /// Returns the element in the specified direction. internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) { - if (AccessibilityImprovements.Level3) { - switch (direction) { - case UnsafeNativeMethods.NavigateDirection.NextSibling: - var propertyGridViewAccessibleObject = (PropertyGridView.PropertyGridViewAccessibleObject)Parent; - var propertyGridView = propertyGridViewAccessibleObject.Owner as PropertyGridView; - bool currentGridEntryFound = false; - return propertyGridViewAccessibleObject.GetNextGridEntry(_owningPropertyDescriptorGridEntry, propertyGridView.TopLevelGridEntries, out currentGridEntryFound); - case UnsafeNativeMethods.NavigateDirection.PreviousSibling: - propertyGridViewAccessibleObject = (PropertyGridView.PropertyGridViewAccessibleObject)Parent; - propertyGridView = propertyGridViewAccessibleObject.Owner as PropertyGridView; - currentGridEntryFound = false; - return propertyGridViewAccessibleObject.GetPreviousGridEntry(_owningPropertyDescriptorGridEntry, propertyGridView.TopLevelGridEntries, out currentGridEntryFound); - case UnsafeNativeMethods.NavigateDirection.FirstChild: - return GetFirstChild(); - case UnsafeNativeMethods.NavigateDirection.LastChild: - return GetLastChild(); - } + switch (direction) { + case UnsafeNativeMethods.NavigateDirection.NextSibling: + var propertyGridViewAccessibleObject = (PropertyGridView.PropertyGridViewAccessibleObject)Parent; + var propertyGridView = propertyGridViewAccessibleObject.Owner as PropertyGridView; + bool currentGridEntryFound = false; + return propertyGridViewAccessibleObject.GetNextGridEntry(_owningPropertyDescriptorGridEntry, propertyGridView.TopLevelGridEntries, out currentGridEntryFound); + case UnsafeNativeMethods.NavigateDirection.PreviousSibling: + propertyGridViewAccessibleObject = (PropertyGridView.PropertyGridViewAccessibleObject)Parent; + propertyGridView = propertyGridViewAccessibleObject.Owner as PropertyGridView; + currentGridEntryFound = false; + return propertyGridViewAccessibleObject.GetPreviousGridEntry(_owningPropertyDescriptorGridEntry, propertyGridView.TopLevelGridEntries, out currentGridEntryFound); + case UnsafeNativeMethods.NavigateDirection.FirstChild: + return GetFirstChild(); + case UnsafeNativeMethods.NavigateDirection.LastChild: + return GetLastChild(); } return base.FragmentNavigate(direction); @@ -1105,7 +1097,7 @@ private UnsafeNativeMethods.IRawElementProviderFragment GetLastChild() { } internal override bool IsPatternSupported(int patternId) { - if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_ValuePatternId) { + if (patternId == NativeMethods.UIA_ValuePatternId) { return true; } @@ -1116,14 +1108,11 @@ internal override object GetPropertyValue(int propertyID) { if (propertyID == NativeMethods.UIA_IsEnabledPropertyId) { return !((PropertyDescriptorGridEntry)owner).IsPropertyReadOnly; } - - if (AccessibilityImprovements.Level3) { - if (propertyID == NativeMethods.UIA_LegacyIAccessibleDefaultActionPropertyId) { - return string.Empty; - } - else if (propertyID == NativeMethods.UIA_IsValuePatternAvailablePropertyId) { - return true; - } + else if (propertyID == NativeMethods.UIA_LegacyIAccessibleDefaultActionPropertyId) { + return string.Empty; + } + else if (propertyID == NativeMethods.UIA_IsValuePatternAvailablePropertyId) { + return true; } return base.GetPropertyValue(propertyID); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyGridView.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyGridView.cs index 479060e5915..17c72c4aa23 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyGridView.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyGridInternal/PropertyGridView.cs @@ -260,7 +260,7 @@ public bool CanUndo { if (!Edit.Visible || !Edit.Focused) { return false; } - return (0 != (int)Edit.SendMessage(NativeMethods.EM_CANUNDO, 0, 0)); + return (0 != (int)Edit.SendMessage(Interop.EditMessages.EM_CANUNDO, 0, 0)); } } @@ -275,7 +275,7 @@ internal DropDownButton DropDownButton { btnDropDown = new DropDownButton(); btnDropDown.UseComboBoxTheme = true; - Bitmap bitmap = CreateResizedBitmap("Arrow.ico", DOWNARROW_ICONWIDTH, DOWNARROW_ICONHEIGHT); + Bitmap bitmap = CreateResizedBitmap("Arrow", DOWNARROW_ICONWIDTH, DOWNARROW_ICONHEIGHT); btnDropDown.Image = bitmap; btnDropDown.BackColor = SystemColors.Control; btnDropDown.ForeColor = SystemColors.ControlText; @@ -303,7 +303,7 @@ private Button DialogButton { btnDialog.BackColor = SystemColors.Control; btnDialog.ForeColor = SystemColors.ControlText; btnDialog.TabIndex = 3; - btnDialog.Image = CreateResizedBitmap("dotdotdot.ico", DOTDOTDOT_ICONWIDTH, DOTDOTDOT_ICONHEIGHT); + btnDialog.Image = CreateResizedBitmap("dotdotdot", DOTDOTDOT_ICONWIDTH, DOTDOTDOT_ICONHEIGHT); btnDialog.Click += new EventHandler(this.OnBtnClick); btnDialog.KeyDown += new KeyEventHandler(this.OnBtnKeyDown); btnDialog.GotFocus += new EventHandler(OnDropDownButtonGotFocus); @@ -319,7 +319,7 @@ private Button DialogButton { private static Bitmap GetBitmapFromIcon(string iconName, int iconsWidth, int iconsHeight) { Size desiredSize = new Size(iconsWidth, iconsHeight); - Icon icon = new Icon(BitmapSelector.GetResourceStream(typeof(PropertyGrid), iconName), desiredSize); + Icon icon = new Icon(new Icon(typeof(PropertyGrid), iconName), desiredSize); Bitmap b = icon.ToBitmap(); icon.Dispose(); @@ -709,11 +709,7 @@ public IServiceProvider ServiceProvider { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces. /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; private int TipColumn { get{ @@ -1205,7 +1201,7 @@ public void DoPasteCommand() { public void DoUndoCommand() { if (this.CanUndo && Edit.Visible) { - Edit.SendMessage(NativeMethods.WM_UNDO, 0, 0); + Edit.SendMessage(Interop.WindowMessages.WM_UNDO, 0, 0); } } @@ -1696,7 +1692,7 @@ public bool EnsurePendingChangesCommitted() { private bool FilterEditWndProc(ref Message m) { // if it's the TAB key, we keep it since we'll give them focus with it. - if (dropDownHolder != null && dropDownHolder.Visible && m.Msg == NativeMethods.WM_KEYDOWN && (int)m.WParam != (int)Keys.Tab) { + if (dropDownHolder != null && dropDownHolder.Visible && m.Msg == Interop.WindowMessages.WM_KEYDOWN && (int)m.WParam != (int)Keys.Tab) { Control ctl = dropDownHolder.Component; if (ctl != null) { m.Result = ctl.SendMessage(m.Msg, m.WParam, m.LParam); @@ -2312,11 +2308,9 @@ private void OnChildLostFocus(object sender, EventArgs e) { } private void OnDropDownButtonGotFocus(object sender, EventArgs e) { - if (AccessibilityImprovements.Level3) { - DropDownButton dropDownButton = sender as DropDownButton; - if (dropDownButton != null) { - dropDownButton.AccessibilityObject.SetFocus(); - } + DropDownButton dropDownButton = sender as DropDownButton; + if (dropDownButton != null) { + dropDownButton.AccessibilityObject.SetFocus(); } } @@ -2345,7 +2339,7 @@ protected override void OnGotFocus(EventArgs e) { } // For empty GridView, draw a focus-indicator rectangle, just inside GridView borders - if ((totalProps <= 0) && AccessibilityImprovements.Level1) { + if (totalProps <= 0) { int doubleOffset = 2 * offset_2Units; if ((Size.Width > doubleOffset) && (Size.Height > doubleOffset)) { @@ -2507,7 +2501,7 @@ protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); // For empty GridView, clear the focus indicator that was painted in OnGotFocus() - if (totalProps <= 0 && AccessibilityImprovements.Level1) { + if (totalProps <= 0) { using (Graphics g = CreateGraphicsInternal()) { Rectangle clearRect = new Rectangle(1, 1, Size.Width - 2, Size.Height - 2); Debug.WriteLineIf(GridViewDebugPaint.TraceVerbose, "Filling empty gridview rect=" + clearRect.ToString()); @@ -2560,9 +2554,7 @@ private void OnEditGotFocus(object sender, EventArgs e) { InvalidateRow(selectedRow); (Edit.AccessibilityObject as ControlAccessibleObject).NotifyClients(AccessibleEvents.Focus); - if (AccessibilityImprovements.Level3) { - Edit.AccessibilityObject.SetFocus(); - } + Edit.AccessibilityObject.SetFocus(); } else { SelectRow(0); @@ -2718,7 +2710,7 @@ private void OnEditMouseDown(object sender, MouseEventArgs me) { if (Math.Abs(screenPoint.X - rowSelectPos.X) < SystemInformation.DoubleClickSize.Width && Math.Abs(screenPoint.Y - rowSelectPos.Y) < SystemInformation.DoubleClickSize.Height) { DoubleClickRow(selectedRow,false, ROWVALUE); - Edit.SendMessage(NativeMethods.WM_LBUTTONUP, 0, (int)(me.Y << 16 | (me.X & 0xFFFF))); + Edit.SendMessage(Interop.WindowMessages.WM_LBUTTONUP, 0, (int)(me.Y << 16 | (me.X & 0xFFFF))); Edit.SelectAll(); } rowSelectPos = Point.Empty; @@ -3048,7 +3040,7 @@ we are removing this functionality. } */ - if (AccessibilityImprovements.Level3 && selectedGridEntry.Enumerable && + if (selectedGridEntry.Enumerable && dropDownHolder != null && dropDownHolder.Visible && (keyCode == Keys.Up || keyCode == Keys.Down)) { @@ -3544,8 +3536,8 @@ private void OnGridEntryValueClick(object s, EventArgs e) { Point editPoint = PointToScreen(lastMouseDown); editPoint = Edit.PointToClientInternal(editPoint); - Edit.SendMessage(NativeMethods.WM_LBUTTONDOWN, 0, (int)(editPoint.Y << 16 | (editPoint.X & 0xFFFF))); - Edit.SendMessage(NativeMethods.WM_LBUTTONUP, 0, (int)(editPoint.Y << 16 | (editPoint.X & 0xFFFF))); + Edit.SendMessage(Interop.WindowMessages.WM_LBUTTONDOWN, 0, (int)(editPoint.Y << 16 | (editPoint.X & 0xFFFF))); + Edit.SendMessage(Interop.WindowMessages.WM_LBUTTONUP, 0, (int)(editPoint.Y << 16 | (editPoint.X & 0xFFFF))); } if (setSelectTime) { @@ -4902,8 +4894,8 @@ private void ShowFormatExceptionMessage(string propName, object value, Exception NativeMethods.MSG mouseMsg = new NativeMethods.MSG(); while (UnsafeNativeMethods.PeekMessage(ref mouseMsg, NativeMethods.NullHandleRef, - NativeMethods.WM_MOUSEFIRST, - NativeMethods.WM_MOUSELAST, + Interop.WindowMessages.WM_MOUSEFIRST, + Interop.WindowMessages.WM_MOUSELAST, NativeMethods.PM_REMOVE)) ; @@ -4985,8 +4977,8 @@ internal void ShowInvalidMessage(string propName, object value, Exception ex) { NativeMethods.MSG mouseMsg = new NativeMethods.MSG(); while (UnsafeNativeMethods.PeekMessage(ref mouseMsg, NativeMethods.NullHandleRef, - NativeMethods.WM_MOUSEFIRST, - NativeMethods.WM_MOUSELAST, + Interop.WindowMessages.WM_MOUSEFIRST, + Interop.WindowMessages.WM_MOUSELAST, NativeMethods.PM_REMOVE)) ; @@ -5123,11 +5115,11 @@ private void UpdateUIBasedOnFont(bool layoutRequired) { if (btnDialog != null) { DialogButton.Size = DropDownButton.Size; if (isScalingRequirementMet) { - btnDialog.Image = CreateResizedBitmap("dotdotdot.ico", DOTDOTDOT_ICONWIDTH, DOTDOTDOT_ICONHEIGHT); + btnDialog.Image = CreateResizedBitmap("dotdotdot", DOTDOTDOT_ICONWIDTH, DOTDOTDOT_ICONHEIGHT); } } if (isScalingRequirementMet) { - btnDropDown.Image = CreateResizedBitmap("Arrow.ico", DOWNARROW_ICONWIDTH, DOWNARROW_ICONHEIGHT); + btnDropDown.Image = CreateResizedBitmap("Arrow", DOWNARROW_ICONWIDTH, DOWNARROW_ICONHEIGHT); } } @@ -5254,7 +5246,7 @@ private unsafe bool WmNotify(ref Message m) { protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_SYSCOLORCHANGE: + case Interop.WindowMessages.WM_SYSCOLORCHANGE: Invalidate(); break; @@ -5263,7 +5255,7 @@ protected override void WndProc(ref Message m) { // Edit or bad bad things can happen with // our state... // - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: if (!GetInPropertySet() && Edit.Visible && (errorState != ERROR_NONE || !Commit())) { base.WndProc(ref m); Edit.FocusInternal(); @@ -5271,18 +5263,18 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_IME_STARTCOMPOSITION: + case Interop.WindowMessages.WM_IME_STARTCOMPOSITION: Edit.FocusInternal(); Edit.Clear(); - UnsafeNativeMethods.PostMessage(new HandleRef(Edit, Edit.Handle), NativeMethods.WM_IME_STARTCOMPOSITION, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(Edit, Edit.Handle), Interop.WindowMessages.WM_IME_STARTCOMPOSITION, 0, 0); return; - case NativeMethods.WM_IME_COMPOSITION: + case Interop.WindowMessages.WM_IME_COMPOSITION: Edit.FocusInternal(); - UnsafeNativeMethods.PostMessage(new HandleRef(Edit, Edit.Handle), NativeMethods.WM_IME_COMPOSITION, m.WParam, m.LParam); + UnsafeNativeMethods.PostMessage(new HandleRef(Edit, Edit.Handle), Interop.WindowMessages.WM_IME_COMPOSITION, m.WParam, m.LParam); return; - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: int flags = NativeMethods.DLGC_WANTCHARS | NativeMethods.DLGC_WANTARROWS; @@ -5300,7 +5292,7 @@ protected override void WndProc(ref Message m) { m.Result = (IntPtr)(flags); return; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: // check if it's the same position, of so eat the message if (unchecked( (int) (long)m.LParam) == lastMouseMove) { @@ -5309,7 +5301,7 @@ protected override void WndProc(ref Message m) { lastMouseMove = unchecked( (int) (long)m.LParam); break; - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: if (WmNotify(ref m)) return; break; @@ -5992,7 +5984,7 @@ public void SetComponent(Control ctl, bool resizable) { protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_ACTIVATE) { + if (m.Msg == Interop.WindowMessages.WM_ACTIVATE) { SetState(STATE_MODAL, true); Debug.WriteLineIf(CompModSwitches.DebugGridView.TraceVerbose, "DropDownHolder:WM_ACTIVATE()"); IntPtr activatedWindow = (IntPtr)m.LParam; @@ -6005,7 +5997,7 @@ protected override void WndProc(ref Message m) { //Active = ((int)m.WParam & 0x0000FFFF) != NativeMethods.WA_INACTIVE; //return; } - else if (m.Msg == NativeMethods.WM_CLOSE) { + else if (m.Msg == Interop.WindowMessages.WM_CLOSE) { // don't let an ALT-F4 get you down // if (Visible) { @@ -6013,7 +6005,7 @@ protected override void WndProc(ref Message m) { } return; } - else if (m.Msg == NativeMethods.WM_DPICHANGED) { + else if (m.Msg == Interop.WindowMessages.WM_DPICHANGED) { // Dropdownholder in PropertyGridView is already scaled based on parent font and other properties that were already set for new DPI // This case is to avoid rescaling(double scaling) of this form m.Result = IntPtr.Zero; @@ -6057,22 +6049,14 @@ internal PropertyGridView OwningPropertyGridView { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// /// Constructs the new instance of the accessibility object for this control. /// /// The accessibility object instance. protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new GridViewListBoxAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new GridViewListBoxAccessibleObject(this); } public virtual bool InSetSelectedIndex() { @@ -6451,12 +6435,8 @@ public virtual bool Filter { /// Indicates whether or not the control supports UIA Providers via /// IRawElementProviderFragment/IRawElementProviderFragmentRoot interfaces /// - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } - + internal override bool SupportsUiaProviders => true; + public override bool Focused { get { if (dontFocusMe) { @@ -6514,11 +6494,7 @@ public GridViewEdit(PropertyGridView psheet) { /// AccessibleObject for this GridViewEdit instance. /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level2) { - return new GridViewEditAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new GridViewEditAccessibleObject(this); } protected override void DestroyHandle() { @@ -6538,7 +6514,7 @@ public void FilterKeyPress(char keyChar) { if (IsInputChar(keyChar)) { this.FocusInternal(); this.SelectAll(); - UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), NativeMethods.WM_CHAR, (IntPtr)keyChar, IntPtr.Zero); + UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_CHAR, (IntPtr)keyChar, IntPtr.Zero); } } @@ -6762,26 +6738,26 @@ protected override void WndProc(ref Message m) { } switch (m.Msg) { - case NativeMethods.WM_STYLECHANGED: + case Interop.WindowMessages.WM_STYLECHANGED: if ((unchecked( (int) (long)m.WParam) & NativeMethods.GWL_EXSTYLE) != 0) { psheet.Invalidate(); } break; - case NativeMethods.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: if (unchecked( (int) (long)m.LParam) == lastMove) { return; } lastMove = unchecked( (int) (long)m.LParam); break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: mouseHook.HookMouseDown = false; break; - case NativeMethods.WM_SHOWWINDOW: + case Interop.WindowMessages.WM_SHOWWINDOW: if (IntPtr.Zero == m.WParam) { mouseHook.HookMouseDown = false; } break; - case NativeMethods.WM_PASTE: + case Interop.WindowMessages.WM_PASTE: /*if (!this.ReadOnly) { IDataObject dataObject = Clipboard.GetDataObject(); Debug.Assert(dataObject != null, "Failed to get dataObject from clipboard"); @@ -6800,7 +6776,7 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: m.Result = (IntPtr)((long)m.Result | NativeMethods.DLGC_WANTARROWS | NativeMethods.DLGC_WANTCHARS); if (psheet.NeedsCommit || this.WantsTab((ModifierKeys & Keys.Shift) == 0)) { @@ -6808,7 +6784,7 @@ protected override void WndProc(ref Message m) { } return; - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: if (WmNotify(ref m)) return; break; @@ -6842,9 +6818,7 @@ public override AccessibleStates State { } } - internal override bool IsIAccessibleExSupported() { - return true; - } + internal override bool IsIAccessibleExSupported() => true; /// /// Returns the element in the specified direction. @@ -6852,16 +6826,14 @@ internal override bool IsIAccessibleExSupported() { /// Indicates the direction in which to navigate. /// Returns the element in the specified direction. internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) { - if (AccessibilityImprovements.Level3) { - if (direction == UnsafeNativeMethods.NavigateDirection.Parent) { - return propertyGridView.SelectedGridEntry.AccessibilityObject; - } - else if (direction == UnsafeNativeMethods.NavigateDirection.NextSibling) { - if (propertyGridView.DropDownButton.Visible) { - return propertyGridView.DropDownButton.AccessibilityObject; - } else if (propertyGridView.DialogButton.Visible) { - return propertyGridView.DialogButton.AccessibilityObject; - } + if (direction == UnsafeNativeMethods.NavigateDirection.Parent) { + return propertyGridView.SelectedGridEntry.AccessibilityObject; + } + else if (direction == UnsafeNativeMethods.NavigateDirection.NextSibling) { + if (propertyGridView.DropDownButton.Visible) { + return propertyGridView.DropDownButton.AccessibilityObject; + } else if (propertyGridView.DialogButton.Visible) { + return propertyGridView.DialogButton.AccessibilityObject; } } @@ -6873,11 +6845,7 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga /// internal override UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRoot { get { - if (AccessibilityImprovements.Level3) { - return propertyGridView.AccessibilityObject; - } - - return base.FragmentRoot; + return propertyGridView.AccessibilityObject; } } @@ -6888,14 +6856,11 @@ internal override object GetPropertyValue(int propertyID) { else if (propertyID == NativeMethods.UIA_IsValuePatternAvailablePropertyId) { return IsPatternSupported(NativeMethods.UIA_ValuePatternId); } - - if (AccessibilityImprovements.Level3) { - if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { - return NativeMethods.UIA_EditControlTypeId; - } - else if (propertyID == NativeMethods.UIA_NamePropertyId) { - return Name; - } + else if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { + return NativeMethods.UIA_EditControlTypeId; + } + else if (propertyID == NativeMethods.UIA_NamePropertyId) { + return Name; } return base.GetPropertyValue(propertyID); @@ -6911,16 +6876,14 @@ internal override bool IsPatternSupported(int patternId) { public override string Name { get { - if (AccessibilityImprovements.Level3) { - string name = Owner.AccessibleName; - if (name != null) { - return name; - } - else { - var selectedGridEntry = propertyGridView.SelectedGridEntry; - if (selectedGridEntry != null) { - return selectedGridEntry.AccessibilityObject.Name; - } + string name = Owner.AccessibleName; + if (name != null) { + return name; + } + else { + var selectedGridEntry = propertyGridView.SelectedGridEntry; + if (selectedGridEntry != null) { + return selectedGridEntry.AccessibilityObject.Name; } } @@ -6944,9 +6907,7 @@ internal override bool IsReadOnly { #endregion internal override void SetFocus() { - if (AccessibilityImprovements.Level3) { - RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); - } + RaiseAutomationEvent(NativeMethods.UIA_AutomationFocusChangedEventId); base.SetFocus(); } @@ -7061,16 +7022,16 @@ private void HookMouse() { private IntPtr MouseHookProc(int nCode, IntPtr wparam, IntPtr lparam) { GC.KeepAlive(this); if (nCode == NativeMethods.HC_ACTION) { - NativeMethods.MOUSEHOOKSTRUCT mhs = (NativeMethods.MOUSEHOOKSTRUCT)UnsafeNativeMethods.PtrToStructure(lparam, typeof(NativeMethods.MOUSEHOOKSTRUCT)); + NativeMethods.MOUSEHOOKSTRUCT mhs = Marshal.PtrToStructure(lparam); if (mhs != null) { switch (unchecked( (int) (long)wparam)) { - case NativeMethods.WM_LBUTTONDOWN: - case NativeMethods.WM_MBUTTONDOWN: - case NativeMethods.WM_RBUTTONDOWN: - case NativeMethods.WM_NCLBUTTONDOWN: - case NativeMethods.WM_NCMBUTTONDOWN: - case NativeMethods.WM_NCRBUTTONDOWN: - case NativeMethods.WM_MOUSEACTIVATE: + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + case Interop.WindowMessages.WM_NCMBUTTONDOWN: + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + case Interop.WindowMessages.WM_MOUSEACTIVATE: if (ProcessMouseDown(mhs.hWnd, mhs.pt_x, mhs.pt_y)) { return (IntPtr)1; } @@ -7230,11 +7191,7 @@ public PropertyGridViewAccessibleObject(PropertyGridView owner, PropertyGrid par /// otherwise return null. /// internal override UnsafeNativeMethods.IRawElementProviderFragment ElementProviderFromPoint(double x, double y) { - if (AccessibilityImprovements.Level3) { - return HitTest((int)x, (int)y); - } - - return base.ElementProviderFromPoint(x, y); + return HitTest((int)x, (int)y); } /// @@ -7243,35 +7200,33 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment ElementProvide /// Indicates the direction in which to navigate. /// Returns the element in the specified direction. internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) { - if (AccessibilityImprovements.Level3) { - var propertyGridAccessibleObject = _parentPropertyGrid.AccessibilityObject as PropertyGridAccessibleObject; - if (propertyGridAccessibleObject != null) { - var navigationTarget = propertyGridAccessibleObject.ChildFragmentNavigate(this, direction); - if (navigationTarget != null) { - return navigationTarget; - } + var propertyGridAccessibleObject = _parentPropertyGrid.AccessibilityObject as PropertyGridAccessibleObject; + if (propertyGridAccessibleObject != null) { + var navigationTarget = propertyGridAccessibleObject.ChildFragmentNavigate(this, direction); + if (navigationTarget != null) { + return navigationTarget; } + } - if (_owningPropertyGridView.OwnerGrid.SortedByCategories) { - switch (direction) { - case UnsafeNativeMethods.NavigateDirection.FirstChild: - return GetFirstCategory(); - case UnsafeNativeMethods.NavigateDirection.LastChild: - return GetLastCategory(); - } + if (_owningPropertyGridView.OwnerGrid.SortedByCategories) { + switch (direction) { + case UnsafeNativeMethods.NavigateDirection.FirstChild: + return GetFirstCategory(); + case UnsafeNativeMethods.NavigateDirection.LastChild: + return GetLastCategory(); } - else { - switch (direction) { - case UnsafeNativeMethods.NavigateDirection.FirstChild: - return GetChild(0); - case UnsafeNativeMethods.NavigateDirection.LastChild: - int childCount = GetChildCount(); - if (childCount > 0) { - return GetChild(childCount - 1); - } + } + else { + switch (direction) { + case UnsafeNativeMethods.NavigateDirection.FirstChild: + return GetChild(0); + case UnsafeNativeMethods.NavigateDirection.LastChild: + int childCount = GetChildCount(); + if (childCount > 0) { + return GetChild(childCount - 1); + } - return null; - } + return null; } } @@ -7283,11 +7238,7 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga /// internal override UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRoot { get { - if (AccessibilityImprovements.Level3) { - return _owningPropertyGridView.OwnerGrid.AccessibilityObject; - } - - return base.FragmentRoot; + return _owningPropertyGridView.OwnerGrid.AccessibilityObject; } } @@ -7296,11 +7247,7 @@ internal override UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRo /// /// The accessible object for the currently focused grid entry. internal override UnsafeNativeMethods.IRawElementProviderFragment GetFocus() { - if (AccessibilityImprovements.Level3) { - return GetFocused(); - } - - return base.FragmentRoot; + return GetFocused(); } /// @@ -7309,12 +7256,10 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment GetFocus() { /// Identifier indicating the property to return /// Returns a ValInfo indicating whether the element supports this property, or has no value for it. internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) { - if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { - return NativeMethods.UIA_TableControlTypeId; - } else if (propertyID == NativeMethods.UIA_NamePropertyId) { - return Name; - } + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { + return NativeMethods.UIA_TableControlTypeId; + } else if (propertyID == NativeMethods.UIA_NamePropertyId) { + return Name; } return base.GetPropertyValue(propertyID); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyManager.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyManager.cs index 38e5672fa02..9809f7d1c52 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyManager.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyManager.cs @@ -23,7 +23,7 @@ private void PropertyChanged(object sender, EventArgs ea) OnCurrentChanged(EventArgs.Empty); } - internal override void SetDataSource(object dataSource) + private protected override void SetDataSource(object dataSource) { if (_dataSource != null && !string.IsNullOrEmpty(_propName)) { @@ -145,14 +145,14 @@ internal protected override void OnCurrentChanged(EventArgs ea) PushData(); onCurrentChangedHandler?.Invoke(this, ea); - onCurrentItemChangedHandler?.Invoke(this, ea); + _onCurrentItemChangedHandler?.Invoke(this, ea); } internal protected override void OnCurrentItemChanged(EventArgs ea) { PushData(); - onCurrentItemChangedHandler?.Invoke(this, ea); + _onCurrentItemChangedHandler?.Invoke(this, ea); } internal override object DataSource => _dataSource; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyStore.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyStore.cs index 4b51f6b782c..2e12d14abc6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PropertyStore.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PropertyStore.cs @@ -2,894 +2,901 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; - using System; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Drawing; - +namespace System.Windows.Forms +{ /// - /// This is a small class that can efficiently store property values. - /// It tries to optimize for size first, "get" access second, and - /// "set" access third. + /// This is a small class that can efficiently store property values. + /// It tries to optimize for size first, "get" access second, and + /// "set" access third. /// - internal class PropertyStore { - - private static int currentKey; - - private IntegerEntry[] intEntries; - private ObjectEntry[] objEntries; - + internal class PropertyStore + { + private static int s_currentKey; + + private IntegerEntry[] s_intEntries; + private ObjectEntry[] s_objEntries; + /// - /// Retrieves an integer value from our property list. - /// This will set value to zero and return false if the - /// list does not contain the given key. + /// Retrieves an integer value from our property list. + /// This will set value to zero and return false if the + /// list does not contain the given key. /// - public bool ContainsInteger(int key) { - bool found; - GetInteger(key, out found); + public bool ContainsInteger(int key) + { + GetInteger(key, out bool found); return found; } - + /// - /// Retrieves an integer value from our property list. - /// This will set value to zero and return false if the - /// list does not contain the given key. + /// Retrieves an integer value from our property list. + /// This will set value to zero and return false if the + /// list does not contain the given key. /// - public bool ContainsObject(int key) { - bool found; - GetObject(key, out found); + public bool ContainsObject(int key) + { + GetObject(key, out bool found); return found; } - + /// - /// Creates a new key for this property store. This is NOT - /// guarded by any thread safety so if you are calling it on - /// multiple threads you should guard. For our purposes, - /// we're fine because this is designed to be called in a class - /// initializer, and we never have the same class hierarchy - /// initializing on multiple threads at once. + /// Creates a new key for this property store. This is NOT + /// guarded by any thread safety so if you are calling it on + /// multiple threads you should guard. For our purposes, + /// we're fine because this is designed to be called in a class + /// initializer, and we never have the same class hierarchy + /// initializing on multiple threads at once. /// - public static int CreateKey() { - return currentKey++; - } + public static int CreateKey() => s_currentKey++; - public Color GetColor(int key) { - bool found; - return GetColor(key, out found); - } + public Color GetColor(int key) => GetColor(key, out _); - // this is a wrapper around GetObject designed to - // reduce the boxing hit - public Color GetColor(int key, out bool found) { + /// + /// A wrapper around GetObject designed to reduce the boxing hit + /// + public Color GetColor(int key, out bool found) + { object storedObject = GetObject(key, out found); - - if (found) { - ColorWrapper wrapper = storedObject as ColorWrapper; - - if (wrapper != null) { + if (found) + { + if (storedObject is ColorWrapper wrapper) + { return wrapper.Color; } -#if DEBUG - else if (storedObject != null) { - Debug.Fail("Have non-null object that isnt a color wrapper stored in a color entry!\r\nDid someone SetObject instead of SetColor?"); - } -#endif + + Debug.Assert(storedObject == null, $"Have non-null object that isnt a color wrapper stored in a color entry!{Environment.NewLine}Did someone SetObject instead of SetColor?"); } - // we didnt actually find a non-null color wrapper. - found = false; - return Color.Empty; - } - - public Padding GetPadding(int key) { - bool found; - return GetPadding(key, out found); + found = false; + return Color.Empty; } - // this is a wrapper around GetObject designed to - // reduce the boxing hit - public Padding GetPadding(int key, out bool found) { + /// + /// A wrapper around GetObject designed to reduce the boxing hit. + /// + public Padding GetPadding(int key, out bool found) + { object storedObject = GetObject(key, out found); - - if (found) { - PaddingWrapper wrapper = storedObject as PaddingWrapper; - - - if (wrapper != null) { + if (found) + { + if (storedObject is PaddingWrapper wrapper) + { return wrapper.Padding; - } -#if DEBUG - else if (storedObject != null) { - Debug.Fail("Have non-null object that isnt a padding wrapper stored in a padding entry!\r\nDid someone SetObject instead of SetPadding?"); } -#endif + + Debug.Assert(storedObject == null, $"Have non-null object that isnt a padding wrapper stored in a padding entry!{Environment.NewLine}Did someone SetObject instead of SetPadding?"); } - - // we didnt actually find a non-null padding wrapper. + found = false; - return Padding.Empty; - } -#if false // FXCOP currently not used - public Size GetSize(int key) { - bool found; - return GetSize(key, out found); + return Padding.Empty; } -#endif - // this is a wrapper around GetObject designed to - // reduce the boxing hit - public Size GetSize(int key, out bool found) { + /// + /// A wrapper around GetObject designed to reduce the boxing hit. + /// + public Size GetSize(int key, out bool found) + { object storedObject = GetObject(key, out found); - - if (found) { - SizeWrapper wrapper = storedObject as SizeWrapper; - if (wrapper != null) { + if (found) + { + if (storedObject is SizeWrapper wrapper) + { return wrapper.Size; } -#if DEBUG - else if (storedObject != null) { - Debug.Fail("Have non-null object that isnt a padding wrapper stored in a padding entry!\r\nDid someone SetObject instead of SetPadding?"); - } -#endif + + Debug.Assert(storedObject == null, $"Have non-null object that isnt a padding wrapper stored in a padding entry!{Environment.NewLine}Did someone SetObject instead of SetPadding?"); } - // we didnt actually find a non-null size wrapper. + found = false; - return Size.Empty; + return Size.Empty; } - public Rectangle GetRectangle(int key) { - bool found; - return GetRectangle(key, out found); - } - - // this is a wrapper around GetObject designed to - // reduce the boxing hit - public Rectangle GetRectangle(int key, out bool found) { + /// + /// A wrapper around GetObject designed to reduce the boxing hit. + /// + public Rectangle GetRectangle(int key, out bool found) + { object storedObject = GetObject(key, out found); - - if (found) { - RectangleWrapper wrapper = storedObject as RectangleWrapper; - if (wrapper != null) { + if (found) + { + if (storedObject is RectangleWrapper wrapper) + { return wrapper.Rectangle; } -#if DEBUG - else if (storedObject != null) { - Debug.Fail("Have non-null object that isnt a Rectangle wrapper stored in a Rectangle entry!\r\nDid someone SetObject instead of SetRectangle?"); - } -#endif + + Debug.Assert(storedObject == null, $"Have non-null object that isnt a Rectangle wrapper stored in a Rectangle entry!{Environment.NewLine}Did someone SetObject instead of SetRectangle?"); } - // we didnt actually find a non-null rectangle wrapper. + found = false; - return Rectangle.Empty; + return Rectangle.Empty; } /// - /// Retrieves an integer value from our property list. - /// This will set value to zero and return false if the - /// list does not contain the given key. + /// Retrieves an integer value from our property list. + /// This will set value to zero and return false if the + /// list does not contain the given key. /// - public int GetInteger(int key) { - bool found; - return GetInteger(key, out found); - } - + public int GetInteger(int key) => GetInteger(key, out _); + /// - /// Retrieves an integer value from our property list. - /// This will set value to zero and return false if the - /// list does not contain the given key. + /// Retrieves an integer value from our property list. + /// This will set value to zero and return false if the + /// list does not contain the given key. /// - public int GetInteger(int key, out bool found) { - - int value = 0; - int index; - short element; - short keyIndex = SplitKey(key, out element); - - found = false; - - if (LocateIntegerEntry(keyIndex, out index)) { - // We have found the relevant entry. See if - // the bitmask indicates the value is used. - // - if (((1 << element) & intEntries[index].Mask) != 0) { - - found = true; - - switch(element) { - case 0: - value = intEntries[index].Value1; - break; - - case 1: - value = intEntries[index].Value2; - break; - - case 2: - value = intEntries[index].Value3; - break; - - case 3: - value = intEntries[index].Value4; - break; - - default: - Debug.Fail("Invalid element obtained from LocateIntegerEntry"); - break; - } - } + public int GetInteger(int key, out bool found) + { + short keyIndex = SplitKey(key, out short element); + if (!LocateIntegerEntry(keyIndex, out int index)) + { + found = false; + return default(int); + } + + // We have found the relevant entry. See if + // the bitmask indicates the value is used. + if (((1 << element) & s_intEntries[index].Mask) == 0) + { + found = false; + return default(int); + } + + found = true; + switch (element) + { + case 0: + return s_intEntries[index].Value1; + case 1: + return s_intEntries[index].Value2; + case 2: + return s_intEntries[index].Value3; + case 3: + return s_intEntries[index].Value4; + default: + Debug.Fail("Invalid element obtained from LocateIntegerEntry"); + return default(int); } - - return value; } - + /// - /// Retrieves an object value from our property list. - /// This will set value to null and return false if the - /// list does not contain the given key. + /// Retrieves an object value from our property list. + /// This will set value to null and return false if the + /// list does not contain the given key. /// - public object GetObject(int key) { - bool found; - return GetObject(key, out found); - } + public object GetObject(int key) => GetObject(key, out _); /// - /// Retrieves an object value from our property list. - /// This will set value to null and return false if the - /// list does not contain the given key. + /// Retrieves an object value from our property list. + /// This will set value to null and return false if the + /// list does not contain the given key. /// - public object GetObject(int key, out bool found) { - - object value = null; - int index; - short element; - short keyIndex = SplitKey(key, out element); - - found = false; - - if (LocateObjectEntry(keyIndex, out index)) { - // We have found the relevant entry. See if - // the bitmask indicates the value is used. - // - if (((1 << element) & objEntries[index].Mask) != 0) { - - found = true; - - switch(element) { - case 0: - value = objEntries[index].Value1; - break; - - case 1: - value = objEntries[index].Value2; - break; - - case 2: - value = objEntries[index].Value3; - break; - - case 3: - value = objEntries[index].Value4; - break; - - default: - Debug.Fail("Invalid element obtained from LocateObjectEntry"); - break; - } - } + public object GetObject(int key, out bool found) + { + short keyIndex = SplitKey(key, out short element); + if (!LocateObjectEntry(keyIndex, out int index)) + { + found = false; + return null; + } + + // We have found the relevant entry. See if + // the bitmask indicates the value is used. + if (((1 << element) & s_objEntries[index].Mask) == 0) + { + found = false; + return null; } - return value; + found = true; + switch (element) + { + case 0: + return s_objEntries[index].Value1; + case 1: + return s_objEntries[index].Value2; + case 2: + return s_objEntries[index].Value3; + case 3: + return s_objEntries[index].Value4; + default: + Debug.Fail("Invalid element obtained from LocateObjectEntry"); + return null; + } } - /// - /// Locates the requested entry in our array if entries. This does - /// not do the mask check to see if the entry is currently being used, - /// but it does locate the entry. If the entry is found, this returns - /// true and fills in index and element. If the entry is not found, - /// this returns false. If the entry is not found, index will contain - /// the insert point at which one would add a new element. + /// Locates the requested entry in our array if entries. This does + /// not do the mask check to see if the entry is currently being used, + /// but it does locate the entry. If the entry is found, this returns + /// true and fills in index and element. If the entry is not found, + /// this returns false. If the entry is not found, index will contain + /// the insert point at which one would add a new element. /// - private bool LocateIntegerEntry(short entryKey, out int index) { - if (intEntries != null) { - int length = intEntries.Length; - if (length <= 16) { - //if the array is small enough, we unroll the binary search to be more efficient. - //usually the performance gain is around 10% to 20% - //DON'T change this code unless you are very confident! - index = 0; - int midPoint = length / 2; - if (intEntries[midPoint].Key <= entryKey) { - index = midPoint; - } - //we don't move this inside the previous if branch since this catches both the case - //index == 0 and index = midPoint - if (intEntries[index].Key == entryKey) { + private bool LocateIntegerEntry(short entryKey, out int index) + { + if (s_intEntries == null) + { + index = 0; + return false; + } + + int length = s_intEntries.Length; + if (length <= 16) + { + // If the array is small enough, we unroll the binary search to be more efficient. + // Usually the performance gain is around 10% to 20% + // DON'T change this code unless you are very confident! + index = 0; + int midPoint = length / 2; + if (s_intEntries[midPoint].Key <= entryKey) + { + index = midPoint; + } + + // We don't move this inside the previous if branch since this catches both + // the case index == 0 and index = midPoint + if (s_intEntries[index].Key == entryKey) + { + return true; + } + + midPoint = (length + 1) / 4; + if (s_intEntries[index + midPoint].Key <= entryKey) + { + index += midPoint; + if (s_intEntries[index].Key == entryKey) + { return true; } - - midPoint = (length + 1) / 4; - if (intEntries[index + midPoint].Key <= entryKey) { - index += midPoint; - if (intEntries[index].Key == entryKey) { - return true; - } - } - - midPoint = (length + 3) / 8; - if (intEntries[index + midPoint].Key <= entryKey) { - index += midPoint; - if (intEntries[index].Key == entryKey) { - return true; - } - } - - midPoint = (length + 7) / 16; - if (intEntries[index + midPoint].Key <= entryKey) { - index += midPoint; - if (intEntries[index].Key == entryKey) { - return true; - } + } + + midPoint = (length + 3) / 8; + if (s_intEntries[index + midPoint].Key <= entryKey) + { + index += midPoint; + if (s_intEntries[index].Key == entryKey) + { + return true; } + } - Debug.Assert(index < length); - if (entryKey > intEntries[index].Key) { - index++; + midPoint = (length + 7) / 16; + if (s_intEntries[index + midPoint].Key <= entryKey) + { + index += midPoint; + if (s_intEntries[index].Key == entryKey) + { + return true; } - Debug_VerifyLocateIntegerEntry(index, entryKey, length); - return false; } - else { - // Entries are stored in numerical order by key index so we can - // do a binary search on them. - // - int max = length - 1; - int min = 0; - int idx = 0; - - do { - idx = (max + min) / 2; - short currentKeyIndex = intEntries[idx].Key; - - if (currentKeyIndex == entryKey) { - index = idx; - return true; - } - else if (entryKey < currentKeyIndex) { - max = idx - 1; - } - else { - min = idx + 1; - } + + Debug.Assert(index < length); + if (entryKey > s_intEntries[index].Key) + { + index++; + } + + Debug_VerifyLocateIntegerEntry(index, entryKey, length); + return false; + } + else + { + // Entries are stored in numerical order by key index so we can + // do a binary search on them. + int max = length - 1; + int min = 0; + int idx = 0; + + do + { + idx = (max + min) / 2; + short currentKeyIndex = s_intEntries[idx].Key; + + if (currentKeyIndex == entryKey) + { + index = idx; + return true; } - while (max >= min); - - // Didn't find the index. Setup our output - // appropriately - // - index = idx; - if (entryKey > intEntries[idx].Key) { - index++; + else if (entryKey < currentKeyIndex) + { + max = idx - 1; + } + else + { + min = idx + 1; } - return false; } - } - else { - index = 0; + while (max >= min); + + // Didn't find the index. Setup our output appropriately + index = idx; + if (entryKey > s_intEntries[idx].Key) + { + index++; + } + return false; } } - + /// - /// Locates the requested entry in our array if entries. This does - /// not do the mask check to see if the entry is currently being used, - /// but it does locate the entry. If the entry is found, this returns - /// true and fills in index and element. If the entry is not found, - /// this returns false. If the entry is not found, index will contain - /// the insert point at which one would add a new element. + /// Locates the requested entry in our array if entries. This does + /// not do the mask check to see if the entry is currently being used, + /// but it does locate the entry. If the entry is found, this returns + /// true and fills in index and element. If the entry is not found, + /// this returns false. If the entry is not found, index will contain + /// the insert point at which one would add a new element. /// - private bool LocateObjectEntry(short entryKey, out int index) { - if (objEntries != null) { - int length = objEntries.Length; + private bool LocateObjectEntry(short entryKey, out int index) + { + if (s_objEntries != null) + { + int length = s_objEntries.Length; Debug.Assert(length > 0); - if (length <= 16) { - //if the array is small enough, we unroll the binary search to be more efficient. - //usually the performance gain is around 10% to 20% - //DON'T change this code unless you are very confident! + if (length <= 16) + { + // If the array is small enough, we unroll the binary search to be more efficient. + // Usually the performance gain is around 10% to 20% + // DON'T change this code unless you are very confident! index = 0; int midPoint = length / 2; - if (objEntries[midPoint].Key <= entryKey) { + if (s_objEntries[midPoint].Key <= entryKey) + { index = midPoint; } - //we don't move this inside the previous if branch since this catches both the case - //index == 0 and index = midPoint - if (objEntries[index].Key == entryKey) { + + // We don't move this inside the previous if branch since this catches + // both the case index == 0 and index = midPoint + if (s_objEntries[index].Key == entryKey) + { return true; } - + midPoint = (length + 1) / 4; - if (objEntries[index + midPoint].Key <= entryKey) { + if (s_objEntries[index + midPoint].Key <= entryKey) + { index += midPoint; - if (objEntries[index].Key == entryKey) { + if (s_objEntries[index].Key == entryKey) + { return true; } } - + midPoint = (length + 3) / 8; - if (objEntries[index + midPoint].Key <= entryKey) { + if (s_objEntries[index + midPoint].Key <= entryKey) + { index += midPoint; - if (objEntries[index].Key == entryKey) { + if (s_objEntries[index].Key == entryKey) + { return true; } } - + midPoint = (length + 7) / 16; - if (objEntries[index + midPoint].Key <= entryKey) { + if (s_objEntries[index + midPoint].Key <= entryKey) + { index += midPoint; - if (objEntries[index].Key == entryKey) { + if (s_objEntries[index].Key == entryKey) + { return true; } } Debug.Assert(index < length); - if (entryKey > objEntries[index].Key) { + if (entryKey > s_objEntries[index].Key) + { index++; } + Debug_VerifyLocateObjectEntry(index, entryKey, length); return false; } - else { + else + { // Entries are stored in numerical order by key index so we can // do a binary search on them. - // int max = length - 1; int min = 0; int idx = 0; - - do { + + do + { idx = (max + min) / 2; - short currentKeyIndex = objEntries[idx].Key; - - if (currentKeyIndex == entryKey) { + short currentKeyIndex = s_objEntries[idx].Key; + + if (currentKeyIndex == entryKey) + { index = idx; return true; } - else if (entryKey < currentKeyIndex) { + else if (entryKey < currentKeyIndex) + { max = idx - 1; } - else { + else + { min = idx + 1; } } while (max >= min); - - // Didn't find the index. Setup our output - // appropriately - // + + // Didn't find the index. Setup our output appropriately index = idx; - if (entryKey > objEntries[idx].Key) { + if (entryKey > s_objEntries[idx].Key) + { index++; } + return false; } } - else { + else + { index = 0; return false; } } -/* - public Color RemoveColor(int key) { - RemoveObject(key); - } -*/ + /// - /// Removes the given key from the array + /// Removes the given key from the array /// - public void RemoveInteger(int key) { - int index; - short element; - short entryKey = SplitKey(key, out element); - - if (LocateIntegerEntry(entryKey, out index)) { - if (((1 << element) & intEntries[index].Mask) == 0) { - // this element is not being used - return right away - return; - } - - // declare that the element is no longer used - intEntries[index].Mask &= (short) (~((short)(1 << element))); - - if (intEntries[index].Mask == 0) { - // this object entry is no longer in use - let's remove it all together - // not great for perf but very simple and we don't expect to remove much - IntegerEntry[] newEntries = new IntegerEntry[intEntries.Length - 1]; - if (index > 0) { - Array.Copy(intEntries, 0, newEntries, 0, index); - } - if (index < newEntries.Length) { - Debug.Assert(intEntries.Length - index - 1 > 0); - Array.Copy(intEntries, index + 1, newEntries, index, intEntries.Length - index - 1); - } - intEntries = newEntries; - } - else { - // this object entry is still in use - let's just clean up the deleted element - switch (element) - { - case 0: - intEntries[index].Value1 = 0; - break; + public void RemoveInteger(int key) + { + short entryKey = SplitKey(key, out short element); + if (!LocateIntegerEntry(entryKey, out int index)) + { + return; + } - case 1: - intEntries[index].Value2 = 0; - break; + if (((1 << element) & s_intEntries[index].Mask) == 0) + { + // this element is not being used - return right away + return; + } - case 2: - intEntries[index].Value3 = 0; - break; + // declare that the element is no longer used + s_intEntries[index].Mask &= (short)(~((short)(1 << element))); - case 3: - intEntries[index].Value4 = 0; - break; + if (s_intEntries[index].Mask == 0) + { + // This object entry is no longer in use - let's remove it all together + // not great for perf but very simple and we don't expect to remove much + IntegerEntry[] newEntries = new IntegerEntry[s_intEntries.Length - 1]; + if (index > 0) + { + Array.Copy(s_intEntries, 0, newEntries, 0, index); + } + if (index < newEntries.Length) + { + Debug.Assert(s_intEntries.Length - index - 1 > 0); + Array.Copy(s_intEntries, index + 1, newEntries, index, s_intEntries.Length - index - 1); + } - default: - Debug.Fail("Invalid element obtained from LocateIntegerEntry"); - break; - } + s_intEntries = newEntries; + } + else + { + // This object entry is still in use - let's just clean up the deleted element + switch (element) + { + case 0: + s_intEntries[index].Value1 = 0; + break; + + case 1: + s_intEntries[index].Value2 = 0; + break; + + case 2: + s_intEntries[index].Value3 = 0; + break; + + case 3: + s_intEntries[index].Value4 = 0; + break; + + default: + Debug.Fail("Invalid element obtained from LocateIntegerEntry"); + break; } } } /// - /// Removes the given key from the array + /// Removes the given key from the array /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] public void RemoveObject(int key) { - int index; - short element; - short entryKey = SplitKey(key, out element); - - if (LocateObjectEntry(entryKey, out index)) { - if (((1 << element) & objEntries[index].Mask) == 0) { - // this element is not being used - return right away - return; - } - - // declare that the element is no longer used - objEntries[index].Mask &= (short)(~((short)(1 << element))); - - if (objEntries[index].Mask == 0) { - // this object entry is no longer in use - let's remove it all together - // not great for perf but very simple and we don't expect to remove much - if (objEntries.Length == 1) + short entryKey = SplitKey(key, out short element); + if (!LocateObjectEntry(entryKey, out int index)) + { + return; + } + + if (((1 << element) & s_objEntries[index].Mask) == 0) + { + // This element is not being used - return right away + return; + } + + // Declare that the element is no longer used + s_objEntries[index].Mask &= (short)(~((short)(1 << element))); + + if (s_objEntries[index].Mask == 0) + { + // This object entry is no longer in use - let's remove it all together + // not great for perf but very simple and we don't expect to remove much + if (s_objEntries.Length == 1) + { + // Instead of allocating an array of length 0, we simply reset the array to null. + s_objEntries = null; + } + else + { + ObjectEntry[] newEntries = new ObjectEntry[s_objEntries.Length - 1]; + if (index > 0) { - // instead of allocating an array of length 0, we simply reset the array to null. - objEntries = null; + Array.Copy(s_objEntries, 0, newEntries, 0, index); } - else + if (index < newEntries.Length) { - ObjectEntry[] newEntries = new ObjectEntry[objEntries.Length - 1]; - if (index > 0) - { - Array.Copy(objEntries, 0, newEntries, 0, index); - } - if (index < newEntries.Length) - { - Debug.Assert(objEntries.Length - index - 1 > 0); - Array.Copy(objEntries, index + 1, newEntries, index, objEntries.Length - index - 1); - } - objEntries = newEntries; + Debug.Assert(s_objEntries.Length - index - 1 > 0); + Array.Copy(s_objEntries, index + 1, newEntries, index, s_objEntries.Length - index - 1); } + s_objEntries = newEntries; } - else { - // this object entry is still in use - let's just clean up the deleted element - switch (element) - { - case 0: - objEntries[index].Value1 = null; - break; - - case 1: - objEntries[index].Value2 = null; - break; - - case 2: - objEntries[index].Value3 = null; - break; - - case 3: - objEntries[index].Value4 = null; - break; - - default: - Debug.Fail("Invalid element obtained from LocateObjectEntry"); - break; - } + } + else + { + // This object entry is still in use - let's just clean up the deleted element + switch (element) + { + case 0: + s_objEntries[index].Value1 = null; + break; + + case 1: + s_objEntries[index].Value2 = null; + break; + + case 2: + s_objEntries[index].Value3 = null; + break; + + case 3: + s_objEntries[index].Value4 = null; + break; + + default: + Debug.Fail("Invalid element obtained from LocateObjectEntry"); + break; } } } - public void SetColor(int key, Color value) { - bool found; - object storedObject = GetObject(key, out found); - - if (!found) { + public void SetColor(int key, Color value) + { + object storedObject = GetObject(key, out bool found); + if (!found) + { SetObject(key, new ColorWrapper(value)); } - else { - ColorWrapper wrapper = storedObject as ColorWrapper; - if(wrapper != null) { + else + { + if (storedObject is ColorWrapper wrapper) + { // re-using the wrapper reduces the boxing hit. wrapper.Color = value; } - else { + else + { Debug.Assert(storedObject == null, "object should either be null or ColorWrapper"); // could someone have SetObject to this key behind our backs? SetObject(key, new ColorWrapper(value)); } - - } + + } } - public void SetPadding(int key, Padding value) { - bool found; - object storedObject = GetObject(key, out found); - if (!found) { + public void SetPadding(int key, Padding value) + { + object storedObject = GetObject(key, out bool found); + if (!found) + { SetObject(key, new PaddingWrapper(value)); } - else { - PaddingWrapper wrapper = storedObject as PaddingWrapper; - if(wrapper != null) { + else + { + if (storedObject is PaddingWrapper wrapper) + { // re-using the wrapper reduces the boxing hit. wrapper.Padding = value; } - else { + else + { Debug.Assert(storedObject == null, "object should either be null or PaddingWrapper"); // could someone have SetObject to this key behind our backs? SetObject(key, new PaddingWrapper(value)); } - - } + + } } - public void SetRectangle(int key, Rectangle value) { - - bool found; - object storedObject = GetObject(key, out found); - - if (!found) { + + public void SetRectangle(int key, Rectangle value) + { + object storedObject = GetObject(key, out bool found); + if (!found) + { SetObject(key, new RectangleWrapper(value)); } - else { - RectangleWrapper wrapper = storedObject as RectangleWrapper; - if(wrapper != null) { + else + { + if (storedObject is RectangleWrapper wrapper) + { // re-using the wrapper reduces the boxing hit. wrapper.Rectangle = value; } - else { + else + { Debug.Assert(storedObject == null, "object should either be null or RectangleWrapper"); // could someone have SetObject to this key behind our backs? SetObject(key, new RectangleWrapper(value)); } - - } - - } - public void SetSize(int key, Size value) { - - bool found; - object storedObject = GetObject(key, out found); - - if (!found) { + } + } + + public void SetSize(int key, Size value) + { + object storedObject = GetObject(key, out bool found); + if (!found) + { SetObject(key, new SizeWrapper(value)); } - else { - SizeWrapper wrapper = storedObject as SizeWrapper; - if(wrapper != null) { + else + { + if (storedObject is SizeWrapper wrapper) + { // re-using the wrapper reduces the boxing hit. wrapper.Size = value; } - else { + else + { Debug.Assert(storedObject == null, "object should either be null or SizeWrapper"); // could someone have SetObject to this key behind our backs? SetObject(key, new SizeWrapper(value)); } - - } + + } } + /// - /// Stores the given value in the key. + /// Stores the given value in the key. /// - public void SetInteger(int key, int value) { - int index; - short element; - short entryKey = SplitKey(key, out element); - - if (!LocateIntegerEntry(entryKey, out index)) { - + public void SetInteger(int key, int value) + { + short entryKey = SplitKey(key, out short element); + if (!LocateIntegerEntry(entryKey, out int index)) + { // We must allocate a new entry. - // - if (intEntries != null) { - IntegerEntry[] newEntries = new IntegerEntry[intEntries.Length + 1]; - - if (index > 0) { - Array.Copy(intEntries, 0, newEntries, 0, index); + if (s_intEntries != null) + { + IntegerEntry[] newEntries = new IntegerEntry[s_intEntries.Length + 1]; + + if (index > 0) + { + Array.Copy(s_intEntries, 0, newEntries, 0, index); } - - if (intEntries.Length - index > 0) { - Array.Copy(intEntries, index, newEntries, index + 1, intEntries.Length - index); + + if (s_intEntries.Length - index > 0) + { + Array.Copy(s_intEntries, index, newEntries, index + 1, s_intEntries.Length - index); } - - intEntries = newEntries; + + s_intEntries = newEntries; } - else { - intEntries = new IntegerEntry[1]; + else + { + s_intEntries = new IntegerEntry[1]; Debug.Assert(index == 0, "LocateIntegerEntry should have given us a zero index."); } - - intEntries[index].Key = entryKey; + + s_intEntries[index].Key = entryKey; } - + // Now determine which value to set. - // - switch(element) { + switch (element) + { case 0: - intEntries[index].Value1 = value; + s_intEntries[index].Value1 = value; break; - + case 1: - intEntries[index].Value2 = value; + s_intEntries[index].Value2 = value; break; - + case 2: - intEntries[index].Value3 = value; + s_intEntries[index].Value3 = value; break; - + case 3: - intEntries[index].Value4 = value; + s_intEntries[index].Value4 = value; break; - + default: Debug.Fail("Invalid element obtained from LocateIntegerEntry"); break; } - intEntries[index].Mask = (short)((1 << element) | (ushort)(intEntries[index].Mask)); + s_intEntries[index].Mask = (short)((1 << element) | (ushort)(s_intEntries[index].Mask)); } - + /// - /// Stores the given value in the key. + /// Stores the given value in the key. /// - public void SetObject(int key, object value) { - int index; - short element; - short entryKey = SplitKey(key, out element); - - if (!LocateObjectEntry(entryKey, out index)) { - + public void SetObject(int key, object value) + { + short entryKey = SplitKey(key, out short element); + if (!LocateObjectEntry(entryKey, out int index)) + { // We must allocate a new entry. - // - if (objEntries != null) { - ObjectEntry[] newEntries = new ObjectEntry[objEntries.Length + 1]; - - if (index > 0) { - Array.Copy(objEntries, 0, newEntries, 0, index); + if (s_objEntries != null) + { + ObjectEntry[] newEntries = new ObjectEntry[s_objEntries.Length + 1]; + + if (index > 0) + { + Array.Copy(s_objEntries, 0, newEntries, 0, index); } - - if (objEntries.Length - index > 0) { - Array.Copy(objEntries, index, newEntries, index + 1, objEntries.Length - index); + + if (s_objEntries.Length - index > 0) + { + Array.Copy(s_objEntries, index, newEntries, index + 1, s_objEntries.Length - index); } - - objEntries = newEntries; + + s_objEntries = newEntries; } - else { - objEntries = new ObjectEntry[1]; + else + { + s_objEntries = new ObjectEntry[1]; Debug.Assert(index == 0, "LocateObjectEntry should have given us a zero index."); } - - objEntries[index].Key = entryKey; + + s_objEntries[index].Key = entryKey; } - + // Now determine which value to set. - // - switch(element) { + switch (element) + { case 0: - objEntries[index].Value1 = value; + s_objEntries[index].Value1 = value; break; - + case 1: - objEntries[index].Value2 = value; + s_objEntries[index].Value2 = value; break; - + case 2: - objEntries[index].Value3 = value; + s_objEntries[index].Value3 = value; break; - + case 3: - objEntries[index].Value4 = value; + s_objEntries[index].Value4 = value; break; - + default: Debug.Fail("Invalid element obtained from LocateObjectEntry"); break; } - - objEntries[index].Mask = (short)((ushort)(objEntries[index].Mask)|(1 << element)); + + s_objEntries[index].Mask = (short)((ushort)(s_objEntries[index].Mask) | (1 << element)); } - + /// - /// Takes the given key and splits it into an index - /// and an element. + /// Takes the given key and splits it into an index and an element. /// - private short SplitKey(int key, out short element) { + private short SplitKey(int key, out short element) + { element = (short)(key & 0x00000003); return (short)(key & 0xFFFFFFFC); } [Conditional("DEBUG_PROPERTYSTORE")] - private void Debug_VerifyLocateIntegerEntry(int index, short entryKey, int length) { + private void Debug_VerifyLocateIntegerEntry(int index, short entryKey, int length) + { int max = length - 1; int min = 0; int idx = 0; - - do { + + do + { idx = (max + min) / 2; - short currentKeyIndex = intEntries[idx].Key; - - if (currentKeyIndex == entryKey) { + short currentKeyIndex = s_intEntries[idx].Key; + + if (currentKeyIndex == entryKey) + { Debug.Assert(index == idx, "GetIntegerEntry in property store broken. index is " + index + " while it should be " + idx + "length of the array is " + length); } - else if (entryKey < currentKeyIndex) { + else if (entryKey < currentKeyIndex) + { max = idx - 1; } - else { + else + { min = idx + 1; } } while (max >= min); - + // shouldn't find the index if we run this debug code - if (entryKey > intEntries[idx].Key) { + if (entryKey > s_intEntries[idx].Key) + { idx++; - } + } Debug.Assert(index == idx, "GetIntegerEntry in property store broken. index is " + index + " while it should be " + idx + "length of the array is " + length); } [Conditional("DEBUG_PROPERTYSTORE")] - private void Debug_VerifyLocateObjectEntry(int index, short entryKey, int length) { + private void Debug_VerifyLocateObjectEntry(int index, short entryKey, int length) + { int max = length - 1; int min = 0; int idx = 0; - - do { + + do + { idx = (max + min) / 2; - short currentKeyIndex = objEntries[idx].Key; - - if (currentKeyIndex == entryKey) { + short currentKeyIndex = s_objEntries[idx].Key; + + if (currentKeyIndex == entryKey) + { Debug.Assert(index == idx, "GetObjEntry in property store broken. index is " + index + " while is should be " + idx + "length of the array is " + length); } - else if (entryKey < currentKeyIndex) { + else if (entryKey < currentKeyIndex) + { max = idx - 1; } - else { + else + { min = idx + 1; } } while (max >= min); - - if (entryKey > objEntries[idx].Key) { + + if (entryKey > s_objEntries[idx].Key) + { idx++; - } + } Debug.Assert(index == idx, "GetObjEntry in property store broken. index is " + index + " while is should be " + idx + "length of the array is " + length); } - + /// - /// Stores the relationship between a key and a value. - /// We do not want to be so inefficient that we require - /// four bytes for each four byte property, so use an algorithm - /// that uses the bottom two bits of the key to identify - /// one of four elements in an entry. + /// Stores the relationship between a key and a value. + /// We do not want to be so inefficient that we require + /// four bytes for each four byte property, so use an algorithm + /// that uses the bottom two bits of the key to identify + /// one of four elements in an entry. /// - private struct IntegerEntry { + private struct IntegerEntry + { public short Key; public short Mask; // only lower four bits are used; mask of used values. public int Value1; @@ -897,15 +904,16 @@ private struct IntegerEntry { public int Value3; public int Value4; } - + /// - /// Stores the relationship between a key and a value. - /// We do not want to be so inefficient that we require - /// four bytes for each four byte property, so use an algorithm - /// that uses the bottom two bits of the key to identify - /// one of four elements in an entry. + /// Stores the relationship between a key and a value. + /// We do not want to be so inefficient that we require + /// four bytes for each four byte property, so use an algorithm + /// that uses the bottom two bits of the key to identify + /// one of four elements in an entry. /// - private struct ObjectEntry { + private struct ObjectEntry + { public short Key; public short Mask; // only lower four bits are used; mask of used values. public object Value1; @@ -914,33 +922,44 @@ private struct ObjectEntry { public object Value4; } - - private sealed class ColorWrapper { + private sealed class ColorWrapper + { public Color Color; - public ColorWrapper(Color color){ - this.Color = color; + + public ColorWrapper(Color color) + { + Color = color; } } - - private sealed class PaddingWrapper{ + private sealed class PaddingWrapper + { public Padding Padding; - public PaddingWrapper(Padding padding){ - this.Padding = padding; + + public PaddingWrapper(Padding padding) + { + Padding = padding; } } - private sealed class RectangleWrapper{ + + private sealed class RectangleWrapper + { public Rectangle Rectangle; - public RectangleWrapper(Rectangle rectangle){ - this.Rectangle = rectangle; + + public RectangleWrapper(Rectangle rectangle) + { + Rectangle = rectangle; } } - private sealed class SizeWrapper { + + private sealed class SizeWrapper + { public Size Size; - public SizeWrapper(Size size){ - this.Size = size; + + public SizeWrapper(Size size) + { + Size = size; } } - } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/RadioButtonRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/RadioButtonRenderer.cs index 42044d32820..b88b0c09d9a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/RadioButtonRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/RadioButtonRenderer.cs @@ -279,8 +279,7 @@ internal static RadioButtonState ConvertFromButtonState(ButtonState state, bool private static void InitializeRenderer(int state) { RadioButtonState radioButtonState = (RadioButtonState)state; int part = RadioElement.Part; - if (AccessibilityImprovements.Level2 - && SystemInformation.HighContrast + if (SystemInformation.HighContrast && (radioButtonState == RadioButtonState.CheckedDisabled || radioButtonState == RadioButtonState.UncheckedDisabled) && VisualStyleRenderer.IsCombinationDefined(RadioElement.ClassName, VisualStyleElement.Button.RadioButton.HighContrastDisabledPart)) { part = VisualStyleElement.Button.RadioButton.HighContrastDisabledPart; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBox.cs index 33b78ceda55..bb9c47f8906 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBox.cs @@ -215,7 +215,7 @@ public bool AutoWordSelection { set { richTextBoxFlags[autoWordSelectionSection] = value ? 1 : 0; if (IsHandleCreated) { - SendMessage(RichTextBoxConstants.EM_SETOPTIONS, + SendMessage(Interop.EditMessages.EM_SETOPTIONS, value ? RichTextBoxConstants.ECOOP_OR : RichTextBoxConstants.ECOOP_XOR, RichTextBoxConstants.ECO_AUTOWORDSELECTION); } @@ -287,7 +287,7 @@ public int BulletIndent { set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(BulletIndent), string.Format(SR.InvalidArgument, "BulletIndent", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(BulletIndent), value)); } this.bulletIndent = value; @@ -322,7 +322,7 @@ public bool CanRedo { get { if (IsHandleCreated) { bool b; - b = unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_CANREDO, 0, 0)) != 0; + b = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_CANREDO, 0, 0)) != 0; return b; } @@ -415,7 +415,7 @@ public bool DetectUrls { if (value != DetectUrls) { richTextBoxFlags[autoUrlDetectSection] = value ? 1 : 0; if (IsHandleCreated) { - this.SendMessage(RichTextBoxConstants.EM_AUTOURLDETECT, value ? 1 : 0, 0); + this.SendMessage(Interop.EditMessages.EM_AUTOURLDETECT, value ? 1 : 0, 0); RecreateHandle(); } } @@ -548,7 +548,7 @@ public RichTextBoxLanguageOptions LanguageOption { RichTextBoxLanguageOptions opt; if (IsHandleCreated) { - opt = (RichTextBoxLanguageOptions)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETLANGOPTIONS, 0, 0); + opt = (RichTextBoxLanguageOptions)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETLANGOPTIONS, 0, 0); } else { opt = languageOption; @@ -561,7 +561,7 @@ public RichTextBoxLanguageOptions LanguageOption { this.languageOption = value; if (IsHandleCreated) { - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETLANGOPTIONS, 0, (int) value); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETLANGOPTIONS, 0, (int) value); } } } @@ -618,7 +618,7 @@ public string RedoActionName { get { if (!CanRedo) return ""; int n; - n = unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_GETREDONAME, 0, 0)); + n = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_GETREDONAME, 0, 0)); return GetEditorActionName(n); } } @@ -657,7 +657,7 @@ public int RightMargin { set { if (this.rightMargin != value) { if (value < 0) - throw new ArgumentOutOfRangeException(nameof(RightMargin), string.Format(SR.InvalidLowBoundArgumentEx, "RightMargin", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(RightMargin), value, 0)); this.rightMargin = value; if (value == 0) { @@ -668,7 +668,7 @@ public int RightMargin { else if (IsHandleCreated) { IntPtr hDC = UnsafeNativeMethods.CreateIC("DISPLAY", null, null, new HandleRef(null, IntPtr.Zero)); try { - SendMessage(RichTextBoxConstants.EM_SETTARGETDEVICE, hDC, (IntPtr)Pixel2Twip(hDC, value, true)); + SendMessage(Interop.EditMessages.EM_SETTARGETDEVICE, hDC, (IntPtr)Pixel2Twip(hDC, value, true)); } finally { if (hDC != IntPtr.Zero) { @@ -780,7 +780,7 @@ public HorizontalAlignment SelectionAlignment { pf.rgxTabs = new int[RichTextBoxConstants.MAX_TAB_STOPS]; // get the format for our currently selected paragraph - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); // check if alignment has been set yet if ((RichTextBoxConstants.PFM_ALIGNMENT & pf.dwMask) != 0) { @@ -827,7 +827,7 @@ public HorizontalAlignment SelectionAlignment { } // set the format for our current paragraph or selection - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETPARAFORMAT, 0, pf); } } @@ -851,7 +851,7 @@ public bool SelectionBullet { pf.rgxTabs = new int[RichTextBoxConstants.MAX_TAB_STOPS]; // get the format for our currently selected paragraph - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); // check if alignment has been set yet if ((RichTextBoxConstants.PFM_NUMBERING & pf.dwMask) != 0) { @@ -881,7 +881,7 @@ public bool SelectionBullet { pf.dxOffset = Pixel2Twip(IntPtr.Zero, bulletIndent, true); } // set the format for our current paragraph or selection - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETPARAFORMAT, 0, pf); } } @@ -917,7 +917,7 @@ public int SelectionCharOffset { } set { if (value > 2000 || value < -2000) - throw new ArgumentOutOfRangeException(nameof(SelectionCharOffset), string.Format(SR.InvalidBoundArgument, "SelectionCharOffset", value, -2000, 2000)); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(SelectionCharOffset), value, -2000, 2000)); ForceHandleCreate(); NativeMethods.CHARFORMATA cf = new NativeMethods.CHARFORMATA(); @@ -929,7 +929,7 @@ public int SelectionCharOffset { // we would cache property values until the handle is created - but for this property, // it's far more simple to just create the handle. // - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf); } } @@ -964,7 +964,7 @@ public Color SelectionColor { cf.crTextColor = ColorTranslator.ToWin32(value); // set the format information - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf); } } @@ -1015,7 +1015,7 @@ public Color SelectionBackColor { cf2.crBackColor = ColorTranslator.ToWin32(value); } - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf2); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf2); } } } @@ -1062,7 +1062,7 @@ public int SelectionHangingIndent { pf.rgxTabs = new int[RichTextBoxConstants.MAX_TAB_STOPS]; // get the format for our currently selected paragraph - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); // check if alignment has been set yet if ((RichTextBoxConstants.PFM_OFFSET & pf.dwMask) != 0) @@ -1078,7 +1078,7 @@ public int SelectionHangingIndent { pf.dxOffset = Pixel2Twip(IntPtr.Zero, value, true); // set the format for our current paragraph or selection - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETPARAFORMAT, 0, pf); } } @@ -1103,7 +1103,7 @@ public int SelectionIndent { pf.rgxTabs = new int[RichTextBoxConstants.MAX_TAB_STOPS]; // get the format for our currently selected paragraph - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); // check if alignment has been set yet if ((RichTextBoxConstants.PFM_STARTINDENT & pf.dwMask) != 0) @@ -1119,7 +1119,7 @@ public int SelectionIndent { pf.dxStartIndent = Pixel2Twip(IntPtr.Zero, value, true); // set the format for our current paragraph or selection - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETPARAFORMAT, 0, pf); } } @@ -1222,7 +1222,7 @@ public int SelectionRightIndent { pf.rgxTabs = new int[RichTextBoxConstants.MAX_TAB_STOPS]; // get the format for our currently selected paragraph - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); // check if alignment has been set yet if ((RichTextBoxConstants.PFM_RIGHTINDENT & pf.dwMask) != 0) @@ -1232,7 +1232,7 @@ public int SelectionRightIndent { } set { if (value < 0) - throw new ArgumentOutOfRangeException(nameof(SelectionRightIndent), string.Format(SR.InvalidLowBoundArgumentEx, "SelectionRightIndent", value, 0)); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectionRightIndent), value, 0)); ForceHandleCreate(); NativeMethods.PARAFORMAT pf = new NativeMethods.PARAFORMAT(); @@ -1240,7 +1240,7 @@ public int SelectionRightIndent { pf.dxRightIndent = Pixel2Twip(IntPtr.Zero, value, true); // set the format for our current paragraph or selection - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETPARAFORMAT, 0, pf); } } @@ -1262,7 +1262,7 @@ public int[] SelectionTabs { pf.rgxTabs = new int[RichTextBoxConstants.MAX_TAB_STOPS]; // get the format for our currently selected paragraph - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); // check if alignment has been set yet if ((RichTextBoxConstants.PFM_TABSTOPS & pf.dwMask) != 0) { @@ -1284,7 +1284,7 @@ public int[] SelectionTabs { // get the format for our currently selected paragraph because // we need to get the number of tabstops to copy - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETPARAFORMAT, 0, pf); pf.cTabCount = (short)((value == null) ? 0 : value.Length); pf.dwMask = RichTextBoxConstants.PFM_TABSTOPS; @@ -1292,7 +1292,7 @@ public int[] SelectionTabs { pf.rgxTabs[x] = Pixel2Twip(IntPtr.Zero, value[x], true); // set the format for our current paragraph or selection - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETPARAFORMAT, 0, pf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETPARAFORMAT, 0, pf); } } @@ -1336,7 +1336,7 @@ public RichTextBoxSelectionTypes SelectionType { ForceHandleCreate(); if (SelectionLength > 0) { int n; - n = unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_SELECTIONTYPE, 0, 0)); + n = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_SELECTIONTYPE, 0, 0)); return (RichTextBoxSelectionTypes)n; } else { @@ -1361,7 +1361,7 @@ public bool ShowSelectionMargin { if (value != ShowSelectionMargin) { richTextBoxFlags[showSelBarSection] = value ? 1 : 0; if (IsHandleCreated) { - SendMessage(RichTextBoxConstants.EM_SETOPTIONS, + SendMessage(Interop.EditMessages.EM_SETOPTIONS, value ? RichTextBoxConstants.ECOOP_OR : RichTextBoxConstants.ECOOP_XOR, RichTextBoxConstants.ECO_SELECTIONBAR); @@ -1418,7 +1418,7 @@ public override string Text { } StreamIn(value, RichTextBoxConstants.SF_TEXT | RichTextBoxConstants.SF_UNICODE); // reset Modified - SendMessage(NativeMethods.EM_SETMODIFY, 0, 0); + SendMessage(Interop.EditMessages.EM_SETMODIFY, 0, 0); } } } @@ -1446,7 +1446,7 @@ public override int TextLength { codepage = 1200 /* CP_UNICODE */ }; - return unchecked((int)(long)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETTEXTLENGTHEX, gtl, 0 /*ignored*/)); + return unchecked((int)(long)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETTEXTLENGTHEX, gtl, 0 /*ignored*/)); } } @@ -1468,7 +1468,7 @@ public string UndoActionName { get { if (!CanUndo) return ""; int n; - n = unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_GETUNDONAME, 0, 0)); + n = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_GETUNDONAME, 0, 0)); return GetEditorActionName(n); } } @@ -1510,7 +1510,7 @@ public float ZoomFactor { if (IsHandleCreated) { int numerator = 0; int denominator = 0; - SendMessage(RichTextBoxConstants.EM_GETZOOM, ref numerator, ref denominator); + SendMessage(Interop.EditMessages.EM_GETZOOM, ref numerator, ref denominator); if ( (numerator != 0) && (denominator != 0) ) { zoomMultiplier = ((float)numerator)/((float)denominator); } @@ -1522,12 +1522,17 @@ public float ZoomFactor { else return zoomMultiplier; } - set { - if (zoomMultiplier == value) return; - + set + { if (value <= 0.015625f || value >= 64.0f) - throw new ArgumentOutOfRangeException(nameof(ZoomFactor), string.Format(SR.InvalidExBoundArgument, "ZoomFactor", (value).ToString(CultureInfo.CurrentCulture), (0.015625f).ToString(CultureInfo.CurrentCulture), (64.0f).ToString(CultureInfo.CurrentCulture))); - SendZoomFactor(value); + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidExBoundArgument, nameof(ZoomFactor), value, 0.015625f, 64.0f)); + } + + if (value != zoomMultiplier) + { + SendZoomFactor(value); + } } } @@ -1695,7 +1700,7 @@ public event EventHandler VScroll { /// public bool CanPaste(DataFormats.Format clipFormat) { bool b = false; - b = unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_CANPASTE, clipFormat.Id, 0)) != 0; + b = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_CANPASTE, clipFormat.Id, 0)) != 0; return b; } @@ -1862,9 +1867,9 @@ public int Find(string str, int start, int end, RichTextBoxFinds options) { if (str == null) throw new ArgumentNullException(nameof(str)); if (start < 0 || start > textLen) - throw new ArgumentOutOfRangeException(nameof(start), string.Format(SR.InvalidBoundArgument, "start", start, 0, textLen)); + throw new ArgumentOutOfRangeException(nameof(start), start, string.Format(SR.InvalidBoundArgument, nameof(start), start, 0, textLen)); if (end < -1) - throw new ArgumentOutOfRangeException(nameof(end), string.Format(SR.RichTextFindEndInvalid, end)); + throw new ArgumentOutOfRangeException(nameof(end), end, string.Format(SR.RichTextFindEndInvalid, end)); bool selectWord = true; NativeMethods.FINDTEXT ft = new NativeMethods.FINDTEXT(); @@ -1922,7 +1927,7 @@ public int Find(string str, int start, int end, RichTextBoxFinds options) { // Perform the find, will return ubyte position int position; - position = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_FINDTEXT, findOptions, ft); + position = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_FINDTEXT, findOptions, ft); // if we didn't find anything, or we don't have to select what was found, @@ -1960,8 +1965,8 @@ public int Find(string str, int start, int end, RichTextBoxFinds options) { chrg.cpMax = foundCursor; } - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_EXSETSEL, 0, chrg); - SendMessage(NativeMethods.EM_SCROLLCARET, 0, 0); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_EXSETSEL, 0, chrg); + SendMessage(Interop.EditMessages.EM_SCROLLCARET, 0, 0); } @@ -2000,9 +2005,9 @@ public int Find(char[] characterSet, int start, int end) { if (characterSet == null) throw new ArgumentNullException(nameof(characterSet)); if (start < 0 || start > textLength) - throw new ArgumentOutOfRangeException(nameof(start), string.Format(SR.InvalidBoundArgument, "start", start, 0, textLength)); + throw new ArgumentOutOfRangeException(nameof(start), start, string.Format(SR.InvalidBoundArgument, nameof(start), start, 0, textLength)); if (end < start && end != -1) - throw new ArgumentOutOfRangeException(nameof(end), string.Format(SR.InvalidLowBoundArgumentEx, "end", end, "start")); + throw new ArgumentOutOfRangeException(nameof(end), end, string.Format(SR.InvalidLowBoundArgumentEx, nameof(end), end, nameof(start))); // Don't do anything if we get nothing to look for if (characterSet.Length == 0) @@ -2065,7 +2070,7 @@ public int Find(char[] characterSet, int start, int end) { // go get the text in this range, if we didn't get any text then punt int len; - len = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETTEXTRANGE, 0, txrg); + len = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETTEXTRANGE, 0, txrg); if (len == 0) { chrg.cpMax = chrg.cpMin = -1; // Hit end of control without finding what we wanted break; @@ -2142,13 +2147,13 @@ private bool InternalSetForeColor(Color value) { private NativeMethods.CHARFORMATA GetCharFormat(bool fSelection) { NativeMethods.CHARFORMATA cf = new NativeMethods.CHARFORMATA(); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETCHARFORMAT, fSelection ? RichTextBoxConstants.SCF_SELECTION : RichTextBoxConstants.SCF_DEFAULT, cf); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETCHARFORMAT, fSelection ? RichTextBoxConstants.SCF_SELECTION : RichTextBoxConstants.SCF_DEFAULT, cf); return cf; } private NativeMethods.CHARFORMAT2A GetCharFormat2(bool fSelection) { NativeMethods.CHARFORMAT2A cf2 = new NativeMethods.CHARFORMAT2A(); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETCHARFORMAT, fSelection ? RichTextBoxConstants.SCF_SELECTION : RichTextBoxConstants.SCF_DEFAULT, cf2); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETCHARFORMAT, fSelection ? RichTextBoxConstants.SCF_SELECTION : RichTextBoxConstants.SCF_DEFAULT, cf2); return cf2; } @@ -2219,7 +2224,7 @@ Font GetCharFormatFont(bool selectionOnly) { /// public override int GetCharIndexFromPosition(Point pt) { NativeMethods.POINT wpt = new NativeMethods.POINT(pt.X, pt.Y); - int index = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_CHARFROMPOS, 0, wpt); + int index = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_CHARFROMPOS, 0, wpt); string t = this.Text; // EM_CHARFROMPOS will return an invalid number if the last character in the RichEdit @@ -2256,7 +2261,7 @@ private bool GetCharInCharSet(char c, char[] charSet, bool negate) { /// return 1 and not 0. /// public override int GetLineFromCharIndex(int index) { - return unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_EXLINEFROMCHAR, 0, index)); + return unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_EXLINEFROMCHAR, 0, index)); } /// @@ -2273,7 +2278,7 @@ public override Point GetPositionFromCharIndex(int index) { } NativeMethods.POINT pt = new NativeMethods.POINT(); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_POSFROMCHAR, pt, index); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_POSFROMCHAR, pt, index); return new Point(pt.x, pt.y); } @@ -2356,7 +2361,7 @@ public void LoadFile(Stream data, RichTextBoxStreamType fileType) { protected override void OnBackColorChanged(EventArgs e) { if (IsHandleCreated) { - SendMessage(RichTextBoxConstants.EM_SETBKGNDCOLOR, 0, ColorTranslator.ToWin32(BackColor)); + SendMessage(Interop.EditMessages.EM_SETBKGNDCOLOR, 0, ColorTranslator.ToWin32(BackColor)); } base.OnBackColorChanged(e); } @@ -2429,7 +2434,7 @@ protected override void OnHandleCreated(EventArgs e) { // This is needed so that the control will fire change and update events // even if it is hidden // - SendMessage(RichTextBoxConstants.EM_SETEVENTMASK, + SendMessage(Interop.EditMessages.EM_SETEVENTMASK, 0, RichTextBoxConstants.ENM_PROTECTED | RichTextBoxConstants.ENM_SELCHANGE | RichTextBoxConstants.ENM_DROPFILES | RichTextBoxConstants.ENM_REQUESTRESIZE | @@ -2445,7 +2450,7 @@ protected override void OnHandleCreated(EventArgs e) { // - this.SendMessage(RichTextBoxConstants.EM_AUTOURLDETECT, DetectUrls ? 1 : 0, 0); + this.SendMessage(Interop.EditMessages.EM_AUTOURLDETECT, DetectUrls ? 1 : 0, 0); if (selectionBackColorToSetOnHandleCreated != Color.Empty) { this.SelectionBackColor = selectionBackColorToSetOnHandleCreated; } @@ -2453,7 +2458,7 @@ protected override void OnHandleCreated(EventArgs e) { // Initialize colors before initializing RTF, otherwise CFE_AUTOCOLOR will be in effect // and our text will all be Color.WindowText. AutoWordSelection = AutoWordSelection; - SendMessage(RichTextBoxConstants.EM_SETBKGNDCOLOR, 0, ColorTranslator.ToWin32(BackColor)); + SendMessage(Interop.EditMessages.EM_SETBKGNDCOLOR, 0, ColorTranslator.ToWin32(BackColor)); InternalSetForeColor(ForeColor); // base sets the Text property. It's important to do this *after* setting EM_AUTOUrlDETECT. @@ -2489,7 +2494,7 @@ protected override void OnHandleCreated(EventArgs e) { if (ShowSelectionMargin) { // If you call SendMessage instead of PostMessage, the control // will resize itself to the size of the parent's client area. Don't know why... - UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETOPTIONS, (IntPtr)RichTextBoxConstants.ECOOP_OR, + UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETOPTIONS, (IntPtr)RichTextBoxConstants.ECOOP_OR, (IntPtr)RichTextBoxConstants.ECO_SELECTIONBAR); } @@ -2599,7 +2604,7 @@ private void PasteUnsafe(DataFormats.Format clipFormat, int hIcon) { rps.dwAspect = DVASPECT_ICON; rps.dwParam = hIcon; } - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_PASTESPECIAL, clipFormat.Id, rps); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_PASTESPECIAL, clipFormat.Id, rps); } /// @@ -2619,7 +2624,7 @@ protected override bool ProcessCmdKey(ref Message m, Keys keyData) { /// Redoes the last undone editing operation. /// public void Redo() { - SendMessage(RichTextBoxConstants.EM_REDO, 0, 0); + SendMessage(Interop.EditMessages.EM_REDO, 0, 0); } //NOTE: Undo is implemented on TextBox @@ -2708,13 +2713,13 @@ private void SendZoomFactor(float zoom) { } if (IsHandleCreated) { - SendMessage(RichTextBoxConstants.EM_SETZOOM, numerator, denominator); + SendMessage(Interop.EditMessages.EM_SETZOOM, numerator, denominator); #if DEBUG // DEBUG CODE: Verify that EM_SETZOOM actually set the zoom int n = 0, d = 0; - SendMessage(RichTextBoxConstants.EM_GETZOOM, ref n, ref d); + SendMessage(Interop.EditMessages.EM_GETZOOM, ref n, ref d); Debug.Assert(n == numerator && d == denominator, "EM_SETZOOM failed"); // END DEBUG CODE #endif @@ -2751,13 +2756,13 @@ private bool SetCharFormat(int mask, int effect, RichTextBoxSelectionAttribute c } // set the format information - return IntPtr.Zero != UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf); + return IntPtr.Zero != UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf); } return false; } private bool SetCharFormat(int charRange, NativeMethods.CHARFORMATA cf) { - return IntPtr.Zero != UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, charRange, cf); + return IntPtr.Zero != UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETCHARFORMAT, charRange, cf); } private void SetCharFormatFont(bool selectionOnly, Font value) { @@ -2788,7 +2793,7 @@ private void SetCharFormatFont(bool selectionOnly, Font value) { cfW.bCharSet = logfont.lfCharSet; cfW.bPitchAndFamily = logfont.lfPitchAndFamily; - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, selectionOnly ? RichTextBoxConstants.SCF_SELECTION : RichTextBoxConstants.SCF_ALL, cfW); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETCHARFORMAT, selectionOnly ? RichTextBoxConstants.SCF_SELECTION : RichTextBoxConstants.SCF_ALL, cfW); } /// @@ -2829,13 +2834,13 @@ private void StreamIn(string str, int flags) { // selection text // if ((RichTextBoxConstants.SFF_SELECTION & flags) != 0) { - SendMessage(NativeMethods.WM_CLEAR, 0, 0); + SendMessage(Interop.WindowMessages.WM_CLEAR, 0, 0); ProtectedError = false; return; } // WM_SETTEXT is allowed even if we have protected text // - SendMessage(NativeMethods.WM_SETTEXT, 0, ""); + SendMessage(Interop.WindowMessages.WM_SETTEXT, 0, ""); return; } @@ -2865,7 +2870,7 @@ private void StreamIn(Stream data, int flags) { // if ((flags & RichTextBoxConstants.SFF_SELECTION) == 0) { NativeMethods.CHARRANGE cr = new NativeMethods.CHARRANGE(); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_EXSETSEL, 0, cr); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_EXSETSEL, 0, cr); } try { @@ -2908,7 +2913,7 @@ private void StreamIn(Stream data, int flags) { // gives us TextBox compatible behavior, programatic text change shouldn't // be limited... // - SendMessage(RichTextBoxConstants.EM_EXLIMITTEXT, 0, int.MaxValue); + SendMessage(Interop.EditMessages.EM_EXLIMITTEXT, 0, int.MaxValue); @@ -2916,13 +2921,13 @@ private void StreamIn(Stream data, int flags) { // Needed for 64-bit if (IntPtr.Size == 8) { NativeMethods.EDITSTREAM64 es64 = ConvertToEDITSTREAM64(es); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_STREAMIN, flags, es64); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_STREAMIN, flags, es64); //Assign back dwError value es.dwError = GetErrorValue64(es64); } else { - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_STREAMIN, flags, es); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_STREAMIN, flags, es); } UpdateMaxLength(); @@ -2937,10 +2942,10 @@ private void StreamIn(Stream data, int flags) { throw new InvalidOperationException(SR.LoadTextError); // set the modify tag on the control - SendMessage(NativeMethods.EM_SETMODIFY, -1, 0); + SendMessage(Interop.EditMessages.EM_SETMODIFY, -1, 0); // EM_GETLINECOUNT will cause the RichTextBoxConstants to recalculate its line indexes - SendMessage(NativeMethods.EM_GETLINECOUNT, 0, 0); + SendMessage(Interop.EditMessages.EM_GETLINECOUNT, 0, 0); } @@ -3013,13 +3018,13 @@ private void StreamOut(Stream data, int flags, bool includeCrLfs) { // Needed for 64-bit if (IntPtr.Size == 8) { NativeMethods.EDITSTREAM64 es64 = ConvertToEDITSTREAM64(es); - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_STREAMOUT, flags, es64); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_STREAMOUT, flags, es64); //Assign back dwError value es.dwError = GetErrorValue64(es64); } else { - UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_STREAMOUT, flags, es); + UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_STREAMOUT, flags, es); } // check to make sure things went well @@ -3118,7 +3123,7 @@ private void UpdateOleCallback() { Guid iidRichEditOleCallback = typeof(UnsafeNativeMethods.IRichEditOleCallback).GUID; Marshal.QueryInterface(punk, ref iidRichEditOleCallback, out pRichEditOleCallback); try { - UnsafeNativeMethods.SendCallbackMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETOLECALLBACK, IntPtr.Zero, pRichEditOleCallback); + UnsafeNativeMethods.SendCallbackMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETOLECALLBACK, IntPtr.Zero, pRichEditOleCallback); } finally { Marshal.Release(pRichEditOleCallback); @@ -3139,7 +3144,7 @@ private void UserPreferenceChangedHandler(object o, UserPreferenceChangedEventAr { if (this.BackColor.IsSystemColor) { - SendMessage(RichTextBoxConstants.EM_SETBKGNDCOLOR, 0, ColorTranslator.ToWin32(BackColor)); + SendMessage(Interop.EditMessages.EM_SETBKGNDCOLOR, 0, ColorTranslator.ToWin32(BackColor)); } if (this.ForeColor.IsSystemColor) { @@ -3175,12 +3180,12 @@ private void EnLinkMsgHandler(ref Message m) { } switch (enlink.msg) { - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: LinkCursor = true; m.Result = (IntPtr)1; return; // Mouse-down triggers Url; this matches Outlook 2000's behavior. - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: string linktext = CharRangeToString(enlink.charrange); if (!string.IsNullOrEmpty(linktext)) { @@ -3218,7 +3223,7 @@ private string CharRangeToString(NativeMethods.CHARRANGE c) { throw new OutOfMemoryException(SR.OutOfMemory); txrg.lpstrText = unmanagedBuffer; - int len = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETTEXTRANGE, 0, txrg); + int len = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETTEXTRANGE, 0, txrg); Debug.Assert(len != 0, "CHARRANGE from RichTextBox was bad! - impossible?"); charBuffer.PutCoTaskMem(unmanagedBuffer); if (txrg.lpstrText != IntPtr.Zero) @@ -3230,7 +3235,7 @@ private string CharRangeToString(NativeMethods.CHARRANGE c) { internal override void UpdateMaxLength() { if (IsHandleCreated) { - SendMessage(RichTextBoxConstants.EM_EXLIMITTEXT, 0, MaxLength); + SendMessage(Interop.EditMessages.EM_EXLIMITTEXT, 0, MaxLength); } } @@ -3280,7 +3285,7 @@ internal void WmReflectNotify(ref Message m) { NativeMethods.ENDROPFILES endropfiles = (NativeMethods.ENDROPFILES)m.GetLParam(typeof(NativeMethods.ENDROPFILES)); // Only look at the first file. - StringBuilder path = new StringBuilder(NativeMethods.MAX_PATH); + StringBuilder path = new StringBuilder(Interop.Kernel32.MAX_PATH); if (UnsafeNativeMethods.DragQueryFileLongPath(new HandleRef(endropfiles, endropfiles.hDrop), 0, path) != 0) { // Try to load the file as an RTF @@ -3333,10 +3338,10 @@ internal void WmReflectNotify(ref Message m) { switch (enprotected.msg) { - case RichTextBoxConstants.EM_SETCHARFORMAT: + case Interop.EditMessages.EM_SETCHARFORMAT: // Allow change of protected style // - NativeMethods.CHARFORMATA charFormat = (NativeMethods.CHARFORMATA)UnsafeNativeMethods.PtrToStructure(enprotected.lParam, typeof(NativeMethods.CHARFORMATA)); + NativeMethods.CHARFORMATA charFormat = Marshal.PtrToStructure(enprotected.lParam); if ((charFormat.dwMask & RichTextBoxConstants.CFM_PROTECTED) != 0) { m.Result = IntPtr.Zero; return; @@ -3345,11 +3350,11 @@ internal void WmReflectNotify(ref Message m) { // Throw an exception for the following // - case RichTextBoxConstants.EM_SETPARAFORMAT: - case NativeMethods.EM_REPLACESEL: + case Interop.EditMessages.EM_SETPARAFORMAT: + case Interop.EditMessages.EM_REPLACESEL: break; - case RichTextBoxConstants.EM_STREAMIN: + case Interop.EditMessages.EM_STREAMIN: // Don't allow STREAMIN to replace protected selection // if ((unchecked( (int) (long)enprotected.wParam) & RichTextBoxConstants.SFF_SELECTION) != 0) @@ -3359,9 +3364,9 @@ internal void WmReflectNotify(ref Message m) { // Allow the following // - case NativeMethods.WM_COPY: - case NativeMethods.WM_SETTEXT: - case RichTextBoxConstants.EM_EXLIMITTEXT: + case Interop.WindowMessages.WM_COPY: + case Interop.WindowMessages.WM_SETTEXT: + case Interop.EditMessages.EM_EXLIMITTEXT: m.Result = IntPtr.Zero; return; @@ -3454,15 +3459,15 @@ private void WmSelectionChange(NativeMethods.SELCHANGE selChange) { if( ImeMode == ImeMode.Hangul || ImeMode == ImeMode.HangulFull ) { // Is the IME CompositionWindow open? - int compMode = unchecked( (int) (long)SendMessage(RichTextBoxConstants.EM_GETIMECOMPMODE, 0, 0)); + int compMode = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_GETIMECOMPMODE, 0, 0)); if (RichTextBoxConstants.ICM_NOTOPEN != compMode) { int textLength = SafeNativeMethods.GetWindowTextLength(new HandleRef(this, Handle)); if (selStart == selEnd && textLength == MaxLength) { - SendMessage(NativeMethods.WM_KILLFOCUS, 0, 0); - SendMessage(NativeMethods.WM_SETFOCUS, 0, 0); - UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), NativeMethods.EM_SETSEL, selEnd - 1, selEnd); + SendMessage(Interop.WindowMessages.WM_KILLFOCUS, 0, 0); + SendMessage(Interop.WindowMessages.WM_SETFOCUS, 0, 0); + UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_SETSEL, selEnd - 1, selEnd); } } } @@ -3502,15 +3507,15 @@ private void WmSetFont(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: WmReflectNotify(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_COMMAND: WmReflectCommand(ref m); break; - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: //NOTE: RichTextBox uses the WM_SETCURSOR message over links to allow us to // change the cursor to a hand. It does this through a synchronous notification // message. So we have to pass the message to the DefWndProc first, and @@ -3531,21 +3536,21 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_SETFONT: + case Interop.WindowMessages.WM_SETFONT: WmSetFont(ref m); break; - case NativeMethods.WM_IME_NOTIFY: + case Interop.WindowMessages.WM_IME_NOTIFY: OnImeChange(EventArgs.Empty); base.WndProc(ref m); break; - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: base.WndProc(ref m); m.Result = (IntPtr)((AcceptsTab) ? unchecked( (int) (long)m.Result) | NativeMethods.DLGC_WANTTAB : unchecked( (int) (long)m.Result) & ~NativeMethods.DLGC_WANTTAB); break; - case NativeMethods.WM_GETOBJECT: + case Interop.WindowMessages.WM_GETOBJECT: base.WndProc(ref m); // OLEACC.DLL uses window class names to identify standard control types. But WinForm controls use app-specific window @@ -3557,7 +3562,7 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: //since RichEdit eats up the WM_CONTEXTMENU message, we need to force DefWndProc //to spit out this message again on receiving WM_RBUTTONUP message. By setting UserMouse //style to true, we effectily let the WmMouseUp method in Control.cs to generate @@ -3568,7 +3573,7 @@ protected override void WndProc(ref Message m) { SetStyle(ControlStyles.UserMouse, oldStyle); break; - case NativeMethods.WM_VSCROLL: + case Interop.WindowMessages.WM_VSCROLL: base.WndProc(ref m); int loWord = Util.LOWORD(m.WParam); if (loWord == NativeMethods.SB_THUMBTRACK) @@ -3581,7 +3586,7 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_HSCROLL: + case Interop.WindowMessages.WM_HSCROLL: base.WndProc(ref m); loWord = Util.LOWORD(m.WParam); if (loWord == NativeMethods.SB_THUMBTRACK) @@ -3846,7 +3851,7 @@ public int GetContextMenu(short seltype, IntPtr lpoleobj, NativeMethods.CHARRANG if (menu == cm) break; else - menu = ((MenuItem) menu).Menu; + menu = ((MenuItem)menu).Parent; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBoxConstants.cs b/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBoxConstants.cs index ec796638868..d93c3453265 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBoxConstants.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/RichTextBoxConstants.cs @@ -51,102 +51,6 @@ internal static class RichTextBoxConstants { internal const string WC_RICHEDITW_41 = RICHEDIT_CLASS41W; /* RichTextBox messages */ - internal const int WM_CONTEXTMENU = 0x007B; - - internal const int WM_PRINTCLIENT = 0x0318; - - internal const int EM_GETLIMITTEXT = (NativeMethods.WM_USER + 37); - - internal const int EM_POSFROMCHAR = (NativeMethods.WM_USER + 38); - internal const int EM_CHARFROMPOS = (NativeMethods.WM_USER + 39); - - internal const int EM_SCROLLCARET = (NativeMethods.WM_USER + 49); - internal const int EM_CANPASTE = (NativeMethods.WM_USER + 50); - internal const int EM_DISPLAYBAND = (NativeMethods.WM_USER + 51); - internal const int EM_EXGETSEL = (NativeMethods.WM_USER + 52); - internal const int EM_EXLIMITTEXT = (NativeMethods.WM_USER + 53); - internal const int EM_EXLINEFROMCHAR = (NativeMethods.WM_USER + 54); - internal const int EM_EXSETSEL = (NativeMethods.WM_USER + 55); - internal const int EM_FINDTEXT = (NativeMethods.WM_USER + 56); - internal const int EM_FORMATRANGE = (NativeMethods.WM_USER + 57); - internal const int EM_GETCHARFORMAT = (NativeMethods.WM_USER + 58); - internal const int EM_GETEVENTMASK = (NativeMethods.WM_USER + 59); - internal const int EM_GETOLEINTERFACE = (NativeMethods.WM_USER + 60); - internal const int EM_GETPARAFORMAT = (NativeMethods.WM_USER + 61); - internal const int EM_GETSELTEXT = (NativeMethods.WM_USER + 62); - internal const int EM_HIDESELECTION = (NativeMethods.WM_USER + 63); - internal const int EM_PASTESPECIAL = (NativeMethods.WM_USER + 64); - internal const int EM_REQUESTRESIZE = (NativeMethods.WM_USER + 65); - internal const int EM_SELECTIONTYPE = (NativeMethods.WM_USER + 66); - internal const int EM_SETBKGNDCOLOR = (NativeMethods.WM_USER + 67); - internal const int EM_SETCHARFORMAT = (NativeMethods.WM_USER + 68); - internal const int EM_SETEVENTMASK = (NativeMethods.WM_USER + 69); - internal const int EM_SETOLECALLBACK = (NativeMethods.WM_USER + 70); - internal const int EM_SETPARAFORMAT = (NativeMethods.WM_USER + 71); - internal const int EM_SETTARGETDEVICE = (NativeMethods.WM_USER + 72); - internal const int EM_STREAMIN = (NativeMethods.WM_USER + 73); - internal const int EM_STREAMOUT = (NativeMethods.WM_USER + 74); - internal const int EM_GETTEXTRANGE = (NativeMethods.WM_USER + 75); - internal const int EM_FINDWORDBREAK = (NativeMethods.WM_USER + 76); - internal const int EM_SETOPTIONS = (NativeMethods.WM_USER + 77); - internal const int EM_GETOPTIONS = (NativeMethods.WM_USER + 78); - internal const int EM_FINDTEXTEX = (NativeMethods.WM_USER + 79); - internal const int EM_GETWORDBREAKPROCEX = (NativeMethods.WM_USER + 80); - internal const int EM_SETWORDBREAKPROCEX = (NativeMethods.WM_USER + 81); - - // Richedit v2.0 messages - internal const int EM_SETUNDOLIMIT = (NativeMethods.WM_USER + 82); - internal const int EM_REDO = (NativeMethods.WM_USER + 84); - internal const int EM_CANREDO = (NativeMethods.WM_USER + 85); - internal const int EM_GETUNDONAME = (NativeMethods.WM_USER + 86); - internal const int EM_GETREDONAME = (NativeMethods.WM_USER + 87); - internal const int EM_STOPGROUPTYPING = (NativeMethods.WM_USER + 88); - - internal const int EM_SETTEXTMODE = (NativeMethods.WM_USER + 89); - internal const int EM_GETTEXTMODE = (NativeMethods.WM_USER + 90); - - internal const int EM_AUTOURLDETECT = (NativeMethods.WM_USER + 91); - internal const int EM_GETAUTOURLDETECT = (NativeMethods.WM_USER + 92); - internal const int EM_SETPALETTE = (NativeMethods.WM_USER + 93); - internal const int EM_GETTEXTEX = (NativeMethods.WM_USER + 94); - internal const int EM_GETTEXTLENGTHEX = (NativeMethods.WM_USER + 95); - - // Asia specific messages - internal const int EM_SETPUNCTUATION = (NativeMethods.WM_USER + 100); - internal const int EM_GETPUNCTUATION = (NativeMethods.WM_USER + 101); - internal const int EM_SETWORDWRAPMODE = (NativeMethods.WM_USER + 102); - internal const int EM_GETWORDWRAPMODE = (NativeMethods.WM_USER + 103); - internal const int EM_SETIMECOLOR = (NativeMethods.WM_USER + 104); - internal const int EM_GETIMECOLOR = (NativeMethods.WM_USER + 105); - internal const int EM_SETIMEOPTIONS = (NativeMethods.WM_USER + 106); - internal const int EM_GETIMEOPTIONS = (NativeMethods.WM_USER + 107); - internal const int EM_CONVPOSITION = (NativeMethods.WM_USER + 108); - - internal const int EM_SETLANGOPTIONS = (NativeMethods.WM_USER + 120); - internal const int EM_GETLANGOPTIONS = (NativeMethods.WM_USER + 121); - internal const int EM_GETIMECOMPMODE = (NativeMethods.WM_USER + 122); - - internal const int EM_FINDTEXTW = (NativeMethods.WM_USER + 123); - internal const int EM_FINDTEXTEXW = (NativeMethods.WM_USER + 124); - - //Rich TextBox 3.0 Asia msgs - internal const int EM_RECONVERSION = (NativeMethods.WM_USER + 125); - internal const int EM_SETIMEMODEBIAS = (NativeMethods.WM_USER + 126); - internal const int EM_GETIMEMODEBIAS = (NativeMethods.WM_USER + 127); - - // BiDi Specific messages - internal const int EM_SETBIDIOPTIONS = (NativeMethods.WM_USER + 200); - internal const int EM_GETBIDIOPTIONS = (NativeMethods.WM_USER + 201); - - internal const int EM_SETTYPOGRAPHYOPTIONS = (NativeMethods.WM_USER + 202); - internal const int EM_GETTYPOGRAPHYOPTIONS = (NativeMethods.WM_USER + 203); - - // Extended TextBox style specific messages - internal const int EM_SETEDITSTYLE = (NativeMethods.WM_USER + 204); - internal const int EM_GETEDITSTYLE = (NativeMethods.WM_USER + 205); - - // Ole Objects Disabling message - internal const int EM_SETQUERYRTFOBJ = (NativeMethods.WM_USER + 270); // Extended edit style masks internal const int SES_EMULATESYSEDIT = 1; @@ -181,20 +85,6 @@ internal static class RichTextBoxConstants { internal const int ICM_LEVEL2_5 = 0x0003; internal const int ICM_LEVEL2_SUI = 0x0004; - // Pegasus outline mode messages (RE 3.0) - - // Outline mode message - internal const int EM_OUTLINE = NativeMethods.WM_USER + 220; - - // Message for getting and restoring scroll pos - internal const int EM_GETSCROLLPOS = NativeMethods.WM_USER + 221; - internal const int EM_SETSCROLLPOS = NativeMethods.WM_USER + 222; - - // Change fontsize in current selection by wparam - internal const int EM_SETFONTSIZE = NativeMethods.WM_USER + 223; - internal const int EM_GETZOOM = NativeMethods.WM_USER + 224; - internal const int EM_SETZOOM = NativeMethods.WM_USER + 225; - // Outline mode wparam values internal const int EMO_EXIT = 0; // enter normal mode, lparam ignored internal const int EMO_ENTER = 1; // enter outline mode, lparam ignored diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ScrollBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ScrollBar.cs index 6a7da6f90b3..efefe44aa68 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ScrollBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ScrollBar.cs @@ -2,495 +2,419 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Runtime.Serialization.Formatters; - using System.Runtime.InteropServices; - using System.Runtime.Remoting; - using System.Diagnostics; - - using System; - - using System.Windows.Forms; - using System.ComponentModel; - using System.Drawing; - using Microsoft.Win32; - using System.Globalization; - - - /// - /// - /// - /// Implements the basic functionality of a scroll bar control. - /// - /// - [ - ComVisible(true), - ClassInterface(ClassInterfaceType.AutoDispatch), - DefaultProperty(nameof(Value)), - DefaultEvent(nameof(Scroll)), - System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors") // Shipped in Everett - ] - public abstract class ScrollBar : Control { - - private static readonly object EVENT_SCROLL = new object(); - private static readonly object EVENT_VALUECHANGED = new object(); - - private int minimum = 0; - private int maximum = 100; - private int smallChange = 1; - private int largeChange = 10; - private int value = 0; - private ScrollOrientation scrollOrientation; - private int wheelDelta = 0; - private bool scaleScrollBarForDpiChange = true; - - /// - /// - /// - /// Initializes a new instance of the - /// class. - /// - /// - /// - public ScrollBar() - : base() { +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms +{ + /// + /// Implements the basic functionality of a scroll bar control. + /// + [ComVisible(true)] + [ClassInterface(ClassInterfaceType.AutoDispatch)] + [DefaultProperty(nameof(Value))] + [DefaultEvent(nameof(Scroll))] + [SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors", Justification = "Already shipped as public API")] + public abstract class ScrollBar : Control + { + private static readonly object s_scrollEvent = new object(); + private static readonly object s_valueChangedEvent = new object(); + + private int _minimum = 0; + private int _maximum = 100; + private int _smallChange = 1; + private int _largeChange = 10; + private int _value = 0; + private ScrollOrientation _scrollOrientation; + private int _wheelDelta = 0; + private bool _scaleScrollBarForDpiChange = true; + + /// + /// Initializes a new instance of the class. + /// + public ScrollBar() : base() + { SetStyle(ControlStyles.UserPaint, false); SetStyle(ControlStyles.StandardClick, false); SetStyle(ControlStyles.UseTextForAccessibility, false); TabStop = false; - if ((this.CreateParams.Style & NativeMethods.SBS_VERT) != 0) + if ((CreateParams.Style & NativeMethods.SBS_VERT) != 0) { - scrollOrientation = ScrollOrientation.VerticalScroll; + _scrollOrientation = ScrollOrientation.VerticalScroll; } else { - scrollOrientation = ScrollOrientation.HorizontalScroll; + _scrollOrientation = ScrollOrientation.HorizontalScroll; } } - /// - /// Hide AutoSize: it doesn't make sense for this control - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), + /// + /// Hide AutoSize: it doesn't make sense for this control + /// + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public override bool AutoSize { - get - { - return base.AutoSize; - } - set - { - base.AutoSize = value; - } + get => base.AutoSize; + set => base.AutoSize = value; } - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler AutoSizeChanged { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler AutoSizeChanged + { + add + { base.AutoSizeChanged += value; } - remove { + remove + { base.AutoSizeChanged -= value; } } - /// - /// - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public override Color BackColor { - get { - return base.BackColor; - } - set { - base.BackColor = value; - } + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override Color BackColor + { + get => base.BackColor; + set => base.BackColor = value; } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler BackColorChanged { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler BackColorChanged + { + add + { base.BackColorChanged += value; } - remove { + remove + { base.BackColorChanged -= value; } } - /// - /// - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public override Image BackgroundImage { - get { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override Image BackgroundImage + { + get + { return base.BackgroundImage; } - set { + set + { base.BackgroundImage = value; } } - - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler BackgroundImageChanged { - add { + + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler BackgroundImageChanged + { + add + { base.BackgroundImageChanged += value; } - remove { + remove + { base.BackgroundImageChanged -= value; } } - /// - /// - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public override ImageLayout BackgroundImageLayout { - get { - return base.BackgroundImageLayout; - } - set { - base.BackgroundImageLayout = value; - } + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override ImageLayout BackgroundImageLayout + { + get => base.BackgroundImageLayout; + set => base.BackgroundImageLayout = value; } - - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler BackgroundImageLayoutChanged { - add { + + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler BackgroundImageLayoutChanged + { + add + { base.BackgroundImageLayoutChanged += value; } - remove { + remove + { base.BackgroundImageLayoutChanged -= value; } } - /// - /// - /// Retrieves the parameters needed to create the handle. Inheriting classes - /// can override this to provide extra functionality. They should not, - /// however, forget to call base.getCreateParams() first to get the struct - /// filled up with the basic info. - /// - /// - protected override CreateParams CreateParams { - get { + protected override CreateParams CreateParams + { + get + { CreateParams cp = base.CreateParams; cp.ClassName = "SCROLLBAR"; cp.Style &= (~NativeMethods.WS_BORDER); return cp; } } - - /// - protected override ImeMode DefaultImeMode { - get { - return ImeMode.Disable; - } - } - protected override Padding DefaultMargin { - get { - return Padding.Empty; - } - } + protected override ImeMode DefaultImeMode => ImeMode.Disable; - /// - /// rescale constants for the DPI change - /// - /// ols dpi - /// new dpi - protected override void RescaleConstantsForDpi(int deviceDpiOld, int deviceDpiNew) { + protected override Padding DefaultMargin => Padding.Empty; + + protected override void RescaleConstantsForDpi(int deviceDpiOld, int deviceDpiNew) + { base.RescaleConstantsForDpi(deviceDpiOld, deviceDpiNew); Scale((float)deviceDpiNew / deviceDpiOld); } - /// - /// - /// - /// - /// Gets or sets the foreground color of the scroll bar control. - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public override Color ForeColor { - get { - return base.ForeColor; - } - set { - base.ForeColor = value; - } + /// + /// Gets or sets the foreground color of the scroll bar control. + /// + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override Color ForeColor + { + get => base.ForeColor; + set => base.ForeColor = value; } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler ForeColorChanged { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler ForeColorChanged + { + add + { base.ForeColorChanged += value; } - remove { + remove + { base.ForeColorChanged -= value; } } - /// - /// - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public override Font Font { - get { - return base.Font; - } - set { - base.Font = value; - } + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override Font Font + { + get => base.Font; + set => base.Font = value; } - - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler FontChanged { - add { + + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler FontChanged + { + add + { base.FontChanged += value; } - remove { + remove + { base.FontChanged -= value; } } - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public ImeMode ImeMode { - get { - return base.ImeMode; - } - set { - base.ImeMode = value; - } + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new ImeMode ImeMode + { + get => base.ImeMode; + set => base.ImeMode = value; } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event EventHandler ImeModeChanged { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler ImeModeChanged + { + add + { base.ImeModeChanged += value; } - remove { + remove + { base.ImeModeChanged -= value; } } - /// - /// - /// - /// Gets or sets a value to be added or subtracted to the - /// property when the scroll box is moved a large distance. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(10), - SRDescription(nameof(SR.ScrollBarLargeChangeDescr)), - RefreshProperties(RefreshProperties.Repaint) - ] - public int LargeChange { - get { + /// + /// Gets or sets a value to be added or subtracted to the + /// property when the scroll box is moved a large distance. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(10)] + [SRDescription(nameof(SR.ScrollBarLargeChangeDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public int LargeChange + { + get + { // We preserve the actual large change value that has been set, but when we come to // get the value of this property, make sure it's within the maximum allowable value. // This way we ensure that we don't depend on the order of property sets when // code is generated at design-time. - // - return Math.Min(largeChange, maximum - minimum + 1); - } - set { - if (largeChange != value) { - - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(LargeChange), string.Format(SR.InvalidLowBoundArgumentEx, "LargeChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + return Math.Min(_largeChange, _maximum - _minimum + 1); + } + set + { + if (_largeChange != value) + { + + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(LargeChange), value, 0)); } - - largeChange = value; + + _largeChange = value; UpdateScrollInfo(); } } } - /// - /// - /// - /// Gets or sets the upper limit of values of the scrollable range. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(100), - SRDescription(nameof(SR.ScrollBarMaximumDescr)), - RefreshProperties(RefreshProperties.Repaint) - ] - public int Maximum { - get { - return maximum; - } - set { - if (maximum != value) { - if (minimum > value) - minimum = value; - // bring this.value in line. - if (value < this.value) + /// + /// Gets or sets the upper limit of values of the scrollable range. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(100)] + [SRDescription(nameof(SR.ScrollBarMaximumDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public int Maximum + { + get => _maximum; + set + { + if (_maximum != value) + { + if (_minimum > value) + { + _minimum = value; + } + if (value < _value) + { Value = value; - maximum = value; + } + + _maximum = value; UpdateScrollInfo(); } } } - /// - /// - /// - /// Gets or sets the lower limit of values of the scrollable range. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(0), - SRDescription(nameof(SR.ScrollBarMinimumDescr)), - RefreshProperties(RefreshProperties.Repaint) - ] - public int Minimum { - get { - return minimum; - } - set { - if (minimum != value) { - if (maximum < value) - maximum = value; - // bring this.value in line. - if (value > this.value) - this.value = value; - minimum = value; + /// + /// Gets or sets the lower limit of values of the scrollable range. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(0)] + [SRDescription(nameof(SR.ScrollBarMinimumDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public int Minimum + { + get => _minimum; + set + { + if (_minimum != value) + { + if (_maximum < value) + { + _maximum = value; + } + if (value > _value) + { + _value = value; + } + + _minimum = value; UpdateScrollInfo(); } } } - /// - /// - /// - /// Gets or sets the value to be added or subtracted to the - /// - /// property when the scroll box is - /// moved a small distance. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(1), - SRDescription(nameof(SR.ScrollBarSmallChangeDescr)) - ] - public int SmallChange { - get { + /// + /// Gets or sets the value to be added or subtracted to the + /// property when the scroll box is moved a small distance. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(1)] + [SRDescription(nameof(SR.ScrollBarSmallChangeDescr))] + public int SmallChange + { + get + { // We can't have SmallChange > LargeChange, but we shouldn't manipulate - // the set values for these properties, so we just return the smaller - // value here. - // - return Math.Min(smallChange, LargeChange); - } - set { - if (smallChange != value) { - - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(SmallChange), string.Format(SR.InvalidLowBoundArgumentEx, "SmallChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + // the set values for these properties, so we just return the smaller + // value here. + return Math.Min(_smallChange, LargeChange); + } + set + { + if (_smallChange != value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(SmallChange), value, 0)); } - - smallChange = value; + + _smallChange = value; UpdateScrollInfo(); } } } - /// - /// - /// - /// [DefaultValue(false)] - new public bool TabStop { - get { - return base.TabStop; - } - set { - base.TabStop = value; - } + public new bool TabStop + { + get => base.TabStop; + set => base.TabStop = value; } - /// - /// - /// - /// - [ - Browsable(false), EditorBrowsable(EditorBrowsableState.Never), - Bindable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) - ] - public override string Text { - get { - return base.Text; - } - set { - base.Text = value; - } + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [Bindable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override string Text + { + get => base.Text; + set => base.Text = value; } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - new public event EventHandler TextChanged { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler TextChanged + { + add + { base.TextChanged += value; } - remove { + remove + { base.TextChanged -= value; } } - - /// - /// - /// - /// Gets or sets a numeric value that represents the current - /// position of the scroll box - /// on - /// the scroll bar control. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(0), - Bindable(true), - SRDescription(nameof(SR.ScrollBarValueDescr)) - ] - public int Value { - get { - return value; - } - set { - if (this.value != value) { - if (value < minimum || value > maximum) { - throw new ArgumentOutOfRangeException(nameof(Value), string.Format(SR.InvalidBoundArgument, "Value", (value).ToString(CultureInfo.CurrentCulture), "'minimum'", "'maximum'")); + + /// + /// Gets or sets a numeric value that represents the current position of the scroll box + /// on the scroll bar control. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(0)] + [Bindable(true)] + [SRDescription(nameof(SR.ScrollBarValueDescr))] + public int Value + { + get => _value; + set + { + if (_value != value) + { + if (value < _minimum || value > _maximum) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidBoundArgument, nameof(Value), value, $"'{nameof(Minimum)}'", "'{nameof(Maximum)}'")); } - this.value = value; + + _value = value; UpdateScrollInfo(); OnValueChanged(EventArgs.Empty); } @@ -500,243 +424,256 @@ public int Value { /// /// Get/Set flag to let scrollbar scale according to the DPI of the window. /// - [SRCategory(nameof(SR.CatBehavior)), - DefaultValue(true), - Browsable(true), - EditorBrowsable(EditorBrowsableState.Always), - SRDescription(nameof(SR.ControlDpiChangeScale))] - public bool ScaleScrollBarForDpiChange { - get { - return scaleScrollBarForDpiChange; - } - set { - scaleScrollBarForDpiChange = value; - } + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(true)] + [Browsable(true)] + [EditorBrowsable(EditorBrowsableState.Always)] + [SRDescription(nameof(SR.ControlDpiChangeScale))] + public bool ScaleScrollBarForDpiChange + { + get => _scaleScrollBarForDpiChange; + set => _scaleScrollBarForDpiChange = value; } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event EventHandler Click { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler Click + { + add + { base.Click += value; } - remove { + remove + { base.Click -= value; } } - - /// - /// - /// ScrollBar Onpaint. - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event PaintEventHandler Paint { - add { + + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event PaintEventHandler Paint + { + add + { base.Paint += value; } - remove { + remove + { base.Paint -= value; } } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event EventHandler DoubleClick { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler DoubleClick + { + add + { base.DoubleClick += value; } - remove { + remove + { base.DoubleClick -= value; } } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event MouseEventHandler MouseClick { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event MouseEventHandler MouseClick + { + add + { base.MouseClick += value; } - remove { + remove + { base.MouseClick -= value; } } - - - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event MouseEventHandler MouseDoubleClick { - add { + + + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event MouseEventHandler MouseDoubleClick + { + add + { base.MouseDoubleClick += value; } - remove { + remove + { base.MouseDoubleClick -= value; } } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event MouseEventHandler MouseDown { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event MouseEventHandler MouseDown + { + add + { base.MouseDown += value; } - remove { + remove + { base.MouseDown -= value; } } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event MouseEventHandler MouseUp { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event MouseEventHandler MouseUp + { + add + { base.MouseUp += value; } - remove { + remove + { base.MouseUp -= value; } } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event MouseEventHandler MouseMove { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event MouseEventHandler MouseMove + { + add + { base.MouseMove += value; } - remove { + remove + { base.MouseMove -= value; } } - /// - /// - /// - /// Occurs when the scroll box has - /// been - /// moved by either a mouse or keyboard action. - /// - /// - [SRCategory(nameof(SR.CatAction)), SRDescription(nameof(SR.ScrollBarOnScrollDescr))] - public event ScrollEventHandler Scroll { - add { - Events.AddHandler(EVENT_SCROLL, value); - } - remove { - Events.RemoveHandler(EVENT_SCROLL, value); - } - } - - /// - /// - /// - /// Occurs when the property has changed, either by a - /// event or programatically. - /// - /// - [SRCategory(nameof(SR.CatAction)), SRDescription(nameof(SR.valueChangedEventDescr))] - public event EventHandler ValueChanged { - add { - Events.AddHandler(EVENT_VALUECHANGED, value); - } - remove { - Events.RemoveHandler(EVENT_VALUECHANGED, value); - } - } - - - /// - /// This is a helper method that is called by ScaleControl to retrieve the bounds - /// that the control should be scaled by. You may override this method if you - /// wish to reuse ScaleControl's scaling logic but you need to supply your own - /// bounds. The default implementation returns scaled bounds that take into - /// account the BoundsSpecified, whether the control is top level, and whether - /// the control is fixed width or auto size, and any adornments the control may have. - /// - protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) { - + /// + /// Occurs when the scroll box has been moved by either a mouse or keyboard action. + /// + [SRCategory(nameof(SR.CatAction))] + [SRDescription(nameof(SR.ScrollBarOnScrollDescr))] + public event ScrollEventHandler Scroll + { + add + { + Events.AddHandler(s_scrollEvent, value); + } + remove + { + Events.RemoveHandler(s_scrollEvent, value); + } + } + + /// + /// Occurs when the property has + /// changed, either by a event + /// or programatically. + /// + [SRCategory(nameof(SR.CatAction))] + [SRDescription(nameof(SR.valueChangedEventDescr))] + public event EventHandler ValueChanged + { + add + { + Events.AddHandler(s_valueChangedEvent, value); + } + remove + { + Events.RemoveHandler(s_valueChangedEvent, value); + } + } + + /// + /// This is a helper method that is called by ScaleControl to retrieve the bounds + /// that the control should be scaled by. You may override this method if you + /// wish to reuse ScaleControl's scaling logic but you need to supply your own + /// bounds. The default implementation returns scaled bounds that take into + /// account the BoundsSpecified, whether the control is top level, and whether + /// the control is fixed width or auto size, and any adornments the control may have. + /// + protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) + { // Adjust Specified for vertical or horizontal scaling - if (scrollOrientation == ScrollOrientation.VerticalScroll) { + if (_scrollOrientation == ScrollOrientation.VerticalScroll) + { specified &= ~BoundsSpecified.Width; } - else { + else + { specified &= ~BoundsSpecified.Height; } return base.GetScaledBounds(bounds, factor, specified); } - internal override IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg) - { - return IntPtr.Zero; - } + internal override IntPtr InitializeDCForWmCtlColor(IntPtr dc, int msg) => IntPtr.Zero; - /// - protected override void OnEnabledChanged(EventArgs e) { - if (Enabled) { + protected override void OnEnabledChanged(EventArgs e) + { + if (Enabled) + { UpdateScrollInfo(); } + base.OnEnabledChanged(e); } - /// - /// - /// Creates the handle. overridden to help set up scrollbar information. - /// - /// - protected override void OnHandleCreated(EventArgs e) { + /// + /// Creates the handle. overridden to help set up scrollbar information. + /// + protected override void OnHandleCreated(EventArgs e) + { base.OnHandleCreated(e); UpdateScrollInfo(); } - /// - /// - /// - /// Raises the event. - /// - /// - protected virtual void OnScroll(ScrollEventArgs se) { - ScrollEventHandler handler = (ScrollEventHandler)Events[EVENT_SCROLL]; - if (handler != null) handler(this,se); - } - - /// - /// - /// Converts mouse wheel movements into scrolling, when scrollbar has the focus. - /// Typically one wheel step will cause one small scroll increment, in either - /// direction. A single wheel message could represent either one wheel step, multiple - /// wheel steps (fast wheeling), or even a fraction of a step (smooth-wheeled mice). - /// So we accumulate the total wheel delta, and consume it in whole numbers of steps. - /// - protected override void OnMouseWheel(MouseEventArgs e) { - wheelDelta += e.Delta; + /// + /// Raises the event. + /// + protected virtual void OnScroll(ScrollEventArgs se) + { + ScrollEventHandler handler = (ScrollEventHandler)Events[s_scrollEvent]; + handler?.Invoke(this, se); + } + + /// + /// Converts mouse wheel movements into scrolling, when scrollbar has the focus. + /// Typically one wheel step will cause one small scroll increment, in either + /// direction. A single wheel message could represent either one wheel step, multiple + /// wheel steps (fast wheeling), or even a fraction of a step (smooth-wheeled mice). + /// So we accumulate the total wheel delta, and consume it in whole numbers of steps. + /// + protected override void OnMouseWheel(MouseEventArgs e) + { + _wheelDelta += e.Delta; bool scrolled = false; - while (Math.Abs(wheelDelta) >= NativeMethods.WHEEL_DELTA) { - if (wheelDelta > 0) { - wheelDelta -= NativeMethods.WHEEL_DELTA; + while (Math.Abs(_wheelDelta) >= NativeMethods.WHEEL_DELTA) + { + if (_wheelDelta > 0) + { + _wheelDelta -= NativeMethods.WHEEL_DELTA; DoScroll(ScrollEventType.SmallDecrement); scrolled = true; } - else { - wheelDelta += NativeMethods.WHEEL_DELTA; + else + { + _wheelDelta += NativeMethods.WHEEL_DELTA; DoScroll(ScrollEventType.SmallIncrement); scrolled = true; } } - if (scrolled) { + if (scrolled) + { DoScroll(ScrollEventType.EndScroll); } - if (e is HandledMouseEventArgs) { - ((HandledMouseEventArgs) e).Handled = true; + if (e is HandledMouseEventArgs mouseEventArgs) + { + mouseEventArgs.Handled = true; } // The base implementation should be called before the implementation above, @@ -745,82 +682,71 @@ protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); } - /// - /// - /// - /// Raises the event. - /// - /// - protected virtual void OnValueChanged(EventArgs e) { - EventHandler handler = (EventHandler)Events[EVENT_VALUECHANGED]; - if (handler != null) handler(this,e); + /// + /// Raises the event. + /// + protected virtual void OnValueChanged(EventArgs e) + { + EventHandler handler = (EventHandler)Events[s_valueChangedEvent]; + handler?.Invoke(this, e); } - // Reflects the position of the scrollbar - private int ReflectPosition(int position) { - if (this is HScrollBar) { - return minimum + (maximum - LargeChange + 1) - position; + private int ReflectPosition(int position) + { + if (this is HScrollBar) + { + return _minimum + (_maximum - LargeChange + 1) - position; } + return position; } - - /// - /// - /// - /// - public override string ToString() { + + public override string ToString() + { string s = base.ToString(); - return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + Value.ToString(CultureInfo.CurrentCulture); - } - - /// - /// - /// Internal helper method - /// - /// - protected void UpdateScrollInfo() { - if (IsHandleCreated && Enabled) { - - NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); - si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); + return s + ", Minimum: " + Minimum + ", Maximum: " + Maximum + ", Value: " + Value; + } + + protected void UpdateScrollInfo() + { + if (IsHandleCreated && Enabled) + { + var si = new NativeMethods.SCROLLINFO(); + si.cbSize = Marshal.SizeOf(); si.fMask = NativeMethods.SIF_ALL; - si.nMin = minimum; - si.nMax = maximum; + si.nMin = _minimum; + si.nMax = _maximum; si.nPage = LargeChange; - - if (RightToLeft == RightToLeft.Yes) { + + if (RightToLeft == RightToLeft.Yes) + { // Reflect the scrollbar position horizontally on an Rtl system - si.nPos = ReflectPosition(value); + si.nPos = ReflectPosition(_value); } - else { - si.nPos = value; + else + { + si.nPos = _value; } - + si.nTrackPos = 0; UnsafeNativeMethods.SetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_CTL, si, true); } } - /// - /// - /// - /// - private void WmReflectScroll(ref Message m) { + private void WmReflectScroll(ref Message m) + { ScrollEventType type = (ScrollEventType)NativeMethods.Util.LOWORD(m.WParam); DoScroll(type); } - /// - /// - /// - /// - private void DoScroll(ScrollEventType type) { - + private void DoScroll(ScrollEventType type) + { // For Rtl systems we need to swap increment and decrement - // - if (RightToLeft == RightToLeft.Yes) { - switch (type) { + if (RightToLeft == RightToLeft.Yes) + { + switch (type) + { case ScrollEventType.First: type = ScrollEventType.Last; break; @@ -846,79 +772,81 @@ private void DoScroll(ScrollEventType type) { break; } } - - int newValue = value; - int oldValue = value; + + int newValue = _value; + int oldValue = _value; // The ScrollEventArgs constants are defined in terms of the windows - // messages.. this eliminates confusion between the VSCROLL and + // messages. This eliminates confusion between the VSCROLL and // HSCROLL constants, which are identical. - // - switch (type) { + switch (type) + { case ScrollEventType.First: - newValue = minimum; + newValue = _minimum; break; case ScrollEventType.Last: - newValue = maximum - LargeChange + 1; // si.nMax - si.nPage + 1; + newValue = _maximum - LargeChange + 1; break; case ScrollEventType.SmallDecrement: - newValue = Math.Max(value - SmallChange, minimum); + newValue = Math.Max(_value - SmallChange, _minimum); break; case ScrollEventType.SmallIncrement: - newValue = Math.Min(value + SmallChange, maximum - LargeChange + 1); // max - lChange + 1); + newValue = Math.Min(_value + SmallChange, _maximum - LargeChange + 1); break; case ScrollEventType.LargeDecrement: - newValue = Math.Max(value - LargeChange, minimum); + newValue = Math.Max(_value - LargeChange, _minimum); break; case ScrollEventType.LargeIncrement: - newValue = Math.Min(value + LargeChange, maximum - LargeChange + 1); // si.nPos + si.nPage,si.nMax - si.nPage + 1); + newValue = Math.Min(_value + LargeChange, _maximum - LargeChange + 1); break; case ScrollEventType.ThumbPosition: case ScrollEventType.ThumbTrack: - NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); + var si = new NativeMethods.SCROLLINFO(); si.fMask = NativeMethods.SIF_TRACKPOS; SafeNativeMethods.GetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_CTL, si); - - if (RightToLeft == RightToLeft.Yes) { + + if (RightToLeft == RightToLeft.Yes) + { newValue = ReflectPosition(si.nTrackPos); } - else { + else + { newValue = si.nTrackPos; } - + break; } - ScrollEventArgs se = new ScrollEventArgs(type, oldValue, newValue, this.scrollOrientation); + var se = new ScrollEventArgs(type, oldValue, newValue, _scrollOrientation); OnScroll(se); Value = se.NewValue; } - /// - /// - /// - /// - protected override void WndProc(ref Message m) { - switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_HSCROLL: - case NativeMethods.WM_REFLECT + NativeMethods.WM_VSCROLL: + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_HSCROLL: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_VSCROLL: WmReflectScroll(ref m); break; - case NativeMethods.WM_ERASEBKGND: + + case Interop.WindowMessages.WM_ERASEBKGND: break; - case NativeMethods.WM_SIZE: - //Fixes the scrollbar focus rect - if (UnsafeNativeMethods.GetFocus() == this.Handle) { + case Interop.WindowMessages.WM_SIZE: + // Fixes the scrollbar focus rect + if (UnsafeNativeMethods.GetFocus() == Handle) + { DefWndProc(ref m); - SendMessage(NativeMethods.WM_KILLFOCUS, 0, 0); - SendMessage(NativeMethods.WM_SETFOCUS, 0, 0); + SendMessage(Interop.WindowMessages.WM_KILLFOCUS, 0, 0); + SendMessage(Interop.WindowMessages.WM_SETFOCUS, 0, 0); } break; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ScrollProperties.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ScrollProperties.cs index db008a2de1e..4c38049f292 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ScrollProperties.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ScrollProperties.cs @@ -2,340 +2,283 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Runtime.InteropServices; - using System.Diagnostics; - using System; - using System.Security.Permissions; - using System.Runtime.Serialization.Formatters; - using System.ComponentModel; - using System.Drawing; - using Microsoft.Win32; - using System.Windows.Forms; - using System.Globalization; - - /// - /// - /// - /// Basic Properties for Scrollbars. - /// - /// - public abstract class ScrollProperties { +using System.ComponentModel; +using System.Globalization; +using System.Runtime.InteropServices; - internal int minimum = 0; - internal int maximum = 100; - internal int smallChange = 1; - internal int largeChange = 10; - internal int value = 0; - internal bool maximumSetExternally; - internal bool smallChangeSetExternally; - internal bool largeChangeSetExternally; +namespace System.Windows.Forms +{ + /// + /// Basic Properties for Scrollbars. + /// + public abstract class ScrollProperties + { + internal int _minimum = 0; + internal int _maximum = 100; + internal int _smallChange = 1; + internal int _largeChange = 10; + internal int _value = 0; + internal bool _maximumSetExternally; + internal bool _smallChangeSetExternally; + internal bool _largeChangeSetExternally; - /// - private ScrollableControl parent; + private ScrollableControl _parent; - protected ScrollableControl ParentControl { - get - { - return parent; - } - } - - /// - /// Number of pixels to scroll the client region as a "line" for autoscroll. - /// - /// - private const int SCROLL_LINE = 5; + protected ScrollableControl ParentControl => _parent; - internal bool visible = false; + internal bool _visible = false; - //Always Enabled - private bool enabled = true; + private bool _enabled = true; - - /// - protected ScrollProperties(ScrollableControl container) { - this.parent = container; + protected ScrollProperties(ScrollableControl container) + { + _parent = container; } - /// - /// - /// - /// Gets or sets a bool value controlling whether the scrollbar is enabled. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(true), - SRDescription(nameof(SR.ScrollBarEnableDescr)) - ] - public bool Enabled { - get { - return enabled; - } - set { - if (parent.AutoScroll) { + /// + /// Gets or sets a bool value controlling whether the scrollbar is enabled. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(true)] + [SRDescription(nameof(SR.ScrollBarEnableDescr))] + public bool Enabled + { + get => _enabled; + set + { + if (_parent.AutoScroll) + { return; } - if (value != enabled) { - enabled = value; - EnableScroll(value); + + if (value != _enabled) + { + _enabled = value; + UnsafeNativeMethods.EnableScrollBar( + new HandleRef(_parent, _parent.Handle), + Orientation, + value ? NativeMethods.ESB_ENABLE_BOTH : NativeMethods.ESB_DISABLE_BOTH + ); } } } - - /// - /// - /// - /// Gets or sets a value to be added or subtracted to the - /// property when the scroll box is moved a large distance. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(10), - SRDescription(nameof(SR.ScrollBarLargeChangeDescr)), - RefreshProperties(RefreshProperties.Repaint) - ] - public int LargeChange { - get { + /// + /// Gets or sets a value to be added or subtracted to the + /// property when the scroll box is moved a large distance. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(10)] + [SRDescription(nameof(SR.ScrollBarLargeChangeDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public int LargeChange + { + get + { // We preserve the actual large change value that has been set, but when we come to // get the value of this property, make sure it's within the maximum allowable value. // This way we ensure that we don't depend on the order of property sets when // code is generated at design-time. - // - return Math.Min(largeChange, maximum - minimum + 1); + return Math.Min(_largeChange, _maximum - _minimum + 1); } - set { - if (largeChange != value ) { - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(LargeChange), string.Format(SR.InvalidLowBoundArgumentEx, "LargeChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + set + { + if (_largeChange != value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(LargeChange), value, 0)); } - largeChange = value; - largeChangeSetExternally = true; + + _largeChange = value; + _largeChangeSetExternally = true; UpdateScrollInfo(); } } } - /// - /// - /// - /// Gets or sets the upper limit of values of the scrollable range. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(100), - SRDescription(nameof(SR.ScrollBarMaximumDescr)), - RefreshProperties(RefreshProperties.Repaint) - ] - public int Maximum { - get { - return maximum; - } - set { - if (parent.AutoScroll) { + /// + /// Gets or sets the upper limit of values of the scrollable range. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(100)] + [SRDescription(nameof(SR.ScrollBarMaximumDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public int Maximum + { + get => _maximum; + set + { + if (_parent.AutoScroll) + { return; } - if (maximum != value) { - if (minimum > value) - minimum = value; - // bring this.value in line. - if (value < this.value) + + if (_maximum != value) + { + if (_minimum > value) + { + _minimum = value; + } + if (value < _value) + { Value = value; - maximum = value; - maximumSetExternally = true; + } + + _maximum = value; + _maximumSetExternally = true; UpdateScrollInfo(); } } } - /// - /// - /// - /// Gets or sets the lower limit of values of the scrollable range. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(0), - SRDescription(nameof(SR.ScrollBarMinimumDescr)), - RefreshProperties(RefreshProperties.Repaint) - ] - public int Minimum { - get { - return minimum; - } - - set { - if (parent.AutoScroll) { + /// + /// Gets or sets the lower limit of values of the scrollable range. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(0)] + [SRDescription(nameof(SR.ScrollBarMinimumDescr))] + [RefreshProperties(RefreshProperties.Repaint)] + public int Minimum + { + get => _minimum; + set + { + if (_parent.AutoScroll) + { return; } - if (minimum != value) { - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(Minimum), string.Format(SR.InvalidLowBoundArgumentEx, "Minimum", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + + if (_minimum != value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(Minimum), value, 0)); + } + + if (_maximum < value) + { + _maximum = value; } - if (maximum < value) - maximum = value; - // bring this.value in line. - if (value > this.value) - this.value = value; - minimum = value; + if (value > _value) + { + _value = value; + } + + _minimum = value; UpdateScrollInfo(); } } } - internal abstract int PageSize { - get; - } - - internal abstract int Orientation { - get; - } + internal abstract int PageSize { get; } - internal abstract int HorizontalDisplayPosition { - get; - } + internal abstract int Orientation { get; } + internal abstract int HorizontalDisplayPosition { get; } - internal abstract int VerticalDisplayPosition { - get; - } + internal abstract int VerticalDisplayPosition { get; } - /// - /// - /// - /// Gets or sets the value to be added or subtracted to the - /// - /// property when the scroll box is - /// moved a small distance. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(1), - SRDescription(nameof(SR.ScrollBarSmallChangeDescr)) - ] - public int SmallChange { - get { + /// + /// Gets or sets the value to be added or subtracted to the + /// property when the scroll box is moved a small distance. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(1)] + [SRDescription(nameof(SR.ScrollBarSmallChangeDescr))] + public int SmallChange + { + get + { // We can't have SmallChange > LargeChange, but we shouldn't manipulate // the set values for these properties, so we just return the smaller // value here. - // - return Math.Min(smallChange, LargeChange); + return Math.Min(_smallChange, LargeChange); } - set { - if (smallChange != value) { - - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(SmallChange), string.Format(SR.InvalidLowBoundArgumentEx, "SmallChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + set + { + if (_smallChange != value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(SmallChange), value, 0)); } - - smallChange = value; - smallChangeSetExternally = true; + + _smallChange = value; + _smallChangeSetExternally = true; UpdateScrollInfo(); } } } - /// - /// - /// - /// Gets or sets a numeric value that represents the current - /// position of the scroll box - /// on - /// the scroll bar control. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(0), - Bindable(true), - SRDescription(nameof(SR.ScrollBarValueDescr)) - ] - public int Value { - get { - return value; - } - set { - if (this.value != value) { - if (value < minimum || value > maximum) { - throw new ArgumentOutOfRangeException(nameof(Value), string.Format(SR.InvalidBoundArgument, "Value", (value).ToString(CultureInfo.CurrentCulture), "'minimum'", "'maximum'")); + /// + /// Gets or sets a numeric value that represents the current position of the scroll box + /// on the scroll bar control. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(0)] + [Bindable(true)] + [SRDescription(nameof(SR.ScrollBarValueDescr))] + public int Value + { + get => _value; + set + { + if (_value != value) + { + if (value < _minimum || value > _maximum) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidBoundArgument, nameof(Value), value, $"'{nameof(Minimum)}'", $"'{nameof(Maximum)}'")); } - this.value = value; + + _value = value; UpdateScrollInfo(); - parent.SetDisplayFromScrollProps(HorizontalDisplayPosition, VerticalDisplayPosition); + _parent.SetDisplayFromScrollProps(HorizontalDisplayPosition, VerticalDisplayPosition); } } } - /// - /// - /// - /// Gets or sets a bool value controlling whether the scrollbar is showing. - /// - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(false), - SRDescription(nameof(SR.ScrollBarVisibleDescr)) - ] - public bool Visible { - get { - return visible; - } - set { - if (parent.AutoScroll) { + /// + /// Gets or sets a bool value controlling whether the scrollbar is showing. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(false)] + [SRDescription(nameof(SR.ScrollBarVisibleDescr))] + public bool Visible + { + get => _visible; + set + { + if (_parent.AutoScroll) + { return; } - if (value != visible) { - visible = value; - parent.UpdateStylesCore (); + + if (value != _visible) + { + _visible = value; + _parent.UpdateStylesCore(); UpdateScrollInfo(); - parent.SetDisplayFromScrollProps(HorizontalDisplayPosition, VerticalDisplayPosition); + _parent.SetDisplayFromScrollProps(HorizontalDisplayPosition, VerticalDisplayPosition); } } } - - /// - /// - /// Internal helper method - /// - /// - internal void UpdateScrollInfo() { - if (parent.IsHandleCreated && visible) { - NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); - si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); - si.fMask = NativeMethods.SIF_ALL; - si.nMin = minimum; - si.nMax = maximum; - si.nPage = (parent.AutoScroll) ? PageSize : LargeChange; - si.nPos = value; - si.nTrackPos = 0; - UnsafeNativeMethods.SetScrollInfo(new HandleRef(parent, parent.Handle), Orientation, si, true); - } - } - /// - /// - /// Internal helper method for enabling or disabling the Vertical Scroll bar. - /// - /// - private void EnableScroll(bool enable) + internal void UpdateScrollInfo() { - if (enable) { - UnsafeNativeMethods.EnableScrollBar(new HandleRef(parent, parent.Handle), Orientation, NativeMethods.ESB_ENABLE_BOTH); - } - else { - UnsafeNativeMethods.EnableScrollBar(new HandleRef(parent, parent.Handle), Orientation, NativeMethods.ESB_DISABLE_BOTH); + if (_parent.IsHandleCreated && _visible) + { + var si = new NativeMethods.SCROLLINFO(); + si.cbSize = Marshal.SizeOf(); + si.fMask = NativeMethods.SIF_ALL; + si.nMin = _minimum; + si.nMax = _maximum; + si.nPage = _parent.AutoScroll ? PageSize : LargeChange; + si.nPos = _value; + si.nTrackPos = 0; + UnsafeNativeMethods.SetScrollInfo(new HandleRef(_parent, _parent.Handle), Orientation, si, true); } - } - } } - diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ScrollableControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ScrollableControl.cs index 52a13fc6e62..1646e3b53fc 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ScrollableControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ScrollableControl.cs @@ -160,7 +160,7 @@ public Size AutoScrollMargin { set { if (value.Width < 0 || value.Height < 0) { - throw new ArgumentOutOfRangeException(nameof(AutoScrollMargin), string.Format(SR.InvalidArgument, "AutoScrollMargin", value.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(AutoScrollMargin), value)); } SetAutoScrollMargin(value.Width, value.Height); } @@ -635,10 +635,10 @@ private Rectangle GetDisplayRectInternal() { if (displayRect.IsEmpty) { displayRect = ClientRectangle; } - if (!AutoScroll && this.HorizontalScroll.visible == true) { + if (!AutoScroll && this.HorizontalScroll._visible == true) { displayRect = new Rectangle(displayRect.X, displayRect.Y, this.HorizontalScroll.Maximum, this.displayRect.Height); } - if (!AutoScroll && this.VerticalScroll.visible == true) { + if (!AutoScroll && this.VerticalScroll._visible == true) { displayRect = new Rectangle(displayRect.X, displayRect.Y, this.displayRect.Width, this.VerticalScroll.Maximum); } return displayRect; @@ -890,7 +890,13 @@ protected void SetDisplayRectLocation(int x, int y) { /// Scrolls the currently active control into view if we are an AutoScroll /// Form that has the Horiz or Vert scrollbar displayed... /// - public void ScrollControlIntoView(Control activeControl) { + public void ScrollControlIntoView(Control activeControl) + { + if (activeControl == null) + { + return; + } + Debug.WriteLineIf(ScrollableControl.AutoScrolling.TraceVerbose, "ScrollControlIntoView(" + activeControl.GetType().FullName + ")"); Debug.Indent(); @@ -899,7 +905,6 @@ public void ScrollControlIntoView(Control activeControl) { if (IsDescendant(activeControl) && AutoScroll && (HScroll || VScroll) - && activeControl != null && (client.Width > 0 && client.Height > 0)) { Debug.WriteLineIf(ScrollableControl.AutoScrolling.TraceVerbose, "Calculating..."); @@ -1019,8 +1024,8 @@ private void ResetAutoScrollMinSize() { private void ResetScrollProperties(ScrollProperties scrollProperties) { // Set only these two values as when the ScrollBars are not visible ... // there is no meaning of the "value" property. - scrollProperties.visible = false; - scrollProperties.value = 0; + scrollProperties._visible = false; + scrollProperties._value = 0; } /// @@ -1089,7 +1094,7 @@ private bool SetVisibleScrollbars(bool horiz, bool vert) { //Update the visible member of ScrollBars.... if (horiz) { - HorizontalScroll.visible = true; + HorizontalScroll._visible = true; } else { @@ -1097,7 +1102,7 @@ private bool SetVisibleScrollbars(bool horiz, bool vert) { } if (vert) { - VerticalScroll.visible = true; + VerticalScroll._visible = true; } else { @@ -1217,36 +1222,36 @@ private void SyncScrollbars(bool autoScroll) { } if (HScroll) { - if (!HorizontalScroll.maximumSetExternally) { - HorizontalScroll.maximum = displayRect.Width-1; + if (!HorizontalScroll._maximumSetExternally) { + HorizontalScroll._maximum = displayRect.Width-1; } - if (!HorizontalScroll.largeChangeSetExternally) { - HorizontalScroll.largeChange = ClientRectangle.Width; + if (!HorizontalScroll._largeChangeSetExternally) { + HorizontalScroll._largeChange = ClientRectangle.Width; } - if (!HorizontalScroll.smallChangeSetExternally) { - HorizontalScroll.smallChange = 5; + if (!HorizontalScroll._smallChangeSetExternally) { + HorizontalScroll._smallChange = 5; } if (resetRTLHScrollValue && !IsMirrored) { resetRTLHScrollValue = false; BeginInvoke(new EventHandler(this.OnSetScrollPosition)); } - else if(-displayRect.X >= HorizontalScroll.minimum && -displayRect.X < HorizontalScroll.maximum) { - HorizontalScroll.value = -displayRect.X; + else if(-displayRect.X >= HorizontalScroll._minimum && -displayRect.X < HorizontalScroll._maximum) { + HorizontalScroll._value = -displayRect.X; } HorizontalScroll.UpdateScrollInfo (); } if (VScroll) { - if (!VerticalScroll.maximumSetExternally) { - VerticalScroll.maximum = displayRect.Height-1; + if (!VerticalScroll._maximumSetExternally) { + VerticalScroll._maximum = displayRect.Height-1; } - if (!VerticalScroll.largeChangeSetExternally) { - VerticalScroll.largeChange = ClientRectangle.Height; + if (!VerticalScroll._largeChangeSetExternally) { + VerticalScroll._largeChange = ClientRectangle.Height; } - if (!VerticalScroll.smallChangeSetExternally) { - VerticalScroll.smallChange = 5; + if (!VerticalScroll._smallChangeSetExternally) { + VerticalScroll._smallChange = 5; } - if (-displayRect.Y >= VerticalScroll.minimum && -displayRect.Y < VerticalScroll.maximum) { - VerticalScroll.value = -displayRect.Y; + if (-displayRect.Y >= VerticalScroll._minimum && -displayRect.Y < VerticalScroll._maximum) { + VerticalScroll._value = -displayRect.Y; } VerticalScroll.UpdateScrollInfo (); } @@ -1269,7 +1274,7 @@ private void SyncScrollbars(bool autoScroll) { private void OnSetScrollPosition(object sender, EventArgs e) { if (!IsMirrored) { - SendMessage(NativeMethods.WM_HSCROLL, + SendMessage(Interop.WindowMessages.WM_HSCROLL, NativeMethods.Util.MAKELPARAM((RightToLeft == RightToLeft.Yes) ? NativeMethods.SB_RIGHT : NativeMethods.SB_LEFT,0), 0); } } @@ -1464,13 +1469,13 @@ private void WmSettingChange(ref Message m) { [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_VSCROLL: + case Interop.WindowMessages.WM_VSCROLL: WmVScroll(ref m); break; - case NativeMethods.WM_HSCROLL: + case Interop.WindowMessages.WM_HSCROLL: WmHScroll(ref m); break; - case NativeMethods.WM_SETTINGCHANGE: + case Interop.WindowMessages.WM_SETTINGCHANGE: WmSettingChange(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/SendKeys.cs b/src/System.Windows.Forms/src/System/Windows/Forms/SendKeys.cs index 63fa79a7312..4ffb82788e7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/SendKeys.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/SendKeys.cs @@ -160,19 +160,19 @@ private static bool AddSimpleKey(char character, int repeat, IntPtr hwnd, int[] if (vk != -1) { if (haveKeys[HAVESHIFT] == 0 && (vk & SHIFTKEYSCAN) != 0) { - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.ShiftKey, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.ShiftKey, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVESHIFT] = UNKNOWN_GROUPING; } if (haveKeys[HAVECTRL] == 0 && (vk & CTRLKEYSCAN) != 0) { - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.ControlKey, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.ControlKey, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVECTRL] = UNKNOWN_GROUPING; } if (haveKeys[HAVEALT] == 0 && (vk & ALTKEYSCAN) != 0) { - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.Menu, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.Menu, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVEALT] = UNKNOWN_GROUPING; } @@ -183,7 +183,7 @@ private static bool AddSimpleKey(char character, int repeat, IntPtr hwnd, int[] else { int oemVal = SafeNativeMethods.OemKeyScan((short)(0xFF & (int)character)); for (int i = 0; i < repeat; i++) { - AddEvent(new SKEvent(NativeMethods.WM_CHAR, character, (int)(oemVal & 0xFFFF), hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_CHAR, character, (int)(oemVal & 0xFFFF), hwnd)); } } @@ -197,9 +197,9 @@ private static bool AddSimpleKey(char character, int repeat, IntPtr hwnd, int[] /// private static void AddMsgsForVK(int vk, int repeat, bool altnoctrldown, IntPtr hwnd) { for (int i = 0; i < repeat; i++) { - AddEvent(new SKEvent(altnoctrldown ? NativeMethods.WM_SYSKEYDOWN : NativeMethods.WM_KEYDOWN, vk, fStartNewChar, hwnd)); + AddEvent(new SKEvent(altnoctrldown ? Interop.WindowMessages.WM_SYSKEYDOWN : Interop.WindowMessages.WM_KEYDOWN, vk, fStartNewChar, hwnd)); // fStartNewChar = false; - AddEvent(new SKEvent(altnoctrldown ? NativeMethods.WM_SYSKEYUP : NativeMethods.WM_KEYUP, vk, fStartNewChar, hwnd)); + AddEvent(new SKEvent(altnoctrldown ? Interop.WindowMessages.WM_SYSKEYUP : Interop.WindowMessages.WM_KEYUP, vk, fStartNewChar, hwnd)); } } @@ -210,15 +210,15 @@ private static void AddMsgsForVK(int vk, int repeat, bool altnoctrldown, IntPtr /// private static void CancelMods(int [] haveKeys, int level, IntPtr hwnd) { if (haveKeys[HAVESHIFT] == level) { - AddEvent(new SKEvent(NativeMethods.WM_KEYUP, (int)Keys.ShiftKey, false, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYUP, (int)Keys.ShiftKey, false, hwnd)); haveKeys[HAVESHIFT] = 0; } if (haveKeys[HAVECTRL] == level) { - AddEvent(new SKEvent(NativeMethods.WM_KEYUP, (int)Keys.ControlKey, false, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYUP, (int)Keys.ControlKey, false, hwnd)); haveKeys[HAVECTRL] = 0; } if (haveKeys[HAVEALT] == level) { - AddEvent(new SKEvent(NativeMethods.WM_SYSKEYUP, (int)Keys.Menu, false, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_SYSKEYUP, (int)Keys.Menu, false, hwnd)); haveKeys[HAVEALT] = 0; } } @@ -464,19 +464,19 @@ private static void ParseKeys(string keys, IntPtr hwnd) { if (vk != -1) { // Unlike AddSimpleKey, the bit mask uses Keys, rather than scan keys if (haveKeys[HAVESHIFT] == 0 && (vk & (int)Keys.Shift) != 0) { - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.ShiftKey, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.ShiftKey, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVESHIFT] = UNKNOWN_GROUPING; } if (haveKeys[HAVECTRL] == 0 && (vk & (int)Keys.Control) != 0) { - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.ControlKey, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.ControlKey, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVECTRL] = UNKNOWN_GROUPING; } if (haveKeys[HAVEALT] == 0 && (vk & (int)Keys.Alt) != 0) { - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.Menu, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.Menu, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVEALT] = UNKNOWN_GROUPING; } @@ -497,7 +497,7 @@ private static void ParseKeys(string keys, IntPtr hwnd) { case '+': if (haveKeys[HAVESHIFT] != 0) throw new ArgumentException(string.Format(SR.InvalidSendKeysString, keys)); - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.ShiftKey, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.ShiftKey, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVESHIFT] = UNKNOWN_GROUPING; break; @@ -505,7 +505,7 @@ private static void ParseKeys(string keys, IntPtr hwnd) { case '^': if (haveKeys[HAVECTRL]!= 0) throw new ArgumentException(string.Format(SR.InvalidSendKeysString, keys)); - AddEvent(new SKEvent(NativeMethods.WM_KEYDOWN, (int)Keys.ControlKey, fStartNewChar, hwnd)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYDOWN, (int)Keys.ControlKey, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVECTRL] = UNKNOWN_GROUPING; break; @@ -513,7 +513,7 @@ private static void ParseKeys(string keys, IntPtr hwnd) { case '%': if (haveKeys[HAVEALT] != 0) throw new ArgumentException(string.Format(SR.InvalidSendKeysString, keys)); - AddEvent(new SKEvent((haveKeys[HAVECTRL] != 0) ? NativeMethods.WM_KEYDOWN : NativeMethods.WM_SYSKEYDOWN, + AddEvent(new SKEvent((haveKeys[HAVECTRL] != 0) ? Interop.WindowMessages.WM_KEYDOWN : Interop.WindowMessages.WM_SYSKEYDOWN, (int)Keys.Menu, fStartNewChar, hwnd)); fStartNewChar = false; haveKeys[HAVEALT] = UNKNOWN_GROUPING; @@ -587,7 +587,7 @@ private static void SendInput(byte[] oldKeyboardState, Queue previousEvents) currentInput[1].inputUnion.ki.time = 0; // send each of our SKEvents using SendInput - int INPUTSize = Marshal.SizeOf(typeof(NativeMethods.INPUT)); + int INPUTSize = Marshal.SizeOf(); // need these outside the lock below uint eventsSent=0; @@ -615,7 +615,7 @@ private static void SendInput(byte[] oldKeyboardState, Queue previousEvents) currentInput[0].inputUnion.ki.dwFlags = 0; - if (skEvent.wm == NativeMethods.WM_CHAR) + if (skEvent.wm == Interop.WindowMessages.WM_CHAR) { // for WM_CHAR, send a KEYEVENTF_UNICODE instead of a Keyboard event // to support extended ascii characters with no keyboard equivalent. @@ -634,7 +634,7 @@ private static void SendInput(byte[] oldKeyboardState, Queue previousEvents) currentInput[0].inputUnion.ki.wScan = 0; // add KeyUp flag if we have a KeyUp - if (skEvent.wm == NativeMethods.WM_KEYUP || skEvent.wm == NativeMethods.WM_SYSKEYUP) + if (skEvent.wm == Interop.WindowMessages.WM_KEYUP || skEvent.wm == Interop.WindowMessages.WM_SYSKEYUP) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_KEYUP; } @@ -704,13 +704,13 @@ private static void AddCancelModifiersForPreviousEvents(Queue previousEvents) SKEvent skEvent = (SKEvent)previousEvents.Dequeue(); bool isOn; - if ((skEvent.wm == NativeMethods.WM_KEYUP) || - (skEvent.wm == NativeMethods.WM_SYSKEYUP)) + if ((skEvent.wm == Interop.WindowMessages.WM_KEYUP) || + (skEvent.wm == Interop.WindowMessages.WM_SYSKEYUP)) { isOn = false; } - else if ((skEvent.wm == NativeMethods.WM_KEYDOWN) || - (skEvent.wm == NativeMethods.WM_SYSKEYDOWN)) + else if ((skEvent.wm == Interop.WindowMessages.WM_KEYDOWN) || + (skEvent.wm == Interop.WindowMessages.WM_SYSKEYDOWN)) { isOn = true; } @@ -735,15 +735,15 @@ private static void AddCancelModifiersForPreviousEvents(Queue previousEvents) if (shift) { - AddEvent(new SKEvent(NativeMethods.WM_KEYUP, (int)Keys.ShiftKey, false, IntPtr.Zero)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYUP, (int)Keys.ShiftKey, false, IntPtr.Zero)); } else if (ctrl) { - AddEvent(new SKEvent(NativeMethods.WM_KEYUP, (int)Keys.ControlKey, false, IntPtr.Zero)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_KEYUP, (int)Keys.ControlKey, false, IntPtr.Zero)); } else if (alt) { - AddEvent(new SKEvent(NativeMethods.WM_SYSKEYUP, (int)Keys.Menu, false, IntPtr.Zero)); + AddEvent(new SKEvent(Interop.WindowMessages.WM_SYSKEYUP, (int)Keys.Menu, false, IntPtr.Zero)); } } @@ -771,7 +771,7 @@ private static void ClearGlobalKeys() private static void CheckGlobalKeys(SKEvent skEvent) { - if (skEvent.wm == NativeMethods.WM_KEYDOWN) + if (skEvent.wm == Interop.WindowMessages.WM_KEYDOWN) { switch (skEvent.paramL) { @@ -988,7 +988,7 @@ public SKWindow() { } protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_CANCELJOURNAL) { + if (m.Msg == Interop.WindowMessages.WM_CANCELJOURNAL) { try { SendKeys.JournalCancel(); } @@ -1052,7 +1052,7 @@ private class SendKeysHookProc { private bool gotNextEvent = false; public virtual IntPtr Callback(int code, IntPtr wparam, IntPtr lparam) { - NativeMethods.EVENTMSG eventmsg = (NativeMethods.EVENTMSG)UnsafeNativeMethods.PtrToStructure(lparam, typeof(NativeMethods.EVENTMSG)); + NativeMethods.EVENTMSG eventmsg = Marshal.PtrToStructure(lparam); if (UnsafeNativeMethods.GetAsyncKeyState((int)Keys.Pause) != 0) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/SplitContainer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/SplitContainer.cs index 28a894b5578..90710e03021 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/SplitContainer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/SplitContainer.cs @@ -394,7 +394,7 @@ public BorderStyle BorderStyle { } } - /// + /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event ControlEventHandler ControlAdded { add { @@ -404,7 +404,7 @@ public BorderStyle BorderStyle { base.ControlAdded -= value; } } - /// + /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event ControlEventHandler ControlRemoved { add { @@ -574,7 +574,7 @@ private Cursor OverrideCursor { UnsafeNativeMethods.GetCursorPos(p); UnsafeNativeMethods.GetWindowRect(new HandleRef(this, Handle), ref r); if ((r.left <= p.x && p.x < r.right && r.top <= p.y && p.y < r.bottom) || UnsafeNativeMethods.GetCapture() == Handle) - SendMessage(NativeMethods.WM_SETCURSOR, Handle, NativeMethods.HTCLIENT); + SendMessage(Interop.WindowMessages.WM_SETCURSOR, Handle, NativeMethods.HTCLIENT); } } } @@ -772,7 +772,7 @@ public int SplitterDistance if (value != SplitterDistance) { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(SplitterDistance), string.Format(SR.InvalidLowBoundArgument, "SplitterDistance", (value).ToString(CultureInfo.CurrentCulture), "0")); + throw new ArgumentOutOfRangeException(nameof(SplitterDistance), string.Format(SR.InvalidLowBoundArgument, "SplitterDistance", value, 0)); } @@ -868,7 +868,7 @@ public int SplitterIncrement { set { if (value < 1 ) { - throw new ArgumentOutOfRangeException(nameof(SplitterIncrement), string.Format(SR.InvalidLowBoundArgumentEx, "SplitterIncrement", (value).ToString(CultureInfo.CurrentCulture), "1")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SplitterIncrement), value, 1)); } splitterInc = value; @@ -1412,17 +1412,17 @@ protected override void OnRightToLeftChanged(EventArgs e) { /// private void ApplyPanel1MinSize(int value) { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(Panel1MinSize), string.Format(SR.InvalidLowBoundArgument, "Panel1MinSize", (value).ToString(CultureInfo.CurrentCulture), "0")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgument, nameof(Panel1MinSize), value)); } if (Orientation== Orientation.Vertical) { if (DesignMode && Width != DefaultSize.Width && value + Panel2MinSize + SplitterWidth > Width) { - throw new ArgumentOutOfRangeException(nameof(Panel1MinSize), string.Format(SR.InvalidArgument, "Panel1MinSize", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(Panel1MinSize), value)); } } else if (Orientation == Orientation.Horizontal) { if (DesignMode && Height != DefaultSize.Height && value + Panel2MinSize + SplitterWidth > Height) { - throw new ArgumentOutOfRangeException(nameof(Panel1MinSize), string.Format(SR.InvalidArgument, "Panel1MinSize", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(Panel1MinSize), value)); } } @@ -1437,17 +1437,17 @@ private void ApplyPanel1MinSize(int value) { /// private void ApplyPanel2MinSize(int value) { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(Panel2MinSize), string.Format(SR.InvalidLowBoundArgument, "Panel2MinSize", (value).ToString(CultureInfo.CurrentCulture), "0")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgument, nameof(Panel2MinSize), value, 0)); } if (Orientation == Orientation.Vertical) { if (DesignMode && Width != DefaultSize.Width && value + Panel1MinSize + SplitterWidth > Width) { - throw new ArgumentOutOfRangeException(nameof(Panel2MinSize), string.Format(SR.InvalidArgument, "Panel2MinSize", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(Panel2MinSize), value.ToString())); } } else if (Orientation == Orientation.Horizontal) { if (DesignMode && Height != DefaultSize.Height && value + Panel1MinSize + SplitterWidth > Height) { - throw new ArgumentOutOfRangeException(nameof(Panel2MinSize), string.Format(SR.InvalidArgument, "Panel2MinSize", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(Panel2MinSize), value)); } } panel2MinSize = value; @@ -1461,17 +1461,17 @@ private void ApplyPanel2MinSize(int value) { /// private void ApplySplitterWidth(int value) { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(SplitterWidth), string.Format(SR.InvalidLowBoundArgumentEx, "SplitterWidth", (value).ToString(CultureInfo.CurrentCulture), "1")); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SplitterWidth), value, 1)); } if (Orientation == Orientation.Vertical) { if (DesignMode && value + Panel1MinSize + Panel2MinSize > Width) { - throw new ArgumentOutOfRangeException(nameof(SplitterWidth), string.Format(SR.InvalidArgument, "SplitterWidth", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SplitterWidth), value)); } } else if (Orientation == Orientation.Horizontal) { if (DesignMode && value + Panel1MinSize + Panel2MinSize > Height) { - throw new ArgumentOutOfRangeException(nameof(SplitterWidth), string.Format(SR.InvalidArgument, "SplitterWidth", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SplitterWidth), value)); } } splitterWidth = value; @@ -2446,14 +2446,14 @@ protected override void OnMouseCaptureChanged(EventArgs e) { /// protected override void WndProc(ref Message msg) { switch (msg.Msg) { - case NativeMethods.WM_SETCURSOR: + case Interop.WindowMessages.WM_SETCURSOR: WmSetCursor(ref msg); break; - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: splitterFocused = true; base.WndProc(ref msg); break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: splitterFocused = false; base.WndProc(ref msg); break; @@ -2496,9 +2496,9 @@ public SplitContainerMessageFilter(SplitContainer splitContainer) /// /// bool IMessageFilter.PreFilterMessage(ref Message m) { - if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST) { - if ((m.Msg == NativeMethods.WM_KEYDOWN && (int)m.WParam == (int)Keys.Escape) - || (m.Msg == NativeMethods.WM_SYSKEYDOWN)) { + if (m.Msg >= Interop.WindowMessages.WM_KEYFIRST && m.Msg <= Interop.WindowMessages.WM_KEYLAST) { + if ((m.Msg == Interop.WindowMessages.WM_KEYDOWN && (int)m.WParam == (int)Keys.Escape) + || (m.Msg == Interop.WindowMessages.WM_SYSKEYDOWN)) { //Notify that splitMOVE was reverted .. //this is used in ONKEYUP!! owner.splitBegin = false; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Splitter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Splitter.cs index 05d4463ac3d..eac47840b9d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Splitter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Splitter.cs @@ -1019,8 +1019,8 @@ public SplitterMessageFilter(Splitter splitter) /// /// public bool PreFilterMessage(ref Message m) { - if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST) { - if (m.Msg == NativeMethods.WM_KEYDOWN && unchecked((int)(long)m.WParam) == (int)Keys.Escape) { + if (m.Msg >= Interop.WindowMessages.WM_KEYFIRST && m.Msg <= Interop.WindowMessages.WM_KEYLAST) { + if (m.Msg == Interop.WindowMessages.WM_KEYDOWN && unchecked((int)(long)m.WParam) == (int)Keys.Escape) { owner.SplitEnd(false); } return true; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/SplitterPanel.cs b/src/System.Windows.Forms/src/System/Windows/Forms/SplitterPanel.cs index 8db2dbaf699..3bc0fa9a4b5 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/SplitterPanel.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/SplitterPanel.cs @@ -10,7 +10,6 @@ namespace System.Windows.Forms { using System.ComponentModel; using System.Diagnostics; using System.Security; - using System.Security.Permissions; using System.Windows.Forms; using System.Drawing; using System.Drawing.Design; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/StatusBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/StatusBar.cs index 72704d7bd1e..b943b744d22 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/StatusBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/StatusBar.cs @@ -1152,14 +1152,14 @@ private void WmNCHitTest(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_NCHITTEST: + case Interop.WindowMessages.WM_NCHITTEST: WmNCHitTest(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_DRAWITEM: WmDrawItem(ref m); break; - case NativeMethods.WM_NOTIFY: - case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT: + case Interop.WindowMessages.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY + Interop.WindowMessages.WM_REFLECT: NativeMethods.NMHDR note = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR)); switch (note.code) { case NativeMethods.NM_CLICK: @@ -1230,7 +1230,7 @@ public virtual StatusBarPanel this[int index] { int length = owner.panels.Count; if (index < 0|| index >= length) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); StatusBarPanel oldPanel = (StatusBarPanel) owner.panels[index]; oldPanel.ParentInternal = null; @@ -1476,7 +1476,7 @@ public virtual void Insert(int index, StatusBarPanel value) { int length = owner.panels.Count; if (index < 0 || index > length) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); value.ParentInternal = owner; switch (value.AutoSize) { @@ -1563,7 +1563,7 @@ void IList.Remove(object value) { public virtual void RemoveAt(int index) { int length = Count; if (index < 0 || index >= length) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); // clear any tooltip // @@ -1830,7 +1830,7 @@ public void Dispose() { /// private NativeMethods.TOOLINFO_T GetMinTOOLINFO(Tool tool) { NativeMethods.TOOLINFO_T ti = new NativeMethods.TOOLINFO_T(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); + ti.cbSize = Marshal.SizeOf(); ti.hwnd = parent.Handle; if ((int)tool.id < 0) { AssignId(tool); @@ -1852,7 +1852,7 @@ private NativeMethods.TOOLINFO_T GetMinTOOLINFO(Tool tool) { /// private NativeMethods.TOOLINFO_T GetTOOLINFO(Tool tool) { NativeMethods.TOOLINFO_T ti = GetMinTOOLINFO(tool); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); + ti.cbSize = Marshal.SizeOf(); ti.uFlags |= NativeMethods.TTF_TRANSPARENT | NativeMethods.TTF_SUBCLASS; // RightToLeft reading order @@ -1882,7 +1882,7 @@ private NativeMethods.TOOLINFO_T GetTOOLINFO(Tool tool) { protected void WndProc(ref Message msg) { switch (msg.Msg) { - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: // diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/StatusBarPanel.cs b/src/System.Windows.Forms/src/System/Windows/Forms/StatusBarPanel.cs index b95c266ac20..ef8bc7216e8 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/StatusBarPanel.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/StatusBarPanel.cs @@ -255,7 +255,7 @@ public int MinWidth { } set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(MinWidth), string.Format(SR.InvalidLowBoundArgumentEx, "MinWidth", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(MinWidth), value, 0)); } if (value != this.minWidth) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/StatusStrip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/StatusStrip.cs index b7e82a086c9..62007929ed5 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/StatusStrip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/StatusStrip.cs @@ -355,13 +355,8 @@ protected override void OnLayout(LayoutEventArgs levent) { } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; - protected override void SetDisplayedItems() { if (state[stateCalledSpringTableLayout]) { bool rightToLeft = ((Orientation == Orientation.Horizontal) && (RightToLeft == RightToLeft.Yes)); @@ -544,7 +539,7 @@ protected virtual void OnSpringTableLayoutCore() { } protected override void WndProc(ref Message m) { - if ((m.Msg == NativeMethods.WM_NCHITTEST) && SizingGrip) { + if ((m.Msg == Interop.WindowMessages.WM_NCHITTEST) && SizingGrip) { // if we're within the grip bounds tell windows // that we're the bottom right of the window. Rectangle sizeGripBounds = SizeGripBounds; @@ -605,7 +600,7 @@ protected override CreateParams CreateParams { } } protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_NCHITTEST) { + if (m.Msg == Interop.WindowMessages.WM_NCHITTEST) { int x = NativeMethods.Util.LOWORD(m.LParam); int y = NativeMethods.Util.HIWORD(m.LParam); @@ -636,7 +631,7 @@ public override AccessibleRole Role { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_ControlTypePropertyId) { + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { return NativeMethods.UIA_StatusBarControlTypeId; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/SystemInformation.cs b/src/System.Windows.Forms/src/System/Windows/Forms/SystemInformation.cs index 062d984e67f..4324e5e2513 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/SystemInformation.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/SystemInformation.cs @@ -1767,7 +1767,7 @@ public static ScreenOrientation ScreenOrientation { get { ScreenOrientation so = ScreenOrientation.Angle0; NativeMethods.DEVMODE dm = new NativeMethods.DEVMODE(); - dm.dmSize = (short) Marshal.SizeOf(typeof(NativeMethods.DEVMODE)); + dm.dmSize = (short) Marshal.SizeOf(); dm.dmDriverExtra = 0; try { SafeNativeMethods.EnumDisplaySettings(null, -1 /*ENUM_CURRENT_SETTINGS*/, ref dm); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs index d76feb86cfd..64f8db6267f 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs @@ -553,7 +553,7 @@ public Size ItemSize { set { if (value.Width < 0 || value.Height < 0) { - throw new ArgumentOutOfRangeException(nameof(ItemSize), string.Format(SR.InvalidArgument, "ItemSize", value.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(ItemSize), value)); } itemSize = value; ApplyItemSize(); @@ -620,10 +620,10 @@ public bool Multiline { return padding; } set { - //do some validation checking here, against min & max GridSize - // - if ( value.X < 0 || value.Y < 0 ) - throw new ArgumentOutOfRangeException(nameof(Padding), string.Format(SR.InvalidArgument, "Padding", value.ToString())); + if (value.X < 0 || value.Y < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(Padding), value)); + } if (padding != value) { padding = value; @@ -712,7 +712,7 @@ public int SelectedIndex { } set { if (value < -1) { - throw new ArgumentOutOfRangeException(nameof(SelectedIndex), string.Format(SR.InvalidLowBoundArgumentEx, "SelectedIndex", value.ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectedIndex), value, -1)); } if (SelectedIndex != value) { @@ -1170,7 +1170,7 @@ public Control GetControl(int index) { internal TabPage GetTabPage(int index) { if (index < 0 || index >= tabPageCount) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } return tabPages[index]; } @@ -1207,7 +1207,7 @@ internal TabPage[] GetTabPages() { /// public Rectangle GetTabRect(int index) { if (index < 0 || (index >= tabPageCount && !tabControlState[TABCONTROLSTATE_getTabRectfromItemSize])) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } tabControlState[TABCONTROLSTATE_getTabRectfromItemSize] = false ; NativeMethods.RECT rect = new NativeMethods.RECT(); @@ -1267,7 +1267,7 @@ internal void Insert(int index, TabPage tabPage) { private void InsertItem(int index, TabPage tabPage) { if (index < 0 || ((tabPages != null) && index > tabPageCount)) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); if (tabPage == null) throw new ArgumentNullException(nameof(tabPage)); @@ -1654,7 +1654,7 @@ protected void RemoveAll() { /// internal void RemoveTabPage(int index) { if (index < 0 || index >= tabPageCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); tabPageCount--; if (index < tabPageCount) { Array.Copy(tabPages, index + 1, tabPages, index, tabPageCount - index); @@ -1700,7 +1700,7 @@ internal void SetToolTip(ToolTip toolTip, string controlToolTipText) { /// internal void SetTabPage(int index, TabPage tabPage, NativeMethods.TCITEM_T tcitem) { if (index < 0 || index >= tabPageCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); if (IsHandleCreated) UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TCM_SETITEM, index, tcitem); // Make the Updated tab page the currently selected tab page @@ -2076,16 +2076,16 @@ private void WmTabBaseReLayout(ref Message m) { protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_DRAWITEM: WmReflectDrawItem(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_MEASUREITEM: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_MEASUREITEM: // We use TCM_SETITEMSIZE instead break; - case NativeMethods.WM_NOTIFY: - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR) m.GetLParam(typeof(NativeMethods.NMHDR)); switch (nmhdr.code) { // new switch added to prevent the TabControl from changing to next TabPage ... diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs index ebc5f23c525..462601b21b9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs @@ -12,7 +12,6 @@ namespace System.Windows.Forms { using System.ComponentModel.Design; using System.Text; using System.Windows.Forms; - using System.Security.Permissions; using Microsoft.Win32; using System.Windows.Forms.VisualStyles; using System.Runtime.InteropServices; @@ -185,9 +184,11 @@ public int ImageIndex { return ImageIndexer.Index; } set { - if (value < -1) { - throw new ArgumentOutOfRangeException ("ImageIndex", string.Format (SR.InvalidLowBoundArgumentEx, "imageIndex", (value).ToString (CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + if (value < -1) + { + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); } + TabControl parent = ParentInternal as TabControl; if (parent != null) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutPanelCellPosition.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutPanelCellPosition.cs index 5ea42b9d934..279693edfc5 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutPanelCellPosition.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutPanelCellPosition.cs @@ -2,140 +2,131 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System; - using System.Collections; - using System.ComponentModel; - using System.ComponentModel.Design; - using System.ComponentModel.Design.Serialization; - using System.Globalization; - - [TypeConverterAttribute(typeof(TableLayoutPanelCellPositionTypeConverter))] - public struct TableLayoutPanelCellPosition { - - private int row; - private int column; - - public TableLayoutPanelCellPosition(int column, int row) { - if (row < -1) { - throw new ArgumentOutOfRangeException(nameof(row), string.Format(SR.InvalidArgument, "row", (row).ToString(CultureInfo.CurrentCulture))); - } - if (column < -1) { - throw new ArgumentOutOfRangeException(nameof(column), string.Format(SR.InvalidArgument, "column", (column).ToString(CultureInfo.CurrentCulture))); - } - this.row = row; - this.column = column; - } +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Globalization; - public int Row { - get { - return row; +namespace System.Windows.Forms +{ + [TypeConverter(typeof(TableLayoutPanelCellPositionTypeConverter))] + public struct TableLayoutPanelCellPosition + { + public TableLayoutPanelCellPosition(int column, int row) + { + if (row < -1) + { + throw new ArgumentOutOfRangeException(nameof(row), row, string.Format(SR.InvalidArgument, nameof(row), row)); } - set { - row = value; + if (column < -1) + { + throw new ArgumentOutOfRangeException(nameof(column), column, string.Format(SR.InvalidArgument, nameof(column), column)); } - } - public int Column { - get { - return column; - } - set { - column = value; - } + Row = row; + Column = column; } - public override bool Equals(object other) { - if(other is TableLayoutPanelCellPosition) { - TableLayoutPanelCellPosition dpeOther = (TableLayoutPanelCellPosition) other; - return (dpeOther.row == row && - dpeOther.column == column); + public int Row { get; set; } + + public int Column { get; set; } + + public override bool Equals(object other) + { + if (!(other is TableLayoutPanelCellPosition otherCellPosition)) + { + return false; } - return false; + + return this == otherCellPosition; } - public static bool operator ==(TableLayoutPanelCellPosition p1, TableLayoutPanelCellPosition p2) { + + public static bool operator ==(TableLayoutPanelCellPosition p1, TableLayoutPanelCellPosition p2) + { return p1.Row == p2.Row && p1.Column == p2.Column; } - public static bool operator !=(TableLayoutPanelCellPosition p1, TableLayoutPanelCellPosition p2) { + + public static bool operator !=(TableLayoutPanelCellPosition p1, TableLayoutPanelCellPosition p2) + { return !(p1 == p2); } - - - public override string ToString() { - return Column.ToString(CultureInfo.CurrentCulture) + "," + Row.ToString(CultureInfo.CurrentCulture); + + + public override string ToString() + { + return Column + "," + Row; } - - public override int GetHashCode() => HashCode.Combine(row, column); + + public override int GetHashCode() => HashCode.Combine(Row, Column); } - - internal class TableLayoutPanelCellPositionTypeConverter : TypeConverter { - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { - if (destinationType == typeof(InstanceDescriptor)) { + internal class TableLayoutPanelCellPositionTypeConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { return true; } + return base.CanConvertTo(context, destinationType); } - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { - if (sourceType == typeof(string)) { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { return true; } + return base.CanConvertFrom(context, sourceType); } - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - - if (value is string) { - - string text = ((string)value).Trim(); - - if (text.Length == 0) { + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string stringValue) + { + stringValue = stringValue.Trim(); + if (stringValue.Length == 0) + { return null; } - else { - // Parse 2 integer values. - // - if (culture == null) { - culture = CultureInfo.CurrentCulture; - } - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(new char[] {sep}); - int[] values = new int[tokens.Length]; - TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); - for (int i = 0; i < values.Length; i++) { - // Note: ConvertFromString will raise exception if value cannot be converted. - values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i]); - } - - if (values.Length == 2) { - return new TableLayoutPanelCellPosition(values[0], values[1]); - } - else { - throw new ArgumentException(string.Format(SR.TextParseFailedFormat, - text, - "column, row")); - } + // Parse 2 integer values. + if (culture == null) + { + culture = CultureInfo.CurrentCulture; } + + string[] tokens = stringValue.Split(new char[] { culture.TextInfo.ListSeparator[0] }); + int[] values = new int[tokens.Length]; + TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int)); + for (int i = 0; i < values.Length; i++) + { + // Note: ConvertFromString will raise exception if value cannot be converted. + values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i]); + } + + if (values.Length != 2) + { + throw new ArgumentException(string.Format(SR.TextParseFailedFormat, stringValue, "column, row"), nameof(value)); + } + + return new TableLayoutPanelCellPosition(values[0], values[1]); } - + return base.ConvertFrom(context, culture, value); } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - if (destinationType == null) { - throw new ArgumentNullException(nameof(destinationType)); - } - - if (destinationType == typeof(InstanceDescriptor) && value is TableLayoutPanelCellPosition) { - TableLayoutPanelCellPosition cellPosition = (TableLayoutPanelCellPosition) value; - + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor) && value is TableLayoutPanelCellPosition cellPosition) + { return new InstanceDescriptor( - typeof(TableLayoutPanelCellPosition).GetConstructor(new Type[] {typeof(int), typeof(int)}), - new object[] {cellPosition.Column, cellPosition.Row}); - + typeof(TableLayoutPanelCellPosition).GetConstructor(new Type[] { typeof(int), typeof(int) }), + new object[] { cellPosition.Column, cellPosition.Row } + ); + } return base.ConvertTo(context, culture, value, destinationType); } @@ -147,25 +138,31 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar throw new ArgumentNullException(nameof(propertyValues)); } - return new TableLayoutPanelCellPosition( - (int)propertyValues["Column"], - (int)propertyValues["Row"] - ); - } - - public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) { - return true; + try + { + return new TableLayoutPanelCellPosition( + (int)propertyValues[nameof(TableLayoutPanelCellPosition.Column)], + (int)propertyValues[nameof(TableLayoutPanelCellPosition.Row)] + ); + } + catch (InvalidCastException invalidCast) + { + throw new ArgumentException(SR.PropertyValueInvalidEntry, nameof(propertyValues), invalidCast); + } + catch (NullReferenceException nullRef) + { + throw new ArgumentException(SR.PropertyValueInvalidEntry, nameof(propertyValues), nullRef); + } } - public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { + public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) => true; + + public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) + { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(TableLayoutPanelCellPosition), attributes); - return props.Sort(new string[] {"Column","Row"}); + return props.Sort(new string[] { nameof(TableLayoutPanelCellPosition.Column), nameof(TableLayoutPanelCellPosition.Row) }); } - public override bool GetPropertiesSupported(ITypeDescriptorContext context) { - return true; - } + public override bool GetPropertiesSupported(ITypeDescriptorContext context) => true; } - - } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutSettings.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutSettings.cs index e1d3890a686..430fcb9159b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutSettings.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutSettings.cs @@ -76,7 +76,7 @@ internal TableLayoutPanelCellBorderStyle CellBorderStyle { set { //valid values are 0x0 to 0x6 if (!ClientUtils.IsEnumValid(value, (int)value, (int)TableLayoutPanelCellBorderStyle.None, (int)TableLayoutPanelCellBorderStyle.OutsetPartial)){ - throw new ArgumentException(string.Format(SR.InvalidArgument, "CellBorderStyle", value.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(CellBorderStyle), value)); } _borderStyle = value; //set the CellBorderWidth according to the current CellBorderStyle. @@ -107,9 +107,11 @@ public int ColumnCount { return containerInfo.MaxColumns; } set { - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(ColumnCount), value, string.Format (SR.InvalidLowBoundArgumentEx, "ColumnCount", value.ToString (CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ColumnCount), value, 0)); } + TableLayout.ContainerInfo containerInfo = TableLayout.GetContainerInfo(Owner); containerInfo.MaxColumns = value; LayoutTransaction.DoLayout(Owner, Owner, PropertyNames.Columns); @@ -133,9 +135,11 @@ public int RowCount { return containerInfo.MaxRows; } set { - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(RowCount), value, string.Format (SR.InvalidLowBoundArgumentEx, "RowCount", value.ToString (CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(RowCount), value, 0)); } + TableLayout.ContainerInfo containerInfo = TableLayout.GetContainerInfo(Owner); containerInfo.MaxRows = value; LayoutTransaction.DoLayout(Owner, Owner, PropertyNames.Rows); @@ -193,7 +197,7 @@ public TableLayoutPanelGrowStyle GrowStyle { set { //valid values are 0x0 to 0x2 if (!ClientUtils.IsEnumValid(value, (int)value, (int)TableLayoutPanelGrowStyle.FixedSize, (int)TableLayoutPanelGrowStyle.AddColumns)){ - throw new ArgumentException(string.Format(SR.InvalidArgument, "GrowStyle", value.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(GrowStyle), value)); } TableLayout.ContainerInfo containerInfo = TableLayout.GetContainerInfo(Owner); @@ -255,7 +259,7 @@ public void SetColumnSpan(object control, int value) } if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidArgument, "ColumnSpan", value)); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(value), value)); } if (IsStub) @@ -302,7 +306,7 @@ public void SetRowSpan(object control, int value) } if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidArgument, "RowSpan", value)); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(value), value)); } if (IsStub) @@ -360,7 +364,7 @@ public void SetRow(object control, int row) } if (row < -1) { - throw new ArgumentOutOfRangeException(nameof(row), string.Format(SR.InvalidArgument, "Row", row)); + throw new ArgumentOutOfRangeException(nameof(row), row, string.Format(SR.InvalidArgument, nameof(row), row)); } SetCellPosition(control, row, -1, rowSpecified: true, colSpecified: false); @@ -436,7 +440,7 @@ public void SetColumn(object control, int column) } if (column < -1) { - throw new ArgumentException(string.Format(SR.InvalidArgument, "Column", column)); + throw new ArgumentOutOfRangeException(nameof(column), column, string.Format(SR.InvalidArgument, nameof(column), column)); } if (IsStub) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutStyle.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutStyle.cs index 32b34db3133..ec5a86c6be8 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutStyle.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TableLayoutStyle.cs @@ -43,7 +43,7 @@ internal float Size { get { return _size; } set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(Size), string.Format(SR.InvalidLowBoundArgumentEx, "Size", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(Size), value, 0)); } if (_size != value) { _size = value; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TextBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TextBox.cs index 6956851be1e..9b9e30c41a1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TextBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TextBox.cs @@ -368,7 +368,7 @@ public char PasswordChar { if (!IsHandleCreated) { CreateHandle(); } - return (char)SendMessage(NativeMethods.EM_GETPASSWORDCHAR, 0, 0); + return (char)SendMessage(Interop.EditMessages.EM_GETPASSWORDCHAR, 0, 0); } set { passwordChar = value; @@ -376,7 +376,7 @@ public char PasswordChar { if (IsHandleCreated) { if (PasswordChar != value) { // Set the password mode. - SendMessage(NativeMethods.EM_SETPASSWORDCHAR, value, 0); + SendMessage(Interop.EditMessages.EM_SETPASSWORDCHAR, value, 0); // Disable IME if setting the control to password mode. VerifyImeRestrictedModeChanged(); @@ -630,7 +630,7 @@ protected override void OnHandleCreated(EventArgs e) { if (passwordChar != 0) { if (!useSystemPasswordChar) { - SendMessage(NativeMethods.EM_SETPASSWORDCHAR, passwordChar, 0); + SendMessage(Interop.EditMessages.EM_SETPASSWORDCHAR, passwordChar, 0); } } @@ -916,7 +916,7 @@ private void DrawPlaceholderText(Graphics graphics) protected override void WndProc(ref Message m) { switch (m.Msg) { // Work around a very obscure Windows issue. - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: MouseButtons realState = MouseButtons; bool wasValidationCancelled = ValidationCancelled; FocusInternal(); @@ -927,10 +927,10 @@ protected override void WndProc(ref Message m) { break; //for readability ... so that we know whats happening ... // case WM_LBUTTONUP is included here eventhough it just calls the base. - case NativeMethods.WM_LBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: base.WndProc(ref m); break; - case NativeMethods.WM_PRINT: + case Interop.WindowMessages.WM_PRINT: WmPrint(ref m); break; default: @@ -938,7 +938,7 @@ protected override void WndProc(ref Message m) { break; } - if ((m.Msg == NativeMethods.WM_PAINT || m.Msg == NativeMethods.WM_KILLFOCUS) && + if ((m.Msg == Interop.WindowMessages.WM_PAINT || m.Msg == Interop.WindowMessages.WM_KILLFOCUS) && !this.GetStyle(ControlStyles.UserPaint) && string.IsNullOrEmpty(this.Text) && !this.Focused) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.cs index c55459904f9..7959f27ba9e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.cs @@ -455,7 +455,7 @@ public bool CanUndo { get { if (IsHandleCreated) { bool b; - b = unchecked( (int) (long)SendMessage(NativeMethods.EM_CANUNDO, 0, 0)) != 0; + b = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_CANUNDO, 0, 0)) != 0; return b; } @@ -732,7 +732,7 @@ public virtual int MaxLength { } set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(MaxLength), string.Format(SR.InvalidLowBoundArgumentEx, "MaxLength", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(MaxLength), value, 0)); } if (maxLength != value) { @@ -758,7 +758,7 @@ public virtual int MaxLength { public bool Modified { get { if (IsHandleCreated) { - bool curState = (0 != unchecked( (int) (long)SendMessage(NativeMethods.EM_GETMODIFY, 0, 0))); + bool curState = (0 != unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_GETMODIFY, 0, 0))); if (textBoxFlags[modified] != curState) { // Raise ModifiedChanged event. See WmReflectCommand for more info. textBoxFlags[modified] = curState; @@ -775,7 +775,7 @@ public bool Modified { set { if (Modified != value) { if (IsHandleCreated) { - SendMessage(NativeMethods.EM_SETMODIFY, value ? 1 : 0, 0); + SendMessage(Interop.EditMessages.EM_SETMODIFY, value ? 1 : 0, 0); // Must maintain this state always in order for the // test in the Get method to work properly. } @@ -974,7 +974,7 @@ internal void GetSelectionStartAndLength( out int start, out int length ){ } else { start = 0; - UnsafeNativeMethods.SendMessage( new HandleRef( this, Handle ), NativeMethods.EM_GETSEL, ref start, ref end ); + UnsafeNativeMethods.SendMessage( new HandleRef( this, Handle ), Interop.EditMessages.EM_GETSEL, ref start, ref end ); //Here, we return the max of either 0 or the # returned by //the windows call. This eliminates a problem on nt4 where @@ -1027,7 +1027,7 @@ public bool ReadOnly { if (textBoxFlags[readOnly] != value) { textBoxFlags[readOnly] = value; if (IsHandleCreated) { - SendMessage(NativeMethods.EM_SETREADONLY, value? -1: 0, 0); + SendMessage(Interop.EditMessages.EM_SETREADONLY, value? -1: 0, 0); } OnReadOnlyChanged(EventArgs.Empty); @@ -1086,20 +1086,20 @@ internal virtual void SetSelectedTextInternal(string text, bool clearUndo){ // The EM_LIMITTEXT message limits only the text the user can enter. It does not affect any text // already in the edit control when the message is sent, nor does it affect the length of the text // copied to the edit control by the WM_SETTEXT message. - SendMessage(NativeMethods.EM_LIMITTEXT, 0, 0); + SendMessage(Interop.EditMessages.EM_LIMITTEXT, 0, 0); if( clearUndo ){ - SendMessage(NativeMethods.EM_REPLACESEL, 0, text); + SendMessage(Interop.EditMessages.EM_REPLACESEL, 0, text); // For consistency with Text, we clear the modified flag - SendMessage(NativeMethods.EM_SETMODIFY, 0, 0); + SendMessage(Interop.EditMessages.EM_SETMODIFY, 0, 0); ClearUndo(); } else{ - SendMessage(NativeMethods.EM_REPLACESEL, /*undoable*/ -1, text); + SendMessage(Interop.EditMessages.EM_REPLACESEL, /*undoable*/ -1, text); } // Re-enable user input. - SendMessage(NativeMethods.EM_LIMITTEXT, maxLength, 0); + SendMessage(Interop.EditMessages.EM_LIMITTEXT, maxLength, 0); } @@ -1127,7 +1127,7 @@ public virtual int SelectionLength { set { if (value < 0){ - throw new ArgumentOutOfRangeException(nameof(SelectionLength), string.Format(SR.InvalidArgument, "SelectionLength", value.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SelectionLength), value)); } int selStart, selLength; @@ -1163,7 +1163,7 @@ public int SelectionStart { } set { if (value < 0){ - throw new ArgumentOutOfRangeException(nameof(SelectionStart), string.Format(SR.InvalidArgument, "SelectionStart", value.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(SelectionStart), value)); } Select(value, SelectionLength); } @@ -1196,7 +1196,7 @@ public override string Text { base.Text = value; if (IsHandleCreated) { // clear the modified flag - SendMessage(NativeMethods.EM_SETMODIFY, 0, 0); + SendMessage(Interop.EditMessages.EM_SETMODIFY, 0, 0); } } } @@ -1391,7 +1391,7 @@ public void Clear() { /// public void ClearUndo() { if (IsHandleCreated) { - SendMessage(NativeMethods.EM_EMPTYUNDOBUFFER, 0, 0); + SendMessage(Interop.EditMessages.EM_EMPTYUNDOBUFFER, 0, 0); } } @@ -1402,7 +1402,7 @@ public void ClearUndo() { /// /// public void Copy() { - SendMessage(NativeMethods.WM_COPY, 0, 0); + SendMessage(Interop.WindowMessages.WM_COPY, 0, 0); } /// @@ -1434,7 +1434,7 @@ protected override void CreateHandle() { /// /// public void Cut() { - SendMessage(NativeMethods.WM_CUT, 0, 0); + SendMessage(Interop.WindowMessages.WM_CUT, 0, 0); } /// @@ -1492,7 +1492,7 @@ protected override void OnHandleCreated(EventArgs e) { UpdateMaxLength(); if (textBoxFlags[modified]){ - SendMessage(NativeMethods.EM_SETMODIFY, 1, 0); + SendMessage(Interop.EditMessages.EM_SETMODIFY, 1, 0); } if (textBoxFlags[scrollToCaretOnHandleCreated]) { ScrollToCaret(); @@ -1519,7 +1519,7 @@ protected override void OnHandleDestroyed(EventArgs e) { /// /// public void Paste() { - SendMessage(NativeMethods.WM_PASTE, 0, 0); + SendMessage(Interop.WindowMessages.WM_PASTE, 0, 0); } /// @@ -1659,7 +1659,7 @@ public virtual char GetCharFromPosition(Point pt) { /// public virtual int GetCharIndexFromPosition(Point pt) { int longPoint = NativeMethods.Util.MAKELONG(pt.X, pt.Y); - int index = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_CHARFROMPOS, 0, longPoint); + int index = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_CHARFROMPOS, 0, longPoint); index = NativeMethods.Util.LOWORD(index); if (index < 0) { @@ -1687,7 +1687,7 @@ public virtual int GetCharIndexFromPosition(Point pt) { /// return 1 and not 0. /// public virtual int GetLineFromCharIndex(int index) { - return unchecked( (int) (long)SendMessage(NativeMethods.EM_LINEFROMCHAR, index, 0)); + return unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_LINEFROMCHAR, index, 0)); } /// @@ -1698,7 +1698,7 @@ public virtual Point GetPositionFromCharIndex(int index) { if (index < 0 || index >= Text.Length) return Point.Empty; - int i = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_POSFROMCHAR, index, 0); + int i = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_POSFROMCHAR, index, 0); return new Point(NativeMethods.Util.SignedLOWORD(i), NativeMethods.Util.SignedHIWORD(i)); } @@ -1708,9 +1708,9 @@ public virtual Point GetPositionFromCharIndex(int index) { /// public int GetFirstCharIndexFromLine(int lineNumber) { if (lineNumber < 0) { - throw new ArgumentOutOfRangeException(nameof(lineNumber), string.Format(SR.InvalidArgument, "lineNumber", lineNumber.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(lineNumber), lineNumber, string.Format(SR.InvalidArgument, nameof(lineNumber), lineNumber)); } - return unchecked( (int) (long)SendMessage(NativeMethods.EM_LINEINDEX, lineNumber, 0)); + return unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_LINEINDEX, lineNumber, 0)); } /// @@ -1718,7 +1718,7 @@ public int GetFirstCharIndexFromLine(int lineNumber) { /// Returns the index of the first character of the line where the caret is. /// public int GetFirstCharIndexOfCurrentLine() { - return unchecked( (int) (long)SendMessage(NativeMethods.EM_LINEINDEX, -1, 0)); + return unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_LINEINDEX, -1, 0)); } @@ -1739,7 +1739,7 @@ public void ScrollToCaret() { object editOle = null; IntPtr editOlePtr = IntPtr.Zero; try { - if (UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETOLEINTERFACE, 0, out editOle) != 0) { + if (UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_GETOLEINTERFACE, 0, out editOle) != 0) { editOlePtr = Marshal.GetIUnknownForObject(editOle); @@ -1771,7 +1771,7 @@ public void ScrollToCaret() { textRange.ScrollIntoView(0); // 0 ==> tomEnd // 2. Get the first visible line. - int firstVisibleLine = unchecked( (int) (long)SendMessage(NativeMethods.EM_GETFIRSTVISIBLELINE, 0, 0)); + int firstVisibleLine = unchecked( (int) (long)SendMessage(Interop.EditMessages.EM_GETFIRSTVISIBLELINE, 0, 0)); // 3. If the first visible line is smaller than the start of the selection, we are done; if (firstVisibleLine <= selStartLine) { @@ -1798,7 +1798,7 @@ public void ScrollToCaret() { } if (!scrolled) { - SendMessage(NativeMethods.EM_SCROLLCARET, 0, 0); + SendMessage(Interop.EditMessages.EM_SCROLLCARET, 0, 0); } } else { @@ -1824,7 +1824,7 @@ public void DeselectAll() { /// public void Select(int start, int length) { if (start < 0){ - throw new ArgumentOutOfRangeException(nameof(start), string.Format(SR.InvalidArgument, "start", start.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(start), start, string.Format(SR.InvalidArgument, nameof(start), start)); } int textLen = TextLength; @@ -1859,7 +1859,7 @@ internal virtual void SelectInternal(int start, int length, int textLen) { int s, e; AdjustSelectionStartAndEnd(start, length, out s, out e, textLen); - SendMessage(NativeMethods.EM_SETSEL, s, e); + SendMessage(Interop.EditMessages.EM_SETSEL, s, e); // } @@ -1959,7 +1959,7 @@ internal void SetSelectionOnHandle() { textBoxFlags[setSelectionOnHandleCreated] = false; int start, end; AdjustSelectionStartAndEnd(this.selectionStart, this.selectionLength, out start, out end, -1); - SendMessage(NativeMethods.EM_SETSEL, start, end); + SendMessage(Interop.EditMessages.EM_SETSEL, start, end); } } @@ -2070,19 +2070,19 @@ public override string ToString() { /// /// public void Undo() { - SendMessage(NativeMethods.EM_UNDO, 0, 0); + SendMessage(Interop.EditMessages.EM_UNDO, 0, 0); } internal virtual void UpdateMaxLength() { if (IsHandleCreated) { - SendMessage(NativeMethods.EM_LIMITTEXT, maxLength, 0); + SendMessage(Interop.EditMessages.EM_LIMITTEXT, maxLength, 0); } } internal override IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg) { - if ((msg == NativeMethods.WM_CTLCOLORSTATIC) && !ShouldSerializeBackColor()) { + if ((msg == Interop.WindowMessages.WM_CTLCOLORSTATIC) && !ShouldSerializeBackColor()) { // Let the Win32 Edit control handle background colors itself. // This is necessary because a disabled edit control will display a different // BackColor than when enabled. @@ -2117,7 +2117,7 @@ private void WmReflectCommand(ref Message m) { void WmSetFont(ref Message m) { base.WndProc(ref m); if (!textBoxFlags[multiline]) { - SendMessage(NativeMethods.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN, 0); + SendMessage(Interop.EditMessages.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN, 0); } } @@ -2186,20 +2186,20 @@ private void WmTextBoxContextMenu(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: this.doubleClickFired = true; base.WndProc(ref m); break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_COMMAND: WmReflectCommand(ref m); break; - case NativeMethods.WM_GETDLGCODE: + case Interop.WindowMessages.WM_GETDLGCODE: WmGetDlgCode(ref m); break; - case NativeMethods.WM_SETFONT: + case Interop.WindowMessages.WM_SETFONT: WmSetFont(ref m); break; - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_CONTEXTMENU: if (ShortcutsEnabled) { //calling base will find ContextMenus in this order: // 1) ContextMenu 2) ContextMenuStrip 3) SystemMenu diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ThreadExceptionDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ThreadExceptionDialog.cs index a86798530ce..34a1926bcc7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ThreadExceptionDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ThreadExceptionDialog.cs @@ -23,8 +23,8 @@ namespace System.Windows.Forms { ClassInterface(ClassInterfaceType.AutoDispatch)] public class ThreadExceptionDialog : Form { - private const string DownBitmapName = "down.bmp"; - private const string UpBitmapName = "up.bmp"; + private const string DownBitmapName = "down"; + private const string UpBitmapName = "up"; private const int MAXWIDTH = 440; private const int MAXHEIGHT = 325; @@ -280,10 +280,8 @@ public ThreadExceptionDialog(Exception t) { if (detailAnchor) { b = detailsButton; - expandImage = new Bitmap(GetType(), DownBitmapName); - expandImage.MakeTransparent(); - collapseImage = new Bitmap(GetType(), UpBitmapName); - collapseImage.MakeTransparent(); + expandImage = DpiHelper.GetBitmapFromIcon(GetType(), DownBitmapName); + collapseImage = DpiHelper.GetBitmapFromIcon(GetType(), UpBitmapName); if (DpiHelper.IsScalingRequirementMet) { @@ -327,14 +325,12 @@ private void ThreadExceptionDialog_DpiChanged(object sender, DpiChangedEventArgs if (expandImage != null) { expandImage.Dispose(); } - expandImage = new Bitmap(GetType(), DownBitmapName); - expandImage.MakeTransparent(); + expandImage = DpiHelper.GetBitmapFromIcon(GetType(), DownBitmapName); if (collapseImage != null) { collapseImage.Dispose(); } - collapseImage = new Bitmap(GetType(), UpBitmapName); - collapseImage.MakeTransparent(); + collapseImage = DpiHelper.GetBitmapFromIcon(GetType(), UpBitmapName); ScaleBitmapLogicalToDevice(ref expandImage); ScaleBitmapLogicalToDevice(ref collapseImage); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Timer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Timer.cs index 39f35ae804c..3d755225a5a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Timer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Timer.cs @@ -2,225 +2,170 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -namespace System.Windows.Forms { - using System.Threading; - using System.Runtime.InteropServices; - using System.ComponentModel; - using System.ComponentModel.Design; - using System.Diagnostics; - using System.Windows.Forms.Design; - using System; - using System.Globalization; - - /// - /// - /// Implements a Windows-based timer that raises an event at user-defined intervals. This timer is optimized for - /// use in Win Forms - /// applications and must be used in a window. - /// - [ - DefaultProperty(nameof(Interval)), - DefaultEvent(nameof(Tick)), - ToolboxItemFilter("System.Windows.Forms"), - SRDescription(nameof(SR.DescriptionTimer)) - ] - public class Timer : Component { - - /// - /// - /// - private int interval; - - /// - /// - /// - private bool enabled; - - /// - /// - /// - internal EventHandler onTimer; - - /// - /// - /// - private GCHandle timerRoot; - - - // our holder for the HWND that handles our Timer messages. - // - private TimerNativeWindow timerWindow; - - /// - /// - /// - private object userData; - - private object syncObj = new object(); - - /// - /// - /// Initializes a new instance of the - /// class. - /// - public Timer() - : base() { - interval = 100; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms +{ + /// + /// Implements a Windows-based timer that raises an event at user-defined intervals. + /// This timer is optimized for use in Win Forms applications and must be used in a window. + /// + [DefaultProperty(nameof(Interval))] + [DefaultEvent(nameof(Tick))] + [ToolboxItemFilter("System.Windows.Forms")] + [SRDescription(nameof(SR.DescriptionTimer))] + public class Timer : Component + { + private int _interval = 100; + + private bool _enabled; + + private protected EventHandler _onTimer; + + private GCHandle _timerRoot; + + + // Holder for the HWND that handles our Timer messages. + private TimerNativeWindow _timerWindow; + + private readonly object _syncObj = new object(); + + /// + /// Initializes a new instance of the class. + /// + public Timer() : base() + { } - /// - /// - /// Initializes a new instance of the class with the specified container. - /// - public Timer(IContainer container) : this() { - if (container == null) { + /// + /// Initializes a new instance of the class with the specified container. + /// + public Timer(IContainer container) : this() + { + if (container == null) + { throw new ArgumentNullException(nameof(container)); } container.Add(this); } - /// - [ - SRCategory(nameof(SR.CatData)), - Localizable(false), - Bindable(true), - SRDescription(nameof(SR.ControlTagDescr)), - DefaultValue(null), - TypeConverter(typeof(StringConverter)), - ] - public object Tag { - get { - return userData; + [SRCategory(nameof(SR.CatData))] + [Localizable(false)] + [Bindable(true)] + [SRDescription(nameof(SR.ControlTagDescr))] + [DefaultValue(null)] + [TypeConverter(typeof(StringConverter))] + public object Tag { get; set; } + + /// + /// Occurs when the specified timer interval has elapsed and the timer is enabled. + /// + [SRCategory(nameof(SR.CatBehavior))] + [SRDescription(nameof(SR.TimerTimerDescr))] + public event EventHandler Tick + { + add + { + _onTimer += value; } - set { - userData = value; + remove + { + _onTimer -= value; } } - /// - /// - /// Occurs when the specified timer - /// interval has elapsed and the timer is enabled. - /// - [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.TimerTimerDescr))] - public event EventHandler Tick { - add { - onTimer += value; - } - remove { - onTimer -= value; - } - } - - /// - /// - /// - /// Disposes of the resources (other than memory) used by the timer. - /// - /// - protected override void Dispose(bool disposing) { - if (disposing) { - if (timerWindow != null) { - timerWindow.StopTimer(); - } - + /// + /// Disposes of the resources (other than memory) used by the timer. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + _timerWindow?.StopTimer(); Enabled = false; } - timerWindow = null; + + _timerWindow = null; base.Dispose(disposing); } - /// - /// - /// Indicates whether the timer is - /// running. - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(false), - SRDescription(nameof(SR.TimerEnabledDescr)) - ] - public virtual bool Enabled { - get { - if (timerWindow == null) { - return enabled; - } - return timerWindow.IsTimerRunning; - } - - set { - lock(syncObj) { - - if (enabled != value) { + /// + /// Indicates whether the timer is running. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(false)] + [SRDescription(nameof(SR.TimerEnabledDescr))] + public virtual bool Enabled + { + get => _timerWindow == null ? _enabled : _timerWindow.IsTimerRunning; + set + { + lock (_syncObj) + { + if (_enabled != value) + { + _enabled = value; - enabled = value; - // At runtime, enable or disable the corresponding Windows timer - // - if (!DesignMode) { - if (value) { - - // create the timer window if needed. - // - if (timerWindow == null) { - - timerWindow = new TimerNativeWindow(this); + if (!DesignMode) + { + if (value) + { + // Create the timer window if needed. + if (_timerWindow == null) + { + + _timerWindow = new TimerNativeWindow(this); } - timerRoot = GCHandle.Alloc(this); - - timerWindow.StartTimer(interval); + _timerRoot = GCHandle.Alloc(this); + _timerWindow.StartTimer(_interval); } - else{ - if (timerWindow != null){ - timerWindow.StopTimer(); - } - - if (timerRoot.IsAllocated) { - timerRoot.Free(); + else + { + _timerWindow?.StopTimer(); + if (_timerRoot.IsAllocated) + { + _timerRoot.Free(); } - } } - - } } - } } - /// - /// - /// - /// Indicates the time, in milliseconds, between timer ticks. - /// - [ - SRCategory(nameof(SR.CatBehavior)), - DefaultValue(100), - SRDescription(nameof(SR.TimerIntervalDescr)) - ] - public int Interval { - get { - return interval; - } - set { - lock(syncObj) { + /// + /// Indicates the time, in milliseconds, between timer ticks. + /// + [SRCategory(nameof(SR.CatBehavior))] + [DefaultValue(100)] + [SRDescription(nameof(SR.TimerIntervalDescr))] + public int Interval + { + get => _interval; + set + { + lock (_syncObj) + { if (value < 1) - throw new ArgumentOutOfRangeException(nameof(Interval), string.Format(SR.TimerInvalidInterval, value, (0).ToString(CultureInfo.CurrentCulture))); - - if (interval != value) { - interval = value; - if (Enabled) { - - Debug.Assert(DesignMode || timerWindow != null, "Why don't we have a timer HWND?"); - // just change the timer value, don't tear down the timer - // itself. - // - if (!DesignMode && timerWindow != null) { - timerWindow.RestartTimer(value); + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.TimerInvalidInterval, value, 0)); + } + + if (_interval != value) + { + _interval = value; + if (Enabled) + { + // Change the timer value, don't tear down the timer itself. + if (!DesignMode && _timerWindow != null) + { + _timerWindow.RestartTimer(value); } } } @@ -228,243 +173,203 @@ public int Interval { } } - /// - /// - /// Raises the - /// event. - /// - protected virtual void OnTick(EventArgs e) { - if (onTimer != null) onTimer(this, e); - } - - /// - /// - /// Starts the - /// timer. - /// - public void Start() { - Enabled = true; - } - - /// - /// - /// Stops the - /// timer. - /// - public void Stop() { - Enabled = false; - } + /// + /// Raises the event. + /// + protected virtual void OnTick(EventArgs e) => _onTimer?.Invoke(this, e); - /// - /// - /// returns us as a string. - /// - /// - public override string ToString() { - string s = base.ToString(); - return s + ", Interval: " + Interval.ToString(CultureInfo.CurrentCulture); - } - + /// + /// Starts the timer. + /// + public void Start() => Enabled = true; - private class TimerNativeWindow : NativeWindow { + /// + /// Stops the timer. + /// + public void Stop() => Enabled = false; + public override string ToString() => $"{base.ToString()}, Interval: {Interval}"; - // the timer that owns us - // - private Timer _owner; + private class TimerNativeWindow : NativeWindow + { + // The timer that owns the window + private readonly Timer _owner; - // our current id -- this is usally the same as TimerID but we also + // The current id -- this is usally the same as TimerID but we also // use it as a flag of when our timer is running. - // - private int _timerID; + private int _timerID; - // arbitrary timer ID. - // - private static int TimerID = 1; + // An arbitrary timer ID. + private static int s_timerID = 1; - // setting this when we are stopping the timer so someone can't restart it in the process. - // + // Setting this when we are stopping the timer so someone can't restart it in the process. private bool _stoppingTimer; - internal TimerNativeWindow(Timer owner) { - - this._owner = owner; + internal TimerNativeWindow(Timer owner) + { + _owner = owner; } - ~TimerNativeWindow() { - - - - - // note this call will work form the finalizer thread. - // + ~TimerNativeWindow() + { + // This call will work form the finalizer thread. StopTimer(); } - public bool IsTimerRunning { - get { - - return _timerID != 0 && Handle != IntPtr.Zero; - } - } - - - // Ensures that our HWND has been created. - // - private bool EnsureHandle() { - if (Handle == IntPtr.Zero) { + public bool IsTimerRunning => _timerID != 0 && Handle != IntPtr.Zero; - - // we create a totally vanilla invisible window just for WM_TIMER messages. - // - CreateParams cp = new CreateParams(); + private bool EnsureHandle() + { + if (Handle == IntPtr.Zero) + { + // Create a totally vanilla invisible window just for WM_TIMER messages + var cp = new CreateParams(); cp.Style = 0; cp.ExStyle = 0; cp.ClassStyle = 0; cp.Caption = GetType().Name; // Message only windows are cheaper and have fewer issues than - // full blown invisible windows. But, they are only supported - // on NT. - if (Environment.OSVersion.Platform == PlatformID.Win32NT) { - cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE; - } + // full blown invisible windows. + cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE; CreateHandle(cp); } - Debug.Assert(Handle != IntPtr.Zero, "Timer HWND creation failed!"); + + Debug.Assert(Handle != IntPtr.Zero, "Could not create timer HWND."); return Handle != IntPtr.Zero; } - // Returns true if we need to marshal across threads to access this timer's HWND. - // - private bool GetInvokeRequired(IntPtr hWnd) { - if (hWnd != IntPtr.Zero) { + /// + /// Returns true if we need to marshal across threads to access this timer's HWND. + /// + private bool GetInvokeRequired(IntPtr hWnd) + { + if (hWnd != IntPtr.Zero) + { int pid; int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid); - int currentThread = SafeNativeMethods.GetCurrentThreadId(); - return(hwndThread != currentThread); + return hwndThread != SafeNativeMethods.GetCurrentThreadId(); } + return false; } - // change the interval of the timer without destroying the HWND. - // - public void RestartTimer(int newInterval) { - StopTimer(false, IntPtr.Zero); + /// + /// Changes the interval of the timer without destroying the HWND. + /// + public void RestartTimer(int newInterval) + { + StopTimer(IntPtr.Zero, destroyHwnd: false); StartTimer(newInterval); } - // Start the timer with the specified interval. - // - public void StartTimer(int interval) { - - if (_timerID == 0 && !_stoppingTimer) { - if (EnsureHandle()) { - _timerID = (int) SafeNativeMethods.SetTimer(new HandleRef(this, Handle), TimerID++, interval, IntPtr.Zero); + public void StartTimer(int interval) + { + if (_timerID == 0 && !_stoppingTimer) + { + if (EnsureHandle()) + { + _timerID = (int)SafeNativeMethods.SetTimer(new HandleRef(this, Handle), s_timerID++, interval, IntPtr.Zero); } } } - // stop the timer. - // - public void StopTimer() { - - StopTimer(true, IntPtr.Zero); - } - - // stop the timer and optionally destroy the HWND. - // - public void StopTimer(bool destroyHwnd, IntPtr hWnd) { - - - if (hWnd == IntPtr.Zero) { + public void StopTimer() => StopTimer(IntPtr.Zero, destroyHwnd: true); + /// + /// Stop the timer and optionally destroy the HWND. + /// + public void StopTimer(IntPtr hWnd, bool destroyHwnd) + { + if (hWnd == IntPtr.Zero) + { hWnd = Handle; } // Fire a message across threads to destroy the timer and HWND on the thread that created it. - // - if (GetInvokeRequired(hWnd)) { - UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), NativeMethods.WM_CLOSE, 0, 0); + if (GetInvokeRequired(hWnd)) + { + UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), Interop.WindowMessages.WM_CLOSE, 0, 0); return; - } + } // Locking 'this' here is ok since this is an internal class. - lock(this) { - - if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) { - + lock (this) + { + if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) + { return; } - if (_timerID != 0) { - - - try { - _stoppingTimer = true; - SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID); + if (_timerID != 0) + { + try + { + _stoppingTimer = true; + SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID); } - finally { - _timerID = 0; + finally + { + _timerID = 0; _stoppingTimer = false; } - } - if (destroyHwnd) { - base.DestroyHandle(); + if (destroyHwnd) + { + base.DestroyHandle(); } } } - // Destroy the handle, stopping the timer first. - // - public override void DestroyHandle() { - // don't recurse! - // - StopTimer(false, IntPtr.Zero); + /// + /// Destroy the handle, stopping the timer first. + /// + public override void DestroyHandle() + { + // Avoid recursing. + StopTimer(IntPtr.Zero, destroyHwnd: false); Debug.Assert(_timerID == 0, "Destroying handle with timerID still set."); base.DestroyHandle(); } - protected override void OnThreadException(Exception e) { + protected override void OnThreadException(Exception e) + { Application.OnThreadException(e); } - public override void ReleaseHandle() { - // don't recurse! - // - StopTimer(false, IntPtr.Zero); + public override void ReleaseHandle() + { + // Avoid recursing. + StopTimer(IntPtr.Zero, destroyHwnd: false); Debug.Assert(_timerID == 0, "Destroying handle with timerID still set."); - base.ReleaseHandle(); } - protected override void WndProc(ref Message m) { - + protected override void WndProc(ref Message m) + { Debug.Assert(m.HWnd == Handle && Handle != IntPtr.Zero, "Timer getting messages for other windows?"); - // for timer messages, make sure they're ours (it'll be wierd if they aren't) - // and call the timer event. - // - if (m.Msg == NativeMethods.WM_TIMER) { - //Debug.Assert((int)m.WParam == _timerID, "Why are we getting a timer message that isn't ours?"); - if (unchecked( (int) (long)m.WParam) == _timerID) { + // For timer messages call the timer event. + if (m.Msg == Interop.WindowMessages.WM_TIMER) + { + if (unchecked((int)(long)m.WParam) == _timerID) + { _owner.OnTick(EventArgs.Empty); return; } } - else if (m.Msg == NativeMethods.WM_CLOSE) { - // this is a posted method from another thread that tells us we need - // to kill the timer. The handle may already be gone, so we specify it here. - // - StopTimer(true, m.HWnd); + else if (m.Msg == Interop.WindowMessages.WM_CLOSE) + { + // This is a posted method from another thread that tells us we need + // to kill the timer. The handle may already be gone, so we specify it here. + StopTimer(m.HWnd, destroyHwnd: true); return; - } + } + base.WndProc(ref m); } - } } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolBar.cs index ae00408a38b..b12743b1c96 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolBar.cs @@ -384,7 +384,7 @@ public Size ButtonSize { set { if (value.Width < 0 || value.Height < 0) - throw new ArgumentOutOfRangeException(nameof(ButtonSize), string.Format(SR.InvalidArgument, "ButtonSize", value.ToString())); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(ButtonSize), value)); if (buttonSize != value) { buttonSize = value; @@ -1124,7 +1124,7 @@ private void ForceButtonWidths() { for (int x = 0; x < buttonCount; x++) { NativeMethods.TBBUTTONINFO tbbi = new NativeMethods.TBBUTTONINFO(); - tbbi.cbSize = Marshal.SizeOf(typeof(NativeMethods.TBBUTTONINFO)); + tbbi.cbSize = Marshal.SizeOf(); tbbi.cx = buttons[x].Width; if (tbbi.cx > maxWidth) { @@ -1175,7 +1175,7 @@ private void InsertButton(int index, ToolBarButton value) { if (value == null) throw new ArgumentNullException(nameof(value)); if (index < 0 || ((buttons != null) && (index > buttonCount))) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); // insert the button into our local array, and then into the // real windows ToolBar control @@ -1273,7 +1273,7 @@ protected override void OnHandleCreated(EventArgs e) { // we have to set the button struct size, because they don't. // - SendMessage(NativeMethods.TB_BUTTONSTRUCTSIZE, Marshal.SizeOf(typeof(NativeMethods.TBBUTTON)), 0); + SendMessage(NativeMethods.TB_BUTTONSTRUCTSIZE, Marshal.SizeOf(), 0); // set up some extra goo // @@ -1358,7 +1358,7 @@ private void RealizeButtons() { // insert the buttons and set their parent pointers // - int cb = Marshal.SizeOf(typeof(NativeMethods.TBBUTTON)); + int cb = Marshal.SizeOf(); int count = buttonCount; ptbbuttons = Marshal.AllocHGlobal(checked(cb * count)); @@ -1630,12 +1630,12 @@ private void WmReflectCommand(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_COMMAND + NativeMethods.WM_REFLECT: + case Interop.WindowMessages.WM_COMMAND + Interop.WindowMessages.WM_REFLECT: WmReflectCommand(ref m); break; - case NativeMethods.WM_NOTIFY: - case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT: + case Interop.WindowMessages.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY + Interop.WindowMessages.WM_REFLECT: NativeMethods.NMHDR note = (NativeMethods.NMHDR) m.GetLParam(typeof(NativeMethods.NMHDR)); switch (note.code) { case NativeMethods.TTN_NEEDTEXT: @@ -1752,7 +1752,7 @@ public ToolBarButtonCollection(ToolBar owner) { public virtual ToolBarButton this[int index] { get { if (index < 0 || ((owner.buttons != null) && (index >= owner.buttonCount))) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); return owner.buttons[index]; } set { @@ -1760,7 +1760,7 @@ public virtual ToolBarButton this[int index] { // Sanity check parameters // if (index < 0 || ((owner.buttons != null) && index >= owner.buttonCount)) { - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); } if (value == null) { throw new ArgumentNullException(nameof(value)); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolBarButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolBarButton.cs index c5f9c7ac551..1641575fbe1 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolBarButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolBarButton.cs @@ -191,7 +191,7 @@ public int ImageIndex { set { if (ImageIndexer.Index != value) { if (value < -1) - throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "ImageIndex", (value).ToString(CultureInfo.CurrentCulture), -1)); + throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); ImageIndexer.Index = value; UpdateButton(false); @@ -547,7 +547,7 @@ internal int GetButtonWidth() { int buttonWidth = Parent.ButtonSize.Width; NativeMethods.TBBUTTONINFO button = new NativeMethods.TBBUTTONINFO(); - button.cbSize = Marshal.SizeOf(typeof(NativeMethods.TBBUTTONINFO)); + button.cbSize = Marshal.SizeOf(); button.dwMask = NativeMethods.TBIF_SIZE; int buttonID = (int)UnsafeNativeMethods.SendMessage(new HandleRef(Parent, Parent.Handle), NativeMethods.TB_GETBUTTONINFO, commandId, ref button); @@ -621,7 +621,7 @@ internal NativeMethods.TBBUTTON GetTBBUTTON(int commandId) { internal NativeMethods.TBBUTTONINFO GetTBBUTTONINFO(bool updateText, int newCommandId) { NativeMethods.TBBUTTONINFO button = new NativeMethods.TBBUTTONINFO(); - button.cbSize = Marshal.SizeOf(typeof(NativeMethods.TBBUTTONINFO)); + button.cbSize = Marshal.SizeOf(); button.dwMask = NativeMethods.TBIF_IMAGE | NativeMethods.TBIF_STATE | NativeMethods.TBIF_STYLE; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStrip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStrip.cs index 4303713ccab..1fe3b73ceab 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStrip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStrip.cs @@ -784,7 +784,7 @@ internal virtual NativeWindow DropDownOwnerWindow { /// /// Returns the drop target manager that all the hwndless - /// items and this winbar share. this is necessary as + /// items and this ToolStrip share. this is necessary as /// RegisterDragDrop requires an HWND. /// internal ToolStripDropTargetManager DropTargetManager { @@ -852,7 +852,7 @@ public override Rectangle DisplayRectangle { /// /// /// - /// Forecolor really has no meaning for winbars - so lets hide it + /// Forecolor really has no meaning for ToolStrips - so lets hide it /// [Browsable(false)] public new Color ForeColor { @@ -949,7 +949,7 @@ public ToolStripGripDisplayStyle GripDisplayStyle { /// /// - /// The external spacing between the grip and the padding of the winbar and the first item in the collection + /// The external spacing between the grip and the padding of the ToolStrip and the first item in the collection /// [ SRCategory(nameof(SR.CatLayout)), @@ -966,7 +966,7 @@ public Padding GripMargin { /// /// - /// The boundaries of the grip on the winbar. If it is invisible - returns Rectangle.Empty. + /// The boundaries of the grip on the ToolStrip. If it is invisible - returns Rectangle.Empty. /// [ Browsable(false) @@ -1139,7 +1139,7 @@ private bool IsLocationChanging { /// The items that belong to this ToolStrip. /// Note - depending on space and layout preferences, not all items /// in this collection will be displayed. They may not even be displayed - /// on this winbar (say in the case where we're overflowing the item). + /// on this ToolStrip (say in the case where we're overflowing the item). /// The collection of _Displayed_ items is the DisplayedItems collection. /// The displayed items collection also includes things like the OverflowButton /// and the Grip. @@ -1220,7 +1220,7 @@ public event ToolStripItemEventHandler ItemRemoved { Events.RemoveHandler(EventItemRemoved, value); } } - /// + /// /// handy check for painting and sizing [Browsable(false)] public bool IsDropDown { @@ -1235,7 +1235,7 @@ internal bool IsDisposingItems { /// /// The OnDrag[blah] methods that will be called if AllowItemReorder is true. /// - /// This allows us to have methods that handle drag/drop of the winbar items + /// This allows us to have methods that handle drag/drop of the ToolStrip items /// without calling back on the user's code /// internal IDropTarget ItemReorderDropTarget { @@ -1251,7 +1251,7 @@ internal IDropTarget ItemReorderDropTarget { /// The OnQueryContinueDrag and OnGiveFeedback methods that will be called if /// AllowItemReorder is true. /// - /// This allows us to have methods that handle drag/drop of the winbar items + /// This allows us to have methods that handle drag/drop of the ToolStrip items /// without calling back on the user's code /// internal ISupportOleDropSource ItemReorderDropSource { @@ -1617,15 +1617,11 @@ public bool Stretch { } } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; /// /// - /// The renderer is used to paint the hwndless winbar items. If someone wanted to + /// The renderer is used to paint the hwndless ToolStrip items. If someone wanted to /// change the "Hot" look of all of their buttons to be a green triangle, they should /// create a class that derives from ToolStripRenderer, assign it to this property and call /// invalidate. @@ -1755,16 +1751,14 @@ public bool ShowItemToolTips { UpdateToolTip(null); } - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - ToolTip internalToolTip = this.ToolTip; - foreach (ToolStripItem item in this.Items) { - if (showItemToolTips) { - KeyboardToolTipStateMachine.Instance.Hook(item, internalToolTip); - } - else { - KeyboardToolTipStateMachine.Instance.Unhook(item, internalToolTip); - } - } + ToolTip internalToolTip = this.ToolTip; + foreach (ToolStripItem item in this.Items) { + if (showItemToolTips) { + KeyboardToolTipStateMachine.Instance.Hook(item, internalToolTip); + } + else { + KeyboardToolTipStateMachine.Instance.Unhook(item, internalToolTip); + } } // If the overflow button has not been created, don't check its properties @@ -2180,37 +2174,32 @@ internal virtual ToolStripItem GetNextItem(ToolStripItem start, ArrowDirection d return GetNextItem(start, direction); } - /// - /// + /// /// Gets the next item from the given start item in the direction specified. /// - This function wraps if at the end /// - This function will only surf the items in the current container /// - Overriding this function will change the tab ordering and accessible child ordering. - /// + /// public virtual ToolStripItem GetNextItem(ToolStripItem start, ArrowDirection direction) { - if (!WindowsFormsUtils.EnumValidator.IsValidArrowDirection(direction)) { - throw new InvalidEnumArgumentException(nameof(direction), (int)direction, typeof(ArrowDirection)); - } - - switch (direction) { + switch (direction) + { case ArrowDirection.Right: - return GetNextItemHorizontal(start, /*forward = */true); + return GetNextItemHorizontal(start, forward: true); case ArrowDirection.Left: - return GetNextItemHorizontal(start, /*forward = */false); + return GetNextItemHorizontal(start, forward: false); case ArrowDirection.Down: - return GetNextItemVertical(start, /*forward = */true); + return GetNextItemVertical(start, down: true); case ArrowDirection.Up: - return GetNextItemVertical(start, /*forward = */false); + return GetNextItemVertical(start, down: false); + default: + throw new InvalidEnumArgumentException(nameof(direction), (int)direction, typeof(ArrowDirection)); } - - return null; } - - // - // Helper function for GetNextItem - do not directly call this. - // + /// + /// Helper function for GetNextItem - do not directly call this. + /// private ToolStripItem GetNextItemHorizontal(ToolStripItem start, bool forward) { if (DisplayedItems.Count <= 0) @@ -2218,11 +2207,10 @@ private ToolStripItem GetNextItemHorizontal(ToolStripItem start, bool forward) { if (start == null) { // The navigation should be consisstent when navigating in forward and - // backward direction entering the toolstrip, it means that for AI.Level3 - // the first toolstrip item should be selected irrespectively TAB or SHIFT+TAB + // backward direction entering the toolstrip, it means that the first + // toolstrip item should be selected irrespectively TAB or SHIFT+TAB // is pressed. - start = (forward) ? DisplayedItems[DisplayedItems.Count -1] : - (AccessibilityImprovements.Level3 ? DisplayedItems[DisplayedItems.Count > 1 ? 1 : 0] : DisplayedItems[0]); + start = (forward) ? DisplayedItems[DisplayedItems.Count -1] : DisplayedItems[DisplayedItems.Count > 1 ? 1 : 0]; } int current = DisplayedItems.IndexOf(start); @@ -2261,12 +2249,9 @@ private ToolStripItem GetNextItemHorizontal(ToolStripItem start, bool forward) { return null; } - - - - // - // Helper function for GetNextItem - do not directly call this. - // + /// + /// Helper function for GetNextItem - do not directly call this. + /// [SuppressMessage("Microsoft.Portability", "CA1902:AvoidTestingForFloatingPointEquality")] private ToolStripItem GetNextItemVertical(ToolStripItem selectedItem, bool down) { @@ -2650,7 +2635,7 @@ private void HookStaticEvents(bool hook) { } } - //initialize winbar + //initialize ToolStrip private void InitializeRenderer(ToolStripRenderer renderer) { // wrap this in a LayoutTransaction so that if they change sizes // in this method we've suspended layout. @@ -2664,7 +2649,7 @@ private void InitializeRenderer(ToolStripRenderer renderer) { } - // sometimes you only want to force a layout if the winbar is visible. + // sometimes you only want to force a layout if the ToolStrip is visible. private void InvalidateLayout() { if (IsHandleCreated) { LayoutTransaction.DoLayout(this, this, null); @@ -2790,7 +2775,7 @@ internal override void PrintToMetaFileRecursive(HandleRef hDC, IntPtr lParam, Re using (Graphics g = Graphics.FromImage(image)) { IntPtr imageHdc = g.GetHdc(); //send the actual wm_print message - UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), NativeMethods.WM_PRINT, (IntPtr)imageHdc, + UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), Interop.WindowMessages.WM_PRINT, (IntPtr)imageHdc, (IntPtr)(NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT)); //now BLT the result to the destination bitmap. @@ -3322,7 +3307,7 @@ protected internal virtual void OnItemAdded(ToolStripItemEventArgs e) { /// /// - /// Called when an item has been clicked on the winbar. + /// Called when an item has been clicked on the ToolStrip. /// protected virtual void OnItemClicked(ToolStripItemClickedEventArgs e) { ToolStripItemClickedEventHandler handler = (ToolStripItemClickedEventHandler)Events[EventItemClicked]; @@ -3418,7 +3403,7 @@ internal virtual void OnLocationChanging(ToolStripLocationCancelEventArgs e) { /// /// - /// Delegate mouse down to the winbar and its affected items + /// Delegate mouse down to the ToolStrip and its affected items /// protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs mea) { @@ -3453,7 +3438,7 @@ protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs mea) { /// /// - /// Delegate mouse moves to the winbar and its affected items + /// Delegate mouse moves to the ToolStrip and its affected items /// protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs mea) { Debug.WriteLineIf(ToolStripItem.MouseDebugging.TraceVerbose,"OnMouseMove called"); @@ -3516,7 +3501,7 @@ protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs mea) { /// /// - /// Delegate mouse leave to the winbar and its affected items + /// Delegate mouse leave to the ToolStrip and its affected items /// protected override void OnMouseLeave(System.EventArgs e) { HandleMouseLeave(); @@ -3539,7 +3524,7 @@ protected override void OnMouseCaptureChanged(System.EventArgs e) { /// /// - /// Delegate mouse up to the winbar and its affected items + /// Delegate mouse up to the ToolStrip and its affected items /// protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs mea) { @@ -4024,7 +4009,7 @@ internal virtual void ResetRenderMode() { RenderMode = ToolStripRenderMode.ManagerRenderMode; } - /// + /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetMinimumSize() { CommonProperties.SetMinimumSize(this, new Size(-1,-1)); @@ -4231,94 +4216,103 @@ internal void SetLargestItemSize(Size size) { } - /// /// /// Afer we've performed a layout we need to reset the DisplayedItems and the OverflowItems collection. /// OverflowItems are not supported in layouts other than ToolStripSplitStack /// - protected virtual void SetDisplayedItems() { - this.DisplayedItems.Clear(); - this.OverflowItems.Clear(); + protected virtual void SetDisplayedItems() + { + DisplayedItems.Clear(); + OverflowItems.Clear(); HasVisibleItems = false; - - Size biggestItemSize = Size.Empty; // used in determining OnPaint caching. + Size biggestItemSize = Size.Empty; // used in determining OnPaint caching. - if (this.LayoutEngine is ToolStripSplitStackLayout) { - if (ToolStripGripStyle.Visible == GripStyle) { - this.DisplayedItems.Add(Grip); + if (LayoutEngine is ToolStripSplitStackLayout) + { + if (ToolStripGripStyle.Visible == GripStyle) + { + DisplayedItems.Add(Grip); SetupGrip(); - } + } - // for splitstack layout we re-arrange the items in the displayed items + // For splitstack layout we re-arrange the items in the displayed items // collection so that we can easily tab through them in natural order - Rectangle displayRect = this.DisplayRectangle; + Rectangle displayRect = DisplayRectangle; int lastRightAlignedItem = -1; - for (int pass=0; pass < 2; pass++) { + for (int pass = 0; pass < 2; pass++) + { int j = 0; - - if (pass == 1 /*add right aligned items*/) { - j = lastRightAlignedItem; + + if (pass == 1 /*add right aligned items*/) + { + j = lastRightAlignedItem; } // add items to the DisplayedItem collection. // in pass 0, we go forward adding the head (left) aligned items // in pass 1, we go backward starting from the last (right) aligned item we found - - for (; j >= 0 && j < Items.Count; j = (pass == 0) ? j+1 : j-1){ - + for (; j >= 0 && j < Items.Count; j = (pass == 0) ? j + 1 : j - 1) + { + ToolStripItem item = Items[j]; ToolStripItemPlacement placement = item.Placement; - if (((IArrangedElement)item).ParticipatesInLayout) { - if (placement == ToolStripItemPlacement.Main) { - bool addItem = false; - if (pass == 0) { // Align.Left items - addItem = (item.Alignment == ToolStripItemAlignment.Left); - if (!addItem) { + if (((IArrangedElement)item).ParticipatesInLayout) + { + if (placement == ToolStripItemPlacement.Main) + { + bool addItem = false; + if (pass == 0) + { // Align.Left items + addItem = (item.Alignment == ToolStripItemAlignment.Left); + if (!addItem) + { // stash away this index so we dont have to iterate through the whole list again. lastRightAlignedItem = j; - } - } - else if (pass == 1) { // Align.Right items - addItem = (item.Alignment == ToolStripItemAlignment.Right); - } - if (addItem) { - HasVisibleItems = true; - biggestItemSize = LayoutUtils.UnionSizes(biggestItemSize, item.Bounds.Size); - this.DisplayedItems.Add(item); - } - } - else if (placement == ToolStripItemPlacement.Overflow && !(item is ToolStripSeparator)) { - if (item is ToolStripControlHost && this.OverflowButton.DropDown.IsRestrictedWindow) { - // Control hosts cannot be added to the overflow in the Internet - // just set the placement to None. - item.SetPlacement(ToolStripItemPlacement.None); + } } - else { - this.OverflowItems.Add(item); + else if (pass == 1) + { + // Align.Right items + addItem = (item.Alignment == ToolStripItemAlignment.Right); + } + if (addItem) + { + HasVisibleItems = true; + biggestItemSize = LayoutUtils.UnionSizes(biggestItemSize, item.Bounds.Size); + this.DisplayedItems.Add(item); } } + else if (placement == ToolStripItemPlacement.Overflow && !(item is ToolStripSeparator)) + { + this.OverflowItems.Add(item); + } } - else { + else + { item.SetPlacement(ToolStripItemPlacement.None); } } - + } ToolStripOverflow overflow = GetOverflow(); - if (overflow != null) { + if (overflow != null) + { overflow.LayoutRequired = true; } - if (OverflowItems.Count ==0) { + if (OverflowItems.Count == 0) + { this.OverflowButton.Visible = false; } - else if (CanOverflow){ + else if (CanOverflow) + { this.DisplayedItems.Add(OverflowButton); } - + } - else { + else + { // NOT a SplitStack layout. We dont change the order of the displayed items collection // for custom keyboard handling override GetNextItem. Debug.WriteLineIf(LayoutDebugSwitch.TraceVerbose, "Setting Displayed Items: Current bounds: " + this.Bounds.ToString()); @@ -4326,30 +4320,34 @@ protected virtual void SetDisplayedItems() { // for all other layout managers, we ignore overflow placement bool allContained = true; - for (int j = 0; j < Items.Count; j++) { + for (int j = 0; j < Items.Count; j++) + { ToolStripItem item = Items[j]; if (((IArrangedElement)item).ParticipatesInLayout) - { + { item.ParentInternal = this; bool boundsCheck = !IsDropDown; bool intersects = item.Bounds.IntersectsWith(clientBounds); bool verticallyContained = clientBounds.Contains(clientBounds.X, item.Bounds.Top) && - clientBounds.Contains(clientBounds.X, item.Bounds.Bottom); - if (!verticallyContained) { - allContained = false; + clientBounds.Contains(clientBounds.X, item.Bounds.Bottom); + if (!verticallyContained) + { + allContained = false; } - if (!boundsCheck || intersects) { - HasVisibleItems = true; - biggestItemSize = LayoutUtils.UnionSizes(biggestItemSize, item.Bounds.Size); - this.DisplayedItems.Add(item); - item.SetPlacement(ToolStripItemPlacement.Main); + if (!boundsCheck || intersects) + { + HasVisibleItems = true; + biggestItemSize = LayoutUtils.UnionSizes(biggestItemSize, item.Bounds.Size); + this.DisplayedItems.Add(item); + item.SetPlacement(ToolStripItemPlacement.Main); } } - else { - item.SetPlacement(ToolStripItemPlacement.None); + else + { + item.SetPlacement(ToolStripItemPlacement.None); } Debug.WriteLineIf(LayoutDebugSwitch.TraceVerbose, item.ToString() + Items[j].Bounds); @@ -4362,7 +4360,6 @@ protected virtual void SetDisplayedItems() { SetLargestItemSize(biggestItemSize); } - /// /// Sets the current value of the specified bit in the control's state. @@ -4485,10 +4482,6 @@ internal void UpdateToolTip(ToolStripItem item) { ToolTip.Hide(this); - if (AccessibilityImprovements.UseLegacyToolTipDisplay) { - ToolTip.Active = false; - } - currentlyActiveTooltipItem = item; @@ -4496,10 +4489,6 @@ internal void UpdateToolTip(ToolStripItem item) { Cursor currentCursor = Cursor.CurrentInternal; if (currentCursor != null) { - if (AccessibilityImprovements.UseLegacyToolTipDisplay) { - ToolTip.Active = true; - } - Point cursorLocation = Cursor.Position; cursorLocation.Y += Cursor.Size.Height - currentCursor.HotSpot.Y; @@ -4585,10 +4574,10 @@ private void UpdateOrientation(Orientation newOrientation) { /// protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_SETFOCUS) { + if (m.Msg == Interop.WindowMessages.WM_SETFOCUS) { SnapFocus(m.WParam); } - if (m.Msg == NativeMethods.WM_MOUSEACTIVATE) { + if (m.Msg == Interop.WindowMessages.WM_MOUSEACTIVATE) { // we want to prevent taking focus if someone clicks on the toolstrip dropdown // itself. the mouse message will still go through, but focus wont be taken. // if someone clicks on a child control (combobox, textbox, etc) focus will @@ -4635,7 +4624,7 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); - if (m.Msg == NativeMethods.WM_NCDESTROY) { + if (m.Msg == Interop.WindowMessages.WM_NCDESTROY) { // Destroy the owner window, if we created one. We // cannot do this in OnHandleDestroyed, because at // that point our handle is not actually destroyed so @@ -4678,17 +4667,13 @@ protected override Control.ControlCollection CreateControlsInstance() { internal void OnItemAddedInternal(ToolStripItem item) { - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - if (this.ShowItemToolTips) { - KeyboardToolTipStateMachine.Instance.Hook(item, this.ToolTip); - } + if (this.ShowItemToolTips) { + KeyboardToolTipStateMachine.Instance.Hook(item, this.ToolTip); } } internal void OnItemRemovedInternal(ToolStripItem item) { - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.Unhook(item, this.ToolTip); - } + KeyboardToolTipStateMachine.Instance.Unhook(item, this.ToolTip); } internal override bool AllowsChildrenToShowToolTips() { @@ -4961,31 +4946,27 @@ internal override UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRo } internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) { - if (AccessibilityImprovements.Level3) { - switch (direction) { - case UnsafeNativeMethods.NavigateDirection.FirstChild: - int childCount = GetChildFragmentCount(); - if (childCount > 0) { - return this.GetChildFragment(0); - } - break; - case UnsafeNativeMethods.NavigateDirection.LastChild: - childCount = GetChildFragmentCount(); - if (childCount > 0) { - return this.GetChildFragment(childCount - 1); - } - break; - } + switch (direction) { + case UnsafeNativeMethods.NavigateDirection.FirstChild: + int childCount = GetChildFragmentCount(); + if (childCount > 0) { + return this.GetChildFragment(0); + } + break; + case UnsafeNativeMethods.NavigateDirection.LastChild: + childCount = GetChildFragmentCount(); + if (childCount > 0) { + return this.GetChildFragment(childCount - 1); + } + break; } return base.FragmentNavigate(direction); } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) { - if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { - return NativeMethods.UIA_ToolBarControlTypeId; - } + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { + return NativeMethods.UIA_ToolBarControlTypeId; } return base.GetPropertyValue(propertyID); @@ -5025,12 +5006,12 @@ public bool PreFilterMessage(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_LBUTTONDOWN: - case NativeMethods.WM_RBUTTONDOWN: - case NativeMethods.WM_MBUTTONDOWN: - case NativeMethods.WM_NCLBUTTONDOWN: - case NativeMethods.WM_NCRBUTTONDOWN: - case NativeMethods.WM_NCMBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + case Interop.WindowMessages.WM_NCMBUTTONDOWN: if (ownerToolStrip.ContainsFocus) { // if we've clicked on something that's not a child of the toolstrip and we // currently have focus, restore it. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripButton.cs index 8edaf6ba9ae..b395243a72b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripButton.cs @@ -266,11 +266,9 @@ public ToolStripButtonAccessibleObject(ToolStripButton ownerItem): base(ownerIte } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) { - switch (propertyID) { - case NativeMethods.UIA_ControlTypePropertyId: - return NativeMethods.UIA_ButtonControlTypeId; - } + switch (propertyID) { + case NativeMethods.UIA_ControlTypePropertyId: + return NativeMethods.UIA_ButtonControlTypeId; } return base.GetPropertyValue(propertyID); @@ -278,7 +276,7 @@ internal override object GetPropertyValue(int propertyID) { public override AccessibleRole Role { get { - if (ownerItem.CheckOnClick && AccessibilityImprovements.Level1) { + if (ownerItem.CheckOnClick) { return AccessibleRole.CheckButton; } else { @@ -293,11 +291,9 @@ public override AccessibleStates State { return base.State | AccessibleStates.Checked; } - if (AccessibilityImprovements.Level1) { - // Disabled ToolStripButton, that is selected, must have focus state so that Narrator can announce it - if (!ownerItem.Enabled && ownerItem.Selected) { - return base.State | AccessibleStates.Focused; - } + // Disabled ToolStripButton, that is selected, must have focus state so that Narrator can announce it + if (!ownerItem.Enabled && ownerItem.Selected) { + return base.State | AccessibleStates.Focused; } return base.State; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripComboBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripComboBox.cs index 3845fcdaf10..e5b8d9c125a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripComboBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripComboBox.cs @@ -13,7 +13,6 @@ namespace System.Windows.Forms { using System.Drawing.Drawing2D; using System.Windows.Forms.Design; using System.Security; - using System.Security.Permissions; using System.Runtime.InteropServices; using System.Windows.Forms.Internal; using System.Globalization; @@ -61,11 +60,7 @@ public ToolStripComboBox(string name) : this() { /// The new instance of the accessibility object for this ToolStripComboBox ToolStrip item /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripComboBoxAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripComboBoxAccessibleObject(this); } /// @@ -153,7 +148,7 @@ private static Control CreateControlInstance() { comboBox.Font = ToolStripManager.DefaultFont; return comboBox; } - /// + /// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Localizable(true), @@ -166,7 +161,7 @@ public System.Windows.Forms.AutoCompleteStringCollection AutoCompleteCustomSourc set { ComboBox.AutoCompleteCustomSource = value;} } - /// + /// [ DefaultValue(AutoCompleteMode.None), SRDescription(nameof(SR.ComboBoxAutoCompleteModeDescr)), @@ -177,7 +172,7 @@ public AutoCompleteMode AutoCompleteMode { set { ComboBox.AutoCompleteMode = value;} } - /// + /// [ DefaultValue(AutoCompleteSource.None), SRDescription(nameof(SR.ComboBoxAutoCompleteSourceDescr)), @@ -259,7 +254,7 @@ protected internal override Padding DefaultMargin { } } - /// + /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.ComboBoxOnDropDownDescr))] public event EventHandler DropDown { add { @@ -270,7 +265,7 @@ public event EventHandler DropDown { } } - /// + /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.ComboBoxOnDropDownClosedDescr))] public event EventHandler DropDownClosed { add { @@ -280,7 +275,7 @@ public event EventHandler DropDownClosed { Events.RemoveHandler(EventDropDownClosed, value); } } - /// + /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.ComboBoxDropDownStyleChangedDescr))] public event EventHandler DropDownStyleChanged { add { @@ -292,7 +287,7 @@ public event EventHandler DropDownStyleChanged { } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.ComboBoxDropDownHeightDescr)), @@ -305,7 +300,7 @@ public int DropDownHeight { } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), DefaultValue(ComboBoxStyle.DropDown), @@ -317,7 +312,7 @@ public ComboBoxStyle DropDownStyle { set { ComboBox.DropDownStyle = value;} } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.ComboBoxDropDownWidthDescr)) @@ -327,7 +322,7 @@ public int DropDownWidth { set { ComboBox.DropDownWidth = value;} } - /// + /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -338,7 +333,7 @@ public bool DroppedDown { set { ComboBox.DroppedDown = value;} } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), DefaultValue(FlatStyle.Popup), @@ -350,7 +345,7 @@ public FlatStyle FlatStyle { set { ComboBox.FlatStyle = value;} } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(true), @@ -378,7 +373,7 @@ public ComboBox.ObjectCollection Items { } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(8), @@ -389,7 +384,7 @@ public int MaxDropDownItems { get { return ComboBox.MaxDropDownItems; } set { ComboBox.MaxDropDownItems = value;} } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(0), @@ -401,7 +396,7 @@ public int MaxLength { set { ComboBox.MaxLength = value; } } - /// + /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -411,7 +406,7 @@ public int SelectedIndex { get { return ComboBox.SelectedIndex; } set { ComboBox.SelectedIndex = value;} } - /// + /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.selectedIndexChangedEventDescr))] public event EventHandler SelectedIndexChanged { add { @@ -421,7 +416,7 @@ public event EventHandler SelectedIndexChanged { Events.RemoveHandler(EventSelectedIndexChanged, value); } } - /// + /// [ Browsable(false), Bindable(true), @@ -433,7 +428,7 @@ public object SelectedItem { set { ComboBox.SelectedItem = value;} } - /// + /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -443,7 +438,7 @@ public string SelectedText { get { return ComboBox.SelectedText; } set { ComboBox.SelectedText = value;} } - /// + /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -454,7 +449,7 @@ public int SelectionLength { set { ComboBox.SelectionLength = value;} } - /// + /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -464,7 +459,7 @@ public int SelectionStart { get { return ComboBox.SelectionStart; } set { ComboBox.SelectionStart = value;} } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(false), @@ -476,7 +471,7 @@ public bool Sorted { } - /// + /// [SRCategory(nameof(SR.CatBehavior)), SRDescription(nameof(SR.ComboBoxOnTextUpdateDescr))] public event EventHandler TextUpdate { add { @@ -489,23 +484,23 @@ public event EventHandler TextUpdate { #region WrappedMethods - /// + /// public void BeginUpdate() { ComboBox.BeginUpdate(); } - /// + /// public void EndUpdate() { ComboBox.EndUpdate(); } - /// + /// public int FindString(string s) { return ComboBox.FindString(s); } - /// + /// public int FindString(string s, int startIndex) { return ComboBox.FindString(s, startIndex); } - /// + /// public int FindStringExact(string s) { return ComboBox.FindStringExact(s); } - /// + /// public int FindStringExact(string s, int startIndex) { return ComboBox.FindStringExact(s, startIndex); } - /// + /// public int GetItemHeight(int index) { return ComboBox.GetItemHeight(index); } - /// + /// public void Select(int start, int length) { ComboBox.Select(start, length); } - /// + /// public void SelectAll() { ComboBox.SelectAll(); } #endregion WrappedMethods @@ -539,7 +534,7 @@ private void HandleTextUpdate(object sender, System.EventArgs e) { OnTextUpdate(e); } - /// + /// protected virtual void OnDropDown(EventArgs e) { if (ParentInternal != null) { Application.ThreadContext.FromCurrent().RemoveMessageFilter(ParentInternal.RestoreFocusFilter); @@ -547,7 +542,7 @@ protected virtual void OnDropDown(EventArgs e) { } RaiseEvent(EventDropDown, e); } - /// + /// protected virtual void OnDropDownClosed(EventArgs e) { if (ParentInternal != null) { // PERF, @@ -557,24 +552,24 @@ protected virtual void OnDropDownClosed(EventArgs e) { } RaiseEvent(EventDropDownClosed, e); } - /// + /// protected virtual void OnDropDownStyleChanged(EventArgs e) { RaiseEvent(EventDropDownStyleChanged, e); } - /// + /// protected virtual void OnSelectedIndexChanged(EventArgs e) { RaiseEvent(EventSelectedIndexChanged, e); } - /// + /// protected virtual void OnSelectionChangeCommitted(EventArgs e) { RaiseEvent(EventSelectionChangeCommitted, e); } - /// + /// protected virtual void OnTextUpdate(EventArgs e) { RaiseEvent(EventTextUpdate, e); } - /// + /// protected override void OnSubscribeControlEvents(Control control) { ComboBox comboBox = control as ComboBox; if (comboBox != null) { @@ -591,7 +586,7 @@ protected override void OnSubscribeControlEvents(Control control) { base.OnSubscribeControlEvents(control); } - /// + /// protected override void OnUnsubscribeControlEvents(Control control) { ComboBox comboBox = control as ComboBox; if (comboBox != null) { @@ -652,11 +647,7 @@ private ProfessionalColorTable ColorTable { /// The new instance of the accessibility object for this ToolStripComboBoxControl item /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripComboBoxControlAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripComboBoxControlAccessibleObject(this); } internal override FlatComboAdapter CreateFlatComboAdapterInstance() { @@ -741,7 +732,7 @@ protected override void DrawFlatComboDropDown(ComboBox comboBox, Graphics g, Rec Brush brush; if (comboBox.Enabled) { - if (AccessibilityImprovements.Level2 && SystemInformation.HighContrast && (comboBox.ContainsFocus || comboBox.MouseIsOver) && ToolStripManager.VisualStylesEnabled) { + if (SystemInformation.HighContrast && (comboBox.ContainsFocus || comboBox.MouseIsOver) && ToolStripManager.VisualStylesEnabled) { brush = SystemBrushes.HighlightText; } else { @@ -779,13 +770,9 @@ protected override void OnDropDownClosed(EventArgs e) { Update(); } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; - internal class ToolStripComboBoxControlAccessibleObject : ComboBoxUiaProvider { + internal class ToolStripComboBoxControlAccessibleObject : ComboBox.ComboBoxAccessibleObject { private ComboBox.ChildAccessibleObject childAccessibleObject; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripControlHost.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripControlHost.cs index e84080a7f61..927095cf654 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripControlHost.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripControlHost.cs @@ -54,9 +54,7 @@ public ToolStripControlHost(Control c) { Rectangle bounds = this.Bounds; CommonProperties.UpdateSpecifiedBounds(c, bounds.X, bounds.Y, bounds.Width, bounds.Height); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - c.ToolStripControlHost = this; - } + c.ToolStripControlHost = this; OnSubscribeControlEvents(c); } @@ -371,7 +369,7 @@ public event EventHandler LostFocus { } - /// + /// /// /// Occurs when a key is pressed down while the control has focus. /// @@ -385,7 +383,7 @@ public event KeyEventHandler KeyDown { } } - /// + /// /// /// Occurs when a key is pressed while the control has focus. /// @@ -399,7 +397,7 @@ public event KeyPressEventHandler KeyPress { } } - /// + /// /// /// Occurs when a key is released while the control has focus. /// @@ -780,15 +778,15 @@ protected virtual void OnLeave(EventArgs e) { protected virtual void OnLostFocus(EventArgs e) { RaiseEvent(EventLostFocus, e); } - /// + /// protected virtual void OnKeyDown(KeyEventArgs e) { RaiseKeyEvent(EventKeyDown, e); } - /// + /// protected virtual void OnKeyPress(KeyPressEventArgs e) { RaiseKeyPressEvent(EventKeyPress, e); } - /// + /// protected virtual void OnKeyUp(KeyEventArgs e) { RaiseKeyEvent(EventKeyUp, e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDown.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDown.cs index 57dba0700bd..f56f321651c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDown.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDown.cs @@ -67,57 +67,26 @@ public class ToolStripDropDown : ToolStrip { private static readonly int stateLayered = BitVector32.CreateMask(); private static readonly int stateAllowTransparency = BitVector32.CreateMask(stateLayered); - private static readonly int stateIsRestrictedWindow = BitVector32.CreateMask(stateAllowTransparency); - private static readonly int stateIsRestrictedWindowChecked = BitVector32.CreateMask(stateIsRestrictedWindow); - private static readonly int stateNotWorkingAreaConstrained = BitVector32.CreateMask(stateIsRestrictedWindowChecked); + private static readonly int stateNotWorkingAreaConstrained = BitVector32.CreateMask(stateAllowTransparency); private static readonly int stateInSetVisibleCore = BitVector32.CreateMask(stateNotWorkingAreaConstrained); - - - - /// - - - - - - - - - - - - - - - - - /// - /// - /// Summary of ToolStripDropDown. - /// - public ToolStripDropDown() { - if (DpiHelper.IsScalingRequirementMet) { + public ToolStripDropDown() + { + if (DpiHelper.IsScalingRequirementMet) + { scaledDefaultPadding = DpiHelper.LogicalToDeviceUnits(defaultPadding); } - // SECURITY NOTE: The IsRestrictedWindow check is done once and cached. We force it to happen here - // since we want to ensure the check is done on the code that constructs the ToolStripDropDown. - bool temp = IsRestrictedWindow; - - this.SuspendLayout(); + SuspendLayout(); Initialize(); - this.ResumeLayout(false); + ResumeLayout(false); } - - /// - /// - /// Summary of ToolStripDropDown. - /// - /// - internal ToolStripDropDown(ToolStripItem ownerItem): this() { + + internal ToolStripDropDown(ToolStripItem ownerItem): this() + { this.ownerItem = ownerItem; } + internal ToolStripDropDown(ToolStripItem ownerItem, bool isAutoGenerated) : this(ownerItem) { this.isAutoGenerated = isAutoGenerated; } @@ -298,7 +267,7 @@ public bool AutoClose { remove { base.ContextMenuStripChanged -= value; } } - /// + /// /// /// /// @@ -575,32 +544,6 @@ internal bool IsAssignedToDropDownItem { } } - /// - /// - /// - /// Determines if this form should display a warning banner - /// when the form is displayed in an unsecure mode. - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)] - internal bool IsRestrictedWindow { - get { - /// - if (!state[stateIsRestrictedWindowChecked]) { - state[stateIsRestrictedWindowChecked] = true; - state[stateIsRestrictedWindow] = false; -#if DEBUG - if (AlwaysRestrictWindows.Enabled) { - state[stateIsRestrictedWindow] = true; - return true; - } -#endif - } - - return state[stateIsRestrictedWindow]; - } - } - - internal override Size ImageScalingSizeInternal { get { if (IsAutoGenerated && OwnerToolStrip != null) { @@ -708,45 +651,41 @@ protected internal override Size MaxItemSize { } } - /// /// - /// Determines the opacity of the form. This can only be set on top level - /// controls. Opacity requires Windows 2000 or later, and is ignored on earlier - /// operating systems. + /// Determines the opacity of the form. This can only be set on top level controls. + /// Opacity requires Windows 2000 or later, and is ignored on earlier operating systems. /// - [ - SRCategory(nameof(SR.CatWindowStyle)), - TypeConverterAttribute(typeof(OpacityConverter)), - SRDescription(nameof(SR.FormOpacityDescr)), - DefaultValue(1.0), - Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced) - ] - public double Opacity { - get { + [SRCategory(nameof(SR.CatWindowStyle))] + [TypeConverterAttribute(typeof(OpacityConverter))] + [SRDescription(nameof(SR.FormOpacityDescr))] + [DefaultValue(1.0)] + [Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)] + public double Opacity + { + get + { object opacity = Properties.GetObject(PropOpacity); - if (opacity != null) { + if (opacity != null) + { return Convert.ToDouble(opacity, CultureInfo.InvariantCulture); } - else { - return 1.0f; - } + + return 1.0f; } - set { - if (IsRestrictedWindow) { - value = Math.Max(value, .50f); - } - - if (value > 1.0) { + set + { + if (value > 1.0) + { value = 1.0f; } - else if (value < 0.0) { + else if (value < 0.0) + { value = 0.0f; } - + Properties.SetObject(PropOpacity, value); - + bool oldLayered = (state[stateLayered]); - if (OpacityAsByte < 255 && OSFeature.Feature.IsPresent(OSFeature.LayeredWindows)) { AllowTransparency = true; @@ -754,13 +693,14 @@ public double Opacity { } else { - state[stateLayered] = false; + state[stateLayered] = false; } if (oldLayered != (state[stateLayered])) { UpdateStyles(); } + UpdateLayered(); } } @@ -964,7 +904,7 @@ protected virtual bool TopMost } - /// + /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool TopLevel { get { @@ -985,7 +925,7 @@ public bool TopLevel { // it's not robust enough for our needs // } - /// + /// /// Override base TabIndex property in order to avoid serialization /// (since a dropdown shouldn't participate in the taborder...) [ @@ -1029,7 +969,7 @@ public bool TopLevel { remove { base.Validating -= value; } } - /// + /// /// Override base Visible property in order to control serialization by setting default value [ SRCategory(nameof(SR.CatBehavior)), @@ -1049,18 +989,13 @@ public bool TopLevel { } // internally we use not so we dont have to initialize it. - internal bool WorkingAreaConstrained { - get { - if (state[stateNotWorkingAreaConstrained]) { - // - - return IsRestrictedWindow; - } - return true; - } - set { + internal bool WorkingAreaConstrained + { + get => true; + set + { bool notConstrained = !value; - state[stateNotWorkingAreaConstrained] = notConstrained; + state[stateNotWorkingAreaConstrained] = !value; } } @@ -1083,7 +1018,7 @@ private void ApplyTopMost(bool topMost) { } } - /// + /// protected override void Dispose(bool disposing) { if (disposing) { SourceControlInternal = null; @@ -1099,13 +1034,17 @@ private void CancelAutoExpand() { } } - internal override bool CanProcessMnemonic() { + internal override bool CanProcessMnemonic() + { // Dont let mnemonics act as keyboard input in IE in the internet. - if (IsRestrictedWindow && !Application.MessageLoop) { + if (Application.MessageLoop) + { return false; } + return base.CanProcessMnemonic(); } + /// protected override AccessibleObject CreateAccessibilityInstance() { return new ToolStripDropDownAccessibleObject(this); @@ -1161,17 +1100,7 @@ public void Close(ToolStripDropDownCloseReason reason) { SetCloseReason(reason); this.Visible = false; } - - internal override Rectangle ApplyBoundsConstraints(int suggestedX, int suggestedY, int proposedWidth, int proposedHeight) { - Rectangle adjustedBounds = base.ApplyBoundsConstraints(suggestedX, suggestedY, proposedWidth, proposedHeight); - - // - if (IsRestrictedWindow && TopMost) { - adjustedBounds = WindowsFormsUtils.ConstrainToScreenWorkingAreaBounds(adjustedBounds); - } - return adjustedBounds; - } /// /// Summary of GetBaseDropDownBounds. /// @@ -1322,7 +1251,7 @@ protected virtual void OnClosing(ToolStripDropDownClosingEventArgs e) { ToolStripDropDownClosingEventHandler handler = (ToolStripDropDownClosingEventHandler)Events[EventClosing]; if (handler != null) handler(this, e); } - /// + /// /// /// When our handle is being created, suspend the deactivation /// portion of the WndProc, as we'll never be shown. @@ -1415,7 +1344,7 @@ protected override void OnVisibleChanged(System.EventArgs e) { } } - /// + /// protected override void OnParentChanged(System.EventArgs e) { base.OnParentChanged(e); Rectangle bounds = this.Bounds; @@ -1457,9 +1386,7 @@ internal void SelectPreviousToolStrip() { if (itemOnPreviousMenuToSelect != null) { itemOnPreviousMenuToSelect.Select(); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(itemOnPreviousMenuToSelect); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(itemOnPreviousMenuToSelect); if (OwnerToolStrip != null) { // make sure we send keyboard handling where we've just @@ -1579,49 +1506,45 @@ protected override bool ProcessDialogKey(Keys keyData) { return base.ProcessDialogKey(keyData); } + [EditorBrowsable(EditorBrowsableState.Advanced)] + protected override bool ProcessDialogChar(char charCode) + { + Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ToolStripDropDown.ProcessDialogChar [" + charCode.ToString() + "]"); - - [EditorBrowsable(EditorBrowsableState.Advanced)] - protected override bool ProcessDialogChar(char charCode) { - #if DEBUG - Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ToolStripDropDown.ProcessDialogChar [" + charCode.ToString() + "]"); - #endif - // since we're toplevel and arent a container control, we've got to do our own mnemonic handling. - // - if ((OwnerItem == null || OwnerItem.Pressed) && charCode != ' ') { - if (ProcessMnemonic(charCode)){ + // Since we're toplevel and arent a container control, we've got to do our own mnemonic handling. + if ((OwnerItem == null || OwnerItem.Pressed) && charCode != ' ') + { + if (ProcessMnemonic(charCode)) + { return true; - } - } - return base.ProcessDialogChar(charCode); - } - - protected internal override bool ProcessMnemonic(char charCode) { - if (!CanProcessMnemonic()) { - return false; // here for security see CanProcessMnemonic. - } - return base.ProcessMnemonic(charCode); - } - internal override void ProcessDuplicateMnemonic(ToolStripItem item, char charCode) { - if (!CanProcessMnemonic()) { - return; // here for security see CanProcessMnemonic. - } - if (item != null) { - // + } + } + return base.ProcessDialogChar(charCode); + } + protected internal override bool ProcessMnemonic(char charCode) + { + if (!CanProcessMnemonic()) + { + return false; + } + return base.ProcessMnemonic(charCode); + } + internal override void ProcessDuplicateMnemonic(ToolStripItem item, char charCode) + { + if (!CanProcessMnemonic()) + { + return; + } - - if (IsRestrictedWindow) { - item.ProcessMnemonic(charCode); // execute the first click - } - else { - base.ProcessDuplicateMnemonic(item,charCode); - } - } - } + if (item != null) + { + base.ProcessDuplicateMnemonic(item, charCode); + } + } internal override void RecreateHandleCore() { // If we're visible, then we'll have set our parent hwnd to the active control. @@ -1752,46 +1675,53 @@ private void SetTopLevelStyle(bool value) { } } - /// - /// - /// Summary of SetVisibleCore. - /// - /// - protected override void SetVisibleCore(bool visible) { - if (state[stateInSetVisibleCore]) { + protected override void SetVisibleCore(bool visible) + { + if (state[stateInSetVisibleCore]) + { return; } + state[stateInSetVisibleCore] = true; - try { - if (visible) { - if (LayoutRequired) { + try + { + if (visible) + { + if (LayoutRequired) + { LayoutTransaction.DoLayout(this, this, PropertyNames.Visible); } - bool openingEventCancelled = true; // assume that it's been cancelled so that if we throw we do nothing. - try { + // Assume that it's been cancelled so that if we throw we do nothing. + bool openingEventCancelled = true; + + try + { // Add opening event. - // Snap the foreground window BEFORE calling any user events so they dont have a - // chance to activate something else. This covers the case where someone handles the - // opening event and throws up a messagebox. - IntPtr foregroundWindow = UnsafeNativeMethods.GetForegroundWindow(); + // Snap the foreground window BEFORE calling any user events so they + // dont have a chance to activate something else. This covers the case + // where someone handles the opening event and throws up a messagebox. + IntPtr foregroundWindow = UnsafeNativeMethods.GetForegroundWindow(); // Fire Opening event - // Cancellable event in which default value of e.Cancel depends on the number of displayed items >0. - // - CancelEventArgs openEventArgs = new CancelEventArgs(/*cancel=*/(DisplayedItems.Count == 0)); - OnOpening(openEventArgs); + // Cancellable event in which default value of e.Cancel depends on + // the number of displayed items >0. + CancelEventArgs openEventArgs = new CancelEventArgs(cancel: DisplayedItems.Count == 0); + OnOpening(openEventArgs); openingEventCancelled = openEventArgs.Cancel; - - if (!openingEventCancelled) { + + if (!openingEventCancelled) + { // do the actual work to open the window. - if (TopLevel) { + if (TopLevel) + { ReparentToActiveToolStripWindow(); } - // review: what is this used for? - if (OwnerToolStrip != null) { + + if (OwnerToolStrip != null) + { OwnerToolStrip.ActiveDropDowns.Add(this); // the act of showing this window can cause a spurious mouse move // in the parent, make sure it retains where the mouse really was. @@ -1799,67 +1729,68 @@ protected override void SetVisibleCore(bool visible) { // Make sure that mouse capture // transitions between the owner and dropdown. - if (OwnerToolStrip.CaptureInternal) { + if (OwnerToolStrip.CaptureInternal) + { CaptureInternal = true; } - } - base.SetVisibleCore(visible); - if (TopLevel){ + } + base.SetVisibleCore(visible); + if (TopLevel) + { ApplyTopMost(true); } - else if (IsHandleCreated && SafeNativeMethods.IsWindowEnabled(new HandleRef(this, Handle))) { + else if (IsHandleCreated && SafeNativeMethods.IsWindowEnabled(new HandleRef(this, Handle))) + { SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), NativeMethods.HWND_TOP, 0, 0, 0, 0, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOACTIVATE); } - } - } - finally { - // Fire Opened event - // fire the opened event only if we actually opened the control. - // - if (!openingEventCancelled) { + finally + { + // Fire the opened event only if we actually opened the control. + if (!openingEventCancelled) + { OnOpened(EventArgs.Empty); } } - } - else { - if (GetVisibleCore()) { + else + { + if (GetVisibleCore()) + { ToolStripDropDownCloseReason reason = closeReason; ResetCloseReason(); - - ToolStripDropDownClosingEventArgs e = new ToolStripDropDownClosingEventArgs(reason); + + var e = new ToolStripDropDownClosingEventArgs(reason); // Fire Closing Event // Cancel is prepopulated based on AutoClose feature. - // - if (e.CloseReason != ToolStripDropDownCloseReason.CloseCalled) { + if (e.CloseReason != ToolStripDropDownCloseReason.CloseCalled) + { e.Cancel = !AutoClose; } - else { + else + { e.Cancel = false; } - try { + try + { OnClosing(e); } - finally { - // - - - if (!e.Cancel || IsRestrictedWindow /*delay evaluate only in the case we need it*/) { - + finally + { + // delay evaluate only in the case we need it + if (!e.Cancel) + { // setting to not visible. Dismiss our child drop downs, reset, set ourselves visible false. DismissActiveDropDowns(); // Make sure we cancel auto expansion on the root ToolStrip topLevelToolStrip = GetToplevelOwnerToolStrip(); - ToolStrip parentToolStrip = null; - if (this.OwnerItem != null) { - parentToolStrip = this.OwnerItem.ParentInternal; - } + ToolStrip parentToolStrip = OwnerItem?.ParentInternal; + // We don't consider reason == ToolStripDropDownCloseReason.Keyboard here. // DropDown needs to be closed when Alt or ESC is pressed, // but these two keys are handled in ToolStrip.RestoreFocusInternal() @@ -1870,70 +1801,71 @@ protected override void SetVisibleCore(bool visible) { if ((reason == ToolStripDropDownCloseReason.AppClicked) || (reason == ToolStripDropDownCloseReason.ItemClicked) || (reason == ToolStripDropDownCloseReason.CloseCalled && topLevelToolStrip == parentToolStrip) || - (reason == ToolStripDropDownCloseReason.AppFocusChange && topLevelToolStrip == parentToolStrip)) { + (reason == ToolStripDropDownCloseReason.AppFocusChange && topLevelToolStrip == parentToolStrip)) + { CancelAutoExpand(); } // if this came through via a click event we should actually - // dismiss everyone in the chain. Other windows will recieve a - // close, closing event with reason AppFocusChange. This is by + // dismiss everyone in the chain. Other windows will recieve a + // close, closing event with reason AppFocusChange. This is by // design since the item wasnt clicked on that window. - if (reason == ToolStripDropDownCloseReason.ItemClicked) { + if (reason == ToolStripDropDownCloseReason.ItemClicked) + { // Preserve the SourceControl value up the chain. - this.saveSourceControl = true; - DismissAll(); + saveSourceControl = true; + DismissAll(); + // make sure that when we roll up, our owner item's selection is cleared. ToolStripItem rootOwnerItem = GetToplevelOwnerItem(); - if (rootOwnerItem != null) { - rootOwnerItem.Unselect(); - } + rootOwnerItem?.Unselect(); ToolStripManager.ModalMenuFilter.RemoveActiveToolStrip(this); - Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose,"[ToolStripDropDown.SetVisibleCore] Exiting menu mode because item clicked"); + Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.SetVisibleCore] Exiting menu mode because item clicked"); ToolStripManager.ModalMenuFilter.ExitMenuMode(); } - else { + else + { ToolStripManager.ModalMenuFilter.RemoveActiveToolStrip(this); } - // snap our bounds, we'll need it for some invalidation later. Rectangle bounds = this.Bounds; - - try { + try + { base.SetVisibleCore(visible); } - finally { - - // remove ourselves from the active dropdown list. - if (OwnerToolStrip != null) { - OwnerToolStrip.ActiveDropDowns.Remove(this); - } + finally + { + // rRmove ourselves from the active dropdown list. + OwnerToolStrip?.ActiveDropDowns.Remove(this); ActiveDropDowns.Clear(); + // If the user traps the click event and starts // pumping their own messages by calling Application.DoEvents, we // should release mouse capture. - if (CaptureInternal) { + if (CaptureInternal) + { CaptureInternal = false; } } // Fire OnClosed. // if you make VisibleChanged throw you dont get closed. Sorry. - - ToolStripDropDownClosedEventArgs closedEventArgs = new ToolStripDropDownClosedEventArgs(reason); + var closedEventArgs = new ToolStripDropDownClosedEventArgs(reason); OnClosed(closedEventArgs); - - if (TopLevel && (!IsDisposed || !Disposing)) { + + if (TopLevel && (!IsDisposed || !Disposing)) + { // Parent back up to our DropDownOwnerWindow. ReparentToDropDownOwnerWindow(); } - - if (!this.saveSourceControl) { + if (!saveSourceControl) + { Debug.Assert(reason != ToolStripDropDownCloseReason.ItemClicked, "Why are we resetting SourceControl on a click event?"); @@ -1945,35 +1877,39 @@ protected override void SetVisibleCore(bool visible) { // We may be about to invoke a click event here... // if we're the topmost dropdown then invalidate our // intersection with the toplevel toolstrip - if (!DesignMode && IsFirstDropDown && OwnerItem != null && TopLevel) { + if (!DesignMode && IsFirstDropDown && OwnerItem != null && TopLevel) + { ToolStrip toolStrip = GetToplevelOwnerToolStrip(); - if (toolStrip != null && !(toolStrip.IsDisposed || toolStrip.Disposing)) { + if (toolStrip != null && !(toolStrip.IsDisposed || toolStrip.Disposing)) + { // translate the bounds (already in screen coords) to toolstrip. bounds.Location = toolStrip.PointToClient(bounds.Location); // find the intersection with the client and use that to invalidate bounds.Intersect(toolStrip.ClientRectangle); - - if (bounds.Width > 0 && bounds.Height >0) { + + if (bounds.Width > 0 && bounds.Height > 0) + { toolStrip.Invalidate(bounds); toolStrip.Update(); } } } - + } } } - else { + else + { ToolStripManager.ModalMenuFilter.RemoveActiveToolStrip(this); } } } - finally { - state[stateInSetVisibleCore] = false; - this.saveSourceControl = false; + finally + { + state[stateInSetVisibleCore] = false; + saveSourceControl = false; } - } private bool ShouldSerializeDefaultDropDownDirection() { @@ -2080,69 +2016,50 @@ internal void UnassignDropDownItem() { countDropDownItemsAssignedTo = Math.Max(--countDropDownItemsAssignedTo, 0); } - protected override void WndProc(ref Message m) { - - if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST && IsRestrictedWindow) { - // - - - - - // NOTE the same kind of fix needs to go into ToolStripScrollButton.StickyLabel (the only alloewed ControlHost) - DefWndProc(ref m); - return; - } - switch (m.Msg) { - case NativeMethods.WM_NCACTIVATE: - // if someone clicks on a child control of the toolstrip dropdown, we want - // the title bar to continue appearing active. Normally we just show without - // taking window activation (ShowWindow(SHOWNOACTIVATE)) but we cant stop - // child controls from taking focus. - WmNCActivate(ref m); - return; - case NativeMethods.WM_ACTIVATE: - // This is the Chrome Panel collection editor scenario - // we had focus, then the Chrome panel was activated and we never went away - // when we get focus again, we should reactivate our message filter. - Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.WndProc] got a WM_ACTIVATE " + (((int)m.WParam == NativeMethods.WA_ACTIVE) ? "WA_ACTIVE" : "WA_INACTIVE") + " - checkin if we need to set the active toolstrip"); - - if((int)m.WParam == NativeMethods.WA_ACTIVE) { - if (this.Visible) { - if (ToolStripManager.ModalMenuFilter.GetActiveToolStrip() != this) { - // if we were inactive and now we are, we should enter menu mode - ToolStripManager.ModalMenuFilter.SetActiveToolStrip(this); - } - } - else { - Debug.Fail("Why are we being activated when we're not visible? Deactivating thingee is " + WindowsFormsUtils.GetControlInformation(m.LParam)); - } - } - else { - Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.WndProc] activating thingee is " + WindowsFormsUtils.GetControlInformation(m.LParam)); - } - - base.WndProc(ref m); - return; -/* case NativeMethods.WM_SYSKEYUP: - Keys keyData = (Keys)(int)m.WParam; - base.WndProc(ref m); - // handle the case where the ALT key has been pressed down while a dropdown - // was open. We need to clear off the MenuKeyToggle so the next ALT will activate - // the menu. - if (IsMenuKey(keyData)) { - ToolStrip toplevel = GetToplevelOwnerToolStrip(); - if (toplevel != null && toplevel.MenuKeyToggle) { - Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown WM_SYSKEYUP]: Got Menu Key, restoring MenuKeyToggle."); - toplevel.MenuKeyToggle = false; + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case Interop.WindowMessages.WM_NCACTIVATE: + // if someone clicks on a child control of the toolstrip dropdown, we want + // the title bar to continue appearing active. Normally we just show without + // taking window activation (ShowWindow(SHOWNOACTIVATE)) but we cant stop + // child controls from taking focus. + WmNCActivate(ref m); + return; + case Interop.WindowMessages.WM_ACTIVATE: + // This is the Chrome Panel collection editor scenario + // we had focus, then the Chrome panel was activated and we never went away + // when we get focus again, we should reactivate our message filter. + Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.WndProc] got a WM_ACTIVATE " + (((int)m.WParam == NativeMethods.WA_ACTIVE) ? "WA_ACTIVE" : "WA_INACTIVE") + " - checkin if we need to set the active toolstrip"); + + if ((int)m.WParam == NativeMethods.WA_ACTIVE) + { + if (Visible) + { + if (ToolStripManager.ModalMenuFilter.GetActiveToolStrip() != this) + { + // if we were inactive and now we are, we should enter menu mode + ToolStripManager.ModalMenuFilter.SetActiveToolStrip(this); + } + } + else + { + Debug.Fail("Why are we being activated when we're not visible? Deactivating thingee is " + WindowsFormsUtils.GetControlInformation(m.LParam)); } } - return;*/ - default: - base.WndProc(ref m); - return; - } + else + { + Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.WndProc] activating thingee is " + WindowsFormsUtils.GetControlInformation(m.LParam)); + } - } + base.WndProc(ref m); + return; + default: + base.WndProc(ref m); + return; + } + } #region DropDownSpecific @@ -2198,7 +2115,7 @@ private void WmNCActivate(ref Message m) { // we're activating - notify the previous guy that we're activating. HandleRef activeHwndHandleRef = ToolStripManager.ModalMenuFilter.ActiveHwnd; - UnsafeNativeMethods.SendMessage(activeHwndHandleRef, NativeMethods.WM_NCACTIVATE, (IntPtr)1, NativeMethods.InvalidIntPtr); + UnsafeNativeMethods.SendMessage(activeHwndHandleRef, Interop.WindowMessages.WM_NCACTIVATE, (IntPtr)1, NativeMethods.InvalidIntPtr); SafeNativeMethods.RedrawWindow(activeHwndHandleRef, null, NativeMethods.NullHandleRef, NativeMethods.RDW_FRAME | NativeMethods.RDW_INVALIDATE); m.WParam = (IntPtr)1; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownButton.cs index b5ec8a00602..89f610d02b3 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownButton.cs @@ -52,12 +52,7 @@ public ToolStripDropDownButton(string text, Image image, params ToolStripItem[] } protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level1) { - return new ToolStripDropDownButtonAccessibleObject(this); - } - else { - return base.CreateAccessibilityInstance(); - } + return new ToolStripDropDownButtonAccessibleObject(this); } [DefaultValue(true)] @@ -104,7 +99,7 @@ internal override ToolStripItemInternalLayout CreateInternalLayout() { protected override ToolStripDropDown CreateDefaultDropDown() { - // AutoGenerate a Winbar DropDown - set the property so we hook events + // AutoGenerate a ToolStrip DropDown - set the property so we hook events return new ToolStripDropDownMenu(this, /*isAutoGenerated=*/true); } @@ -177,7 +172,7 @@ protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { Rectangle dropDownArrowRect = (layout != null) ? layout.DropDownArrowRect :Rectangle.Empty; Color arrowColor; - if (Selected && !Pressed && AccessibilityImprovements.Level2 && SystemInformation.HighContrast) { + if (Selected && !Pressed && SystemInformation.HighContrast) { arrowColor = Enabled ? SystemColors.HighlightText : SystemColors.ControlDark; } else { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownItem.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownItem.cs index 7ad9189570f..a8429ac932f 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownItem.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownItem.cs @@ -196,7 +196,7 @@ internal protected virtual Point DropDownLocation } } - /// + /// [ SRCategory(nameof(SR.CatAction)), SRDescription(nameof(SR.ToolStripDropDownOpeningDescr)) @@ -300,7 +300,7 @@ protected override AccessibleObject CreateAccessibilityInstance() { /// protected virtual ToolStripDropDown CreateDefaultDropDown() { - // AutoGenerate a Winbar DropDown - set the property so we hook events + // AutoGenerate a ToolStrip DropDown - set the property so we hook events return new ToolStripDropDown(this, true); } @@ -414,10 +414,9 @@ public void HideDropDown() { if (this.dropDown != null && this.dropDown.Visible) { DropDown.Visible = false; - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.StateChange); - AccessibilityNotifyClients(AccessibleEvents.NameChange); - } + + AccessibilityNotifyClients(AccessibleEvents.StateChange); + AccessibilityNotifyClients(AccessibleEvents.NameChange); } } @@ -552,9 +551,7 @@ protected internal override bool ProcessDialogKey(Keys keyData) { if (Enabled || DesignMode) { // |__[ * File ]_____| * is where you are. Up or down arrow hit should expand menu this.ShowDropDown(); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); this.DropDown.SelectNextToolStripItem(null, true); }// else eat the key return true; @@ -574,9 +571,7 @@ protected internal override bool ProcessDialogKey(Keys keyData) { if (Enabled || DesignMode) { this.ShowDropDown(); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); this.DropDown.SelectNextToolStripItem(null, true); } // else eat the key return true; @@ -602,9 +597,7 @@ protected internal override bool ProcessDialogKey(Keys keyData) { if (parent != null && !parent.IsFirstDropDown) { // we're walking back up the dropdown chain. parent.SetCloseReason(ToolStripDropDownCloseReason.Keyboard); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); parent.SelectPreviousToolStrip(); return true; } @@ -693,10 +686,8 @@ private void ShowDropDownInternal() { this.dropDown.Show(); this.Invalidate(); - if (AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.StateChange); - AccessibilityNotifyClients(AccessibleEvents.NameChange); - } + AccessibilityNotifyClients(AccessibleEvents.StateChange); + AccessibilityNotifyClients(AccessibleEvents.NameChange); } } @@ -756,7 +747,7 @@ public override void DoDefaultAction() { } internal override bool IsIAccessibleExSupported() { - if (owner!= null && AccessibilityImprovements.Level1 ) { + if (owner != null) { return true; } else { @@ -774,7 +765,7 @@ internal override bool IsPatternSupported(int patternId) { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_IsOffscreenPropertyId && owner != null && owner.Owner is ToolStripDropDown) { + if (propertyID == NativeMethods.UIA_IsOffscreenPropertyId && owner != null && owner.Owner is ToolStripDropDown) { return !((ToolStripDropDown)owner.Owner).Visible; } @@ -812,7 +803,7 @@ public override int GetChildCount() { // Do not expose child items when the submenu is collapsed to prevent Narrator from announcing // invisible menu items when Narrator is in item's mode (CAPSLOCK + Arrow Left/Right) or // in scan mode (CAPSLOCK + Space) - if (AccessibilityImprovements.Level3 && ExpandCollapseState == UnsafeNativeMethods.ExpandCollapseState.Collapsed) { + if (ExpandCollapseState == UnsafeNativeMethods.ExpandCollapseState.Collapsed) { return 0; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownMenu.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownMenu.cs index f26d0668fec..30e8e6f8425 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownMenu.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropDownMenu.cs @@ -15,7 +15,6 @@ namespace System.Windows.Forms { using System.Reflection; using System.Runtime.InteropServices; using System.Security; - using System.Security.Permissions; using System.Windows.Forms.Internal; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; @@ -212,7 +211,7 @@ protected internal override Size MaxItemSize { } } - /// + /// [ DefaultValue(true), SRDescription(nameof(SR.ToolStripDropDownMenuShowImageMarginDescr)), @@ -230,7 +229,7 @@ public bool ShowImageMargin { } } - /// + /// [ DefaultValue(false), SRDescription(nameof(SR.ToolStripDropDownMenuShowCheckMarginDescr)), @@ -287,7 +286,7 @@ internal static ToolStripDropDownMenu FromHMenu(IntPtr hmenu, IWin32Window targe for (int i = 0; i < count; i++) { // peek at the i'th item. NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); + info.cbSize = Marshal.SizeOf(); info.fMask = NativeMethods.MIIM_FTYPE; info.fType = NativeMethods.MIIM_FTYPE; UnsafeNativeMethods.GetMenuItemInfo(menuHandle, i, /*fByPosition=*/ true, info); @@ -299,7 +298,7 @@ internal static ToolStripDropDownMenu FromHMenu(IntPtr hmenu, IWin32Window targe else { // its a menu item... lets fish out the command id info = new NativeMethods.MENUITEMINFO_T_RW(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); + info.cbSize = Marshal.SizeOf(); info.fMask = NativeMethods.MIIM_ID; info.fType = NativeMethods.MIIM_ID; UnsafeNativeMethods.GetMenuItemInfo(menuHandle, i, /*fByPosition=*/ true, info); @@ -310,7 +309,7 @@ internal static ToolStripDropDownMenu FromHMenu(IntPtr hmenu, IWin32Window targe // if there is a submenu fetch it. info = new NativeMethods.MENUITEMINFO_T_RW(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); + info.cbSize = Marshal.SizeOf(); info.fMask = NativeMethods.MIIM_SUBMENU; info.fType = NativeMethods.MIIM_SUBMENU; UnsafeNativeMethods.GetMenuItemInfo(menuHandle, i, /*fByPosition=*/ true, info); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropTargetManager.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropTargetManager.cs index a14d7b05d35..9d7b04d6c12 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropTargetManager.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripDropTargetManager.cs @@ -108,7 +108,7 @@ public void OnDragEnter(DragEventArgs e) { lastDropTarget = ((IDropTarget)item); } else if (owner.AllowDrop) { - // the winbar wants this event + // the ToolStrip wants this event Debug.WriteLineIf(DragDropDebug.TraceVerbose, "ToolStrip taking this because AllowDrop set to true."); lastDropTarget = ((IDropTarget)owner); @@ -162,7 +162,7 @@ public void OnDragOver(DragEventArgs e) { newDropTarget = ((IDropTarget)item); } else if (owner.AllowDrop) { - // the winbar wants this event + // the ToolStrip wants this event Debug.WriteLineIf(DragDropDebug.TraceVerbose, "ToolStrip taking this because AllowDrop set to true."); newDropTarget = ((IDropTarget)owner); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGrip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGrip.cs index 51a02ae32aa..d94acb9fc0d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGrip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGrip.cs @@ -274,13 +274,11 @@ public override AccessibleRole Role { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) { - switch (propertyID) { - case NativeMethods.UIA_IsOffscreenPropertyId: - return false; - case NativeMethods.UIA_ControlTypePropertyId: - return NativeMethods.UIA_ThumbControlTypeId; - } + switch (propertyID) { + case NativeMethods.UIA_IsOffscreenPropertyId: + return false; + case NativeMethods.UIA_ControlTypePropertyId: + return NativeMethods.UIA_ThumbControlTypeId; } return base.GetPropertyValue(propertyID); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGripRenderEventHandler.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGripRenderEventHandler.cs index 4def4acb7a2..9db51b83be5 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGripRenderEventHandler.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripGripRenderEventHandler.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms { /// - /// Called when the background of a winbar item is being rendered + /// Called when the background of a ToolStrip item is being rendered /// public delegate void ToolStripGripRenderEventHandler(object sender, ToolStripGripRenderEventArgs e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripHighContrastRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripHighContrastRenderer.cs index eb455b77f03..9e4b5c1654e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripHighContrastRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripHighContrastRenderer.cs @@ -103,28 +103,26 @@ protected override void OnRenderDropDownButtonBackground(ToolStripItemRenderEven } protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) { - if (AccessibilityImprovements.Level1) { - // The ARGB values came directly from the bitmap. - // If the bitmap colors change this code will no longer work and will - // need to be updated. - Color checkColor = Color.FromArgb(255, 4, 2, 4); - - // Create a color map to remap the check color to either the theme - // color for highlighted text or menu text, depending on whether - // the menu item is selected. - ColorMap[] checkColorMap = new ColorMap[1]; - checkColorMap[0] = new ColorMap(); - checkColorMap[0].OldColor = checkColor; - - checkColorMap[0].NewColor = ((e.Item.Selected || e.Item.Pressed) && e.Item.Enabled) ? - SystemColors.HighlightText : SystemColors.MenuText; - - // If we already have an image attributes associated with the event, - // just add the color map. Otherwise, create a new one. - ImageAttributes imageAttr = e.ImageAttributes ?? new ImageAttributes(); - imageAttr.SetRemapTable(checkColorMap, ColorAdjustType.Bitmap); - e.ImageAttributes = imageAttr; - } + // The ARGB values came directly from the bitmap. + // If the bitmap colors change this code will no longer work and will + // need to be updated. + Color checkColor = Color.FromArgb(255, 4, 2, 4); + + // Create a color map to remap the check color to either the theme + // color for highlighted text or menu text, depending on whether + // the menu item is selected. + ColorMap[] checkColorMap = new ColorMap[1]; + checkColorMap[0] = new ColorMap(); + checkColorMap[0].OldColor = checkColor; + + checkColorMap[0].NewColor = ((e.Item.Selected || e.Item.Pressed) && e.Item.Enabled) ? + SystemColors.HighlightText : SystemColors.MenuText; + + // If we already have an image attributes associated with the event, + // just add the color map. Otherwise, create a new one. + ImageAttributes imageAttr = e.ImageAttributes ?? new ImageAttributes(); + imageAttr.SetRemapTable(checkColorMap, ColorAdjustType.Bitmap); + e.ImageAttributes = imageAttr; base.OnRenderItemCheck(e); } @@ -154,7 +152,7 @@ protected override void OnRenderSplitButtonBackground(ToolStripItemRenderEventAr g.DrawRectangle(SystemPens.ButtonHighlight, dropDownRect); } - Color arrowColor = AccessibilityImprovements.Level2 && item.Selected && !item.Pressed ? SystemColors.HighlightText : SystemColors.ControlText; + Color arrowColor = item.Selected && !item.Pressed ? SystemColors.HighlightText : SystemColors.ControlText; DrawArrow(new ToolStripArrowRenderEventArgs(g, item, dropDownRect, arrowColor, ArrowDirection.Down)); } } @@ -196,7 +194,7 @@ protected override void OnRenderOverflowButtonBackground(ToolStripItemRenderEven protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { - if (AccessibilityImprovements.Level2 && e.Item.Selected && (!e.Item.Pressed || e.Item is ToolStripButton)) { + if (e.Item.Selected && (!e.Item.Pressed || e.Item is ToolStripButton)) { e.DefaultTextColor = SystemColors.HighlightText; } else if (e.TextColor != SystemColors.HighlightText && e.TextColor != SystemColors.ControlText) { @@ -212,8 +210,7 @@ protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { // ToolstripButtons that are checked are rendered with a highlight // background. In that case, set the text color to highlight as well. - if (AccessibilityImprovements.Level1 && - typeof(ToolStripButton).IsAssignableFrom(e.Item.GetType()) && + if (typeof(ToolStripButton).IsAssignableFrom(e.Item.GetType()) && ((ToolStripButton)e.Item).DisplayStyle != ToolStripItemDisplayStyle.Image && ((ToolStripButton)e.Item).Checked) { e.TextColor = SystemColors.HighlightText; @@ -398,7 +395,7 @@ protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) if (button.CheckState == CheckState.Checked) { g.FillRectangle(SystemBrushes.Highlight, bounds); } - if (button.Selected && AccessibilityImprovements.Level1) { + if (button.Selected) { g.DrawRectangle(SystemPens.Highlight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); } else { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItem.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItem.cs index a5386ada1a1..213a60e70cb 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItem.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItem.cs @@ -327,7 +327,7 @@ public AccessibleRole AccessibleRole { /// /// - /// Determines if the item aligns towards the beginning or end of the winbar. + /// Determines if the item aligns towards the beginning or end of the ToolStrip. /// [ DefaultValue(ToolStripItemAlignment.Left), @@ -874,7 +874,7 @@ public event EventHandler DragLeave { /// /// This represents what we're actually going to drag. If the parent has set AllowItemReorder to true, /// then the item should call back on the private OnQueryContinueDrag/OnGiveFeedback that is implemented - /// in the parent winbar. + /// in the parent ToolStrip. /// /// Else if the parent does not support reordering of items (Parent.AllowItemReorder = false) - /// then call back on the ToolStripItem's OnQueryContinueDrag/OnGiveFeedback methods. @@ -917,7 +917,7 @@ public virtual bool Enabled { // clear all the other states. state[stateSelected | statePressed] = false; - if (wasSelected && !AccessibilityImprovements.UseLegacyToolTipDisplay) { + if (wasSelected) { KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); } @@ -1221,7 +1221,7 @@ public virtual Image Image { } - /// + /// [ Localizable(true), SRCategory(nameof(SR.CatAppearance)), @@ -1270,7 +1270,7 @@ public int ImageIndex { } set { if (value < -1) { - throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value.ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, -1)); } @@ -1745,8 +1745,8 @@ public event PaintEventHandler Paint { /// /// The parent of this ToolStripItem. This can be distinct from the owner because /// the item can fall onto another window (overflow). In this case the overflow - /// would be the parent but the original winbar would be the Owner. The "parent" - /// winbar will be firing things like paint events - where as the "owner" winbar + /// would be the parent but the original ToolStrip would be the Owner. The "parent" + /// ToolStrip will be firing things like paint events - where as the "owner" ToolStrip /// will be containing shared data like image lists. Typically the only one who should /// set the parent property is the layout manager on the ToolStrip. /// @@ -1768,7 +1768,7 @@ internal protected ToolStrip Parent { /// /// - /// Specifies whether or not the item is glued to the winbar or overflow or + /// Specifies whether or not the item is glued to the ToolStrip or overflow or /// can float between the two. /// [ @@ -1814,7 +1814,7 @@ public virtual Padding Padding { } /// - /// This is explicitly a winbar, because only winbars know how to manage winbaritems + /// This is explicitly a ToolStrip, because only ToolStrips know how to manage ToolStripitems /// internal ToolStrip ParentInternal { get { @@ -2278,20 +2278,22 @@ public virtual ToolStripTextDirection TextDirection { } } - /// - [DefaultValue(TextImageRelation.ImageBeforeText), - Localizable(true), - SRDescription(nameof(SR.ToolStripItemTextImageRelationDescr)), - SRCategory(nameof(SR.CatAppearance))] - public TextImageRelation TextImageRelation { - get { - return textImageRelation; - } - set { - if (!WindowsFormsUtils.EnumValidator.IsValidTextImageRelation(value)) { + [DefaultValue(TextImageRelation.ImageBeforeText)] + [Localizable(true)] + [SRDescription(nameof(SR.ToolStripItemTextImageRelationDescr))] + [SRCategory(nameof(SR.CatAppearance))] + public TextImageRelation TextImageRelation + { + get => textImageRelation; + set + { + if (!ClientUtils.IsEnumValid(value, (int)value, (int)TextImageRelation.Overlay, (int)TextImageRelation.TextBeforeImage, 1)) + { throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(TextImageRelation)); } - if(value != TextImageRelation) { + + if(value != TextImageRelation) + { textImageRelation = value; InvalidateItemLayout(PropertyNames.TextImageRelation); } @@ -2445,7 +2447,7 @@ internal virtual ToolStripItemInternalLayout CreateInternalLayout() { } /// /// - /// Disposes this winbar item... + /// Disposes this ToolStrip item... /// protected override void Dispose(bool disposing) { @@ -2786,9 +2788,7 @@ private void HandleMouseEnter(System.EventArgs e) { } } - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutMouseEnter(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutMouseEnter(this); if (Enabled) { OnMouseEnter(e); @@ -2824,9 +2824,7 @@ private void HandleLeave() { if (state[stateMouseDownAndNoDrag] || state[statePressed] || state[stateSelected]) { state[stateMouseDownAndNoDrag | statePressed | stateSelected] = false; - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); Invalidate(); } @@ -3329,7 +3327,7 @@ protected internal virtual bool ProcessDialogKey(Keys keyData) { // if (keyData == Keys.Enter || (state[stateSupportsSpaceKey] && keyData == Keys.Space)) { FireEvent(ToolStripItemEventType.Click); - if (ParentInternal != null && !ParentInternal.IsDropDown && !(AccessibilityImprovements.Level2 && !Enabled)) { + if (ParentInternal != null && !ParentInternal.IsDropDown && Enabled) { ParentInternal.RestoreFocusInternal(); } return true; @@ -3432,11 +3430,9 @@ public void Select() { } } - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(this); - if (AccessibilityImprovements.Level3 && AccessibilityObject is ToolStripItemAccessibleObject) { + if (AccessibilityObject is ToolStripItemAccessibleObject) { ((ToolStripItemAccessibleObject)AccessibilityObject).RaiseFocusChanged(); } @@ -3802,9 +3798,7 @@ internal void Unselect() { ParentInternal.NotifySelectionChange(this); } - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); #if SELECTEDCHANGED OnSelectedChanged(EventArgs.Empty); #endif @@ -3992,23 +3986,18 @@ public override string KeyboardShortcut { internal override int[] RuntimeId { get { - if (AccessibilityImprovements.Level1) { - if (runtimeId == null) { - // we need to provide a unique ID - // others are implementing this in the same manner - // first item is static - 0x2a - // [AccessibilityImprovements.Level3] first item should be UiaAppendRuntimeId since this is not a top-level element of the fragment. - // second item can be anything, but here it is a hash. For toolstrip hash is unique even with child controls. Hwnd is not. - - runtimeId = new int[2]; - runtimeId[0] = AccessibilityImprovements.Level3 ? NativeMethods.UiaAppendRuntimeId : 0x2a; - runtimeId[1] = ownerItem.GetHashCode(); - } - return runtimeId; - } - else { - return base.RuntimeId; + if (runtimeId == null) { + // we need to provide a unique ID + // others are implementing this in the same manner + // first item should be UiaAppendRuntimeId since this is not a top-level element of the fragment. + // second item can be anything, but here it is a hash. For toolstrip hash is unique even with child controls. Hwnd is not. + + runtimeId = new int[2]; + runtimeId[0] = NativeMethods.UiaAppendRuntimeId; + runtimeId[1] = ownerItem.GetHashCode(); } + + return runtimeId; } } @@ -4018,33 +4007,25 @@ internal override int[] RuntimeId { /// The accessible property ID. /// The accessible property value. internal override object GetPropertyValue(int propertyID) { - - if (AccessibilityImprovements.Level1) { - if (propertyID == NativeMethods.UIA_NamePropertyId) { + switch (propertyID) { + case NativeMethods.UIA_NamePropertyId: return Name; - } - else if (propertyID == NativeMethods.UIA_IsExpandCollapsePatternAvailablePropertyId) { + case NativeMethods.UIA_IsExpandCollapsePatternAvailablePropertyId: return (object)this.IsPatternSupported(NativeMethods.UIA_ExpandCollapsePatternId); - } - } - - if (AccessibilityImprovements.Level3) { - switch (propertyID) { - case NativeMethods.UIA_IsEnabledPropertyId: - return ownerItem.Enabled; - case NativeMethods.UIA_IsOffscreenPropertyId: - return ownerItem.Placement != ToolStripItemPlacement.Main; - case NativeMethods.UIA_IsKeyboardFocusablePropertyId: - return ownerItem.CanSelect; - case NativeMethods.UIA_HasKeyboardFocusPropertyId: - return ownerItem.Selected; - case NativeMethods.UIA_AccessKeyPropertyId: - return KeyboardShortcut; - case NativeMethods.UIA_IsPasswordPropertyId: - return false; - case NativeMethods.UIA_HelpTextPropertyId: - return Help ?? string.Empty; - } + case NativeMethods.UIA_IsEnabledPropertyId: + return ownerItem.Enabled; + case NativeMethods.UIA_IsOffscreenPropertyId: + return ownerItem.Placement != ToolStripItemPlacement.Main; + case NativeMethods.UIA_IsKeyboardFocusablePropertyId: + return ownerItem.CanSelect; + case NativeMethods.UIA_HasKeyboardFocusPropertyId: + return ownerItem.Selected; + case NativeMethods.UIA_AccessKeyPropertyId: + return KeyboardShortcut; + case NativeMethods.UIA_IsPasswordPropertyId: + return false; + case NativeMethods.UIA_HelpTextPropertyId: + return Help ?? string.Empty; } return base.GetPropertyValue(propertyID); @@ -4100,19 +4081,14 @@ public override AccessibleStates State { if (!ownerItem.Enabled) { - - if (AccessibilityImprovements.Level2) { - if (ownerItem.Selected && ownerItem is ToolStripMenuItem) { - return AccessibleStates.Unavailable | additionalState | AccessibleStates.Focused; - } + if (ownerItem.Selected && ownerItem is ToolStripMenuItem) { + return AccessibleStates.Unavailable | additionalState | AccessibleStates.Focused; } // Disabled menu items that are selected must have focus // state so that Narrator can announce them. - if (AccessibilityImprovements.Level1) { - if (ownerItem.Selected && ownerItem is ToolStripMenuItem) { - return AccessibleStates.Focused; - } + if (ownerItem.Selected && ownerItem is ToolStripMenuItem) { + return AccessibleStates.Focused; } return AccessibleStates.Unavailable | additionalState; @@ -4296,19 +4272,10 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga int increment = direction == UnsafeNativeMethods.NavigateDirection.NextSibling ? 1 : -1; AccessibleObject sibling = null; - if (AccessibilityImprovements.Level3) { - index += increment; - int itemsCount = GetChildFragmentCount(); - if (index >= 0 && index < itemsCount) { - sibling = GetChildFragment(index); - } - } - else { - // Skipping contol host items, as they are provided by system - do { - index += increment; - sibling = index >= 0 && index < Parent.GetChildCount() ? Parent.GetChild(index) : null; - } while (sibling != null && sibling is Control.ControlAccessibleObject); + index += increment; + int itemsCount = GetChildFragmentCount(); + if (index >= 0 && index < itemsCount) { + sibling = GetChildFragment(index); } return sibling; @@ -4587,7 +4554,7 @@ private ButtonBaseAdapter.LayoutData GetLayoutData() { public virtual Size GetPreferredSize(Size constrainingSize) { Size preferredSize = Size.Empty; EnsureLayout(); - // we would prefer not to be larger than the winbar itself. + // we would prefer not to be larger than the ToolStrip itself. // so we'll ask the ButtonAdapter layout guy what it thinks // its preferred size should be - and we'll tell it to be no // bigger than the ToolStrip itself. Note this is "Parent" not diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemEventType.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemEventType.cs index 8c8a770eca6..361d831c2c5 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemEventType.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemEventType.cs @@ -6,7 +6,7 @@ namespace System.Windows.Forms { /// /// These methods allow the ToolStrip to route events - /// to the winbar item. Since a ToolStrip is not a ToolStripItem, + /// to the ToolStrip item. Since a ToolStrip is not a ToolStripItem, /// it cannot directly call OnPaint. /// internal enum ToolStripItemEventType diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventArgs.cs index 77985c1f7ee..ff30011abd9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventArgs.cs @@ -16,7 +16,7 @@ public ToolStripItemImageRenderEventArgs(Graphics g, ToolStripItem item, Rectang } /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public ToolStripItemImageRenderEventArgs(Graphics g, ToolStripItem item, Image image, Rectangle imageRectangle) : base(g, item) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventHandler.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventHandler.cs index eef228db0d6..431979b5744 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventHandler.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemImageRenderEventHandler.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms { /// - /// Called when the background of a winbar item is being rendered + /// Called when the background of a ToolStrip item is being rendered /// public delegate void ToolStripItemImageRenderEventHandler(object sender, ToolStripItemImageRenderEventArgs e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemOverflow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemOverflow.cs index 379a296a286..20431e28996 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemOverflow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemOverflow.cs @@ -9,7 +9,7 @@ namespace System.Windows.Forms /// public enum ToolStripItemOverflow { - Never, // on the main winbar itself, + Never, // on the main ToolStrip itself, Always, // on the overflow window AsNeeded // DEFAULT try for main, overflow as necessary } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemPlacement.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemPlacement.cs index 6905bde34d5..4cc07d4e74c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemPlacement.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemPlacement.cs @@ -9,7 +9,7 @@ namespace System.Windows.Forms /// public enum ToolStripItemPlacement { - Main, // in the main winbar itself + Main, // in the main ToolStrip itself Overflow, // in the overflow window None // either offscreen or visible == false so we didn't lay it out } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventArgs.cs index c782b447166..8754eb07f3e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventArgs.cs @@ -9,7 +9,7 @@ namespace System.Windows.Forms public class ToolStripItemRenderEventArgs : EventArgs { /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public ToolStripItemRenderEventArgs(Graphics g, ToolStripItem item) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventHandler.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventHandler.cs index db226838d81..f15a606ae5a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventHandler.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemRenderEventHandler.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms { /// - /// Called when the background of a winbar item is being rendered + /// Called when the background of a ToolStrip item is being rendered /// public delegate void ToolStripItemRenderEventHandler(object sender, ToolStripItemRenderEventArgs e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventArgs.cs index 4b5ad5b13ca..fb02c0fb1e4 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventArgs.cs @@ -7,7 +7,7 @@ namespace System.Windows.Forms { /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public class ToolStripItemTextRenderEventArgs : ToolStripItemRenderEventArgs { @@ -16,7 +16,7 @@ public class ToolStripItemTextRenderEventArgs : ToolStripItemRenderEventArgs private bool _textColorChanged = false; /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public ToolStripItemTextRenderEventArgs(Graphics g, ToolStripItem item, string text, Rectangle textRectangle, Color textColor, Font textFont, TextFormatFlags format) : base(g, item) { @@ -30,7 +30,7 @@ public ToolStripItemTextRenderEventArgs(Graphics g, ToolStripItem item, string t } /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public ToolStripItemTextRenderEventArgs(Graphics g, ToolStripItem item, string text, Rectangle textRectangle, Color textColor, Font textFont, ContentAlignment textAlign) : base(g, item) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventHandler.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventHandler.cs index 56b0f99b5fe..3c1e2ab13dc 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventHandler.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItemTextRenderEventHandler.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms { /// - /// Called when the background of a winbar item is being rendered + /// Called when the background of a ToolStrip item is being rendered /// public delegate void ToolStripItemTextRenderEventHandler(object sender, ToolStripItemTextRenderEventArgs e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripLabel.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripLabel.cs index 59633793b9d..6e0c4a21dae 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripLabel.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripLabel.cs @@ -14,7 +14,7 @@ namespace System.Windows.Forms { /// /// - /// A non selectable winbar item + /// A non selectable ToolStrip item /// [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip)] public class ToolStripLabel : ToolStripItem { @@ -33,7 +33,7 @@ public class ToolStripLabel : ToolStripItem { /// /// - /// A non selectable winbar item + /// A non selectable ToolStrip item /// public ToolStripLabel() { } @@ -377,13 +377,11 @@ public override void DoDefaultAction() { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3) { - if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { - return NativeMethods.UIA_TextControlTypeId; - } - else if (propertyID == NativeMethods.UIA_LegacyIAccessibleStatePropertyId) { - return this.State; - } + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { + return NativeMethods.UIA_TextControlTypeId; + } + else if (propertyID == NativeMethods.UIA_LegacyIAccessibleStatePropertyId) { + return this.State; } return base.GetPropertyValue(propertyID); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripManager.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripManager.cs index b8e6183d3e4..83da03a69e2 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripManager.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripManager.cs @@ -815,9 +815,7 @@ private void EnterMenuModeCore() { } _inMenuMode = true; - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - NotifyLastLastFocusedToolAboutFocusLoss(); - } + NotifyLastLastFocusedToolAboutFocusLoss(); // fire timer messages to force our filter to get evaluated. ProcessMessages(true); @@ -876,13 +874,10 @@ private void ExitMenuModeCore() { SafeNativeMethods.ShowCaret(NativeMethods.NullHandleRef); } - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - IKeyboardToolTip tool; - if(this.lastFocusedTool.TryGetTarget(out tool) && tool != null) { - KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(tool); - } + IKeyboardToolTip tool; + if(this.lastFocusedTool.TryGetTarget(out tool) && tool != null) { + KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(tool); } - } finally { _inMenuMode = false; @@ -1161,13 +1156,13 @@ private static bool IsChildOrSameWindow(HandleRef hwndParent, HandleRef hwndChil private static bool IsKeyOrMouseMessage(Message m) { bool filterMessage = false; - if (m.Msg >= NativeMethods.WM_MOUSEFIRST && m.Msg <= NativeMethods.WM_MOUSELAST) { + if (m.Msg >= Interop.WindowMessages.WM_MOUSEFIRST && m.Msg <= Interop.WindowMessages.WM_MOUSELAST) { filterMessage = true; } - else if (m.Msg >= NativeMethods.WM_NCLBUTTONDOWN && m.Msg <= NativeMethods.WM_NCMBUTTONDBLCLK) { + else if (m.Msg >= Interop.WindowMessages.WM_NCLBUTTONDOWN && m.Msg <= Interop.WindowMessages.WM_NCMBUTTONDBLCLK) { filterMessage = true; } - else if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST) { + else if (m.Msg >= Interop.WindowMessages.WM_KEYFIRST && m.Msg <= Interop.WindowMessages.WM_KEYLAST) { filterMessage = true; } return filterMessage; @@ -1221,8 +1216,8 @@ public bool PreFilterMessage(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_MOUSEMOVE: - case NativeMethods.WM_NCMOUSEMOVE: + case Interop.WindowMessages.WM_MOUSEMOVE: + case Interop.WindowMessages.WM_NCMOUSEMOVE: // Mouse move messages should be eaten if they arent for a dropdown. // this prevents things like ToolTips and mouse over highlights from // being processed. @@ -1258,9 +1253,9 @@ public bool PreFilterMessage(ref Message m) { } } break; - case NativeMethods.WM_LBUTTONDOWN: - case NativeMethods.WM_RBUTTONDOWN: - case NativeMethods.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: // // When a mouse button is pressed, we should determine if it is within the client coordinates // of the active dropdown. If not, we should dismiss it. @@ -1270,9 +1265,9 @@ public bool PreFilterMessage(ref Message m) { /*y=*/NativeMethods.Util.SignedHIWORD(m.LParam)); break; - case NativeMethods.WM_NCLBUTTONDOWN: - case NativeMethods.WM_NCRBUTTONDOWN: - case NativeMethods.WM_NCMBUTTONDOWN: + case Interop.WindowMessages.WM_NCLBUTTONDOWN: + case Interop.WindowMessages.WM_NCRBUTTONDOWN: + case Interop.WindowMessages.WM_NCMBUTTONDOWN: // // When a mouse button is pressed, we should determine if it is within the client coordinates // of the active dropdown. If not, we should dismiss it. @@ -1282,14 +1277,14 @@ public bool PreFilterMessage(ref Message m) { /*y=*/NativeMethods.Util.SignedHIWORD(m.LParam)); break; - case NativeMethods.WM_KEYDOWN: - case NativeMethods.WM_KEYUP: - case NativeMethods.WM_CHAR: - case NativeMethods.WM_DEADCHAR: - case NativeMethods.WM_SYSKEYDOWN: - case NativeMethods.WM_SYSKEYUP: - case NativeMethods.WM_SYSCHAR: - case NativeMethods.WM_SYSDEADCHAR: + case Interop.WindowMessages.WM_KEYDOWN: + case Interop.WindowMessages.WM_KEYUP: + case Interop.WindowMessages.WM_CHAR: + case Interop.WindowMessages.WM_DEADCHAR: + case Interop.WindowMessages.WM_SYSKEYDOWN: + case Interop.WindowMessages.WM_SYSKEYUP: + case Interop.WindowMessages.WM_SYSCHAR: + case Interop.WindowMessages.WM_SYSDEADCHAR: if (!activeToolStrip.ContainsFocus) { Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ModalMenuFilter.PreFilterMessage] MODIFYING Keyboard message " + m.ToString()); @@ -1377,7 +1372,7 @@ private unsafe IntPtr MessageHookProc(int nCode, IntPtr wparam, IntPtr lparam) { // call pretranslate on the message - this should execute // the message filters and preprocess message. if (Application.ThreadContext.FromCurrent().PreTranslateMessage(ref *msg)) { - msg->message = NativeMethods.WM_NULL; + msg->message = Interop.WindowMessages.WM_NULL; } } } @@ -1484,7 +1479,7 @@ internal static bool ProcessCmdKey(ref Message m, Keys keyData) { return ToolStripManager.ProcessShortcut(ref m, keyData); } - if (m.Msg == NativeMethods.WM_SYSKEYDOWN) { + if (m.Msg == Interop.WindowMessages.WM_SYSKEYDOWN) { Debug.WriteLineIf(Control.ControlKeyboardRouting.TraceVerbose, "ToolStripManager.ProcessCmdKey - Checking if it's a menu key: [" + keyData.ToString() + "]"); ToolStripManager.ModalMenuFilter.ProcessMenuKeyDown(ref m); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripMenuItem.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripMenuItem.cs index 291c1991c20..fe30ae8cdc7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripMenuItem.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripMenuItem.cs @@ -159,7 +159,7 @@ private void ClearShortcutCache() { /// protected override ToolStripDropDown CreateDefaultDropDown() { - // AutoGenerate a Winbar DropDown - set the property so we hook events + // AutoGenerate a ToolStrip DropDown - set the property so we hook events return new ToolStripDropDownMenu(this, true); } @@ -196,13 +196,13 @@ protected override Size DefaultSize { } - /// + /// protected internal override Padding DefaultMargin { get { return Padding.Empty; } } - /// + /// protected override Padding DefaultPadding { get { if (IsOnDropDown) { @@ -274,13 +274,11 @@ internal Image CheckedImage { if (checkedState == CheckState.Indeterminate) { if (indeterminateCheckedImage == null) { if (DpiHelper.IsScalingRequirementMet) { - indeterminateCheckedImage = GetBitmapFromIcon("IndeterminateChecked.ico", scaledCheckMarkBitmapSize); + indeterminateCheckedImage = GetBitmapFromIcon("IndeterminateChecked", scaledCheckMarkBitmapSize); } else { - Bitmap indeterminateCheckedBmp = new Bitmap(typeof(ToolStripMenuItem), "IndeterminateChecked.bmp"); + Bitmap indeterminateCheckedBmp = DpiHelper.GetBitmapFromIcon(typeof(ToolStripMenuItem), "IndeterminateChecked"); if (indeterminateCheckedBmp != null) { - // - indeterminateCheckedBmp.MakeTransparent(indeterminateCheckedBmp.GetPixel(1, 1)); if (DpiHelper.IsScalingRequired) { DpiHelper.ScaleBitmapLogicalToDevice(ref indeterminateCheckedBmp); } @@ -293,13 +291,11 @@ internal Image CheckedImage { else if (checkedState == CheckState.Checked) { if (checkedImage == null) { if (DpiHelper.IsScalingRequirementMet) { - checkedImage = GetBitmapFromIcon("Checked.ico", scaledCheckMarkBitmapSize); + checkedImage = GetBitmapFromIcon("Checked", scaledCheckMarkBitmapSize); } else { - Bitmap checkedBmp = new Bitmap(typeof(ToolStripMenuItem), "Checked.bmp"); + Bitmap checkedBmp = DpiHelper.GetBitmapFromIcon(typeof(ToolStripMenuItem), "Checked"); if (checkedBmp != null) { - // - checkedBmp.MakeTransparent(checkedBmp.GetPixel(1, 1)); if (DpiHelper.IsScalingRequired) { DpiHelper.ScaleBitmapLogicalToDevice(ref checkedBmp); } @@ -330,7 +326,6 @@ private static Bitmap GetBitmapFromIcon(string iconName, Size desiredIconSize) if (b != null) { - b.MakeTransparent(b.GetPixel(1, 1)); if (DpiHelper.IsScalingRequired && (b.Size.Width != desiredIconSize.Width || b.Size.Height != desiredIconSize.Height)) { Bitmap scaledBitmap = DpiHelper.CreateResizedBitmap(b, desiredIconSize); @@ -353,7 +348,7 @@ private static Bitmap GetBitmapFromIcon(string iconName, Size desiredIconSize) return b; } - /// + /// [ DefaultValue(false), SRCategory(nameof(SR.CatBehavior)), @@ -436,7 +431,7 @@ public event EventHandler CheckStateChanged { /// /// - /// Specifies whether or not the item is glued to the winbar or overflow or + /// Specifies whether or not the item is glued to the ToolStrip or overflow or /// can float between the two. /// [ @@ -684,7 +679,7 @@ private bool GetNativeMenuItemEnabled() { return false; } NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW(); - info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); + info.cbSize = Marshal.SizeOf(); info.fMask = NativeMethods.MIIM_STATE; info.fType = NativeMethods.MIIM_STATE; info.wID = nativeMenuCommandID; @@ -831,14 +826,14 @@ internal string GetShortcutText() { internal void HandleAutoExpansion() { if (Enabled && ParentInternal != null && ParentInternal.MenuAutoExpand && HasDropDownItems) { ShowDropDown(); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); + DropDown.SelectNextToolStripItem(null, /*forward=*/true); } } - /// + /// protected override void OnClick(EventArgs e) { if (checkOnClick) { this.Checked = !this.Checked; @@ -852,13 +847,13 @@ protected override void OnClick(EventArgs e) { // use PostMessage instead of SendMessage so that the DefWndProc can appropriately handle // the system message... if we use SendMessage the dismissal of our window // breaks things like the modal sizing loop. - UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), NativeMethods.WM_SYSCOMMAND,nativeMenuCommandID, 0); + UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), Interop.WindowMessages.WM_SYSCOMMAND,nativeMenuCommandID, 0); } else { // These are user added items like ".Net Window..." // be consistent with sending a WM_SYSCOMMAND, use POST not SEND. - UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), NativeMethods.WM_COMMAND, nativeMenuCommandID, 0); + UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), Interop.WindowMessages.WM_COMMAND, nativeMenuCommandID, 0); } this.Invalidate(); } @@ -1102,7 +1097,7 @@ protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { else { - // Toplevel item support, menu items hosted on a plain winbar dropdown + // Toplevel item support, menu items hosted on a plain ToolStrip dropdown if ((DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) { renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, this.Text, InternalLayout.TextRectangle, textColor, this.Font, InternalLayout.TextFormat)); } @@ -1141,9 +1136,7 @@ protected internal override bool ProcessMnemonic(char charCode) { Select(); ShowDropDown(); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutLostFocus(this); DropDown.SelectNextToolStripItem(null, /*forward=*/true); return true; @@ -1152,7 +1145,7 @@ protected internal override bool ProcessMnemonic(char charCode) { return base.ProcessMnemonic(charCode); } - /// + /// /// overridden here so we scooch over when we're in the ToolStripDropDownMenu internal protected override void SetBounds(Rectangle rect) { @@ -1240,7 +1233,7 @@ internal override object GetPropertyValue(int propertyID) { if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { return NativeMethods.UIA_MenuItemControlTypeId; } - else if (AccessibilityImprovements.Level2 && propertyID == NativeMethods.UIA_AcceleratorKeyPropertyId) { + else if (propertyID == NativeMethods.UIA_AcceleratorKeyPropertyId) { return ownerItem.GetShortcutText(); } else { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflow.cs index 02a29f929d5..e92ed7c731a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflow.cs @@ -11,7 +11,6 @@ namespace System.Windows.Forms { using System.Diagnostics.CodeAnalysis; using System.Windows.Forms.Layout; using System.Security; - using System.Security.Permissions; using System.Runtime.InteropServices; @@ -144,7 +143,7 @@ protected override void OnLayout(LayoutEventArgs e) { /// protected override void SetDisplayedItems() { // do nothing here.... this is really for the setting the overflow/displayed items on the - // main winbar. Our working item collection is our displayed item collection... calling + // main ToolStrip. Our working item collection is our displayed item collection... calling // base would clear it out. Size biggestItemSize = Size.Empty; for (int j = 0; j < DisplayedItems.Count; j++) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflowButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflowButton.cs index 9b95c5884f3..e70c56096d7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflowButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripOverflowButton.cs @@ -53,7 +53,7 @@ protected override void Dispose(bool disposing) { base.Dispose(disposing); } - /// + /// protected internal override Padding DefaultMargin { get { return Padding.Empty; @@ -96,7 +96,7 @@ protected override AccessibleObject CreateAccessibilityInstance() { /// protected override ToolStripDropDown CreateDefaultDropDown() { - // AutoGenerate a Winbar DropDown - set the property so we hook events + // AutoGenerate a ToolStrip DropDown - set the property so we hook events return new ToolStripOverflow(this); } @@ -162,7 +162,7 @@ public override string Name { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_ControlTypePropertyId) { + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { return NativeMethods.UIA_MenuItemControlTypeId; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanel.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanel.cs index 9873e6221f1..ea718baee62 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanel.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanel.cs @@ -23,7 +23,7 @@ namespace System.Windows.Forms { [ComVisible(true)] [ClassInterface(ClassInterfaceType.AutoDispatch)] [Designer("System.Windows.Forms.Design.ToolStripPanelDesigner, " + AssemblyRef.SystemDesign)] - [ToolboxBitmapAttribute(typeof(ToolStripPanel), "ToolStripPanel_standalone.bmp")] + [ToolboxBitmapAttribute(typeof(ToolStripPanel), "ToolStripPanel_standalone")] public class ToolStripPanel : ContainerControl, IArrangedElement { @@ -377,9 +377,8 @@ public ToolStripPanelRow[] Rows { return base.TabStop; } set { - if (AccessibilityImprovements.Level2) { - SetStyle(ControlStyles.Selectable, value); - } + SetStyle(ControlStyles.Selectable, value); + base.TabStop = value; } } @@ -850,7 +849,7 @@ private void ForceSynchronousPaint() { try { NativeMethods.MSG msg = new NativeMethods.MSG(); while (UnsafeNativeMethods.PeekMessage(ref msg, new HandleRef(this, IntPtr.Zero), - NativeMethods.WM_PAINT, NativeMethods.WM_PAINT, + Interop.WindowMessages.WM_PAINT, Interop.WindowMessages.WM_PAINT, NativeMethods.PM_REMOVE)) { SafeNativeMethods.UpdateWindow(new HandleRef(null, msg.hwnd)); @@ -888,7 +887,7 @@ public void MoveTo(Point newLocation) { } protected override void WndProc(ref Message m){ - if (m.Msg == NativeMethods.WM_NCHITTEST){ + if (m.Msg == Interop.WindowMessages.WM_NCHITTEST){ m.Result = (IntPtr)NativeMethods.HTTRANSPARENT; } base.WndProc(ref m); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanelRow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanelRow.cs index dc018c052e1..8212bda6028 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanelRow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripPanelRow.cs @@ -692,7 +692,7 @@ void IArrangedElement.PerformLayout(IArrangedElement container, string propertyN #region MouseStuff #if DEBUG - internal static readonly TraceSwitch ToolStripPanelMouseDebug = new TraceSwitch("ToolStripPanelMouse", "Debug WinBar WM_MOUSEACTIVATE code"); + internal static readonly TraceSwitch ToolStripPanelMouseDebug = new TraceSwitch("ToolStripPanelMouse", "Debug ToolStrip WM_MOUSEACTIVATE code"); #else internal static readonly TraceSwitch ToolStripPanelMouseDebug; #endif diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripProgressBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripProgressBar.cs index f080f647e4f..e78fd77b38b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripProgressBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripProgressBar.cs @@ -9,7 +9,6 @@ namespace System.Windows.Forms { using System.ComponentModel; using System.Drawing; using System.Security; - using System.Security.Permissions; /// [DefaultProperty(nameof(Value))] @@ -260,15 +259,11 @@ public int Value { /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripProgressBarAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripProgressBarAccessibleObject(this); } private static Control CreateControlInstance() { - ProgressBar progressBar = AccessibilityImprovements.Level3 ? new ToolStripProgressBarControl() : new ProgressBar(); + ProgressBar progressBar = new ToolStripProgressBarControl(); progressBar.Size = new Size(100,15); return progressBar; } @@ -524,18 +519,10 @@ public ToolStripProgressBar Owner { set { ownerItem = value; } } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripProgressBarControlAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripProgressBarControlAccessibleObject(this); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderEventHandler.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderEventHandler.cs index b3695ad9722..29dbfc93b3b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderEventHandler.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderEventHandler.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms { /// - /// Called when the background of the winbar is being rendered + /// Called when the background of the ToolStrip is being rendered /// public delegate void ToolStripRenderEventHandler(object sender, ToolStripRenderEventArgs e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderer.cs index c48183708bd..f1a2da79729 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripRenderer.cs @@ -131,7 +131,7 @@ internal virtual ToolStripRenderer RendererOverride { - /// + /// public event ToolStripArrowRenderEventHandler RenderArrow { add { AddHandler(EventRenderArrow, value); @@ -259,7 +259,7 @@ public event ToolStripItemImageRenderEventHandler RenderItemImage { RemoveHandler(EventRenderItemImage, value); } } - /// + /// /// /// Draws the checkmark /// @@ -317,7 +317,7 @@ public event ToolStripItemRenderEventHandler RenderMenuItemBackground { } } - /// + /// /// /// Draws the split button /// @@ -357,7 +357,7 @@ public event ToolStripItemRenderEventHandler RenderSplitButtonBackground { } - /// + /// public event ToolStripSeparatorRenderEventHandler RenderSeparator { add { AddHandler(EventRenderSeparator, value); @@ -388,7 +388,7 @@ public static Image CreateDisabledImage(Image normalImage) { return CreateDisabledImage(normalImage, null); } - /// + /// public void DrawArrow(ToolStripArrowRenderEventArgs e) { OnRenderArrow(e); @@ -534,7 +534,7 @@ public void DrawItemImage(ToolStripItemImageRenderEventArgs e) { } } - /// + /// /// /// Draw image /// @@ -590,7 +590,7 @@ public void DrawSplitButton(ToolStripItemRenderEventArgs e) { } - /// + /// /// /// Draw the background color /// @@ -681,7 +681,7 @@ protected static void ScaleArrowOffsetsIfNeeded() { } - /// + /// protected virtual void OnRenderArrow(ToolStripArrowRenderEventArgs e){ if (RendererOverride != null) { @@ -740,7 +740,7 @@ protected virtual void OnRenderArrow(ToolStripArrowRenderEventArgs e){ /// /// - /// Draw the winbar background. ToolStrip users should override this if they want to draw differently. + /// Draw the ToolStrip background. ToolStrip users should override this if they want to draw differently. /// protected virtual void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { if (RendererOverride != null) { @@ -866,7 +866,7 @@ protected virtual void OnRenderItemImage(ToolStripItemImageRenderEventArgs e) { } - /// + /// protected virtual void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) { if (RendererOverride != null) { RendererOverride.OnRenderItemCheck(e); @@ -977,7 +977,7 @@ protected virtual void OnRenderToolStripContentPanelBackground(ToolStripContentP } } - /// + /// protected virtual void OnRenderToolStripStatusLabelBackground(ToolStripItemRenderEventArgs e) { if (RendererOverride != null) { RendererOverride.OnRenderToolStripStatusLabelBackground(e); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripScrollButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripScrollButton.cs index 246b94fec8c..5af12fc5e27 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripScrollButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripScrollButton.cs @@ -13,7 +13,7 @@ namespace System.Windows.Forms { /// /// - /// A non selectable winbar item + /// A non selectable ToolStrip item /// internal class ToolStripScrollButton : ToolStripControlHost { private bool up = true; @@ -60,9 +60,7 @@ protected override Padding DefaultPadding { private static Image DownImage { get { if (downScrollImage == null) { - downScrollImage = new Bitmap(typeof(ToolStripScrollButton), "ScrollButtonDown.bmp"); - downScrollImage.MakeTransparent(Color.White); - + downScrollImage = DpiHelper.GetBitmapFromIcon(typeof(ToolStripScrollButton), "ScrollButtonDown"); } return downScrollImage; } @@ -78,9 +76,7 @@ internal StickyLabel Label { private static Image UpImage { get { if (upScrollImage == null) { - upScrollImage = new Bitmap(typeof(ToolStripScrollButton), "ScrollButtonUp.bmp"); - upScrollImage.MakeTransparent(Color.White); - + upScrollImage = DpiHelper.GetBitmapFromIcon(typeof(ToolStripScrollButton), "ScrollButtonUp"); } return upScrollImage; } @@ -176,7 +172,7 @@ protected override void SetBoundsCore(int x,int y,int width, int height, BoundsS protected override void WndProc(ref Message m) { - if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST) { + if (m.Msg >= Interop.WindowMessages.WM_KEYFIRST && m.Msg <= Interop.WindowMessages.WM_KEYLAST) { // DefWndProc(ref m); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparator.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparator.cs index cd7e8a5cc7f..2434897d6bc 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparator.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparator.cs @@ -13,13 +13,13 @@ namespace System.Windows.Forms { /// /// /// - /// Called when the background of the winbar is being rendered + /// Called when the background of the ToolStrip is being rendered /// /// [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.ContextMenuStrip)] public class ToolStripSeparator : ToolStripItem { - private const int WINBAR_SEPARATORTHICKNESS = 6; - private const int WINBAR_SEPARATORHEIGHT = 23; + private const int ToolStrip_SEPARATORTHICKNESS = 6; + private const int ToolStrip_SEPARATORHEIGHT = 23; [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public ToolStripSeparator() { @@ -88,12 +88,12 @@ public override bool CanSelect { /// protected override Size DefaultSize { get { - return new Size(WINBAR_SEPARATORTHICKNESS, WINBAR_SEPARATORTHICKNESS); + return new Size(ToolStrip_SEPARATORTHICKNESS, ToolStrip_SEPARATORTHICKNESS); } } - /// + /// protected internal override Padding DefaultMargin { get { return Padding.Empty; @@ -410,24 +410,24 @@ public override Size GetPreferredSize(Size constrainingSize) { parent = Owner; } if (parent == null) { - return new Size(WINBAR_SEPARATORTHICKNESS, WINBAR_SEPARATORTHICKNESS); + return new Size(ToolStrip_SEPARATORTHICKNESS, ToolStrip_SEPARATORTHICKNESS); } ToolStripDropDownMenu dropDownMenu = parent as ToolStripDropDownMenu; if (dropDownMenu != null) { - return new Size(parent.Width - (parent.Padding.Horizontal - dropDownMenu.ImageMargin.Width), WINBAR_SEPARATORTHICKNESS); + return new Size(parent.Width - (parent.Padding.Horizontal - dropDownMenu.ImageMargin.Width), ToolStrip_SEPARATORTHICKNESS); } else { if (parent.LayoutStyle != ToolStripLayoutStyle.HorizontalStackWithOverflow || parent.LayoutStyle != ToolStripLayoutStyle.VerticalStackWithOverflow) { // we dont actually know what size to make it, so just keep it a stock size. - constrainingSize.Width = WINBAR_SEPARATORHEIGHT; - constrainingSize.Height = WINBAR_SEPARATORHEIGHT; + constrainingSize.Width = ToolStrip_SEPARATORHEIGHT; + constrainingSize.Height = ToolStrip_SEPARATORHEIGHT; } if (IsVertical) { - return new Size(WINBAR_SEPARATORTHICKNESS, constrainingSize.Height); + return new Size(ToolStrip_SEPARATORTHICKNESS, constrainingSize.Height); } else { - return new Size(constrainingSize.Width, WINBAR_SEPARATORTHICKNESS); + return new Size(constrainingSize.Width, ToolStrip_SEPARATORTHICKNESS); } } @@ -495,7 +495,7 @@ public override AccessibleRole Role { } internal override object GetPropertyValue(int propertyID) { - if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_ControlTypePropertyId) { + if (propertyID == NativeMethods.UIA_ControlTypePropertyId) { return NativeMethods.UIA_SeparatorControlTypeId; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventArgs.cs index 96aec8f80f3..fe78b055b98 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventArgs.cs @@ -7,12 +7,12 @@ namespace System.Windows.Forms { /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public class ToolStripSeparatorRenderEventArgs : ToolStripItemRenderEventArgs { /// - /// This class represents all the information to render the winbar + /// This class represents all the information to render the ToolStrip /// public ToolStripSeparatorRenderEventArgs(Graphics g, ToolStripSeparator separator, bool vertical) : base(g, separator) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventHandler.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventHandler.cs index 2cea2693b1e..7ba0161f3aa 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventHandler.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSeparatorRenderEventHandler.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms { /// - /// Called when the background of a winbar item is being rendered + /// Called when the background of a ToolStrip item is being rendered /// public delegate void ToolStripSeparatorRenderEventHandler(object sender, ToolStripSeparatorRenderEventArgs e); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitButton.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitButton.cs index f029bd6d632..791d4f33083 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitButton.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitButton.cs @@ -254,7 +254,7 @@ public int DropDownButtonWidth { set { if (value < 0) { // throw if less than 0. - throw new ArgumentOutOfRangeException(nameof(DropDownButtonWidth), string.Format(SR.InvalidLowBoundArgumentEx, "DropDownButtonWidth", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(DropDownButtonWidth), value, 0)); } if (dropDownButtonWidth != value) { @@ -393,19 +393,11 @@ private void CalculateLayout() { } protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripSplitButtonUiaProvider(this); - } - else if (AccessibilityImprovements.Level1) { - return new ToolStripSplitButtonExAccessibleObject(this); - } - else { - return new ToolStripSplitButtonAccessibleObject(this); - } - } + return new ToolStripSplitButtonUiaProvider(this); + } protected override ToolStripDropDown CreateDefaultDropDown() { - // AutoGenerate a Winbar DropDown - set the property so we hook events + // AutoGenerate a ToolStrip DropDown - set the property so we hook events return new ToolStripDropDownMenu(this, /*isAutoGenerated=*/true); } @@ -645,7 +637,7 @@ internal virtual bool ShouldSerializeDropDownButtonWidth() { /// This class represents the item to the left of the dropdown [ A |v] (e.g the "A") /// It exists so that we can use our existing methods for text and image layout /// and have a place to stick certain state information like pushed and selected - /// Note since this is NOT an actual item hosted on the Winbar - it wont get things + /// Note since this is NOT an actual item hosted on the ToolStrip - it wont get things /// like MouseOver, wont be laid out by the ToolStrip, etc etc. This is purely internal /// convenience. /// @@ -859,7 +851,7 @@ private int DropDownItemsCount { // Do not expose child items when the drop-down is collapsed to prevent Narrator from announcing // invisible menu items when Narrator is in item's mode (CAPSLOCK + Arrow Left/Right) or // in scan mode (CAPSLOCK + Space) - if (AccessibilityImprovements.Level3 && ExpandCollapseState == UnsafeNativeMethods.ExpandCollapseState.Collapsed) { + if (ExpandCollapseState == UnsafeNativeMethods.ExpandCollapseState.Collapsed) { return 0; } @@ -885,9 +877,7 @@ internal override object GetPropertyValue(int propertyID) { return _accessibleObject.GetPropertyValue(propertyID); } - internal override bool IsIAccessibleExSupported() { - return true; - } + internal override bool IsIAccessibleExSupported() => true; internal override bool IsPatternSupported(int patternId) { return _accessibleObject.IsPatternSupported(patternId); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitStackLayout.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitStackLayout.cs index 914b29bedec..347eb3fb343 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitStackLayout.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSplitStackLayout.cs @@ -81,7 +81,7 @@ private bool OverflowRequired { } } - // the current winbar we're operating over. + // the current ToolStrip we're operating over. public ToolStrip ToolStrip { get { return toolStrip; @@ -89,7 +89,7 @@ public ToolStrip ToolStrip { } // - // This method will mark whether items should be placed in the overflow or on the main winbar. + // This method will mark whether items should be placed in the overflow or on the main ToolStrip. // private void CalculatePlacementsHorizontal() { ResetItemPlacements(); @@ -139,7 +139,7 @@ private void CalculatePlacementsHorizontal() { } // - // This method will mark whether items should be placed in the overflow or on the main winbar. + // This method will mark whether items should be placed in the overflow or on the main ToolStrip. // private void CalculatePlacementsVertical() { ResetItemPlacements(); @@ -577,7 +577,7 @@ private void ResetItemPlacements() { // // This method is called when we are walking through the item collection and we have realized that we - // need to free up "X" amount of space to be able to fit an item onto the winbar. + // need to free up "X" amount of space to be able to fit an item onto the ToolStrip. private int SendNextItemToOverflow(int spaceNeeded, bool horizontal) { #if DEBUG if (DebugLayoutTraceSwitch.TraceVerbose) { Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "SendNextItemToOverflow attempting to free {0}", spaceNeeded)); } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripStatusLabel.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripStatusLabel.cs index 0f4d04213db..69e0475af94 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripStatusLabel.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripStatusLabel.cs @@ -9,7 +9,6 @@ namespace System.Windows.Forms { using System.Drawing.Design; using System.Diagnostics; using System.Windows.Forms.ButtonInternal; - using System.Security.Permissions; using System.Security; using System.Windows.Forms.Layout; using System.Windows.Forms.Design; @@ -19,7 +18,7 @@ namespace System.Windows.Forms { /// /// - /// A non selectable winbar item + /// A non selectable ToolStrip item /// [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.StatusStrip)] public class ToolStripStatusLabel : ToolStripLabel, IAutomationLiveRegion { @@ -35,7 +34,7 @@ public class ToolStripStatusLabel : ToolStripLabel, IAutomationLiveRegion { /// /// - /// A non selectable winbar item + /// A non selectable ToolStrip item /// public ToolStripStatusLabel() { Initialize(); @@ -66,11 +65,7 @@ public ToolStripStatusLabel(string text, Image image, EventHandler onClick, stri /// AccessibleObject for this ToolStripStatusLabel instance. /// protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripStatusLabelAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripStatusLabelAccessibleObject(this); } /// @@ -206,7 +201,7 @@ public AutomationLiveSetting LiveSetting { protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); - if (AccessibilityImprovements.Level3 && LiveSetting != AutomationLiveSetting.Off) { + if (LiveSetting != AutomationLiveSetting.Off) { AccessibilityObject.RaiseLiveRegionChanged(); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSystemRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSystemRenderer.cs index fd02dc0411b..bbcbba5a5df 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSystemRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripSystemRenderer.cs @@ -88,25 +88,25 @@ private static bool GetPen(Color color, ref Pen pen) { } } /// - /// translates the winbar item state into a toolbar state, which is something the renderer understands + /// translates the ToolStrip item state into a toolbar state, which is something the renderer understands /// private static int GetItemState(ToolStripItem item) { return (int)GetToolBarState(item); } /// - /// translates the winbar item state into a toolbar state, which is something the renderer understands + /// translates the ToolStrip item state into a toolbar state, which is something the renderer understands /// private static int GetSplitButtonDropDownItemState(ToolStripSplitButton item) { return (int)GetSplitButtonToolBarState(item, true); } /// - /// translates the winbar item state into a toolbar state, which is something the renderer understands + /// translates the ToolStrip item state into a toolbar state, which is something the renderer understands /// private static int GetSplitButtonItemState(ToolStripSplitButton item) { return (int)GetSplitButtonToolBarState(item, false); } /// - /// translates the winbar item state into a toolbar state, which is something the renderer understands + /// translates the ToolStrip item state into a toolbar state, which is something the renderer understands /// private static ToolBarState GetSplitButtonToolBarState(ToolStripSplitButton button, bool dropDownButton) { ToolBarState state = ToolBarState.Normal; @@ -136,7 +136,7 @@ private static ToolBarState GetSplitButtonToolBarState(ToolStripSplitButton butt } /// - /// translates the winbar item state into a toolbar state, which is something the renderer understands + /// translates the ToolStrip item state into a toolbar state, which is something the renderer understands /// private static ToolBarState GetToolBarState(ToolStripItem item) { ToolBarState state = ToolBarState.Normal; @@ -145,7 +145,7 @@ private static ToolBarState GetToolBarState(ToolStripItem item) { state = ToolBarState.Disabled; } if (item is ToolStripButton && ((ToolStripButton)item).Checked) { - if (((ToolStripButton)item).Selected && AccessibilityImprovements.Level1) { + if (((ToolStripButton)item).Selected) { state = ToolBarState.Hot; // we'd prefer HotChecked here, but Color Theme uses the same color as Checked } else { @@ -166,7 +166,7 @@ private static ToolBarState GetToolBarState(ToolStripItem item) { /// /// - /// Draw the winbar background. ToolStrip users should override this if they want to draw differently. + /// Draw the ToolStrip background. ToolStrip users should override this if they want to draw differently. /// protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { ToolStrip toolStrip = e.ToolStrip; @@ -398,18 +398,16 @@ protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs // Legacy behavior is to always paint the menu item background. // The correct behavior is to only paint the background if the menu item is // enabled. - if (!AccessibilityImprovements.Level1 || item.Enabled) { + if (item.Enabled) { g.FillRectangle(SystemBrushes.Highlight, fillRect); } - if (AccessibilityImprovements.Level1) { - Color borderColor = ToolStripManager.VisualStylesEnabled ? - SystemColors.Highlight : ProfessionalColors.MenuItemBorder; + Color borderColor = ToolStripManager.VisualStylesEnabled ? + SystemColors.Highlight : ProfessionalColors.MenuItemBorder; - // draw selection border - always drawn regardless of Enabled. - using (Pen p = new Pen(borderColor)) { - g.DrawRectangle(p, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); - } + // draw selection border - always drawn regardless of Enabled. + using (Pen p = new Pen(borderColor)) { + g.DrawRectangle(p, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); } } else { @@ -436,7 +434,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { } - /// + /// protected override void OnRenderToolStripStatusLabelBackground(ToolStripItemRenderEventArgs e) { RenderLabelInternal(e); ToolStripStatusLabel item = e.Item as ToolStripStatusLabel; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripTextBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripTextBox.cs index 29cac21eb3a..7ec153e4696 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripTextBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolStripTextBox.cs @@ -13,7 +13,6 @@ namespace System.Windows.Forms { using System.Runtime.InteropServices; using System.Windows.Forms.Design; using System.Security; - using System.Security.Permissions; using Microsoft.Win32; /// @@ -114,11 +113,7 @@ public TextBox TextBox { [EditorBrowsable(EditorBrowsableState.Advanced)] protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripTextBoxAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripTextBoxAccessibleObject(this); } [System.Runtime.InteropServices.ComVisible(true)] @@ -186,33 +181,33 @@ private void HandleReadOnlyChanged(object sender, EventArgs e) { private void HandleTextBoxTextAlignChanged(object sender, EventArgs e) { RaiseEvent(EventTextBoxTextAlignChanged, e); } - /// + /// protected virtual void OnAcceptsTabChanged(EventArgs e) { RaiseEvent(EventAcceptsTabChanged, e); } - /// + /// protected virtual void OnBorderStyleChanged(EventArgs e) { RaiseEvent(EventBorderStyleChanged, e); } - /// + /// protected virtual void OnHideSelectionChanged(EventArgs e) { RaiseEvent(EventHideSelectionChanged, e); } - /// + /// protected virtual void OnModifiedChanged(EventArgs e) { RaiseEvent(EventModifiedChanged, e); } - /// + /// protected virtual void OnMultilineChanged(EventArgs e) { RaiseEvent(EventMultilineChanged, e); } - /// + /// protected virtual void OnReadOnlyChanged(EventArgs e) { RaiseEvent(EventReadOnlyChanged, e); } - /// + /// protected override void OnSubscribeControlEvents(Control control) { TextBox textBox = control as TextBox; if (textBox != null) { @@ -231,7 +226,7 @@ protected override void OnSubscribeControlEvents(Control control) { base.OnSubscribeControlEvents(control); } - /// + /// protected override void OnUnsubscribeControlEvents(Control control) { TextBox textBox = control as TextBox; @@ -257,7 +252,7 @@ internal override bool ShouldSerializeFont() { #region WrappedProperties - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(false), @@ -268,7 +263,7 @@ public bool AcceptsTab { set { TextBox.AcceptsTab = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(false), @@ -279,7 +274,7 @@ public bool AcceptsReturn { set { TextBox.AcceptsReturn = value; } } - /// + /// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Localizable(true), @@ -292,7 +287,7 @@ public System.Windows.Forms.AutoCompleteStringCollection AutoCompleteCustomSourc set { TextBox.AutoCompleteCustomSource = value; } } - /// + /// [ DefaultValue(AutoCompleteMode.None), SRDescription(nameof(SR.TextBoxAutoCompleteModeDescr)), @@ -303,7 +298,7 @@ public AutoCompleteMode AutoCompleteMode { set { TextBox.AutoCompleteMode = value; } } - /// + /// [ DefaultValue(AutoCompleteSource.None), SRDescription(nameof(SR.TextBoxAutoCompleteSourceDescr)), @@ -314,7 +309,7 @@ public AutoCompleteSource AutoCompleteSource { set { TextBox.AutoCompleteSource = value; } } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), DefaultValue(BorderStyle.Fixed3D), @@ -326,7 +321,7 @@ public BorderStyle BorderStyle { set { TextBox.BorderStyle = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), Browsable(false), @@ -337,7 +332,7 @@ public bool CanUndo { get { return TextBox.CanUndo; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(CharacterCasing.Normal), @@ -348,7 +343,7 @@ public CharacterCasing CharacterCasing { set { TextBox.CharacterCasing = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(true), @@ -359,7 +354,7 @@ public bool HideSelection { set { TextBox.HideSelection = value; } } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -372,7 +367,7 @@ public string[] Lines { set { TextBox.Lines = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(32767), @@ -384,7 +379,7 @@ public int MaxLength { set { TextBox.MaxLength = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), Browsable(false), @@ -396,7 +391,7 @@ public bool Modified { set { TextBox.Modified = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(false), @@ -410,7 +405,7 @@ public bool Multiline { set { TextBox.Multiline = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(false), @@ -420,7 +415,7 @@ public bool ReadOnly { get { return TextBox.ReadOnly; } set { TextBox.ReadOnly = value; } } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), Browsable(false), @@ -432,7 +427,7 @@ public string SelectedText { set { TextBox.SelectedText = value; } } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), Browsable(false), @@ -443,7 +438,7 @@ public int SelectionLength { get { return TextBox.SelectionLength; } set { TextBox.SelectionLength = value; } } - /// + /// [ SRCategory(nameof(SR.CatAppearance)), Browsable(false), @@ -454,7 +449,7 @@ public int SelectionStart { get { return TextBox.SelectionStart; } set { TextBox.SelectionStart = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), DefaultValue(true), @@ -464,7 +459,7 @@ public bool ShortcutsEnabled { get { return TextBox.ShortcutsEnabled; } set { TextBox.ShortcutsEnabled = value; } } - /// + /// [Browsable(false)] public int TextLength { get { return TextBox.TextLength; } @@ -481,7 +476,7 @@ public HorizontalAlignment TextBoxTextAlign { set { TextBox.TextAlign = value; } } - /// + /// [ SRCategory(nameof(SR.CatBehavior)), Localizable(true), @@ -500,7 +495,7 @@ public bool WordWrap { #region WrappedEvents - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.TextBoxBaseOnAcceptsTabChangedDescr))] public event EventHandler AcceptsTabChanged { add { @@ -512,7 +507,7 @@ public event EventHandler AcceptsTabChanged { } - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.TextBoxBaseOnBorderStyleChangedDescr))] public event EventHandler BorderStyleChanged { add { @@ -523,7 +518,7 @@ public event EventHandler BorderStyleChanged { } } - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.TextBoxBaseOnHideSelectionChangedDescr))] public event EventHandler HideSelectionChanged { add { @@ -534,7 +529,7 @@ public event EventHandler HideSelectionChanged { } } - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.TextBoxBaseOnModifiedChangedDescr))] public event EventHandler ModifiedChanged { add { @@ -545,7 +540,7 @@ public event EventHandler ModifiedChanged { } } - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.TextBoxBaseOnMultilineChangedDescr)),Browsable(false),EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler MultilineChanged { add { @@ -556,7 +551,7 @@ public event EventHandler MultilineChanged { } } - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.TextBoxBaseOnReadOnlyChangedDescr))] public event EventHandler ReadOnlyChanged { add { @@ -568,7 +563,7 @@ public event EventHandler ReadOnlyChanged { } - /// + /// [SRCategory(nameof(SR.CatPropertyChanged)), SRDescription(nameof(SR.ToolStripTextBoxTextBoxTextAlignChangedDescr))] public event EventHandler TextBoxTextAlignChanged { add { @@ -581,39 +576,39 @@ public event EventHandler TextBoxTextAlignChanged { #endregion WrappedEvents #region WrappedMethods - /// + /// public void AppendText(string text) { TextBox.AppendText(text); } - /// + /// public void Clear(){ TextBox.Clear(); } - /// + /// public void ClearUndo() {TextBox.ClearUndo(); } - /// + /// public void Copy() {TextBox.Copy(); } - /// + /// public void Cut() {TextBox.Copy(); } - /// + /// public void DeselectAll() { TextBox.DeselectAll(); } - /// + /// public char GetCharFromPosition(System.Drawing.Point pt) { return TextBox.GetCharFromPosition(pt); } - /// + /// public int GetCharIndexFromPosition(System.Drawing.Point pt) { return TextBox.GetCharIndexFromPosition(pt); } - /// + /// public int GetFirstCharIndexFromLine(int lineNumber) { return TextBox.GetFirstCharIndexFromLine(lineNumber); } - /// + /// public int GetFirstCharIndexOfCurrentLine() { return TextBox.GetFirstCharIndexOfCurrentLine(); } - /// + /// public int GetLineFromCharIndex(int index) { return TextBox.GetLineFromCharIndex(index); } - /// + /// public System.Drawing.Point GetPositionFromCharIndex(int index) { return TextBox.GetPositionFromCharIndex(index); } - /// + /// public void Paste() { TextBox.Paste(); } - /// + /// public void ScrollToCaret() { TextBox.ScrollToCaret(); } - /// + /// public void Select(int start, int length) { TextBox.Select(start, length); } - /// + /// public void SelectAll() { TextBox.SelectAll(); } - /// + /// public void Undo() { TextBox.Undo(); } #endregion private class ToolStripTextBoxControl : TextBox { @@ -696,7 +691,7 @@ public override Font Font { get { return base.Font; } set { base.Font = value; - isFontSet = ShouldSerializeFont(); + isFontSet = ShouldSerializeFont(); } } @@ -705,11 +700,7 @@ public ToolStripTextBox Owner { set { ownerItem = value; } } - internal override bool SupportsUiaProviders { - get { - return AccessibilityImprovements.Level3; - } - } + internal override bool SupportsUiaProviders => true; private void InvalidateNonClient() { if (!IsPopupTextBox) { @@ -821,11 +812,7 @@ protected override void OnVisibleChanged(EventArgs e) { } protected override AccessibleObject CreateAccessibilityInstance() { - if (AccessibilityImprovements.Level3) { - return new ToolStripTextBoxControlAccessibleObject(this); - } - - return base.CreateAccessibilityInstance(); + return new ToolStripTextBoxControlAccessibleObject(this); } protected override void Dispose(bool disposing) { @@ -888,7 +875,7 @@ private void WmNCPaint(ref Message m) { } protected override void WndProc(ref Message m) { - if (m.Msg == NativeMethods.WM_NCPAINT) { + if (m.Msg == Interop.WindowMessages.WM_NCPAINT) { WmNCPaint(ref m); return; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ToolTip.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ToolTip.cs index cfaba468fea..5519337e394 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/ToolTip.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/ToolTip.cs @@ -165,7 +165,7 @@ public int AutomaticDelay { set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(AutomaticDelay), string.Format(SR.InvalidLowBoundArgumentEx, "AutomaticDelay", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(AutomaticDelay), value, 0)); } SetDelayTime(NativeMethods.TTDT_AUTOMATIC, value); } @@ -193,7 +193,7 @@ public int AutoPopDelay { set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(AutoPopDelay), string.Format(SR.InvalidLowBoundArgumentEx, "AutoPopDelay", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(AutoPopDelay), value, 0)); } SetDelayTime(NativeMethods.TTDT_AUTOPOP, value); } @@ -363,7 +363,7 @@ public int InitialDelay { set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(InitialDelay), string.Format(SR.InvalidLowBoundArgumentEx, "InitialDelay", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(InitialDelay), value, 0)); } SetDelayTime(NativeMethods.TTDT_INITIAL, value); } @@ -409,7 +409,7 @@ public int ReshowDelay { } set { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(ReshowDelay), string.Format(SR.InvalidLowBoundArgumentEx, "ReshowDelay", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ReshowDelay), value, 0)); } SetDelayTime(NativeMethods.TTDT_RESHOW, value); } @@ -716,9 +716,7 @@ private void HandleCreated(object sender, EventArgs eventargs) { this.CheckNativeToolTip(control); this.CheckCompositeControls(control); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.Hook(control, this); - } + KeyboardToolTipStateMachine.Instance.Hook(control, this); } private void CheckNativeToolTip(Control associatedControl) { @@ -776,9 +774,7 @@ private void HandleDestroyed(object sender, EventArgs eventargs) { Control control = (Control)sender; this.DestroyRegion(control); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.Unhook(control, this); - } + KeyboardToolTipStateMachine.Instance.Unhook(control, this); } /// @@ -1116,7 +1112,7 @@ private NativeMethods.TOOLINFO_TOOLTIP GetMinToolInfoForTool(IWin32Window tool) private NativeMethods.TOOLINFO_TOOLTIP GetMinToolInfoForHandle(IntPtr handle) { NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); ti.hwnd = handle; ti.uFlags |= NativeMethods.TTF_IDISHWND; ti.uId = handle; @@ -1134,7 +1130,7 @@ private NativeMethods.TOOLINFO_TOOLTIP GetMinToolInfoForHandle(IntPtr handle) { private NativeMethods.TOOLINFO_TOOLTIP GetTOOLINFO(Control ctl, string caption, out bool allocatedString) { allocatedString = false; NativeMethods.TOOLINFO_TOOLTIP ti = GetMinTOOLINFO(ctl); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); ti.uFlags |= NativeMethods.TTF_TRANSPARENT | NativeMethods.TTF_SUBCLASS; // RightToLeft reading order @@ -1173,7 +1169,7 @@ private NativeMethods.TOOLINFO_TOOLTIP GetTOOLINFO(Control ctl, string caption, private NativeMethods.TOOLINFO_TOOLTIP GetWinTOOLINFO(IntPtr hWnd) { NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); ti.hwnd = hWnd; ti.uFlags |= NativeMethods.TTF_IDISHWND | NativeMethods.TTF_TRANSPARENT | NativeMethods.TTF_SUBCLASS; @@ -1340,9 +1336,7 @@ public void RemoveAll() { regions[i].HandleCreated -= new EventHandler(this.HandleCreated); regions[i].HandleDestroyed -= new EventHandler(this.HandleDestroyed); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.Unhook(regions[i], this); - } + KeyboardToolTipStateMachine.Instance.Unhook(regions[i], this); } created.Clear(); @@ -1351,9 +1345,7 @@ public void RemoveAll() { ClearTopLevelControlEvents(); this.topLevelControl = null; - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.ResetStateMachine(this); - } + KeyboardToolTipStateMachine.Instance.ResetStateMachine(this); } /// @@ -1606,7 +1598,7 @@ public void Show(string text, IWin32Window window) { /// public void Show(string text, IWin32Window window, int duration) { if (duration < 0) { - throw new ArgumentOutOfRangeException(nameof(duration), string.Format(SR.InvalidLowBoundArgumentEx, "duration", (duration).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(duration), duration, string.Format(SR.InvalidLowBoundArgumentEx, nameof(duration), duration, 0)); } if (IsWindowActive(window)) { @@ -1648,7 +1640,7 @@ public void Show(string text, IWin32Window window, Point point, int duration) { throw new ArgumentNullException(nameof(window)); } if (duration < 0) { - throw new ArgumentOutOfRangeException(nameof(duration), string.Format(SR.InvalidLowBoundArgumentEx, "duration", (duration).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(duration), duration, string.Format(SR.InvalidLowBoundArgumentEx, nameof(duration), duration, 0)); } if (IsWindowActive(window)) { @@ -1697,7 +1689,7 @@ public void Show(string text, IWin32Window window, int x, int y, int duration) { throw new ArgumentNullException(nameof(window)); } if (duration < 0) { - throw new ArgumentOutOfRangeException(nameof(duration), string.Format(SR.InvalidLowBoundArgumentEx, "duration", (duration).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(duration), duration, string.Format(SR.InvalidLowBoundArgumentEx, nameof(duration), duration, 0)); } if (IsWindowActive(window)) { @@ -1716,7 +1708,7 @@ internal void ShowKeyboardToolTip(string text, IKeyboardToolTip tool, int durati throw new ArgumentNullException(nameof(tool)); } if (duration < 0) { - throw new ArgumentOutOfRangeException(nameof(duration), string.Format(SR.InvalidLowBoundArgumentEx, nameof(duration), (duration).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(duration), string.Format(SR.InvalidLowBoundArgumentEx, nameof(duration), (duration).ToString(CultureInfo.CurrentCulture), 0)); } Rectangle toolRectangle = tool.GetNativeScreenRectangle(); @@ -1956,9 +1948,7 @@ public void Hide(IWin32Window win) { private void BaseFormDeactivate(object sender, System.EventArgs e){ HideAllToolTips(); - if (!AccessibilityImprovements.UseLegacyToolTipDisplay) { - KeyboardToolTipStateMachine.Instance.NotifyAboutFormDeactivation(this); - } + KeyboardToolTipStateMachine.Instance.NotifyAboutFormDeactivation(this); } private void HideAllToolTips() { @@ -1976,7 +1966,7 @@ private void SetTool(IWin32Window win, string text, TipInfo.Type type, Point pos bool allocatedString = false; NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); try { - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); ti.hwnd = tool.Handle; ti.uId = tool.Handle; int ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETTOOLINFO, 0, ti); @@ -2149,7 +2139,7 @@ private void WmMove() { NativeMethods.RECT r = new NativeMethods.RECT(); UnsafeNativeMethods.GetWindowRect(new HandleRef(this, Handle), ref r); NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); int ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETCURRENTTOOL, 0, ti); if (ret != 0) { @@ -2193,7 +2183,7 @@ private void WmMove() { private void WmMouseActivate(ref Message msg) { NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); int ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETCURRENTTOOL, 0, ti); if (ret != 0) { @@ -2249,7 +2239,7 @@ private void WmShow() { UnsafeNativeMethods.GetWindowRect(new HandleRef(this, Handle), ref r); NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); int ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETCURRENTTOOL, 0, ti); if (ret != 0) { @@ -2359,7 +2349,7 @@ private unsafe void WmWindowPosChanging(ref Message m) { NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); int ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETCURRENTTOOL, 0, ti); if (ret != 0) { @@ -2446,7 +2436,7 @@ private unsafe void WmWindowPosChanging(ref Message m) { private void WmPop() { NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); int ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETCURRENTTOOL, 0, ti); if (ret != 0) { @@ -2508,7 +2498,7 @@ private void WndProc(ref Message msg) { switch (msg.Msg) { - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR) msg.GetLParam(typeof(NativeMethods.NMHDR)); if (nmhdr.code == NativeMethods.TTN_SHOW && !trackPosition) { WmShow(); @@ -2521,22 +2511,22 @@ private void WndProc(ref Message msg) { } break; - case NativeMethods.WM_WINDOWPOSCHANGING: + case Interop.WindowMessages.WM_WINDOWPOSCHANGING: WmWindowPosChanging(ref msg); break; - case NativeMethods.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: if (!WmWindowPosChanged() && window != null) { window.DefWndProc(ref msg); } break; - case NativeMethods.WM_MOUSEACTIVATE: + case Interop.WindowMessages.WM_MOUSEACTIVATE: WmMouseActivate(ref msg); break; - case NativeMethods.WM_MOVE: + case Interop.WindowMessages.WM_MOVE: WmMove(); break; @@ -2544,10 +2534,10 @@ private void WndProc(ref Message msg) { WmWindowFromPoint(ref msg); break; - case NativeMethods.WM_PRINTCLIENT: - goto case NativeMethods.WM_PAINT; + case Interop.WindowMessages.WM_PRINTCLIENT: + goto case Interop.WindowMessages.WM_PAINT; - case NativeMethods.WM_PAINT: + case Interop.WindowMessages.WM_PAINT: if (ownerDraw && !isBalloon && !trackPosition) { NativeMethods.PAINTSTRUCT ps = new NativeMethods.PAINTSTRUCT(); @@ -2561,7 +2551,7 @@ private void WndProc(ref Message msg) { return; } NativeMethods.TOOLINFO_TOOLTIP ti = new NativeMethods.TOOLINFO_TOOLTIP(); - ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_TOOLTIP)); + ti.cbSize = Marshal.SizeOf(); int ret = unchecked( (int) (long)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_GETCURRENTTOOL, 0, ti)); if (ret != 0) { IWin32Window win = (IWin32Window)owners[ti.hwnd]; @@ -2571,7 +2561,7 @@ private void WndProc(ref Message msg) { } Font font; try { - font = Font.FromHfont(UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.WM_GETFONT, 0, 0)); + font = Font.FromHfont(UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_GETFONT, 0, 0)); } catch (ArgumentException) { // If the current default tooltip font is a non-TrueType font, then diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TrackBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TrackBar.cs index 1f414bed8b0..82254c0753d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TrackBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TrackBar.cs @@ -661,7 +661,10 @@ public int Value { set { if (this.value != value) { if (!initializing && ((value < minimum) || (value > maximum))) - throw new ArgumentOutOfRangeException(nameof(Value), string.Format(SR.InvalidBoundArgument, "Value", (value).ToString(CultureInfo.CurrentCulture), "'Minimum'", "'Maximum'")); + { + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidBoundArgument, nameof(Value), value, $"'{nameof(Minimum)}'", $"'${nameof(Maximum)}'")); + } + this.value = value; SetTrackBarPosition(); OnValueChanged(EventArgs.Empty); @@ -1120,7 +1123,7 @@ private void SetTrackBarPosition() { public override string ToString() { string s = base.ToString(); - return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + Value.ToString(CultureInfo.CurrentCulture); + return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + value; } /// @@ -1132,8 +1135,8 @@ public override string ToString() { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_REFLECT+NativeMethods.WM_HSCROLL: - case NativeMethods.WM_REFLECT+NativeMethods.WM_VSCROLL: + case Interop.WindowMessages.WM_REFLECT+Interop.WindowMessages.WM_HSCROLL: + case Interop.WindowMessages.WM_REFLECT+Interop.WindowMessages.WM_VSCROLL: switch (NativeMethods.Util.LOWORD(m.WParam)) { case NativeMethods.TB_LINEUP: case NativeMethods.TB_LINEDOWN: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TreeNode.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TreeNode.cs index fa7bf52d2dd..0a7212486d6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TreeNode.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TreeNode.cs @@ -959,7 +959,7 @@ public int StateImageIndex { } set { if (value < -1 || value > ALLOWEDIMAGES) { - throw new ArgumentOutOfRangeException(nameof(StateImageIndex), string.Format(SR.InvalidArgument, "StateImageIndex", (value).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidArgument, nameof(StateImageIndex), value)); } StateImageIndexer.Index = value; if (treeView != null && !treeView.CheckBoxes) @@ -1398,7 +1398,7 @@ protected virtual void Deserialize(SerializationInfo serializationInfo, Streamin case "IsChecked": CheckedStateInternal = serializationInfo.GetBoolean(entry.Name); break; - case "ImageIndex": + case nameof(ImageIndex): imageIndex = serializationInfo.GetInt32(entry.Name); break; case "SelectedImageIndex": @@ -1731,7 +1731,7 @@ internal void Realize(bool insertFirst) { // and this is the FIRST NODE to get added.. // This is Comctl quirk where it just doesn't draw // the first node after a Clear( ) if Scrollable == false. - UnsafeNativeMethods.SendMessage(new HandleRef(tv, tv.Handle), NativeMethods.WM_SETREDRAW, 1, 0); + UnsafeNativeMethods.SendMessage(new HandleRef(tv, tv.Handle), Interop.WindowMessages.WM_SETREDRAW, 1, 0); nodesCleared = false; } @@ -1849,7 +1849,7 @@ protected virtual void Serialize(SerializationInfo si, StreamingContext context) si.AddValue("ToolTipText", toolTipText); si.AddValue("Name", Name); si.AddValue("IsChecked", treeNodeState[TREENODESTATE_isChecked]); - si.AddValue("ImageIndex", ImageIndexer.Index); + si.AddValue(nameof(ImageIndex), ImageIndexer.Index); si.AddValue("ImageKey", ImageIndexer.Key); si.AddValue("SelectedImageIndex", SelectedImageIndexer.Index); si.AddValue("SelectedImageKey", SelectedImageIndexer.Key); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TreeNodeCollection.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TreeNodeCollection.cs index c740d0c4f05..b787896a2d9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TreeNodeCollection.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TreeNodeCollection.cs @@ -59,7 +59,7 @@ public virtual TreeNode this[int index] { } set { if (index < 0 || index >= owner.childCount) - throw new ArgumentOutOfRangeException(nameof(index), string.Format(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(index), index, string.Format(SR.InvalidArgument, nameof(index), index)); value.parent = owner; value.index = index; owner.children[index] = value; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TreeView.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TreeView.cs index 91deb7c60e0..0644575f0c9 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TreeView.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TreeView.cs @@ -562,7 +562,7 @@ public int ImageIndex { } if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "ImageIndex", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(ImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, nameof(ImageIndex), value, 0)); } if (ImageIndexer.Index != value) { @@ -749,10 +749,10 @@ public int Indent { set { if (indent != value) { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(Indent), string.Format(SR.InvalidLowBoundArgumentEx, "Indent", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(Indent), value, 0)); } if (value > MaxIndent) { - throw new ArgumentOutOfRangeException(nameof(Indent), string.Format(SR.InvalidHighBoundArgumentEx, "Indent", (value).ToString(CultureInfo.CurrentCulture), (MaxIndent).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgumentEx, nameof(Indent), value, MaxIndent)); } indent = value; if (IsHandleCreated) { @@ -791,11 +791,12 @@ public int ItemHeight { set { if (itemHeight != value) { if (value < 1) { - throw new ArgumentOutOfRangeException(nameof(ItemHeight), string.Format(SR.InvalidLowBoundArgumentEx, "ItemHeight", (value).ToString(CultureInfo.CurrentCulture), (1).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(ItemHeight), value, 1)); } if (value >= short.MaxValue) { - throw new ArgumentOutOfRangeException(nameof(ItemHeight), string.Format(SR.InvalidHighBoundArgument, "ItemHeight", (value).ToString(CultureInfo.CurrentCulture), short.MaxValue.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidHighBoundArgument, nameof(ItemHeight), value, short.MaxValue)); } + itemHeight = value; if (IsHandleCreated) { if (itemHeight % 2 != 0) { @@ -1043,7 +1044,7 @@ public int SelectedImageIndex { } if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(SelectedImageIndex), string.Format(SR.InvalidLowBoundArgumentEx, "SelectedImageIndex", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(SR.InvalidLowBoundArgumentEx, nameof(SelectedImageIndex), value, 0)); } if (SelectedImageIndexer.Index != value) { SelectedImageIndexer.Index = value; @@ -1677,11 +1678,11 @@ internal void ForceScrollbarUpdate(bool delayed) { if (!IsUpdating()) { if (IsHandleCreated) { - SendMessage(NativeMethods.WM_SETREDRAW, 0, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, 0, 0); if (delayed) - UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), NativeMethods.WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); + UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), Interop.WindowMessages.WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); else - SendMessage(NativeMethods.WM_SETREDRAW, 1, 0); + SendMessage(Interop.WindowMessages.WM_SETREDRAW, 1, 0); } } } @@ -2651,7 +2652,7 @@ private void CustomDraw(ref Message m) { Rectangle bounds = node.RowBounds; NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); - si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); + si.cbSize = Marshal.SizeOf(); si.fMask = NativeMethods.SIF_POS; if (UnsafeNativeMethods.GetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_HORZ,si) != false) { @@ -2959,7 +2960,7 @@ private unsafe void WmNotify(ref Message m) { } else { treeViewState[TREEVIEWSTATE_showTreeViewContextMenu] = true; - SendMessage(NativeMethods.WM_CONTEXTMENU, Handle, SafeNativeMethods.GetMessagePos()); + SendMessage(Interop.WindowMessages.WM_CONTEXTMENU, Handle, SafeNativeMethods.GetMessagePos()); } m.Result = (IntPtr)1; @@ -3016,7 +3017,7 @@ private void ShowContextMenu(TreeNode treeNode) { null); // Force task switch (see above) - UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero); + UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), Interop.WindowMessages.WM_NULL, IntPtr.Zero, IntPtr.Zero); } // Need to send TVM_SELECTITEM to highlight the node while the contextMenuStrip is being shown. else if (menu != null) @@ -3056,10 +3057,10 @@ private void WmPrint(ref Message m) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_WINDOWPOSCHANGING: - case NativeMethods.WM_NCCALCSIZE: - case NativeMethods.WM_WINDOWPOSCHANGED: - case NativeMethods.WM_SIZE: + case Interop.WindowMessages.WM_WINDOWPOSCHANGING: + case Interop.WindowMessages.WM_NCCALCSIZE: + case Interop.WindowMessages.WM_WINDOWPOSCHANGED: + case Interop.WindowMessages.WM_SIZE: // While we are changing size of treeView to avoid the scrollbar; dont respond to the window-sizing messages. if (treeViewState[TREEVIEWSTATE_stopResizeWindowMsgs]) { @@ -3071,7 +3072,7 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); } break; - case NativeMethods.WM_HSCROLL: + case Interop.WindowMessages.WM_HSCROLL: base.WndProc(ref m); if (DrawMode == TreeViewDrawMode.OwnerDrawAll) { @@ -3079,7 +3080,7 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_PRINT: + case Interop.WindowMessages.WM_PRINT: WmPrint(ref m); break; case NativeMethods.TVM_SETITEM: @@ -3099,7 +3100,7 @@ protected override void WndProc(ref Message m) { } } break; - case NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_NOTIFY: NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR) m.GetLParam(typeof(NativeMethods.NMHDR)); switch (nmhdr.code) { case NativeMethods.TTN_GETDISPINFO: @@ -3128,10 +3129,10 @@ protected override void WndProc(ref Message m) { break; } break; - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFY: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFY: WmNotify(ref m); break; - case NativeMethods.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Left, 2); //just maintain state and fire double click.. in final mouseUp... treeViewState[TREEVIEWSTATE_doubleclickFired] = true; @@ -3141,7 +3142,7 @@ protected override void WndProc(ref Message m) { // CaptureInternal = true; break; - case NativeMethods.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_LBUTTONDOWN: try { treeViewState[TREEVIEWSTATE_ignoreSelects] = true; @@ -3179,8 +3180,8 @@ protected override void WndProc(ref Message m) { } downButton = MouseButtons.Left; break; - case NativeMethods.WM_LBUTTONUP: - case NativeMethods.WM_RBUTTONUP: + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONUP: NativeMethods.TV_HITTESTINFO tvhi = new NativeMethods.TV_HITTESTINFO(); tvhi.pt_x = NativeMethods.Util.SignedLOWORD(m.LParam); tvhi.pt_y = NativeMethods.Util.SignedHIWORD(m.LParam); @@ -3220,24 +3221,24 @@ protected override void WndProc(ref Message m) { //always clear our hit-tested node we cached on mouse down hNodeMouseDown = IntPtr.Zero; break; - case NativeMethods.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: //fire Up in the Wndproc !! treeViewState[TREEVIEWSTATE_mouseUpFired] = false; WmMouseDown(ref m, MouseButtons.Middle, 2); break; - case NativeMethods.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: //Always Reset the MouseupFired.... treeViewState[TREEVIEWSTATE_mouseUpFired] = false; WmMouseDown(ref m, MouseButtons.Middle, 1); downButton = MouseButtons.Middle; break; - case NativeMethods.WM_MOUSELEAVE: + case Interop.WindowMessages.WM_MOUSELEAVE: // if the mouse leaves and then reenters the TreeView // NodeHovered events should be raised. prevHoveredNode = null; base.WndProc(ref m); break; - case NativeMethods.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: WmMouseDown(ref m, MouseButtons.Right, 2); //just maintain state and fire double click.. in final mouseUp... treeViewState[TREEVIEWSTATE_doubleclickFired] = true; @@ -3247,7 +3248,7 @@ protected override void WndProc(ref Message m) { // CaptureInternal = true; break; - case NativeMethods.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: //Always Reset the MouseupFired.... treeViewState[TREEVIEWSTATE_mouseUpFired] = false; //Cache the hit-tested node for verification when mouse up is fired @@ -3259,11 +3260,11 @@ protected override void WndProc(ref Message m) { WmMouseDown(ref m, MouseButtons.Right, 1); downButton = MouseButtons.Right; break; - case NativeMethods.WM_SYSCOLORCHANGE: + case Interop.WindowMessages.WM_SYSCOLORCHANGE: SendMessage(NativeMethods.TVM_SETINDENT, Indent, 0); base.WndProc(ref m); break; - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: // If we get focus through the LBUttonDown .. we might have done the validation... // so skip it.. if (treeViewState[TREEVIEWSTATE_lastControlValidated]) @@ -3278,7 +3279,7 @@ protected override void WndProc(ref Message m) { base.WndProc(ref m); } break; - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_CONTEXTMENU: if (treeViewState[TREEVIEWSTATE_showTreeViewContextMenu]) { treeViewState[TREEVIEWSTATE_showTreeViewContextMenu] = false; base.WndProc(ref m); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.cs index 9a7977480a7..b744b9ad23a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.cs @@ -726,12 +726,7 @@ internal override Rectangle ApplyBoundsConstraints(int suggestedX, int suggested /// The accessible name. internal string GetAccessibleName(string baseName) { if (baseName == null) { - if (AccessibilityImprovements.Level3) { - return SR.SpinnerAccessibleName; - } - else if (AccessibilityImprovements.Level1) { - return this.GetType().Name; - } + return SR.SpinnerAccessibleName; } return baseName; @@ -1206,7 +1201,7 @@ protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: if (!HostedInWin32DialogManager) { if (ActiveControl == null) { SetActiveControlInternal(TextBox); @@ -1222,7 +1217,7 @@ protected override void WndProc(ref Message m) base.WndProc(ref m); } break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: DefWndProc(ref m); break; default: @@ -1273,8 +1268,8 @@ public override string Text { set { bool valueChanged = (value != base.Text); base.Text = value; - if (valueChanged && AccessibilityImprovements.Level1) { - AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); + if (valueChanged) { + AccessibilityNotifyClients(AccessibleEvents.NameChange, -1); } } } @@ -1816,12 +1811,10 @@ public override string Name { get { string baseName = base.Name; if (baseName == null || baseName.Length == 0) { - if (AccessibilityImprovements.Level3) { - // For AI.Level3 spinner is already announced so use type name. - return Owner.ParentInternal.GetType().Name; - } - return SR.SpinnerAccessibleName; + // Spinner is already announced so use type name. + return Owner.ParentInternal.GetType().Name; } + return baseName; } set { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/UserControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/UserControl.cs index b86aa0d983d..739a6241e65 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/UserControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/UserControl.cs @@ -349,7 +349,7 @@ private void WmSetFocus(ref Message m) { [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_SETFOCUS: + case Interop.WindowMessages.WM_SETFOCUS: WmSetFocus(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/VScrollBar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/VScrollBar.cs index 81d13fc093e..3cbf29170ee 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/VScrollBar.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/VScrollBar.cs @@ -2,87 +2,68 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; -namespace System.Windows.Forms { - - using System.Diagnostics; - - using System; - using System.Windows.Forms; - using System.ComponentModel; - using System.Drawing; - using Microsoft.Win32; - using System.Runtime.InteropServices; - - /// - /// - /// Represents - /// a standard Windows vertical scroll bar. - /// +namespace System.Windows.Forms +{ + /// + /// Represents a standard Windows vertical scroll bar. + /// [ComVisible(true)] [ClassInterface(ClassInterfaceType.AutoDispatch)] [SRDescription(nameof(SR.DescriptionVScrollBar))] - public class VScrollBar : ScrollBar { + public class VScrollBar : ScrollBar + { + private const int DefaultHeight = 80; - private const int VERTICAL_SCROLLBAR_HEIGHT = 80; - - /// - /// - /// - /// - /// Returns the parameters needed to create the handle. Inheriting classes - /// can override this to provide extra functionality. They should not, - /// however, forget to call base.getCreateParams() first to get the struct - /// filled up with the basic info. - /// - /// - protected override CreateParams CreateParams { - get { + protected override CreateParams CreateParams + { + get + { CreateParams cp = base.CreateParams; cp.Style |= NativeMethods.SBS_VERT; return cp; } } - /// - /// - /// Deriving classes can override this to configure a default size for their control. - /// This is more efficient than setting the size in the control's constructor. - /// - protected override Size DefaultSize { - get { - if (DpiHelper.IsScalingRequirementMet) { - return new Size(SystemInformation.GetVerticalScrollBarWidthForDpi(this.deviceDpi), LogicalToDeviceUnits(VERTICAL_SCROLLBAR_HEIGHT)); + protected override Size DefaultSize + { + get + { + if (DpiHelper.IsScalingRequirementMet) + { + return new Size(SystemInformation.GetVerticalScrollBarWidthForDpi(deviceDpi), LogicalToDeviceUnits(DefaultHeight)); } - else { - return new Size(SystemInformation.VerticalScrollBarWidth, VERTICAL_SCROLLBAR_HEIGHT); + else + { + return new Size(SystemInformation.VerticalScrollBarWidth, DefaultHeight); } } } - /// - /// - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public override RightToLeft RightToLeft { - get { - return RightToLeft.No; - } - set { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override RightToLeft RightToLeft + { + get => RightToLeft.No; + set + { } } - /// - /// - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public new event EventHandler RightToLeftChanged { - add { + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public new event EventHandler RightToLeftChanged + { + add + { base.RightToLeftChanged += value; } - remove { + remove + { base.RightToLeftChanged -= value; } } - } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/VScrollProperties.cs b/src/System.Windows.Forms/src/System/Windows/Forms/VScrollProperties.cs index 22558ad9c61..f13a0a074a6 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/VScrollProperties.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/VScrollProperties.cs @@ -2,51 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Windows.Forms { - using System.Runtime.InteropServices; - using System.Diagnostics; - using System; - using System.Security.Permissions; - using System.Runtime.Serialization.Formatters; - using System.ComponentModel; - using System.Drawing; - using Microsoft.Win32; - using System.Windows.Forms; - - /// +namespace System.Windows.Forms +{ /// - /// - /// Basic Properties for VScroll. - /// + /// Basic Properties for VScroll. /// - public class VScrollProperties : ScrollProperties { - - /// - public VScrollProperties(ScrollableControl container) : base(container) { + public class VScrollProperties : ScrollProperties + { + public VScrollProperties(ScrollableControl container) : base(container) + { } - internal override int PageSize { - get { - return ParentControl.ClientRectangle.Height; - } - } + internal override int PageSize => ParentControl.ClientRectangle.Height; - internal override int Orientation { - get { - return NativeMethods.SB_VERT; - } - } - - internal override int HorizontalDisplayPosition { - get { - return ParentControl.DisplayRectangle.X; - } - } + internal override int Orientation => NativeMethods.SB_VERT; - internal override int VerticalDisplayPosition { - get { - return -this.value; - } - } + internal override int HorizontalDisplayPosition => ParentControl.DisplayRectangle.X; + + internal override int VerticalDisplayPosition => -_value; } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/TextMetrics.cs b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/TextMetrics.cs new file mode 100644 index 00000000000..8d7979aca1d --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/TextMetrics.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Microsoft.MSInternal", "CA905:SystemAndMicrosoftNamespacesRequireApproval", Scope = "namespace", Target = "System.Windows.Forms.VisualStyles")] + +namespace System.Windows.Forms.VisualStyles +{ + public struct TextMetrics + { + public int Height { get; set; } + + public int Ascent { get; set; } + + public int Descent { get; set; } + + public int InternalLeading { get; set; } + + public int ExternalLeading { get; set; } + + public int AverageCharWidth { get; set; } + + public int MaxCharWidth { get; set; } + + public int Weight { get; set; } + + public int Overhang { get; set; } + + public int DigitizedAspectX { get; set; } + + public int DigitizedAspectY { get; set; } + + public char FirstChar { get; set; } + + public char LastChar { get; set; } + + public char DefaultChar { get; set; } + + public char BreakChar { get; set; } + + public bool Italic { get; set; } + + public bool Underlined { get; set; } + + public bool StruckOut { get; set; } + + public TextMetricsPitchAndFamilyValues PitchAndFamily { get; set; } + + public TextMetricsCharacterSet CharSet { get; set; } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleInformation.cs b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleInformation.cs index b06ab04a04d..835d7402976 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleInformation.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleInformation.cs @@ -113,7 +113,7 @@ public static string DisplayName { get { if (IsEnabledByUser) { StringBuilder name = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.DisplayName, name, name.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.DisplayName, name, name.Capacity); return name.ToString(); } @@ -129,7 +129,7 @@ public static string Company { get { if (IsEnabledByUser) { StringBuilder company = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.Company, company, company.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.Company, company, company.Capacity); return company.ToString(); } @@ -145,7 +145,7 @@ public static string Author { get { if (IsEnabledByUser) { StringBuilder author = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.Author, author, author.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.Author, author, author.Capacity); return author.ToString(); } @@ -161,7 +161,7 @@ public static string Copyright { get { if (IsEnabledByUser) { StringBuilder copyright = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.Copyright, copyright, copyright.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.Copyright, copyright, copyright.Capacity); return copyright.ToString(); } @@ -179,7 +179,7 @@ public static string Url { get { if (IsEnabledByUser) { StringBuilder url = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.Url, url, url.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.Url, url, url.Capacity); return url.ToString(); } @@ -195,7 +195,7 @@ public static string Version { get { if (IsEnabledByUser) { StringBuilder version = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.Version, version, version.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.Version, version, version.Capacity); return version.ToString(); } @@ -211,7 +211,7 @@ public static string Description { get { if (IsEnabledByUser) { StringBuilder description = new StringBuilder(512); - SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, VisualStyleDocProperty.Description, description, description.Capacity); + SafeNativeMethods.GetThemeDocumentationProperty(ThemeFilename, SafeNativeMethods.VisualStyleDocProperty.Description, description, description.Capacity); return description.ToString(); } @@ -233,7 +233,7 @@ public static bool SupportsFlatMenus { visualStyleRenderer.SetParameters(VisualStyleElement.Window.Caption.Active); } - return (SafeNativeMethods.GetThemeSysBool(new HandleRef(null, visualStyleRenderer.Handle), VisualStyleSystemProperty.SupportsFlatMenus)); + return (SafeNativeMethods.GetThemeSysBool(new HandleRef(null, visualStyleRenderer.Handle), SafeNativeMethods.VisualStyleSystemProperty.SupportsFlatMenus)); } return false; @@ -256,7 +256,7 @@ public static int MinimumColorDepth { int mcDepth = 0; - SafeNativeMethods.GetThemeSysInt(new HandleRef(null, visualStyleRenderer.Handle), VisualStyleSystemProperty.MinimumColorDepth, ref mcDepth); + SafeNativeMethods.GetThemeSysInt(new HandleRef(null, visualStyleRenderer.Handle), SafeNativeMethods.VisualStyleSystemProperty.MinimumColorDepth, ref mcDepth); return mcDepth; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleRenderer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleRenderer.cs index db3668c3d3f..0491fe4d4df 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleRenderer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleRenderer.cs @@ -403,7 +403,7 @@ public void DrawImage(Graphics g, Rectangle bounds, ImageList imageList, int ima } if (imageIndex < 0 || imageIndex >= imageList.Images.Count) { - throw new ArgumentOutOfRangeException(nameof(imageIndex), string.Format(SR.InvalidArgument, "imageIndex", imageIndex.ToString(CultureInfo.CurrentCulture))); + throw new ArgumentOutOfRangeException(nameof(imageIndex), imageIndex, string.Format(SR.InvalidArgument, nameof(imageIndex), imageIndex)); } if (bounds.Width < 0 || bounds.Height < 0) { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleTypesAndProperties.cs b/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleTypesAndProperties.cs deleted file mode 100644 index a3d4d24de1f..00000000000 --- a/src/System.Windows.Forms/src/System/Windows/Forms/VisualStyles/VisualStyleTypesAndProperties.cs +++ /dev/null @@ -1,309 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Microsoft.MSInternal", "CA905:SystemAndMicrosoftNamespacesRequireApproval", Scope = "namespace", Target = "System.Windows.Forms.VisualStyles")] - -namespace System.Windows.Forms.VisualStyles -{ - public struct TextMetrics - { - private int height; - private int ascent; - private int descent; - private int internalLeading; - private int externalLeading; - private int aveCharWidth; - private int maxCharWidth; - private int weight; - private int overhang; - private int digitizedAspectX; - private int digitizedAspectY; - private char firstChar; - private char lastChar; - private char defaultChar; - private char breakChar; - private bool italic; - private bool underlined; - private bool struckOut; - private TextMetricsPitchAndFamilyValues pitchAndFamily; - private TextMetricsCharacterSet charSet; - - /// - public int Height - { - get - { - return height; - } set - { - height = value; - } - } - - /// - public int Ascent - { - get - { - return ascent; - } - set - { - ascent = value; - } - } - /// - public int Descent - { - get - { - return descent; - } - set - { - descent = value; - } - } - - /// - public int InternalLeading - { - get - { - return internalLeading; - } - set - { - internalLeading = value; - } - } - - /// - public int ExternalLeading - { - get - { - return externalLeading; - } - set - { - externalLeading = value; - } - } - - /// - public int AverageCharWidth - { - get - { - return aveCharWidth; - } - set - { - aveCharWidth = value; - } - } - - /// - public int MaxCharWidth - { - get - { - return maxCharWidth; - } - set - { - maxCharWidth = value; - } - } - - /// - public int Weight - { - get - { - return weight; - } - set - { - weight = value; - } - } - - /// - public int Overhang - { - get - { - return overhang; - } - set - { - overhang = value; - } - } - - /// - public int DigitizedAspectX - { - get - { - return digitizedAspectX; - } - set - { - digitizedAspectX = value; - } - } - - /// - public int DigitizedAspectY - { - get - { - return digitizedAspectY; - } - set - { - digitizedAspectY = value; - } - } - - /// - public char FirstChar - { - get - { - return firstChar; - } - set - { - firstChar = value; - } - } - - /// - public char LastChar - { - get - { - return lastChar; - } - set - { - lastChar = value; - } - } - - /// - public char DefaultChar - { - get - { - return defaultChar; - } - set - { - defaultChar = value; - } - } - - /// - public char BreakChar - { - get - { - return breakChar; - } - set - { - breakChar = value; - } - } - - /// - public bool Italic - { - get - { - return italic; - } - set - { - italic = value; - } - } - - /// - public bool Underlined - { - get - { - return underlined; - } - set - { - underlined = value; - } - } - - /// - public bool StruckOut - { - get - { - return struckOut; - } - set - { - struckOut = value; - } - } - - /// - public TextMetricsPitchAndFamilyValues PitchAndFamily - { - get - { - return pitchAndFamily; - } - set - { - pitchAndFamily = value; - } - } - - /// - public TextMetricsCharacterSet CharSet - { - get - { - return charSet; - } - set - { - charSet = value; - } - } - } - - internal struct VisualStyleDocProperty - { - internal static string DisplayName = "DisplayName"; - internal static string Company = "Company"; - internal static string Author = "Author"; - internal static string Copyright = "Copyright"; - internal static string Url = "Url"; - internal static string Version = "Version"; - internal static string Description = "Description"; - } - - internal struct VisualStyleSystemProperty - { - internal static int SupportsFlatMenus = 1001; - internal static int MinimumColorDepth = 1301; - } -} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowser.cs b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowser.cs index 7e45a471f32..8fa9dae5bb7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowser.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowser.cs @@ -1598,7 +1598,7 @@ private bool ShowContextMenu(int x, int y) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_CONTEXTMENU: int x = NativeMethods.Util.SignedLOWORD(m.LParam); int y = NativeMethods.Util.SignedHIWORD(m.LParam); @@ -1636,10 +1636,6 @@ private UnsafeNativeMethods.IWebBrowser2 AxIWebBrowser2 { // // WebBrowserSite class: // - // - // We slap InheritanceDemand on this class so that only users with - // UnmanagedCode permissions can override this type. - // /// /// /// @@ -1793,7 +1789,7 @@ int UnsafeNativeMethods.IDocHostUIHandler.TranslateAccelerator(ref NativeMethods { int keyCode = (int)msg.wParam | (int)Control.ModifierKeys; - if (msg.message != NativeMethods.WM_CHAR + if (msg.message != Interop.WindowMessages.WM_CHAR && Enum.IsDefined(typeof(Shortcut), (Shortcut)keyCode)) { return NativeMethods.S_OK; } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserBase.cs index 62056016b80..421e072c86a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserBase.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserBase.cs @@ -148,10 +148,6 @@ public object ActiveXInstance { // ActiveX wrapper controls that derive from this class should override the // below method and return their own WebBrowserSiteBaseBase derived object. // - // This method is protected by an InheritanceDemand because extending a - // site is strictly an advanced feature for which one needs UnmanagedCode - // permissions. - // /// /// /// @@ -382,7 +378,7 @@ protected internal override bool ProcessMnemonic(char charCode) { // alt key setting. NativeMethods.MSG msg = new NativeMethods.MSG(); msg.hwnd = IntPtr.Zero; - msg.message = NativeMethods.WM_SYSKEYDOWN; + msg.message = Interop.WindowMessages.WM_SYSKEYDOWN; msg.wParam = (IntPtr)char.ToUpper(charCode, CultureInfo.CurrentCulture); msg.lParam = (IntPtr) 0x20180001; msg.time = SafeNativeMethods.GetTickCount(); @@ -417,39 +413,39 @@ protected override void WndProc(ref Message m) { // // Things we explicitly ignore and pass to the ActiveX's windproc // - case NativeMethods.WM_ERASEBKGND: - case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFYFORMAT: - case NativeMethods.WM_SETCURSOR: - case NativeMethods.WM_SYSCOLORCHANGE: - case NativeMethods.WM_LBUTTONDBLCLK: - case NativeMethods.WM_LBUTTONUP: - case NativeMethods.WM_MBUTTONDBLCLK: - case NativeMethods.WM_MBUTTONUP: - case NativeMethods.WM_RBUTTONDBLCLK: - case NativeMethods.WM_RBUTTONUP: - case NativeMethods.WM_CONTEXTMENU: + case Interop.WindowMessages.WM_ERASEBKGND: + case Interop.WindowMessages.WM_REFLECT + Interop.WindowMessages.WM_NOTIFYFORMAT: + case Interop.WindowMessages.WM_SETCURSOR: + case Interop.WindowMessages.WM_SYSCOLORCHANGE: + case Interop.WindowMessages.WM_LBUTTONDBLCLK: + case Interop.WindowMessages.WM_LBUTTONUP: + case Interop.WindowMessages.WM_MBUTTONDBLCLK: + case Interop.WindowMessages.WM_MBUTTONUP: + case Interop.WindowMessages.WM_RBUTTONDBLCLK: + case Interop.WindowMessages.WM_RBUTTONUP: + case Interop.WindowMessages.WM_CONTEXTMENU: // // Some of the MSComCtl controls respond to this message to do some // custom painting. So, we should just pass this message through. - case NativeMethods.WM_DRAWITEM: + case Interop.WindowMessages.WM_DRAWITEM: DefWndProc(ref m); break; - case NativeMethods.WM_COMMAND: + case Interop.WindowMessages.WM_COMMAND: if (!ReflectMessageInternal(m.LParam, ref m)) DefWndProc(ref m); break; - case NativeMethods.WM_HELP: + case Interop.WindowMessages.WM_HELP: // We want to both fire the event, and let the ActiveX have the message... base.WndProc(ref m); DefWndProc(ref m); break; - case NativeMethods.WM_LBUTTONDOWN: - case NativeMethods.WM_MBUTTONDOWN: - case NativeMethods.WM_RBUTTONDOWN: - case NativeMethods.WM_MOUSEACTIVATE: + case Interop.WindowMessages.WM_LBUTTONDOWN: + case Interop.WindowMessages.WM_MBUTTONDOWN: + case Interop.WindowMessages.WM_RBUTTONDOWN: + case Interop.WindowMessages.WM_MOUSEACTIVATE: if (!DesignMode) { if (containingControl != null && containingControl.ActiveControl != this) { FocusInternal(); @@ -458,7 +454,7 @@ protected override void WndProc(ref Message m) { DefWndProc(ref m); break; - case NativeMethods.WM_KILLFOCUS: + case Interop.WindowMessages.WM_KILLFOCUS: hwndFocus = (IntPtr)m.WParam; try { base.WndProc(ref m); @@ -468,7 +464,7 @@ protected override void WndProc(ref Message m) { } break; - case NativeMethods.WM_DESTROY: + case Interop.WindowMessages.WM_DESTROY: // // If we are currently in a state of InPlaceActive or above, // we should first reparent the ActiveX control to our parking @@ -1957,7 +1953,7 @@ public WebBrowserBaseNativeWindow(WebBrowserBase ax) { /// protected override void WndProc(ref Message m) { switch (m.Msg) { - case NativeMethods.WM_WINDOWPOSCHANGING: + case Interop.WindowMessages.WM_WINDOWPOSCHANGING: WmWindowPosChanging(ref m); break; default: diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserContainer.cs b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserContainer.cs index d5792594c20..0f910270ea8 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserContainer.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserContainer.cs @@ -8,7 +8,6 @@ using System; using System.Reflection; using System.Globalization; -using System.Security.Permissions; using System.Collections; using System.Drawing; using System.Windows.Forms.Design; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserHelper.cs b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserHelper.cs index bead9bba212..26a4eb9c01d 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserHelper.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserHelper.cs @@ -13,7 +13,6 @@ using System; using System.Reflection; using System.Globalization; -using System.Security.Permissions; using Microsoft.Win32; using System.Collections; using System.Collections.Specialized; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserSiteBase.cs b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserSiteBase.cs index 60600d986ca..449268d302b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserSiteBase.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserSiteBase.cs @@ -13,7 +13,6 @@ using System; using System.Reflection; using System.Globalization; -using System.Security.Permissions; using Microsoft.Win32; using System.Collections; using System.Collections.Specialized; @@ -308,7 +307,7 @@ int UnsafeNativeMethods.IOleInPlaceSite.GetWindowContext(out UnsafeNativeMethods lprcClipRect = WebBrowserHelper.GetClipRect(); if (lpFrameInfo != null) { - lpFrameInfo.cb = Marshal.SizeOf(typeof(NativeMethods.tagOIFI)); + lpFrameInfo.cb = Marshal.SizeOf(); lpFrameInfo.fMDIApp = false; lpFrameInfo.hAccel = IntPtr.Zero; lpFrameInfo.cAccelEntries = 0; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/WinFormsUtils.cs b/src/System.Windows.Forms/src/System/Windows/Forms/WinFormsUtils.cs index 4af118f7473..c5801d58335 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/WinFormsUtils.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/WinFormsUtils.cs @@ -2,103 +2,111 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Windows.Forms.WindowsFormsUtils..ctor()")] - +using System.Collections; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms.Internal; + +[assembly: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Windows.Forms.WindowsFormsUtils..ctor()")] namespace System.Windows.Forms { - using System; - using System.Collections; - using System.ComponentModel; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Drawing; - using System.Globalization; - using System.Runtime.InteropServices; - using System.Runtime.Versioning; - using System.Security; - using System.Text; - using System.Windows.Forms.Internal; - - // Miscellaneous Windows Forms utilities - internal sealed class WindowsFormsUtils { - - // A better initializer than Size.Empty to force code using uninitialized to noticably fail. - public static readonly Size UninitializedSize = new Size(-7199369, -5999471); - - public static readonly ContentAlignment AnyRightAlign = ContentAlignment.TopRight | ContentAlignment.MiddleRight | ContentAlignment.BottomRight; - public static readonly ContentAlignment AnyLeftAlign = ContentAlignment.TopLeft | ContentAlignment.MiddleLeft | ContentAlignment.BottomLeft; - public static readonly ContentAlignment AnyTopAlign = ContentAlignment.TopLeft | ContentAlignment.TopCenter | ContentAlignment.TopRight; - public static readonly ContentAlignment AnyBottomAlign = ContentAlignment.BottomLeft | ContentAlignment.BottomCenter | ContentAlignment.BottomRight; - public static readonly ContentAlignment AnyMiddleAlign = ContentAlignment.MiddleLeft | ContentAlignment.MiddleCenter | ContentAlignment.MiddleRight; - public static readonly ContentAlignment AnyCenterAlign = ContentAlignment.TopCenter | ContentAlignment.MiddleCenter | ContentAlignment.BottomCenter; - - /// + internal sealed class WindowsFormsUtils + { + public static readonly ContentAlignment AnyRightAlign = ContentAlignment.TopRight | ContentAlignment.MiddleRight | ContentAlignment.BottomRight; + public static readonly ContentAlignment AnyLeftAlign = ContentAlignment.TopLeft | ContentAlignment.MiddleLeft | ContentAlignment.BottomLeft; + public static readonly ContentAlignment AnyTopAlign = ContentAlignment.TopLeft | ContentAlignment.TopCenter | ContentAlignment.TopRight; + public static readonly ContentAlignment AnyBottomAlign = ContentAlignment.BottomLeft | ContentAlignment.BottomCenter | ContentAlignment.BottomRight; + public static readonly ContentAlignment AnyMiddleAlign = ContentAlignment.MiddleLeft | ContentAlignment.MiddleCenter | ContentAlignment.MiddleRight; + public static readonly ContentAlignment AnyCenterAlign = ContentAlignment.TopCenter | ContentAlignment.MiddleCenter | ContentAlignment.BottomCenter; + + /// /// The GetMessagePos function retrieves the cursor position for the last message /// retrieved by the GetMessage function. - /// - public static Point LastCursorPoint { - get { + /// + public static Point LastCursorPoint + { + get + { int lastXY = SafeNativeMethods.GetMessagePos(); - return new Point(NativeMethods.Util.SignedLOWORD(lastXY),NativeMethods.Util.SignedHIWORD(lastXY)) ; + return new Point(NativeMethods.Util.SignedLOWORD(lastXY), NativeMethods.Util.SignedHIWORD(lastXY)); } } + /// /// this graphics requires disposal. - - - public static Graphics CreateMeasurementGraphics() { + /// + public static Graphics CreateMeasurementGraphics() + { return Graphics.FromHdcInternal(WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.Hdc); } - - // If you want to know if a piece of text contains one and only one & - // this is your function. If you have a character "t" and want match it to &Text - // Control.IsMnemonic is a better bet. - public static bool ContainsMnemonic(string text) { - if (text != null) { + + /// + /// If you want to know if a piece of text contains one and only one & + /// this is your function. If you have a character "t" and want match it to &Text + /// Control.IsMnemonic is a better bet. + /// + public static bool ContainsMnemonic(string text) + { + if (text != null) + { int textLength = text.Length; int firstAmpersand = text.IndexOf('&', 0); - if (firstAmpersand >=0 && firstAmpersand <= /*second to last char=*/textLength -2) { + if (firstAmpersand >= 0 && firstAmpersand <= /*second to last char=*/textLength - 2) + { // we found one ampersand and it's either the first character // or the second to last character // or a character in between // We're so close! make sure we don't have a double ampersand now. - int secondAmpersand = text.IndexOf('&', firstAmpersand+1); - if (secondAmpersand == -1) { + int secondAmpersand = text.IndexOf('&', firstAmpersand + 1); + if (secondAmpersand == -1) + { // didn't find a second one in the string. return true; - } + } } } return false; } - internal static Rectangle ConstrainToScreenWorkingAreaBounds(Rectangle bounds) { + internal static Rectangle ConstrainToScreenWorkingAreaBounds(Rectangle bounds) + { return ConstrainToBounds(Screen.GetWorkingArea(bounds), bounds); } - /// given a rectangle, constrain it to fit onto the current screen. - /// - internal static Rectangle ConstrainToScreenBounds(Rectangle bounds) { + /// + /// Given a rectangle, constrain it to fit onto the current screen. + /// + internal static Rectangle ConstrainToScreenBounds(Rectangle bounds) + { return ConstrainToBounds(Screen.FromRectangle(bounds).Bounds, bounds); } - internal static Rectangle ConstrainToBounds(Rectangle constrainingBounds, Rectangle bounds) { + internal static Rectangle ConstrainToBounds(Rectangle constrainingBounds, Rectangle bounds) + { // use screen instead of SystemInformation.WorkingArea for better multimon support. - if (!constrainingBounds.Contains(bounds)) { + if (!constrainingBounds.Contains(bounds)) + { // make sure size does not exceed working area. - bounds.Size = new Size(Math.Min(constrainingBounds.Width -2, bounds.Width), - Math.Min(constrainingBounds.Height -2, bounds.Height)); - + bounds.Size = new Size(Math.Min(constrainingBounds.Width - 2, bounds.Width), + Math.Min(constrainingBounds.Height - 2, bounds.Height)); + // X calculations // // scooch so it will fit on the screen. - if (bounds.Right > constrainingBounds.Right) { + if (bounds.Right > constrainingBounds.Right) + { // its too far to the right. bounds.X = constrainingBounds.Right - bounds.Width; } - else if (bounds.Left < constrainingBounds.Left) { + else if (bounds.Left < constrainingBounds.Left) + { // its too far to the left. bounds.X = constrainingBounds.Left; } @@ -106,121 +114,137 @@ internal static Rectangle ConstrainToBounds(Rectangle constrainingBounds, Rectan // Y calculations // // scooch so it will fit on the screen. - if (bounds.Bottom > constrainingBounds.Bottom) { - // its too far to the bottom. - bounds.Y = constrainingBounds.Bottom - 1 - bounds.Height; + if (bounds.Bottom > constrainingBounds.Bottom) + { + // its too far to the bottom. + bounds.Y = constrainingBounds.Bottom - 1 - bounds.Height; } - else if (bounds.Top < constrainingBounds.Top) { - // its too far to the top. - bounds.Y = constrainingBounds.Top; + else if (bounds.Top < constrainingBounds.Top) + { + // its too far to the top. + bounds.Y = constrainingBounds.Top; } } - return bounds; + return bounds; } - // adds an extra & to to the text so that Fish & Chips can be displayed on a menu item without underlining - // anything. This is used in MDIWindowList as we use the MDIChildForm.Text as menu item text. - // Fish & Chips --> Fish && Chips - internal static string EscapeTextWithAmpersands(string text) { - if (text == null) { + /// + /// Adds an extra & to to the text so that "Fish & Chips" can be displayed on a menu item + /// without underlining anything. + /// Fish & Chips --> Fish && Chips + /// + internal static string EscapeTextWithAmpersands(string text) + { + if (text == null) + { return null; } int index = text.IndexOf('&'); - - if (index == -1) { + if (index == -1) + { return text; } - + StringBuilder str = new StringBuilder(text.Substring(0, index)); - for(; index < text.Length; ++index) { - if (text[index] == '&') { + for (; index < text.Length; ++index) + { + if (text[index] == '&') + { str.Append("&"); } - if (index < text.Length) { + if (index < text.Length) + { str.Append(text[index]); } } return str.ToString(); } - // helper function for generating information about a particular control - // use AssertControlInformation if sticking in an assert - then the work - // to figure out the control info will only be done when the assertion is false. - internal static string GetControlInformation(IntPtr hwnd) { - if (hwnd == IntPtr.Zero) { + /// + /// helper function for generating information about a particular control + /// use AssertControlInformation if sticking in an assert - then the work + /// to figure out the control info will only be done when the assertion is false. + /// + internal static string GetControlInformation(IntPtr hwnd) + { + if (hwnd == IntPtr.Zero) + { return "Handle is IntPtr.Zero"; } - string ret = ""; // in RETAIL just return empty string + #if DEBUG - try { - int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(null, hwnd)); - StringBuilder sb = new StringBuilder(textLen+1); - UnsafeNativeMethods.GetWindowText(new HandleRef(null, hwnd), sb, sb.Capacity); - - string typeOfControl = "Unknown"; - string nameOfControl = "Name: "; - Control c = Control.FromHandle(hwnd); - if (c != null) { - typeOfControl = c.GetType().ToString(); - if (!string.IsNullOrEmpty(c.Name)) { - nameOfControl += c.Name; - } - else { - nameOfControl += "Unknown"; - - // some extra debug info for toolstripdropdowns... - if (c is ToolStripDropDown) { - ToolStripDropDown dd = c as ToolStripDropDown; - if (dd.OwnerItem != null) { - nameOfControl += "\r\n\tOwnerItem: " + dd.OwnerItem.ToString(); - } - } + int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(null, hwnd)); + StringBuilder sb = new StringBuilder(textLen+1); + UnsafeNativeMethods.GetWindowText(new HandleRef(null, hwnd), sb, sb.Capacity); + + string typeOfControl = "Unknown"; + string nameOfControl = "Name: "; + Control c = Control.FromHandle(hwnd); + if (c != null) + { + typeOfControl = c.GetType().ToString(); + if (!string.IsNullOrEmpty(c.Name)) + { + nameOfControl += c.Name; + } + else + { + nameOfControl += "Unknown"; + + // Add some extra debug info for ToolStripDropDowns. + if (c is ToolStripDropDown dd && dd.OwnerItem != null) + { + nameOfControl += Environment.NewLine + "\tOwnerItem: " + dd.OwnerItem.ToString(); } - } - ret = sb.ToString() + "\r\n\tType: " + typeOfControl + "\r\n\t" + nameOfControl + "\r\n"; - } - catch (SecurityException) { - // some suites run under DEBUG - just eat this exception + } } -#endif - return ret; + return sb.ToString() + Environment.NewLine + "\tType: " + typeOfControl + Environment.NewLine + "\t" + nameOfControl + Environment.NewLine; +#else + return string.Empty; +#endif } - // only fetch the information on a false assertion. - internal static string AssertControlInformation(bool condition, Control control) { - if (condition) { + internal static string AssertControlInformation(bool condition, Control control) + { + if (condition) + { return string.Empty; } - else { + else + { return GetControlInformation(control.Handle); } } - // Retrieves the mnemonic from a given string, or zero if no mnemonic. - // As used by the Control.Mnemonic to get mnemonic from Control.Text. - // - // Boolean argument determines whether returned char is converted to upper - // case or lower case (always one or the other - case is never preserved). - public static char GetMnemonic(string text, bool bConvertToUpperCase) { - char mnemonic = (char)0; - - if (text != null) { + /// + /// Retrieves the mnemonic from a given string, or zero if no mnemonic. + /// As used by the Control.Mnemonic to get mnemonic from Control.Text. + /// + public static char GetMnemonic(string text, bool convertToUpperCase) + { + char mnemonic = '\0'; + if (text != null) + { int len = text.Length; - for (int i = 0; i < len - 1; i++) { - if (text[i] == '&') { + for (int i = 0; i < len - 1; i++) + { + if (text[i] == '&') + { if (text[i + 1] == '&') { // we have an escaped &, so we need to skip it. - // i++; continue; } - if (bConvertToUpperCase) { - mnemonic = char.ToUpper(text[i+1], CultureInfo.CurrentCulture); + + if (convertToUpperCase) + { + mnemonic = char.ToUpper(text[i + 1], CultureInfo.CurrentCulture); } - else { - mnemonic = char.ToLower(text[i+1], CultureInfo.CurrentCulture); + else + { + mnemonic = char.ToLower(text[i + 1], CultureInfo.CurrentCulture); } break; } @@ -229,336 +253,348 @@ public static char GetMnemonic(string text, bool bConvertToUpperCase) { return mnemonic; } - // for a given handle, finds the toplevel handle - public static HandleRef GetRootHWnd(HandleRef hwnd) { + /// + /// Finds the top level handle for a given handle. + /// + public static HandleRef GetRootHWnd(HandleRef hwnd) + { IntPtr rootHwnd = UnsafeNativeMethods.GetAncestor(new HandleRef(hwnd, hwnd.Handle), NativeMethods.GA_ROOT); - return new HandleRef(hwnd.Wrapper, rootHwnd); + return new HandleRef(hwnd.Wrapper, rootHwnd); } - // for a given control, finds the toplevel handle - public static HandleRef GetRootHWnd(Control control) { - return GetRootHWnd(new HandleRef(control, control.Handle)); + /// + /// Finds the top level handle for a given handle. + /// + public static HandleRef GetRootHWnd(Control control) + { + return GetRootHWnd(new HandleRef(control, control.Handle)); } - // Strips all keyboard mnemonic prefixes from a given string, eg. turning "He&lp" into "Help". - // Note: Be careful not to call this multiple times on the same string, otherwise you'll turn - // something like "Fi&sh && Chips" into "Fish & Chips" on the first call, and then "Fish Chips" - // on the second call. - public static string TextWithoutMnemonics(string text) { - if (text == null) { + /// + /// Strips all keyboard mnemonic prefixes from a given string, eg. turning "He&lp" into "Help". + /// + /// + /// Note: Be careful not to call this multiple times on the same string, otherwise you'll turn + /// something like "Fi&sh && Chips" into "Fish & Chips" on the first call, and then "Fish Chips" + /// on the second call. + /// + public static string TextWithoutMnemonics(string text) + { + if (text == null) + { return null; } int index = text.IndexOf('&'); - - if (index == -1) { + if (index == -1) + { return text; } StringBuilder str = new StringBuilder(text.Substring(0, index)); - for(; index < text.Length; ++index) { - if (text[index] == '&') { - index++; // Skip this & and copy the next character instead + for (; index < text.Length; ++index) + { + if (text[index] == '&') + { + // Skip this & and copy the next character instead + index++; } - if (index < text.Length) { + + if (index < text.Length) + { str.Append(text[index]); } } + return str.ToString(); } - + /// /// Translates a point from one control's coordinate system to the other /// same as: - /// controlTo.PointToClient(controlFrom.PointToScreen(point)) + /// controlTo.PointToClient(controlFrom.PointToScreen(point)) /// but slightly more performant. - public static Point TranslatePoint(Point point, Control fromControl, Control toControl) { + /// + public static Point TranslatePoint(Point point, Control fromControl, Control toControl) + { NativeMethods.POINT pt = new NativeMethods.POINT(point.X, point.Y); UnsafeNativeMethods.MapWindowPoints(new HandleRef(fromControl, fromControl.Handle), new HandleRef(toControl, toControl.Handle), pt, 1); - return new Point(pt.x, pt.y); + return new Point(pt.x, pt.y); } - - - // Compares the strings using invariant culture for Turkish-I support. Returns true if they match. - // - // If your strings are symbolic (returned from APIs, not from user) the following calls - // are faster than this method: - // - // String.Equals(s1, s2, StringComparison.Ordinal) - // String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase) - // - public static bool SafeCompareStrings(string string1, string string2, bool ignoreCase) { - if ((string1 == null) || (string2 == null)) { - // if either key is null, we should return false - return false; + + + /// + /// Compares the strings using invariant culture for Turkish-I support. Returns true if they match. + /// + /// If your strings are symbolic (returned from APIs, not from user) the following calls + /// are faster than this method: + /// + /// String.Equals(s1, s2, StringComparison.Ordinal) + /// String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase) + /// + public static bool SafeCompareStrings(string string1, string string2, bool ignoreCase) + { + if ((string1 == null) || (string2 == null)) + { + // if either key is null, we should return false + return false; } // Because String.Compare returns an ordering, it can not terminate early if lengths are not the same. // Also, equivalent characters can be encoded in different byte sequences, so it can not necessarily - // terminate on the first byte which doesn't match. Hence this optimization. - if (string1.Length != string2.Length) { + // terminate on the first byte which doesn't match. Hence this optimization. + if (string1.Length != string2.Length) + { return false; } return string.Compare(string1, string2, ignoreCase, CultureInfo.InvariantCulture) == 0; } - public static string GetComponentName(IComponent component, string defaultNameValue) { + public static string GetComponentName(IComponent component, string defaultNameValue) + { Debug.Assert(component != null, "component passed here cannot be null"); - string result = string.Empty; - if (string.IsNullOrEmpty(defaultNameValue)) { - if(component.Site != null) { - result = component.Site.Name; - } - if(result == null) { - result = string.Empty; - } - } else { - result = defaultNameValue; - } - return result; + if (string.IsNullOrEmpty(defaultNameValue)) + { + return component.Site?.Name ?? string.Empty; + } + else + { + return defaultNameValue; + } } - public static class EnumValidator { - - // IsValidContentAlignment - // Valid values are 0x001,0x002,0x004, 0x010,0x020,0x040, 0x100, 0x200,0x400 - // Method for verifying - // Verify that the number passed in has only one bit on - // Verify that the bit that is on is a valid bit by bitwise anding it to a mask. - // - public static bool IsValidContentAlignment(ContentAlignment contentAlign) { - if (ClientUtils.GetBitCount((uint)contentAlign) != 1) { + public static class EnumValidator + { + /// + /// Valid values are 0x001,0x002,0x004, 0x010,0x020,0x040, 0x100, 0x200,0x400 + /// Method for verifying + /// Verify that the number passed in has only one bit on + /// Verify that the bit that is on is a valid bit by bitwise anding it to a mask. + /// + public static bool IsValidContentAlignment(ContentAlignment contentAlign) + { + if (ClientUtils.GetBitCount((uint)contentAlign) != 1) + { return false; } + // to calculate: // foreach (int val in Enum.GetValues(typeof(ContentAlignment))) { mask |= val; } int contentAlignmentMask = 0x777; return ((contentAlignmentMask & (int)contentAlign) != 0); } - // IsEnumWithinShiftedRange - // shifts off the number of bits specified by numBitsToShift - // - makes sure the bits we've shifted off are just zeros - // - then compares if the resulting value is between minValAfterShift and maxValAfterShift - // - // EXAMPLE: - // MessageBoxIcon. Valid values are 0x0, 0x10, 0x20, 0x30, 0x40 - // Method for verifying: chop off the last 0 by shifting right 4 bits, verify resulting number is between 0 & 4. - // - // WindowsFormsUtils.EnumValidator.IsEnumWithinShiftedRange(icon, /*numBitsToShift*/4, /*min*/0x0,/*max*/0x4) - // - public static bool IsEnumWithinShiftedRange(Enum enumValue, int numBitsToShift, int minValAfterShift, int maxValAfterShift){ + /// + /// shifts off the number of bits specified by numBitsToShift + /// - makes sure the bits we've shifted off are just zeros + /// - then compares if the resulting value is between minValAfterShift and maxValAfterShift + /// + /// EXAMPLE: + /// MessageBoxIcon. Valid values are 0x0, 0x10, 0x20, 0x30, 0x40 + /// Method for verifying: chop off the last 0 by shifting right 4 bits, verify resulting number is between 0 & 4. + /// + /// WindowsFormsUtils.EnumValidator.IsEnumWithinShiftedRange(icon, /*numBitsToShift*/4, /*min*/0x0,/*max*/0x4) + /// + public static bool IsEnumWithinShiftedRange(Enum enumValue, int numBitsToShift, int minValAfterShift, int maxValAfterShift) + { int iValue = Convert.ToInt32(enumValue, CultureInfo.InvariantCulture); int remainder = iValue >> numBitsToShift; - if (remainder << numBitsToShift != iValue) { + if (remainder << numBitsToShift != iValue) + { // there were bits that we shifted out. return false; } return (remainder >= minValAfterShift && remainder <= maxValAfterShift); } - - // IsValidTextImageRelation - // valid values are 0,1,2,4,8 - // Method for verifying - // Verify that the number is between 0 and 8 - // Verify that the bit that is on - thus forcing it to be a power of two. - // - public static bool IsValidTextImageRelation(TextImageRelation relation) { - return ClientUtils.IsEnumValid(relation, (int)relation, (int)TextImageRelation.Overlay, (int)TextImageRelation.TextBeforeImage,1); - } - - public static bool IsValidArrowDirection(ArrowDirection direction) { - switch (direction) { - case ArrowDirection.Up: - case ArrowDirection.Down: - case ArrowDirection.Left: - case ArrowDirection.Right: - return true; - default: - return false; - } - } } - // To enumerate over only part of an array. - public class ArraySubsetEnumerator : IEnumerator { - private object[] array; // Perhaps this should really be typed Array, but then we suffer a performance penalty. - private int total; - private int current; + public class ArraySubsetEnumerator : IEnumerator + { + private object[] _array; + private int _total; + private int _current; - public ArraySubsetEnumerator(object[] array, int count) { + public ArraySubsetEnumerator(object[] array, int count) + { Debug.Assert(count == 0 || array != null, "if array is null, count should be 0"); Debug.Assert(array == null || count <= array.Length, "Trying to enumerate more than the array contains"); - this.array = array; - this.total = count; - current = -1; + _array = array; + _total = count; + _current = -1; } - public bool MoveNext() { - if (current < total - 1) { - current++; + public bool MoveNext() + { + if (_current < _total - 1) + { + _current++; return true; } - else - return false; + + return false; } - public void Reset() { - current = -1; + public void Reset() + { + _current = -1; } - public object Current { - get { - if (current == -1) - return null; - else - return array[current]; - } - } + public object Current => _current == -1 ? null : _array[_current]; } - /// - /// This is a ControlCollection which can be made readonly. In readonly mode, this - /// ControlCollection throws NotSupportedExceptions for any operation that attempts - /// to modify the collection. - /// - internal class ReadOnlyControlCollection : Control.ControlCollection { - + /// + /// This is a ControlCollection which can be made readonly. In readonly mode, this + /// ControlCollection throws NotSupportedExceptions for any operation that attempts + /// to modify the collection. + /// + internal class ReadOnlyControlCollection : Control.ControlCollection + { + private readonly bool _isReadOnly; - - public ReadOnlyControlCollection(Control owner, bool isReadOnly) : base(owner) { + + public ReadOnlyControlCollection(Control owner, bool isReadOnly) : base(owner) + { _isReadOnly = isReadOnly; } - public override void Add(Control value) { - if (IsReadOnly) { + public override void Add(Control value) + { + if (IsReadOnly) + { throw new NotSupportedException(SR.ReadonlyControlsCollection); } + AddInternal(value); } - internal virtual void AddInternal(Control value) { - base.Add(value); - } + internal virtual void AddInternal(Control value) => base.Add(value); - public override void Clear() { - if (IsReadOnly) { + public override void Clear() + { + if (IsReadOnly) + { throw new NotSupportedException(SR.ReadonlyControlsCollection); } + base.Clear(); } - internal virtual void RemoveInternal(Control value) { - base.Remove(value); - } - - public override void RemoveByKey(string key) { - if (IsReadOnly) { + internal virtual void RemoveInternal(Control value) => base.Remove(value); + + public override void RemoveByKey(string key) + { + if (IsReadOnly) + { throw new NotSupportedException(SR.ReadonlyControlsCollection); } + base.RemoveByKey(key); } - public override bool IsReadOnly { - get { return _isReadOnly; } - } + public override bool IsReadOnly => _isReadOnly; } - - /// + + /// /// This control collection only allows a specific type of control - /// into the controls collection. It optionally supports readonlyness. - /// - internal class TypedControlCollection : ReadOnlyControlCollection { - - private Type typeOfControl; - private Control ownerControl; - - public TypedControlCollection(Control owner, Type typeOfControl, bool isReadOnly) : base(owner, isReadOnly) { - this.typeOfControl = typeOfControl; - this.ownerControl = owner; - } - - public TypedControlCollection(Control owner, Type typeOfControl) : base(owner, /*isReadOnly*/false) { - this.typeOfControl = typeOfControl; - this.ownerControl = owner; - } - - public override void Add(Control value) { - //Check parenting first for consistency - Control.CheckParentingCycle(ownerControl, value); - - if (value == null) { + /// into the controls collection. It optionally supports readonlyness. + /// + internal class TypedControlCollection : ReadOnlyControlCollection + { + private Type _typeOfControl; + private Control _ownerControl; + + public TypedControlCollection(Control owner, Type typeOfControl, bool isReadOnly) : base(owner, isReadOnly) + { + _typeOfControl = typeOfControl; + _ownerControl = owner; + } + + public TypedControlCollection(Control owner, Type typeOfControl) : base(owner, /*isReadOnly*/false) + { + _typeOfControl = typeOfControl; + _ownerControl = owner; + } + + public override void Add(Control value) + { + // Check parenting first for consistency + Control.CheckParentingCycle(_ownerControl, value); + + if (value == null) + { throw new ArgumentNullException(nameof(value)); } - if (IsReadOnly) { + if (IsReadOnly) + { throw new NotSupportedException(SR.ReadonlyControlsCollection); } - if (!typeOfControl.IsAssignableFrom(value.GetType())) { - throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, string.Format(SR.TypedControlCollectionShouldBeOfType, typeOfControl.Name)), value.GetType().Name); + if (!_typeOfControl.IsAssignableFrom(value.GetType())) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, string.Format(SR.TypedControlCollectionShouldBeOfType, _typeOfControl.Name)), value.GetType().Name); } + base.Add(value); } } - /// - /// DCMapping is used to change the mapping and clip region of the - /// the specified device context to the given bounds. When the - /// DCMapping is disposed, the original mapping and clip rectangle - /// are restored. + /// + /// DCMapping is used to change the mapping and clip region of the + /// the specified device context to the given bounds. When the + /// DCMapping is disposed, the original mapping and clip rectangle + /// are restored. /// - /// Example: - /// - /// using(WindowsFormsUtils.DCMapping mapping = new WindowsFormsUtils.DCMapping(hDC, new Rectangle(10,10, 50, 50) { - /// // inside here the hDC's mapping of (0,0) is inset by (10,10) and - /// // all painting is clipped at (0,0) - (50,50) - /// } - /// - /// To use with GDI+ you can get the hDC from the Graphics object. You'd want to do this in a situation where - /// you're handing off a graphics object to someone, and you want the world translated some amount X,Y. This - /// works better than g.TranslateTransform(x,y) - as if someone calls g.GetHdc and does a GDI operation - their - /// world is NOT transformed. + /// Example: + /// + /// using(WindowsFormsUtils.DCMapping mapping = new WindowsFormsUtils.DCMapping(hDC, new Rectangle(10,10, 50, 50) { + /// // inside here the hDC's mapping of (0,0) is inset by (10,10) and + /// // all painting is clipped at (0,0) - (50,50) + /// } /// - /// HandleRef hDC = new HandleRef(this, originalGraphics.GetHdc()); - /// try { - /// using(WindowsFormsUtils.DCMapping mapping = new WindowsFormsUtils.DCMapping(hDC, new Rectangle(10,10, 50, 50) { - /// - /// // DO NOT ATTEMPT TO USE originalGraphics here - you'll get an Object Busy error - /// // rather ask the mapping object for a graphics object. - /// mapping.Graphics.DrawRectangle(Pens.Black, rect); - /// } - /// } - /// finally { g.ReleaseHdc(hDC.Handle);} + /// To use with GDI+ you can get the hDC from the Graphics object. You'd want to do this in a situation where + /// you're handing off a graphics object to someone, and you want the world translated some amount X,Y. This + /// works better than g.TranslateTransform(x,y) - as if someone calls g.GetHdc and does a GDI operation - their + /// world is NOT transformed. /// - /// PERF: DCMapping is a structure so that it will allocate on the stack rather than in GC managed - /// memory. This way disposing the object does not force a GC. Since DCMapping objects aren't - /// likely to be passed between functions rather used and disposed in the same one, this reduces - /// overhead. - /// - internal struct DCMapping : IDisposable { - - private DeviceContext dc; - private Graphics graphics; - Rectangle translatedBounds; - - - - public DCMapping(HandleRef hDC, Rectangle bounds) { - if (hDC.Handle == IntPtr.Zero) { + /// HandleRef hDC = new HandleRef(this, originalGraphics.GetHdc()); + /// try { + /// using(WindowsFormsUtils.DCMapping mapping = new WindowsFormsUtils.DCMapping(hDC, new Rectangle(10,10, 50, 50) { + /// + /// // DO NOT ATTEMPT TO USE originalGraphics here - you'll get an Object Busy error + /// // rather ask the mapping object for a graphics object. + /// mapping.Graphics.DrawRectangle(Pens.Black, rect); + /// } + /// } + /// finally { g.ReleaseHdc(hDC.Handle);} + /// + /// PERF: DCMapping is a structure so that it will allocate on the stack rather than in GC managed + /// memory. This way disposing the object does not force a GC. Since DCMapping objects aren't + /// likely to be passed between functions rather used and disposed in the same one, this reduces + /// overhead. + /// + internal struct DCMapping : IDisposable + { + private DeviceContext _dc; + private Graphics _graphics; + private Rectangle _translatedBounds; + + public DCMapping(HandleRef hDC, Rectangle bounds) + { + if (hDC.Handle == IntPtr.Zero) + { throw new ArgumentNullException(nameof(hDC)); } bool success; - NativeMethods.POINT viewportOrg = new NativeMethods.POINT(); - HandleRef hOriginalClippingRegion = NativeMethods.NullHandleRef; + NativeMethods.POINT viewportOrg = new NativeMethods.POINT(); + HandleRef hOriginalClippingRegion = NativeMethods.NullHandleRef; NativeMethods.RegionFlags originalRegionType = NativeMethods.RegionFlags.NULLREGION; - - this.translatedBounds = bounds; - this.graphics = null; - this.dc = DeviceContext.FromHdc(hDC.Handle); - this.dc.SaveHdc(); + _translatedBounds = bounds; + _graphics = null; + _dc = DeviceContext.FromHdc(hDC.Handle); + _dc.SaveHdc(); // Retrieve the x-coordinates and y-coordinates of the viewport origin for the specified device context. success = SafeNativeMethods.GetViewportOrgEx(hDC, viewportOrg); @@ -618,69 +654,68 @@ public DCMapping(HandleRef hDC, Rectangle bounds) { "SIMPLEREGION or NULLLREGION expected."); } - catch (Exception ex) + catch (Exception ex) when (!ClientUtils.IsSecurityOrCriticalException(ex)) { - if (ClientUtils.IsSecurityOrCriticalException(ex)) - { - throw; - } - - this.dc.RestoreHdc(); - this.dc.Dispose(); + _dc.RestoreHdc(); + _dc.Dispose(); } - finally { + finally + { // Delete the new clipping region, as the clipping region for the HDC is now set - // to this rectangle. Hold on to hOriginalClippingRegion, as we'll need to restore + // to this rectangle. Hold on to hOriginalClippingRegion, as we'll need to restore // it when this object is disposed. success = SafeNativeMethods.DeleteObject(hClippingRegion); Debug.Assert(success, "DeleteObject(hClippingRegion) failed."); - if (hOriginalClippingRegion.Handle != IntPtr.Zero) { + if (hOriginalClippingRegion.Handle != IntPtr.Zero) + { success = SafeNativeMethods.DeleteObject(hOriginalClippingRegion); Debug.Assert(success, "DeleteObject(hOriginalClippingRegion) failed."); } } } - - public void Dispose() { - if( graphics != null ){ + + public void Dispose() + { + if (_graphics != null) + { // Reset GDI+ if used. // we need to dispose the graphics object first, as it will do // some restoration to the ViewPort and ClipRectangle to restore the hDC to // the same state it was created in - graphics.Dispose(); - graphics = null; + _graphics.Dispose(); + _graphics = null; } - if (this.dc != null) { + if (_dc != null) + { // Now properly reset GDI. - this.dc.RestoreHdc(); - this.dc.Dispose(); - this.dc = null; + _dc.RestoreHdc(); + _dc.Dispose(); + _dc = null; } } - /// + /// /// Allows you to get the graphics object based off of the translated HDC. /// Note this will be disposed when the DCMapping object is disposed. - /// + /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public Graphics Graphics { - - - get { - Debug.Assert(this.dc != null, "unexpected null dc!"); + public Graphics Graphics + { + get + { + Debug.Assert(_dc != null, "unexpected null dc!"); - if (this.graphics == null) { - this.graphics = Graphics.FromHdcInternal(dc.Hdc); - this.graphics.SetClip(new Rectangle(Point.Empty, translatedBounds.Size)); + if (_graphics == null) + { + _graphics = Graphics.FromHdcInternal(_dc.Hdc); + _graphics.SetClip(new Rectangle(Point.Empty, _translatedBounds.Size)); } - return this.graphics; + + return _graphics; } } } - } + } } - - - diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/control.ime.cs b/src/System.Windows.Forms/src/System/Windows/Forms/control.ime.cs index 8fbf9c16a1a..c8d8f6ee32c 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/control.ime.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/control.ime.cs @@ -19,7 +19,6 @@ namespace System.Windows.Forms { using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; - using System.Security.Permissions; using System.Security; using System.IO; using System.Reflection; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/formatter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/formatter.cs index 07c8139fad9..b18abba5fa0 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/formatter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/formatter.cs @@ -9,7 +9,6 @@ namespace System.Windows.Forms using System.Globalization; using System.Reflection; using System.Security; - using System.Security.Permissions; internal class Formatter { diff --git a/src/System.Windows.Forms/src/misc/AccessibilityImprovements.cs b/src/System.Windows.Forms/src/misc/AccessibilityImprovements.cs deleted file mode 100644 index 8427bea2e7c..00000000000 --- a/src/System.Windows.Forms/src/misc/AccessibilityImprovements.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System { - using System; -#if DRAWINGDESIGN_NAMESPACE - using System.Drawing.Design; -#elif WINFORMS_NAMESPACE - using System.Windows.Forms; -#endif - using System.Runtime.CompilerServices; - - /// - /// This class maps accessibility quirks set in the app.config file or based on the target framework moniker - /// to accessibility levels that are referenced in the source code. - /// - internal static class AccessibilityImprovements { - private static bool levelsValidated; - private static int useLegacyAccessibilityFeatures; - private static int useLegacyAccessibilityFeatures2; - private static int useLegacyAccessibilityFeatures3; - - private static int useLegacyToolTipDisplayBehavior; - - // We assume that accessibility quirks have the same names in different assemblies. - internal const string UseLegacyAccessibilityFeaturesSwitchName = @"Switch.UseLegacyAccessibilityFeatures"; - internal const string UseLegacyAccessibilityFeatures2SwitchName = @"Switch.UseLegacyAccessibilityFeatures.2"; - internal const string UseLegacyAccessibilityFeatures3SwitchName = @"Switch.UseLegacyAccessibilityFeatures.3"; - - internal const string UseLegacyToolTipDisplaySwitchName = @"Switch.System.Windows.Forms.UseLegacyToolTipDisplay"; - - /// - /// False - opt-out of the accessibility improvements introduced in 4.7.1. - /// This is the case of application that target .NET frameworks below 4.7.1 or - /// applications that target 4.7.1 and above and have the following - /// - /// in the section in the app.config file. - /// - /// True - opt-in into the accessibility improvements introduced in 4.7.1. - /// - internal static bool Level1 { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { - if (useLegacyAccessibilityFeatures < 0) return true; - if (useLegacyAccessibilityFeatures > 0) return false; - ValidateLevels(); - - return (useLegacyAccessibilityFeatures < 0); - } - } - - /// - /// Opt in or out of the accessibility improvements introduced in .NET Framework versions 4.7.2 and 4.7.1. - /// - internal static bool Level2 { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { - if (useLegacyAccessibilityFeatures2 < 0) return true; - if (useLegacyAccessibilityFeatures2 > 0) return false; - ValidateLevels(); - - return (useLegacyAccessibilityFeatures2 < 0); - } - } - - /// - /// Opt in or out of the accessibility improvements introduced in .NET Framework version 4.7.3. - /// - internal static bool Level3 { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { - if (useLegacyAccessibilityFeatures3 < 0) return true; - if (useLegacyAccessibilityFeatures3 > 0) return false; - ValidateLevels(); - - return (useLegacyAccessibilityFeatures3 < 0); - } - } - - /// - /// Opt in or out of the keyboard tooltips triggering - /// - internal static bool UseLegacyToolTipDisplay { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { - if (useLegacyToolTipDisplayBehavior > 0) return true; - if (useLegacyToolTipDisplayBehavior < 0) return false; - ValidateLevels(); - - return (useLegacyToolTipDisplayBehavior > 0); - } - } - - internal static void ValidateLevels() { - if (levelsValidated) { - return; - } - - // Level[N+1] accessibility improvements are building upon the infrastructure introduced in Level[N], - // thus the application has to opt-in into Level[N] level in order to get the Level[N+1] level of support. - Tuple>[] levelNamesAndSetters = { - Tuple.Create>(UseLegacyAccessibilityFeaturesSwitchName, (switchValue) => useLegacyAccessibilityFeatures = switchValue), - Tuple.Create>(UseLegacyAccessibilityFeatures2SwitchName, (switchValue) => useLegacyAccessibilityFeatures2 = switchValue), - Tuple.Create>(UseLegacyAccessibilityFeatures3SwitchName, (switchValue) => useLegacyAccessibilityFeatures3 = switchValue) - }; - bool higherLevelsAreExpectedToBeDisabled = false; - bool invalidSwitchesCombination = false; - bool[] levelState = new bool[levelNamesAndSetters.Length]; - for (int i = 0; i < levelNamesAndSetters.Length; i++) { - string levelName = levelNamesAndSetters[i].Item1; - Action setLevelSwitchValue = levelNamesAndSetters[i].Item2; - - int levelSwitchValue = 0; - bool levelIsDisabled = LocalAppContext.GetCachedSwitchValue(levelName, ref levelSwitchValue); - - if (levelIsDisabled) { - higherLevelsAreExpectedToBeDisabled = true; - } - else if (higherLevelsAreExpectedToBeDisabled) { - invalidSwitchesCombination = true; - } - - setLevelSwitchValue(levelSwitchValue); - - levelState[i] = levelIsDisabled; - } - - if (invalidSwitchesCombination) { -#if DEPLOYMENT_NAMESPACE - throw new NotSupportedException(System.Deployment.Application.Resources.GetString("CombinationOfAccessibilitySwitchesNotSupported")); -#else - throw new NotSupportedException(SR.CombinationOfAccessibilitySwitchesNotSupported); -#endif - } - - // Get other improvements values - bool useLegacyToolTipDisplay = LocalAppContext.GetCachedSwitchValue(UseLegacyToolTipDisplaySwitchName, ref useLegacyToolTipDisplayBehavior); - - // If new ToolTip display behavior is enabled, Level3 should be enabled - if (!useLegacyToolTipDisplay && levelState[2]) { -#if DEPLOYMENT_NAMESPACE - throw new NotSupportedException(System.Deployment.Application.Resources.GetString("KeyboardToolTipDisplayBehaviorRequiresAccessibilityImprovementsLevel3")); -#else - throw new NotSupportedException(SR.KeyboardToolTipDisplayBehaviorRequiresAccessibilityImprovementsLevel3); -#endif - } - - // If this code is executed concurrently, in the worst case we'll throw the same exception on each thread. - levelsValidated = true; - } - } -} diff --git a/src/System.Windows.Forms/src/misc/DbgUtil.cs b/src/System.Windows.Forms/src/misc/DbgUtil.cs index 4cd00e680b1..e433848b2b3 100644 --- a/src/System.Windows.Forms/src/misc/DbgUtil.cs +++ b/src/System.Windows.Forms/src/misc/DbgUtil.cs @@ -18,7 +18,7 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke", Scope="member", Target="System.Windows.Forms.Internal.DbgUtil.GetLastErrorStr():System.String")] -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/ApplyGraphicsProperties.cs b/src/System.Windows.Forms/src/misc/GDI/ApplyGraphicsProperties.cs index 6d93e2f405e..ebdf90e9486 100644 --- a/src/System.Windows.Forms/src/misc/GDI/ApplyGraphicsProperties.cs +++ b/src/System.Windows.Forms/src/misc/GDI/ApplyGraphicsProperties.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceCapabilities.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceCapabilities.cs index aa2cb814645..628fe2228f9 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceCapabilities.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceCapabilities.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContext.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContext.cs index 87981430404..5307af3d851 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContext.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContext.cs @@ -5,7 +5,7 @@ // #define TRACK_HDC // #define GDI_FINALIZATION_WATCH -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContext2.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContext2.cs index 97364357dad..b9fe9ba5573 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContext2.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContext2.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextBackgroundMode.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextBackgroundMode.cs index e926dd78b2c..5a274ac21ee 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextBackgroundMode.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextBackgroundMode.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextGraphicsMode.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextGraphicsMode.cs index 0f01c0e02d3..6bcadbba5aa 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextGraphicsMode.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextGraphicsMode.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextLayout.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextLayout.cs index 6c197adae54..a5eac88fd81 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextLayout.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextLayout.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextMapMode.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextMapMode.cs index 45092145426..38be9362fd0 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextMapMode.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextMapMode.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextRasterOperationFlags.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextRasterOperationFlags.cs index 3b16493e685..50ad0adfa51 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextRasterOperationFlags.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextRasterOperationFlags.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextTextAlignment.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextTextAlignment.cs index 75e75054db4..da5e52d2348 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextTextAlignment.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextTextAlignment.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContextType.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContextType.cs index ad5fd1cbc98..ded83b9ed1b 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContextType.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContextType.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/DeviceContexts.cs b/src/System.Windows.Forms/src/misc/GDI/DeviceContexts.cs index 74c459f7a0f..8693f36b111 100644 --- a/src/System.Windows.Forms/src/misc/GDI/DeviceContexts.cs +++ b/src/System.Windows.Forms/src/misc/GDI/DeviceContexts.cs @@ -7,7 +7,7 @@ #define GDI_FONT_CACHE_TRACK #endif -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/FxCopSuppression.cs b/src/System.Windows.Forms/src/misc/GDI/FxCopSuppression.cs index 3e014b19790..442e219c215 100644 --- a/src/System.Windows.Forms/src/misc/GDI/FxCopSuppression.cs +++ b/src/System.Windows.Forms/src/misc/GDI/FxCopSuppression.cs @@ -11,7 +11,7 @@ using System.Diagnostics.CodeAnalysis; -#if WINFORMS_NAMESPACE ////////////////////////////////// FxCop suppressions for System.Windows.Forms.dll ////////////////////////////////// +#if DRAWING_DESIGN_NAMESPACE ////////////////////////////////// FxCop suppressions for System.Windows.Forms.dll ////////////////////////////////// //// SECURITY diff --git a/src/System.Windows.Forms/src/misc/GDI/GdiObjectType.cs b/src/System.Windows.Forms/src/misc/GDI/GdiObjectType.cs index 2f21f23fee9..46337c08f7a 100644 --- a/src/System.Windows.Forms/src/misc/GDI/GdiObjectType.cs +++ b/src/System.Windows.Forms/src/misc/GDI/GdiObjectType.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/MeasurementDCInfo.cs b/src/System.Windows.Forms/src/misc/GDI/MeasurementDCInfo.cs index a07cf072470..c88cadaa278 100644 --- a/src/System.Windows.Forms/src/misc/GDI/MeasurementDCInfo.cs +++ b/src/System.Windows.Forms/src/misc/GDI/MeasurementDCInfo.cs @@ -8,7 +8,7 @@ #define GDI_FONT_CACHE_TRACK #endif -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal { #elif DRAWING_NAMESPACE namespace System.Drawing.Internal { diff --git a/src/System.Windows.Forms/src/misc/GDI/NativeMethods.cs b/src/System.Windows.Forms/src/misc/GDI/NativeMethods.cs index 65f7b14d22e..7ac633db1cf 100644 --- a/src/System.Windows.Forms/src/misc/GDI/NativeMethods.cs +++ b/src/System.Windows.Forms/src/misc/GDI/NativeMethods.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal @@ -241,7 +241,7 @@ public override string ToString() [StructLayout(LayoutKind.Sequential)] public class DRAWTEXTPARAMS { - private int cbSize = Marshal.SizeOf(typeof(DRAWTEXTPARAMS)); + private int cbSize = Marshal.SizeOf(); public int iTabLength; public int iLeftMargin; public int iRightMargin; diff --git a/src/System.Windows.Forms/src/misc/GDI/SafeNativeMethods.cs b/src/System.Windows.Forms/src/misc/GDI/SafeNativeMethods.cs index 5b49efb829e..089d53bda25 100644 --- a/src/System.Windows.Forms/src/misc/GDI/SafeNativeMethods.cs +++ b/src/System.Windows.Forms/src/misc/GDI/SafeNativeMethods.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/TextFormatFlags.cs b/src/System.Windows.Forms/src/misc/GDI/TextFormatFlags.cs index e0123193e40..ad633cc3735 100644 --- a/src/System.Windows.Forms/src/misc/GDI/TextFormatFlags.cs +++ b/src/System.Windows.Forms/src/misc/GDI/TextFormatFlags.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/TextPaddingOptions.cs b/src/System.Windows.Forms/src/misc/GDI/TextPaddingOptions.cs index 94a419253da..d3e6ca7e660 100644 --- a/src/System.Windows.Forms/src/misc/GDI/TextPaddingOptions.cs +++ b/src/System.Windows.Forms/src/misc/GDI/TextPaddingOptions.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/UnsafeNativeMethods.cs b/src/System.Windows.Forms/src/misc/GDI/UnsafeNativeMethods.cs index e080dbef099..8cbc313c508 100644 --- a/src/System.Windows.Forms/src/misc/GDI/UnsafeNativeMethods.cs +++ b/src/System.Windows.Forms/src/misc/GDI/UnsafeNativeMethods.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal @@ -247,7 +247,7 @@ public static bool DeleteObject(HandleRef hObject) public static extern int IntGetObject(HandleRef hBrush, int nSize, [In, Out] IntNativeMethods.LOGBRUSH lb); public static int GetObject(HandleRef hBrush, IntNativeMethods.LOGBRUSH lb) { - int retVal = IntGetObject(hBrush, System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntNativeMethods.LOGBRUSH)), lb); + int retVal = IntGetObject(hBrush, System.Runtime.InteropServices.Marshal.SizeOf(), lb); DbgUtil.AssertWin32(retVal != 0, "GetObject(hObj=[0x{0:X8}], [LOGBRUSH]) failed.", hBrush.Handle); return retVal; } @@ -258,7 +258,7 @@ public static int GetObject(HandleRef hBrush, IntNativeMethods.LOGBRUSH lb) public static extern int IntGetObject(HandleRef hFont, int nSize, [In, Out] IntNativeMethods.LOGFONT lf); public static int GetObject(HandleRef hFont, IntNativeMethods.LOGFONT lp) { - int retVal = IntGetObject(hFont, System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntNativeMethods.LOGFONT)), lp); + int retVal = IntGetObject(hFont, System.Runtime.InteropServices.Marshal.SizeOf(), lp); DbgUtil.AssertWin32(retVal != 0, "GetObject(hObj=[0x{0:X8}], [LOGFONT]) failed.", hFont.Handle); return retVal; } diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsBrush.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsBrush.cs index 38d9e74937b..da55eda39f9 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsBrush.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsBrush.cs @@ -6,7 +6,7 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Windows.Forms.Internal.WindowsBrush.FromHdc(System.IntPtr):System.Windows.Forms.Internal.WindowsBrush")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Windows.Forms.Internal.WindowsBrush.FromBrush(System.Drawing.Brush):System.Windows.Forms.Internal.WindowsBrush")] -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsFont.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsFont.cs index 4ce2fc65e61..d975c2b45bc 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsFont.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsFont.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsFontQuality.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsFontQuality.cs index 4486d769f96..c3e1f9b5568 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsFontQuality.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsFontQuality.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics.cs index 1ad43b4895a..8790bf91f3c 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics.cs @@ -7,7 +7,7 @@ // THIS PARTIAL CLASS CONTAINS THE BASE METHODS FOR CREATING AND DISPOSING A WINDOWSGRAPHICS AS WELL // GETTING, DISPOSING AND WORKING WITH A DC. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics2.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics2.cs index f7b7f16891e..e995c9e03c2 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics2.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsGraphics2.cs @@ -5,7 +5,7 @@ // THIS PARTIAL CLASS CONTAINS THE BASE METHODS FOR DRAWING WITH A WINDOWSGRAPHICS. // (Compiled in System.Windows.Forms but not in System.Drawing). -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsGraphicsCacheManager.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsGraphicsCacheManager.cs index 025e0b9d461..8f070397c15 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsGraphicsCacheManager.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsGraphicsCacheManager.cs @@ -7,7 +7,7 @@ #define GDI_FONT_CACHE_TRACK #endif -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsPen.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsPen.cs index 9cd1e965353..d4472451a5c 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsPen.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsPen.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsPenStyle.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsPenStyle.cs index 916599fa8e2..226189763bc 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsPenStyle.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsPenStyle.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsRegion.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsRegion.cs index 5b467793230..fe16dbf7354 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsRegion.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsRegion.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsRegionCombineMode.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsRegionCombineMode.cs index 7f675ed22bd..7a74315d6a8 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsRegionCombineMode.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsRegionCombineMode.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/GDI/WindowsSolidBrush.cs b/src/System.Windows.Forms/src/misc/GDI/WindowsSolidBrush.cs index 48e331b89ab..c0157bb8b8a 100644 --- a/src/System.Windows.Forms/src/misc/GDI/WindowsSolidBrush.cs +++ b/src/System.Windows.Forms/src/misc/GDI/WindowsSolidBrush.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if WINFORMS_NAMESPACE +#if DRAWING_DESIGN_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal diff --git a/src/System.Windows.Forms/src/misc/WeakHashtable.cs b/src/System.Windows.Forms/src/misc/WeakHashtable.cs index e64e62ec50f..061870c50b7 100644 --- a/src/System.Windows.Forms/src/misc/WeakHashtable.cs +++ b/src/System.Windows.Forms/src/misc/WeakHashtable.cs @@ -6,14 +6,12 @@ namespace System.ComponentModel { using System; using System.Collections; - using System.Security.Permissions; /// /// This is a hashtable that stores object keys as weak references. /// It monitors memory usage and will periodically scavenge the /// hash table to clean out dead references. /// - [HostProtection(SharedState = true)] internal sealed class WeakHashtable : Hashtable { private static IEqualityComparer _comparer = new WeakKeyComparer(); diff --git a/src/System.Windows.Forms/tests/Common/TestHelper.cs b/src/System.Windows.Forms/tests/Common/TestHelper.cs deleted file mode 100644 index 1cf28fe5ad0..00000000000 --- a/src/System.Windows.Forms/tests/Common/TestHelper.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Xunit; - -namespace Winforms.Common.TestHelper -{ - internal static class UtilityMethods - { - // helper method to generate theory data from all values of an enum type - internal static TheoryData GetEnumTheoryData() where T : Enum - { - var data = new TheoryData(); - foreach (T item in Enum.GetValues(typeof(T))) - data.Add(item); - return data; - } - - // helper method to generate invalid theory data for an enum type - // This method assumes that int.MinValue and int.MaxValue are not in the enum - internal static TheoryData GetEnumTheoryDataInvalid() where T : Enum - { - var data = new TheoryData(); - // This boxing is necessary because you can't cast an int to a generic, - // even if the generic is guaranteed to be an enum - data.Add((T)(object)int.MinValue); - data.Add((T)(object)int.MaxValue); - return data; - } - - #region Primitives - - // helper method to generate theory data for all values of a boolean - internal static TheoryData GetBoolTheoryData() - { - var data = new TheoryData(); - data.Add(true); - data.Add(false); - return data; - } - - // helper method to generate theory data for some values of a int - internal static TheoryData GetIntTheoryData() - { - var data = new TheoryData(); - data.Add(int.MinValue); - data.Add(int.MaxValue); - data.Add(0); - data.Add(1); - data.Add(-1); - data.Add(int.MaxValue / 2); - return data; - } - - // helper method to generate theory data for some values of a int - internal static TheoryData GetUIntTheoryData() - { - var data = new TheoryData(); - data.Add(int.MaxValue); - data.Add(0); - data.Add(1); - data.Add(int.MaxValue / 2); - return data; - } - - // helper method to generate theory data for some values of a int - internal static TheoryData GetNIntTheoryData() - { - var data = new TheoryData(); - data.Add(int.MinValue); - data.Add(-1); - data.Add(int.MinValue / 2); - return data; - } - - // helper method to generate theory data for some values of a int - internal static TheoryData GetFloatTheoryData() - { - var data = new TheoryData(); - data.Add(float.MaxValue); - data.Add(float.MinValue); - data.Add(Single.Epsilon); - data.Add(Single.Epsilon * -1); - data.Add(Single.NegativeInfinity); // not sure about these two - data.Add(Single.PositiveInfinity); // 2 - data.Add(0); - data.Add(-1); - data.Add(1); - data.Add(float.MaxValue / 2); - return data; - } - - // helper method to generate theory data for some values of a int - internal static TheoryData GetUFloatTheoryData() - { - var data = new TheoryData(); - data.Add(float.MaxValue); - data.Add(Single.Epsilon); - data.Add(Single.PositiveInfinity); // not sure about this one - data.Add(0); - data.Add(1); - data.Add(float.MaxValue / 2); - return data; - } - - // helper method to generate theory data for a span of string values - internal static TheoryData GetStringTheoryData() - { - var data = new TheoryData(); - data.Add(string.Empty); - data.Add("reasonable"); - return data; - } - - #endregion - } -} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/System.Windows.Forms.IntegrationTests/System.Windows.Forms.IntegrationTests.csproj b/src/System.Windows.Forms/tests/IntegrationTests/System.Windows.Forms.IntegrationTests/System.Windows.Forms.IntegrationTests.csproj index 200a0387d28..79005648560 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/System.Windows.Forms.IntegrationTests/System.Windows.Forms.IntegrationTests.csproj +++ b/src/System.Windows.Forms/tests/IntegrationTests/System.Windows.Forms.IntegrationTests/System.Windows.Forms.IntegrationTests.csproj @@ -2,7 +2,6 @@ netcoreapp3.0 - false diff --git a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/ScalingBeforeChanges.cs b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/ScalingBeforeChanges.cs index 4c2d5724d95..20a59981f1f 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/ScalingBeforeChanges.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/ScalingBeforeChanges.cs @@ -41,8 +41,6 @@ public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter [DllImport("user32", EntryPoint = "#2704")] internal static extern bool EnableChildWindowDpiMessage(HandleRef hWnd, bool fEnable); - internal const int WM_DPICHANGED = 0x02E0; - internal const double LogicalDpi = 96.0; internal const int LOGPIXELSX = 88; internal const int LOGPIXELSY = 90; @@ -96,12 +94,12 @@ protected override void WndProc(ref Message m) base.WndProc(ref m); switch (m.Msg) { - case WM_DPICHANGED: + case Interop.WindowMessages.WM_DPICHANGED: int x = LOWORD(m.WParam); int y = HIWORD(m.WParam); if (x != deviceDpiX || y != deviceDpiY) { - RECT suggestedRect = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); + RECT suggestedRect = Marshal.PtrToStructure(m.LParam); SetWindowPos(new HandleRef(this, Handle), new HandleRef(null, IntPtr.Zero), suggestedRect.left, suggestedRect.top, suggestedRect.right - suggestedRect.left, suggestedRect.bottom - suggestedRect.top, 0x4 | 0x10); @@ -124,9 +122,6 @@ protected override void WndProc(ref Message m) public class MyCheckBox : CheckBox { - internal const int WM_DPICHANGED_BEFOREPARENT = 0x02E2; - internal const int WM_DPICHANGED_AFTERPARENT = 0x02E3; - [DllImport("User32", ExactSpelling = true, SetLastError = true)] public static extern uint GetDpiForWindow(HandleRef hWnd); @@ -139,13 +134,13 @@ protected override void WndProc(ref Message m) uint dpi; switch (m.Msg) { - case WM_DPICHANGED_BEFOREPARENT: + case Interop.WindowMessages.WM_DPICHANGED_BEFOREPARENT: dpi = GetDpiForWindow(new HandleRef(this, Handle)); Debug.WriteLine($"WM_DPICHANGED_BEFOREPARENT {dpi}"); m.Result = (IntPtr)1; break; - case WM_DPICHANGED_AFTERPARENT: + case Interop.WindowMessages.WM_DPICHANGED_AFTERPARENT: dpi = GetDpiForWindow(new HandleRef(this, Handle)); Debug.WriteLine($"WM_DPICHANGED_AFTERPARENT {dpi}"); m.Result = (IntPtr)1; diff --git a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/WinformsControlsTest.csproj b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/WinformsControlsTest.csproj index f9ec74cb295..d99628bb115 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/WinformsControlsTest.csproj +++ b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/WinformsControlsTest.csproj @@ -71,6 +71,10 @@ + + + + WinformsControlsTest.SmallA.bmp diff --git a/src/System.Windows.Forms/tests/UnitTests/AccessibleObjects/DataGridViewCellAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/UnitTests/AccessibleObjects/DataGridViewCellAccessibleObjectTests.cs new file mode 100644 index 00000000000..3369dd4e79c --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/AccessibleObjects/DataGridViewCellAccessibleObjectTests.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Threading; +using Xunit; + +namespace System.Windows.Forms.Tests.AccessibleObjects +{ + public class DataGridViewCellsAccessibleObjectTests + { + [Theory] + [InlineData(RightToLeft.No)] + [InlineData(RightToLeft.Yes)] + public void DataGridViewCellsAccessibleObject_Ctor_Default(RightToLeft rightToLeft) + { + DataGridView dataGridView = new DataGridView(); + + dataGridView.RightToLeft = rightToLeft; + dataGridView.ColumnCount = 4; + dataGridView.Width = 85; + + dataGridView.Columns[0].Width = 40; + dataGridView.Columns[1].Width = 40; + dataGridView.Columns[2].Width = 40; + dataGridView.Columns[3].Width = 40; + + AccessibleObject rr = dataGridView.AccessibilityObject; //it is necessary to be in time to initialize elements + + var accCellWidthSum = 0; + for(int i = 0; i < 4; i++) + { + accCellWidthSum += dataGridView.Rows[0].Cells[i].AccessibilityObject.BoundingRectangle.Width; + } + var accRowWidth = dataGridView.Rows[0].AccessibilityObject.BoundingRectangle.Width; + + Assert.True(accCellWidthSum == accRowWidth - dataGridView.RowHeadersWidth); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/AccessibleObjects/DataGridViewRowsAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/UnitTests/AccessibleObjects/DataGridViewRowsAccessibleObjectTests.cs new file mode 100644 index 00000000000..c4c9cc75730 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/AccessibleObjects/DataGridViewRowsAccessibleObjectTests.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Windows.Forms.Tests.AccessibleObjects +{ + public class DataGridViewRowsAccessibleObjectTests + { + [Fact] + public void DataGridViewRowsAccessibleObject_Ctor_Default() + { + DataGridView dataGridView = new DataGridView(); + + dataGridView.RowCount = 5; + dataGridView.Height = 87; + + dataGridView.Rows[0].Height = 20; + dataGridView.Rows[1].Height = 20; + dataGridView.Rows[2].Height = 20; + dataGridView.Rows[3].Height = 20; + dataGridView.Rows[4].Height = 20; + + AccessibleObject accObject = dataGridView.AccessibilityObject; //it is necessary to be in time to initialize elements + + int accRowHeightSum = 0; + for (int i = 0; i < 5; i++) + { + accRowHeightSum += dataGridView.Rows[i].AccessibilityObject.BoundingRectangle.Height; + } + int accDataGridViewHeight = dataGridView.AccessibilityObject.BoundingRectangle.Height; + int borders = 2 * dataGridView.BorderWidth; //top border and bottom border + + Assert.True(accRowHeightSum == accDataGridViewHeight - borders - dataGridView.ColumnHeadersHeight); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/CheckedListBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/CheckedListBoxTests.cs index e8d69e1d666..d271223cdba 100644 --- a/src/System.Windows.Forms/tests/UnitTests/CheckedListBoxTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/CheckedListBoxTests.cs @@ -154,39 +154,19 @@ public void CheckedListBox_ValueMember(string expected) Assert.Equal(expected, box.ValueMember); } - /// - /// Data for the Padding test - /// - public static TheoryData PaddingData => - TestHelper.GetPaddingTheoryData(); - [Theory] - [MemberData(nameof(PaddingData))] - public void CheckedListBox_Padding(Padding expected) + [CommonMemberData(nameof(CommonTestHelper.GetPaddingNormalizedTheoryData))] + public void CheckedListBox_Padding_Set_GetReturnsExpected(Padding value, Padding expected) { - var box = new CheckedListBox(); - - box.Padding = expected; - + var box = new CheckedListBox + { + Padding = value + }; Assert.Equal(expected, box.Padding); - } - - /// - /// Data for the PaddingInvalid test - /// - public static TheoryData PaddingDataInvalid => - TestHelper.GetPaddingTheoryDataInvalid(); - - [Theory] - [MemberData(nameof(PaddingDataInvalid))] - public void CheckedListBox_PaddingInvalid(Padding attempted) - { - var box = new CheckedListBox(); - box.Padding = attempted; - - Assert.NotEqual(attempted, box.Padding); //paddings cannot be negative - Assert.Equal(new Padding(), box.Padding); + // Set same. + box.Padding = value; + Assert.Equal(expected, box.Padding); } [Theory] diff --git a/src/System.Windows.Forms/tests/UnitTests/ContainerControlTests.cs b/src/System.Windows.Forms/tests/UnitTests/ContainerControlTests.cs deleted file mode 100644 index b4647b7876f..00000000000 --- a/src/System.Windows.Forms/tests/UnitTests/ContainerControlTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Xunit; -using System.Drawing; -using WinForms.Common.Tests; - -namespace System.Windows.Forms.Tests -{ - public class ContainerControlTests - { - /// - /// Data for the AutoScaleBaseSize test - /// - public static TheoryData AutoScaleBaseSizeData => - TestHelper.GetSizeTheoryData(); - - [Theory] - [MemberData(nameof(AutoScaleBaseSizeData))] - public void ContainerControl_AutoScaleBaseSize(System.Drawing.Size expected) - { - var contCont = new ContainerControl(); - - if (expected.Width < 0 || expected.Height < 0) - { - Assert.Throws(() => contCont.AutoScaleDimensions = expected); - } - else - { - contCont.AutoScaleDimensions = expected; - var actual = contCont.AutoScaleDimensions; - - Assert.Equal(expected, actual); - } - - } - - } -} diff --git a/src/System.Windows.Forms/tests/UnitTests/ContextMenuTests.cs b/src/System.Windows.Forms/tests/UnitTests/ContextMenuTests.cs index fac547d3df0..45a7f83e1cd 100644 --- a/src/System.Windows.Forms/tests/UnitTests/ContextMenuTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/ContextMenuTests.cs @@ -80,9 +80,7 @@ public void ContextMenu_SourceControl_GetProcessingKeyMessage_Succes() } [Theory] - [InlineData(RightToLeft.Yes, RightToLeft.Yes)] - [InlineData(RightToLeft.No, RightToLeft.No)] - [InlineData(RightToLeft.Inherit, RightToLeft.No)] + [CommonMemberData(nameof(CommonTestHelper.GetRightToLeftTheoryData))] public void ContextMenu_RightToLeft_SetWithoutSourceControl_GetReturnsExpected(RightToLeft value, RightToLeft expectedValue) { var menu = new ContextMenu diff --git a/src/System.Windows.Forms/tests/UnitTests/DomainUpDownTests.cs b/src/System.Windows.Forms/tests/UnitTests/DomainUpDownTests.cs index 3ed3a1d61f8..cf958622291 100644 --- a/src/System.Windows.Forms/tests/UnitTests/DomainUpDownTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/DomainUpDownTests.cs @@ -35,12 +35,8 @@ public void DomainUpDown_SelectedIndexGetSet(int indexToSet, int indexAfterSet, [Fact] public void DomainUpDown_SelectedIndex_ArgumentOutOfRangeException() { - var underTest = GetNewDomainUpDown(); - var index = 3100; - var paramName = "SelectedIndex"; - var ex = Assert.Throws(() => underTest.SelectedIndex = index); - Assert.Equal(paramName, ex.ParamName); - Assert.Contains($"Value of '{index}' is not valid for '{paramName}'.{Environment.NewLine}Parameter name: {paramName}", ex.Message); + var upDown = GetNewDomainUpDown(); + Assert.Throws(() => upDown.SelectedIndex = 3100); } [Fact] diff --git a/src/System.Windows.Forms/tests/UnitTests/DpiHelperTests.cs b/src/System.Windows.Forms/tests/UnitTests/DpiHelperTests.cs index 42f92326ffa..b595acc14fc 100644 --- a/src/System.Windows.Forms/tests/UnitTests/DpiHelperTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/DpiHelperTests.cs @@ -26,14 +26,8 @@ public void DpiHelper_LogicalToDeviceUnits(int value) Assert.Equal(expected, DpiHelper.LogicalToDeviceUnits(value)); } - /// - /// Data for the LogicalToDeviceUnitsSize test - /// - public static TheoryData LogicalToDeviceUnitsSizeData => - TestHelper.GetSizeTheoryData(); - [Theory] - [MemberData(nameof(LogicalToDeviceUnitsSizeData))] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] public void DpiHelper_LogicalToDeviceUnitsSize(Size value) { var expected = new Size ((int)Math.Round(value.Width * (DpiHelper.DeviceDpi / DpiHelper.LogicalDpi)), diff --git a/src/System.Windows.Forms/tests/UnitTests/ListBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/ListBoxTests.cs deleted file mode 100644 index 416e0f78549..00000000000 --- a/src/System.Windows.Forms/tests/UnitTests/ListBoxTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.ComponentModel; -using Moq; -using Xunit; - -namespace System.Windows.Forms.Tests -{ - public class ListBoxTests - { - [Fact] - public void ListBox_Constructor() - { - var lb = new ListBox(); - - Assert.NotNull(lb); - Assert.Equal(0, lb.Location.X); - Assert.Equal(0, lb.Location.Y); - Assert.Equal(120, lb.Width); - Assert.Equal(96, lb.Height); - } - } -} diff --git a/src/System.Windows.Forms/tests/UnitTests/MenuItemTests.cs b/src/System.Windows.Forms/tests/UnitTests/MenuItemTests.cs index 3cff9f5bbed..8866a5ff43d 100644 --- a/src/System.Windows.Forms/tests/UnitTests/MenuItemTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/MenuItemTests.cs @@ -367,7 +367,7 @@ public void MenuItem_Checked_SetWithMainMenuParent_ThrowsArgumentException() { var menuItem = new MenuItem(); var menu = new MainMenu(new MenuItem[] { menuItem }); - Assert.Throws(null, () => menuItem.Checked = true); + Assert.Throws("value", () => menuItem.Checked = true); Assert.False(menuItem.Checked); menuItem.Checked = false; @@ -378,7 +378,7 @@ public void MenuItem_Checked_SetWithMainMenuParent_ThrowsArgumentException() public void MenuItem_Checked_SetWithChildren_ThrowsArgumentException() { var menuItem = new MenuItem("text", new MenuItem[] { new MenuItem() }); - Assert.Throws(null, () => menuItem.Checked = true); + Assert.Throws("value", () => menuItem.Checked = true); Assert.False(menuItem.Checked); menuItem.Checked = false; @@ -481,7 +481,7 @@ public void MenuItem_Index_SetInvalid_ThrowsArgumentOutOfRangeException(int valu { var menuItem = new MenuItem(); var menu = new SubMenu(new MenuItem[] { menuItem }); - Assert.Throws("Index", () => menuItem.Index = value); + Assert.Throws("value", () => menuItem.Index = value); } [Theory] diff --git a/src/System.Windows.Forms/tests/UnitTests/System.Windows.Forms.Tests.csproj b/src/System.Windows.Forms/tests/UnitTests/System.Windows.Forms.Tests.csproj index f8cbe2f2050..0c3236df43b 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System.Windows.Forms.Tests.csproj +++ b/src/System.Windows.Forms/tests/UnitTests/System.Windows.Forms.Tests.csproj @@ -14,9 +14,12 @@ + + + + - diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AmbientPropertiesTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AmbientPropertiesTests.cs index f29029812c7..bb226422b2f 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AmbientPropertiesTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AmbientPropertiesTests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Drawing; +using WinForms.Common.Tests; using Xunit; namespace System.Windows.Forms.Tests @@ -19,45 +20,64 @@ public void Ctor_Default() Assert.Equal(Color.Empty, property.ForeColor); } - [Fact] - public void BackColor_Set_GetReturnsExpected() + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetColorTheoryData))] + public void BackColor_Set_GetReturnsExpected(Color value) { var property = new AmbientProperties { - BackColor = Color.Red + BackColor = value }; - Assert.Equal(Color.Red, property.BackColor); + Assert.Equal(value, property.BackColor); + + // Set same. + property.BackColor = value; + Assert.Equal(value, property.BackColor); } - [Fact] - public void Cursor_Set_GetReturnsExpected() + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetCursorTheoryData))] + public void Cursor_Set_GetReturnsExpected(Cursor value) { - var cursor = new Cursor((IntPtr)1); var property = new AmbientProperties { - Cursor = cursor + Cursor = value }; - Assert.Equal(cursor, property.Cursor); + Assert.Equal(value, property.Cursor); + + // Set same. + property.Cursor = value; + Assert.Equal(value, property.Cursor); } - [Fact] - public void Font_Set_GetReturnsExpected() + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void Font_Set_GetReturnsExpected(Font value) { var property = new AmbientProperties { - Font = SystemFonts.DefaultFont + Font = value }; - Assert.Equal(SystemFonts.DefaultFont, property.Font); + Assert.Equal(value, property.Font); + + // Set same. + property.Font = value; + Assert.Equal(value, property.Font); } - [Fact] - public void ForeColor_Set_GetReturnsExpected() + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetColorTheoryData))] + public void ForeColor_Set_GetReturnsExpected(Color value) { var property = new AmbientProperties { - ForeColor = Color.Red + ForeColor = value }; - Assert.Equal(Color.Red, property.ForeColor); + Assert.Equal(value, property.ForeColor); + + // Set same. + property.ForeColor = value; + Assert.Equal(value, property.ForeColor); } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/BindingContextTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/BindingContextTests.cs new file mode 100644 index 00000000000..2d9273201bc --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/BindingContextTests.cs @@ -0,0 +1,1025 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using Moq; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class BindingContextTests + { + [Fact] + public void BindingContext_Ctor_Default() + { + var context = new BindingContext(); + Assert.False(context.IsReadOnly); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_ICollection_GetProperties_ReturnsExpected() + { + ICollection context = new BindingContext(); + Assert.False(context.IsSynchronized); + Assert.Null(context.SyncRoot); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_Count_GetWithNullWeakReferenceTarget_ScrubsWeakRefs() + { + var context = new BindingContext(); + var dataSource1 = new DataSource { Property = 1 }; + var dataSource2 = new DataSource { Property = 2 }; + PropertyManager manager1 = Assert.IsAssignableFrom(context[dataSource1, "Property"]); + PropertyManager manager2 = Assert.IsAssignableFrom(context[dataSource2, "Property"]); + var array = new DictionaryEntry[4]; + ((ICollection)context).CopyTo(array, 0); + + WeakReference reference1 = Assert.IsType(array.Single(p => ((WeakReference)p.Value).Target == manager1).Value); + WeakReference reference2 = Assert.IsType(array.Single(p => ((WeakReference)p.Value).Target == manager2).Value); + Assert.Same(manager1, reference1.Target); + Assert.Same(manager2, reference2.Target); + + // Simulate a GC by assigning the weak reference to null. + reference1.Target = null; + reference2.Target = null; + + // Verify these weak references have been scrubbed. + Assert.Equal(2, ((ICollection)context).Count); + } + + [Fact] + public void BindingContext_Add_NullDataSource_ThrowsArgumentNullException() + { + var context = new BindingContext(); + var source = new BindingSource(); + Assert.Throws("dataSource", () => context.Add(null, source.CurrencyManager)); + } + + [Fact] + public void BindingContext_Add_Invoke_GetReturnsExpected() + { + var context = new BindingContext(); + var source1 = new BindingSource(); + var source2 = new BindingSource(); + var dataSource = new DataSource(); + context.Add(dataSource, source1.CurrencyManager); + Assert.Single(context); + + Assert.Same(source1.CurrencyManager, context[dataSource]); + Assert.Same(source1.CurrencyManager, context[dataSource, null]); + Assert.Same(source1.CurrencyManager, context[dataSource, string.Empty]); + + // Set new value. + context.Add(dataSource, source2.CurrencyManager); + Assert.Single(context); + Assert.Same(source2.CurrencyManager, context[dataSource]); + Assert.Same(source2.CurrencyManager, context[dataSource, null]); + Assert.Same(source2.CurrencyManager, context[dataSource, string.Empty]); + } + + [Fact] + public void BindingContext_Add_InvokeMultiple_Success() + { + var context = new BindingContext(); + var source1 = new BindingSource(); + var source2 = new BindingSource(); + var dataSource1 = new DataSource(); + var dataSource2 = new DataSource(); + context.Add(dataSource1, source1.CurrencyManager); + context.Add(dataSource2, source2.CurrencyManager); + Assert.Equal(2, ((ICollection)context).Count); + + Assert.Same(source1.CurrencyManager, context[dataSource1]); + Assert.Same(source2.CurrencyManager, context[dataSource2]); + } + + [Fact] + public void BindingContext_Add_NullListManager_ThrowsArgumentNullException() + { + var context = new BindingContext(); + Assert.Throws("listManager", () => context.Add(1, null)); + } + + [Fact] + public void BindingContext_AddCore_Invoke_GetReturnsExpected() + { + var context = new SubBindingContext(); + var source1 = new BindingSource(); + var source2 = new BindingSource(); + var dataSource = new DataSource(); + context.AddCore(dataSource, source1.CurrencyManager); + Assert.Single(context); + + Assert.Same(source1.CurrencyManager, context[dataSource]); + Assert.Same(source1.CurrencyManager, context[dataSource, null]); + Assert.Same(source1.CurrencyManager, context[dataSource, string.Empty]); + + // Set new value. + context.AddCore(dataSource, source2.CurrencyManager); + Assert.Single(context); + Assert.Same(source2.CurrencyManager, context[dataSource]); + Assert.Same(source2.CurrencyManager, context[dataSource, null]); + Assert.Same(source2.CurrencyManager, context[dataSource, string.Empty]); + } + + [Fact] + public void BindingContext_AddCore_InvokeMultiple_Success() + { + var context = new SubBindingContext(); + var source1 = new BindingSource(); + var source2 = new BindingSource(); + var dataSource1 = new DataSource(); + var dataSource2 = new DataSource(); + context.AddCore(dataSource1, source1.CurrencyManager); + context.AddCore(dataSource2, source2.CurrencyManager); + Assert.Equal(2, ((ICollection)context).Count); + + Assert.Same(source1.CurrencyManager, context[dataSource1]); + Assert.Same(source2.CurrencyManager, context[dataSource2]); + } + + [Fact] + public void BindingContext_AddCore_NullDataSource_ThrowsArgumentNullException() + { + var context = new SubBindingContext(); + var source = new BindingSource(); + Assert.Throws("dataSource", () => context.AddCore(null, source.CurrencyManager)); + } + + [Fact] + public void BindingContext_AddCore_NullListManager_ThrowsArgumentNullException() + { + var context = new SubBindingContext(); + Assert.Throws("listManager", () => context.AddCore(1, null)); + } + + [Fact] + public void BindingContext_CopyTo_Invoke_Success() + { + var context = new BindingContext(); + var source = new BindingSource(); + var dataSource = new DataSource(); + context.Add(dataSource, source.CurrencyManager); + + var array = new object[] { 1, 2, 3 }; + ((ICollection)context).CopyTo(array, 1); + Assert.Equal(1, array[0]); + Assert.NotNull(Assert.IsType(array[1]).Key); + Assert.Equal(source.CurrencyManager, Assert.IsType(Assert.IsType(array[1]).Value).Target); + Assert.Equal(3, array[2]); + } + + [Fact] + public void BindingContext_CopyTo_WithNullWeakReferenceTarget_ScrubsWeakRefs() + { + var context = new BindingContext(); + var dataSource1 = new DataSource { Property = 1 }; + var dataSource2 = new DataSource { Property = 2 }; + PropertyManager manager1 = Assert.IsAssignableFrom(context[dataSource1, "Property"]); + PropertyManager manager2 = Assert.IsAssignableFrom(context[dataSource2, "Property"]); + var array = new DictionaryEntry[4]; + ((ICollection)context).CopyTo(array, 0); + + WeakReference reference1 = Assert.IsType(array.Single(p => ((WeakReference)p.Value).Target == manager1).Value); + WeakReference reference2 = Assert.IsType(array.Single(p => ((WeakReference)p.Value).Target == manager2).Value); + Assert.Same(manager1, reference1.Target); + Assert.Same(manager2, reference2.Target); + + // Simulate a GC by assigning the weak reference to null. + reference1.Target = null; + reference2.Target = null; + + // Verify these weak references have been scrubbed. + var destArray = new object[] { 1, 2, 3, 4 }; + ((ICollection)context).CopyTo(destArray, 1); + Assert.Equal(1, destArray[0]); + Assert.IsType(destArray[1]); + Assert.IsType(destArray[2]); + Assert.Equal(4, destArray[3]); + } + + [Fact] + public void BindingContext_GetEnumerator_WithNullWeakReferenceTarget_ScrubsWeakRefs() + { + var context = new BindingContext(); + var dataSource1 = new DataSource { Property = 1 }; + var dataSource2 = new DataSource { Property = 2 }; + PropertyManager manager1 = Assert.IsAssignableFrom(context[dataSource1, "Property"]); + PropertyManager manager2 = Assert.IsAssignableFrom(context[dataSource2, "Property"]); + var array = new DictionaryEntry[4]; + ((ICollection)context).CopyTo(array, 0); + + WeakReference reference1 = Assert.IsType(array.Single(p => ((WeakReference)p.Value).Target == manager1).Value); + WeakReference reference2 = Assert.IsType(array.Single(p => ((WeakReference)p.Value).Target == manager2).Value); + Assert.Same(manager1, reference1.Target); + Assert.Same(manager2, reference2.Target); + + // Simulate a GC by assigning the weak reference to null. + reference1.Target = null; + reference2.Target = null; + + // Verify these weak references have been scrubbed. + IEnumerator enumerator = ((ICollection)context).GetEnumerator(); + Assert.True(enumerator.MoveNext()); + Assert.IsType(enumerator.Current); + Assert.True(enumerator.MoveNext()); + Assert.IsType(enumerator.Current); + Assert.False(enumerator.MoveNext()); + } + + [Fact] + public void BindingContext_Remove_Invoke_Success() + { + var context = new BindingContext(); + var source1 = new BindingSource(); + var dataSource1 = new DataSource(); + var source2 = new BindingSource(); + var dataSource2 = new DataSource(); + context.Add(dataSource1, source1.CurrencyManager); + context.Add(dataSource2, source2.CurrencyManager); + + context.Remove(dataSource1); + Assert.Single(context); + + // Remove again. + context.Remove(dataSource1); + Assert.Single(context); + + context.Remove(dataSource2); + Assert.Empty(context); + + // Remove again. + context.Remove(dataSource2); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_Remove_NullDataSource_ThrowsArgumentNullException() + { + var context = new SubBindingContext(); + Assert.Throws("dataSource", () => context.Remove(null)); + } + + [Fact] + public void BindingContext_RemoveCore_Invoke_Success() + { + var context = new SubBindingContext(); + var source1 = new BindingSource(); + var dataSource1 = new DataSource(); + var source2 = new BindingSource(); + var dataSource2 = new DataSource(); + context.Add(dataSource1, source1.CurrencyManager); + context.Add(dataSource2, source2.CurrencyManager); + + context.RemoveCore(dataSource1); + Assert.Single(context); + + // Remove again. + context.RemoveCore(dataSource1); + Assert.Single(context); + + context.RemoveCore(dataSource2); + Assert.Empty(context); + + // Remove again. + context.RemoveCore(dataSource2); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_RemoveCore_NullDataSource_ThrowsArgumentNullException() + { + var context = new SubBindingContext(); + Assert.Throws("dataSource", () => context.RemoveCore(null)); + } + + [Fact] + public void BindingContext_Clear_Empty_Success() + { + var context = new BindingContext(); + context.Clear(); + Assert.Empty(context); + + // Clear again. + context.Clear(); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_Clear_NotEmpty_Success() + { + var context = new BindingContext(); + var source = new BindingSource(); + context.Add(new DataSource(), source.CurrencyManager); + + // Clear again. + context.Clear(); + Assert.Empty(context); + + context.Clear(); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_ClearCore_Empty_Success() + { + var context = new SubBindingContext(); + context.ClearCore(); + Assert.Empty(context); + + // Clear again. + context.ClearCore(); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_ClearCore_NotEmpty_Success() + { + var context = new SubBindingContext(); + var source = new BindingSource(); + context.Add(new DataSource(), source.CurrencyManager); + + // Clear again. + context.ClearCore(); + Assert.Empty(context); + + context.ClearCore(); + Assert.Empty(context); + } + + public static IEnumerable Contains_DataSource_TestData() + { + var context = new BindingContext(); + var source = new BindingSource(); + var dataSource = new DataSource(); + context.Add(dataSource, source.CurrencyManager); + yield return new object[] { context, dataSource, true }; + yield return new object[] { context, 1, false }; + } + + [Theory] + [MemberData(nameof(Contains_DataSource_TestData))] + public void BindingContext_Contains_DataSource_ReturnsExpected(BindingContext context, object dataSource, bool expected) + { + Assert.Equal(expected, context.Contains(dataSource)); + Assert.Equal(expected, context.Contains(dataSource, null)); + Assert.Equal(expected, context.Contains(dataSource, string.Empty)); + } + + + public static IEnumerable Contains_DataSourceDataMember_TestData() + { + var context = new BindingContext(); + var source = new BindingSource(); + var dataSource1 = new DataSource(); + var dataSource2 = new DataSource(); + context.Add(dataSource1, source.CurrencyManager); + Assert.NotNull(context[dataSource2, "Property"]); + + yield return new object[] { context, dataSource1, string.Empty, true }; + yield return new object[] { context, dataSource1, null, true }; + yield return new object[] { context, dataSource1, "Property", false }; + yield return new object[] { context, dataSource2, "Property", true }; + yield return new object[] { context, dataSource2, "property", true }; + yield return new object[] { context, dataSource2, "NoSuchProperty", false }; + yield return new object[] { context, dataSource2, string.Empty, true }; + yield return new object[] { context, dataSource2, null, true }; + yield return new object[] { context, 1, "Property", false }; + } + + [Theory] + [MemberData(nameof(Contains_DataSourceDataMember_TestData))] + public void BindingContext_Contains_DataSourceDataMember_ReturnsExpected(BindingContext context, object dataSource, string dataMember, bool expected) + { + Assert.Equal(expected, context.Contains(dataSource, dataMember)); + } + + [Fact] + public void BindingContext_Contains_NullDataSource_ThrowsArgumentNullException() + { + var context = new BindingContext(); + Assert.Throws("dataSource", () => context.Contains(null)); + Assert.Throws("dataSource", () => context.Contains(null, null)); + Assert.Throws("dataSource", () => context.Contains(null, string.Empty)); + } + + [Fact] + public void BindingContext_Item_GetNoSuchDataSource_AddsToCollection() + { + var context = new BindingContext(); + var dataSource = new DataSource(); + PropertyManager manager = Assert.IsType(context[dataSource]); + Assert.Same(dataSource, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Single(context); + Assert.Same(manager, context[dataSource]); + } + + [Fact] + public void BindingContext_Item_GetIListDataSource_AddsToCollection() + { + var context = new BindingContext(); + var dataSource = new List { 1, 2, 3}; + CurrencyManager manager = Assert.IsType(context[dataSource]); + Assert.Same(dataSource, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Single(context); + Assert.Same(manager, context[dataSource]); + } + + [Fact] + public void BindingContext_Item_GetArrayDataSource_AddsToCollection() + { + var context = new BindingContext(); + var dataSource = new int[] { 1, 2, 3}; + CurrencyManager manager = Assert.IsType(context[dataSource]); + Assert.Same(dataSource, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Single(context); + Assert.Same(manager, context[dataSource]); + } + + [Fact] + public void BindingContext_Item_GetIListSourceDataSource_AddsToCollection() + { + var context = new BindingContext(); + var dataSource = new List { 1, 2, 3}; + var mockIListSource = new Mock(MockBehavior.Strict); + mockIListSource + .Setup(s => s.GetList()) + .Returns(dataSource); + + CurrencyManager manager = Assert.IsType(context[mockIListSource.Object]); + Assert.Same(dataSource, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Single(context); + Assert.Same(manager, context[mockIListSource.Object]); + } + + [Fact] + public void BindingContext_Item_GetIListSourceDataSourceReturningNull_ThrowsArgumentNullException() + { + var context = new BindingContext(); + var mockIListSource = new Mock(MockBehavior.Strict); + mockIListSource + .Setup(s => s.GetList()) + .Returns((IList)null); + + Assert.Throws("dataSource", () => context[mockIListSource.Object]); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_Item_GetWithICurrencyManagerProvider_DoesNotAddToCollection() + { + var context = new BindingContext(); + CurrencyManager manager = new BindingSource().CurrencyManager; + var mockCurrencyManagerProvider = new Mock(); + mockCurrencyManagerProvider + .Setup(p => p.GetRelatedCurrencyManager("dataMember")) + .Returns(manager); + + Assert.Same(manager, context[mockCurrencyManagerProvider.Object, "dataMember"]); + Assert.Empty(context); + } + + [Fact] + public void BindingContext_Item_GetWithNullICurrencyManagerProvider_AddsToCollection() + { + var context = new BindingContext(); + var mockCurrencyManagerProvider = new Mock(); + mockCurrencyManagerProvider + .Setup(p => p.GetRelatedCurrencyManager("dataMember")) + .Returns((CurrencyManager)null); + + PropertyManager manager = Assert.IsType(context[mockCurrencyManagerProvider.Object]); + Assert.Single(context); + Assert.Same(manager, context[mockCurrencyManagerProvider.Object]); + } + + public static IEnumerable Item_DataSourceWithDataMember_TestData() + { + var dataSource = new ParentDataSource + { + ParentProperty = new DataSource + { + Property = 1 + } + }; + yield return new object[] { dataSource, "ParentProperty", dataSource.ParentProperty, 2 }; + yield return new object[] { dataSource, "ParentProperty.Property", dataSource.ParentProperty.Property, 3 }; + yield return new object[] { dataSource, "parentproperty", dataSource.ParentProperty, 2 }; + yield return new object[] { dataSource, "parentproperty.property", dataSource.ParentProperty.Property, 3 }; + } + + [Theory] + [MemberData(nameof(Item_DataSourceWithDataMember_TestData))] + public void BindingContext_Item_GetNoSuchDataSourceWithDataMember_AddsToCollection(object dataSource, string dataMember, object expectedCurrent, int expectedCount) + { + var context = new BindingContext(); + PropertyManager manager = Assert.IsAssignableFrom(context[dataSource, dataMember]); + Assert.Equal(expectedCurrent, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(expectedCount, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, dataMember]); + Assert.Same(manager, context[dataSource, dataMember.ToLower()]); + } + + [Fact] + public void BindingContext_Item_GetWithAddedDataSourceWithDataMember_ThrowsArgumentException() + { + var context = new BindingContext(); + var source = new BindingSource(); + var dataSource = new DataSource(); + context.Add(dataSource, source.CurrencyManager); + Assert.Throws(null, () => context[dataSource, "Property"]); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void BindingContext_Item_GetNoSuchDataSourceNullOrEmptyMember_AddsToCollection(string dataMember) + { + var context = new SubBindingContext(); + var dataSource = new DataSource(); + PropertyManager manager = Assert.IsType(context[dataSource, dataMember]); + Assert.Single(context); + Assert.Same(manager, context[dataSource]); + Assert.Same(manager, context[dataSource, string.Empty]); + Assert.Same(manager, context[dataSource]); + Assert.Same(manager, context[dataSource, null]); + } + + [Theory] + [InlineData("NoSuchProperty")] + [InlineData(".")] + [InlineData("..")] + [InlineData("ParentProperty.")] + [InlineData("ParentProperty.NoSuchProperty")] + public void BindingContext_Item_GetNoSuchDataSourceNoSuchDataMember_ThrowsArgumentException(string dataMember) + { + var context = new SubBindingContext(); + var dataSource = new ParentDataSource(); + Assert.Throws(null, () => context[dataSource, dataMember]); + } + + [Fact] + public void BindingContext_Item_GetIListWithDataMemberReturningIList_AddsToCollection() + { + var context = new BindingContext(); + var list = new List { 1, 2, 3}; + var dataSource = new IListDataSource(); + dataSource.Property = list; + + CurrencyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(list, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(2, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, "Property"]); + } + + [Fact] + public void BindingContext_Item_GetIListWithDataMemberReturningNonIList_AddsToCollection() + { + var context = new BindingContext(); + var list = new List { 1, 2, 3}; + var dataSource = new ObjectDataSource(); + dataSource.Property = list; + + PropertyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(list, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(2, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, "Property"]); + } + + [Fact] + public void BindingContext_Item_GetArrayWithDataMember_AddsToCollection() + { + var context = new BindingContext(); + var list = new int[] { 1, 2, 3}; + var dataSource = new IListDataSource(); + dataSource.Property = list; + + CurrencyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(list, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(2, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, "Property"]); + } + + [Fact] + public void BindingContext_Item_GetIListSourceDataSourceWithDataMemberReturningIList_AddsToCollection() + { + var context = new BindingContext(); + var list = new List { 1, 2, 3}; + var dataSource = new IListDataSource(); + var mockIListSource = new Mock(MockBehavior.Strict); + mockIListSource + .Setup(s => s.GetList()) + .Returns(list); + var mockIList = mockIListSource.As(); + dataSource.Property = mockIList.Object; + + CurrencyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(list, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(2, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, "Property"]); + } + + [Fact] + public void BindingContext_Item_GetIListSourceDataSourceWithDataMemberReturningNonIList_AddsToCollection() + { + var context = new BindingContext(); + var list = new List { 1, 2, 3}; + var dataSource = new IListSourceDataSource(); + var mockIListSource = new Mock(MockBehavior.Strict); + mockIListSource + .Setup(s => s.GetList()) + .Returns(list); + dataSource.Property = mockIListSource.Object; + + PropertyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(mockIListSource.Object, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(2, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, "Property"]); + } + + [Fact] + public void BindingContext_Item_GetIListSourceDataSourceWithDataMemberReturningIListNull_ThrowsArgumentNullException() + { + var context = new BindingContext(); + var dataSource = new IListDataSource(); + var mockIListSource = new Mock(MockBehavior.Strict); + mockIListSource + .Setup(s => s.GetList()) + .Returns((IList)null); + var mockIList = mockIListSource.As(); + dataSource.Property = mockIList.Object; + + Assert.Throws("dataSource", () => context[dataSource, "Property"]); + + // Does, however, add the parent. + PropertyManager parentManager = Assert.IsType(Assert.IsType(Assert.IsType(Assert.Single(context)).Value).Target); + Assert.Same(dataSource, parentManager.Current); + } + + [Fact] + public void BindingContext_Item_GetIListSourceDataSourceWithDataMemberReturningNonIListNull_AddsToCollection() + { + var context = new BindingContext(); + var dataSource = new IListSourceDataSource(); + var mockIListSource = new Mock(MockBehavior.Strict); + mockIListSource + .Setup(s => s.GetList()) + .Returns((IList)null); + dataSource.Property = mockIListSource.Object; + + PropertyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(mockIListSource.Object, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Equal(2, ((ICollection)context).Count); + Assert.Same(manager, context[dataSource, "Property"]); + } + + [Fact] + public void BindingContext_Item_GetWithNullWeakReferenceTarget_Success() + { + var context = new BindingContext(); + var dataSource = new DataSource(); + PropertyManager manager = Assert.IsType(context[dataSource]); + WeakReference reference = Assert.IsType(Assert.IsType(Assert.Single(context)).Value); + Assert.Same(manager, reference.Target); + + // Simulate a GC by assigning the weak reference to null. + reference.Target = null; + + // Now get the new manager and verify it. + PropertyManager newManager = Assert.IsType(context[dataSource]); + Assert.NotSame(manager, newManager); + Assert.Same(dataSource, newManager.Current); + Assert.Equal(1, newManager.Count); + Assert.Equal(0, newManager.Position); + Assert.Single(context); + Assert.Same(newManager, context[dataSource]); + } + + [Fact] + public void BindingContext_Item_GetNullDataSource_ThrowsArgumentNullException() + { + var context = new SubBindingContext(); + Assert.Throws("dataSource", () => context[null]); + Assert.Throws("dataSource", () => context[null, null]); + Assert.Throws("dataSource", () => context[null, string.Empty]); + } + + [Fact] + public void BindingContext_CollectionChanged_Add_ThrowsNotImplementedException() + { + var context = new BindingContext(); + CollectionChangeEventHandler handler = (sender, e) => { }; + Assert.Throws(() => context.CollectionChanged += handler); + } + + [Fact] + public void BindingContext_CollectionChanged_Remove_Nop() + { + var context = new BindingContext(); + CollectionChangeEventHandler handler = (sender, e) => { }; + context.CollectionChanged -= handler; + } + + [Fact] + public void BindingContext_OnCollectionChanged_Invoke_Nop() + { + var context = new SubBindingContext(); + CollectionChangeEventHandler handler = (sender, e) => { }; + context.OnCollectionChanged(null); + } + + public static IEnumerable Equals_TestData() + { + var context1 = new BindingContext(); + var context2 = new BindingContext(); + var context3 = new BindingContext(); + var context4 = new BindingContext(); + var source1 = new BindingSource(); + var source2 = new BindingSource(); + var dataSource1 = new DataSource(); + var dataSource2 = new DataSource(); + + context1.Add(dataSource1, source1.CurrencyManager); + context2.Add(dataSource1, source1.CurrencyManager); + context3.Add(dataSource2, source1.CurrencyManager); + context4.Add(dataSource2, source2.CurrencyManager); + + yield return new object[] { Assert.Single(context1), Assert.Single(context1), true }; + yield return new object[] { Assert.Single(context1), Assert.Single(context2), true }; + yield return new object[] { Assert.Single(context1), Assert.Single(context3), false }; + yield return new object[] { Assert.Single(context1), Assert.Single(context4), false }; + + yield return new object[] { Assert.Single(context1), new object(), false }; + yield return new object[] { Assert.Single(context1), null, false }; + } + + [Theory] + [MemberData(nameof(Equals_TestData))] + public void BindingContext_KeyEquals_Invoke_ReturnsExpected(DictionaryEntry entry, object other, bool expected) + { + if (other is DictionaryEntry otherEntry) + { + Assert.Equal(expected, entry.Key.Equals(otherEntry.Key)); + } + else + { + Assert.Equal(expected, entry.Key.Equals(other)); + } + } + + [Fact] + public void BindingContext_UpdateBinding_NewBindingWithoutDataMember_Success() + { + var context = new BindingContext(); + var dataSource = new DataSource(); + var binding = new Binding(null, dataSource, "dataMember"); + + BindingContext.UpdateBinding(context, binding); + Assert.Single(context); + + PropertyManager manager = Assert.IsType(context[dataSource]); + Assert.Same(binding, Assert.Single(manager.Bindings)); + Assert.Same(dataSource, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Same(manager, binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_NewListBindingWithoutDataMember_Success() + { + var context = new BindingContext(); + var dataSource = new List { 1, 2, 3 }; + var binding = new Binding(null, dataSource, "dataMember"); + + BindingContext.UpdateBinding(context, binding); + Assert.Single(context); + + CurrencyManager manager = Assert.IsType(context[dataSource]); + Assert.Same(binding, Assert.Single(manager.Bindings)); + Assert.Same(dataSource, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Same(manager, binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_NewBindingWithDataMember_Success() + { + var context = new BindingContext(); + var dataSource = new DataSource { Property = 1 }; + var binding = new Binding(null, dataSource, "Property.ignored"); + + BindingContext.UpdateBinding(context, binding); + Assert.Equal(2, ((ICollection)context).Count); + + PropertyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(binding, Assert.Single(manager.Bindings)); + Assert.Equal(1, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Same(manager, binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_NewListBindingWithDataMember_Success() + { + var context = new BindingContext(); + var list = new List { 1, 2, 3 }; + var dataSource = new IListDataSource { Property = list }; + var binding = new Binding(null, dataSource, "Property.ignore"); + + BindingContext.UpdateBinding(context, binding); + Assert.Equal(2, ((ICollection)context).Count); + + CurrencyManager manager = Assert.IsAssignableFrom(context[dataSource, "Property"]); + Assert.Same(binding, Assert.Single(manager.Bindings)); + Assert.Same(list, manager.List); + Assert.Equal(1, manager.Current); + Assert.Equal(3, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Same(manager, binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_UpdateBindingWithoutDataMember_Success() + { + var context1 = new BindingContext(); + var context2 = new BindingContext(); + var dataSource = new DataSource(); + var binding = new Binding(null, dataSource, "dataMember"); + + BindingContext.UpdateBinding(context1, binding); + Assert.Single(context1); + Assert.Empty(context2); + + // Update. + BindingContext.UpdateBinding(context2, binding); + Assert.Single(context1); + Assert.Single(context2); + + PropertyManager manager1 = Assert.IsType(context1[dataSource]); + Assert.Empty(manager1.Bindings); + Assert.Same(dataSource, manager1.Current); + Assert.Equal(1, manager1.Count); + Assert.Equal(0, manager1.Position); + + PropertyManager manager2 = Assert.IsType(context2[dataSource]); + Assert.Same(binding, Assert.Single(manager2.Bindings)); + Assert.Same(dataSource, manager2.Current); + Assert.Equal(1, manager2.Count); + Assert.Equal(0, manager2.Position); + Assert.Same(manager2, binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_UpdateListBindingWithoutDataMember_Success() + { + var context1 = new BindingContext(); + var context2 = new BindingContext(); + var dataSource = new List { 1, 2, 3 }; + var binding = new Binding(null, dataSource, "dataMember"); + + BindingContext.UpdateBinding(context1, binding); + Assert.Single(context1); + Assert.Empty(context2); + + // Update. + BindingContext.UpdateBinding(context2, binding); + Assert.Single(context1); + Assert.Single(context2); + + CurrencyManager manager1 = Assert.IsType(context1[dataSource]); + Assert.Empty(manager1.Bindings); + Assert.Same(dataSource, manager1.List); + Assert.Equal(1, manager1.Current); + Assert.Equal(3, manager1.Count); + Assert.Equal(0, manager1.Position); + + CurrencyManager manager2 = Assert.IsType(context2[dataSource]); + Assert.Same(binding, Assert.Single(manager2.Bindings)); + Assert.Same(dataSource, manager2.List); + Assert.Equal(1, manager2.Current); + Assert.Equal(3, manager2.Count); + Assert.Equal(0, manager2.Position); + Assert.Same(manager2, binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_NullBindingContext_Success() + { + var context = new BindingContext(); + var dataSource = new DataSource(); + var binding = new Binding(null, dataSource, "dataMember"); + + // Without binding manager. + BindingContext.UpdateBinding(null, binding); + Assert.Null(binding.BindingManagerBase); + + // With binding manager. + BindingContext.UpdateBinding(context, binding); + Assert.Single(context); + Assert.NotNull(binding.BindingManagerBase); + + BindingContext.UpdateBinding(null, binding); + Assert.Single(context); + + PropertyManager manager = Assert.IsAssignableFrom(context[dataSource]); + Assert.Empty(manager.Bindings); + Assert.Equal(dataSource, manager.Current); + Assert.Equal(1, manager.Count); + Assert.Equal(0, manager.Position); + Assert.Null(binding.BindingManagerBase); + } + + [Fact] + public void BindingContext_UpdateBinding_NullBinding_ThrowsArgumentNullException() + { + Assert.Throws("binding", () => BindingContext.UpdateBinding(new BindingContext(), null)); + } + + private class ParentDataSource + { + public DataSource ParentProperty { get; set; } + } + + private class DataSource + { + public int Property { get; set; } + } + + private class IListDataSource + { + public IList Property { get; set; } + } + + private class IListSourceDataSource + { + public IListSource Property { get; set; } + } + + private class ObjectDataSource + { + public object Property { get; set; } + } + + private class SubBindingContext : BindingContext + { + public new void AddCore(object dataSource, BindingManagerBase listManager) + { + base.AddCore(dataSource, listManager); + } + + public new void RemoveCore(object dataSource) + { + base.RemoveCore(dataSource); + } + + public new void ClearCore() + { + base.ClearCore(); + } + + public new void OnCollectionChanged(CollectionChangeEventArgs ccevent) + { + base.OnCollectionChanged(ccevent); + } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ButtonBaseTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ButtonBaseTests.cs new file mode 100644 index 00000000000..d91c475cd94 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ButtonBaseTests.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class ButtonBaseTests + { + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(TextImageRelation))] + public void ToolStripItem_TextImageRelation_Set_GetReturnsExpected(TextImageRelation value) + { + var button = new SubButtonBase + { + TextImageRelation = value + }; + Assert.Equal(value, button.TextImageRelation); + + // Set same. + button.TextImageRelation = value; + Assert.Equal(value, button.TextImageRelation); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(TextImageRelation))] + [InlineData((TextImageRelation)3)] + [InlineData((TextImageRelation)5)] + [InlineData((TextImageRelation)6)] + [InlineData((TextImageRelation)7)] + public void ButtonBase_TextImageRelation_SetInvalid_ThrowsInvalidEnumArgumentException(TextImageRelation value) + { + var button = new SubButtonBase(); + Assert.Throws("value", () => button.TextImageRelation = value); + } + + private class SubButtonBase : ButtonBase + { + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnHeaderTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnHeaderTests.cs index f736d752bdd..1c2d671a0f0 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnHeaderTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnHeaderTests.cs @@ -294,7 +294,7 @@ public void ColumnHeader_ImageIndex_SetWithListViewWithHandle_GetReturnsExpected public void ColumnHeader_ImageIndex_SetInvalid_ThrowsArgumentOutOfRangeException(int value) { var header = new ColumnHeader(); - Assert.Throws("ImageIndex", () => header.ImageIndex = value); + Assert.Throws("value", () => header.ImageIndex = value); } [Theory] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnStyleTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnStyleTests.cs index b37eefc6bd5..57f07b8db4b 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnStyleTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ColumnStyleTests.cs @@ -44,7 +44,7 @@ public void ColumnStyle_Ctor_SizeType_Float(SizeType sizeType, float width) [Fact] public void ColumnStyle_Ctor_NegativeWidth_ThrowsArgumentOutOfRangeException() { - Assert.Throws("Size", () => new ColumnStyle(SizeType.AutoSize, -1)); + Assert.Throws("value", () => new ColumnStyle(SizeType.AutoSize, -1)); } [Theory] @@ -74,7 +74,7 @@ public void ColumnStyle_Width_SetOwned_GetReturnsExpected(float value) public void ColumnStyle_Width_SetNegative_ThrowsArgumentOutOfRangeException() { var style = new ColumnStyle(); - Assert.Throws("Size", () => style.Width = -1); + Assert.Throws("value", () => style.Width = -1); } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs new file mode 100644 index 00000000000..0c621a4554a --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs @@ -0,0 +1,867 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class ComboBoxTests + { + [Fact] + public void Ctor_Default() + { + var control = new SubComboBox(); + Assert.True(control.AllowSelection); + Assert.Empty(control.AutoCompleteCustomSource); + Assert.Same(control.AutoCompleteCustomSource, control.AutoCompleteCustomSource); + Assert.Equal(AutoCompleteMode.None, control.AutoCompleteMode); + Assert.Equal(AutoCompleteSource.None, control.AutoCompleteSource); + Assert.Equal(SystemColors.Window, control.BackColor); + Assert.Null(control.BackgroundImage); + Assert.Equal(ImageLayout.Tile, control.BackgroundImageLayout); + Assert.Equal(0, control.Bounds.X); + Assert.Equal(0, control.Bounds.Y); + Assert.Equal(121, control.Bounds.Width); + Assert.True(control.Bounds.Height > 0); + Assert.True(control.ClientSize.Width > 0); + Assert.True(control.ClientSize.Height > 0); + Assert.Equal(0, control.ClientRectangle.X); + Assert.Equal(0, control.ClientRectangle.Y); + Assert.True(control.ClientRectangle.Width > 0); + Assert.True(control.ClientRectangle.Height > 0); + Assert.Null(control.DataManager); + Assert.Null(control.DataSource); + Assert.Equal(Size.Empty, control.DefaultMaximumSize); + Assert.Equal(Size.Empty, control.DefaultMinimumSize); + Assert.Equal(Padding.Empty, control.DefaultPadding); + Assert.Equal(121, control.DefaultSize.Width); + Assert.True(control.DefaultSize.Height > 0); + Assert.Empty(control.DisplayMember); + Assert.Equal(0, control.DisplayRectangle.X); + Assert.Equal(0, control.DisplayRectangle.Y); + Assert.True(control.DisplayRectangle.Width > 0); + Assert.True(control.DisplayRectangle.Height > 0); + Assert.Equal(DrawMode.Normal, control.DrawMode); + Assert.Equal(106, control.DropDownHeight); + Assert.Equal(ComboBoxStyle.DropDown, control.DropDownStyle); + Assert.Equal(121, control.DropDownWidth); + Assert.False(control.DroppedDown); + Assert.Equal(FlatStyle.Standard, control.FlatStyle); + Assert.False(control.Focused); + Assert.Null(control.FormatInfo); + Assert.Empty(control.FormatString); + Assert.False(control.FormattingEnabled); + Assert.Same(Control.DefaultFont, control.Font); + Assert.Equal(SystemColors.WindowText, control.ForeColor); + Assert.True(control.Height > 0); + Assert.True(control.IntegralHeight); + Assert.Equal(Control.DefaultFont.Height + 2, control.ItemHeight); + Assert.Empty(control.Items); + Assert.Same(control.Items, control.Items); + Assert.Equal(Point.Empty, control.Location); + Assert.Equal(8, control.MaxDropDownItems); + Assert.Equal(Size.Empty, control.MaximumSize); + Assert.Equal(0, control.MaxLength); + Assert.Equal(Size.Empty, control.MinimumSize); + Assert.Equal(Padding.Empty, control.Padding); + Assert.Equal(121, control.PreferredSize.Width); + Assert.True(control.PreferredSize.Height > 0); + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.Null(control.SelectedValue); + Assert.Equal(-1, control.SelectedIndex); + Assert.Null(control.SelectedItem); + Assert.Empty(control.SelectedText); + Assert.Equal(121, control.Size.Width); + Assert.True(control.Size.Height > 0); + Assert.Empty(control.Text); + Assert.Equal(0, control.SelectionLength); + Assert.Equal(0, control.SelectionStart); + Assert.False(control.Sorted); + Assert.Empty(control.ValueMember); + Assert.Equal(121, control.Width); + } + + public static IEnumerable BackColor_Set_TestData() + { + yield return new object[] { Color.Empty, SystemColors.Window }; + yield return new object[] { Color.Red, Color.Red }; + } + + [Theory] + [MemberData(nameof(BackColor_Set_TestData))] + public void BackColor_Set_GetReturnsExpected(Color value, Color expected) + { + var control = new ComboBox + { + BackColor = value + }; + Assert.Equal(expected, control.BackColor); + + // Set same. + control.BackColor = value; + Assert.Equal(expected, control.BackColor); + } + + [Fact] + public void BackColor_SetWithHandler_CallsBackColorChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BackColorChanged += handler; + + // Set different. + control.BackColor = Color.Red; + Assert.Equal(Color.Red, control.BackColor); + Assert.Equal(1, callCount); + + // Set same. + control.BackColor = Color.Red; + Assert.Equal(Color.Red, control.BackColor); + Assert.Equal(1, callCount); + + // Set different. + control.BackColor = Color.Empty; + Assert.Equal(SystemColors.Window, control.BackColor); + Assert.Equal(2, callCount); + + // Remove handler. + control.BackColorChanged -= handler; + control.BackColor = Color.Red; + Assert.Equal(Color.Red, control.BackColor); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetImageTheoryData))] + public void BackgroundImage_Set_GetReturnsExpected(Image value) + { + var control = new ComboBox + { + BackgroundImage = value + }; + Assert.Equal(value, control.BackgroundImage); + + // Set same. + control.BackgroundImage = value; + Assert.Equal(value, control.BackgroundImage); + } + + [Fact] + public void BackgroundImage_SetWithHandler_CallsBackColorChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BackgroundImageChanged += handler; + + // Set different. + var image1 = new Bitmap(10, 10); + control.BackgroundImage = image1; + Assert.Same(image1, control.BackgroundImage); + Assert.Equal(1, callCount); + + // Set same. + control.BackgroundImage = image1; + Assert.Same(image1, control.BackgroundImage); + Assert.Equal(1, callCount); + + // Set different. + var image2 = new Bitmap(10, 10); + control.BackgroundImage = image2; + Assert.Same(image2, control.BackgroundImage); + Assert.Equal(2, callCount); + + // Set null. + control.BackgroundImage = null; + Assert.Null(control.BackgroundImage); + Assert.Equal(3, callCount); + + // Remove handler. + control.BackgroundImageChanged -= handler; + control.BackgroundImage = image1; + Assert.Same(image1, control.BackgroundImage); + Assert.Equal(3, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(ImageLayout))] + public void BackgroundImageLayout_Set_GetReturnsExpected(ImageLayout value) + { + var control = new ComboBox + { + BackgroundImageLayout = value + }; + Assert.Equal(value, control.BackgroundImageLayout); + + // Set same. + control.BackgroundImageLayout = value; + Assert.Equal(value, control.BackgroundImageLayout); + } + + [Fact] + public void BackgroundImageLayout_SetWithHandler_CallsBackgroundImageLayoutChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BackgroundImageLayoutChanged += handler; + + // Set different. + control.BackgroundImageLayout = ImageLayout.Center; + Assert.Equal(ImageLayout.Center, control.BackgroundImageLayout); + Assert.Equal(1, callCount); + + // Set same. + control.BackgroundImageLayout = ImageLayout.Center; + Assert.Equal(ImageLayout.Center, control.BackgroundImageLayout); + Assert.Equal(1, callCount); + + // Set different. + control.BackgroundImageLayout = ImageLayout.Stretch; + Assert.Equal(ImageLayout.Stretch, control.BackgroundImageLayout); + Assert.Equal(2, callCount); + + // Remove handler. + control.BackgroundImageLayoutChanged -= handler; + control.BackgroundImageLayout = ImageLayout.Center; + Assert.Equal(ImageLayout.Center, control.BackgroundImageLayout); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(ImageLayout))] + public void BackgroundImageLayout_SetInvalid_ThrowsInvalidEnumArgumentException(ImageLayout value) + { + var control = new ComboBox(); + Assert.Throws("value", () => control.BackgroundImageLayout = value); + } + + public static IEnumerable DataSource_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new List() }; + yield return new object[] { new int[0] }; + + var mockSource = new Mock(MockBehavior.Strict); + mockSource + .Setup(s => s.GetList()) + .Returns(new int[] { 1 }); + yield return new object[] { mockSource.Object }; + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_Set_GetReturnsExpected(object value) + { + var control = new SubComboBox + { + DataSource = value + }; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetWithHandler_CallsDataSourceChanged() + { + var control = new ComboBox(); + int dataSourceCallCount = 0; + int displayMemberCallCount = 0; + EventHandler dataSourceHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + dataSourceCallCount++; + }; + EventHandler displayMemberHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + displayMemberCallCount++; + }; + control.DataSourceChanged += dataSourceHandler; + control.DisplayMemberChanged += displayMemberHandler; + + // Set different. + var dataSource1 = new List(); + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(0, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set same. + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(0, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set different. + var dataSource2 = new List(); + control.DataSource = dataSource2; + Assert.Same(dataSource2, control.DataSource); + Assert.Equal(0, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set null. + control.DataSource = null; + Assert.Null(control.DataSource); + Assert.Equal(0, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Remove handler. + control.DataSourceChanged -= dataSourceHandler; + control.DisplayMemberChanged -= displayMemberHandler; + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(0, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void Font_Set_GetReturnsExpected(Font value) + { + var control = new ComboBox + { + Font = value + }; + Assert.Equal(value ?? Control.DefaultFont, control.Font); + + // Set same. + control.Font = value; + Assert.Equal(value ?? Control.DefaultFont, control.Font); + } + + [Fact] + public void Font_SetWithHandler_CallsFontChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.FontChanged += handler; + + // Set different. + var font1 = SystemFonts.MenuFont; + control.Font = font1; + Assert.Same(font1, control.Font); + Assert.Equal(1, callCount); + + // Set same. + control.Font = font1; + Assert.Same(font1, control.Font); + Assert.Equal(1, callCount); + + // Set different. + var font2 = SystemFonts.DialogFont; + control.Font = font2; + Assert.Same(font2, control.Font); + Assert.Equal(2, callCount); + + // Set null. + control.Font = null; + Assert.Same(Control.DefaultFont, control.Font); + Assert.Equal(3, callCount); + + // Remove handler. + control.FontChanged -= handler; + control.Font = font1; + Assert.Same(font1, control.Font); + Assert.Equal(3, callCount); + } + + public static IEnumerable ForeColor_Set_TestData() + { + yield return new object[] { Color.Empty, SystemColors.WindowText }; + yield return new object[] { Color.Red, Color.Red }; + } + + [Theory] + [MemberData(nameof(ForeColor_Set_TestData))] + public void ForeColor_Set_GetReturnsExpected(Color value, Color expected) + { + var control = new ComboBox + { + ForeColor = value + }; + Assert.Equal(expected, control.ForeColor); + + // Set same. + control.ForeColor = value; + Assert.Equal(expected, control.ForeColor); + } + + [Fact] + public void ForeColor_SetWithHandler_CallsForeColorChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.ForeColorChanged += handler; + + // Set different. + control.ForeColor = Color.Red; + Assert.Equal(Color.Red, control.ForeColor); + Assert.Equal(1, callCount); + + // Set same. + control.ForeColor = Color.Red; + Assert.Equal(Color.Red, control.ForeColor); + Assert.Equal(1, callCount); + + // Set different. + control.ForeColor = Color.Empty; + Assert.Equal(SystemColors.WindowText, control.ForeColor); + Assert.Equal(2, callCount); + + // Remove handler. + control.ForeColorChanged -= handler; + control.ForeColor = Color.Red; + Assert.Equal(Color.Red, control.ForeColor); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetPaddingNormalizedTheoryData))] + public void Padding_Set_GetReturnsExpected(Padding value, Padding expected) + { + var control = new ComboBox + { + Padding = value + }; + Assert.Equal(expected, control.Padding); + + // Set same. + control.Padding = value; + Assert.Equal(expected, control.Padding); + } + + [Fact] + public void Padding_SetWithHandler_CallsPaddingChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.PaddingChanged += handler; + + // Set different. + control.Padding = new Padding(1); + Assert.Equal(new Padding(1), control.Padding); + Assert.Equal(1, callCount); + + // Set same. + control.Padding = new Padding(1); + Assert.Equal(new Padding(1), control.Padding); + Assert.Equal(1, callCount); + + // Set different. + control.Padding = new Padding(2); + Assert.Equal(new Padding(2), control.Padding); + Assert.Equal(2, callCount); + + // Remove handler. + control.PaddingChanged -= handler; + control.Padding = new Padding(1); + Assert.Equal(new Padding(1), control.Padding); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetRightToLeftTheoryData))] + public void RightToLeft_Set_GetReturnsExpected(RightToLeft value, RightToLeft expected) + { + var control = new ComboBox + { + RightToLeft = value + }; + Assert.Equal(expected, control.RightToLeft); + + // Set same. + control.RightToLeft = value; + Assert.Equal(expected, control.RightToLeft); + } + + [Fact] + public void RightToLeft_SetWithHandler_CallsRightToLeftChanged() + { + var control = new ComboBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.RightToLeftChanged += handler; + + // Set different. + control.RightToLeft = RightToLeft.Yes; + Assert.Equal(RightToLeft.Yes, control.RightToLeft); + Assert.Equal(1, callCount); + + // Set same. + control.RightToLeft = RightToLeft.Yes; + Assert.Equal(RightToLeft.Yes, control.RightToLeft); + Assert.Equal(1, callCount); + + // Set different. + control.RightToLeft = RightToLeft.Inherit; + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.Equal(2, callCount); + + // Remove handler. + control.RightToLeftChanged -= handler; + control.RightToLeft = RightToLeft.Yes; + Assert.Equal(RightToLeft.Yes, control.RightToLeft); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(RightToLeft))] + public void RightToLeft_SetInvalid_ThrowsInvalidEnumArgumentException(RightToLeft value) + { + var control = new ComboBox(); + Assert.Throws("value", () => control.RightToLeft = value); + } + + [Theory] + [InlineData(-1, "")] + [InlineData(0, "System.Windows.Forms.Tests.ComboBoxTests+DataClass")] + [InlineData(1, "System.Windows.Forms.Tests.ComboBoxTests+DataClass")] + public void SelectedIndex_SetWithoutDisplayMember_GetReturnsExpected(int value, string expectedText) + { + var control = new ComboBox(); + control.Items.Add(new DataClass { Value = "Value1" }); + control.Items.Add(new DataClass { Value = "Value2" }); + + control.SelectedIndex = value; + Assert.Equal(value, control.SelectedIndex); + Assert.Equal(value == -1 ? null : control.Items[control.SelectedIndex], control.SelectedItem); + Assert.Equal(expectedText, control.Text); + + // Set same. + control.SelectedIndex = value; + Assert.Equal(value, control.SelectedIndex); + Assert.Equal(value == -1 ? null : control.Items[control.SelectedIndex], control.SelectedItem); + Assert.Equal(expectedText, control.Text); + } + + [Theory] + [InlineData(-1, "")] + [InlineData(0, "Value1")] + [InlineData(1, "Value2")] + public void SelectedIndex_SetWithDisplayMember_GetReturnsExpected(int value, string expectedText) + { + var control = new ComboBox + { + DisplayMember = "Value" + }; + control.Items.Add(new DataClass { Value = "Value1" }); + control.Items.Add(new DataClass { Value = "Value2" }); + + control.SelectedIndex = value; + Assert.Equal(value, control.SelectedIndex); + Assert.Equal(value == -1 ? null : control.Items[control.SelectedIndex], control.SelectedItem); + Assert.Equal(expectedText, control.Text); + + // Set same. + control.SelectedIndex = value; + Assert.Equal(value, control.SelectedIndex); + Assert.Equal(value == -1 ? null : control.Items[control.SelectedIndex], control.SelectedItem); + Assert.Equal(expectedText, control.Text); + } + + public static IEnumerable FindString_TestData() + { + foreach (int startIndex in new int[] { -2, -1, 0, 1 }) + { + yield return new object[] { new ComboBox(), null, startIndex, -1 }; + yield return new object[] { new ComboBox(), string.Empty, startIndex, -1 }; + yield return new object[] { new ComboBox(), "s", startIndex, -1 }; + + var controlWithNoItems = new ComboBox(); + Assert.Empty(controlWithNoItems.Items); + yield return new object[] { new ComboBox(), null, startIndex, -1 }; + yield return new object[] { new ComboBox(), string.Empty, startIndex, -1 }; + yield return new object[] { new ComboBox(), "s", startIndex, -1 }; + } + + var controlWithItems = new ComboBox + { + DisplayMember = "Value" + }; + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "ABC" }); + controlWithItems.Items.Add(new DataClass { Value = "def" }); + controlWithItems.Items.Add(new DataClass { Value = "" }); + controlWithItems.Items.Add(new DataClass { Value = null }); + + yield return new object[] { controlWithItems, "abc", -1, 0 }; + yield return new object[] { controlWithItems, "abc", 0, 1 }; + yield return new object[] { controlWithItems, "abc", 1, 2 }; + yield return new object[] { controlWithItems, "abc", 2, 0 }; + yield return new object[] { controlWithItems, "abc", 5, 0 }; + + yield return new object[] { controlWithItems, "ABC", -1, 0 }; + yield return new object[] { controlWithItems, "ABC", 0, 1 }; + yield return new object[] { controlWithItems, "ABC", 1, 2 }; + yield return new object[] { controlWithItems, "ABC", 2, 0 }; + yield return new object[] { controlWithItems, "ABC", 5, 0 }; + + yield return new object[] { controlWithItems, "a", -1, 0 }; + yield return new object[] { controlWithItems, "a", 0, 1 }; + yield return new object[] { controlWithItems, "a", 1, 2 }; + yield return new object[] { controlWithItems, "a", 2, 0 }; + yield return new object[] { controlWithItems, "a", 5, 0 }; + + yield return new object[] { controlWithItems, "A", -1, 0 }; + yield return new object[] { controlWithItems, "A", 0, 1 }; + yield return new object[] { controlWithItems, "A", 1, 2 }; + yield return new object[] { controlWithItems, "A", 2, 0 }; + yield return new object[] { controlWithItems, "A", 5, 0 }; + + yield return new object[] { controlWithItems, "abcd", -1, -1 }; + yield return new object[] { controlWithItems, "abcd", 0, -1 }; + yield return new object[] { controlWithItems, "abcd", 1, -1 }; + yield return new object[] { controlWithItems, "abcd", 2, -1 }; + yield return new object[] { controlWithItems, "abcd", 5, -1 }; + + yield return new object[] { controlWithItems, "def", -1, 3 }; + yield return new object[] { controlWithItems, "def", 0, 3 }; + yield return new object[] { controlWithItems, "def", 1, 3 }; + yield return new object[] { controlWithItems, "def", 2, 3 }; + yield return new object[] { controlWithItems, "def", 5, 3 }; + + yield return new object[] { controlWithItems, null, -1, -1 }; + yield return new object[] { controlWithItems, null, 0, -1 }; + yield return new object[] { controlWithItems, null, 1, -1 }; + yield return new object[] { controlWithItems, null, 2, -1 }; + yield return new object[] { controlWithItems, null, 5, -1 }; + + yield return new object[] { controlWithItems, string.Empty, -1, 0 }; + yield return new object[] { controlWithItems, string.Empty, 0, 1 }; + yield return new object[] { controlWithItems, string.Empty, 1, 2 }; + yield return new object[] { controlWithItems, string.Empty, 2, 3 }; + yield return new object[] { controlWithItems, string.Empty, 5, 0 }; + + yield return new object[] { controlWithItems, "NoSuchItem", -1, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 0, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 1, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 2, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 5, -1 }; + } + + [Theory] + [MemberData(nameof(FindString_TestData))] + public void FindString_Invoke_ReturnsExpected(ComboBox control, string s, int startIndex, int expected) + { + if (startIndex == -1) + { + Assert.Equal(expected, control.FindString(s)); + } + + Assert.Equal(expected, control.FindString(s, startIndex)); + } + + [Theory] + [InlineData(-2)] + [InlineData(1)] + [InlineData(2)] + public void FindString_InvalidStartIndex_ThrowsArgumentOutOfRangeException(int startIndex) + { + var control = new ComboBox(); + control.Items.Add("item"); + Assert.Throws("startIndex", () => control.FindString("s", startIndex)); + } + + public static IEnumerable FindStringExact_TestData() + { + foreach (int startIndex in new int[] { -2, -1, 0, 1 }) + { + foreach (bool ignoreCase in new bool[] { true, false }) + { + yield return new object[] { new ComboBox(), null, startIndex, ignoreCase, -1 }; + yield return new object[] { new ComboBox(), string.Empty, startIndex, ignoreCase, -1 }; + yield return new object[] { new ComboBox(), "s", startIndex, ignoreCase, -1 }; + + var controlWithNoItems = new ComboBox(); + Assert.Empty(controlWithNoItems.Items); + yield return new object[] { new ComboBox(), null, startIndex, ignoreCase, -1 }; + yield return new object[] { new ComboBox(), string.Empty, startIndex, ignoreCase, -1 }; + yield return new object[] { new ComboBox(), "s", startIndex, ignoreCase, -1 }; + } + } + + var controlWithItems = new ComboBox + { + DisplayMember = "Value" + }; + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "ABC" }); + controlWithItems.Items.Add(new DataClass { Value = "def" }); + controlWithItems.Items.Add(new DataClass { Value = "" }); + controlWithItems.Items.Add(new DataClass { Value = null }); + + foreach (bool ignoreCase in new bool[] { true, false }) + { + yield return new object[] { controlWithItems, "abc", -1, ignoreCase, 0 }; + yield return new object[] { controlWithItems, "abc", 0, ignoreCase, 1 }; + yield return new object[] { controlWithItems, "abc", 1, ignoreCase, ignoreCase ? 2 : 0 }; + yield return new object[] { controlWithItems, "abc", 2, ignoreCase, 0 }; + yield return new object[] { controlWithItems, "abc", 5, ignoreCase, 0 }; + } + + yield return new object[] { controlWithItems, "ABC", -1, false, 2 }; + yield return new object[] { controlWithItems, "ABC", 0, false, 2 }; + yield return new object[] { controlWithItems, "ABC", 1, false, 2 }; + yield return new object[] { controlWithItems, "ABC", 2, false, 2 }; + yield return new object[] { controlWithItems, "ABC", 5, false, 2 }; + + yield return new object[] { controlWithItems, "ABC", -1, true, 0 }; + yield return new object[] { controlWithItems, "ABC", 0, true, 1 }; + yield return new object[] { controlWithItems, "ABC", 1, true, 2 }; + yield return new object[] { controlWithItems, "ABC", 2, true, 0 }; + yield return new object[] { controlWithItems, "ABC", 5, true, 0 }; + + foreach (bool ignoreCase in new bool[] { true, false }) + { + yield return new object[] { controlWithItems, "a", -1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "a", 0, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "a", 1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "a", 2, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "a", 5, ignoreCase, -1 }; + + yield return new object[] { controlWithItems, "A", -1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "A", 0, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "A", 1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "A", 2, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "A", 5, ignoreCase, -1 }; + + yield return new object[] { controlWithItems, "abcd", -1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "abcd", 0, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "abcd", 1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "abcd", 2, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "abcd", 5, ignoreCase, -1 }; + + yield return new object[] { controlWithItems, "def", -1, ignoreCase, 3 }; + yield return new object[] { controlWithItems, "def", 0, ignoreCase, 3 }; + yield return new object[] { controlWithItems, "def", 1, ignoreCase, 3 }; + yield return new object[] { controlWithItems, "def", 2, ignoreCase, 3 }; + yield return new object[] { controlWithItems, "def", 5, ignoreCase, 3 }; + + yield return new object[] { controlWithItems, null, -1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, null, 0, ignoreCase, -1 }; + yield return new object[] { controlWithItems, null, 1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, null, 2, ignoreCase, -1 }; + yield return new object[] { controlWithItems, null, 5, ignoreCase, -1 }; + + yield return new object[] { controlWithItems, string.Empty, -1, ignoreCase, 4 }; + yield return new object[] { controlWithItems, string.Empty, 0, ignoreCase, 4 }; + yield return new object[] { controlWithItems, string.Empty, 1, ignoreCase, 4 }; + yield return new object[] { controlWithItems, string.Empty, 2, ignoreCase, 4 }; + yield return new object[] { controlWithItems, string.Empty, 5, ignoreCase, 4 }; + + yield return new object[] { controlWithItems, "NoSuchItem", -1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 0, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 1, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 2, ignoreCase, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 5, ignoreCase, -1 }; + } + } + + [Theory] + [MemberData(nameof(FindStringExact_TestData))] + public void FindStringExact_Invoke_ReturnsExpected(ComboBox control, string s, int startIndex, bool ignoreCase, int expected) + { + if (ignoreCase) + { + if (startIndex == -1) + { + Assert.Equal(expected, control.FindStringExact(s)); + } + + Assert.Equal(expected, control.FindStringExact(s, startIndex)); + } + + Assert.Equal(expected, control.FindStringExact(s, startIndex, ignoreCase)); + } + + [Theory] + [InlineData(-2)] + [InlineData(1)] + [InlineData(2)] + public void FindStringExact_InvalidStartIndex_ThrowsArgumentOutOfRangeException(int startIndex) + { + var control = new ComboBox(); + control.Items.Add("item"); + Assert.Throws("startIndex", () => control.FindStringExact("s", startIndex)); + Assert.Throws("startIndex", () => control.FindStringExact("s", startIndex, ignoreCase: true)); + Assert.Throws("startIndex", () => control.FindStringExact("s", startIndex, ignoreCase: false)); + } + + private class SubComboBox : ComboBox + { + public new bool AllowSelection => base.AllowSelection; + + public new CurrencyManager DataManager => base.DataManager; + + public new Size DefaultMaximumSize => base.DefaultMaximumSize; + + public new Size DefaultMinimumSize => base.DefaultMinimumSize; + + public new Padding DefaultPadding => base.DefaultPadding; + + public new Size DefaultSize => base.DefaultSize; + } + + private class DataClass + { + public string Value { get; set; } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ContainerControlTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ContainerControlTests.cs new file mode 100644 index 00000000000..0f586964ce8 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ContainerControlTests.cs @@ -0,0 +1,422 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class ContainerControlTests + { + [Fact] + public void Ctor_Default() + { + var control = new SubContainerControl(); + Assert.Null(control.ActiveControl); + Assert.False(control.AutoScroll); + Assert.Equal(SizeF.Empty, control.AutoScaleDimensions); + Assert.Equal(new SizeF(1, 1), control.AutoScaleFactor); + Assert.Equal(AutoScaleMode.Inherit, control.AutoScaleMode); + Assert.Equal(Size.Empty, control.AutoScrollMargin); + Assert.Equal(Point.Empty, control.AutoScrollPosition); + Assert.Equal(AutoValidate.EnablePreventFocusChange, control.AutoValidate); + Assert.NotNull(control.BindingContext); + Assert.Same(control.BindingContext, control.BindingContext); + Assert.Equal(Rectangle.Empty, control.Bounds); + Assert.False(control.CanEnableIme); + Assert.True(control.CanProcessMnemonic()); + Assert.Equal(Size.Empty, control.ClientSize); + Assert.Equal(Rectangle.Empty, control.ClientRectangle); + Assert.Equal(SizeF.Empty, control.CurrentAutoScaleDimensions); + Assert.NotNull(control.DockPadding); + Assert.Same(control.DockPadding, control.DockPadding); + Assert.Equal(0, control.DockPadding.Top); + Assert.Equal(0, control.DockPadding.Bottom); + Assert.Equal(0, control.DockPadding.Left); + Assert.Equal(0, control.DockPadding.Right); + Assert.Equal(Rectangle.Empty, control.DisplayRectangle); + Assert.NotNull(control.HorizontalScroll); + Assert.Same(control.HorizontalScroll, control.HorizontalScroll); + Assert.False(control.HScroll); + Assert.Equal(Padding.Empty, control.Padding); + Assert.Null(control.ParentForm); + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.NotNull(control.VerticalScroll); + Assert.Same(control.VerticalScroll, control.VerticalScroll); + Assert.False(control.VScroll); + Assert.True(control.Visible); + } + + [Fact] + public void ActiveControl_Set_GetReturnsExpected() + { + var control = new ContainerControl(); + var child = new Control(); + var grandchild = new Control(); + control.Controls.Add(child); + child.Controls.Add(grandchild); + + control.ActiveControl = child; + Assert.Same(child, control.ActiveControl); + + // Set same. + control.ActiveControl = child; + Assert.Same(child, control.ActiveControl); + + // Set grandchild. + control.ActiveControl = grandchild; + Assert.Same(grandchild, control.ActiveControl); + + // Set null. + control.ActiveControl = null; + Assert.Null(control.ActiveControl); + } + + [Fact] + public void ActiveControl_SetInvalid_ThrowsArgumentException() + { + var control = new ContainerControl(); + Assert.Throws("value", () => control.ActiveControl = control); + Assert.Throws("value", () => control.ActiveControl = new Control()); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoNegatives)] + public void AutoScaleDimensions_Set_GetReturnsExpected(Size value) + { + var control = new ContainerControl + { + AutoScaleDimensions = value + }; + Assert.Equal(value, control.AutoScaleDimensions); + + // Set same. + control.AutoScaleDimensions = value; + Assert.Equal(value, control.AutoScaleDimensions); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoNegatives)] + public void AutoScaleDimensions_SetWithChildren_GetReturnsExpected(Size value) + { + var child = new Control(); + var control = new ContainerControl(); + control.Controls.Add(child); + + control.AutoScaleDimensions = value; + Assert.Equal(value, control.AutoScaleDimensions); + + // Set same. + control.AutoScaleDimensions = value; + Assert.Equal(value, control.AutoScaleDimensions); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoPositives)] + public void AutoScaleDimensions_SetInvalid_ThrowsArgumentOutOfRangeException(Size value) + { + var control = new ContainerControl(); + Assert.Throws("value", () => control.AutoScaleDimensions = value); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(AutoScaleMode))] + public void AutoScaleMode_Set_GetReturnsExpected(AutoScaleMode value) + { + var control = new ContainerControl + { + AutoScaleMode = value + }; + Assert.Equal(value, control.AutoScaleMode); + + // Set same. + control.AutoScaleMode = value; + Assert.Equal(value, control.AutoScaleMode); + } + + public static IEnumerable AutoScaleMode_SetDifferent_TestData() + { + yield return new object[] { AutoScaleMode.None, SizeF.Empty }; + yield return new object[] { AutoScaleMode.Dpi, new SizeF(96, 96) }; + yield return new object[] { AutoScaleMode.Inherit, SizeF.Empty }; + } + + [Theory] + [MemberData(nameof(AutoScaleMode_SetDifferent_TestData))] + public void AutoScaleMode_SetDifferent_ResetsAutoScaleDimensions(AutoScaleMode value, SizeF expectedAutoScaleDimensions) + { + var control = new ContainerControl + { + AutoScaleDimensions = new SizeF(1, 2), + AutoScaleMode = AutoScaleMode.Font + }; + + control.AutoScaleMode = value; + Assert.Equal(value, control.AutoScaleMode); + Assert.Equal(expectedAutoScaleDimensions, control.AutoScaleDimensions); + Assert.Equal(expectedAutoScaleDimensions, control.CurrentAutoScaleDimensions); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(AutoScaleMode))] + public void AutoScaleMode_SetInvalid_ThrowsInvalidEnumArgumentException(AutoScaleMode value) + { + var control = new ContainerControl(); + Assert.Throws("value", () => control.AutoScaleMode = value); + } + + public static IEnumerable AutoValidate_Set_TestData() + { + yield return new object[] { AutoValidate.Disable, AutoValidate.Disable }; + yield return new object[] { AutoValidate.EnablePreventFocusChange, AutoValidate.EnablePreventFocusChange }; + yield return new object[] { AutoValidate.EnableAllowFocusChange, AutoValidate.EnableAllowFocusChange }; + yield return new object[] { AutoValidate.Inherit, AutoValidate.EnablePreventFocusChange }; + } + + [Theory] + [MemberData(nameof(AutoValidate_Set_TestData))] + public void AutoValidate_Set_GetReturnsExpected(AutoValidate value, AutoValidate expected) + { + var control = new ContainerControl + { + AutoValidate = value + }; + Assert.Equal(expected, control.AutoValidate); + + // Set same. + control.AutoValidate = value; + Assert.Equal(expected, control.AutoValidate); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(AutoValidate))] + public void AutoValidate_SetInvalid_ThrowsInvalidEnumArgumentException(AutoValidate value) + { + var control = new ContainerControl(); + Assert.Throws("value", () => control.AutoValidate = value); + } + + [Fact] + public void AutoValidate_SetWithHandler_CallsAutoValidateChanged() + { + var control = new ContainerControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.AutoValidateChanged += handler; + + // Set different. + control.AutoValidate = AutoValidate.EnablePreventFocusChange; + Assert.Equal(AutoValidate.EnablePreventFocusChange, control.AutoValidate); + Assert.Equal(1, callCount); + + // Set same. + control.AutoValidate = AutoValidate.EnablePreventFocusChange; + Assert.Equal(AutoValidate.EnablePreventFocusChange, control.AutoValidate); + Assert.Equal(1, callCount); + + // Set different. + control.AutoValidate = AutoValidate.EnableAllowFocusChange; + Assert.Equal(AutoValidate.EnableAllowFocusChange, control.AutoValidate); + Assert.Equal(2, callCount); + + // Remove handler. + control.AutoValidateChanged -= handler; + control.AutoValidate = AutoValidate.Disable; + Assert.False(control.AutoSize); + Assert.Equal(2, callCount); + } + + [Fact] + public void BindingContext_Set_GetReturnsExpected() + { + var value = new BindingContext(); + var control = new ContainerControl + { + BindingContext = value + }; + Assert.Same(value, control.BindingContext); + + // Set same. + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + + // Set null. + control.BindingContext = null; + Assert.NotNull(control.BindingContext); + } + + [Fact] + public void BindingContext_SetWithHandler_CallsBindingContextChanged() + { + var control = new ContainerControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BindingContextChanged += handler; + + // Set different. + var value1 = new BindingContext(); + control.BindingContext = value1; + Assert.Same(value1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set same. + control.BindingContext = value1; + Assert.Same(value1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set different. + var value2 = new BindingContext(); + control.BindingContext = value2; + Assert.Equal(value2, control.BindingContext); + Assert.Equal(2, callCount); + + // Remove handler. + var value3 = new BindingContext(); + control.BindingContextChanged -= handler; + control.BindingContext = value3; + Assert.Same(value3, control.BindingContext); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void Font_Set_GetReturnsExpected(Font value) + { + var control = new ContainerControl + { + Font = value + }; + Assert.Same(value ?? Control.DefaultFont, control.Font); + + // Set same. + control.Font = value; + Assert.Same(value ?? Control.DefaultFont, control.Font); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void Font_SetWithAutoScaleFont_GetReturnsExpected(Font value) + { + var control = new SubContainerControl + { + AutoScaleMode = AutoScaleMode.Font + }; + + control.Font = value; + Assert.Same(value ?? Control.DefaultFont, control.Font); + Assert.Equal(new Size(1, 1), control.AutoScaleFactor); + + // Set same. + control.Font = value; + Assert.Same(value ?? Control.DefaultFont, control.Font); + Assert.Equal(new Size(1, 1), control.AutoScaleFactor); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(AutoScaleMode))] + public void PerformAutoScale_InvokeWithoutChildren_Success(AutoScaleMode autoScaleMode) + { + var control = new SubContainerControl + { + AutoScaleMode = autoScaleMode + }; + control.PerformAutoScale(); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(AutoScaleMode))] + public void PerformAutoScale_InvokeWithChildren_Success(AutoScaleMode autoScaleMode) + { + var child = new Control(); + var control = new SubContainerControl + { + AutoScaleMode = autoScaleMode + }; + control.Controls.Add(child); + control.PerformAutoScale(); + } + + [Fact] + public void CreateControl_Invoke_CallsBindingContextChanged() + { + var control = new ContainerControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BindingContextChanged += handler; + + // Set different. + var value1 = new BindingContext(); + control.BindingContext = value1; + Assert.Same(value1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set same. + control.BindingContext = value1; + Assert.Same(value1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set different. + var value2 = new BindingContext(); + control.BindingContext = value2; + Assert.Equal(value2, control.BindingContext); + Assert.Equal(2, callCount); + + // Remove handler. + var value3 = new BindingContext(); + control.BindingContextChanged -= handler; + control.BindingContext = value3; + Assert.Same(value3, control.BindingContext); + Assert.Equal(2, callCount); + } + + [Fact] + public void Dispose_Invoke_ResetsActiveControl() + { + var control = new ContainerControl(); + var child = new Control(); + control.Controls.Add(child); + control.ActiveControl = child; + + control.Dispose(); + Assert.Null(control.ActiveControl); + } + + private class SubContainerControl : ContainerControl + { + public new SizeF AutoScaleFactor => base.AutoScaleFactor; + + public new bool CanEnableIme => base.CanEnableIme; + + public new bool HScroll + { + get => base.HScroll; + set => base.HScroll = value; + } + + public new bool VScroll + { + get => base.VScroll; + set => base.VScroll = value; + } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/ControlTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs similarity index 71% rename from src/System.Windows.Forms/tests/UnitTests/ControlTests.cs rename to src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs index cadc1953d21..40e2c13fa87 100644 --- a/src/System.Windows.Forms/tests/UnitTests/ControlTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs @@ -2,123 +2,172 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Xunit; +using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using Moq; using WinForms.Common.Tests; +using Xunit; namespace System.Windows.Forms.Tests { public class ControlTests { - - #region Constructor - [Fact] - public void Control_Constructor() - { - var cont = new Control(); - - Assert.NotNull(cont); - Assert.Equal(DpiHelper.DeviceDpi, cont.deviceDpi); - Assert.True(cont.RequiredScalingEnabled); - Assert.Equal(BoundsSpecified.All, cont.RequiredScaling); - Assert.Equal(0, cont.TabIndex); - Assert.Equal(Size.Empty, cont.Size); - Assert.Null(cont.Parent); - Assert.True(cont.TabStop); - Assert.Equal(cont.Location, new Point()); - Assert.True(cont.Enabled); - Assert.Equal(Control.DefaultFont, cont.Font); - Assert.Equal(Control.DefaultForeColor, cont.ForeColor); - Assert.Equal(Control.DefaultBackColor, cont.BackColor); - Assert.Equal("", cont.Text); - Assert.True(cont.Visible); - Assert.False(cont.Created); + public void Control_Ctor_Default() + { + var control = new Control(); + Assert.Equal(Control.DefaultBackColor, control.BackColor); + Assert.Null(control.BindingContext); + Assert.Equal(0, control.Bottom); + Assert.False(control.Created); + Assert.Equal(DpiHelper.DeviceDpi, control.deviceDpi); + Assert.True(control.Enabled); + Assert.Equal(Control.DefaultFont, control.Font); + Assert.Equal(Control.DefaultForeColor, control.ForeColor); + Assert.Equal(0, control.Left); + Assert.Equal(Point.Empty, control.Location); + Assert.Null(control.Parent); + Assert.Equal(BoundsSpecified.All, control.RequiredScaling); + Assert.True(control.RequiredScalingEnabled); + Assert.Equal(0, control.Right); + Assert.Equal(Size.Empty, control.Size); + Assert.Equal(0, control.TabIndex); + Assert.True(control.TabStop); + Assert.Empty(control.Text); + Assert.Equal(0, control.Top); + Assert.True(control.Visible); } - [Fact] - public void Control_ConstructorText() - { - var cont = new Control("Foo"); - - Assert.Equal("Foo", cont.Text); - Assert.Null(cont.Parent); - Assert.True(cont.TabStop); - Assert.Equal(cont.Location, new Point()); - Assert.True(cont.Enabled); - Assert.Equal(Control.DefaultFont, cont.Font); - Assert.Equal(Control.DefaultForeColor, cont.ForeColor); - Assert.Equal(Control.DefaultBackColor, cont.BackColor); - Assert.True(cont.Visible); - Assert.False(cont.Created); + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void Control_Ctor_String(string text) + { + var control = new Control(text); + Assert.Equal(Control.DefaultBackColor, control.BackColor); + Assert.Null(control.BindingContext); + Assert.Equal(0, control.Bottom); + Assert.False(control.Created); + Assert.Equal(DpiHelper.DeviceDpi, control.deviceDpi); + Assert.True(control.Enabled); + Assert.Equal(Control.DefaultFont, control.Font); + Assert.Equal(Control.DefaultForeColor, control.ForeColor); + Assert.Equal(0, control.Left); + Assert.Equal(Point.Empty, control.Location); + Assert.Null(control.Parent); + Assert.Equal(BoundsSpecified.All, control.RequiredScaling); + Assert.True(control.RequiredScalingEnabled); + Assert.Equal(0, control.Right); + Assert.Equal(Size.Empty, control.Size); + Assert.Equal(0, control.TabIndex); + Assert.True(control.TabStop); + Assert.Equal(text ?? string.Empty, control.Text); + Assert.Equal(0, control.Top); + Assert.True(control.Visible); + } + + public static IEnumerable Ctor_String_Int_Int_Int_Int() + { + yield return new object[] { null, -1, -2, -3, -4 }; + yield return new object[] { string.Empty, 0, 0, 0, 0 }; + yield return new object[] { "Foo", 1, 2, 3, 4 }; } - [Fact] - public void Control_ConstructorSize() - { - var cont = new Control("Foo", 1, 2, 3, 4); - - Assert.Equal("Foo", cont.Text); - Assert.Equal(1, cont.Left); - Assert.Equal(2, cont.Top); - Assert.Equal(3, cont.Width); - Assert.Equal(4, cont.Height); - Assert.True(cont.TabStop); - Assert.True(cont.Enabled); - Assert.Equal(Control.DefaultFont, cont.Font); - Assert.Equal(Control.DefaultForeColor, cont.ForeColor); - Assert.Equal(Control.DefaultBackColor, cont.BackColor); - Assert.True(cont.Visible); - Assert.False(cont.Created); + [Theory] + [MemberData(nameof(Ctor_String_Int_Int_Int_Int))] + public void Control_ConstructorSize(string text, int left, int top, int width, int height) + { + var control = new Control(text, left, top, width, height); + Assert.Equal(Control.DefaultBackColor, control.BackColor); + Assert.Null(control.BindingContext); + Assert.Equal(top + height, control.Bottom); + Assert.False(control.Created); + Assert.Equal(DpiHelper.DeviceDpi, control.deviceDpi); + Assert.True(control.Enabled); + Assert.Equal(Control.DefaultFont, control.Font); + Assert.Equal(Control.DefaultForeColor, control.ForeColor); + Assert.Equal(left, control.Left); + Assert.Equal(new Point(left, top), control.Location); + Assert.Null(control.Parent); + Assert.Equal(BoundsSpecified.All, control.RequiredScaling); + Assert.True(control.RequiredScalingEnabled); + Assert.Equal(left + width, control.Right); + Assert.Equal(new Size(width, height), control.Size); + Assert.Equal(0, control.TabIndex); + Assert.True(control.TabStop); + Assert.Equal(text ?? string.Empty, control.Text); + Assert.Equal(top, control.Top); + Assert.True(control.Visible); + } + + public static IEnumerable Ctor_Control_String_TestData() + { + yield return new object[] { null, null }; + yield return new object[] { new Control(), string.Empty }; + yield return new object[] { new Control(), "text" }; } - [Fact] - public void Control_ConstructorParent() - { - var parent = new Control(); - - var cont = new Control(parent, "Foo"); - - Assert.NotNull(cont.Parent); - Assert.Equal(parent, cont.Parent); - Assert.Equal("Foo", cont.Text); - Assert.Equal(Size.Empty, cont.Size); - Assert.True(cont.TabStop); - Assert.Equal(cont.Location, new Point()); - Assert.True(cont.Enabled); - Assert.Equal(Control.DefaultFont, cont.Font); - Assert.Equal(Control.DefaultForeColor, cont.ForeColor); - Assert.Equal(Control.DefaultBackColor, cont.BackColor); - Assert.True(cont.Visible); - Assert.False(cont.Created); + [Theory] + [MemberData(nameof(Ctor_Control_String_TestData))] + public void Control_Ctor_Control_String(Control parent, string text) + { + var control = new Control(parent, text); + Assert.Equal(Control.DefaultBackColor, control.BackColor); + Assert.Null(control.BindingContext); + Assert.Equal(0, control.Bottom); + Assert.False(control.Created); + Assert.Equal(DpiHelper.DeviceDpi, control.deviceDpi); + Assert.True(control.Enabled); + Assert.Equal(Control.DefaultFont, control.Font); + Assert.Equal(Control.DefaultForeColor, control.ForeColor); + Assert.Equal(0, control.Left); + Assert.Equal(Point.Empty, control.Location); + Assert.Same(parent, control.Parent); + Assert.Equal(BoundsSpecified.All, control.RequiredScaling); + Assert.True(control.RequiredScalingEnabled); + Assert.Equal(0, control.Right); + Assert.Equal(Size.Empty, control.Size); + Assert.Equal(0, control.TabIndex); + Assert.True(control.TabStop); + Assert.Equal(text ?? string.Empty, control.Text); + Assert.Equal(0, control.Top); + Assert.True(control.Visible); + } + + public static IEnumerable Ctor_Control_String_Int_Int_Int_Int_TestData() + { + yield return new object[] { null, null, -1, -2, -3, -4 }; + yield return new object[] { new Control(), string.Empty, 0, 0, 0, 0 }; + yield return new object[] { new Control(), "text", 1, 2, 3, 4 }; } - [Fact] - public void Control_ConstructorAll() - { - var parent = new Control(); - - var cont = new Control(parent, "Foo", 1, 2, 3, 4); - - Assert.Equal(parent, cont.Parent); - Assert.Equal("Foo", cont.Text); - Assert.Equal(1, cont.Left); - Assert.Equal(2, cont.Top); - Assert.Equal(3, cont.Width); - Assert.Equal(4, cont.Height); - Assert.True(cont.TabStop); - Assert.True(cont.Enabled); - Assert.Equal(Control.DefaultFont, cont.Font); - Assert.Equal(Control.DefaultForeColor, cont.ForeColor); - Assert.Equal(Control.DefaultBackColor, cont.BackColor); - Assert.True(cont.Visible); - Assert.False(cont.Created); + [Theory] + [MemberData(nameof(Ctor_Control_String_Int_Int_Int_Int_TestData))] + public void Control_Ctor_Control_String_Int_Int_Int_Int(Control parent, string text, int left, int top, int width, int height) + { + var control = new Control(parent, text, left, top, width, height); + Assert.Equal(Control.DefaultBackColor, control.BackColor); + Assert.Null(control.BindingContext); + Assert.Equal(top + height, control.Bottom); + Assert.False(control.Created); + Assert.Equal(DpiHelper.DeviceDpi, control.deviceDpi); + Assert.True(control.Enabled); + Assert.Equal(Control.DefaultFont, control.Font); + Assert.Equal(Control.DefaultForeColor, control.ForeColor); + Assert.Equal(left, control.Left); + Assert.Equal(new Point(left, top), control.Location); + Assert.Same(parent, control.Parent); + Assert.Equal(BoundsSpecified.All, control.RequiredScaling); + Assert.True(control.RequiredScalingEnabled); + Assert.Equal(left + width, control.Right); + Assert.Equal(new Size(width, height), control.Size); + Assert.Equal(0, control.TabIndex); + Assert.True(control.TabStop); + Assert.Equal(text ?? string.Empty, control.Text); + Assert.Equal(top, control.Top); + Assert.True(control.Visible); } - #endregion - #region Control Creation [Fact] @@ -692,14 +741,22 @@ public void Control_RegionGetSet() } [Theory] - [MemberData(nameof(AutoSizeGetSetData))] - public void Control_AutoSizeGetSet(bool expected) + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Control_AutoSize_Set_GetReturnsExpected(bool value) { - var cont = new Control(); + var control = new Control + { + AutoSize = value + }; + Assert.Equal(value, control.AutoSize); - cont.AutoSize = expected; + // Set same. + control.AutoSize = value; + Assert.Equal(value, control.AutoSize); - Assert.Equal(expected, cont.AutoSize); + // Set different. + control.AutoSize = value; + Assert.Equal(value, control.AutoSize); } [Fact] @@ -731,20 +788,12 @@ public void Control_ApplySizeConstraints(int expected) Assert.Equal(expectedSize, actualSize); } - /// - /// Data for the ApplySizeConstraintsSize test - /// - public static TheoryData ApplySizeConstraintsSizeData => - TestHelper.GetSizeTheoryData(); - [Theory] - [MemberData(nameof(ApplySizeConstraintsSizeData))] - public void Control_ApplySizeConstraintsSize(Size expectedSize) + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] + public void Control_ApplySizeConstraintsSize_Invoke_ReturnsExpected(Size expectedSize) { - var cont = new Control(); - - var actualSize = cont.ApplySizeConstraints(expectedSize); - + var control = new Control(); + var actualSize = control.ApplySizeConstraints(expectedSize); Assert.Equal(expectedSize, actualSize); } @@ -772,21 +821,19 @@ public void Control_ApplyBoundsConstraints(int expected) #endregion - /// - /// Data for the PaddingGetSet test - /// - public static TheoryData PaddingGetSetData => - TestHelper.GetPaddingTheoryData(); - [Theory] - [MemberData(nameof(PaddingGetSetData))] - public void Control_PaddingGetSet(Padding expected) + [CommonMemberData(nameof(CommonTestHelper.GetPaddingNormalizedTheoryData))] + public void Control_Padding_Set_GetReturnsExpected(Padding value, Padding expected) { - var cont = new Control(); - - cont.Padding = expected; + var control = new Control + { + Padding = value + }; + Assert.Equal(expected, control.Padding); - Assert.Equal(expected, cont.Padding); + // Set same. + control.Padding = value; + Assert.Equal(expected, control.Padding); } /// @@ -868,106 +915,98 @@ public void Control_TopGetSet(int expected) Assert.Equal(expected, cont.Top); } - /// - /// Data for the IsAccessibleGetSet test - /// - public static TheoryData LocationGetSetData => - TestHelper.GetPointTheoryData(); - [Theory] - [MemberData(nameof(LocationGetSetData))] - public void Control_LocationGetSet(Point expected) + [CommonMemberData(nameof(CommonTestHelper.GetPointTheoryData))] + public void Control_LocationGetSet(Point value) { - var cont = new Control(); - - cont.Location = expected; + var control = new Control + { + Location = value + }; + Assert.Equal(value, control.Location); - Assert.Equal(expected, cont.Location); + // Set same. + control.Location = value; + Assert.Equal(value, control.Location); } - /// - /// Data for the MarginGetSet test - /// - public static TheoryData MarginGetSetData => - TestHelper.GetPaddingTheoryData(); - [Theory] - [MemberData(nameof(MarginGetSetData))] - public void Control_MarginGetSet(Padding expected) + [CommonMemberData(nameof(CommonTestHelper.GetPaddingNormalizedTheoryData))] + public void Control_Margin_Set_GetReturnsExpected(Padding value, Padding expected) { - var cont = new Control(); - - cont.Margin = expected; + var control = new Control + { + Margin = value + }; + Assert.Equal(expected, control.Margin); - Assert.Equal(expected, cont.Margin); + // Set same. + control.Margin = value; + Assert.Equal(expected, control.Margin); } - /// - /// Data for the MaximumSizeGetSet test - /// - public static TheoryData MaximumSizeGetSetData => - TestHelper.GetSizeTheoryData(); - [Theory] - [MemberData(nameof(MaximumSizeGetSetData))] - public void Control_MaximumSizeGetSet(Size expected) + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] + public void Control_MaximumSize_Set_GetReturnsExpected(Size value) { - var cont = new Control(); - - cont.MaximumSize = expected; + var control = new Control + { + MaximumSize = value + }; + Assert.Equal(value, control.MaximumSize); - Assert.Equal(expected, cont.MaximumSize); + // Set same. + control.MaximumSize = value; + Assert.Equal(value, control.MaximumSize); } - /// - /// Data for the MinimumSizeGetSet test - /// - public static TheoryData MinimumSizeGetSetData => - TestHelper.GetSizeTheoryData(); - [Theory] - [MemberData(nameof(MinimumSizeGetSetData))] - public void Control_MinimumSizeGetSet(Size expected) + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] + public void Control_MinimumSize_Set_GetReturnsExpected(Size value) { - var cont = new Control(); - - cont.MinimumSize = expected; + var control = new Control + { + MinimumSize = value + }; + Assert.Equal(value, control.MinimumSize); - Assert.Equal(expected, cont.MinimumSize); + // Set same. + control.MinimumSize = value; + Assert.Equal(value, control.MinimumSize); } - /// - /// Data for the RequiredScaling test - /// - public static TheoryData RequiredScalingData => - CommonTestHelper.GetEnumTheoryData(); - [Theory] - [MemberData(nameof(RequiredScalingData))] - public void Control_RequiredScaling(BoundsSpecified expected) + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(BoundsSpecified))] + public void Control_RequiredScaling_Set_GetReturnsExpected(BoundsSpecified value) { - var cont = new Control(); - - cont.RequiredScaling = expected; + var control = new Control + { + RequiredScaling = value + }; + Assert.Equal(value, control.RequiredScaling); - Assert.Equal(expected, cont.RequiredScaling); + // Set same. + control.RequiredScaling = value; + Assert.Equal(value, control.RequiredScaling); } - /// - /// Data for the RequiredScalingEnabled test - /// - public static TheoryData RequiredScalingEnabledData => - CommonTestHelper.GetBoolTheoryData(); - [Theory] - [MemberData(nameof(RequiredScalingEnabledData))] - public void Control_RequiredScalingEnabled(bool expected) + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Control_RequiredScalingEnabled_Get_ReturnsExpected(bool value) { - var cont = new Control(); + var control = new Control + { + RequiredScalingEnabled = value + }; + Assert.Equal(value, control.RequiredScalingEnabled); - cont.RequiredScalingEnabled = expected; + // Set same. + control.RequiredScalingEnabled = value; + Assert.Equal(value, control.RequiredScalingEnabled); - Assert.Equal(expected, cont.RequiredScalingEnabled); + // Set different. + control.RequiredScalingEnabled = !value; + Assert.Equal(!value, control.RequiredScalingEnabled); } [Theory] @@ -995,38 +1034,27 @@ public void Control_RightToLeftInherit() Assert.Equal(RightToLeft.Yes, cont.RightToLeft); } - /// - /// Data for the RightToLeftInvalid test - /// - public static TheoryData RightToLeftInvalidData => - CommonTestHelper.GetEnumTheoryDataInvalid(); - [Theory] - [MemberData(nameof(RightToLeftInvalidData))] - public void Control_RightToLeftInvalid(RightToLeft expected) + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(RightToLeft))] + public void Control_RightToLeft_SetInvalid_ThrowsInvalidEnumArgumentException(RightToLeft value) { - var cont = new Control(); - - // act & assert - var ex = Assert.Throws(() => cont.RightToLeft = expected); - Assert.Equal("RightToLeft", ex.ParamName); + var control = new Control(); + Assert.Throws("value", () => control.RightToLeft = value); } - /// - /// Data for the SizeGetSet test - /// - public static TheoryData SizeGetSetData => - TestHelper.GetSizeTheoryData(); - [Theory] - [MemberData(nameof(SizeGetSetData))] - public void Control_SizeGetSet(Size expected) + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] + public void Control_SizeGetSet(Size value) { - var cont = new Control(); - - cont.Size = expected; + var control = new Control + { + Size = value + }; + Assert.Equal(value, control.Size); - Assert.Equal(expected, cont.Size); + // Set same. + control.Size = value; + Assert.Equal(value, control.Size); } /// @@ -1311,21 +1339,19 @@ public void Control_Hide() #region Font - /// - /// Data for the FontGetSet test - /// - public static TheoryData FontGetSetData => - TestHelper.GetFontTheoryData(); - [Theory] - [MemberData(nameof(FontGetSetData))] - public void Control_FontGetSet(Font expected) + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void Control_FontGetSet(Font value) { - var cont = new Control(); - - cont.Font = expected; - - Assert.Equal(expected, cont.Font); + var control = new Control + { + Font = value + }; + Assert.Equal(value ?? Control.DefaultFont, control.Font); + + // Set same. + control.Font = value; + Assert.Equal(value ?? Control.DefaultFont, control.Font); } [Theory] @@ -1724,39 +1750,99 @@ public void Control_AllowDropGetSet(bool expected) Assert.Equal(expected, cont.AllowDrop); } - /// - /// Data for the AutoSizeGetSet test - /// - public static TheoryData AutoSizeGetSetData => - CommonTestHelper.GetBoolTheoryData(); + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetPointTheoryData))] + public void Control_AutoScrollOffsetGetSet(Point value) + { + var control = new Control + { + AutoScrollOffset = value + }; + Assert.Equal(value, control.AutoScrollOffset); - /// - /// Data for the AutoScrollOffsetGetSet test - /// - public static TheoryData AutoScrollOffsetGetSetData => - TestHelper.GetPointTheoryData(); + // Set same. + control.AutoScrollOffset = value; + Assert.Equal(value, control.AutoScrollOffset); + } + + public static IEnumerable BindingContext_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new BindingContext() }; + } [Theory] - [MemberData(nameof(AutoScrollOffsetGetSetData))] - public void Control_AutoScrollOffsetGetSet(Point expected) + [MemberData(nameof(BindingContext_Set_TestData))] + public void Control_BindingContext_Set_GetReturnsExpected(BindingContext value) { - var cont = new Control(); + var control = new Control + { + BindingContext = value + }; + Assert.Same(value, control.BindingContext); + + // Set same. + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + } + + [Theory] + [MemberData(nameof(BindingContext_Set_TestData))] + public void Control_BindingContext_SetWithNonNullBindingContext_GetReturnsExpected(BindingContext value) + { + var control = new Control + { + BindingContext = new BindingContext() + }; - cont.AutoScrollOffset = expected; + control.BindingContext = value; + Assert.Same(value, control.BindingContext); - Assert.Equal(expected, cont.AutoScrollOffset); + // Set same. + control.BindingContext = value; + Assert.Same(value, control.BindingContext); } [Fact] - public void Control_BindingContextGetSet() + public void Control_BindingContext_SetWithHandler_CallsBindingContextChanged() { - var cont = new Control(); - var expected = new BindingContext(); + var control = new Control(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BindingContextChanged += handler; + + // Set different. + var context1 = new BindingContext(); + control.BindingContext = context1; + Assert.Same(context1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set same. + control.BindingContext = context1; + Assert.Same(context1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set different. + var context2 = new BindingContext(); + control.BindingContext = context2; + Assert.Same(context2, control.BindingContext); + Assert.Equal(2, callCount); - cont.BindingContext = expected; + // Set null. + control.BindingContext = null; + Assert.Null(control.BindingContext); + Assert.Equal(3, callCount); - Assert.NotNull(cont.BindingContext); - Assert.Equal(expected, cont.BindingContext); + // Remove handler. + control.BindingContextChanged -= handler; + control.BindingContext = context1; + Assert.Same(context1, control.BindingContext); + Assert.Equal(3, callCount); } /// @@ -1788,21 +1874,19 @@ public void Control_CacheTextInternalGetSet(bool given, bool expected) Assert.Equal(expected, cont.CacheTextInternal); } - /// - /// Data for the ClientSizeGetSet test - /// - public static TheoryData ClientSizeGetSetData => - TestHelper.GetSizeTheoryData(); - [Theory] - [MemberData(nameof(ClientSizeGetSetData))] - public void Control_ClientSizeGetSet(Size expected) + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] + public void Control_ClientSize_Set_GetReturnsExpected(Size value) { - var cont = new Control(); - - cont.ClientSize = expected; + var control = new Control + { + ClientSize = value + }; + Assert.Equal(value, control.ClientSize); - Assert.Equal(expected, cont.ClientSize); + // Set same. + control.ClientSize = value; + Assert.Equal(value, control.ClientSize); } [Fact] @@ -1861,21 +1945,19 @@ public void Control_IsTopMdiWindowClosingGetSet(bool expected) Assert.Equal(expected, cont.IsTopMdiWindowClosing); } - /// - /// Data for the CursorGetSet test - /// - public static TheoryData CursorGetSetData => - TestHelper.GetCursorTheoryData(); - [Theory] - [MemberData(nameof(CursorGetSetData))] - public void Control_CursorGetSet(Cursor expected) + [CommonMemberData(nameof(CommonTestHelper.GetCursorTheoryData))] + public void Control_Cursor_Set_GetReturnsExpected(Cursor value) { - var cont = new Control(); - - cont.Cursor = expected; + var control = new Control + { + Cursor = value + }; + Assert.Same(value ?? Cursors.Default, control.Cursor); - Assert.Equal(expected, cont.Cursor); + // Set same. + control.Cursor = value; + Assert.Same(value ?? Cursors.Default, control.Cursor); } /// diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataFormatsTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataFormatsTests.cs new file mode 100644 index 00000000000..ea154765932 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataFormatsTests.cs @@ -0,0 +1,187 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.InteropServices; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class DataFormatsTests + { + public static IEnumerable KnownFormats_TestData() + { + yield return new object[] { DataFormats.Bitmap, "Bitmap" }; + yield return new object[] { DataFormats.CommaSeparatedValue, "Csv" }; + yield return new object[] { DataFormats.Dib, "DeviceIndependentBitmap" }; + yield return new object[] { DataFormats.Dif, "DataInterchangeFormat" }; + yield return new object[] { DataFormats.EnhancedMetafile, "EnhancedMetafile" }; + yield return new object[] { DataFormats.FileDrop, "FileDrop" }; + yield return new object[] { DataFormats.Html, "HTML Format" }; + yield return new object[] { DataFormats.Locale, "Locale" }; + yield return new object[] { DataFormats.MetafilePict, "MetaFilePict" }; + yield return new object[] { DataFormats.OemText, "OEMText" }; + yield return new object[] { DataFormats.Palette, "Palette" }; + yield return new object[] { DataFormats.PenData, "PenData" }; + yield return new object[] { DataFormats.Riff, "RiffAudio" }; + yield return new object[] { DataFormats.Rtf, "Rich Text Format" }; + yield return new object[] { DataFormats.Serializable, "WindowsForms10PersistentObject" }; + yield return new object[] { DataFormats.StringFormat, "System.String" }; + yield return new object[] { DataFormats.SymbolicLink, "SymbolicLink" }; + yield return new object[] { DataFormats.Text, "Text" }; + yield return new object[] { DataFormats.Tiff, "TaggedImageFileFormat" }; + yield return new object[] { DataFormats.UnicodeText, "UnicodeText" }; + yield return new object[] { DataFormats.WaveAudio, "WaveAudio" }; + } + + [Theory] + [MemberData(nameof(KnownFormats_TestData))] + public void DataFormats_KnownFormat_Get_ReturnsExpected(string value, string expected) + { + Assert.Equal(expected, value); + } + + public static IEnumerable GetFormat_KnownString_TestData() + { + yield return new object[] { DataFormats.Bitmap, "Bitmap", 2 }; + yield return new object[] { DataFormats.Dib, "DeviceIndependentBitmap", 8 }; + yield return new object[] { DataFormats.Dif, "DataInterchangeFormat", 5 }; + yield return new object[] { DataFormats.EnhancedMetafile, "EnhancedMetafile", 14 }; + yield return new object[] { DataFormats.FileDrop, "FileDrop", 15 }; + yield return new object[] { DataFormats.Locale, "Locale", 16 }; + yield return new object[] { DataFormats.MetafilePict, "MetaFilePict", 3 }; + yield return new object[] { DataFormats.OemText, "OEMText", 7 }; + yield return new object[] { DataFormats.Palette, "Palette", 9 }; + yield return new object[] { DataFormats.PenData, "PenData", 10 }; + yield return new object[] { DataFormats.Riff, "RiffAudio", 11 }; + yield return new object[] { DataFormats.SymbolicLink, "SymbolicLink", 4 }; + yield return new object[] { DataFormats.Text, "Text", 1 }; + yield return new object[] { DataFormats.Tiff, "TaggedImageFileFormat", 6 }; + yield return new object[] { DataFormats.UnicodeText, "UnicodeText", 13 }; + yield return new object[] { DataFormats.WaveAudio, "WaveAudio", 12 }; + } + + [Theory] + [MemberData(nameof(GetFormat_KnownString_TestData))] + public void DataFormats_GetFormat_InvokeKnownString_ReturnsExpected(string format, string expectedName, int expectedId) + { + DataFormats.Format result = DataFormats.GetFormat(format); + Assert.Same(result, DataFormats.GetFormat(format.ToLower())); + Assert.Equal(expectedName, result.Name); + Assert.Equal(expectedId, result.Id); + + // Call again to test caching behavior. + Assert.Same(result, DataFormats.GetFormat(format)); + } + + public static IEnumerable GetFormat_UnknownString_TestData() + { + yield return new object[] { DataFormats.CommaSeparatedValue, "Csv" }; + yield return new object[] { DataFormats.Html, "HTML Format" }; + yield return new object[] { DataFormats.Rtf, "Rich Text Format" }; + yield return new object[] { DataFormats.Serializable, "WindowsForms10PersistentObject" }; + yield return new object[] { DataFormats.StringFormat, "System.String" }; + yield return new object[] { "Custom", "Custom" }; + } + + [Theory] + [MemberData(nameof(GetFormat_UnknownString_TestData))] + public void DataFormats_GetFormat_InvokeUnknownFormatString_ReturnsExpected(string format, string expectedName) + { + DataFormats.Format result = DataFormats.GetFormat(format); + Assert.Same(result, DataFormats.GetFormat(format)); + Assert.Same(result, DataFormats.GetFormat(format.ToLower())); + Assert.Equal(expectedName, result.Name); + + // Internally the format is registered with RegisterClipboardFormat. + // According to the documentation: "Registered clipboard formats are + // identified by values in the range 0xC000 through 0xFFFF." + Assert.True(result.Id >= 0xC000); + Assert.True(result.Id < 0xFFFF); + + // Should register the format. + Assert.Same(result, DataFormats.GetFormat(result.Id)); + } + + public static IEnumerable GetFormat_InvalidString_TestData() + { + yield return new object[] { null }; + yield return new object[] { string.Empty }; + yield return new object[] { new string('a', 256) }; + } + + [Theory] + [MemberData(nameof(GetFormat_InvalidString_TestData))] + public void DataFormats_GetFormat_NullOrEmptyString_ThrowsWin32Exception(string format) + { + Assert.Throws(() => DataFormats.GetFormat(format)); + } + + [DllImport("user32.dll")] + private static extern int RegisterClipboardFormat(string format); + + public static IEnumerable GetFormat_Int_TestData() + { + yield return new object[] { 2, "Bitmap" }; + yield return new object[] { 8, "DeviceIndependentBitmap" }; + yield return new object[] { 5, "DataInterchangeFormat" }; + yield return new object[] { 14, "EnhancedMetafile" }; + yield return new object[] { 15, "FileDrop" }; + yield return new object[] { 16, "Locale" }; + yield return new object[] { 3, "MetaFilePict" }; + yield return new object[] { 7, "OEMText" }; + yield return new object[] { 9, "Palette" }; + yield return new object[] { 10, "PenData" }; + yield return new object[] { 11, "RiffAudio" }; + yield return new object[] { 4, "SymbolicLink" }; + yield return new object[] { 1, "Text" }; + yield return new object[] { 6, "TaggedImageFileFormat" }; + yield return new object[] { 13, "UnicodeText" }; + yield return new object[] { 12, "WaveAudio" }; + yield return new object[] { 12 & 0xFFFFFFFF, "WaveAudio" }; + + yield return new object[] { -1, "Format65535" }; + yield return new object[] { 1234, "Format1234" }; + + int? manuallyRegisteredFormatId = null; + int? longManuallyRegisteredFormatId = null; + try + { + manuallyRegisteredFormatId = RegisterClipboardFormat("ManuallyRegisteredFormat"); + longManuallyRegisteredFormatId = RegisterClipboardFormat(new string('a', 255)); + } + catch + { + } + + if (manuallyRegisteredFormatId.HasValue) + { + yield return new object[] { manuallyRegisteredFormatId, "ManuallyRegisteredFormat" }; + yield return new object[] { longManuallyRegisteredFormatId, new string('a', 255) }; + } + } + + [Theory] + [MemberData(nameof(GetFormat_Int_TestData))] + public void DataFormats_GetFormat_InvokeId_ReturnsExpected(int id, string expectedName) + { + DataFormats.Format result = DataFormats.GetFormat(id); + Assert.Same(result, DataFormats.GetFormat(id)); + Assert.Equal(expectedName, result.Name); + Assert.Equal(id & 0xFFFF, result.Id); + } + + [Theory] + [InlineData(null, -1)] + [InlineData("", 0)] + [InlineData("name", int.MaxValue)] + public void DataFormats_Format_Ctor_String_Int(string name, int id) + { + var format = new DataFormats.Format(name, id); + Assert.Same(name, format.Name); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridCellTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridCellTests.cs new file mode 100644 index 00000000000..ce1a5e2fb3e --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridCellTests.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class DataGridCellTests + { + [Fact] + public void DataGridCell_Ctor_Default() + { + var cell = new DataGridCell(); + Assert.Equal(0, cell.RowNumber); + Assert.Equal(0, cell.ColumnNumber); + } + + [Theory] + [InlineData(-1, -2)] + [InlineData(0, 0)] + [InlineData(1, 2)] + [InlineData(1, 0)] + [InlineData(0, 1)] + public void DataGridCell_Ctor_Int_Int(int rowNumber, int columnNumber) + { + var cell = new DataGridCell(rowNumber, columnNumber); + Assert.Equal(rowNumber, cell.RowNumber); + Assert.Equal(columnNumber, cell.ColumnNumber); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void DataGridCell_RowNumber_Set_GetReturnsExpected(int value) + { + var cell = new DataGridCell + { + RowNumber = value + }; + Assert.Equal(value, cell.RowNumber); + + // Set same. + cell.RowNumber = value; + Assert.Equal(value, cell.RowNumber); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void DataGridCell_ColumnNumber_Set_GetReturnsExpected(int value) + { + var cell = new DataGridCell + { + ColumnNumber = value + }; + Assert.Equal(value, cell.ColumnNumber); + + // Set same. + cell.ColumnNumber = value; + Assert.Equal(value, cell.ColumnNumber); + } + + public static IEnumerable Equals_TestData() + { + yield return new object[] { new DataGridCell(1, 2), new DataGridCell(1, 2), true }; + yield return new object[] { new DataGridCell(1, 2), new DataGridCell(2, 2), false }; + yield return new object[] { new DataGridCell(1, 2), new DataGridCell(1, 3), false }; + + yield return new object[] { new DataGridCell(1, 2), new object(), false }; + yield return new object[] { new DataGridCell(1, 2), null, false }; + } + + [Theory] + [MemberData(nameof(Equals_TestData))] + public void DataGridCell_Equals_Invoke_ReturnsExpected(DataGridCell cell, object other, bool expected) + { + if (other is DataGridCell otherCell) + { + Assert.Equal(expected, cell.GetHashCode().Equals(otherCell.GetHashCode())); + } + + Assert.Equal(expected, cell.Equals(other)); + } + + [Fact] + public void DataGridCell_ToString_Invoke_ReturnsExpected() + { + var cell = new DataGridCell(1, 2); + Assert.Equal("DataGridCell {RowNumber = 1, ColumnNumber = 2}", cell.ToString()); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgsTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgsTests.cs index a0cdc475361..570f2618fd7 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgsTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowHeightInfoNeededEventArgsTests.cs @@ -50,7 +50,7 @@ public void Height_SetInvalid_ThrowsArgumentOutOfRangeException(int value) DataGridViewRowHeightInfoNeededEventHandler handler = (sender, e) => { callCount++; - Assert.Throws("Height", () => e.Height = value); + Assert.Throws("value", () => e.Height = value); }; dataGridView.RowHeightInfoNeeded += handler; @@ -106,7 +106,7 @@ public void MinimumHeight_SetInvalid_ThrowsArgumentOutOfRangeException(int value DataGridViewRowHeightInfoNeededEventHandler handler = (sender, e) => { callCount++; - Assert.Throws("MinimumHeight", () => e.MinimumHeight = value); + Assert.Throws("value", () => e.MinimumHeight = value); }; dataGridView.RowHeightInfoNeeded += handler; diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowTests.cs index 1e875a74d58..356d0994fd5 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewRowTests.cs @@ -405,7 +405,7 @@ public void DataGridViewRow_DefaultHeaderCellType_SetWithNonNullOldValue_GetRetu public void DataGridViewRow_DefaultHeaderCellType_SetInvalidWithNullOldValue_GetReturnsExpected(Type value) { var row = new SubDataGridViewRow(); - Assert.Throws(null, () => row.DefaultHeaderCellType = value); + Assert.Throws("value", () => row.DefaultHeaderCellType = value); } [Theory] @@ -417,7 +417,7 @@ public void DataGridViewRow_DefaultHeaderCellType_SetInvalidWithNonNullOldValue_ { DefaultHeaderCellType = typeof(DataGridViewRowHeaderCell) }; - Assert.Throws(null, () => row.DefaultHeaderCellType = value); + Assert.Throws("value", () => row.DefaultHeaderCellType = value); } public static IEnumerable Displayed_Get_TestData() @@ -528,7 +528,7 @@ public void DataGridViewRow_DividerHeight_SetWithDataGridView_CallsRowDividerHei public void DataGridViewRow_DividerHeight_SetInvalid_ThrowsArgumentOutOfRangeException(int value) { var row = new DataGridViewRow(); - Assert.Throws("DividerHeight", () => row.DividerHeight = value); + Assert.Throws("value", () => row.DividerHeight = value); } [Theory] @@ -1052,7 +1052,7 @@ public void DataGridViewRow_Height_SetWithDataGridView_CallsRowHeightChanged() public void DataGridViewRow_Height_SetInvalid_ThrowsArgumentOutOfRangeException(int value) { var row = new DataGridViewRow(); - Assert.Throws("Height", () => row.Height = value); + Assert.Throws("value", () => row.Height = value); } [Theory] @@ -1353,14 +1353,14 @@ public void DataGridViewRow_MinimumHeight_SetWithDataGridView_CallsRowMinimumHei } [Theory] - [InlineData(-1, "MinimumHeight")] - [InlineData(0, "MinimumHeight")] - [InlineData(1, "MinimumHeight")] - [InlineData(65537, "Height")] - public void DataGridViewRow_MinimumHeight_SetInvalid_ThrowsArgumentOutOfRangeException(int value, string paramName) + [InlineData(-1)] + [InlineData(0)] + [InlineData(1)] + [InlineData(65537)] + public void DataGridViewRow_MinimumHeight_SetInvalid_ThrowsArgumentOutOfRangeException(int value) { var row = new DataGridViewRow(); - Assert.Throws(paramName, () => row.MinimumHeight = value); + Assert.Throws("value", () => row.MinimumHeight = value); Assert.Equal(3, row.MinimumHeight); Assert.Equal(Control.DefaultFont.Height + 9, row.Height); } @@ -2889,7 +2889,7 @@ public void DataGridViewRow_GetState_Invoke_ReturnsExpected(DataGridViewRow row, public void DataGridViewRow_GetState_NoDataGridViewInvalidRowIndex_ThrowsArgumentException(int rowIndex) { var row = new DataGridViewRow(); - Assert.Throws(null, () => row.GetState(rowIndex)); + Assert.Throws("rowIndex", () => row.GetState(rowIndex)); } [Theory] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FeatureSupportTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FeatureSupportTests.cs new file mode 100644 index 00000000000..f9a53861e3e --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FeatureSupportTests.cs @@ -0,0 +1,201 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Reflection; +using Moq; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class FeatureSupportTests + { + public static IEnumerable IsPresent_DefaultMinimumVersion_TestData() + { + yield return new object[] { null, new object(), false }; + yield return new object[] { new Version(0, 0, 0, 0), new object(), true }; + yield return new object[] { new Version(1, 2, 3, 4), new object(), true }; + } + + [Theory] + [MemberData(nameof(IsPresent_DefaultMinimumVersion_TestData))] + public void FeatureSupport_IsPresent_InvokeDefaultMinimVersion_ReturnsExpected(Version versionPresent, object feature, bool expected) + { + var featureSupport = new Mock(MockBehavior.Strict); + featureSupport + .Setup(s => s.IsPresent(feature)) + .CallBase(); + featureSupport + .Setup(s => s.IsPresent(feature, new Version(0, 0, 0, 0))) + .CallBase(); + featureSupport + .Setup(s => s.GetVersionPresent(feature)) + .Returns(versionPresent); + Assert.Equal(expected, featureSupport.Object.IsPresent(feature)); + } + + public static IEnumerable IsPresent_CustomMinimumVersion_TestData() + { + yield return new object[] { null, new object(), new Version(1, 2, 3, 4), false }; + yield return new object[] { null, new object(), null, false }; + yield return new object[] { new Version(0, 0, 0, 0), new object(), new Version(0, 0, 0, 0), true }; + yield return new object[] { new Version(0, 0, 0, 0), new object(), new Version(1, 2, 3, 4), false }; + yield return new object[] { new Version(0, 0, 0, 0), new object(), null, true }; + yield return new object[] { new Version(1, 2, 3, 4), new object(), new Version(1, 2, 3, 4), true }; + yield return new object[] { new Version(1, 2, 3, 4), new object(), new Version(1, 2, 3, 4), true }; + yield return new object[] { new Version(1, 2, 3, 4), new object(), new Version(2, 3, 4, 5), false }; + yield return new object[] { new Version(1, 2, 3, 4), new object(), null, true }; + } + + [Theory] + [MemberData(nameof(IsPresent_CustomMinimumVersion_TestData))] + public void FeatureSupport_IsPresent_InvokeCustomMinimumVersion_ReturnsExpected(Version versionPresent, object feature, Version minimumVersion, bool expected) + { + var featureSupport = new Mock(MockBehavior.Strict); + featureSupport + .Setup(s => s.IsPresent(feature, minimumVersion)) + .CallBase(); + featureSupport + .Setup(s => s.GetVersionPresent(feature)) + .Returns(versionPresent); + Assert.Equal(expected, featureSupport.Object.IsPresent(feature, minimumVersion)); + } + public static IEnumerable GetVersionPresent_TestData() + { + foreach (string invalidType in new string[] { null, string.Empty, "NoSuchType" }) + { + yield return new object[] { invalidType, null, null }; + yield return new object[] { invalidType, string.Empty, null }; + yield return new object[] { invalidType, "NoSuchField", null }; + } + + yield return new object[] { typeof(NonIFeatureSupportClass).AssemblyQualifiedName, nameof(NonIFeatureSupportClass.s_field), null }; + + yield return new object[] { typeof(IFeatureSupportClass).FullName, nameof(IFeatureSupportClass.s_field), null }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "NoSuchField", null }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "_privateField", null }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "s_privateField", null }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_field), new Version(1, 2, 3, 4) }; + } + + [Theory] + [MemberData(nameof(GetVersionPresent_TestData))] + public void FeatureSupport_GetVersionPresent_Invoke_ReturnsExpected(string featureClassName, string featureConstName, Version expected) + { + Assert.Equal(expected, FeatureSupport.GetVersionPresent(featureClassName, featureConstName)); + } + + [Theory] + [InlineData(typeof(IFeatureSupportClass), nameof(IFeatureSupportClass._field))] + [InlineData(typeof(NonIFeatureSupportClass), nameof(NonIFeatureSupportClass._field))] + public void FeatureSupport_GetVersionPresent_NonStaticField_ThrowsTargetException(Type featureClassType, string featureConstName) + { + Assert.Throws(() => FeatureSupport.GetVersionPresent(featureClassType.AssemblyQualifiedName, featureConstName)); + } + + public static IEnumerable IsPresent_DefaultMinimumVersionClassName_TestData() + { + foreach (string invalidType in new string[] { null, string.Empty, "NoSuchType" }) + { + yield return new object[] { invalidType, null, false }; + yield return new object[] { invalidType, string.Empty, false }; + yield return new object[] { invalidType, "NoSuchField", false }; + } + + yield return new object[] { typeof(NonIFeatureSupportClass).AssemblyQualifiedName, nameof(NonIFeatureSupportClass.s_field), false }; + + yield return new object[] { typeof(IFeatureSupportClass).FullName, nameof(IFeatureSupportClass.s_field), false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "NoSuchField", false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "_privateField", false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "s_privateField", false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_zeroVersionField), true }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_nonZeroVersionField), true }; + } + + [Theory] + [MemberData(nameof(IsPresent_DefaultMinimumVersionClassName_TestData))] + public void FeatureSupport_IsPresent_InvokeDefaultMinimumVersionClassName_ReturnsExpected(string featureClassName, string featureConstName, bool expected) + { + Assert.Equal(expected, FeatureSupport.IsPresent(featureClassName, featureConstName)); + } + + public static IEnumerable IsPresent_CustomMinimumVersionClassName_TestData() + { + foreach (string invalidType in new string[] { null, string.Empty, "NoSuchType" }) + { + yield return new object[] { invalidType, null, new Version(1, 2, 3, 4), false }; + yield return new object[] { invalidType, string.Empty, new Version(1, 2, 3, 4), false }; + yield return new object[] { invalidType, "NoSuchField", new Version(1, 2, 3, 4), false }; + } + + yield return new object[] { typeof(NonIFeatureSupportClass).AssemblyQualifiedName, nameof(NonIFeatureSupportClass.s_field), new Version(1, 2, 3, 4), false }; + + yield return new object[] { typeof(IFeatureSupportClass).FullName, nameof(IFeatureSupportClass.s_field), new Version(1, 2, 3, 4), false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "NoSuchField", new Version(1, 2, 3, 4), false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "_privateField", new Version(1, 2, 3, 4), false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, "s_privateField", new Version(1, 2, 3, 4), false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_zeroVersionField), new Version(0, 0, 0, 0), true }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_zeroVersionField), new Version(1, 2, 3, 4), false }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_nonZeroVersionField), new Version(0, 0, 0, 0), true }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_nonZeroVersionField), new Version(1, 2, 3, 4), true }; + yield return new object[] { typeof(IFeatureSupportClass).AssemblyQualifiedName, nameof(IFeatureSupportClass.s_nonZeroVersionField), new Version(2, 3, 4, 5), false }; + } + + [Theory] + [MemberData(nameof(IsPresent_CustomMinimumVersionClassName_TestData))] + public void FeatureSupport_IsPresent_InvokeCustomMinimumVersionClassName_ReturnsExpected(string featureClassName, string featureConstName, Version minimumVersion, bool expected) + { + Assert.Equal(expected, FeatureSupport.IsPresent(featureClassName, featureConstName, minimumVersion)); + } + + [Theory] + [InlineData(typeof(IFeatureSupportClass), nameof(IFeatureSupportClass._field))] + [InlineData(typeof(NonIFeatureSupportClass), nameof(NonIFeatureSupportClass._field))] + public void FeatureSupport_IsPresent_NonStaticField_ThrowsTargetException(Type featureClassType, string featureConstName) + { + Assert.Throws(() => FeatureSupport.IsPresent(featureClassType.AssemblyQualifiedName, featureConstName)); + Assert.Throws(() => FeatureSupport.IsPresent(featureClassType.AssemblyQualifiedName, featureConstName, new Version(1, 2, 3, 4))); + } + + private class IFeatureSupportClass : IFeatureSupport + { + public bool IsPresent(object feature) => throw new NotImplementedException(); + + public bool IsPresent(object feature, Version minimumVersion) + { + if (feature == s_zeroVersionField) + { + return new Version(0, 0, 0, 0) >= minimumVersion; + } + else if (feature == s_nonZeroVersionField) + { + return new Version(1, 2, 3, 4) >= minimumVersion; + } + + throw new InvalidOperationException(); + } + + public Version GetVersionPresent(object feature) + { + Assert.Equal(s_field, feature); + return new Version(1, 2, 3, 4); + } + + public object _field = new object(); + public static object s_field = new object(); + + public static object s_zeroVersionField = new object(); + public static object s_nonZeroVersionField = new object(); + + private object _privateField = new object(); + private static object s_privateField = new object(); + } + + private class NonIFeatureSupportClass + { + public object _field = new object(); + public static object s_field = new object(); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/FormTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FormTests.cs similarity index 51% rename from src/System.Windows.Forms/tests/UnitTests/FormTests.cs rename to src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FormTests.cs index c81722cdab9..cce8883623e 100644 --- a/src/System.Windows.Forms/tests/UnitTests/FormTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FormTests.cs @@ -12,12 +12,18 @@ namespace System.Windows.Forms.Tests public class FormTests { [Fact] - public void Form_Constructor() + public void Form_Ctor_Default() { var form = new Form(); - - // and & assert - Assert.NotNull(form); + Assert.False(form.Active); + Assert.Null(form.ActiveMdiChild); + Assert.False(form.AllowTransparency); +#pragma warning disable 0618 + Assert.True(form.AutoScale); +#pragma warning restore 0618 + Assert.Equal(AutoScaleMode.Inherit, form.AutoScaleMode); + Assert.False(form.AutoScroll); + Assert.False(form.AutoSize); Assert.False(form.IsRestrictedWindow); Assert.True(form.TopLevel); Assert.False(form.Visible); @@ -35,23 +41,19 @@ public void Form_AcceptButtonGetSet() Assert.Equal(mock.Object, form.AcceptButton); } - #region Activation - - /// - /// Data for the ActiveGetSet test - /// - public static TheoryData ActiveGetSetData => - CommonTestHelper.GetBoolTheoryData(); - [Theory] - [MemberData(nameof(ActiveGetSetData))] - public void Form_ActiveGetSet(bool expected) + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Form_Active_Set_GetReturnsExpected(bool value) { - var form = new Form(); - - form.Active = expected; - - Assert.Equal(expected, form.Active); + var form = new Form + { + Active = value + }; + Assert.Equal(value, form.Active); + + // Set same. + form.Active = value; + Assert.Equal(value, form.Active); } // non deterministic, commenting out for now @@ -120,86 +122,83 @@ public void Form_ActiveMdiChildGetSetChildNotEnabled() Assert.Null(form.ActiveMdiChild); } - [Fact] - public void Form_ActiveMdiChildNoSet() + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Form_AllowTransparency_Set_GetReturnsExpected(bool value) { - var form = new Form(); - - // act - - Assert.Null(form.ActiveMdiChild); + var form = new Form + { + AllowTransparency = value + }; + Assert.Equal(value, form.AllowTransparency); + + // Set same. + form.AllowTransparency = value; + Assert.Equal(value, form.AllowTransparency); } - #endregion - - /// - /// Data for the AllowTransparencyGetSet test - /// - public static TheoryData AllowTransparencyGetSetData => - CommonTestHelper.GetBoolTheoryData(); +#pragma warning disable 0618 [Theory] - [MemberData(nameof(AllowTransparencyGetSetData))] - public void Form_AllowTransparencyGetSet(bool expected) + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Form_AutoScale_Set_GetReturnsExpected(bool value) { - var form = new Form(); - - form.AllowTransparency = expected; - - Assert.Equal(expected, form.AllowTransparency); + var form = new Form + { + AutoScale = value + }; + Assert.Equal(value, form.AutoScale); + + // Set same. + form.AutoScale = value; + Assert.Equal(value, form.AutoScale); } - /// - /// Data for the AutoScaleModeGetSet test - /// - public static TheoryData AutoScaleModeGetSetData => - CommonTestHelper.GetEnumTheoryData(); +#pragma warning restore 0618 [Theory] - [MemberData(nameof(AutoScaleModeGetSetData))] - public void Form_AutoScaleModeGetSet(AutoScaleMode expected) + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(AutoScaleMode))] + public void Form_AutoScaleMode_Set_GetReturnsExpected(AutoScaleMode value) { - var form = new Form(); - - form.AutoScaleMode = expected; - - Assert.Equal(expected, form.AutoScaleMode); + var form = new Form + { + AutoScaleMode = value + }; + Assert.Equal(value, form.AutoScaleMode); + + // Set same. + form.AutoScaleMode = value; + Assert.Equal(value, form.AutoScaleMode); } - /// - /// Data for the AutoScrollGetSet test - /// - public static TheoryData AutoScrollGetSetData => - CommonTestHelper.GetBoolTheoryData(); - [Theory] - [MemberData(nameof(AutoScrollGetSetData))] - public void Form_AutoScrollGetSet(bool expected) + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Form_AutoScroll_Set_GetReturnsExpected(bool value) { - var form = new Form(); - - form.AutoScroll = expected; - - Assert.Equal(expected, form.AutoScroll); + var form = new Form + { + AutoScroll = value + }; + Assert.Equal(value, form.AutoScroll); + + // Set same. + form.AutoScroll = value; + Assert.Equal(value, form.AutoScroll); } - /// - /// Data for the AutoSizeGetSet test - /// - public static TheoryData AutoSizeGetSetData => - CommonTestHelper.GetBoolTheoryData(); - [Theory] - [MemberData(nameof(AutoSizeGetSetData))] - public void Form_AutoSizeGetSet(bool expected) + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Form_AutoSizeSet_GetReturnsExpected(bool value) { - var form = new Form(); - - form.AutoSize = expected; - - Assert.Equal(expected, form.AutoSize); + var form = new Form + { + AutoSize = value + }; + Assert.Equal(value, form.AutoSize); + + // Set same. + form.AutoSize = value; + Assert.Equal(value, form.AutoSize); } - - } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/HelpProviderTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/HelpProviderTests.cs new file mode 100644 index 00000000000..983754dae2a --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/HelpProviderTests.cs @@ -0,0 +1,547 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class HelpProviderTests + { + [Fact] + public void HelpProvider_Ctor_Default() + { + var provider = new SubHelpProvider(); + Assert.True(provider.CanRaiseEvents); + Assert.Null(provider.Container); + Assert.False(provider.DesignMode); + Assert.NotNull(provider.Events); + Assert.Same(provider.Events, provider.Events); + Assert.Null(provider.HelpNamespace); + Assert.Null(provider.Site); + Assert.Null(provider.Tag); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void HelpProvider_HelpNamespace_Set_GetReturnsExpected(string value) + { + var provider = new HelpProvider + { + HelpNamespace = value + }; + Assert.Equal(value, provider.HelpNamespace); + + // Set same. + provider.HelpNamespace = value; + Assert.Equal(value, provider.HelpNamespace); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void HelpProvider_HelpNamespace_SetWithBoundControls_GetReturnsExpected(string value) + { + var provider = new HelpProvider + { + HelpNamespace = value + }; + Assert.Equal(value, provider.HelpNamespace); + + var control = new Control(); + provider.SetShowHelp(control, true); + Assert.Equal(0, control.AccessibilityObject.GetHelpTopic(out string fileName)); + Assert.Equal(value, fileName); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void HelpProvider_Tag_Set_GetReturnsExpected(string value) + { + var provider = new HelpProvider + { + Tag = value + }; + Assert.Equal(value, provider.Tag); + + // Set same. + provider.Tag = value; + Assert.Equal(value, provider.Tag); + } + + public static IEnumerable CanExtend_TestData() + { + yield return new object[] { null, false }; + yield return new object[] { new object(), false }; + yield return new object[] { new Control(), true }; + } + + [Theory] + [MemberData(nameof(CanExtend_TestData))] + public void HelpProvider_CanExtend_Invoke_ReturnsExpected(object target, bool expected) + { + var provider = new HelpProvider(); + Assert.Equal(expected, provider.CanExtend(target)); + } + + [Fact] + public void HelpProvider_GetHelpKeyword_NoSuchControl_ReturnsNull() + { + var provider = new HelpProvider(); + Assert.Null(provider.GetHelpKeyword(new Control())); + } + + [Fact] + public void HelpProvider_GetHelpKeyword_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.GetHelpKeyword(null)); + } + + [Fact] + public void HelpProvider_GetHelpNavigator_NoSuchControl_ReturnsAssociateIndex() + { + var provider = new HelpProvider(); + Assert.Equal(HelpNavigator.AssociateIndex, provider.GetHelpNavigator(new Control())); + } + + [Fact] + public void HelpProvider_GetHelpNavigator_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.GetHelpNavigator(null)); + } + + [Fact] + public void HelpProvider_GetHelpString_NoSuchControl_ReturnsNull() + { + var provider = new HelpProvider(); + Assert.Null(provider.GetHelpString(new Control())); + } + + [Fact] + public void HelpProvider_GetHelpString_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.GetHelpString(null)); + } + + [Fact] + public void HelpProvider_GetShowHelp_NoSuchControl_ReturnsFalse() + { + var provider = new HelpProvider(); + Assert.False(provider.GetShowHelp(new Control())); + } + + [Fact] + public void HelpProvider_GetShowHelp_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.GetShowHelp(null)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void HelpProvider_ResetShowHelp_WithShowHelp_Success(bool showHelp) + { + var provider = new HelpProvider(); + var control = new Control(); + provider.SetShowHelp(control, showHelp); + provider.ResetShowHelp(control); + Assert.False(provider.GetShowHelp(control)); + Assert.False(provider.ShouldSerializeShowHelp(control)); + } + + [Fact] + public void HelpProvider_ResetShowHelp_NoSuchControl_Success() + { + var provider = new HelpProvider(); + var control = new Control(); + provider.ResetShowHelp(control); + Assert.False(provider.GetShowHelp(control)); + Assert.False(provider.ShouldSerializeShowHelp(control)); + } + + [Fact] + public void HelpProvider_ResetShowHelp_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.ResetShowHelp(null)); + } + + [Theory] + [InlineData(null, 0, null)] + [InlineData("", 0, null)] + [InlineData("helpKeyword", 0, "HelpNamespace")] + [InlineData("1", 1, "HelpNamespace")] + public void HelpProvider_SetHelpKeyword_GetHelpKeyword_ReturnsExpected(string keyword, int expectedHelpTopic, string expectedFileName) + { + var provider = new HelpProvider + { + HelpNamespace = "HelpNamespace" + }; + var control = new Control(); + + provider.SetHelpKeyword(control, keyword); + Assert.Same(keyword, provider.GetHelpKeyword(control)); + Assert.Equal(!string.IsNullOrEmpty(keyword), provider.GetShowHelp(control)); + Assert.Equal(expectedHelpTopic, control.AccessibilityObject.GetHelpTopic(out string fileName)); + Assert.Equal(expectedFileName, fileName); + + // Set same. + provider.SetHelpKeyword(control, keyword); + Assert.Same(keyword, provider.GetHelpKeyword(control)); + Assert.Equal(!string.IsNullOrEmpty(keyword), provider.GetShowHelp(control)); + Assert.Equal(expectedHelpTopic, control.AccessibilityObject.GetHelpTopic(out fileName)); + Assert.Equal(expectedFileName, fileName); + } + + [Theory] + [InlineData(null, 0)] + [InlineData("", 0)] + [InlineData("helpKeyword", 0)] + [InlineData("1", 1)] + public void HelpProvider_SetHelpKeyword_WithShowHelpTrue_ReturnsExpected(string keyword, int expectedHelpTopic) + { + var provider = new HelpProvider + { + HelpNamespace = "HelpNamespace" + }; + var control = new Control(); + provider.SetShowHelp(control, true); + + provider.SetHelpKeyword(control, keyword); + Assert.Same(keyword, provider.GetHelpKeyword(control)); + Assert.True(provider.GetShowHelp(control)); + Assert.Equal(expectedHelpTopic, control.AccessibilityObject.GetHelpTopic(out string fileName)); + Assert.Equal("HelpNamespace", fileName); + + // Set same. + provider.SetHelpKeyword(control, keyword); + Assert.Same(keyword, provider.GetHelpKeyword(control)); + Assert.True(provider.GetShowHelp(control)); + Assert.Equal(expectedHelpTopic, control.AccessibilityObject.GetHelpTopic(out fileName)); + Assert.Equal("HelpNamespace", fileName); + } + + [Theory] + [InlineData(null, 0, null)] + [InlineData("", 0, null)] + [InlineData("helpKeyword", 0, "HelpNamespace")] + [InlineData("1", 1, "HelpNamespace")] + public void HelpProvider_SetHelpKeyword_WithShowHelpFalse_ReturnsExpected(string keyword, int expectedHelpTopic, string expectedFileName) + { + var provider = new HelpProvider + { + HelpNamespace = "HelpNamespace" + }; + var control = new Control(); + provider.SetShowHelp(control, false); + + provider.SetHelpKeyword(control, keyword); + Assert.Same(keyword, provider.GetHelpKeyword(control)); + Assert.Equal(!string.IsNullOrEmpty(keyword), provider.GetShowHelp(control)); + Assert.Equal(expectedHelpTopic, control.AccessibilityObject.GetHelpTopic(out string fileName)); + Assert.Equal(expectedFileName, fileName); + + // Set same. + provider.SetHelpKeyword(control, keyword); + Assert.Same(keyword, provider.GetHelpKeyword(control)); + Assert.Equal(!string.IsNullOrEmpty(keyword), provider.GetShowHelp(control)); + Assert.Equal(expectedFileName, fileName); + } + + [Fact] + public void HelpProvider_SetHelpKeyword_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.SetHelpKeyword(null, "keyword")); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(HelpNavigator))] + public void HelpProvider_SetHelpNavigator_GetHelpNavigator_ReturnsExpected(HelpNavigator navigator) + { + var provider = new HelpProvider(); + var control = new Control(); + + provider.SetHelpNavigator(control, navigator); + Assert.Equal(navigator, provider.GetHelpNavigator(control)); + Assert.True(provider.GetShowHelp(control)); + + // Set same. + provider.SetHelpNavigator(control, navigator); + Assert.Equal(navigator, provider.GetHelpNavigator(control)); + Assert.True(provider.GetShowHelp(control)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(HelpNavigator))] + public void HelpProvider_SetHelpNavigator_WithShowHelpTrue_ReturnsExpected(HelpNavigator navigator) + { + var provider = new HelpProvider(); + var control = new Control(); + provider.SetShowHelp(control, true); + + provider.SetHelpNavigator(control, navigator); + Assert.Equal(navigator, provider.GetHelpNavigator(control)); + Assert.True(provider.GetShowHelp(control)); + + // Set same. + provider.SetHelpNavigator(control, navigator); + Assert.Equal(navigator, provider.GetHelpNavigator(control)); + Assert.True(provider.GetShowHelp(control)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(HelpNavigator))] + public void HelpProvider_SetHelpNavigator_WithShowHelpFalse_ReturnsExpected(HelpNavigator navigator) + { + var provider = new HelpProvider(); + var control = new Control(); + provider.SetShowHelp(control, false); + + provider.SetHelpNavigator(control, navigator); + Assert.Equal(navigator, provider.GetHelpNavigator(control)); + Assert.True(provider.GetShowHelp(control)); + + // Set same. + provider.SetHelpNavigator(control, navigator); + Assert.Equal(navigator, provider.GetHelpNavigator(control)); + Assert.True(provider.GetShowHelp(control)); + } + + [Fact] + public void HelpProvider_SetHelpNavigator_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.SetHelpNavigator(null, HelpNavigator.AssociateIndex)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(HelpNavigator))] + public void HelpProvider_SetHelpNavigator_InvalidNavigator_ThrowsInvalidEnumArgumentException(HelpNavigator navigator) + { + var provider = new HelpProvider(); + Assert.Throws("navigator", () => provider.SetHelpNavigator(null, navigator)); + Assert.Throws("navigator", () => provider.SetHelpNavigator(new Control(), navigator)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void HelpProvider_SetHelpString_GetHelpString_ReturnsExpected(string helpString) + { + var provider = new HelpProvider(); + var control = new Control(); + + provider.SetHelpString(control, helpString); + Assert.Same(helpString, provider.GetHelpString(control)); + Assert.Equal(!string.IsNullOrEmpty(helpString), provider.GetShowHelp(control)); + Assert.Equal(string.IsNullOrEmpty(helpString) ? null : helpString, control.AccessibilityObject.Help); + + // Set same. + provider.SetHelpString(control, helpString); + Assert.Same(helpString, provider.GetHelpString(control)); + Assert.Equal(!string.IsNullOrEmpty(helpString), provider.GetShowHelp(control)); + Assert.Equal(string.IsNullOrEmpty(helpString) ? null : helpString, control.AccessibilityObject.Help); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void HelpProvider_SetHelpString_WithShowHelpTrue_ReturnsExpected(string helpString) + { + var provider = new HelpProvider(); + var control = new Control(); + provider.SetShowHelp(control, true); + + provider.SetHelpString(control, helpString); + Assert.Same(helpString, provider.GetHelpString(control)); + Assert.True(provider.GetShowHelp(control)); + Assert.Equal(helpString, control.AccessibilityObject.Help); + + // Set same. + provider.SetHelpString(control, helpString); + Assert.Same(helpString, provider.GetHelpString(control)); + Assert.True(provider.GetShowHelp(control)); + Assert.Equal(helpString, control.AccessibilityObject.Help); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void HelpProvider_SetHelpString_WithShowHelpFalse_ReturnsExpected(string helpString) + { + var provider = new HelpProvider(); + var control = new Control(); + provider.SetShowHelp(control, false); + + provider.SetHelpString(control, helpString); + Assert.Same(helpString, provider.GetHelpString(control)); + Assert.Equal(!string.IsNullOrEmpty(helpString), provider.GetShowHelp(control)); + Assert.Equal(string.IsNullOrEmpty(helpString) ? null : helpString, control.AccessibilityObject.Help); + + // Set same. + provider.SetHelpString(control, helpString); + Assert.Same(helpString, provider.GetHelpString(control)); + Assert.Equal(!string.IsNullOrEmpty(helpString), provider.GetShowHelp(control)); + Assert.Equal(string.IsNullOrEmpty(helpString) ? null : helpString, control.AccessibilityObject.Help); + } + + [Fact] + public void HelpProvider_SetHelpString_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.SetHelpString(null, "keyword")); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void HelpProvider_SetShowHelp_GetShowHelp_ReturnsExpected(bool value) + { + var provider = new HelpProvider(); + var control = new Control(); + provider.SetShowHelp(control, value); + + Assert.Equal(value, provider.GetShowHelp(control)); + Assert.True(provider.ShouldSerializeShowHelp(control)); + + // Set same. + provider.SetShowHelp(control, value); + Assert.Equal(value, provider.GetShowHelp(control)); + Assert.True(provider.ShouldSerializeShowHelp(control)); + + // Set opposite. + provider.SetShowHelp(control, !value); + Assert.Equal(!value, provider.GetShowHelp(control)); + Assert.True(provider.ShouldSerializeShowHelp(control)); + } + + [Fact] + public void HelpProvider_SetShowHelp_SetFalseThenTrue_UnbindsAndBindsControl() + { + var provider = new HelpProvider + { + HelpNamespace = "HelpNamespace" + }; + var control = new Control(); + provider.SetShowHelp(control, true); + provider.SetHelpKeyword(control, "1"); + provider.SetHelpString(control, "HelpString"); + + Assert.Equal(1, control.AccessibilityObject.GetHelpTopic(out string fileName)); + Assert.Equal("HelpNamespace", fileName); + Assert.Equal("HelpString", control.AccessibilityObject.Help); + + // Set false. + provider.SetShowHelp(control, false); + Assert.Equal(0, control.AccessibilityObject.GetHelpTopic(out fileName)); + Assert.Null(fileName); + Assert.Null(control.AccessibilityObject.Help); + + // Set true. + provider.SetShowHelp(control, true); + Assert.Equal(1, control.AccessibilityObject.GetHelpTopic(out fileName)); + Assert.Equal("HelpNamespace", fileName); + Assert.Equal("HelpString", control.AccessibilityObject.Help); + } + + [Fact] + public void HelpProvider_SetShowHelp_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.SetShowHelp(null, true)); + } + + [Fact] + public void HelpProvider_ShouldSerializeShowHelp_NoSuchControl_ReturnsFalse() + { + var provider = new HelpProvider(); + Assert.False(provider.ShouldSerializeShowHelp(new Control())); + } + + [Fact] + public void HelpProvider_ShouldSerializeShowHelp_NullCtl_ThrowsArgumentNullException() + { + var provider = new HelpProvider(); + Assert.Throws("key", () => provider.ShouldSerializeShowHelp(null)); + } + + [Theory] + [InlineData(null, "System.Windows.Forms.HelpProvider, HelpNamespace: ")] + [InlineData("", "System.Windows.Forms.HelpProvider, HelpNamespace: ")] + [InlineData("helpNamespace", "System.Windows.Forms.HelpProvider, HelpNamespace: helpNamespace")] + public void HelpProvider_ToString_Invoke_ReturnsExpected(string helpNamespace, string expected) + { + var provider = new HelpProvider + { + HelpNamespace = helpNamespace + }; + Assert.Equal(expected, provider.ToString()); + } + + [Fact] + public void HelpProvider_BoundControl_ValidEventArgs_Nop() + { + var provider = new HelpProvider(); + var control = new SubControl(); + provider.SetShowHelp(control, true); + + control.OnHelpRequested(new HelpEventArgs(new Point(1, 2))); + } + + [Fact] + public void HelpProvider_BoundControl_NoInformation_Nop() + { + var provider = new HelpProvider(); + var control = new SubControl(); + provider.SetShowHelp(control, true); + + var e = new HelpEventArgs(new Point(1, 2)); + control.OnHelpRequested(e); + Assert.True(e.Handled); + } + + [Theory] + [InlineData("")] + [InlineData("InvalidUri")] + [InlineData("file://")] + [InlineData("file://C:/NoSuchFile")] + public void HelpProvider_BoundControl_InvalidNamespace_ThrowsArgumentException(string helpNamespace) + { + var provider = new HelpProvider + { + HelpNamespace = helpNamespace + }; + var control = new SubControl(); + provider.SetShowHelp(control, true); + + var e = new HelpEventArgs(new Point(1, 2)); + Assert.Throws("url", () => control.OnHelpRequested(e)); + Assert.False(e.Handled); + } + + [Fact] + public void HelpProvider_BoundControl_NullEventEventArgs_Nop() + { + var provider = new HelpProvider(); + var control = new SubControl(); + provider.SetShowHelp(control, true); + + control.OnHelpRequested(null); + } + + private class SubHelpProvider : HelpProvider + { + public new bool CanRaiseEvents => base.CanRaiseEvents; + public new bool DesignMode => base.DesignMode; + public new EventHandlerList Events => base.Events; + } + + private class SubControl : Control + { + public new void OnHelpRequested(HelpEventArgs e) => base.OnHelpRequested(e); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Layout/TableLayoutSettingsTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Layout/TableLayoutSettingsTests.cs index b881da8b5e8..ee1fb18c740 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Layout/TableLayoutSettingsTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Layout/TableLayoutSettingsTests.cs @@ -95,7 +95,7 @@ public void TableLayoutSettings_ColumnCount_SetNegative_ThrowsArgumentOutOfRange { var toolStrip = new ToolStrip { LayoutStyle = ToolStripLayoutStyle.Table }; TableLayoutSettings settings = Assert.IsType(toolStrip.LayoutSettings); - Assert.Throws("ColumnCount", () => settings.ColumnCount = -1); + Assert.Throws("value", () => settings.ColumnCount = -1); } [Theory] @@ -114,7 +114,7 @@ public void TableLayoutSettings_RowCount_SetNegative_ThrowsArgumentOutOfRangeExc { var toolStrip = new ToolStrip { LayoutStyle = ToolStripLayoutStyle.Table }; TableLayoutSettings settings = Assert.IsType(toolStrip.LayoutSettings); - Assert.Throws("RowCount", () => settings.RowCount = -1); + Assert.Throws("value", () => settings.RowCount = -1); } [Theory] @@ -132,11 +132,11 @@ public void TableLayoutSettings_GrowStyle_Set_GetReturnsExpected(TableLayoutPane [Theory] [InlineData((TableLayoutPanelGrowStyle)(TableLayoutPanelGrowStyle.FixedSize - 1))] [InlineData((TableLayoutPanelGrowStyle)(TableLayoutPanelGrowStyle.AddColumns + 1))] - public void TableLayoutSettings_GrowStyle_SetNegative_ThrowsArgumentException(TableLayoutPanelGrowStyle value) + public void TableLayoutSettings_GrowStyle_SetNegative_ThrowsArgumentOutOfRangeException(TableLayoutPanelGrowStyle value) { var toolStrip = new ToolStrip { LayoutStyle = ToolStripLayoutStyle.Table }; TableLayoutSettings settings = Assert.IsType(toolStrip.LayoutSettings); - Assert.Throws(null, () => settings.GrowStyle = value); + Assert.Throws("value", () => settings.GrowStyle = value); } [Theory] @@ -651,9 +651,9 @@ public void TableLayoutSettings_SetColumn_InvalidControlStub_ThrowsNotSupportedE [Theory] [MemberData(nameof(EmptySettings_TestData))] - public void TableLayoutSettings_SetColumn_InvalidColumn_ThrowsArgumentException(TableLayoutSettings settings) + public void TableLayoutSettings_SetColumn_InvalidColumn_ThrowsArgumentOutOfRangeException(TableLayoutSettings settings) { - Assert.Throws(null, () => settings.SetColumn("control", -2)); + Assert.Throws("column", () => settings.SetColumn("control", -2)); } [Fact] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkAreaConverterTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkAreaConverterTests.cs new file mode 100644 index 00000000000..74863708d00 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkAreaConverterTests.cs @@ -0,0 +1,226 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Globalization; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class LinkAreaConverterTests + { + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetConvertFromTheoryData))] + [InlineData(typeof(LinkArea), false)] + [InlineData(typeof(string), true)] + public void LinkAreaConverter_CanConvertFrom_Invoke_ReturnsExpected(Type sourceType, bool expected) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Equal(expected, converter.CanConvertFrom(sourceType)); + } + + public static IEnumerable ConvertFrom_TestData() + { + yield return new object[] { "1,2", new LinkArea(1, 2) }; + yield return new object[] { " 1 , 1", new LinkArea(1, 1) }; + yield return new object[] { " ", null }; + yield return new object[] { string.Empty, null }; + } + + [Theory] + [MemberData(nameof(ConvertFrom_TestData))] + public void LinkAreaConverter_ConvertFrom_String_ReturnsExpected(string value, object expected) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Equal(expected, converter.ConvertFrom(value)); + Assert.Equal(expected, converter.ConvertFrom(null, null, value)); + Assert.Equal(expected, converter.ConvertFrom(null, CultureInfo.InvariantCulture, value)); + } + + [Theory] + [InlineData(1)] + [InlineData(null)] + public void LinkAreaConverter_ConvertFrom_InvalidValue_ThrowsNotSupportedException(object value) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws(() => converter.ConvertFrom(value)); + } + + [Theory] + [InlineData("1")] + [InlineData("1,2,3")] + public void LinkAreaConverter_ConvertFrom_InvalidString_ThrowsArgumentException(string value) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws(null, () => converter.ConvertFrom(value)); + } + + [Theory] + [InlineData(typeof(string), true)] + [InlineData(typeof(InstanceDescriptor), true)] + [InlineData(typeof(LinkArea), false)] + [InlineData(typeof(int), false)] + [InlineData(null, false)] + public void LinkAreaConverter_CanConvertTo_Invoke_ReturnsExpected(Type destinationType, bool expected) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Equal(expected, converter.CanConvertTo(destinationType)); + } + + [Fact] + public void LinkAreaConverter_ConvertTo_String_ReturnsExpected() + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Equal("1, 2", converter.ConvertTo(new LinkArea(1, 2), typeof(string))); + Assert.Equal("1, 2", converter.ConvertTo(null, null, new LinkArea(1, 2), typeof(string))); + Assert.Equal("1, 2", converter.ConvertTo(null, CultureInfo.InvariantCulture, new LinkArea(1, 2), typeof(string))); + } + + [Fact] + public void LinkAreaConverter_ConvertTo_InstanceDescriptor_ReturnsExpected() + { + var converter = new LinkArea.LinkAreaConverter(); + InstanceDescriptor descriptor = Assert.IsType(converter.ConvertTo(new LinkArea(1, 2), typeof(InstanceDescriptor))); + Assert.Equal(typeof(LinkArea).GetConstructor(new Type[] { typeof(int), typeof(int) }), descriptor.MemberInfo); + Assert.Equal(new object[] { 1, 2 }, descriptor.Arguments); + } + + [Fact] + public void LinkAreaConverter_ConvertTo_NullDestinationType_ThrowsArgumentNullException() + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws("destinationType", () => converter.ConvertTo(new object(), null)); + } + + [Fact] + public void LinkAreaConverter_ConvertTo_ValueNotLinkArea_ThrowsNotSupportedException() + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws(() => converter.ConvertTo(1, typeof(InstanceDescriptor))); + } + + [Theory] + [InlineData(typeof(LinkArea))] + [InlineData(typeof(int))] + public void LinkAreaConverter_ConvertTo_InvalidDestinationType_ThrowsNotSupportedException(Type destinationType) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws(() => converter.ConvertTo(new LinkArea(), destinationType)); + } + + [Fact] + public void LinkAreaConverter_CreateInstance_ValidPropertyValues_ReturnsExpected() + { + var converter = new LinkArea.LinkAreaConverter(); + LinkArea area = Assert.IsType(converter.CreateInstance( + null, new Dictionary + { + {nameof(LinkArea.Start), 1}, + {nameof(LinkArea.Length), 2} + }) + ); + Assert.Equal(new LinkArea(1, 2), area); + } + + [Fact] + public void LinkAreaConverter_CreateInstance_NullPropertyValues_ThrowsArgumentNullException() + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws("propertyValues", () => converter.CreateInstance(null, null)); + } + + public static IEnumerable CreateInstance_InvalidPropertyValueType_TestData() + { + yield return new object[] + { + new Dictionary + { + {nameof(LinkArea.Start), new object()}, + {nameof(LinkArea.Length), 2}, + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(LinkArea.Start), null}, + {nameof(LinkArea.Length), 2}, + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(LinkArea.Length), 2} + } + }; + + yield return new object[] + { + new Dictionary + { + {nameof(LinkArea.Start), 1}, + {nameof(LinkArea.Length), new object()} + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(LinkArea.Start), 1}, + {nameof(LinkArea.Length), null} + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(LinkArea.Start), 1} + } + }; + } + + [Theory] + [MemberData(nameof(CreateInstance_InvalidPropertyValueType_TestData))] + public void LinkAreaConverter_CreateInstance_InvalidPropertyValueType_ThrowsArgumentException(IDictionary propertyValues) + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.Throws("propertyValues", () => converter.CreateInstance(null, propertyValues)); + } + + [Fact] + public void LinkAreaConverter_GetCreateInstanceSupported_Invoke_ReturnsTrue() + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.True(converter.GetCreateInstanceSupported()); + } + + [Fact] + public void LinkAreaConverter_GetProperties_Invoke_ReturnsExpected() + { + var converter = new LinkArea.LinkAreaConverter(); + PropertyDescriptorCollection properties = converter.GetProperties(null); + Assert.Equal(2, properties.Count); + Assert.Equal(nameof(LinkArea.Start), properties[0].Name); + Assert.Equal(nameof(LinkArea.Length), properties[1].Name); + } + + [Fact] + public void LinkAreaConverter_GetPropertiesSupported_Invoke_ReturnsTrue() + { + var converter = new LinkArea.LinkAreaConverter(); + Assert.True(converter.GetPropertiesSupported()); + } + + private class ClassWithLinkArea + { + public LinkArea LinkArea { get; set; } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkAreaTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkAreaTests.cs new file mode 100644 index 00000000000..f529f30c60e --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkAreaTests.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class LinkAreaTests + { + [Fact] + public void LinkArea_Ctor_Default() + { + var area = new LinkArea(); + Assert.Equal(0, area.Start); + Assert.Equal(0, area.Length); + Assert.True(area.IsEmpty); + } + + [Theory] + [InlineData(-1, -2, false)] + [InlineData(0, 0, true)] + [InlineData(1, 2, false)] + [InlineData(1, 0, false)] + [InlineData(0, 1, false)] + public void LinkArea_Ctor_Int_Int(int start, int length, bool expectedIsEmpty) + { + var area = new LinkArea(start, length); + Assert.Equal(start, area.Start); + Assert.Equal(length, area.Length); + Assert.Equal(expectedIsEmpty, area.IsEmpty); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void LinkArea_Start_Set_GetReturnsExpected(int value) + { + var area = new LinkArea + { + Start = value + }; + Assert.Equal(value, area.Start); + + // Set same. + area.Start = value; + Assert.Equal(value, area.Start); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void LinkArea_Length_Set_GetReturnsExpected(int value) + { + var area = new LinkArea + { + Length = value + }; + Assert.Equal(value, area.Length); + + // Set same. + area.Length = value; + Assert.Equal(value, area.Length); + } + + public static IEnumerable Equals_TestData() + { + yield return new object[] { new LinkArea(1, 2), new LinkArea(1, 2), true }; + yield return new object[] { new LinkArea(1, 2), new LinkArea(2, 2), false }; + yield return new object[] { new LinkArea(1, 2), new LinkArea(1, 3), false }; + + yield return new object[] { new LinkArea(1, 2), new object(), false }; + yield return new object[] { new LinkArea(1, 2), null, false }; + } + + [Theory] + [MemberData(nameof(Equals_TestData))] + public void LinkArea_Equals_Invoke_ReturnsExpected(LinkArea area, object other, bool expected) + { + if (other is LinkArea otherArea) + { + Assert.Equal(expected, area == otherArea); + Assert.Equal(!expected, area != otherArea); + Assert.Equal(expected, area.GetHashCode().Equals(otherArea.GetHashCode())); + } + + Assert.Equal(expected, area.Equals(other)); + } + + [Fact] + public void LinkArea_ToString_Invoke_ReturnsExpected() + { + var area = new LinkArea(1, 2); + Assert.Equal("{Start=1, Length=2}", area.ToString()); + } + + [Fact] + public void LinkArea_TypeConverter_Get_ReturnsLinkAreaConverter() + { + var area = new LinkArea(1, 2); + Assert.IsType(TypeDescriptor.GetConverter(area)); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkConverterTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkConverterTests.cs new file mode 100644 index 00000000000..e931a8cc392 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkConverterTests.cs @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Globalization; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class LinkConverterTests + { + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetConvertFromTheoryData))] + [InlineData(typeof(LinkLabel.Link), false)] + [InlineData(typeof(string), true)] + public void LinkConverter_CanConvertFrom_Invoke_ReturnsExpected(Type sourceType, bool expected) + { + var converter = new LinkConverter(); + Assert.Equal(expected, converter.CanConvertFrom(sourceType)); + } + + public static IEnumerable ConvertFrom_TestData() + { + yield return new object[] { "1,2", new LinkLabel.Link(1, 2) }; + yield return new object[] { " 1 , 1", new LinkLabel.Link(1, 1) }; + yield return new object[] { " ", null }; + yield return new object[] { string.Empty, null }; + } + + [Theory] + [MemberData(nameof(ConvertFrom_TestData))] + public void LinkConverter_ConvertFrom_String_ReturnsExpected(string value, object expected) + { + var converter = new LinkConverter(); + AssertEqualLink(expected, converter.ConvertFrom(value)); + AssertEqualLink(expected, converter.ConvertFrom(null, null, value)); + AssertEqualLink(expected, converter.ConvertFrom(null, CultureInfo.InvariantCulture, value)); + } + + [Theory] + [InlineData(1)] + [InlineData(null)] + public void LinkConverter_ConvertFrom_InvalidValue_ThrowsNotSupportedException(object value) + { + var converter = new LinkConverter(); + Assert.Throws(() => converter.ConvertFrom(value)); + } + + [Theory] + [InlineData("1")] + [InlineData("1,2,3")] + public void LinkConverter_ConvertFrom_InvalidString_ThrowsArgumentException(string value) + { + var converter = new LinkConverter(); + Assert.Throws(null, () => converter.ConvertFrom(value)); + } + + [Theory] + [InlineData(typeof(string), true)] + [InlineData(typeof(InstanceDescriptor), true)] + [InlineData(typeof(LinkLabel.Link), false)] + [InlineData(typeof(int), false)] + [InlineData(null, false)] + public void LinkConverter_CanConvertTo_Invoke_ReturnsExpected(Type destinationType, bool expected) + { + var converter = new LinkConverter(); + Assert.Equal(expected, converter.CanConvertTo(destinationType)); + } + + [Fact] + public void LinkConverter_ConvertTo_String_ReturnsExpected() + { + var converter = new LinkConverter(); + Assert.Equal("1, 2", converter.ConvertTo(new LinkLabel.Link(1, 2), typeof(string))); + Assert.Equal("1, 2", converter.ConvertTo(null, null, new LinkLabel.Link(1, 2), typeof(string))); + Assert.Equal("1, 2", converter.ConvertTo(null, CultureInfo.InvariantCulture, new LinkLabel.Link(1, 2), typeof(string))); + } + + [Fact] + public void LinkConverter_ConvertTo_InstanceDescriptor_ReturnsExpected() + { + var converter = new LinkConverter(); + InstanceDescriptor descriptor = Assert.IsType(converter.ConvertTo(new LinkLabel.Link(1, 2), typeof(InstanceDescriptor))); + Assert.Equal(typeof(LinkLabel.Link).GetConstructor(new Type[] { typeof(int), typeof(int) }), descriptor.MemberInfo); + Assert.Equal(new object[] { 1, 2 }, descriptor.Arguments); + Assert.True(descriptor.IsComplete); + } + + [Fact] + public void LinkConverter_ConvertTo_InstanceDescriptorWithLinkData_ReturnsExpected() + { + var converter = new LinkConverter(); + InstanceDescriptor descriptor = Assert.IsType(converter.ConvertTo(new LinkLabel.Link(1, 2, "linkData"), typeof(InstanceDescriptor))); + Assert.Equal(typeof(LinkLabel.Link).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(object) }), descriptor.MemberInfo); + Assert.Equal(new object[] { 1, 2, "linkData" }, descriptor.Arguments); + Assert.True(descriptor.IsComplete); + } + + [Fact] + public void LinkConverter_ConvertTo_NullDestinationType_ThrowsArgumentNullException() + { + var converter = new LinkConverter(); + Assert.Throws("destinationType", () => converter.ConvertTo(new object(), null)); + } + + [Fact] + public void LinkConverter_ConvertTo_ValueNotLink_ThrowsNotSupportedException() + { + var converter = new LinkConverter(); + Assert.Throws(() => converter.ConvertTo(1, typeof(InstanceDescriptor))); + } + + [Theory] + [InlineData(typeof(LinkLabel.Link))] + [InlineData(typeof(int))] + public void LinkConverter_ConvertTo_InvalidDestinationType_ThrowsNotSupportedException(Type destinationType) + { + var converter = new LinkConverter(); + Assert.Throws(() => converter.ConvertTo(new LinkLabel.Link(), destinationType)); + } + + [Fact] + public void LinkConverter_GetCreateInstanceSupported_Invoke_ReturnsFalse() + { + var converter = new LinkConverter(); + Assert.False(converter.GetCreateInstanceSupported()); + } + + [Fact] + public void LinkConverter_GetPropertiesSupported_Invoke_ReturnsFalse() + { + var converter = new LinkConverter(); + Assert.False(converter.GetPropertiesSupported()); + } + + private static void AssertEqualLink(object expected, object actual) + { + if (expected is LinkLabel.Link expectedLink && actual is LinkLabel.Link actualLink) + { + Assert.Equal(expectedLink.Description, actualLink.Description); + Assert.Equal(expectedLink.Enabled, actualLink.Enabled); + Assert.Equal(expectedLink.Length, actualLink.Length); + Assert.Equal(expectedLink.LinkData, actualLink.LinkData); + Assert.Equal(expectedLink.Name, actualLink.Name); + Assert.Equal(expectedLink.Start, actualLink.Start); + Assert.Equal(expectedLink.Tag, actualLink.Tag); + Assert.Equal(expectedLink.Visited, actualLink.Visited); + } + else + { + Assert.Equal(expected, actual); + } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkTests.cs new file mode 100644 index 00000000000..61c34b64084 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/LinkTests.cs @@ -0,0 +1,197 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Drawing; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class LinkTests + { + [Fact] + public void Link_Ctor_Default() + { + var link = new LinkLabel.Link(); + Assert.Null(link.Description); + Assert.True(link.Enabled); + Assert.Equal(0, link.Length); + Assert.Null(link.LinkData); + Assert.Empty(link.Name); + Assert.Equal(0, link.Start); + Assert.Null(link.Tag); + Assert.False(link.Visited); + } + + [Theory] + [InlineData(-2, -3, -3)] + [InlineData(-2, -1, 0)] + [InlineData(-1, 0, 0)] + [InlineData(0, 0, 0)] + [InlineData(1, 2, 2)] + public void Link_Ctor_Int_Int(int start, int length, int expectedLength) + { + var link = new LinkLabel.Link(start, length); + Assert.Null(link.Description); + Assert.True(link.Enabled); + Assert.Equal(expectedLength, link.Length); + Assert.Null(link.LinkData); + Assert.Empty(link.Name); + Assert.Equal(start, link.Start); + Assert.Null(link.Tag); + Assert.False(link.Visited); + } + + [Theory] + [InlineData(-2, -3, null, -3)] + [InlineData(-2, -1, "", 0)] + [InlineData(-1, 0, "linkData", 0)] + [InlineData(0, 0, "linkData", 0)] + [InlineData(1, 2, "linkData", 2)] + public void Link_Ctor_Int_Int_Object(int start, int length, object linkData, int expectedLength) + { + var link = new LinkLabel.Link(start, length, linkData); + Assert.Null(link.Description); + Assert.True(link.Enabled); + Assert.Equal(expectedLength, link.Length); + Assert.Same(linkData, link.LinkData); + Assert.Empty(link.Name); + Assert.Equal(start, link.Start); + Assert.Null(link.Tag); + Assert.False(link.Visited); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void Link_Description_SetWithoutOwner_GetReturnsExpected(string value) + { + var link = new LinkLabel.Link + { + Description = value + }; + Assert.Same(value, link.Description); + + // Set same. + link.Description = value; + Assert.Same(value, link.Description); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Link_Enabled_SetWithoutOwner_GetReturnsExpected(bool value) + { + var link = new LinkLabel.Link + { + Enabled = value + }; + Assert.Equal(value, link.Enabled); + + // Set same. + link.Enabled = value; + Assert.Equal(value, link.Enabled); + + // Set opposite. + link.Enabled = !value; + Assert.Equal(!value, link.Enabled); + } + + [Theory] + [InlineData(-2, -2)] + [InlineData(-1, 0)] + [InlineData(0, 0)] + [InlineData(1, 1)] + public void Link_Length_SetWithoutOwner_GetReturnsExpected(int value, int expected) + { + var link = new LinkLabel.Link + { + Length = value + }; + Assert.Equal(expected, link.Length); + + // Set same. + link.Length = value; + Assert.Equal(expected, link.Length); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void Link_LinkData_SetWithoutOwner_GetReturnsExpected(string value) + { + var link = new LinkLabel.Link + { + LinkData = value + }; + Assert.Same(value, link.LinkData); + + // Set same. + link.LinkData = value; + Assert.Same(value, link.LinkData); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void Link_Name_SetWithoutOwner_GetReturnsExpected(string value) + { + var link = new LinkLabel.Link + { + Name = value + }; + Assert.Same(value ?? string.Empty, link.Name); + + // Set same. + link.LinkData = value; + Assert.Same(value ?? string.Empty, link.Name); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void Link_Start_SetWithoutOwner_GetReturnsExpected(int value) + { + var link = new LinkLabel.Link + { + Start = value + }; + Assert.Equal(value, link.Start); + + // Set same. + link.Start = value; + Assert.Equal(value, link.Start); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void Link_Tag_SetWithoutOwner_GetReturnsExpected(string value) + { + var link = new LinkLabel.Link + { + Tag = value + }; + Assert.Same(value, link.Tag); + + // Set same. + link.Tag = value; + Assert.Same(value, link.Tag); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Link_Visited_SetWithoutOwner_GetReturnsExpected(bool value) + { + var link = new LinkLabel.Link + { + Visited = value + }; + Assert.Equal(value, link.Visited); + + // Set same. + link.Visited = value; + Assert.Equal(value, link.Visited); + + // Set opposite. + link.Visited = !value; + Assert.Equal(!value, link.Visited); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListBoxTests.cs new file mode 100644 index 00000000000..79b1049d0a6 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListBoxTests.cs @@ -0,0 +1,799 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class ListBoxTests + { + [Fact] + public void Ctor_Default() + { + var control = new SubListBox(); + Assert.True(control.AllowSelection); + Assert.Equal(SystemColors.Window, control.BackColor); + Assert.Null(control.BackgroundImage); + Assert.Equal(ImageLayout.Tile, control.BackgroundImageLayout); + Assert.Equal(BorderStyle.Fixed3D, control.BorderStyle); + Assert.Equal(0, control.Bounds.X); + Assert.Equal(0, control.Bounds.Y); + Assert.Equal(120, control.Bounds.Width); + Assert.True(control.Bounds.Height > 0); + Assert.True(control.ClientSize.Width > 0); + Assert.True(control.ClientSize.Height > 0); + Assert.Equal(0, control.ClientRectangle.X); + Assert.Equal(0, control.ClientRectangle.Y); + Assert.True(control.ClientRectangle.Width > 0); + Assert.True(control.ClientRectangle.Height > 0); + Assert.Equal(0, control.ColumnWidth); + Assert.Empty(control.CustomTabOffsets); + Assert.Same(control.CustomTabOffsets, control.CustomTabOffsets); + Assert.Equal(0, control.DisplayRectangle.X); + Assert.Equal(0, control.DisplayRectangle.Y); + Assert.True(control.DisplayRectangle.Width > 0); + Assert.True(control.DisplayRectangle.Height > 0); + Assert.Null(control.DataManager); + Assert.Null(control.DataSource); + Assert.Equal(Size.Empty, control.DefaultMaximumSize); + Assert.Equal(Size.Empty, control.DefaultMinimumSize); + Assert.Equal(Padding.Empty, control.DefaultPadding); + Assert.Equal(120, control.DefaultSize.Width); + Assert.True(control.DefaultSize.Height > 0); + Assert.Empty(control.DisplayMember); + Assert.Equal(DrawMode.Normal, control.DrawMode); + Assert.Null(control.FormatInfo); + Assert.Empty(control.FormatString); + Assert.False(control.FormattingEnabled); + Assert.Same(Control.DefaultFont, control.Font); + Assert.Equal(SystemColors.WindowText, control.ForeColor); + Assert.True(control.Height > 0); + Assert.Equal(0, control.HorizontalExtent); + Assert.False(control.HorizontalScrollbar); + Assert.True(control.IntegralHeight); + Assert.Equal(13, control.ItemHeight); + Assert.Empty(control.Items); + Assert.Same(control.Items, control.Items); + Assert.Equal(Point.Empty, control.Location); + Assert.Equal(Size.Empty, control.MaximumSize); + Assert.Equal(Size.Empty, control.MinimumSize); + Assert.False(control.MultiColumn); + Assert.Equal(Padding.Empty, control.Padding); + Assert.Equal(120, control.PreferredSize.Width); + Assert.True(control.PreferredSize.Height > 0); + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.False(control.ScrollAlwaysVisible); + Assert.Null(control.SelectedValue); + Assert.Equal(-1, control.SelectedIndex); + Assert.Empty(control.SelectedIndices); + Assert.Same(control.SelectedIndices, control.SelectedIndices); + Assert.Null(control.SelectedItem); + Assert.Empty(control.SelectedItems); + Assert.Same(control.SelectedItems, control.SelectedItems); + Assert.Equal(SelectionMode.One, control.SelectionMode); + Assert.Equal(120, control.Size.Width); + Assert.True(control.Size.Height > 0); + Assert.False(control.Sorted); + Assert.Empty(control.Text); + Assert.Equal(0, control.TopIndex); + Assert.False(control.UseCustomTabOffsets); + Assert.True(control.UseTabStops); + Assert.Empty(control.ValueMember); + Assert.Equal(120, control.Width); + } + + public static IEnumerable BackColor_Set_TestData() + { + yield return new object[] { Color.Empty, SystemColors.Window }; + yield return new object[] { Color.Red, Color.Red }; + } + + [Theory] + [MemberData(nameof(BackColor_Set_TestData))] + public void BackColor_Set_GetReturnsExpected(Color value, Color expected) + { + var control = new ListBox + { + BackColor = value + }; + Assert.Equal(expected, control.BackColor); + + // Set same. + control.BackColor = value; + Assert.Equal(expected, control.BackColor); + } + + [Fact] + public void BackColor_SetWithHandler_CallsBackColorChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BackColorChanged += handler; + + // Set different. + control.BackColor = Color.Red; + Assert.Equal(Color.Red, control.BackColor); + Assert.Equal(1, callCount); + + // Set same. + control.BackColor = Color.Red; + Assert.Equal(Color.Red, control.BackColor); + Assert.Equal(1, callCount); + + // Set different. + control.BackColor = Color.Empty; + Assert.Equal(SystemColors.Window, control.BackColor); + Assert.Equal(2, callCount); + + // Remove handler. + control.BackColorChanged -= handler; + control.BackColor = Color.Red; + Assert.Equal(Color.Red, control.BackColor); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetImageTheoryData))] + public void BackgroundImage_Set_GetReturnsExpected(Image value) + { + var control = new ListBox + { + BackgroundImage = value + }; + Assert.Equal(value, control.BackgroundImage); + + // Set same. + control.BackgroundImage = value; + Assert.Equal(value, control.BackgroundImage); + } + + [Fact] + public void BackgroundImage_SetWithHandler_CallsBackColorChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BackgroundImageChanged += handler; + + // Set different. + var image1 = new Bitmap(10, 10); + control.BackgroundImage = image1; + Assert.Same(image1, control.BackgroundImage); + Assert.Equal(1, callCount); + + // Set same. + control.BackgroundImage = image1; + Assert.Same(image1, control.BackgroundImage); + Assert.Equal(1, callCount); + + // Set different. + var image2 = new Bitmap(10, 10); + control.BackgroundImage = image2; + Assert.Same(image2, control.BackgroundImage); + Assert.Equal(2, callCount); + + // Set null. + control.BackgroundImage = null; + Assert.Null(control.BackgroundImage); + Assert.Equal(3, callCount); + + // Remove handler. + control.BackgroundImageChanged -= handler; + control.BackgroundImage = image1; + Assert.Same(image1, control.BackgroundImage); + Assert.Equal(3, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(ImageLayout))] + public void BackgroundImageLayout_Set_GetReturnsExpected(ImageLayout value) + { + var control = new ListBox + { + BackgroundImageLayout = value + }; + Assert.Equal(value, control.BackgroundImageLayout); + + // Set same. + control.BackgroundImageLayout = value; + Assert.Equal(value, control.BackgroundImageLayout); + } + + [Fact] + public void BackgroundImageLayout_SetWithHandler_CallsBackgroundImageLayoutChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BackgroundImageLayoutChanged += handler; + + // Set different. + control.BackgroundImageLayout = ImageLayout.Center; + Assert.Equal(ImageLayout.Center, control.BackgroundImageLayout); + Assert.Equal(1, callCount); + + // Set same. + control.BackgroundImageLayout = ImageLayout.Center; + Assert.Equal(ImageLayout.Center, control.BackgroundImageLayout); + Assert.Equal(1, callCount); + + // Set different. + control.BackgroundImageLayout = ImageLayout.Stretch; + Assert.Equal(ImageLayout.Stretch, control.BackgroundImageLayout); + Assert.Equal(2, callCount); + + // Remove handler. + control.BackgroundImageLayoutChanged -= handler; + control.BackgroundImageLayout = ImageLayout.Center; + Assert.Equal(ImageLayout.Center, control.BackgroundImageLayout); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(ImageLayout))] + public void BackgroundImageLayout_SetInvalid_ThrowsInvalidEnumArgumentException(ImageLayout value) + { + var control = new ListBox(); + Assert.Throws("value", () => control.BackgroundImageLayout = value); + } + + public static IEnumerable DataSource_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new List() }; + yield return new object[] { new int[0] }; + + var mockSource = new Mock(MockBehavior.Strict); + mockSource + .Setup(s => s.GetList()) + .Returns(new int[] { 1 }); + yield return new object[] { mockSource.Object }; + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_Set_GetReturnsExpected(object value) + { + var control = new SubListBox + { + DataSource = value + }; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetWithHandler_CallsDataSourceChanged() + { + var control = new ListBox(); + int dataSourceCallCount = 0; + int displayMemberCallCount = 0; + EventHandler dataSourceHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + dataSourceCallCount++; + }; + EventHandler displayMemberHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + displayMemberCallCount++; + }; + control.DataSourceChanged += dataSourceHandler; + control.DisplayMemberChanged += displayMemberHandler; + + // Set different. + var dataSource1 = new List(); + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(1, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set same. + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(1, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set different. + var dataSource2 = new List(); + control.DataSource = dataSource2; + Assert.Same(dataSource2, control.DataSource); + Assert.Equal(2, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set null. + control.DataSource = null; + Assert.Null(control.DataSource); + Assert.Equal(3, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Remove handler. + control.DataSourceChanged -= dataSourceHandler; + control.DisplayMemberChanged -= displayMemberHandler; + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(3, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void Font_Set_GetReturnsExpected(Font value) + { + var control = new ListBox + { + Font = value + }; + Assert.Equal(value ?? Control.DefaultFont, control.Font); + + // Set same. + control.Font = value; + Assert.Equal(value ?? Control.DefaultFont, control.Font); + } + + [Fact] + public void Font_SetWithHandler_CallsFontChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.FontChanged += handler; + + // Set different. + var font1 = SystemFonts.MenuFont; + control.Font = font1; + Assert.Same(font1, control.Font); + Assert.Equal(1, callCount); + + // Set same. + control.Font = font1; + Assert.Same(font1, control.Font); + Assert.Equal(1, callCount); + + // Set different. + var font2 = SystemFonts.DialogFont; + control.Font = font2; + Assert.Same(font2, control.Font); + Assert.Equal(2, callCount); + + // Set null. + control.Font = null; + Assert.Same(Control.DefaultFont, control.Font); + Assert.Equal(3, callCount); + + // Remove handler. + control.FontChanged -= handler; + control.Font = font1; + Assert.Same(font1, control.Font); + Assert.Equal(3, callCount); + } + + public static IEnumerable ForeColor_Set_TestData() + { + yield return new object[] { Color.Empty, SystemColors.WindowText }; + yield return new object[] { Color.Red, Color.Red }; + } + + [Theory] + [MemberData(nameof(ForeColor_Set_TestData))] + public void ForeColor_Set_GetReturnsExpected(Color value, Color expected) + { + var control = new ListBox + { + ForeColor = value + }; + Assert.Equal(expected, control.ForeColor); + + // Set same. + control.ForeColor = value; + Assert.Equal(expected, control.ForeColor); + } + + [Fact] + public void ForeColor_SetWithHandler_CallsForeColorChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.ForeColorChanged += handler; + + // Set different. + control.ForeColor = Color.Red; + Assert.Equal(Color.Red, control.ForeColor); + Assert.Equal(1, callCount); + + // Set same. + control.ForeColor = Color.Red; + Assert.Equal(Color.Red, control.ForeColor); + Assert.Equal(1, callCount); + + // Set different. + control.ForeColor = Color.Empty; + Assert.Equal(SystemColors.WindowText, control.ForeColor); + Assert.Equal(2, callCount); + + // Remove handler. + control.ForeColorChanged -= handler; + control.ForeColor = Color.Red; + Assert.Equal(Color.Red, control.ForeColor); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetPaddingNormalizedTheoryData))] + public void Padding_Set_GetReturnsExpected(Padding value, Padding expected) + { + var control = new ListBox + { + Padding = value + }; + Assert.Equal(expected, control.Padding); + + // Set same. + control.Padding = value; + Assert.Equal(expected, control.Padding); + } + + [Fact] + public void Padding_SetWithHandler_CallsPaddingChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.PaddingChanged += handler; + + // Set different. + control.Padding = new Padding(1); + Assert.Equal(new Padding(1), control.Padding); + Assert.Equal(1, callCount); + + // Set same. + control.Padding = new Padding(1); + Assert.Equal(new Padding(1), control.Padding); + Assert.Equal(1, callCount); + + // Set different. + control.Padding = new Padding(2); + Assert.Equal(new Padding(2), control.Padding); + Assert.Equal(2, callCount); + + // Remove handler. + control.PaddingChanged -= handler; + control.Padding = new Padding(1); + Assert.Equal(new Padding(1), control.Padding); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetRightToLeftTheoryData))] + public void RightToLeft_Set_GetReturnsExpected(RightToLeft value, RightToLeft expected) + { + var control = new ListBox + { + RightToLeft = value + }; + Assert.Equal(expected, control.RightToLeft); + + // Set same. + control.RightToLeft = value; + Assert.Equal(expected, control.RightToLeft); + } + + [Fact] + public void RightToLeft_SetWithHandler_CallsRightToLeftChanged() + { + var control = new ListBox(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.RightToLeftChanged += handler; + + // Set different. + control.RightToLeft = RightToLeft.Yes; + Assert.Equal(RightToLeft.Yes, control.RightToLeft); + Assert.Equal(1, callCount); + + // Set same. + control.RightToLeft = RightToLeft.Yes; + Assert.Equal(RightToLeft.Yes, control.RightToLeft); + Assert.Equal(1, callCount); + + // Set different. + control.RightToLeft = RightToLeft.Inherit; + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.Equal(2, callCount); + + // Remove handler. + control.RightToLeftChanged -= handler; + control.RightToLeft = RightToLeft.Yes; + Assert.Equal(RightToLeft.Yes, control.RightToLeft); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(RightToLeft))] + public void RightToLeft_SetInvalid_ThrowsInvalidEnumArgumentException(RightToLeft value) + { + var control = new ListBox(); + Assert.Throws("value", () => control.RightToLeft = value); + } + + public static IEnumerable FindString_TestData() + { + foreach (int startIndex in new int[] { -2, -1, 0, 1 }) + { + yield return new object[] { new ListBox(), null, startIndex, -1 }; + yield return new object[] { new ListBox(), string.Empty, startIndex, -1 }; + yield return new object[] { new ListBox(), "s", startIndex, -1 }; + + var controlWithNoItems = new ListBox(); + Assert.Empty(controlWithNoItems.Items); + yield return new object[] { new ListBox(), null, startIndex, -1 }; + yield return new object[] { new ListBox(), string.Empty, startIndex, -1 }; + yield return new object[] { new ListBox(), "s", startIndex, -1 }; + } + + var controlWithItems = new ListBox + { + DisplayMember = "Value" + }; + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "ABC" }); + controlWithItems.Items.Add(new DataClass { Value = "def" }); + controlWithItems.Items.Add(new DataClass { Value = "" }); + controlWithItems.Items.Add(new DataClass { Value = null }); + + yield return new object[] { controlWithItems, "abc", -1, 0 }; + yield return new object[] { controlWithItems, "abc", 0, 1 }; + yield return new object[] { controlWithItems, "abc", 1, 2 }; + yield return new object[] { controlWithItems, "abc", 2, 0 }; + yield return new object[] { controlWithItems, "abc", 5, 0 }; + + yield return new object[] { controlWithItems, "ABC", -1, 0 }; + yield return new object[] { controlWithItems, "ABC", 0, 1 }; + yield return new object[] { controlWithItems, "ABC", 1, 2 }; + yield return new object[] { controlWithItems, "ABC", 2, 0 }; + yield return new object[] { controlWithItems, "ABC", 5, 0 }; + + yield return new object[] { controlWithItems, "a", -1, 0 }; + yield return new object[] { controlWithItems, "a", 0, 1 }; + yield return new object[] { controlWithItems, "a", 1, 2 }; + yield return new object[] { controlWithItems, "a", 2, 0 }; + yield return new object[] { controlWithItems, "a", 5, 0 }; + + yield return new object[] { controlWithItems, "A", -1, 0 }; + yield return new object[] { controlWithItems, "A", 0, 1 }; + yield return new object[] { controlWithItems, "A", 1, 2 }; + yield return new object[] { controlWithItems, "A", 2, 0 }; + yield return new object[] { controlWithItems, "A", 5, 0 }; + + yield return new object[] { controlWithItems, "abcd", -1, -1 }; + yield return new object[] { controlWithItems, "abcd", 0, -1 }; + yield return new object[] { controlWithItems, "abcd", 1, -1 }; + yield return new object[] { controlWithItems, "abcd", 2, -1 }; + yield return new object[] { controlWithItems, "abcd", 5, -1 }; + + yield return new object[] { controlWithItems, "def", -1, 3 }; + yield return new object[] { controlWithItems, "def", 0, 3 }; + yield return new object[] { controlWithItems, "def", 1, 3 }; + yield return new object[] { controlWithItems, "def", 2, 3 }; + yield return new object[] { controlWithItems, "def", 5, 3 }; + + yield return new object[] { controlWithItems, null, -1, -1 }; + yield return new object[] { controlWithItems, null, 0, -1 }; + yield return new object[] { controlWithItems, null, 1, -1 }; + yield return new object[] { controlWithItems, null, 2, -1 }; + yield return new object[] { controlWithItems, null, 5, -1 }; + + yield return new object[] { controlWithItems, string.Empty, -1, 0 }; + yield return new object[] { controlWithItems, string.Empty, 0, 1 }; + yield return new object[] { controlWithItems, string.Empty, 1, 2 }; + yield return new object[] { controlWithItems, string.Empty, 2, 3 }; + yield return new object[] { controlWithItems, string.Empty, 5, 0 }; + + yield return new object[] { controlWithItems, "NoSuchItem", -1, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 0, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 1, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 2, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 5, -1 }; + } + + [Theory] + [MemberData(nameof(FindString_TestData))] + public void FindString_Invoke_ReturnsExpected(ListBox control, string s, int startIndex, int expected) + { + if (startIndex == -1) + { + Assert.Equal(expected, control.FindString(s)); + } + + Assert.Equal(expected, control.FindString(s, startIndex)); + } + + [Theory] + [InlineData(-2)] + [InlineData(1)] + [InlineData(2)] + public void FindString_InvalidStartIndex_ThrowsArgumentOutOfRangeException(int startIndex) + { + var control = new ListBox(); + control.Items.Add("item"); + Assert.Throws("startIndex", () => control.FindString("s", startIndex)); + } + + public static IEnumerable FindStringExact_TestData() + { + foreach (int startIndex in new int[] { -2, -1, 0, 1 }) + { + yield return new object[] { new ListBox(), null, startIndex, -1 }; + yield return new object[] { new ListBox(), string.Empty, startIndex, -1 }; + yield return new object[] { new ListBox(), "s", startIndex, -1 }; + + var controlWithNoItems = new ListBox(); + Assert.Empty(controlWithNoItems.Items); + yield return new object[] { new ListBox(), null, startIndex, -1 }; + yield return new object[] { new ListBox(), string.Empty, startIndex, -1 }; + yield return new object[] { new ListBox(), "s", startIndex, -1 }; + } + + var controlWithItems = new ListBox + { + DisplayMember = "Value" + }; + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "abc" }); + controlWithItems.Items.Add(new DataClass { Value = "ABC" }); + controlWithItems.Items.Add(new DataClass { Value = "def" }); + controlWithItems.Items.Add(new DataClass { Value = "" }); + controlWithItems.Items.Add(new DataClass { Value = null }); + + yield return new object[] { controlWithItems, "abc", -1, 0 }; + yield return new object[] { controlWithItems, "abc", 0, 1 }; + yield return new object[] { controlWithItems, "abc", 1, 2 }; + yield return new object[] { controlWithItems, "abc", 2, 0 }; + yield return new object[] { controlWithItems, "abc", 5, 0 }; + + yield return new object[] { controlWithItems, "ABC", -1, 0 }; + yield return new object[] { controlWithItems, "ABC", 0, 1 }; + yield return new object[] { controlWithItems, "ABC", 1, 2 }; + yield return new object[] { controlWithItems, "ABC", 2, 0 }; + yield return new object[] { controlWithItems, "ABC", 5, 0 }; + + yield return new object[] { controlWithItems, "a", -1, -1 }; + yield return new object[] { controlWithItems, "a", 0, -1 }; + yield return new object[] { controlWithItems, "a", 1, -1 }; + yield return new object[] { controlWithItems, "a", 2, -1 }; + yield return new object[] { controlWithItems, "a", 5, -1 }; + + yield return new object[] { controlWithItems, "A", -1, -1 }; + yield return new object[] { controlWithItems, "A", 0, -1 }; + yield return new object[] { controlWithItems, "A", 1, -1 }; + yield return new object[] { controlWithItems, "A", 2, -1 }; + yield return new object[] { controlWithItems, "A", 5, -1 }; + + yield return new object[] { controlWithItems, "abcd", -1, -1 }; + yield return new object[] { controlWithItems, "abcd", 0, -1 }; + yield return new object[] { controlWithItems, "abcd", 1, -1 }; + yield return new object[] { controlWithItems, "abcd", 2, -1 }; + yield return new object[] { controlWithItems, "abcd", 5, -1 }; + + yield return new object[] { controlWithItems, "def", -1, 3 }; + yield return new object[] { controlWithItems, "def", 0, 3 }; + yield return new object[] { controlWithItems, "def", 1, 3 }; + yield return new object[] { controlWithItems, "def", 2, 3 }; + yield return new object[] { controlWithItems, "def", 5, 3 }; + + yield return new object[] { controlWithItems, null, -1, -1 }; + yield return new object[] { controlWithItems, null, 0, -1 }; + yield return new object[] { controlWithItems, null, 1, -1 }; + yield return new object[] { controlWithItems, null, 2, -1 }; + yield return new object[] { controlWithItems, null, 5, -1 }; + + yield return new object[] { controlWithItems, string.Empty, -1, 4 }; + yield return new object[] { controlWithItems, string.Empty, 0, 4 }; + yield return new object[] { controlWithItems, string.Empty, 1, 4 }; + yield return new object[] { controlWithItems, string.Empty, 2, 4 }; + yield return new object[] { controlWithItems, string.Empty, 5, 4 }; + + yield return new object[] { controlWithItems, "NoSuchItem", -1, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 0, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 1, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 2, -1 }; + yield return new object[] { controlWithItems, "NoSuchItem", 5, -1 }; + } + + [Theory] + [MemberData(nameof(FindStringExact_TestData))] + public void FindStringExact_Invoke_ReturnsExpected(ListBox control, string s, int startIndex, int expected) + { + if (startIndex == -1) + { + Assert.Equal(expected, control.FindStringExact(s)); + } + + Assert.Equal(expected, control.FindStringExact(s, startIndex)); + } + + [Theory] + [InlineData(-2)] + [InlineData(1)] + [InlineData(2)] + public void FindStringExact_InvalidStartIndex_ThrowsArgumentOutOfRangeException(int startIndex) + { + var control = new ListBox(); + control.Items.Add("item"); + Assert.Throws("startIndex", () => control.FindStringExact("s", startIndex)); + } + + private class SubListBox : ListBox + { + public new bool AllowSelection => base.AllowSelection; + + public new CurrencyManager DataManager => base.DataManager; + + public new Size DefaultMaximumSize => base.DefaultMaximumSize; + + public new Size DefaultMinimumSize => base.DefaultMinimumSize; + + public new Padding DefaultPadding => base.DefaultPadding; + + public new Size DefaultSize => base.DefaultSize; + } + + private class DataClass + { + public string Value { get; set; } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListControlTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListControlTests.cs new file mode 100644 index 00000000000..7ea93bef24d --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListControlTests.cs @@ -0,0 +1,2849 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Globalization; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class ListControlTess + { + [Fact] + public void Ctor_Default() + { + var control = new SubListControl(); + Assert.True(control.AllowSelectionEntry); + Assert.Equal(Control.DefaultBackColor, control.BackColor); + Assert.Null(control.BackgroundImage); + Assert.Equal(ImageLayout.Tile, control.BackgroundImageLayout); + Assert.Equal(Rectangle.Empty, control.Bounds); + Assert.Equal(Size.Empty, control.ClientSize); + Assert.Equal(Rectangle.Empty, control.ClientRectangle); + Assert.Null(control.DataManager); + Assert.Null(control.DataSource); + Assert.Equal(Size.Empty, control.DefaultMaximumSize); + Assert.Equal(Size.Empty, control.DefaultMinimumSize); + Assert.Equal(Padding.Empty, control.DefaultPadding); + Assert.Equal(Size.Empty, control.DefaultSize); + Assert.Empty(control.DisplayMember); + Assert.Equal(Rectangle.Empty, control.DisplayRectangle); + Assert.Null(control.FormatInfo); + Assert.Empty(control.FormatString); + Assert.False(control.FormattingEnabled); + Assert.Same(Control.DefaultFont, control.Font); + Assert.Equal(SystemColors.ControlText, control.ForeColor); + Assert.Equal(0, control.Height); + Assert.Equal(Point.Empty, control.Location); + Assert.Equal(Size.Empty, control.MaximumSize); + Assert.Equal(Size.Empty, control.MinimumSize); + Assert.Equal(Padding.Empty, control.Padding); + Assert.Equal(Size.Empty, control.PreferredSize); + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.Null(control.SelectedValue); + Assert.Equal(Size.Empty, control.Size); + Assert.Empty(control.Text); + Assert.Empty(control.ValueMember); + Assert.Equal(0, control.Width); + } + + public static IEnumerable BindingContext_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new BindingContext() }; + } + + [Theory] + [MemberData(nameof(BindingContext_Set_TestData))] + public void BindingContext_Set_GetReturnsExpected(BindingContext value) + { + var control = new SubListControl + { + BindingContext = value + }; + Assert.Same(value, control.BindingContext); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [MemberData(nameof(BindingContext_Set_TestData))] + public void BindingContext_SetWithNonNullBindingContext_GetReturnsExpected(BindingContext value) + { + var control = new SubListControl + { + BindingContext = new BindingContext() + }; + + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void BindingContext_SetWithDataSource_GetReturnsExpected() + { + var value = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + DataSource = dataSource + }; + + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Same(dataSource, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + + // Set same. + control.BindingContext = value; + Assert.Same(dataSource, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + } + + [Fact] + public void BindingContext_SetWithDataSourceAndDisplayMember_GetReturnsExpected() + { + var value = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + DataSource = dataSource, + DisplayMember = "Value" + }; + + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Same(dataSource, control.DataSource); + Assert.Equal("Value", control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + + // Set same. + control.BindingContext = value; + Assert.Same(dataSource, control.DataSource); + Assert.Equal("Value", control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + } + + [Fact] + public void BindingContext_SetWithDataSourceWithBindingContext_GetReturnsExpected() + { + var originalValue = new BindingContext(); + var value = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = originalValue, + DataSource = dataSource + }; + + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Same(dataSource, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + + // Set same. + control.BindingContext = value; + Assert.Same(dataSource, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + } + + [Fact] + public void BindingContext_SetWithDataSourceAndDisplayMemberWithBindingContext_GetReturnsExpected() + { + var originalValue = new BindingContext(); + var value = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = originalValue, + DataSource = dataSource, + DisplayMember = "Value" + }; + + control.BindingContext = value; + Assert.Same(value, control.BindingContext); + Assert.Same(dataSource, control.DataSource); + Assert.Equal("Value", control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + + // Set same. + control.BindingContext = value; + Assert.Same(dataSource, control.DataSource); + Assert.Equal("Value", control.DisplayMember); + Assert.Same(value[dataSource], control.DataManager); + } + + [Fact] + public void BindingContext_SetWithHandler_CallsBindingContextChanged() + { + var control = new SubListControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.BindingContextChanged += handler; + + // Set different. + var context1 = new BindingContext(); + control.BindingContext = context1; + Assert.Same(context1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set same. + control.BindingContext = context1; + Assert.Same(context1, control.BindingContext); + Assert.Equal(1, callCount); + + // Set different. + var context2 = new BindingContext(); + control.BindingContext = context2; + Assert.Same(context2, control.BindingContext); + Assert.Equal(2, callCount); + + // Set null. + control.BindingContext = null; + Assert.Null(control.BindingContext); + Assert.Equal(3, callCount); + + // Remove handler. + control.BindingContextChanged -= handler; + control.BindingContext = context1; + Assert.Same(context1, control.BindingContext); + Assert.Equal(3, callCount); + } + + [Fact] + public void DataManager_ChangePosition_UpdatesSelectionIndex() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource + }; + + control.DataManager.Position = 1; + Assert.Equal(1, control.SelectedIndex); + } + + [Fact] + public void DataManager_ChangePositionDoesNotAllowSelection_DoesNotUpdateSelectionIndex() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new AllowSelectionFalseListControl + { + SelectedIndex = -2, + BindingContext = context, + DataSource = dataSource, + }; + + control.DataManager.Position = 1; + Assert.Equal(-2, control.SelectedIndex); + } + + [Fact] + public void DataManager_SuspendResumeBinding_CallsSetItemsCore() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new SubListControl + { + SelectedIndex = -1, + BindingContext = context, + DataSource = dataSource + }; + int callCount = 0; + control.SetItemsCoreHandler += (items) => + { + Assert.Same(dataSource, items); + callCount++; + }; + + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(0, control.DataManager.Position); + + // Supsending should call. + control.DataManager.SuspendBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + + // Suspending again should be a nop. + control.DataManager.SuspendBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + + // Resuming should call. + control.DataManager.ResumeBinding(); + Assert.Equal(0, control.SelectedIndex); + Assert.Equal(2, callCount); + + // Resuming again should be a nop. + control.DataManager.ResumeBinding(); + Assert.Equal(0, control.SelectedIndex); + Assert.Equal(2, callCount); + + // Should not call if the DataSource is changed. + control.DataSource = new List(); + } + + [Fact] + public void DataManager_SuspendResumeBindingAfterDataManagerChanged_DoesNotCallSetItemsCore() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new SubListControl + { + SelectedIndex = -1, + BindingContext = context, + DataSource = dataSource + }; + int callCount = 0; + control.SetItemsCoreHandler += (items) => + { + Assert.Same(dataSource, items); + callCount++; + }; + + CurrencyManager dataManger = control.DataManager; + dataManger.SuspendBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + + // Should not call if the DataSource is changed. + control.DataSource = new List(); + Assert.NotSame(dataManger, control.DataManager); + dataManger.ResumeBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + } + + [Fact] + public void DataManager_SuspendResumeBindingDoesNotAllowSelection_CallsSetItemsCore() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new AllowSelectionFalseListControl + { + SelectedIndex = -1, + BindingContext = context, + DataSource = dataSource + }; + int callCount = 0; + control.SetItemsCoreHandler += (items) => + { + Assert.Same(dataSource, items); + callCount++; + }; + + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(0, control.DataManager.Position); + + // Supsending should call. + control.DataManager.SuspendBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + + // Suspending again should be a nop. + control.DataManager.SuspendBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + + // Resuming should call. + control.DataManager.ResumeBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(2, callCount); + + // Resuming again should be a nop. + control.DataManager.ResumeBinding(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(2, callCount); + } + + [Fact] + public void DataManager_CancelCurrentEdit_CallsSetItemCore() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new SubListControl + { + SelectedIndex = -1, + BindingContext = context, + DataSource = dataSource + }; + int callCount = 0; + control.SetItemCoreHandler += (index, value) => + { + Assert.Equal(0, index); + Assert.Same(dataSource[0], value); + callCount++; + }; + + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(0, control.DataManager.Position); + + control.DataManager.CancelCurrentEdit(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + } + + [Fact] + public void DataManager_CancelCurrentEditAfterDataManagerChanged_DoesNotCallSetItemCore() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass(), new DataClass() }; + var control = new SubListControl + { + SelectedIndex = -1, + BindingContext = context, + DataSource = dataSource + }; + int callCount = 0; + control.SetItemCoreHandler += (index, value) => + { + Assert.Equal(0, index); + Assert.Same(dataSource[0], value); + callCount++; + }; + + CurrencyManager dataManger = control.DataManager; + dataManger.CancelCurrentEdit(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + + // Should not call if the DataSource is changed. + control.DataSource = new List(); + Assert.NotSame(dataManger, control.DataManager); + dataManger.CancelCurrentEdit(); + Assert.Equal(-1, control.SelectedIndex); + Assert.Equal(1, callCount); + } + + public static IEnumerable DataSource_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new List() }; + yield return new object[] { new int[0] }; + + var mockSource = new Mock(MockBehavior.Strict); + mockSource + .Setup(s => s.GetList()) + .Returns(new int[] { 1 }); + yield return new object[] { mockSource.Object }; + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_Set_GetReturnsExpected(object value) + { + var control = new SubListControl + { + DataSource = value + }; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_SetWithDataSourceNoDisplayMember_GetReturnsExpected(object value) + { + var control = new SubListControl + { + DataSource = new List() + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_SetWithDisplayMember_GetReturnsExpected(object value) + { + var control = new SubListControl + { + DisplayMember = "Capacity" + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal("Capacity", control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal("Capacity", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_SetWithDataSourceNoSuchDisplayMemberAnymore_GetReturnsExpected(object value) + { + var originalValue = new List(); + var control = new SubListControl + { + DataSource = originalValue, + DisplayMember = "Capacity" + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal(value == null ? string.Empty : "Capacity", control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal(value == null ? string.Empty : "Capacity", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetComponent_DisposeValue_Removes() + { + var value = new ComponentList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.Dispose(); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetComponent_DisposeValueDifferentSender_Removes() + { + var value = new ComponentList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnDisposed(new object(), EventArgs.Empty); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetComponent_DisposeValueNullSender_Removes() + { + var value = new ComponentList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnDisposed(null, null); + Assert.Null(control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetOverridenComponent_DisposeValue_DoesNotRemove() + { + var originalValue = new ComponentList(); + var value = new List(); + var control = new SubListControl + { + DataSource = originalValue, + DisplayMember = "Count" + }; + Assert.Same(originalValue, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + control.DataSource = value; + originalValue.Dispose(); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetSupportInitializeNotification_InitializeValueNotInitializedSetsInitialized_Success() + { + var value = new SupportInitializeNotificationList(); + value.Initialized += (sender, e) => + { + value.IsInitialized = true; + }; + + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnInitialized(value, EventArgs.Empty); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetSupportInitializeNotification_InitializeValueNotInitialized_Success() + { + var value = new SupportInitializeNotificationList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnInitialized(value, EventArgs.Empty); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetSupportInitializeNotification_InitializeValueInitialized_Success() + { + var value = new SupportInitializeNotificationList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnInitialized(value, EventArgs.Empty); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetSupportInitializeNotification_InitializeValueDifferentSender_Success() + { + var value = new SupportInitializeNotificationList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnInitialized(new object(), EventArgs.Empty); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Fact] + public void DataSource_SetSupportInitializeNotification_InitializeValueNullSender_Succes() + { + var value = new SupportInitializeNotificationList(); + var control = new SubListControl + { + DataSource = value, + DisplayMember = "Count" + }; + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + value.OnInitialized(null, null); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DataSource_SetOverridenSupportInitializeNotification_InitializeValue_Success(bool isInitialized) + { + var originalValue = new SupportInitializeNotificationList(); + var value = new List(); + var control = new SubListControl + { + DataSource = originalValue, + DisplayMember = "Count" + }; + Assert.Same(originalValue, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + + originalValue.IsInitialized = isInitialized; + control.DataSource = value; + originalValue.OnInitialized(originalValue, EventArgs.Empty); + Assert.Same(value, control.DataSource); + Assert.Equal("Count", control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_SetWithBindingContext_GetReturnsExpected(object value) + { + var context = new BindingContext(); + var control = new SubListControl + { + BindingContext = context + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[value], control.DataManager); + } + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[value], control.DataManager); + } + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_SetWithBindingContextWithDataSource_GetReturnsExpected(object value) + { + var context = new BindingContext(); + var control = new SubListControl + { + BindingContext = context, + DataSource = new List() + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[value], control.DataManager); + } + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[value], control.DataManager); + } + } + + [Fact] + public void DataSource_SetWithBindingContextWithDisplayMemberCanCreate_GetReturnsExpected() + { + var context = new BindingContext(); + var value = new List(); + var control = new SubListControl + { + BindingContext = context, + DisplayMember = "Value" + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal("Value", control.DisplayMember); + Assert.Same(context[value], control.DataManager); + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal("Value", control.DisplayMember); + Assert.Same(context[value], control.DataManager); + } + + [Theory] + [MemberData(nameof(DataSource_Set_TestData))] + public void DataSource_SetWithBindingContextWithDisplayMemberCantCreate_GetReturnsExpected(object value) + { + var context = new BindingContext(); + var control = new SubListControl + { + BindingContext = context, + DisplayMember = "NoSuchDisplayMember" + }; + + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal(value == null ? "NoSuchDisplayMember" : string.Empty, control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[value], control.DataManager); + } + + // Set same. + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Equal(value == null ? "NoSuchDisplayMember" : string.Empty, control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[value], control.DataManager); + } + } + + [Fact] + public void DataSource_SetWithHandler_CallsDataSourceChanged() + { + var control = new SubListControl(); + int dataSourceCallCount = 0; + int displayMemberCallCount = 0; + EventHandler dataSourceHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + dataSourceCallCount++; + }; + EventHandler displayMemberHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + displayMemberCallCount++; + }; + control.DataSourceChanged += dataSourceHandler; + control.DisplayMemberChanged += displayMemberHandler; + + // Set different. + var dataSource1 = new List(); + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(1, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set same. + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(1, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set different. + var dataSource2 = new List(); + control.DataSource = dataSource2; + Assert.Same(dataSource2, control.DataSource); + Assert.Equal(2, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Set null. + control.DataSource = null; + Assert.Null(control.DataSource); + Assert.Equal(3, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + + // Remove handler. + control.DataSourceChanged -= dataSourceHandler; + control.DisplayMemberChanged -= displayMemberHandler; + control.DataSource = dataSource1; + Assert.Same(dataSource1, control.DataSource); + Assert.Equal(3, dataSourceCallCount); + Assert.Equal(0, displayMemberCallCount); + } + + [Fact] + public void DataSource_SetInsideDataSourceChanged_Nop() + { + var control = new SubListControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + control.DataSource = new int[0]; + callCount++; + }; + control.DataSourceChanged += handler; + + var value = new List(); + control.DataSource = value; + Assert.Same(value, control.DataSource); + Assert.Empty(control.DisplayMember); + Assert.Equal(1, callCount); + } + + [Fact] + public void DataSource_SetInvalid_ThrowsArgumentException() + { + var control = new SubListControl(); + Assert.Throws("value", () => control.DataSource = new object()); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void DisplayMember_Set_GetReturnsExpected(string value) + { + var control = new SubListControl + { + DisplayMember = value + }; + Assert.Null(control.DataSource); + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Null(control.DataManager); + + // Set same. + control.DisplayMember = value; + Assert.Null(control.DataSource); + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void DataMember_SetWithDisplayMember_GetReturnsExpected(string value) + { + var control = new SubListControl + { + DisplayMember = "DataMember" + }; + + control.DisplayMember = value; + Assert.Equal(value ?? string.Empty, control.DisplayMember); + Assert.Null(control.DataSource); + Assert.Null(control.DataManager); + + // Set same. + control.DisplayMember = value; + Assert.Equal(value ?? string.Empty, control.DisplayMember); + Assert.Null(control.DataSource); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void DisplayMember_SetWithDataSource_GetReturnsExpected(string value) + { + var dataSource = new List(); + var control = new SubListControl + { + DataSource = dataSource + }; + + control.DisplayMember = value; + Assert.Equal(value, control.DisplayMember); + Assert.Same(dataSource, control.DataSource); + Assert.Null(control.DataManager); + + // Set same. + control.DisplayMember = value; + Assert.Equal(value, control.DisplayMember); + Assert.Same(dataSource, control.DataSource); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void DisplayMember_SetWithBindingContext_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var control = new SubListControl + { + BindingContext = context + }; + + control.DisplayMember = value; + Assert.Equal(value ?? string.Empty, control.DisplayMember); + Assert.Null(control.DataSource); + Assert.Null(control.DataManager); + + // Set same. + control.DisplayMember = value; + Assert.Equal(value ?? string.Empty, control.DisplayMember); + Assert.Null(control.DataSource); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void DisplayMember_SetWithBindingContextWithDataSource_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource + }; + + control.DisplayMember = value; + Assert.Empty(control.DisplayMember); + Assert.Same(dataSource, control.DataSource); + Assert.Same(context[dataSource], control.DataManager); + + // Set same. + control.DisplayMember = value; + Assert.Empty(control.DisplayMember); + Assert.Same(dataSource, control.DataSource); + Assert.Same(context[dataSource], control.DataManager); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("Value")] + [InlineData("value")] + public void DisplayMember_SetWithBindingContextWithDataSourceCanCreate_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource + }; + + control.DisplayMember = value; + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Equal(dataSource, control.DataSource); + Assert.Same(context[dataSource], control.DataManager); + + // Set same. + control.DisplayMember = value; + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Equal(dataSource, control.DataSource); + Assert.Same(context[dataSource], control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + [InlineData("ListValue")] + public void DisplayMember_SetWithBindingContextWithDataSourceCantCreate_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource + }; + + control.DisplayMember = value; + Assert.Same(dataSource, control.DataSource); + Assert.Empty(control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[dataSource], control.DataManager); + } + + // Set same. + control.DisplayMember = value; + Assert.Same(dataSource, control.DataSource); + Assert.Empty(control.DisplayMember); + if (value == null) + { + Assert.Null(control.DataManager); + } + else + { + Assert.Same(context[dataSource], control.DataManager); + } + } + + [Fact] + public void DisplayMember_SetWithHandler_CallsDisplayMemberChanged() + { + var control = new SubListControl(); + int displayMemberCallCount = 0; + int dataSourceCallCount = 0; + EventHandler displayMemberHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + displayMemberCallCount++; + }; + EventHandler dataSourceHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + dataSourceCallCount++; + }; + control.DisplayMemberChanged += displayMemberHandler; + control.DataSourceChanged += dataSourceHandler; + + // Set different. + control.DisplayMember = "Value1"; + Assert.Same("Value1", control.DisplayMember); + Assert.Equal(1, displayMemberCallCount); + Assert.Equal(0, dataSourceCallCount); + + // Set same. + control.DisplayMember = "Value1"; + Assert.Same("Value1", control.DisplayMember); + Assert.Equal(1, displayMemberCallCount); + Assert.Equal(0, dataSourceCallCount); + + // Set different. + control.DisplayMember = "Value2"; + Assert.Same("Value2", control.DisplayMember); + Assert.Equal(2, displayMemberCallCount); + Assert.Equal(0, dataSourceCallCount); + + // Set null. + control.DisplayMember = null; + Assert.Empty(control.DisplayMember); + Assert.Equal(3, displayMemberCallCount); + Assert.Equal(0, dataSourceCallCount); + + // Set empty. + control.DisplayMember = string.Empty; + Assert.Empty(control.DisplayMember); + Assert.Equal(3, displayMemberCallCount); + Assert.Equal(0, dataSourceCallCount); + + // Remove handler. + control.DisplayMemberChanged -= displayMemberHandler; + control.DataSourceChanged -= dataSourceHandler; + control.DisplayMember = "Value1"; + Assert.Equal("Value1", control.DisplayMember); + Assert.Equal(3, displayMemberCallCount); + Assert.Equal(0, dataSourceCallCount); + } + + [Fact] + public void DisplayMember_SetInsideDisplayMemberChanged_Nop() + { + var control = new SubListControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + control.DisplayMember = "Value2"; + callCount++; + }; + control.DisplayMemberChanged += handler; + + control.DisplayMember = "Value1"; + Assert.Equal("Value1", control.DisplayMember); + Assert.Equal(1, callCount); + } + + [Fact] + public void Format_AddRemove_CallsRefreshItems() + { + var control = new SubListControl(); + int callCount = 0; + control.RefreshItemsHandler = () => callCount++; + ListControlConvertEventHandler handler = (sender, e) => { }; + + // Add. + control.Format += handler; + Assert.Equal(1, callCount); + + // Remove. + control.Format -= handler; + Assert.Equal(2, callCount); + } + + public static IEnumerable FormatInfo_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { CultureInfo.CurrentCulture }; + } + + [Theory] + [MemberData(nameof(FormatInfo_Set_TestData))] + public void FormatInfo_Set_GetReturnsExpected(IFormatProvider value) + { + var control = new SubListControl + { + FormatInfo = value + }; + Assert.Same(value, control.FormatInfo); + + // Set same. + control.FormatInfo = value; + Assert.Same(value, control.FormatInfo); + } + + [Theory] + [MemberData(nameof(FormatInfo_Set_TestData))] + public void FormatInfo_SetWithFormatInfo_GetReturnsExpected(IFormatProvider value) + { + var control = new SubListControl + { + FormatInfo = CultureInfo.InvariantCulture + }; + + control.FormatInfo = value; + Assert.Same(value, control.FormatInfo); + + // Set same. + control.FormatInfo = value; + Assert.Same(value, control.FormatInfo); + } + + [Fact] + public void FormatInfo_Set_CallsRefreshItems() + { + var control = new SubListControl(); + int callCount = 0; + control.RefreshItemsHandler = () => callCount++; + + // Set different. + control.FormatInfo = CultureInfo.CurrentCulture; + Assert.Same(CultureInfo.CurrentCulture, control.FormatInfo); + Assert.Equal(1, callCount); + + // Set same. + control.FormatInfo = CultureInfo.CurrentCulture; + Assert.Same(CultureInfo.CurrentCulture, control.FormatInfo); + Assert.Equal(1, callCount); + + // Set different. + control.FormatInfo = CultureInfo.InvariantCulture; + Assert.Same(CultureInfo.InvariantCulture, control.FormatInfo); + Assert.Equal(2, callCount); + + // Set null. + control.FormatInfo = null; + Assert.Null(control.FormatInfo); + Assert.Equal(3, callCount); + } + + [Fact] + public void FormatInfo_SetWithHandler_CallsOnFormatInfoChanged() + { + var control = new SubListControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.FormatInfoChanged += handler; + + // Set different. + control.FormatInfo = CultureInfo.CurrentCulture; + Assert.Same(CultureInfo.CurrentCulture, control.FormatInfo); + Assert.Equal(1, callCount); + + // Set same. + control.FormatInfo = CultureInfo.CurrentCulture; + Assert.Same(CultureInfo.CurrentCulture, control.FormatInfo); + Assert.Equal(1, callCount); + + // Set different. + control.FormatInfo = CultureInfo.InvariantCulture; + Assert.Same(CultureInfo.InvariantCulture, control.FormatInfo); + Assert.Equal(2, callCount); + + // Set null. + control.FormatInfo = null; + Assert.Null(control.FormatInfo); + Assert.Equal(3, callCount); + + // Remove handler. + control.FormatInfoChanged -= handler; + control.FormatInfo = CultureInfo.CurrentCulture; + Assert.Same(CultureInfo.CurrentCulture, control.FormatInfo); + Assert.Equal(3, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void FormatString_Set_GetReturnsExpected(string value) + { + var control = new SubListControl + { + FormatString = value + }; + Assert.Equal(value ?? string.Empty, control.FormatString); + + // Set same. + control.FormatString = value; + Assert.Equal(value ?? string.Empty, control.FormatString); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void FormatString_SetWithFormatString_GetReturnsExpected(string value) + { + var control = new SubListControl + { + FormatString = "FormatString" + }; + + control.FormatString = value; + Assert.Equal(value ?? string.Empty, control.FormatString); + + // Set same. + control.FormatString = value; + Assert.Equal(value ?? string.Empty, control.FormatString); + } + + [Fact] + public void FormatString_Set_CallsRefreshItems() + { + var control = new SubListControl(); + int callCount = 0; + control.RefreshItemsHandler = () => callCount++; + + // Set different. + control.FormatString = "Value1"; + Assert.Equal("Value1", control.FormatString); + Assert.Equal(1, callCount); + + // Set same. + control.FormatString = "Value1"; + Assert.Equal("Value1", control.FormatString); + Assert.Equal(1, callCount); + + // Set different. + control.FormatString = "Value2"; + Assert.Equal("Value2", control.FormatString); + Assert.Equal(2, callCount); + + // Set null. + control.FormatString = null; + Assert.Empty(control.FormatString); + Assert.Equal(3, callCount); + + // Set empty. + control.FormatString = string.Empty; + Assert.Empty(control.FormatString); + Assert.Equal(3, callCount); + } + + [Fact] + public void FormatStringSetWithHandler_CallsOnFormatStringChanged() + { + var control = new SubListControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.FormatStringChanged += handler; + + // Set different. + control.FormatString = "Value1"; + Assert.Same("Value1", control.FormatString); + Assert.Equal(1, callCount); + + // Set same. + control.FormatString = "Value1"; + Assert.Same("Value1", control.FormatString); + Assert.Equal(1, callCount); + + // Set different. + control.FormatString = "Value2"; + Assert.Same("Value2", control.FormatString); + Assert.Equal(2, callCount); + + // Set null. + control.FormatString = null; + Assert.Empty(control.FormatString); + Assert.Equal(3, callCount); + + // Set empty. + control.FormatString = string.Empty; + Assert.Empty(control.FormatString); + Assert.Equal(3, callCount); + + // Remove handler. + control.FormatStringChanged -= handler; + control.FormatString = "Value1"; + Assert.Equal("Value1", control.FormatString); + Assert.Equal(3, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void FormattingEnabled_Set_GetReturnsExpected(bool value) + { + var control = new SubListControl + { + FormattingEnabled = value + }; + Assert.Equal(value, control.FormattingEnabled); + + // Set same. + control.FormattingEnabled = value; + Assert.Equal(value, control.FormattingEnabled); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void FormattingEnabled_SetWithFormattingEnabled_GetReturnsExpected(bool value) + { + var control = new SubListControl + { + FormattingEnabled = true + }; + + control.FormattingEnabled = value; + Assert.Equal(value, control.FormattingEnabled); + + // Set same. + control.FormattingEnabled = value; + Assert.Equal(value, control.FormattingEnabled); + } + + [Fact] + public void FormattingEnabled_Set_CallsRefreshItems() + { + var control = new SubListControl(); + int callCount = 0; + control.RefreshItemsHandler = () => callCount++; + + // Set different. + control.FormattingEnabled = true; + Assert.True(control.FormattingEnabled); + Assert.Equal(1, callCount); + + // Set same. + control.FormattingEnabled = true; + Assert.True(control.FormattingEnabled); + Assert.Equal(1, callCount); + + // Set different. + control.FormattingEnabled = false; + Assert.False(control.FormattingEnabled); + Assert.Equal(2, callCount); + } + + [Fact] + public void FormattingEnabledSetWithHandler_CallsOnFormattingEnabledChanged() + { + var control = new SubListControl(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.FormattingEnabledChanged += handler; + + // Set different. + control.FormattingEnabled = true; + Assert.True(control.FormattingEnabled); + Assert.Equal(1, callCount); + + // Set same. + control.FormattingEnabled = true; + Assert.True(control.FormattingEnabled); + Assert.Equal(1, callCount); + + // Set different. + control.FormattingEnabled = false; + Assert.False(control.FormattingEnabled); + Assert.Equal(2, callCount); + + // Remove handler. + control.FormattingEnabledChanged -= handler; + control.FormattingEnabled = true; + Assert.True(control.FormattingEnabled); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ValueMember_Set_GetReturnsExpected(string value) + { + var control = new SubListControl + { + ValueMember = value + }; + Assert.Null(control.DataSource); + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Same(value ?? string.Empty, control.ValueMember); + Assert.Null(control.DataManager); + + // Set same. + control.ValueMember = value; + Assert.Null(control.DataSource); + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Same(value ?? string.Empty, control.ValueMember); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ValueMember_SetWithDisplayMember_GetReturnsExpected(string value) + { + var control = new SubListControl + { + DisplayMember = "DisplayMember" + }; + + control.ValueMember = value; + Assert.Null(control.DataSource); + Assert.Equal("DisplayMember", control.DisplayMember); + Assert.Same(value ?? string.Empty, control.ValueMember); + Assert.Null(control.DataManager); + + // Set same. + control.ValueMember = value; + Assert.Null(control.DataSource); + Assert.Equal("DisplayMember", control.DisplayMember); + Assert.Same(value ?? string.Empty, control.ValueMember); + Assert.Null(control.DataManager); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ValueMember_SetWithBindingContext_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var control = new SubListControl + { + BindingContext = context + }; + + control.ValueMember = value; + Assert.Null(control.DataSource); + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Same(value ?? string.Empty, control.ValueMember); + Assert.Null(control.DataManager); + + // Set same. + control.ValueMember = value; + Assert.Null(control.DataSource); + Assert.Same(value ?? string.Empty, control.DisplayMember); + Assert.Same(value ?? string.Empty, control.ValueMember); + Assert.Null(control.DataManager); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("Value")] + [InlineData("value")] + public void ValueMember_SetWithBindingContextWithDataSourceCanCreate_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource + }; + + control.ValueMember = value; + Assert.Same(dataSource, control.DataSource); + Assert.Equal(value ?? string.Empty, control.DisplayMember); + Assert.Equal(value ?? string.Empty, control.ValueMember); + Assert.Same(context[dataSource], control.DataManager); + + // Set same. + control.ValueMember = value; + Assert.Same(dataSource, control.DataSource); + Assert.Equal(value ?? string.Empty, control.DisplayMember); + Assert.Equal(value ?? string.Empty, control.ValueMember); + Assert.Same(context[dataSource], control.DataManager); + } + + [Fact] + public void ValueMember_SetWithBindingContextWithDataSourceCantCreate_ThrowsArgumentException() + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource + }; + + Assert.Throws("newDisplayMember", (() => control.ValueMember = "NoSuchValue")); + Assert.Equal("NoSuchValue", control.DisplayMember); + Assert.Empty(control.ValueMember); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("Value")] + [InlineData("value")] + public void ValueMember_SetWithBindingContextWithDataSourceWithDisplayMemberCanCreate_GetReturnsExpected(string value) + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource, + DisplayMember = "OtherValue" + }; + + control.ValueMember = value; + Assert.Same(dataSource, control.DataSource); + Assert.Equal("OtherValue", control.DisplayMember); + Assert.Equal(value ?? string.Empty, control.ValueMember); + Assert.Same(context[dataSource], control.DataManager); + + // Set same. + control.ValueMember = value; + Assert.Same(dataSource, control.DataSource); + Assert.Equal("OtherValue", control.DisplayMember); + Assert.Equal(value ?? string.Empty, control.ValueMember); + Assert.Same(context[dataSource], control.DataManager); + } + + [Fact] + public void ValueMember_SetWithBindingContextWithDataSourceWithDisplayMemberCantCreate_ThrowsArgumentException() + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + BindingContext = context, + DataSource = dataSource, + DisplayMember = "Value" + }; + + Assert.Throws("value", (() => control.ValueMember = "NoSuchValue")); + Assert.Equal("Value", control.DisplayMember); + Assert.Empty(control.ValueMember); + } + + [Fact] + public void ValueMember_SetWithHandler_CallsValueMemberChanged() + { + var control = new SubListControl(); + int valueMemberCallCount = 0; + int selectedValueCallCount = 0; + EventHandler valueMemberHandler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + valueMemberCallCount++; + }; + EventHandler selectedValueHanlder = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + Assert.True(valueMemberCallCount > selectedValueCallCount); + selectedValueCallCount++; + }; + control.ValueMemberChanged += valueMemberHandler; + control.SelectedValueChanged += selectedValueHanlder; + + // Set different. + control.ValueMember = "Value1"; + Assert.Same("Value1", control.ValueMember); + Assert.Equal(1, valueMemberCallCount); + Assert.Equal(1, selectedValueCallCount); + + // Set same. + control.ValueMember = "Value1"; + Assert.Same("Value1", control.ValueMember); + Assert.Equal(1, valueMemberCallCount); + Assert.Equal(1, selectedValueCallCount); + + // Set different. + control.ValueMember = "Value2"; + Assert.Same("Value2", control.ValueMember); + Assert.Equal(2, valueMemberCallCount); + Assert.Equal(2, selectedValueCallCount); + + // Set null. + control.ValueMember = null; + Assert.Empty(control.ValueMember); + Assert.Equal(3, valueMemberCallCount); + Assert.Equal(3, selectedValueCallCount); + + // Set empty. + control.ValueMember = string.Empty; + Assert.Empty(control.ValueMember); + Assert.Equal(3, valueMemberCallCount); + Assert.Equal(3, selectedValueCallCount); + + // Remove handler. + control.ValueMemberChanged -= valueMemberHandler; + control.SelectedValueChanged -= selectedValueHanlder; + control.ValueMember = "Value1"; + Assert.Equal("Value1", control.ValueMember); + Assert.Equal(3, valueMemberCallCount); + Assert.Equal(3, selectedValueCallCount); + } + + [Theory] + [InlineData("Value")] + [InlineData("value")] + public void SelectedValue_SetWithMatchingValue_Success(string valueMember) + { + var context = new BindingContext(); + var dataSource = new List { new DataClass { Value = "StringValue" } }; + var control = new SubListControl + { + SelectedIndex = 0, + ValueMember = valueMember, + BindingContext = context, + DataSource = dataSource + }; + + control.SelectedValue = "StringValue"; + Assert.Equal(0, control.SelectedIndex); + Assert.Equal("StringValue", control.SelectedValue); + } + + public static IEnumerable SelectedValue_NoMatchingValue_TestData() + { + yield return new object[] { new List(), "selected" }; + yield return new object[] { new List { new DataClass { Value = "NoSuchValue" }}, string.Empty }; + yield return new object[] { new List { new DataClass { Value = "NoSuchValue" }}, "selected" }; + yield return new object[] { new List { new DataClass { Value = "NoSuchValue" }}, "nosuchvalue" }; + } + + [Theory] + [MemberData(nameof(SelectedValue_NoMatchingValue_TestData))] + public void SelectedValue_SetWithNoMatchingValue_Success(object dataSource, string value) + { + var context = new BindingContext(); + var control = new SubListControl + { + SelectedIndex = 0, + ValueMember = "Value", + BindingContext = context, + DataSource = dataSource + }; + + control.SelectedValue = value; + Assert.Equal(-1, control.SelectedIndex); + Assert.Null(control.SelectedValue); + } + + [Fact] + public void SelectedValue_SetWithChangedDataManager_Success() + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + SelectedIndex = 0, + ValueMember = "ValueMember", + BindingContext = context, + DataSource = dataSource + }; + + control.SelectedValue = "selected"; + Assert.Equal(-1, control.SelectedIndex); + Assert.Null(control.SelectedValue); + } + + [Theory] + [InlineData(null)] + [InlineData(1)] + public void SelectedValue_SetWithoutDataManager_GetReturnsNull(object value) + { + var control = new SubListControl + { + SelectedIndex = 0, + SelectedValue = value + }; + Assert.Equal(0, control.SelectedIndex); + Assert.Null(control.SelectedValue); + + // Not set even when given a DataManager. + control.BindingContext = new BindingContext(); + control.DataSource = new List(); + Assert.Equal(0, control.SelectedIndex); + Assert.Throws(() => control.SelectedValue); + } + + [Fact] + public void SelectedValue_SetWithHandler_DoesNotCallSelectedValueChanged() + { + var context = new BindingContext(); + var dataSource = new List { new DataClass { Value = "StringValue" } }; + var control = new SubListControl + { + SelectedIndex = 0, + ValueMember = "Value", + BindingContext = context, + DataSource = dataSource + }; + + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(control, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + control.SelectedValueChanged += handler; + + // Set different. + control.SelectedValue = "StringValue"; + Assert.Equal("StringValue", control.SelectedValue); + Assert.Equal(0, callCount); + + // Set same. + control.SelectedValue = "StringValue"; + Assert.Equal("StringValue", control.SelectedValue); + Assert.Equal(0, callCount); + + // Remove handler. + control.SelectedValueChanged -= handler; + control.SelectedValue = "StringValue"; + Assert.Equal("StringValue", control.SelectedValue); + Assert.Equal(0, callCount); + } + + [Fact] + public void SelectedValue_SetNull_ThrowsArgumentNullException() + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + SelectedIndex = 0, + BindingContext = context, + DataSource = dataSource, + ValueMember = "Value" + }; + Assert.Throws("key", () => control.SelectedValue = null); + Assert.Equal(-1, control.SelectedIndex); + Assert.Null(control.SelectedValue); + } + + [Theory] + [InlineData(null)] + [InlineData(1)] + public void SelectedValue_SetWithoutValueMember_ThrowsInvalidOperationException(object value) + { + var context = new BindingContext(); + var dataSource = new List(); + var control = new SubListControl + { + SelectedIndex = 0, + BindingContext = context, + DataSource = dataSource + }; + Assert.Throws(() => control.SelectedValue = value); + Assert.Equal(0, control.SelectedIndex); + Assert.Throws(() => control.SelectedValue); + } + + [Theory] + [InlineData(Keys.Alt, false)] + [InlineData(Keys.Alt | Keys.PageUp, false)] + [InlineData(Keys.PageUp, true)] + [InlineData(Keys.PageDown, true)] + [InlineData(Keys.Home, true)] + [InlineData(Keys.End, true)] + [InlineData(Keys.A, false)] + public void IsInputKey_Invoke_ReturnsExpected(Keys keyData, bool expected) + { + var control = new SubListControl(); + Assert.Equal(expected, control.IsInputKey(keyData)); + } + + public static IEnumerable FilterItemOnProperty_TestData() + { + yield return new object[] + { + new SubListControl(), + null, + null + }; + + var item = new object(); + yield return new object[] + { + new SubListControl(), + item, + item + }; + + yield return new object[] + { + new SubListControl { DisplayMember = "Length" }, + "abc", + 3 + }; + yield return new object[] + { + new SubListControl { DisplayMember = "length" }, + "abc", + 3 + }; + yield return new object[] + { + new SubListControl { DisplayMember = "Path.Length" }, + "abc", + 3 + }; + yield return new object[] + { + new SubListControl { DisplayMember = "NoSuchProperty" }, + "abc", + "abc" + }; + + var dataClass = new DataClass { Value = 10 }; + var list = new List { dataClass }; + yield return new object[] + { + new SubListControl + { + DataSource = list + }, + list, + list + }; + + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list + }, + list, + list + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list, + DisplayMember = "Value" + }, + list, + list + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list, + DisplayMember = "Value" + }, + dataClass, + 10 + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list, + DisplayMember = "value" + }, + dataClass, + 10 + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list, + DisplayMember = "NoSuchProperty" + }, + dataClass, + dataClass + }; + } + + [Theory] + [MemberData(nameof(FilterItemOnProperty_TestData))] + public void FilterItemOnProperty_Invoke_ReturnsExpected(SubListControl control, object item, object expected) + { + Assert.Equal(expected, control.FilterItemOnProperty(item)); + } + + public static IEnumerable FilterItemOnProperty_String_TestData() + { + yield return new object[] + { + new SubListControl(), + null, + "Field", + null + }; + + var item = new object(); + yield return new object[] + { + new SubListControl(), + item, + null, + item + }; + yield return new object[] + { + new SubListControl(), + item, + string.Empty, + item + }; + + yield return new object[] + { + new SubListControl(), + "abc", + "Length", + 3 + }; + yield return new object[] + { + new SubListControl(), + "abc", + "length", + 3 + }; + yield return new object[] + { + new SubListControl(), + "abc", + "NoSuchProperty", + "abc" + }; + + var dataClass = new DataClass { Value = 10 }; + var list = new List { dataClass }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list + }, + list, + "NoSuchField", + list + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list + }, + list, + "Value", + list + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list + }, + dataClass, + "Value", + 10 + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list + }, + dataClass, + "value", + 10 + }; + yield return new object[] + { + new SubListControl + { + BindingContext = new BindingContext(), + DataSource = list + }, + dataClass, + "NoSuchProperty", + dataClass + }; + } + + [Theory] + [MemberData(nameof(FilterItemOnProperty_String_TestData))] + public void FilterItemOnProperty_InvokeString_ReturnsExpected(SubListControl control, object item, string field, object expected) + { + Assert.Equal(expected, control.FilterItemOnProperty(item, field)); + } + + public static IEnumerable GetItemText_TestData() + { + yield return new object[] + { + new SubListControl(), null, string.Empty + }; + yield return new object[] + { + new SubListControl(), + "abc", + "abc" + }; + yield return new object[] + { + new SubListControl + { + DisplayMember = "Length" + }, + "abc", + 3 + }; + yield return new object[] + { + new SubListControl + { + DisplayMember = "Value" + }, + new DataClass { Value = 1 }, + "1" + }; + yield return new object[] + { + new SubListControl + { + DisplayMember = "Value" + }, + new DataClass { Value = null }, + string.Empty + }; + } + + [Theory] + [MemberData(nameof(GetItemText_TestData))] + public void GetItemText_Invoke_ReturnsExpected(ListControl control, object item, string expected) + { + Assert.Equal(expected, control.GetItemText(item)); + + // Test caching behaviour. + Assert.Equal(expected, control.GetItemText(item)); + } + + public static IEnumerable GetItemText_HasHandler_TestData() + { + var item = new DataClass { Value = 3 }; + yield return new object[] { item, null, "3" }; + yield return new object[] { item, new object(), "3" }; + yield return new object[] { item, item, "3" }; + yield return new object[] { item, "custom", "custom" }; + } + + [Theory] + [MemberData(nameof(GetItemText_HasHandler_TestData))] + public void GetItemText_HasHandler_CallsFormat(object item, object value, object expected) + { + var control = new SubListControl + { + FormattingEnabled = true, + DisplayMember = "Value" + }; + + // Handler. + int callCount = 0; + ListControlConvertEventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Equal(3, e.Value); + Assert.Equal(typeof(string), e.DesiredType); + Assert.Same(item, e.ListItem); + + e.Value = value; + callCount++; + }; + + control.Format += handler; + Assert.Equal(expected, control.GetItemText(item)); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.Format -= handler; + Assert.Equal("3", control.GetItemText(item)); + Assert.Equal(1, callCount); + } + + public static IEnumerable GetItemText_HasHandlerFormattingDisabled_TestData() + { + var item = new DataClass { Value = 3 }; + yield return new object[] { item, null }; + yield return new object[] { item, new object() }; + yield return new object[] { item, item }; + yield return new object[] { item, "custom" }; + } + + [Theory] + [MemberData(nameof(GetItemText_HasHandlerFormattingDisabled_TestData))] + public void GetItemText_HasHandlerFormattingDisabled_DoesNotCallFormat(object item, object value) + { + var control = new SubListControl + { + FormattingEnabled = false, + DisplayMember = "Value" + }; + + // Handler. + int callCount = 0; + ListControlConvertEventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Equal(3, e.Value); + Assert.Equal(typeof(string), e.DesiredType); + Assert.Same(item, e.ListItem); + + e.Value = value; + callCount++; + }; + + control.Format += handler; + Assert.Equal("3", control.GetItemText(item)); + Assert.Equal(0, callCount); + + // Should not call if the handler is removed. + control.Format -= handler; + Assert.Equal("3", control.GetItemText(item)); + Assert.Equal(0, callCount); + } + + [Fact] + public void GetItemText_CustomConverter_ReturnsExpected() + { + var item = new CustomTypeConverterDataClass { Value = 10 }; + var control = new SubListControl + { + FormattingEnabled = true, + BindingContext = new BindingContext(), + DataSource = new List { item }, + DisplayMember = "Value" + }; + Assert.Equal("custom", control.GetItemText(item)); + + // Test caching behaviour. + Assert.Equal("custom", control.GetItemText(item)); + } + + [Fact] + public void GetItemText_CustomConverterFormattingDisabled_ReturnsExpected() + { + var item = new CustomTypeConverterDataClass { Value = 10 }; + var control = new SubListControl + { + FormattingEnabled = false, + BindingContext = new BindingContext(), + DataSource = new List { item }, + DisplayMember = "Value" + }; + Assert.Equal("10", control.GetItemText(item)); + + // Test caching behaviour. + Assert.Equal("10", control.GetItemText(item)); + } + + [Fact] + public void GetItemText_CustomConverterNoContext_ReturnsExpected() + { + var item = new CustomTypeConverterDataClass { Value = 10 }; + var control = new SubListControl + { + FormattingEnabled = true, + DataSource = new List { item }, + DisplayMember = "Value" + }; + Assert.Equal("10", control.GetItemText(item)); + + // Test caching behaviour. + Assert.Equal("10", control.GetItemText(item)); + } + + [Fact] + public void GetItemText_NonCriticalThrowingExceptionType_ReturnsExpected() + { + var item = new NonCriticalThrowingTypeConverterDataClass(); + var control = new SubListControl + { + FormattingEnabled = true, + BindingContext = new BindingContext(), + DataSource = new List { item }, + DisplayMember = "Value" + }; + Assert.Equal("NonCriticalThrowingTypeConverterDataClassToString", control.GetItemText(item)); + + // Test caching behaviour. + Assert.Equal("NonCriticalThrowingTypeConverterDataClassToString", control.GetItemText(item)); + } + + [Fact] + public void GetItemText_CriticalThrowingExceptionType_RethrowsException() + { + var item = new CriticalThrowingTypeConverterDataClass(); + var control = new SubListControl + { + FormattingEnabled = true, + BindingContext = new BindingContext(), + DataSource = new List { item }, + DisplayMember = "Value" + }; + Assert.Throws(() => control.GetItemText(item)); + + // Test caching behaviour. + Assert.Throws(() => control.GetItemText(item)); + } + + [Fact] + public void OnBindingContextChanged_Invoke_CallsBindingContextChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnBindingContextChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.BindingContextChanged += handler; + control.OnBindingContextChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.BindingContextChanged -= handler; + control.OnBindingContextChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnDataSourceChanged_Invoke_CallsDataSourceChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnDataSourceChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.DataSourceChanged += handler; + control.OnDataSourceChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.DataSourceChanged -= handler; + control.OnDataSourceChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnDisplayMemberChanged_Invoke_CallsDisplayMemberChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnDisplayMemberChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.DisplayMemberChanged += handler; + control.OnDisplayMemberChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.DisplayMemberChanged -= handler; + control.OnDisplayMemberChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnFormat_Invoke_CallsFormat() + { + var control = new SubListControl(); + var eventArgs = new ListControlConvertEventArgs(new object(), typeof(int), new object()); + + // No handler. + control.OnFormat(eventArgs); + + // Handler. + int callCount = 0; + ListControlConvertEventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.Format += handler; + control.OnFormat(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.Format -= handler; + control.OnFormat(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnFormatInfoChanged_Invoke_CallsFormatInfoChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnFormatInfoChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.FormatInfoChanged += handler; + control.OnFormatInfoChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.FormatInfoChanged -= handler; + control.OnFormatInfoChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnFormatStringChanged_Invoke_CallsFormatStringChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnFormatStringChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.FormatStringChanged += handler; + control.OnFormatStringChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.FormatStringChanged -= handler; + control.OnFormatStringChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnFormattingEnabledChanged_Invoke_CallsFormattingEnabledChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnFormattingEnabledChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.FormattingEnabledChanged += handler; + control.OnFormattingEnabledChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.FormattingEnabledChanged -= handler; + control.OnFormattingEnabledChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnSelectedIndexChanged_Invoke_CallsSelectedValueChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnSelectedIndexChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.SelectedValueChanged += handler; + control.OnSelectedIndexChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.SelectedValueChanged -= handler; + control.OnSelectedIndexChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnSelectedValueChanged_Invoke_CallsSelectedValueChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnSelectedValueChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.SelectedValueChanged += handler; + control.OnSelectedValueChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.SelectedValueChanged -= handler; + control.OnSelectedValueChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void OnValueMemberChanged_Invoke_CallsValueMemberChanged() + { + var control = new SubListControl(); + var eventArgs = new EventArgs(); + + // No handler. + control.OnValueMemberChanged(eventArgs); + + // Handler. + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Equal(control, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + control.ValueMemberChanged += handler; + control.OnValueMemberChanged(eventArgs); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + control.ValueMemberChanged -= handler; + control.OnValueMemberChanged(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void RefreshItems_Invoke_Nop() + { + var control = new SubListControl(); + control.RefreshItemsEntry(); + } + + [Theory] + [InlineData(0, null)] + [InlineData(-1, 1)] + public void SetItemCore_Invoke_Nop(int index, object value) + { + var control = new SubListControl(); + control.SetItemCoreEntry(index, value); + } + + private class DataClass + { + public object Value { get; set; } + public object OtherValue { get; set; } + public IList ListValue { get; set; } + + public override string ToString() => "DataClassToString"; + } + + private class ComponentList : List, IComponent + { + public ISite Site { get; set; } + + public event EventHandler Disposed; + + public void Dispose() => OnDisposed(this, EventArgs.Empty); + + public void OnDisposed(object sender, EventArgs e) + { + Disposed?.Invoke(sender, e); + } + } + + private class SupportInitializeNotificationList : List, ISupportInitializeNotification + { + public bool IsInitialized { get; set; } + + public event EventHandler Initialized; + + public void BeginInit() + { + } + + public void EndInit() + { + } + + public void OnInitialized(object sender, EventArgs e) + { + Initialized?.Invoke(sender, e); + } + } + + public class SubListControl : ListControl + { + public override int SelectedIndex { get; set; } + + public bool AllowSelectionEntry => base.AllowSelection; + + public new CurrencyManager DataManager => base.DataManager; + + public new Size DefaultMaximumSize => base.DefaultMaximumSize; + + public new Size DefaultMinimumSize => base.DefaultMinimumSize; + + public new Padding DefaultPadding => base.DefaultPadding; + + public new Size DefaultSize => base.DefaultSize; + + public new bool IsInputKey(Keys keyData) => base.IsInputKey(keyData); + + public new object FilterItemOnProperty(object item) => base.FilterItemOnProperty(item); + + public new object FilterItemOnProperty(object item, string field) => base.FilterItemOnProperty(item, field); + + public new void OnBindingContextChanged(EventArgs e) => base.OnBindingContextChanged(e); + + public new void OnDataSourceChanged(EventArgs e) => base.OnDataSourceChanged(e); + + public new void OnDisplayMemberChanged(EventArgs e) => base.OnDisplayMemberChanged(e); + + public new void OnFormat(ListControlConvertEventArgs e) => base.OnFormat(e); + + public new void OnFormatInfoChanged(EventArgs e) => base.OnFormatInfoChanged(e); + + public new void OnFormatStringChanged(EventArgs e) => base.OnFormatStringChanged(e); + + public new void OnFormattingEnabledChanged(EventArgs e) => base.OnFormattingEnabledChanged(e); + + public new void OnSelectedIndexChanged(EventArgs e) => base.OnSelectedIndexChanged(e); + + public new void OnSelectedValueChanged(EventArgs e) => base.OnSelectedValueChanged(e); + + public new void OnValueMemberChanged(EventArgs e) => base.OnValueMemberChanged(e); + + public Action RefreshItemsHandler { get; set; } + + public void RefreshItemsEntry() => RefreshItems(); + + protected override void RefreshItem(int index) + { + } + + protected override void RefreshItems() + { + RefreshItemsHandler?.Invoke(); + base.RefreshItems(); + } + + public Action SetItemCoreHandler { get; set; } + + public void SetItemCoreEntry(int index, object value) => base.SetItemCore(index, value); + + protected override void SetItemCore(int index, object value) + { + SetItemCoreHandler?.Invoke(index, value); + } + + public Action SetItemsCoreHandler { get; set; } + + protected override void SetItemsCore(IList items) + { + SetItemsCoreHandler?.Invoke(items); + } + } + + public class AllowSelectionFalseListControl : SubListControl + { + protected override bool AllowSelection => false; + } + + public class CustomTypeConverterDataClass + { + [TypeConverter(typeof(CustomTypeConverter))] + public int Value { get; set; } + + public override string ToString() => "CustomTypeConverterDataClassToString"; + } + + private class CustomTypeConverter : TypeConverter + { + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + Assert.Equal(10, value); + Assert.Equal(typeof(string), destinationType); + return "custom"; + } + } + + public class NonCriticalThrowingTypeConverterDataClass + { + [TypeConverter(typeof(NonCriticalThrowingTypeConverter))] + public int Value { get; set; } + + public override string ToString() => "NonCriticalThrowingTypeConverterDataClassToString"; + } + + private class NonCriticalThrowingTypeConverter : TypeConverter + { + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + throw new InvalidOperationException(); + } + } + + public class CriticalThrowingTypeConverterDataClass + { + [TypeConverter(typeof(CriticalThrowingTypeConverter))] + public int Value { get; set; } + } + + private class CriticalThrowingTypeConverter : TypeConverter + { + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + throw new StackOverflowException(); + } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/MessageTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/MessageTests.cs new file mode 100644 index 00000000000..d6e9c616bbf --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/MessageTests.cs @@ -0,0 +1,511 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Runtime.InteropServices; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class MessageTests + { + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntPtrTheoryData))] + public void Message_HWnd_Set_GetReturnsExpected(IntPtr value) + { + var message = new Message + { + HWnd = value + }; + Assert.Equal(value, message.HWnd); + + // Set same. + message.HWnd = value; + Assert.Equal(value, message.HWnd); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void Message_Msg_Set_GetReturnsExpected(int value) + { + var message = new Message + { + Msg = value + }; + Assert.Equal(value, message.Msg); + + // Set same. + message.Msg = value; + Assert.Equal(value, message.Msg); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntPtrTheoryData))] + public void Message_WParam_Set_GetReturnsExpected(IntPtr value) + { + var message = new Message + { + WParam = value + }; + Assert.Equal(value, message.WParam); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntPtrTheoryData))] + public void Message_LParam_Set_GetReturnsExpected(IntPtr value) + { + var message = new Message + { + LParam = value + }; + Assert.Equal(value, message.LParam); + + // Set same. + message.LParam = value; + Assert.Equal(value, message.LParam); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntPtrTheoryData))] + public void Message_Result_Set_GetReturnsExpected(IntPtr value) + { + var message = new Message + { + Result = value + }; + Assert.Equal(value, message.Result); + + // Set same. + message.Result = value; + Assert.Equal(value, message.Result); + } + + public static IEnumerable Create_TestData() + { + yield return new object[] { (IntPtr)(-1), -1, (IntPtr)(-1), (IntPtr)(-1) }; + yield return new object[] { IntPtr.Zero, 1, IntPtr.Zero, IntPtr.Zero }; + yield return new object[] { (IntPtr)1, 1, (IntPtr)1, (IntPtr)1 }; + } + + [Theory] + [MemberData(nameof(Create_TestData))] + public void Message_Create_Invoke_ReturnsExpected(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) + { + Message message = Message.Create(hWnd, msg, wparam, lparam); + Assert.Equal(hWnd, message.HWnd); + Assert.Equal(msg, message.Msg); + Assert.Equal(wparam, message.WParam); + Assert.Equal(lparam, message.LParam); + Assert.Equal(IntPtr.Zero, message.Result); + } + + public static IEnumerable Equals_TestData() + { + Message Create(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam, IntPtr result) + { + Message message = Message.Create(hWnd, msg, wparam, lparam); + message.Result = result; + return message; + } + + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + true + }; + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + Create((IntPtr)2, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + false + }; + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + Create((IntPtr)1, 3, (IntPtr)3, (IntPtr)4, (IntPtr)5), + false + }; + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + Create((IntPtr)1, 2, (IntPtr)4, (IntPtr)4, (IntPtr)5), + false + }; + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)5, (IntPtr)5), + false + }; + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)6), + false + }; + + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + new object(), + false + }; + yield return new object[] + { + Create((IntPtr)1, 2, (IntPtr)3, (IntPtr)4, (IntPtr)5), + null, + false + }; + } + + [Theory] + [MemberData(nameof(Equals_TestData))] + public void Message_Equals_Invoke_ReturnsExpected(Message message, object other, bool expected) + { + if (other is Message otherMessage) + { + Assert.Equal(expected, message == otherMessage); + Assert.Equal(!expected, message != otherMessage); + } + + Assert.Equal(expected, message.Equals(other)); + } + + [Fact] + public void Message_GetHashCode_Invoke_ReturnsExpected() + { + Message message = Message.Create((IntPtr)1, 1, (IntPtr)1, (IntPtr)1); + Assert.NotEqual(0, message.GetHashCode()); + Assert.Equal(message.GetHashCode(), message.GetHashCode()); + } + + [Fact] + public void Message_GetLParam_Invoke_ReturnsExpected() + { + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf()); + try + { + var original = new TestStruct + { + _field1 = 1, + _field2 = 2 + }; + Marshal.StructureToPtr(original, ptr, fDeleteOld: false); + + var message = new Message + { + LParam = ptr + }; + var lparam = Assert.IsType(message.GetLParam(typeof(TestStruct))); + Assert.Equal(1, lparam._field1); + Assert.Equal(2, lparam._field2); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + } + + [StructLayout(LayoutKind.Sequential)] + private struct TestStruct + { + public int _field1; + public int _field2; + } + + public static IEnumerable ToString_TestData() + { + yield return new object[] { 0x1FFF, null }; + yield return new object[] { 0x2000, " (WM_REFLECT + WM_NULL)" }; + yield return new object[] { -1 | 0x2000, " (WM_REFLECT + ???)" }; + + yield return new object[] { Interop.WindowMessages.WM_NULL, " (WM_NULL)" }; + yield return new object[] { Interop.WindowMessages.WM_CREATE, " (WM_CREATE)" }; + yield return new object[] { Interop.WindowMessages.WM_DESTROY, " (WM_DESTROY)" }; + yield return new object[] { Interop.WindowMessages.WM_MOVE, " (WM_MOVE)" }; + yield return new object[] { Interop.WindowMessages.WM_SIZE, " (WM_SIZE)" }; + yield return new object[] { Interop.WindowMessages.WM_ACTIVATE, " (WM_ACTIVATE)" }; + yield return new object[] { Interop.WindowMessages.WM_SETFOCUS, " (WM_SETFOCUS)" }; + yield return new object[] { Interop.WindowMessages.WM_KILLFOCUS, " (WM_KILLFOCUS)" }; + yield return new object[] { Interop.WindowMessages.WM_ENABLE, " (WM_ENABLE)" }; + yield return new object[] { Interop.WindowMessages.WM_SETREDRAW, " (WM_SETREDRAW)" }; + yield return new object[] { Interop.WindowMessages.WM_SETTEXT, " (WM_SETTEXT)" }; + yield return new object[] { Interop.WindowMessages.WM_GETTEXT, " (WM_GETTEXT)" }; + yield return new object[] { Interop.WindowMessages.WM_GETTEXTLENGTH, " (WM_GETTEXTLENGTH)" }; + yield return new object[] { Interop.WindowMessages.WM_PAINT, " (WM_PAINT)" }; + yield return new object[] { Interop.WindowMessages.WM_CLOSE, " (WM_CLOSE)" }; + yield return new object[] { Interop.WindowMessages.WM_QUERYENDSESSION, " (WM_QUERYENDSESSION)" }; + yield return new object[] { Interop.WindowMessages.WM_QUIT, " (WM_QUIT)" }; + yield return new object[] { Interop.WindowMessages.WM_QUERYOPEN, " (WM_QUERYOPEN)" }; + yield return new object[] { Interop.WindowMessages.WM_ERASEBKGND, " (WM_ERASEBKGND)" }; + yield return new object[] { Interop.WindowMessages.WM_SYSCOLORCHANGE, " (WM_SYSCOLORCHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_ENDSESSION, " (WM_ENDSESSION)" }; + yield return new object[] { Interop.WindowMessages.WM_SHOWWINDOW, " (WM_SHOWWINDOW)" }; + yield return new object[] { Interop.WindowMessages.WM_WININICHANGE, " (WM_WININICHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_DEVMODECHANGE, " (WM_DEVMODECHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_ACTIVATEAPP, " (WM_ACTIVATEAPP)" }; + yield return new object[] { Interop.WindowMessages.WM_FONTCHANGE, " (WM_FONTCHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_TIMECHANGE, " (WM_TIMECHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_CANCELMODE, " (WM_CANCELMODE)" }; + yield return new object[] { Interop.WindowMessages.WM_SETCURSOR, " (WM_SETCURSOR)" }; + yield return new object[] { Interop.WindowMessages.WM_MOUSEACTIVATE, " (WM_MOUSEACTIVATE)" }; + yield return new object[] { Interop.WindowMessages.WM_CHILDACTIVATE, " (WM_CHILDACTIVATE)" }; + yield return new object[] { Interop.WindowMessages.WM_QUEUESYNC, " (WM_QUEUESYNC)" }; + yield return new object[] { Interop.WindowMessages.WM_GETMINMAXINFO, " (WM_GETMINMAXINFO)" }; + yield return new object[] { Interop.WindowMessages.WM_PAINTICON, " (WM_PAINTICON)" }; + yield return new object[] { Interop.WindowMessages.WM_ICONERASEBKGND, " (WM_ICONERASEBKGND)" }; + yield return new object[] { Interop.WindowMessages.WM_NEXTDLGCTL, " (WM_NEXTDLGCTL)" }; + yield return new object[] { Interop.WindowMessages.WM_SPOOLERSTATUS, " (WM_SPOOLERSTATUS)" }; + yield return new object[] { Interop.WindowMessages.WM_DRAWITEM, " (WM_DRAWITEM)" }; + yield return new object[] { Interop.WindowMessages.WM_MEASUREITEM, " (WM_MEASUREITEM)" }; + yield return new object[] { Interop.WindowMessages.WM_DELETEITEM, " (WM_DELETEITEM)" }; + yield return new object[] { Interop.WindowMessages.WM_VKEYTOITEM, " (WM_VKEYTOITEM)" }; + yield return new object[] { Interop.WindowMessages.WM_CHARTOITEM, " (WM_CHARTOITEM)" }; + yield return new object[] { Interop.WindowMessages.WM_SETFONT, " (WM_SETFONT)" }; + yield return new object[] { Interop.WindowMessages.WM_GETFONT, " (WM_GETFONT)" }; + yield return new object[] { Interop.WindowMessages.WM_SETHOTKEY, " (WM_SETHOTKEY)" }; + yield return new object[] { Interop.WindowMessages.WM_GETHOTKEY, " (WM_GETHOTKEY)" }; + yield return new object[] { Interop.WindowMessages.WM_QUERYDRAGICON, " (WM_QUERYDRAGICON)" }; + yield return new object[] { Interop.WindowMessages.WM_COMPAREITEM, " (WM_COMPAREITEM)" }; + yield return new object[] { Interop.WindowMessages.WM_GETOBJECT, " (WM_GETOBJECT)" }; + yield return new object[] { Interop.WindowMessages.WM_COMPACTING, " (WM_COMPACTING)" }; + yield return new object[] { Interop.WindowMessages.WM_COMMNOTIFY, " (WM_COMMNOTIFY)" }; + yield return new object[] { Interop.WindowMessages.WM_WINDOWPOSCHANGING, " (WM_WINDOWPOSCHANGING)" }; + yield return new object[] { Interop.WindowMessages.WM_WINDOWPOSCHANGED, " (WM_WINDOWPOSCHANGED)" }; + yield return new object[] { Interop.WindowMessages.WM_POWER, " (WM_POWER)" }; + yield return new object[] { Interop.WindowMessages.WM_COPYDATA, " (WM_COPYDATA)" }; + yield return new object[] { Interop.WindowMessages.WM_CANCELJOURNAL, " (WM_CANCELJOURNAL)" }; + yield return new object[] { Interop.WindowMessages.WM_NOTIFY, " (WM_NOTIFY)" }; + yield return new object[] { Interop.WindowMessages.WM_INPUTLANGCHANGEREQUEST, " (WM_INPUTLANGCHANGEREQUEST)" }; + yield return new object[] { Interop.WindowMessages.WM_INPUTLANGCHANGE, " (WM_INPUTLANGCHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_TCARD, " (WM_TCARD)" }; + yield return new object[] { Interop.WindowMessages.WM_HELP, " (WM_HELP)" }; + yield return new object[] { Interop.WindowMessages.WM_USERCHANGED, " (WM_USERCHANGED)" }; + yield return new object[] { Interop.WindowMessages.WM_NOTIFYFORMAT, " (WM_NOTIFYFORMAT)" }; + yield return new object[] { Interop.WindowMessages.WM_CONTEXTMENU, " (WM_CONTEXTMENU)" }; + yield return new object[] { Interop.WindowMessages.WM_STYLECHANGING, " (WM_STYLECHANGING)" }; + yield return new object[] { Interop.WindowMessages.WM_STYLECHANGED, " (WM_STYLECHANGED)" }; + yield return new object[] { Interop.WindowMessages.WM_DISPLAYCHANGE, " (WM_DISPLAYCHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_GETICON, " (WM_GETICON)" }; + yield return new object[] { Interop.WindowMessages.WM_SETICON, " (WM_SETICON)" }; + yield return new object[] { Interop.WindowMessages.WM_NCCREATE, " (WM_NCCREATE)" }; + yield return new object[] { Interop.WindowMessages.WM_NCDESTROY, " (WM_NCDESTROY)" }; + yield return new object[] { Interop.WindowMessages.WM_NCCALCSIZE, " (WM_NCCALCSIZE)" }; + yield return new object[] { Interop.WindowMessages.WM_NCHITTEST, " (WM_NCHITTEST)" }; + yield return new object[] { Interop.WindowMessages.WM_NCPAINT, " (WM_NCPAINT)" }; + yield return new object[] { Interop.WindowMessages.WM_NCACTIVATE, " (WM_NCACTIVATE)" }; + yield return new object[] { Interop.WindowMessages.WM_GETDLGCODE, " (WM_GETDLGCODE)" }; + yield return new object[] { Interop.WindowMessages.WM_NCMOUSEMOVE, " (WM_NCMOUSEMOVE)" }; + yield return new object[] { Interop.WindowMessages.WM_NCLBUTTONDOWN, " (WM_NCLBUTTONDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_NCLBUTTONUP, " (WM_NCLBUTTONUP)" }; + yield return new object[] { Interop.WindowMessages.WM_NCLBUTTONDBLCLK, " (WM_NCLBUTTONDBLCLK)" }; + yield return new object[] { Interop.WindowMessages.WM_NCRBUTTONDOWN, " (WM_NCRBUTTONDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_NCRBUTTONUP, " (WM_NCRBUTTONUP)" }; + yield return new object[] { Interop.WindowMessages.WM_NCRBUTTONDBLCLK, " (WM_NCRBUTTONDBLCLK)" }; + yield return new object[] { Interop.WindowMessages.WM_NCMBUTTONDOWN, " (WM_NCMBUTTONDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_NCMBUTTONUP, " (WM_NCMBUTTONUP)" }; + yield return new object[] { Interop.WindowMessages.WM_NCMBUTTONDBLCLK, " (WM_NCMBUTTONDBLCLK)" }; + yield return new object[] { Interop.WindowMessages.WM_KEYDOWN, " (WM_KEYDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_KEYUP, " (WM_KEYUP)" }; + yield return new object[] { Interop.WindowMessages.WM_CHAR, " (WM_CHAR)" }; + yield return new object[] { Interop.WindowMessages.WM_DEADCHAR, " (WM_DEADCHAR)" }; + yield return new object[] { Interop.WindowMessages.WM_SYSKEYDOWN, " (WM_SYSKEYDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_SYSKEYUP, " (WM_SYSKEYUP)" }; + yield return new object[] { Interop.WindowMessages.WM_SYSCHAR, " (WM_SYSCHAR)" }; + yield return new object[] { Interop.WindowMessages.WM_SYSDEADCHAR, " (WM_SYSDEADCHAR)" }; + yield return new object[] { Interop.WindowMessages.WM_KEYLAST, " (WM_KEYLAST)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_STARTCOMPOSITION, " (WM_IME_STARTCOMPOSITION)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_ENDCOMPOSITION, " (WM_IME_ENDCOMPOSITION)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_COMPOSITION, " (WM_IME_COMPOSITION)" }; + yield return new object[] { Interop.WindowMessages.WM_INITDIALOG, " (WM_INITDIALOG)" }; + yield return new object[] { Interop.WindowMessages.WM_COMMAND, " (WM_COMMAND)" }; + yield return new object[] { Interop.WindowMessages.WM_SYSCOMMAND, " (WM_SYSCOMMAND)" }; + yield return new object[] { Interop.WindowMessages.WM_TIMER, " (WM_TIMER)" }; + yield return new object[] { Interop.WindowMessages.WM_HSCROLL, " (WM_HSCROLL)" }; + yield return new object[] { Interop.WindowMessages.WM_VSCROLL, " (WM_VSCROLL)" }; + yield return new object[] { Interop.WindowMessages.WM_INITMENU, " (WM_INITMENU)" }; + yield return new object[] { Interop.WindowMessages.WM_INITMENUPOPUP, " (WM_INITMENUPOPUP)" }; + yield return new object[] { Interop.WindowMessages.WM_MENUSELECT, " (WM_MENUSELECT)" }; + yield return new object[] { Interop.WindowMessages.WM_MENUCHAR, " (WM_MENUCHAR)" }; + yield return new object[] { Interop.WindowMessages.WM_ENTERIDLE, " (WM_ENTERIDLE)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLORMSGBOX, " (WM_CTLCOLORMSGBOX)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLOREDIT, " (WM_CTLCOLOREDIT)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLORLISTBOX, " (WM_CTLCOLORLISTBOX)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLORBTN, " (WM_CTLCOLORBTN)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLORDLG, " (WM_CTLCOLORDLG)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLORSCROLLBAR, " (WM_CTLCOLORSCROLLBAR)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLORSTATIC, " (WM_CTLCOLORSTATIC)" }; + yield return new object[] { Interop.WindowMessages.WM_MOUSEMOVE, " (WM_MOUSEMOVE)" }; + yield return new object[] { Interop.WindowMessages.WM_LBUTTONDOWN, " (WM_LBUTTONDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_LBUTTONUP, " (WM_LBUTTONUP)" }; + yield return new object[] { Interop.WindowMessages.WM_LBUTTONDBLCLK, " (WM_LBUTTONDBLCLK)" }; + yield return new object[] { Interop.WindowMessages.WM_RBUTTONDOWN, " (WM_RBUTTONDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_RBUTTONUP, " (WM_RBUTTONUP)" }; + yield return new object[] { Interop.WindowMessages.WM_RBUTTONDBLCLK, " (WM_RBUTTONDBLCLK)" }; + yield return new object[] { Interop.WindowMessages.WM_MBUTTONDOWN, " (WM_MBUTTONDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_MBUTTONUP, " (WM_MBUTTONUP)" }; + yield return new object[] { Interop.WindowMessages.WM_MBUTTONDBLCLK, " (WM_MBUTTONDBLCLK)" }; + yield return new object[] { Interop.WindowMessages.WM_MOUSEWHEEL, " (WM_MOUSEWHEEL)" }; + yield return new object[] { Interop.WindowMessages.WM_PARENTNOTIFY, " (WM_PARENTNOTIFY)", " (WM_DESTROY)" }; + yield return new object[] { Interop.WindowMessages.WM_ENTERMENULOOP, " (WM_ENTERMENULOOP)" }; + yield return new object[] { Interop.WindowMessages.WM_EXITMENULOOP, " (WM_EXITMENULOOP)" }; + yield return new object[] { Interop.WindowMessages.WM_NEXTMENU, " (WM_NEXTMENU)" }; + yield return new object[] { Interop.WindowMessages.WM_SIZING, " (WM_SIZING)" }; + yield return new object[] { Interop.WindowMessages.WM_CAPTURECHANGED, " (WM_CAPTURECHANGED)" }; + yield return new object[] { Interop.WindowMessages.WM_MOVING, " (WM_MOVING)" }; + yield return new object[] { Interop.WindowMessages.WM_POWERBROADCAST, " (WM_POWERBROADCAST)" }; + yield return new object[] { Interop.WindowMessages.WM_DEVICECHANGE, " (WM_DEVICECHANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_SETCONTEXT, " (WM_IME_SETCONTEXT)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_NOTIFY, " (WM_IME_NOTIFY)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_CONTROL, " (WM_IME_CONTROL)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_COMPOSITIONFULL, " (WM_IME_COMPOSITIONFULL)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_SELECT, " (WM_IME_SELECT)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_CHAR, " (WM_IME_CHAR)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_KEYDOWN, " (WM_IME_KEYDOWN)" }; + yield return new object[] { Interop.WindowMessages.WM_IME_KEYUP, " (WM_IME_KEYUP)" }; + yield return new object[] { Interop.WindowMessages.WM_MDICREATE, " (WM_MDICREATE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIDESTROY, " (WM_MDIDESTROY)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIACTIVATE, " (WM_MDIACTIVATE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIRESTORE, " (WM_MDIRESTORE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDINEXT, " (WM_MDINEXT)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIMAXIMIZE, " (WM_MDIMAXIMIZE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDITILE, " (WM_MDITILE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDICASCADE, " (WM_MDICASCADE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIICONARRANGE, " (WM_MDIICONARRANGE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIGETACTIVE, " (WM_MDIGETACTIVE)" }; + yield return new object[] { Interop.WindowMessages.WM_MDISETMENU, " (WM_MDISETMENU)" }; + yield return new object[] { Interop.WindowMessages.WM_ENTERSIZEMOVE, " (WM_ENTERSIZEMOVE)" }; + yield return new object[] { Interop.WindowMessages.WM_EXITSIZEMOVE, " (WM_EXITSIZEMOVE)" }; + yield return new object[] { Interop.WindowMessages.WM_DROPFILES, " (WM_DROPFILES)" }; + yield return new object[] { Interop.WindowMessages.WM_MDIREFRESHMENU, " (WM_MDIREFRESHMENU)" }; + yield return new object[] { Interop.WindowMessages.WM_MOUSEHOVER, " (WM_MOUSEHOVER)" }; + yield return new object[] { Interop.WindowMessages.WM_MOUSELEAVE, " (WM_MOUSELEAVE)" }; + yield return new object[] { Interop.WindowMessages.WM_CUT, " (WM_CUT)" }; + yield return new object[] { Interop.WindowMessages.WM_COPY, " (WM_COPY)" }; + yield return new object[] { Interop.WindowMessages.WM_PASTE, " (WM_PASTE)" }; + yield return new object[] { Interop.WindowMessages.WM_CLEAR, " (WM_CLEAR)" }; + yield return new object[] { Interop.WindowMessages.WM_UNDO, " (WM_UNDO)" }; + yield return new object[] { Interop.WindowMessages.WM_RENDERFORMAT, " (WM_RENDERFORMAT)" }; + yield return new object[] { Interop.WindowMessages.WM_RENDERALLFORMATS, " (WM_RENDERALLFORMATS)" }; + yield return new object[] { Interop.WindowMessages.WM_DESTROYCLIPBOARD, " (WM_DESTROYCLIPBOARD)" }; + yield return new object[] { Interop.WindowMessages.WM_DRAWCLIPBOARD, " (WM_DRAWCLIPBOARD)" }; + yield return new object[] { Interop.WindowMessages.WM_PAINTCLIPBOARD, " (WM_PAINTCLIPBOARD)" }; + yield return new object[] { Interop.WindowMessages.WM_VSCROLLCLIPBOARD, " (WM_VSCROLLCLIPBOARD)" }; + yield return new object[] { Interop.WindowMessages.WM_SIZECLIPBOARD, " (WM_SIZECLIPBOARD)" }; + yield return new object[] { Interop.WindowMessages.WM_ASKCBFORMATNAME, " (WM_ASKCBFORMATNAME)" }; + yield return new object[] { Interop.WindowMessages.WM_CHANGECBCHAIN, " (WM_CHANGECBCHAIN)" }; + yield return new object[] { Interop.WindowMessages.WM_HSCROLLCLIPBOARD, " (WM_HSCROLLCLIPBOARD)" }; + yield return new object[] { Interop.WindowMessages.WM_QUERYNEWPALETTE, " (WM_QUERYNEWPALETTE)" }; + yield return new object[] { Interop.WindowMessages.WM_PALETTEISCHANGING, " (WM_PALETTEISCHANGING)" }; + yield return new object[] { Interop.WindowMessages.WM_PALETTECHANGED, " (WM_PALETTECHANGED)" }; + yield return new object[] { Interop.WindowMessages.WM_HOTKEY, " (WM_HOTKEY)" }; + yield return new object[] { Interop.WindowMessages.WM_PRINT, " (WM_PRINT)" }; + yield return new object[] { Interop.WindowMessages.WM_PRINTCLIENT, " (WM_PRINTCLIENT)" }; + yield return new object[] { Interop.WindowMessages.WM_HANDHELDFIRST, " (WM_HANDHELDFIRST)" }; + yield return new object[] { Interop.WindowMessages.WM_HANDHELDLAST, " (WM_HANDHELDLAST)" }; + yield return new object[] { Interop.WindowMessages.WM_AFXFIRST, " (WM_AFXFIRST)" }; + yield return new object[] { Interop.WindowMessages.WM_AFXLAST, " (WM_AFXLAST)" }; + yield return new object[] { Interop.WindowMessages.WM_PENWINFIRST, " (WM_PENWINFIRST)" }; + yield return new object[] { Interop.WindowMessages.WM_PENWINLAST, " (WM_PENWINLAST)" }; + yield return new object[] { Interop.WindowMessages.WM_APP, " (WM_APP)" }; + yield return new object[] { Interop.WindowMessages.WM_USER, " (WM_USER)" }; + yield return new object[] { Interop.WindowMessages.WM_CTLCOLOR, " (WM_CTLCOLOR)" }; + + // RichEdit messages + yield return new object[] { Interop.EditMessages.EM_GETLIMITTEXT, " (EM_GETLIMITTEXT)" }; + yield return new object[] { Interop.EditMessages.EM_POSFROMCHAR, " (EM_POSFROMCHAR)" }; + yield return new object[] { Interop.EditMessages.EM_CHARFROMPOS, " (EM_CHARFROMPOS)" }; + yield return new object[] { Interop.EditMessages.EM_SCROLLCARET, " (EM_SCROLLCARET)" }; + yield return new object[] { Interop.EditMessages.EM_CANPASTE, " (EM_CANPASTE)" }; + yield return new object[] { Interop.EditMessages.EM_DISPLAYBAND, " (EM_DISPLAYBAND)" }; + yield return new object[] { Interop.EditMessages.EM_EXGETSEL, " (EM_EXGETSEL)" }; + yield return new object[] { Interop.EditMessages.EM_EXLIMITTEXT, " (EM_EXLIMITTEXT)" }; + yield return new object[] { Interop.EditMessages.EM_EXLINEFROMCHAR, " (EM_EXLINEFROMCHAR)" }; + yield return new object[] { Interop.EditMessages.EM_EXSETSEL, " (EM_EXSETSEL)" }; + yield return new object[] { Interop.EditMessages.EM_FINDTEXT, " (EM_FINDTEXT)" }; + yield return new object[] { Interop.EditMessages.EM_FORMATRANGE, " (EM_FORMATRANGE)" }; + yield return new object[] { Interop.EditMessages.EM_GETCHARFORMAT, " (EM_GETCHARFORMAT)" }; + yield return new object[] { Interop.EditMessages.EM_GETEVENTMASK, " (EM_GETEVENTMASK)" }; + yield return new object[] { Interop.EditMessages.EM_GETOLEINTERFACE, " (EM_GETOLEINTERFACE)" }; + yield return new object[] { Interop.EditMessages.EM_GETPARAFORMAT, " (EM_GETPARAFORMAT)" }; + yield return new object[] { Interop.EditMessages.EM_GETSELTEXT, " (EM_GETSELTEXT)" }; + yield return new object[] { Interop.EditMessages.EM_HIDESELECTION, " (EM_HIDESELECTION)" }; + yield return new object[] { Interop.EditMessages.EM_PASTESPECIAL, " (EM_PASTESPECIAL)" }; + yield return new object[] { Interop.EditMessages.EM_REQUESTRESIZE, " (EM_REQUESTRESIZE)" }; + yield return new object[] { Interop.EditMessages.EM_SELECTIONTYPE, " (EM_SELECTIONTYPE)" }; + yield return new object[] { Interop.EditMessages.EM_SETBKGNDCOLOR, " (EM_SETBKGNDCOLOR)" }; + yield return new object[] { Interop.EditMessages.EM_SETCHARFORMAT, " (EM_SETCHARFORMAT)" }; + yield return new object[] { Interop.EditMessages.EM_SETEVENTMASK, " (EM_SETEVENTMASK)" }; + yield return new object[] { Interop.EditMessages.EM_SETOLECALLBACK, " (EM_SETOLECALLBACK)" }; + yield return new object[] { Interop.EditMessages.EM_SETPARAFORMAT, " (EM_SETPARAFORMAT)" }; + yield return new object[] { Interop.EditMessages.EM_SETTARGETDEVICE, " (EM_SETTARGETDEVICE)" }; + yield return new object[] { Interop.EditMessages.EM_STREAMIN, " (EM_STREAMIN)" }; + yield return new object[] { Interop.EditMessages.EM_STREAMOUT, " (EM_STREAMOUT)" }; + yield return new object[] { Interop.EditMessages.EM_GETTEXTRANGE, " (EM_GETTEXTRANGE)" }; + yield return new object[] { Interop.EditMessages.EM_FINDWORDBREAK, " (EM_FINDWORDBREAK)" }; + yield return new object[] { Interop.EditMessages.EM_SETOPTIONS, " (EM_SETOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_GETOPTIONS, " (EM_GETOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_FINDTEXTEX, " (EM_FINDTEXTEX)" }; + yield return new object[] { Interop.EditMessages.EM_GETWORDBREAKPROCEX, " (EM_GETWORDBREAKPROCEX)" }; + yield return new object[] { Interop.EditMessages.EM_SETWORDBREAKPROCEX, " (EM_SETWORDBREAKPROCEX)" }; + + // Richedit v2.0 messages + yield return new object[] { Interop.EditMessages.EM_SETUNDOLIMIT, " (EM_SETUNDOLIMIT)" }; + yield return new object[] { Interop.EditMessages.EM_REDO, " (EM_REDO)" }; + yield return new object[] { Interop.EditMessages.EM_CANREDO, " (EM_CANREDO)" }; + yield return new object[] { Interop.EditMessages.EM_GETUNDONAME, " (EM_GETUNDONAME)" }; + yield return new object[] { Interop.EditMessages.EM_GETREDONAME, " (EM_GETREDONAME)" }; + yield return new object[] { Interop.EditMessages.EM_STOPGROUPTYPING, " (EM_STOPGROUPTYPING)" }; + yield return new object[] { Interop.EditMessages.EM_SETTEXTMODE, " (EM_SETTEXTMODE)" }; + yield return new object[] { Interop.EditMessages.EM_GETTEXTMODE, " (EM_GETTEXTMODE)" }; + yield return new object[] { Interop.EditMessages.EM_AUTOURLDETECT, " (EM_AUTOURLDETECT)" }; + yield return new object[] { Interop.EditMessages.EM_GETAUTOURLDETECT, " (EM_GETAUTOURLDETECT)" }; + yield return new object[] { Interop.EditMessages.EM_SETPALETTE, " (EM_SETPALETTE)" }; + yield return new object[] { Interop.EditMessages.EM_GETTEXTEX, " (EM_GETTEXTEX)" }; + yield return new object[] { Interop.EditMessages.EM_GETTEXTLENGTHEX, " (EM_GETTEXTLENGTHEX)" }; + + // Asia specific messages + yield return new object[] { Interop.EditMessages.EM_SETPUNCTUATION, " (EM_SETPUNCTUATION)" }; + yield return new object[] { Interop.EditMessages.EM_GETPUNCTUATION, " (EM_GETPUNCTUATION)" }; + yield return new object[] { Interop.EditMessages.EM_SETWORDWRAPMODE, " (EM_SETWORDWRAPMODE)" }; + yield return new object[] { Interop.EditMessages.EM_GETWORDWRAPMODE, " (EM_GETWORDWRAPMODE)" }; + yield return new object[] { Interop.EditMessages.EM_SETIMECOLOR, " (EM_SETIMECOLOR)" }; + yield return new object[] { Interop.EditMessages.EM_GETIMECOLOR, " (EM_GETIMECOLOR)" }; + yield return new object[] { Interop.EditMessages.EM_SETIMEOPTIONS, " (EM_SETIMEOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_GETIMEOPTIONS, " (EM_GETIMEOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_CONVPOSITION, " (EM_CONVPOSITION)" }; + yield return new object[] { Interop.EditMessages.EM_SETLANGOPTIONS, " (EM_SETLANGOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_GETLANGOPTIONS, " (EM_GETLANGOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_GETIMECOMPMODE, " (EM_GETIMECOMPMODE)" }; + yield return new object[] { Interop.EditMessages.EM_FINDTEXTW, " (EM_FINDTEXTW)" }; + yield return new object[] { Interop.EditMessages.EM_FINDTEXTEXW, " (EM_FINDTEXTEXW)" }; + + // Rich Edit 3.0 Asia msgs + yield return new object[] { Interop.EditMessages.EM_RECONVERSION, " (EM_RECONVERSION)" }; + yield return new object[] { Interop.EditMessages.EM_SETIMEMODEBIAS, " (EM_SETIMEMODEBIAS)" }; + yield return new object[] { Interop.EditMessages.EM_GETIMEMODEBIAS, " (EM_GETIMEMODEBIAS)" }; + + // BiDi Specific messages + yield return new object[] { Interop.EditMessages.EM_SETBIDIOPTIONS, " (EM_SETBIDIOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_GETBIDIOPTIONS, " (EM_GETBIDIOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_SETTYPOGRAPHYOPTIONS, " (EM_SETTYPOGRAPHYOPTIONS)" }; + yield return new object[] { Interop.EditMessages.EM_GETTYPOGRAPHYOPTIONS, " (EM_GETTYPOGRAPHYOPTIONS)" }; + + // Extended Edit style specific messages + yield return new object[] { Interop.EditMessages.EM_SETEDITSTYLE, " (EM_SETEDITSTYLE)" }; + yield return new object[] { Interop.EditMessages.EM_GETEDITSTYLE, " (EM_GETEDITSTYLE)" }; + } + + [Theory] + [MemberData(nameof(ToString_TestData))] + public void Message_ToString_Invoke_ReturnsExpected(int msg, string expected, string additionalMsg = null) + { + Message message = Message.Create((IntPtr)1, msg, (IntPtr)2, (IntPtr)3); + message.Result = (IntPtr)4; + Assert.Equal("msg=0x" + Convert.ToString(msg, 16) + expected + " hwnd=0x1 wparam=0x2 lparam=0x3" + additionalMsg + " result=0x4", message.ToString()); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/OSFeatureTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/OSFeatureTests.cs new file mode 100644 index 00000000000..1aa2f445fc4 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/OSFeatureTests.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Reflection; +using Moq; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class OSFeatureTests + { + [Fact] + public void OSFeature_Ctor_Default() + { + // Make sure it doesn't throw. + new SubOSFeature(); + } + + [Fact] + public void OSFeature_Feature_Get_ReturnsExpected() + { + OSFeature feature = OSFeature.Feature; + Assert.NotNull(feature); + Assert.Same(feature, OSFeature.Feature); + } + + [Fact] + public void OSFeature_LayeredWindows_Get_ReturnsExpected() + { + object feature = OSFeature.LayeredWindows; + Assert.NotNull(feature); + Assert.Same(feature, OSFeature.LayeredWindows); + } + + [Fact] + public void OSFeature_Themes_Get_ReturnsExpected() + { + object feature = OSFeature.Themes; + Assert.NotNull(feature); + Assert.Same(feature, OSFeature.Themes); + } + + public static IEnumerable GetVersionPresent_TestData() + { + yield return new object[] { OSFeature.LayeredWindows, new Version(0, 0, 0, 0) }; + yield return new object[] { OSFeature.Themes, new Version(0, 0, 0, 0) }; + yield return new object[] { new object(), null }; + yield return new object[] { null, null }; + } + + [Theory] + [MemberData(nameof(GetVersionPresent_TestData))] + public void OSFeature_GetVersionPresent_Invoke_ReturnsExpected(object feature, Version expected) + { + Assert.Equal(expected, OSFeature.Feature.GetVersionPresent(feature)); + + // Call again to test caching. + Assert.Equal(expected, OSFeature.Feature.GetVersionPresent(feature)); + } + + public static IEnumerable IsPresent_TestData() + { + yield return new object[] { SystemParameter.DropShadow, true }; + yield return new object[] { SystemParameter.FlatMenu, true }; + yield return new object[] { SystemParameter.FontSmoothingContrastMetric, true }; + yield return new object[] { SystemParameter.FontSmoothingTypeMetric, true }; + yield return new object[] { SystemParameter.MenuFadeEnabled, true }; + yield return new object[] { SystemParameter.SelectionFade, true }; + yield return new object[] { SystemParameter.ToolTipAnimationMetric, true }; + yield return new object[] { SystemParameter.UIEffects, true }; + yield return new object[] { SystemParameter.CaretWidthMetric, true }; + yield return new object[] { SystemParameter.VerticalFocusThicknessMetric, true }; + yield return new object[] { SystemParameter.HorizontalFocusThicknessMetric, true }; + yield return new object[] { SystemParameter.DropShadow - 1, false }; + yield return new object[] { SystemParameter.HorizontalFocusThicknessMetric + 1, false }; + } + + [Theory] + [MemberData(nameof(IsPresent_TestData))] + public void OSFeature_IsPresent_Invoke_ReturnsExpected(SystemParameter feature, bool expected) + { + Assert.Equal(expected, OSFeature.IsPresent(feature)); + } + + private class SubOSFeature : OSFeature + { + public SubOSFeature() : base() + { + } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/OwnerDrawPropertyBagTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/OwnerDrawPropertyBagTests.cs new file mode 100644 index 00000000000..1f34a109bab --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/OwnerDrawPropertyBagTests.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class OwnerDrawPropertyBagTests + { + [Fact] + public void OwnerDrawPropertyBag_Ctor_Default() + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag bag = treeView.GetItemRenderStyles(null, 0); + Assert.Equal(Color.Empty, bag.BackColor); + Assert.Null(bag.Font); + Assert.Equal(Color.Empty, bag.ForeColor); + Assert.True(bag.IsEmpty()); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetColorWithEmptyTheoryData))] + public void OwnerDrawPropertyBag_BackColor_Set_GetReturnsExpected(Color value) + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag bag = treeView.GetItemRenderStyles(null, 0); + + bag.BackColor = value; + Assert.Equal(value, bag.BackColor); + Assert.Equal(value.IsEmpty, bag.IsEmpty()); + + // Set same. + bag.BackColor = value; + Assert.Equal(value, bag.BackColor); + Assert.Equal(value.IsEmpty, bag.IsEmpty()); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetFontTheoryData))] + public void OwnerDrawPropertyBag_Font_Set_GetReturnsExpected(Font value) + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag bag = treeView.GetItemRenderStyles(null, 0); + + bag.Font = value; + Assert.Same(value, bag.Font); + Assert.Equal(value == null, bag.IsEmpty()); + + // Set same. + bag.Font = value; + Assert.Same(value, bag.Font); + Assert.Equal(value == null, bag.IsEmpty()); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetColorWithEmptyTheoryData))] + public void OwnerDrawPropertyBag_ForeColor_Set_GetReturnsExpected(Color value) + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag bag = treeView.GetItemRenderStyles(null, 0); + + bag.ForeColor = value; + Assert.Equal(value, bag.ForeColor); + Assert.Equal(value.IsEmpty, bag.IsEmpty()); + + // Set same. + bag.ForeColor = value; + Assert.Equal(value, bag.ForeColor); + Assert.Equal(value.IsEmpty, bag.IsEmpty()); + } + + [Fact] + public void OwnerDrawPropertyBag_Copy_CustomValue_ReturnsClone() + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag value = treeView.GetItemRenderStyles(null, 0); + value.BackColor = Color.Blue; + value.Font = SystemFonts.MenuFont; + value.ForeColor = Color.Red; + + OwnerDrawPropertyBag bag = OwnerDrawPropertyBag.Copy(value); + Assert.NotSame(value, bag); + Assert.Equal(Color.Blue, bag.BackColor); + Assert.Equal(SystemFonts.MenuFont.Name, bag.Font.Name); + Assert.Equal(Color.Red, bag.ForeColor); + Assert.False(bag.IsEmpty()); + } + + [Fact] + public void OwnerDrawPropertyBag_Copy_NullValue_ReturnsDefault() + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag value = treeView.GetItemRenderStyles(null, 0); + OwnerDrawPropertyBag bag = OwnerDrawPropertyBag.Copy(value); + Assert.NotSame(value, bag); + Assert.Equal(Color.Empty, bag.BackColor); + Assert.Null(bag.Font); + Assert.Equal(Color.Empty, bag.ForeColor); + Assert.True(bag.IsEmpty()); + } + + [Fact] + public void OwnerDrawPropertyBag_Serailize_Deserialize_Success() + { + var treeView = new SubTreeView(); + OwnerDrawPropertyBag original = treeView.GetItemRenderStyles(null, 0); + original.BackColor = Color.Blue; + original.Font = SystemFonts.MenuFont; + original.ForeColor = Color.Red; + + using (var stream = new MemoryStream()) + { + var formatter = new BinaryFormatter(); + formatter.Serialize(stream, original); + + stream.Position = 0; + OwnerDrawPropertyBag bag = Assert.IsType(formatter.Deserialize(stream)); + Assert.Equal(Color.Blue, bag.BackColor); + Assert.Equal(SystemFonts.MenuFont.Name, bag.Font.Name); + Assert.Equal(Color.Red, bag.ForeColor); + Assert.False(bag.IsEmpty()); + } + } + + private class SubTreeView : TreeView + { + public new OwnerDrawPropertyBag GetItemRenderStyles(TreeNode node, int state) => base.GetItemRenderStyles(node, state); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingConverterTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingConverterTests.cs index 6fb80e73438..d29e65305c7 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingConverterTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingConverterTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; +using System.Globalization; using Moq; using WinForms.Common.Tests; using Xunit; @@ -14,12 +15,8 @@ namespace System.Windows.Forms.Tests { public class PaddingConverterTests { - - public static TheoryData CanConvertFromData => - CommonTestHelper.GetConvertFromTheoryData(); - [Theory] - [MemberData(nameof(CanConvertFromData))] + [CommonMemberData(nameof(CommonTestHelper.GetConvertFromTheoryData))] [InlineData(typeof(Padding), false)] [InlineData(typeof(string), true)] public void PaddingConverter_CanConvertFrom_Invoke_ReturnsExpected(Type sourceType, bool expected) @@ -43,6 +40,7 @@ public void PaddingConverter_ConvertFrom_String_ReturnsExpected(string value, ob var converter = new PaddingConverter(); Assert.Equal(expected, converter.ConvertFrom(value)); Assert.Equal(expected, converter.ConvertFrom(null, null, value)); + Assert.Equal(expected, converter.ConvertFrom(null, CultureInfo.InvariantCulture, value)); } [Theory] @@ -60,7 +58,7 @@ public void PaddingConverter_ConvertFrom_InvalidValue_ThrowsNotSupportedExceptio public void PaddingConverter_ConvertFrom_InvalidString_ThrowsArgumentException(string value) { var converter = new PaddingConverter(); - Assert.Throws(null, () => converter.ConvertFrom(value)); + Assert.Throws("value", () => converter.ConvertFrom(value)); } [Theory] @@ -81,6 +79,7 @@ public void PaddingConverter_ConvertTo_String_ReturnsExpected() var converter = new PaddingConverter(); Assert.Equal("1, 2, 3, 4", converter.ConvertTo(new Padding(1, 2, 3, 4), typeof(string))); Assert.Equal("1, 2, 3, 4", converter.ConvertTo(null, null, new Padding(1, 2, 3, 4), typeof(string))); + Assert.Equal("1, 2, 3, 4", converter.ConvertTo(null, CultureInfo.InvariantCulture, new Padding(1, 2, 3, 4), typeof(string))); } [Fact] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingTests.cs index 6f708634d1d..8ced8d2e348 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PaddingTests.cs @@ -92,6 +92,46 @@ public void Padding_All_Set_GetReturnsExpected(int value) Assert.Equal(value, padding.Bottom); } + [Fact] + public void Padding_AllPropertyDescriptor_ResetValue_SetsToZero() + { + var padding = new Padding(1, 2, 3, 4); + object boxedPadding = padding; + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(padding); + PropertyDescriptor property = properties[nameof(Padding.All)]; + Assert.False(property.CanResetValue(boxedPadding)); + Assert.False(property.ShouldSerializeValue(boxedPadding)); + property.ResetValue(boxedPadding); + + Assert.Equal(0, ((Padding)boxedPadding).All); + Assert.Equal(0, ((Padding)boxedPadding).Left); + Assert.Equal(0, ((Padding)boxedPadding).Top); + Assert.Equal(0, ((Padding)boxedPadding).Right); + Assert.Equal(0, ((Padding)boxedPadding).Bottom); + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + } + + [Fact] + public void Padding_AllPropertyDescriptor_ResetValueOnAll_SetsToZero() + { + var padding = new Padding(1); + object boxedPadding = padding; + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(padding); + PropertyDescriptor property = properties[nameof(Padding.All)]; + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + property.ResetValue(boxedPadding); + + Assert.Equal(0, ((Padding)boxedPadding).All); + Assert.Equal(0, ((Padding)boxedPadding).Left); + Assert.Equal(0, ((Padding)boxedPadding).Top); + Assert.Equal(0, ((Padding)boxedPadding).Right); + Assert.Equal(0, ((Padding)boxedPadding).Bottom); + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + } + [Theory] [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] public void Padding_All_SetOnAll_GetReturnsExpected(int value) @@ -122,6 +162,26 @@ public void Padding_Left_Set_GetReturnsExpected(int value) Assert.Equal(4, padding.Bottom); } + [Fact] + public void Padding_LeftPropertyDescriptor_ResetValue_SetsToZero() + { + var padding = new Padding(1, 2, 3, 4); + object boxedPadding = padding; + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(padding); + PropertyDescriptor property = properties[nameof(Padding.Left)]; + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + property.ResetValue(boxedPadding); + + Assert.Equal(-1, ((Padding)boxedPadding).All); + Assert.Equal(0, ((Padding)boxedPadding).Left); + Assert.Equal(2, ((Padding)boxedPadding).Top); + Assert.Equal(3, ((Padding)boxedPadding).Right); + Assert.Equal(4, ((Padding)boxedPadding).Bottom); + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + } + [Theory] [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] public void Padding_Left_SetOnAll_GetReturnsExpected(int value) @@ -152,6 +212,26 @@ public void Padding_Top_Set_GetReturnsExpected(int value) Assert.Equal(4, padding.Bottom); } + [Fact] + public void Padding_TopPropertyDescriptor_ResetValue_SetsToZero() + { + var padding = new Padding(1, 2, 3, 4); + object boxedPadding = padding; + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(padding); + PropertyDescriptor property = properties[nameof(Padding.Top)]; + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + property.ResetValue(boxedPadding); + + Assert.Equal(-1, ((Padding)boxedPadding).All); + Assert.Equal(1, ((Padding)boxedPadding).Left); + Assert.Equal(0, ((Padding)boxedPadding).Top); + Assert.Equal(3, ((Padding)boxedPadding).Right); + Assert.Equal(4, ((Padding)boxedPadding).Bottom); + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + } + [Theory] [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] public void Padding_Top_SetOnAll_GetReturnsExpected(int value) @@ -182,6 +262,26 @@ public void Padding_Right_Set_GetReturnsExpected(int value) Assert.Equal(4, padding.Bottom); } + [Fact] + public void Padding_RightPropertyDescriptor_ResetValue_SetsToZero() + { + var padding = new Padding(1, 2, 3, 4); + object boxedPadding = padding; + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(padding); + PropertyDescriptor property = properties[nameof(Padding.Right)]; + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + property.ResetValue(boxedPadding); + + Assert.Equal(-1, ((Padding)boxedPadding).All); + Assert.Equal(1, ((Padding)boxedPadding).Left); + Assert.Equal(2, ((Padding)boxedPadding).Top); + Assert.Equal(0, ((Padding)boxedPadding).Right); + Assert.Equal(4, ((Padding)boxedPadding).Bottom); + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + } + [Theory] [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] public void Padding_Right_SetOnAll_GetReturnsExpected(int value) @@ -212,6 +312,26 @@ public void Padding_Bottom_Set_GetReturnsExpected(int value) Assert.Equal(value, padding.Bottom); } + [Fact] + public void Padding_BottomPropertyDescriptor_ResetValue_SetsToZero() + { + var padding = new Padding(1, 2, 3, 4); + object boxedPadding = padding; + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(padding); + PropertyDescriptor property = properties[nameof(Padding.Bottom)]; + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + property.ResetValue(boxedPadding); + + Assert.Equal(-1, ((Padding)boxedPadding).All); + Assert.Equal(1, ((Padding)boxedPadding).Left); + Assert.Equal(2, ((Padding)boxedPadding).Top); + Assert.Equal(3, ((Padding)boxedPadding).Right); + Assert.Equal(0, ((Padding)boxedPadding).Bottom); + Assert.True(property.CanResetValue(boxedPadding)); + Assert.True(property.ShouldSerializeValue(boxedPadding)); + } + [Theory] [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] public void Padding_Bottom_SetOnAll_GetReturnsExpected(int value) @@ -298,5 +418,12 @@ public void Padding_ToString_InvokeAll_ReturnsExpected() var padding = new Padding(1); Assert.Equal("{Left=1,Top=1,Right=1,Bottom=1}", padding.ToString()); } + + [Fact] + public void Padding_TypeConverter_Get_ReturnsPaddingConverter() + { + var padding = new Padding(1); + Assert.IsType(TypeDescriptor.GetConverter(padding)); + } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/RowStyleTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/RowStyleTests.cs index 5407e106d34..3f00e47ea96 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/RowStyleTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/RowStyleTests.cs @@ -44,7 +44,7 @@ public void RowStyle_Ctor_SizeType_Float(SizeType sizeType, float height) [Fact] public void RowStyle_Ctor_NegativeHeight_ThrowsArgumentOutOfRangeException() { - Assert.Throws("Size", () => new RowStyle(SizeType.AutoSize, -1)); + Assert.Throws("value", () => new RowStyle(SizeType.AutoSize, -1)); } [Theory] @@ -74,7 +74,7 @@ public void RowStyle_Height_SetOwned_GetReturnsExpected(float value) public void RowStyle_Height_SetNegative_ThrowsArgumentOutOfRangeException() { var style = new RowStyle(); - Assert.Throws("Size", () => style.Height = -1); + Assert.Throws("value", () => style.Height = -1); } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollPropertiesTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollPropertiesTests.cs index 818ea6cdc4f..53488c8f470 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollPropertiesTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollPropertiesTests.cs @@ -101,7 +101,7 @@ public void ScrollProperties_LargeChange_SetNegative_ThrowsArgumentOutOfRangeExc { var control = new ScrollableControl(); var properties = new SubScrollProperties(control); - Assert.Throws("LargeChange", () => properties.LargeChange = -1); + Assert.Throws("value", () => properties.LargeChange = -1); Assert.Equal(10, properties.LargeChange); } @@ -150,7 +150,7 @@ public void ScrollProperties_SmallChange_SetNegative_ThrowsArgumentOutOfRangeExc { var control = new ScrollableControl(); var properties = new SubScrollProperties(control); - Assert.Throws("SmallChange", () => properties.SmallChange = -1); + Assert.Throws("value", () => properties.SmallChange = -1); Assert.Equal(1, properties.SmallChange); } @@ -301,7 +301,7 @@ public void ScrollProperties_Minimum_SetNegative_ThrowsArgumentOutOfRangeExcepti { var control = new ScrollableControl(); var properties = new SubScrollProperties(control); - Assert.Throws("Minimum", () => properties.Minimum = -1); + Assert.Throws("value", () => properties.Minimum = -1); Assert.Equal(0, properties.Minimum); } @@ -359,7 +359,7 @@ public void ScrollProperties_Value_SetOutOfRange_ThrowsArgumentOutOfRangeExcepti { var control = new ScrollableControl(); var properties = new SubScrollProperties(control); - Assert.Throws("Value", () => properties.Value = value); + Assert.Throws("value", () => properties.Value = value); Assert.Equal(0, properties.Value); } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollableControlTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollableControlTests.cs index 3d8c2653e02..4de90798b8f 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollableControlTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ScrollableControlTests.cs @@ -19,6 +19,9 @@ public void ScrollableControl_Ctor_Default() Assert.False(control.AutoScroll); Assert.Equal(Size.Empty, control.AutoScrollMargin); Assert.Equal(Point.Empty, control.AutoScrollPosition); + Assert.Equal(Rectangle.Empty, control.Bounds); + Assert.Equal(Size.Empty, control.ClientSize); + Assert.Equal(Rectangle.Empty, control.ClientRectangle); Assert.NotNull(control.HorizontalScroll); Assert.Same(control.HorizontalScroll, control.HorizontalScroll); Assert.NotNull(control.VerticalScroll); @@ -30,44 +33,51 @@ public void ScrollableControl_Ctor_Default() Assert.Equal(0, control.DockPadding.Left); Assert.Equal(0, control.DockPadding.Right); Assert.Equal(Rectangle.Empty, control.DisplayRectangle); - Assert.False(control.HScrollEntry); - Assert.False(control.VScrollEntry); + Assert.False(control.HScroll); + Assert.Equal(Padding.Empty, control.Padding); + Assert.Equal(RightToLeft.No, control.RightToLeft); + Assert.False(control.VScroll); + Assert.True(control.Visible); } [Theory] [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] public void ScrollableControl_AutoScroll_Set_GetReturnsExpected(bool value) { - var control = new ScrollableControl() + var control = new SubScrollableControl { AutoScroll = value }; Assert.Equal(value, control.AutoScroll); + Assert.Equal(value, control.GetScrollState(SubScrollableControl.ScrollStateAutoScrolling)); + + // Set same. + control.AutoScroll = value; + Assert.Equal(value, control.AutoScroll); + Assert.Equal(value, control.GetScrollState(SubScrollableControl.ScrollStateAutoScrolling)); } [Theory] - [MemberData(nameof(TestHelper.GetSizeTheoryData), TestIncludeType.NoNegatives, MemberType = typeof(TestHelper))] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoNegatives)] public void ScrollableControl_AutoScrollMargin_Set_GetReturnsExpected(Size value) { - var control = new ScrollableControl() + var control = new ScrollableControl { AutoScrollMargin = value }; Assert.Equal(value, control.AutoScrollMargin); - } - public static IEnumerable AutoScrollMargin_Invalid_TestData() - { - yield return new object[] { new Size(-1, 0) }; - yield return new object[] { new Size(0, -1) }; + // Set same. + control.AutoScrollMargin = value; + Assert.Equal(value, control.AutoScrollMargin); } [Theory] - [MemberData(nameof(AutoScrollMargin_Invalid_TestData))] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoPositives)] public void ScrollableControl_AutoScrollMargin_SetInvalid_ThrowsArgumentOutOfRangeException(Size value) { var control = new ScrollableControl(); - Assert.Throws("AutoScrollMargin", () => control.AutoScrollMargin = value); + Assert.Throws("value", () => control.AutoScrollMargin = value); } public static IEnumerable SetAutoScrollMargin_TestData() @@ -89,48 +99,101 @@ public void ScrollableControl_SetAutoScrollMargin_Invoke_Success(int width, int } [Theory] - [MemberData(nameof(TestHelper.GetPointTheoryData), MemberType = typeof(TestHelper))] + [CommonMemberData(nameof(CommonTestHelper.GetPointTheoryData))] public void ScrollableControl_AutoScrollPosition_Set_GetReturnsExpected(Point value) { - var control = new ScrollableControl() + var control = new ScrollableControl + { + AutoScrollPosition = value + }; + Assert.Equal(Point.Empty, control.AutoScrollPosition); + + // Set same. + control.AutoScrollPosition = value; + Assert.Equal(Point.Empty, control.AutoScrollPosition); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetPointTheoryData))] + public void ScrollableControl_AutoScrollPosition_SetWithAutoScroll_GetReturnsExpected(Point value) + { + var control = new ScrollableControl { + AutoScroll = true, AutoScrollPosition = value }; Assert.Equal(Point.Empty, control.AutoScrollPosition); + + // Set same. + control.AutoScrollPosition = value; + Assert.Equal(Point.Empty, control.AutoScrollPosition); } [Theory] - [MemberData(nameof(TestHelper.GetSizeTheoryData), MemberType = typeof(TestHelper))] + [CommonMemberData(nameof(CommonTestHelper.GetPointTheoryData))] + public void ScrollableControl_AutoScrollPosition_SetWithVisibleBars_GetReturnsExpected(Point value) + { + var control = new ScrollableControl(); + control.HorizontalScroll.Visible = true; + control.VerticalScroll.Visible = true; + + control.AutoScrollPosition = value; + Assert.Equal(Point.Empty, control.AutoScrollPosition); + + // Set same. + control.AutoScrollPosition = value; + Assert.Equal(Point.Empty, control.AutoScrollPosition); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] public void ScrollableControl_AutoScrollMinSize_Set_GetReturnsExpected(Size value) { - var control = new ScrollableControl() + var control = new ScrollableControl { AutoScrollMinSize = value }; Assert.Equal(value, control.AutoScrollMinSize); Assert.Equal(value != Size.Empty, control.AutoScroll); + + // Set same. + control.AutoScrollMinSize = value; + Assert.Equal(value, control.AutoScrollMinSize); + Assert.Equal(value != Size.Empty, control.AutoScroll); } [Theory] [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] public void ScrollableControl_HScroll_Set_GetReturnsExpected(bool value) { - var control = new SubScrollableControl() + var control = new SubScrollableControl { - HScrollEntry = value + HScroll = value }; - Assert.Equal(value, control.HScrollEntry); + Assert.Equal(value, control.HScroll); + Assert.Equal(value, control.GetScrollState(SubScrollableControl.ScrollStateHScrollVisible)); + + // Set same. + control.HScroll = value; + Assert.Equal(value, control.HScroll); + Assert.Equal(value, control.GetScrollState(SubScrollableControl.ScrollStateHScrollVisible)); } [Theory] [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] public void ScrollableControl_VScroll_Set_GetReturnsExpected(bool value) { - var control = new SubScrollableControl() + var control = new SubScrollableControl { - VScrollEntry = value + VScroll = value }; - Assert.Equal(value, control.VScrollEntry); + Assert.Equal(value, control.VScroll); + Assert.Equal(value, control.GetScrollState(SubScrollableControl.ScrollStateVScrollVisible)); + + // Set same. + control.HScroll = value; + Assert.Equal(value, control.HScroll); + Assert.Equal(value, control.GetScrollState(SubScrollableControl.ScrollStateVScrollVisible)); } [Theory] @@ -142,81 +205,433 @@ public void ScrollableControl_DisplayRectangle_Get_ReturnsExpected(bool hScroll, { ClientSize = new Size(70, 80), Padding = new Padding(1, 2, 3, 4), - HScrollEntry = hScroll, - VScrollEntry = vScroll + HScroll = hScroll, + VScroll = vScroll }; Assert.Equal(new Rectangle(1, 2, 66, 74), control.DisplayRectangle); } + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetPaddingNormalizedTheoryData))] + public void ScrollableControl_Padding_Set_GetReturnsExpected(Padding value, Padding expected) + { + var control = new ScrollableControl + { + Padding = value + }; + Assert.Equal(expected, control.Padding); + + // Set same. + control.Padding = value; + Assert.Equal(expected, control.Padding); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetRightToLeftTheoryData))] + public void ScrollableControl_RightToLeft_Set_GetReturnsExpected(RightToLeft value, RightToLeft expected) + { + var control = new ScrollableControl + { + RightToLeft = value + }; + Assert.Equal(expected, control.RightToLeft); + + // Set same. + control.RightToLeft = value; + Assert.Equal(expected, control.RightToLeft); + } + [Fact] - public void ScrollableControl_OnScroll_Invoke_Success() + public void ScrollableControl_Visible_Set_GetReturnsExpected() { - var control = new SubScrollableControl(); + var control = new ScrollableControl + { + Visible = false + }; + Assert.False(control.Visible); + + // Set same. + control.Visible = false; + Assert.False(control.Visible); + + // Set different. + control.Visible = true; + Assert.True(control.Visible); + } + + [Fact] + public void ScrollableControl_ScrollStateAutoScrolling_Get_ReturnsExpected() + { + Assert.Equal(0x0001, SubScrollableControl.ScrollStateAutoScrolling); + } + + [Fact] + public void ScrollableControl_ScrollStateHScrollVisible_Get_ReturnsExpected() + { + Assert.Equal(0x0002, SubScrollableControl.ScrollStateHScrollVisible); + } + + [Fact] + public void ScrollableControl_ScrollStateVScrollVisible_Get_ReturnsExpected() + { + Assert.Equal(0x0004, SubScrollableControl.ScrollStateVScrollVisible); + } - // No handler. - control.OnScrollEntry(null); + [Fact] + public void ScrollableControl_ScrollStateUserHasScrolled_Get_ReturnsExpected() + { + Assert.Equal(0x0008, SubScrollableControl.ScrollStateUserHasScrolled); + } - // Handler. + [Fact] + public void ScrollableControl_ScrollStateFullDrag_Get_ReturnsExpected() + { + Assert.Equal(0x0010, SubScrollableControl.ScrollStateFullDrag); + } + + [Fact] + public void ScrollableControl_OnScroll_Invoke_CallsHandler() + { + var control = new SubScrollableControl(); + var eventArgs = new ScrollEventArgs(ScrollEventType.First, 0); int callCount = 0; ScrollEventHandler handler = (sender, e) => { - Assert.Equal(control, sender); + Assert.Same(control, sender); + Assert.Same(eventArgs, e); callCount++; }; + // Call with handler. control.Scroll += handler; - control.OnScrollEntry(null); + control.OnScroll(eventArgs); Assert.Equal(1, callCount); - // Should not call if the handler is removed. + // Remove handler. control.Scroll -= handler; - control.OnScrollEntry(null); + control.OnScroll(eventArgs); Assert.Equal(1, callCount); } [Fact] - public void ScrollableControl_OnPaddingChanged_Invoke_Success() + public void ScrollableControl_OnPaddingChanged_Invoke_CallsHandler() { var control = new SubScrollableControl(); - - // No handler. - control.OnPaddingChangedEntry(null); - - // Handler. + var eventArgs = new EventArgs(); int callCount = 0; EventHandler handler = (sender, e) => { - Assert.Equal(control, sender); + Assert.Same(control, sender); + Assert.Same(eventArgs, e); callCount++; }; + // Call with handler. control.PaddingChanged += handler; - control.OnPaddingChangedEntry(null); + control.OnPaddingChanged(eventArgs); Assert.Equal(1, callCount); - // Should not call if the handler is removed. + // Remove handler. control.PaddingChanged -= handler; - control.OnPaddingChangedEntry(null); + control.OnPaddingChanged(eventArgs); Assert.Equal(1, callCount); } - private class SubScrollableControl : ScrollableControl + public static IEnumerable AdjustFormScrollbars_TestData() { - public bool HScrollEntry + foreach (bool hScroll in new bool[] { true, false }) + { + foreach (bool vScroll in new bool[] { true, false }) + { + var control1 = new SubScrollableControl + { + HScroll = hScroll, + VScroll = vScroll + }; + yield return new object[] { control1, false, false, false }; + + var control2 = new SubScrollableControl + { + HScroll = hScroll, + VScroll = vScroll + }; + yield return new object[] { control2, true, false, false }; + } + } + + var controlWithAutoScrollMinSize = new SubScrollableControl + { + HScroll = true, + VScroll = true, + AutoScrollMinSize = new Size(10, 20) + }; + yield return new object[] { controlWithAutoScrollMinSize, true, true, true }; + } + + [Theory] + [MemberData(nameof(AdjustFormScrollbars_TestData))] + public void ScrollableControl_AdjustFormScrollbars_Invoke_Success(SubScrollableControl control, bool displayScrollbars, bool expectedHScroll, bool expectedVScroll) + { + control.AdjustFormScrollbars(displayScrollbars); + Assert.Equal(expectedHScroll, control.HScroll); + Assert.Equal(expectedVScroll, control.VScroll); + } + +#pragma warning disable 0618 + [Fact] + public void ScrollableControl_ScaleCore_InvokeWithDockPadding_Success() + { + var control = new ScrollableControl(); + control.Padding = new Padding(1, 2, 3, 4); + Assert.Equal(1, control.DockPadding.Left); + Assert.Equal(2, control.DockPadding.Top); + Assert.Equal(3, control.DockPadding.Right); + Assert.Equal(4, control.DockPadding.Bottom); + control.Scale(10, 20); + + Assert.Equal(1, control.DockPadding.Left); + Assert.Equal(2, control.DockPadding.Top); + Assert.Equal(3, control.DockPadding.Right); + Assert.Equal(4, control.DockPadding.Bottom); + Assert.Equal(new Padding(1, 2, 3, 4), control.Padding); + } + + [Fact] + public void ScrollableControl_ScaleCore_InvokeWithoutDockPadding_Success() + { + var control = new ScrollableControl(); + control.Scale(10, 20); + Assert.Equal(0, control.DockPadding.Left); + Assert.Equal(0, control.DockPadding.Top); + Assert.Equal(0, control.DockPadding.Right); + Assert.Equal(0, control.DockPadding.Bottom); + Assert.Equal(Padding.Empty, control.Padding); + } +#pragma warning restore 0618 + + [Fact] + public void ScrollableControl_ScaleControl_InvokeWithDockPadding_Success() + { + var control = new ScrollableControl(); + control.Padding = new Padding(1, 2, 3, 4); + Assert.Equal(1, control.DockPadding.Left); + Assert.Equal(2, control.DockPadding.Top); + Assert.Equal(3, control.DockPadding.Right); + Assert.Equal(4, control.DockPadding.Bottom); + control.Scale(new SizeF(10, 20)); + + Assert.Equal(10, control.DockPadding.Left); + Assert.Equal(40, control.DockPadding.Top); + Assert.Equal(30, control.DockPadding.Right); + Assert.Equal(80, control.DockPadding.Bottom); + Assert.Equal(new Padding(10, 40, 30, 80), control.Padding); + } + + [Fact] + public void ScrollableControl_ScaleControl_InvokeWithoutDockPadding_Success() + { + var control = new ScrollableControl(); + control.Scale(new SizeF(10, 20)); + Assert.Equal(0, control.DockPadding.Left); + Assert.Equal(0, control.DockPadding.Top); + Assert.Equal(0, control.DockPadding.Right); + Assert.Equal(0, control.DockPadding.Bottom); + Assert.Equal(Padding.Empty, control.Padding); + } + + public static IEnumerable SetDisplayRectLocation_TestData() + { + yield return new object[] { true, 0, 0, new Rectangle(0, 0, 100, 150), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { false, 0, 0, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + yield return new object[] { true, -10, 0, new Rectangle(-10, 0, 110, 150), new Rectangle(-10, 0, 100, 150) }; + yield return new object[] { false, -10, 0, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + yield return new object[] { true, 0, -20, new Rectangle(0, -20, 100, 150), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { false, 0, -20, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + yield return new object[] { true, -10, -20, new Rectangle(-10, -20, 110, 170), new Rectangle(-10, -20, 100, 150) }; + yield return new object[] { false, -10, -20, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + // Overflow. + yield return new object[] { true, -100, -20, new Rectangle(-30, -20, 130, 170), new Rectangle(-30, -20, 100, 150) }; + yield return new object[] { false, -100, -20, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + yield return new object[] { true, -10, -200, new Rectangle(-10, -70, 110, 220), new Rectangle(-10, -70, 100, 150) }; + yield return new object[] { false, -10, -200, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + // Underflow. + yield return new object[] { true, 1, 20, new Rectangle(0, 0, 100, 150), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { false, 1, 20, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + + yield return new object[] { true, 10, 2, new Rectangle(0, 0, 100, 150), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { false, 10, 2, new Rectangle(0, 0, 70, 80), new Rectangle(0, 0, 100, 150) }; + } + + [Theory] + [MemberData(nameof(SetDisplayRectLocation_TestData))] + public void SetDisplayRectLocation_InvokeWithoutHandle_Success(bool autoScroll, int x, int y, Rectangle expectedDisplayRectangle, Rectangle expectedBounds) + { + var control = new SubScrollableControl + { + AutoScroll = autoScroll, + ClientSize = new Size(70, 80) + }; + + // Without child. + control.SetDisplayRectLocation(x, y); + Assert.Equal(new Rectangle(0, 0, 70, 80), control.DisplayRectangle); + Assert.Equal(Point.Empty, control.AutoScrollPosition); + + // With child. + var child = new LargeControl(); + control.Controls.Add(child); + Assert.Equal(new Rectangle(0, 0, 100, 150), child.Bounds); + + control.SetDisplayRectLocation(x, y); + Assert.Equal(expectedDisplayRectangle, control.DisplayRectangle); + Assert.Equal(expectedDisplayRectangle.Location, control.AutoScrollPosition); + Assert.Equal(expectedBounds, child.Bounds); + } + + [Theory] + [MemberData(nameof(SetDisplayRectLocation_TestData))] + public void SetDisplayRectLocation_InvokeWithHandle_Success(bool autoScroll, int x, int y, Rectangle expectedDisplayRectangle, Rectangle expectedBounds) + { + var control = new SubScrollableControl + { + AutoScroll = autoScroll, + ClientSize = new Size(70, 80) + }; + + // Without child. + control.SetDisplayRectLocation(x, y); + Assert.Equal(new Rectangle(0, 0, 70, 80), control.DisplayRectangle); + Assert.Equal(Point.Empty, control.AutoScrollPosition); + + // With child. + var child = new LargeControl(); + control.Controls.Add(child); + Assert.Equal(new Rectangle(0, 0, 100, 150), child.Bounds); + + // With created handle. + Assert.NotEqual(IntPtr.Zero, child.Handle); + control.SetDisplayRectLocation(x, y); + Assert.Equal(expectedDisplayRectangle, control.DisplayRectangle); + Assert.Equal(expectedDisplayRectangle.Location, control.AutoScrollPosition); + Assert.Equal(expectedBounds, child.Bounds); + } + + public static IEnumerable ScrollControlIntoView_TestData() + { + // Can't scroll - invalid child. + yield return new object[] { true, true, true, new Size(70, 80), null, new Rectangle(0, 0, 70, 80) }; + yield return new object[] { false, true, true, new Size(70, 80), null, new Rectangle(0, 0, 70, 80) }; + + yield return new object[] { true, true, true, new Size(70, 80), new Control(), new Rectangle(0, 0, 70, 80) }; + + // Can't scroll - not AutoScroll. + yield return new object[] { false, true, true, new Size(70, 80), new LargeControl(), new Rectangle(0, 0, 70, 80) }; + + // Can't scroll - not HScroll or VScroll. + yield return new object[] { true, false, false, new Size(70, 80), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + + // Can't scroll - empty. + yield return new object[] { true, false, false, new Size(0, 80), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, false, false, new Size(-1, 80), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, false, false, new Size(70, 0), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, false, false, new Size(70, -1), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + + // Can scroll. + yield return new object[] { true, true, false, new Size(70, 80), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, false, true, new Size(70, 80), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, true, true, new Size(70, 80), new LargeControl(), new Rectangle(0, 0, 100, 150) }; + + yield return new object[] { true, true, false, new Size(70, 80), new SmallControl(), new Rectangle(0, 0, 70, 80) }; + yield return new object[] { true, false, true, new Size(70, 80), new SmallControl(), new Rectangle(0, 0, 70, 80) }; + yield return new object[] { true, true, true, new Size(70, 80), new SmallControl(), new Rectangle(0, 0, 70, 80) }; + + foreach (bool hScroll in new bool[] { true, false }) + { + var childControl = new SmallControl(); + var parentControl = new LargeControl(); + parentControl.Controls.Add(childControl); + yield return new object[] { true, true, true, new Size(70, 80), parentControl, new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, hScroll, true, new Size(70, 80), childControl, new Rectangle(0, 0, 100, 150) }; + } + + foreach (bool vScroll in new bool[] { true, false }) + { + var childControl = new SmallControl(); + var parentControl = new LargeControl(); + parentControl.Controls.Add(childControl); + yield return new object[] { true, true, true, new Size(70, 80), parentControl, new Rectangle(0, 0, 100, 150) }; + yield return new object[] { true, true, vScroll, new Size(70, 80), childControl, new Rectangle(0, 0, 100, 150) }; + } + } + + [Theory] + [MemberData(nameof(ScrollControlIntoView_TestData))] + public void ScrollControlIntoView_Invoke_Success(bool autoScroll, bool hScroll, bool vScroll, Size clientSize, Control activeControl, Rectangle expectedDisplayRectangle) + { + var control = new SubScrollableControl + { + AutoScroll = autoScroll, + HScroll = hScroll, + VScroll = vScroll, + ClientSize = clientSize + }; + if ((activeControl is LargeControl || activeControl is SmallControl)) + { + control.Controls.Add(activeControl.Parent ?? activeControl); + } + control.ScrollControlIntoView(activeControl); + Assert.Equal(expectedDisplayRectangle, control.DisplayRectangle); + } + + private class LargeControl : Control + { + protected override Size DefaultSize => new Size(100, 150); + } + + private class SmallControl : Control + { + protected override Size DefaultSize => new Size(50, 60); + } + + public class SubScrollableControl : ScrollableControl + { + public new const int ScrollStateAutoScrolling = ScrollableControl.ScrollStateAutoScrolling; + + public new const int ScrollStateHScrollVisible = ScrollableControl.ScrollStateHScrollVisible; + + public new const int ScrollStateVScrollVisible = ScrollableControl.ScrollStateVScrollVisible; + + public new const int ScrollStateUserHasScrolled = ScrollableControl.ScrollStateUserHasScrolled; + + public new const int ScrollStateFullDrag = ScrollableControl.ScrollStateFullDrag; + + public new bool HScroll { get => base.HScroll; set => base.HScroll = value; } - public bool VScrollEntry + public new bool VScroll { get => base.VScroll; set => base.VScroll = value; } - public void OnScrollEntry(ScrollEventArgs se) => OnScroll(se); + public new void AdjustFormScrollbars(bool displayScrollbars) => base.AdjustFormScrollbars(displayScrollbars); + + public new bool GetScrollState(int bit) => base.GetScrollState(bit); + + public new void OnScroll(ScrollEventArgs se) => base.OnScroll(se); + + public new void OnPaddingChanged(EventArgs e) => base.OnPaddingChanged(e); - public void OnPaddingChangedEntry(EventArgs e) => OnPaddingChanged(e); + public new void SetDisplayRectLocation(int x, int y) => base.SetDisplayRectLocation(x, y); } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutControlCollectionTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutControlCollectionTests.cs index 1d545782d7a..8b722e10314 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutControlCollectionTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutControlCollectionTests.cs @@ -40,12 +40,12 @@ public void TableLayoutControlCollection_Add_ValidControl_Success(int column, in } [Fact] - public void TableLayoutControlCollection_Add_NegativeColumn_ThrowsArgumentException() + public void TableLayoutControlCollection_Add_NegativeColumn_ThrowsArgumentOutOfRangeException() { var container = new TableLayoutPanel(); var collection = new TableLayoutControlCollection(container); var control = new Control(); - Assert.Throws(null, () => collection.Add(control, -2, 2)); + Assert.Throws("column", () => collection.Add(control, -2, 2)); Assert.Equal(control, Assert.Single(collection)); Assert.Equal(-1, container.GetColumn(control)); Assert.Equal(-1, container.GetRow(control)); diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelCellPositionTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelCellPositionTests.cs index 486d4b26a09..37611c6f8e5 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelCellPositionTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelCellPositionTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; @@ -141,7 +142,7 @@ public void TableLayoutPanelCellPosition_ConvertFrom_InvalidValue_ThrowsNotSuppo public void TableLayoutPanelCellPosition_ConverterConvertFrom_InvalidString_ThrowsArgumentException(string value) { TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); - Assert.Throws(null, () => converter.ConvertFrom(value)); + Assert.Throws("value", () => converter.ConvertFrom(value)); } [Fact] @@ -177,6 +178,7 @@ public void TableLayoutPanelCellPosition_ConverterConvertTo_InstanceDescriptor_R InstanceDescriptor descriptor = Assert.IsType(converter.ConvertTo(new TableLayoutPanelCellPosition(1, 2), typeof(InstanceDescriptor))); Assert.Equal(typeof(TableLayoutPanelCellPosition).GetConstructor(new Type[] { typeof(int), typeof(int) }), descriptor.MemberInfo); Assert.Equal(new object[] { 1, 2 }, descriptor.Arguments); + Assert.True(descriptor.IsComplete); } [Fact] @@ -208,29 +210,76 @@ public void TableLayoutPanelCellPosition_ConverterCreateInstance_ValidPropertyVa TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); TableLayoutPanelCellPosition position = Assert.IsType(converter.CreateInstance(null, new Dictionary { - {"Column", 1}, - {"Row", 2} + {nameof(TableLayoutPanelCellPosition.Column), 1}, + {nameof(TableLayoutPanelCellPosition.Row), 2} })); - Assert.Equal(1, position.Column); - Assert.Equal(2, position.Row); + Assert.Equal(new TableLayoutPanelCellPosition(1, 2), position); } + [Fact] public void TableLayoutPanelCellPosition_ConverterCreateInstance_NullPropertyValues_ThrowsArgumentNullException() { TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); Assert.Throws("propertyValues", () => converter.CreateInstance(null, null)); } + public static IEnumerable CreateInstance_InvalidPropertyValueType_TestData() + { + yield return new object[] + { + new Dictionary + { + {nameof(TableLayoutPanelCellPosition.Row), new object()}, + {nameof(TableLayoutPanelCellPosition.Column), 2}, + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(TableLayoutPanelCellPosition.Row), null}, + {nameof(TableLayoutPanelCellPosition.Column), 2}, + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(TableLayoutPanelCellPosition.Column), 2} + } + }; - [Fact] - public void TableLayoutPanelCellPosition_ConverterCreateInstance_InvalidColumnType_ThrowsInvalidCastException() + yield return new object[] + { + new Dictionary + { + {nameof(TableLayoutPanelCellPosition.Row), 1}, + {nameof(TableLayoutPanelCellPosition.Column), new object()} + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(TableLayoutPanelCellPosition.Row), 1}, + {nameof(TableLayoutPanelCellPosition.Column), null} + } + }; + yield return new object[] + { + new Dictionary + { + {nameof(TableLayoutPanelCellPosition.Row), 1} + } + }; + } + + [Theory] + [MemberData(nameof(CreateInstance_InvalidPropertyValueType_TestData))] + public void TableLayoutPanelCellPosition_CreateInstance_InvalidPropertyValueType_ThrowsArgumentException(IDictionary propertyValues) { TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); - Assert.Throws(() => converter.CreateInstance(null, new Dictionary - { - {"Column", new object()}, - {"Row", 2} - })); + Assert.Throws("propertyValues", () => converter.CreateInstance(null, propertyValues)); } [Fact] @@ -239,8 +288,8 @@ public void TableLayoutPanelCellPosition_ConverterCreateInstance_InvalidColumn_T TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); Assert.Throws("column", () => converter.CreateInstance(null, new Dictionary { - {"Column", -2}, - {"Row", 2} + {nameof(TableLayoutPanelCellPosition.Column), -2}, + {nameof(TableLayoutPanelCellPosition.Row), 2} })); } @@ -250,19 +299,8 @@ public void TableLayoutPanelCellPosition_ConverterCreateInstance_InvalidRow_Thro TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); Assert.Throws("row", () => converter.CreateInstance(null, new Dictionary { - {"Column", 1}, - {"Row", -2} - })); - } - - [Fact] - public void TableLayoutPanelCellPosition_ConverterCreateInstance_InvalidRowType_ThrowsInvalidCastException() - { - TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); - Assert.Throws(() => converter.CreateInstance(null, new Dictionary - { - {"Column", 1}, - {"Row", new object()} + {nameof(TableLayoutPanelCellPosition.Column), 1}, + {nameof(TableLayoutPanelCellPosition.Row), -2} })); } @@ -279,8 +317,8 @@ public void TableLayoutPanelCellPosition_ConverterGetProperties_Invoke_ReturnsEx TypeConverter converter = TypeDescriptor.GetConverter(typeof(TableLayoutPanelCellPosition)); PropertyDescriptorCollection properties = converter.GetProperties(null); Assert.Equal(2, properties.Count); - Assert.Equal("Column", properties[0].Name); - Assert.Equal("Row", properties[1].Name); + Assert.Equal(nameof(TableLayoutPanelCellPosition.Column), properties[0].Name); + Assert.Equal(nameof(TableLayoutPanelCellPosition.Row), properties[1].Name); } [Fact] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelTests.cs index 68644a0b376..bd571705efe 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TableLayoutPanelTests.cs @@ -62,10 +62,10 @@ public void TableLayoutPanel_CellBorderStyle_Set_GetReturnsExpected(TableLayoutP [Theory] [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(TableLayoutPanelCellBorderStyle))] - public void TableLayoutPanel_CellBorderStyle_SetInvalid_ThrowsArgumentException(TableLayoutPanelCellBorderStyle value) + public void TableLayoutPanel_CellBorderStyle_SetInvalid_ThrowsArgumentOutOfRangeException(TableLayoutPanelCellBorderStyle value) { var panel = new TableLayoutPanel(); - Assert.Throws(null, () => panel.CellBorderStyle = value); + Assert.Throws("value", () => panel.CellBorderStyle = value); } [Fact] @@ -183,7 +183,7 @@ public void TableLayoutPanel_ColumnCount_Set_GetReturnsExpected(int value) public void TableLayoutPanel_ColumnCount_SetNegative_ThrowsArgumentOutOfRangeException() { var panel = new TableLayoutPanel(); - Assert.Throws("ColumnCount", () => panel.ColumnCount = -1); + Assert.Throws("value", () => panel.ColumnCount = -1); } [Theory] @@ -202,7 +202,7 @@ public void TableLayoutPanel_RowCount_Set_GetReturnsExpected(int value) public void TableLayoutPanel_RowCount_SetNegative_ThrowsArgumentOutOfRangeException() { var panel = new TableLayoutPanel(); - Assert.Throws("RowCount", () => panel.RowCount = -1); + Assert.Throws("value", () => panel.RowCount = -1); } [Theory] @@ -221,10 +221,10 @@ public void TableLayoutPanel_GrowStyle_Set_GetReturnsExpected(TableLayoutPanelGr [Theory] [InlineData((TableLayoutPanelGrowStyle)(TableLayoutPanelGrowStyle.FixedSize - 1))] [InlineData((TableLayoutPanelGrowStyle)(TableLayoutPanelGrowStyle.AddColumns + 1))] - public void TableLayoutPanel_GrowStyle_SetNegative_ThrowsArgumentException(TableLayoutPanelGrowStyle value) + public void TableLayoutPanel_GrowStyle_SetNegative_ThrowsArgumentOutOfRangeException(TableLayoutPanelGrowStyle value) { var panel = new TableLayoutPanel(); - Assert.Throws(null, () => panel.GrowStyle = value); + Assert.Throws("value", () => panel.GrowStyle = value); } [Fact] @@ -513,10 +513,10 @@ public void TableLayoutPanel_SetColumn_NullControl_ThrowsArgumentNullException(i } [Fact] - public void TableLayoutPanel_SetColumn_InvalidColumn_ThrowsArgumentException() + public void TableLayoutPanel_SetColumn_InvalidColumn_ThrowsArgumentOutOfRangeException() { var panel = new TableLayoutPanel(); - Assert.Throws(null, () => panel.SetColumn(new Control(), -2)); + Assert.Throws("column", () => panel.SetColumn(new Control(), -2)); } [Theory] @@ -599,19 +599,19 @@ public void TableLayoutPanel_GetControlFromPosition_NoSuchControl_ReturnsExpecte [Theory] [InlineData(-2)] [InlineData(-1)] - public void TableLayoutPanel_GetControlFromPosition_NegativeColumn_ThrowsArgumentException(int column) + public void TableLayoutPanel_GetControlFromPosition_NegativeColumn_ThrowsArgumentOutOfRangeException(int column) { var panel = new TableLayoutPanel(); - Assert.Throws(null, () => panel.GetControlFromPosition(column, 0)); + Assert.Throws("column", () => panel.GetControlFromPosition(column, 0)); } [Theory] [InlineData(-2)] [InlineData(-1)] - public void TableLayoutPanel_GetControlFromPosition_NegativeRow_ThrowsArgumentException(int row) + public void TableLayoutPanel_GetControlFromPosition_NegativeRow_ThrowsArgumentOutOfRangeException(int row) { var panel = new TableLayoutPanel(); - Assert.Throws(null, () => panel.GetControlFromPosition(0, row)); + Assert.Throws("row", () => panel.GetControlFromPosition(0, row)); } [Theory] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TimerTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TimerTests.cs new file mode 100644 index 00000000000..7930f4fa5f5 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TimerTests.cs @@ -0,0 +1,430 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class TimerTests + { + [Fact] + public void Ctor_Default() + { + var timer = new SubTimer(); + Assert.Null(timer.Container); + Assert.False(timer.DesignMode); + Assert.False(timer.Enabled); + Assert.Equal(100, timer.Interval); + Assert.Null(timer.Site); + Assert.Null(timer.Tag); + } + + [Fact] + public void Ctor_IContainer() + { + var container = new Container(); + var timer = new SubTimer(container); + Assert.Same(container, timer.Container); + Assert.False(timer.DesignMode); + Assert.False(timer.Enabled); + Assert.Equal(100, timer.Interval); + Assert.NotNull(timer.Site); + Assert.Null(timer.Tag); + } + + [Fact] + public void Ctor_NullContainer_ThrowsArgumentNullException() + { + Assert.Throws("container", () => new Timer(null)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Enabled_Set_GetReturnsExpected(bool value) + { + var timer = new Timer + { + Enabled = value + }; + Assert.Equal(value, timer.Enabled); + + // Set same. + timer.Enabled = value; + Assert.Equal(value, timer.Enabled); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Enabled_SetDesignMode_GetReturnsExpected(bool value) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(true); + timer.Site = mockSite.Object; + Assert.True(timer.DesignMode); + + timer.Enabled = value; + Assert.Equal(value, timer.Enabled); + + // Set same. + timer.Enabled = value; + Assert.Equal(value, timer.Enabled); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Enabled_SetDesignModeAfterEnabling_GetReturnsExpected(bool value) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(true); + timer.Site = mockSite.Object; + Assert.True(timer.DesignMode); + + timer.Start(); + + mockSite + .Setup(s => s.DesignMode) + .Returns(false); + + timer.Enabled = value; + Assert.Equal(value, timer.Enabled); + + // Set same. + timer.Enabled = value; + Assert.Equal(value, timer.Enabled); + } + + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Interval_Set_GetReturnsExpected(int value) + { + var timer = new Timer + { + Interval = value + }; + Assert.Equal(value, timer.Interval); + + // Set same. + timer.Interval = value; + Assert.Equal(value, timer.Interval); + } + + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Interval_SetStarted_GetReturnsExpected(int value) + { + var timer = new Timer(); + timer.Start(); + + timer.Interval = value; + Assert.Equal(value, timer.Interval); + + // Set same. + timer.Interval = value; + Assert.Equal(value, timer.Interval); + } + + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Interval_SetStopped_GetReturnsExpected(int value) + { + var timer = new Timer(); + timer.Start(); + timer.Stop(); + + timer.Interval = value; + Assert.Equal(value, timer.Interval); + + // Set same. + timer.Interval = value; + Assert.Equal(value, timer.Interval); + } + + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Interval_SetDesignMode_GetReturnsExpected(int value) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(true); + timer.Site = mockSite.Object; + Assert.True(timer.DesignMode); + + timer.Interval = value; + Assert.Equal(value, timer.Interval); + + // Set same. + timer.Interval = value; + Assert.Equal(value, timer.Interval); + } + + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Interval_SetDesignModeAfterEnabling_GetReturnsExpected(int value) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(true); + timer.Site = mockSite.Object; + Assert.True(timer.DesignMode); + + timer.Start(); + + mockSite + .Setup(s => s.DesignMode) + .Returns(false); + + timer.Interval = value; + Assert.Equal(value, timer.Interval); + + // Set same. + timer.Interval = value; + Assert.Equal(value, timer.Interval); + } + + [Theory] + [InlineData(0)] + [InlineData(-1)] + public void Interval_SetInvalid_ThrowsArgumentOutOfRangeException(int value) + { + var timer = new Timer(); + Assert.Throws("value", () => timer.Interval = value); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void Tag_Set_GetReturnsExpected(object value) + { + var timer = new Timer + { + Tag = value + }; + Assert.Same(value, timer.Tag); + + // Set same. + timer.Tag = value; + Assert.Same(value, timer.Tag); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringWithNullTheoryData))] + public void Tag_SetDesignMode_GetReturnsExpected(object value) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(true); + timer.Site = mockSite.Object; + Assert.True(timer.DesignMode); + + timer.Tag = value; + Assert.Same(value, timer.Tag); + + // Set same. + timer.Tag = value; + Assert.Same(value, timer.Tag); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Start_Stop_Success(bool designMode) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(designMode); + timer.Site = mockSite.Object; + Assert.Equal(designMode, timer.DesignMode); + + // Start + timer.Start(); + Assert.True(timer.Enabled); + + // Stop. + timer.Stop(); + Assert.False(timer.Enabled); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Start_MultipleTimes_Success(bool designMode) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(designMode); + timer.Site = mockSite.Object; + Assert.Equal(designMode, timer.DesignMode); + + // Start + timer.Start(); + Assert.True(timer.Enabled); + + // Start again. + timer.Start(); + Assert.True(timer.Enabled); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Stop_Restart_Success(bool designMode) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(designMode); + timer.Site = mockSite.Object; + Assert.Equal(designMode, timer.DesignMode); + + // Start + timer.Start(); + Assert.True(timer.Enabled); + + // Stop. + timer.Stop(); + Assert.False(timer.Enabled); + + // Start again. + timer.Start(); + Assert.True(timer.Enabled); + + // Stop again. + timer.Stop(); + Assert.False(timer.Enabled); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void Stop_MultipleTimes_Success(bool designMode) + { + var timer = new SubTimer(); + var mockSite = new Mock(MockBehavior.Strict); + mockSite + .Setup(s => s.DesignMode) + .Returns(designMode); + timer.Site = mockSite.Object; + Assert.Equal(designMode, timer.DesignMode); + + // Start + timer.Start(); + Assert.True(timer.Enabled); + + // Stop. + timer.Stop(); + Assert.False(timer.Enabled); + + // Stop again. + timer.Stop(); + Assert.False(timer.Enabled); + } + + [Fact] + public void OnTick_Invoke_CallsTick() + { + var timer = new SubTimer(); + var eventArgs = new EventArgs(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(timer, sender); + Assert.Same(eventArgs, e); + callCount++; + }; + + // Call with handler. + timer.Tick += handler; + timer.OnTick(eventArgs); + Assert.Equal(1, callCount); + + // Remove handler. + timer.Tick -= handler; + timer.OnTick(eventArgs); + Assert.Equal(1, callCount); + } + + [Fact] + public void Dispose_NotStarted_Succcess() + { + var timer = new Timer(); + timer.Dispose(); + Assert.False(timer.Enabled); + + // Call again. + timer.Dispose(); + Assert.False(timer.Enabled); + } + + [Fact] + public void Dispose_Started_Succcess() + { + var timer = new Timer(); + timer.Start(); + + timer.Dispose(); + Assert.False(timer.Enabled); + + // Call again. + timer.Dispose(); + Assert.False(timer.Enabled); + } + + [Fact] + public void Dispose_Stopped_Succcess() + { + var timer = new Timer(); + timer.Start(); + timer.Stop(); + + timer.Dispose(); + Assert.False(timer.Enabled); + + // Call again. + timer.Dispose(); + Assert.False(timer.Enabled); + } + + [Fact] + public void ToString_Invoke_ReturnsExpected() + { + var timer = new Timer(); + Assert.Equal("System.Windows.Forms.Timer, Interval: 100", timer.ToString()); + } + + private class SubTimer : Timer + { + public SubTimer() : base() + { + } + + public SubTimer(IContainer container) : base(container) + { + } + + public new bool DesignMode => base.DesignMode; + + public new void OnTick(EventArgs e) => base.OnTick(e); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripItemTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripItemTests.cs index ec46b08b1e4..d4f4ac902bd 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripItemTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripItemTests.cs @@ -2238,6 +2238,10 @@ public void ToolStripItem_TextImageRelation_SetWithOwner_GetReturnsExpected(Text [Theory] [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(TextImageRelation))] + [InlineData((TextImageRelation)3)] + [InlineData((TextImageRelation)5)] + [InlineData((TextImageRelation)6)] + [InlineData((TextImageRelation)7)] public void ToolStripItem_TextImageRelation_SetInvalid_ThrowsInvalidEnumArgumentException(TextImageRelation value) { var item = new SubToolStripItem(); diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripPanelTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripPanelTests.cs new file mode 100644 index 00000000000..3ff0a796ac1 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripPanelTests.cs @@ -0,0 +1,189 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Drawing; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Tests +{ + public class ToolStripPanelTests + { + [Fact] + public void Ctor_Default() + { + var panel = new SubToolStripPanel(); + Assert.False(panel.AllowDrop); + Assert.False(panel.AutoScroll); + Assert.Equal(Size.Empty, panel.AutoScrollMargin); + Assert.Equal(Point.Empty, panel.AutoScrollPosition); + Assert.True(panel.AutoSize); + Assert.Equal(Padding.Empty, panel.DefaultMargin); + Assert.Equal(Padding.Empty, panel.DefaultPadding); + Assert.NotNull(panel.DockPadding); + Assert.Same(panel.DockPadding, panel.DockPadding); + Assert.Equal(0, panel.DockPadding.Top); + Assert.Equal(0, panel.DockPadding.Bottom); + Assert.Equal(0, panel.DockPadding.Left); + Assert.Equal(0, panel.DockPadding.Right); + Assert.Equal(Rectangle.Empty, panel.DisplayRectangle); + Assert.NotNull(panel.HorizontalScroll); + Assert.Same(panel.HorizontalScroll, panel.HorizontalScroll); + Assert.False(panel.HScroll); + Assert.Equal(Padding.Empty, panel.Margin); + Assert.Equal(Padding.Empty, panel.Padding); + Assert.Equal(new Padding(3, 0, 0, 0), panel.RowMargin); + Assert.NotNull(panel.VerticalScroll); + Assert.Same(panel.VerticalScroll, panel.VerticalScroll); + Assert.False(panel.VScroll); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void AllowDrop_Set_GetReturnsExpected(bool value) + { + var panel = new ToolStripPanel + { + AllowDrop = value + }; + Assert.Equal(value, panel.AllowDrop); + + // Set same. + panel.AllowDrop = value; + Assert.Equal(value, panel.AllowDrop); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void AutoScroll_Set_GetReturnsExpected(bool value) + { + var panel = new ToolStripPanel + { + AutoScroll = value + }; + Assert.Equal(value, panel.AutoScroll); + + // Set same. + panel.AutoScroll = value; + Assert.Equal(value, panel.AutoScroll); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoNegatives)] + public void AutoScrollMargin_Set_GetReturnsExpected(Size value) + { + var panel = new ToolStripPanel + { + AutoScrollMargin = value + }; + Assert.Equal(value, panel.AutoScrollMargin); + + // Set same. + panel.AutoScrollMargin = value; + Assert.Equal(value, panel.AutoScrollMargin); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData), TestIncludeType.NoPositives)] + public void AutoScrollMargin_SetInvalid_ThrowsArgumentOutOfRangeException(Size value) + { + var panel = new ToolStripPanel(); + Assert.Throws("value", () => panel.AutoScrollMargin = value); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetSizeTheoryData))] + public void AutoScrollMinSize_Set_GetReturnsExpected(Size value) + { + var panel = new ToolStripPanel + { + AutoScrollMinSize = value + }; + Assert.Equal(value, panel.AutoScrollMinSize); + Assert.Equal(value != Size.Empty, panel.AutoScroll); + + // Set same. + panel.AutoScrollMinSize = value; + Assert.Equal(value, panel.AutoScrollMinSize); + Assert.Equal(value != Size.Empty, panel.AutoScroll); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void AutoSize_Set_GetReturnsExpected(bool value) + { + var panel = new ToolStripPanel + { + AutoSize = value + }; + Assert.Equal(value, panel.AutoSize); + + // Set same. + panel.AutoSize = value; + Assert.Equal(value, panel.AutoSize); + } + + [Fact] + public void AutoSize_SetWithHandler_CallsAutoSizeChanged() + { + var panel = new ToolStripPanel(); + int callCount = 0; + EventHandler handler = (sender, e) => + { + Assert.Same(panel, sender); + Assert.Same(EventArgs.Empty, e); + callCount++; + }; + panel.AutoSizeChanged += handler; + + // Set different. + panel.AutoSize = false; + Assert.False(panel.AutoSize); + Assert.Equal(1, callCount); + + // Set same. + panel.AutoSize = false; + Assert.False(panel.AutoSize); + Assert.Equal(1, callCount); + + // Set different. + panel.AutoSize = true; + Assert.True(panel.AutoSize); + Assert.Equal(2, callCount); + + // Remove handler. + panel.AutoSizeChanged -= handler; + panel.AutoSize = false; + Assert.False(panel.AutoSize); + Assert.Equal(2, callCount); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetPaddingTheoryData))] + public void RowMargin_Set_GetReturnsExpected(Padding value) + { + var panel = new ToolStripPanel + { + RowMargin = value + }; + Assert.Equal(value, panel.RowMargin); + + // Set same. + panel.RowMargin = value; + Assert.Equal(value, panel.RowMargin); + } + + private class SubToolStripPanel : ToolStripPanel + { + public new Padding DefaultPadding => base.DefaultPadding; + + public new Padding DefaultMargin => base.DefaultMargin; + + public new bool HScroll => base.HScroll; + + public new bool VScroll => base.VScroll; + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/ToolStripTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripTests.cs similarity index 57% rename from src/System.Windows.Forms/tests/UnitTests/ToolStripTests.cs rename to src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripTests.cs index 4953cba1867..e4eb91b7da2 100644 --- a/src/System.Windows.Forms/tests/UnitTests/ToolStripTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel; +using WinForms.Common.Tests; using Xunit; namespace System.Windows.Forms.Tests @@ -42,5 +44,27 @@ public void ToolStrip_ConstructorItems() Assert.Single(ts.Items); Assert.Equal(button, ts.Items[0]); } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(ArrowDirection))] + public void ToolStrip_GetNextItem_NoItems_ReturnsNull(ArrowDirection direction) + { + var toolStrip = new ToolStrip(); + Assert.Null(toolStrip.GetNextItem(new SubToolStripItem(), direction)); + Assert.Null(toolStrip.GetNextItem(null, direction)); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(ArrowDirection))] + public void ToolStrip_GetNextItem_InvalidDirection_ThrowsInvalidEnumArgumentException(ArrowDirection direction) + { + var toolStrip = new ToolStrip(); + Assert.Throws("direction", () => toolStrip.GetNextItem(new SubToolStripItem(), direction)); + Assert.Throws("direction", () => toolStrip.GetNextItem(null, direction)); + } + + private class SubToolStripItem : ToolStripItem + { + } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/VisualStyles/TextMetricsTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/VisualStyles/TextMetricsTests.cs new file mode 100644 index 00000000000..2e5da67465f --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/VisualStyles/TextMetricsTests.cs @@ -0,0 +1,339 @@ + // Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.VisualStyles.Tests +{ + public class TextMetricsTests + { + [Fact] + public void TextMetrics_Ctor_Default() + { + var metric = new TextMetrics(); + Assert.Equal(0, metric.Ascent); + Assert.Equal(0, metric.AverageCharWidth); + Assert.Equal('\0', metric.BreakChar); + Assert.Equal(TextMetricsCharacterSet.Ansi, metric.CharSet); + Assert.Equal('\0', metric.DefaultChar); + Assert.Equal(0, metric.Descent); + Assert.Equal(0, metric.DigitizedAspectX); + Assert.Equal(0, metric.DigitizedAspectY); + Assert.Equal(0, metric.ExternalLeading); + Assert.Equal('\0', metric.FirstChar); + Assert.Equal(0, metric.Height); + Assert.Equal(0, metric.InternalLeading); + Assert.False(metric.Italic); + Assert.Equal(0, metric.MaxCharWidth); + Assert.Equal(0, metric.Overhang); + Assert.Equal((TextMetricsPitchAndFamilyValues)0, metric.PitchAndFamily); + Assert.False(metric.StruckOut); + Assert.False(metric.Underlined); + Assert.Equal(0, metric.Weight); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_Ascent_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + Ascent = value + }; + Assert.Equal(value, metric.Ascent); + + // Set same. + metric.Ascent = value; + Assert.Equal(value, metric.Ascent); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_AverageCharWidth_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + AverageCharWidth = value + }; + Assert.Equal(value, metric.AverageCharWidth); + + // Set same. + metric.AverageCharWidth = value; + Assert.Equal(value, metric.AverageCharWidth); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetCharTheoryData))] + public void TextMetrics_BreakChar_Set_GetReturnsExpected(char value) + { + var metric = new TextMetrics + { + BreakChar = value + }; + Assert.Equal(value, metric.BreakChar); + + // Set same. + metric.BreakChar = value; + Assert.Equal(value, metric.BreakChar); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(TextMetricsCharacterSet))] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(TextMetricsCharacterSet))] + public void TextMetrics_CharSet_Set_GetReturnsExpected(TextMetricsCharacterSet value) + { + var metric = new TextMetrics + { + CharSet = value + }; + Assert.Equal(value, metric.CharSet); + + // Set same. + metric.CharSet = value; + Assert.Equal(value, metric.CharSet); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetCharTheoryData))] + public void TextMetrics_DefaultChar_Set_GetReturnsExpected(char value) + { + var metric = new TextMetrics + { + DefaultChar = value + }; + Assert.Equal(value, metric.DefaultChar); + + // Set same. + metric.DefaultChar = value; + Assert.Equal(value, metric.DefaultChar); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_Descent_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + Descent = value + }; + Assert.Equal(value, metric.Descent); + + // Set same. + metric.Descent = value; + Assert.Equal(value, metric.Descent); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_DigitizedAspectX_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + DigitizedAspectX = value + }; + Assert.Equal(value, metric.DigitizedAspectX); + + // Set same. + metric.DigitizedAspectX = value; + Assert.Equal(value, metric.DigitizedAspectX); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_DigitizedAspectY_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + DigitizedAspectY = value + }; + Assert.Equal(value, metric.DigitizedAspectY); + + // Set same. + metric.DigitizedAspectY = value; + Assert.Equal(value, metric.DigitizedAspectY); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_ExternalLeading_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + ExternalLeading = value + }; + Assert.Equal(value, metric.ExternalLeading); + + // Set same. + metric.ExternalLeading = value; + Assert.Equal(value, metric.ExternalLeading); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetCharTheoryData))] + public void TextMetrics_FirstChar_Set_GetReturnsExpected(char value) + { + var metric = new TextMetrics + { + FirstChar = value + }; + Assert.Equal(value, metric.FirstChar); + + // Set same. + metric.FirstChar = value; + Assert.Equal(value, metric.FirstChar); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_Height_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + Height = value + }; + Assert.Equal(value, metric.Height); + + // Set same. + metric.Height = value; + Assert.Equal(value, metric.Height); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_InternalLeading_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + InternalLeading = value + }; + Assert.Equal(value, metric.InternalLeading); + + // Set same. + metric.InternalLeading = value; + Assert.Equal(value, metric.InternalLeading); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void TextMetrics_Italic_Set_GetReturnsExpected(bool value) + { + var metric = new TextMetrics + { + Italic = value + }; + Assert.Equal(value, metric.Italic); + + // Set same. + metric.Italic = value; + Assert.Equal(value, metric.Italic); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetCharTheoryData))] + public void TextMetrics_LastChar_Set_GetReturnsExpected(char value) + { + var metric = new TextMetrics + { + LastChar = value + }; + Assert.Equal(value, metric.LastChar); + + // Set same. + metric.LastChar = value; + Assert.Equal(value, metric.LastChar); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_MaxCharWidth_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + MaxCharWidth = value + }; + Assert.Equal(value, metric.MaxCharWidth); + + // Set same. + metric.MaxCharWidth = value; + Assert.Equal(value, metric.MaxCharWidth); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_Overhang_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + Overhang = value + }; + Assert.Equal(value, metric.Overhang); + + // Set same. + metric.Overhang = value; + Assert.Equal(value, metric.Overhang); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(TextMetricsPitchAndFamilyValues))] + [CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(TextMetricsPitchAndFamilyValues))] + public void TextMetrics_PitchAndFamily_GetReturnsExpected(TextMetricsPitchAndFamilyValues value) + { + var metric = new TextMetrics + { + PitchAndFamily = value + }; + Assert.Equal(value, metric.PitchAndFamily); + + // Set same. + metric.PitchAndFamily = value; + Assert.Equal(value, metric.PitchAndFamily); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void TextMetrics_StruckOut_Set_GetReturnsExpected(bool value) + { + var metric = new TextMetrics + { + StruckOut = value + }; + Assert.Equal(value, metric.StruckOut); + + // Set same. + metric.StruckOut = value; + Assert.Equal(value, metric.StruckOut); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void TextMetrics_Underlined_Set_GetReturnsExpected(bool value) + { + var metric = new TextMetrics + { + Underlined = value + }; + Assert.Equal(value, metric.Underlined); + + // Set same. + metric.Underlined = value; + Assert.Equal(value, metric.Underlined); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetIntTheoryData))] + public void TextMetrics_Weight_Set_GetReturnsExpected(int value) + { + var metric = new TextMetrics + { + Weight = value + }; + Assert.Equal(value, metric.Weight); + + // Set same. + metric.Weight = value; + Assert.Equal(value, metric.Weight); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/TestHelper.cs b/src/System.Windows.Forms/tests/UnitTests/TestHelper.cs deleted file mode 100644 index 52ba217a3ae..00000000000 --- a/src/System.Windows.Forms/tests/UnitTests/TestHelper.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Xunit; -using System.Drawing; - -namespace System.Windows.Forms.Tests -{ - public static class TestHelper - { - - #region System.Windows.Forms - - // helper method to generate theory data for Padding - public static TheoryData GetPaddingTheoryData() - { - var data = new TheoryData(); - data.Add(new Padding()); - data.Add(new Padding(0)); - data.Add(new Padding(1)); - data.Add(new Padding(int.MaxValue)); - return data; - } - - // helper method to generate invalid theory data for Padding - public static TheoryData GetPaddingTheoryDataInvalid() - { - var data = new TheoryData(); - data.Add(new Padding(-1)); - data.Add(new Padding(int.MinValue)); - return data; - } - - public static TheoryData GetCursorTheoryData() - { - - var data = new TheoryData(); - foreach (System.Reflection.MethodInfo info in typeof(Cursors).GetMethods()) - { - if(info.ReturnType == typeof(Cursor)) - { - data.Add(info.Invoke(null, null) as Cursor); - } - } - return data; - } - - #endregion - - #region - - // helper method to generate theory data Point values - public static TheoryData GetPointTheoryData() => GetPointTheoryData(TestIncludeType.All); - - public static TheoryData GetPointTheoryData(TestIncludeType includeType) - { - var data = new TheoryData(); - data.Add(new Point()); - data.Add(new Point(10)); - data.Add(new Point(1, 2)); - if (!includeType.HasFlag(TestIncludeType.NoNegatives)) - { - data.Add(new Point(int.MaxValue, int.MinValue)); - data.Add(new Point(-1, -2)); - } - return data; - } - - // helper method to generate theory data Point values - public static TheoryData GetSizeTheoryData() => GetSizeTheoryData(TestIncludeType.All); - - public static TheoryData GetSizeTheoryData(TestIncludeType includeType) - { - var data = new TheoryData(); - data.Add(new Size()); - data.Add(new Size(new Point(1,1))); - data.Add(new Size(1, 2)); - if (!includeType.HasFlag(TestIncludeType.NoNegatives)) - { - data.Add(new Size(-1, -2)); - data.Add(new Size(int.MaxValue, int.MinValue)); - } - return data; - } - - public static TheoryData GetFontTheoryData() - { - var data = new TheoryData(); - foreach (Drawing.Text.GenericFontFamilies genericFontFamily in Enum.GetValues(typeof(Drawing.Text.GenericFontFamilies))) - { - var family = new FontFamily(genericFontFamily); - data.Add(new Font(family, float.Epsilon)); - data.Add(new Font(family, 10)); - data.Add(new Font(family, 84)); - data.Add(new Font(family, float.MaxValue)); - } - return data; - } - - #endregion - } - - [Flags] - public enum TestIncludeType - { - All, - NoNegatives - } -} diff --git a/src/System.Windows.Forms/tests/UnitTests/TextBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/TextBoxTests.cs index e132fc67ae8..99b1ef6a509 100644 --- a/src/System.Windows.Forms/tests/UnitTests/TextBoxTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/TextBoxTests.cs @@ -33,11 +33,11 @@ public void TextBox_PlaceholderTextAlignments() System.Runtime.InteropServices.HandleRef refHandle = new System.Runtime.InteropServices.HandleRef(tb, tb.Handle); //Cover the Placeholder draw code path - UnsafeNativeMethods.SendMessage(refHandle, NativeMethods.WM_PAINT, false, 0); + UnsafeNativeMethods.SendMessage(refHandle, Interop.WindowMessages.WM_PAINT, false, 0); tb.TextAlign = HorizontalAlignment.Center; - UnsafeNativeMethods.SendMessage(refHandle, NativeMethods.WM_PAINT, false, 0); + UnsafeNativeMethods.SendMessage(refHandle, Interop.WindowMessages.WM_PAINT, false, 0); tb.TextAlign = HorizontalAlignment.Right; - UnsafeNativeMethods.SendMessage(refHandle, NativeMethods.WM_PAINT, false, 0); + UnsafeNativeMethods.SendMessage(refHandle, Interop.WindowMessages.WM_PAINT, false, 0); Assert.False(string.IsNullOrEmpty(tb.PlaceholderText)); } @@ -52,11 +52,11 @@ public void TextBox_PlaceholderTextAlignmentsInRightToLeft() System.Runtime.InteropServices.HandleRef refHandle = new System.Runtime.InteropServices.HandleRef(tb, tb.Handle); //Cover the Placeholder draw code path in RightToLeft scenario - UnsafeNativeMethods.SendMessage(refHandle, NativeMethods.WM_PAINT, false, 0); + UnsafeNativeMethods.SendMessage(refHandle, Interop.WindowMessages.WM_PAINT, false, 0); tb.TextAlign = HorizontalAlignment.Center; - UnsafeNativeMethods.SendMessage(refHandle, NativeMethods.WM_PAINT, false, 0); + UnsafeNativeMethods.SendMessage(refHandle, Interop.WindowMessages.WM_PAINT, false, 0); tb.TextAlign = HorizontalAlignment.Right; - UnsafeNativeMethods.SendMessage(refHandle, NativeMethods.WM_PAINT, false, 0); + UnsafeNativeMethods.SendMessage(refHandle, Interop.WindowMessages.WM_PAINT, false, 0); Assert.False(string.IsNullOrEmpty(tb.PlaceholderText)); }