diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 65eaa7271..873f6bda9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -72,6 +72,213 @@ jobs:
- name: Restore
run: dotnet restore "Source/Krypton Components/Krypton Toolkit Suite 2022 - VS2022.sln"
+ - name: Setup WebView2 SDK
+ run: |
+ # Create WebView2SDK directory
+ mkdir WebView2SDK
+
+ # Get latest WebView2 SDK version using multiple API methods
+ $packageId = "Microsoft.Web.WebView2"
+ Write-Host "Fetching latest stable WebView2 version using multiple API methods..." -ForegroundColor Cyan
+
+ $latestVersion = $null
+
+ # Method 1: Try the search API first (most reliable for latest versions)
+ try {
+ Write-Host "Trying search API (most reliable)..." -ForegroundColor Cyan
+ $searchUrl = "https://azuresearch-usnc.nuget.org/query?q=$packageId&prerelease=false&semVerLevel=2.0.0&take=1"
+ $searchResponse = Invoke-RestMethod -Uri $searchUrl -Method Get
+
+ if ($searchResponse.data -and $searchResponse.data.Count -gt 0) {
+ $packageData = $searchResponse.data[0]
+ $latestVersion = $packageData.version
+ Write-Host "Found latest stable version via search API: $latestVersion" -ForegroundColor Green
+ }
+ } catch {
+ Write-Host "Search API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+
+ # Method 2: Try alternative search endpoint if primary failed
+ if (-not $latestVersion) {
+ try {
+ Write-Host "Trying alternative search endpoint..." -ForegroundColor Cyan
+ $altSearchUrl = "https://azuresearch-ussc.nuget.org/query?q=$packageId&prerelease=false&semVerLevel=2.0.0&take=1"
+ $altSearchResponse = Invoke-RestMethod -Uri $altSearchUrl -Method Get
+
+ if ($altSearchResponse.data -and $altSearchResponse.data.Count -gt 0) {
+ $packageData = $altSearchResponse.data[0]
+ $latestVersion = $packageData.version
+ Write-Host "Found latest stable version via alternative search API: $latestVersion" -ForegroundColor Green
+ }
+ } catch {
+ Write-Host "Alternative search API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+ }
+
+ # Method 3: Try the flatcontainer API (may have stale data)
+ if (-not $latestVersion) {
+ try {
+ $apiUrl = "https://api.nuget.org/v3-flatcontainer/$packageId/index.json"
+ Write-Host "Trying flatcontainer API (may have stale data)..." -ForegroundColor Cyan
+ $response = Invoke-RestMethod -Uri $apiUrl -Method Get
+
+ if ($response.versions) {
+ # Filter for stable versions only (no prerelease identifiers)
+ $stableVersions = $response.versions | Where-Object { $_ -notmatch '[-]' -and $_ -match '^\d+\.\d+\.\d+$' }
+ if ($stableVersions) {
+ # Sort by version number and get the latest
+ $latestVersion = $stableVersions | Sort-Object { [System.Version]$_ } -Descending | Select-Object -First 1
+ Write-Host "Found latest stable version via flatcontainer API: $latestVersion" -ForegroundColor Green
+ }
+ }
+ } catch {
+ Write-Host "Flatcontainer API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+ }
+
+ # Method 4: Try registration API (with better error handling)
+ if (-not $latestVersion) {
+ try {
+ Write-Host "Trying registration API..." -ForegroundColor Cyan
+ $regUrl = "https://api.nuget.org/v3/registration5-semver1/$($packageId.ToLower())/index.json"
+ $regResponse = Invoke-RestMethod -Uri $regUrl -Method Get
+
+ if ($regResponse.items -and $regResponse.items.Count -gt 0) {
+ # Filter out prerelease versions and sort by version
+ $stableItems = $regResponse.items | Where-Object {
+ $_.upper -notmatch '[-]' -and $_.upper -match '^\d+\.\d+\.\d+$'
+ }
+ if ($stableItems) {
+ $latestItem = $stableItems | Sort-Object { [System.Version]$_.upper } -Descending | Select-Object -First 1
+ if ($latestItem.items -and $latestItem.items.Count -gt 0) {
+ $latestVersion = $latestItem.items[0].catalogEntry.version
+ Write-Host "Found latest stable version via registration API: $latestVersion" -ForegroundColor Green
+ }
+ }
+ }
+ } catch {
+ Write-Host "Registration API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+ }
+
+ # Final fallback
+ if (-not $latestVersion) {
+ Write-Host "All API methods failed, using hardcoded fallback version: 1.0.3485.44" -ForegroundColor Red
+ $latestVersion = "1.0.3485.44"
+ }
+
+ Write-Host "Using WebView2 SDK version: $latestVersion" -ForegroundColor Green
+
+ # Add WebView2 package to project
+ Write-Host "Adding WebView2 package to project..."
+ Write-Host "Attempting to install version: $latestVersion"
+
+ # Verify the package version exists by trying to get package info
+ try {
+ $packageInfoUrl = "https://api.nuget.org/v3-flatcontainer/$packageId/$latestVersion/$packageId.$latestVersion.nupkg"
+ $packageCheck = Invoke-WebRequest -Uri $packageInfoUrl -Method Head -UseBasicParsing
+ Write-Host "Package version $latestVersion verified as available" -ForegroundColor Green
+ } catch {
+ Write-Host "Package version $latestVersion not found, trying latest available..." -ForegroundColor Yellow
+ # Try to get the latest available version
+ try {
+ $searchUrl = "https://azuresearch-usnc.nuget.org/query?q=$packageId&prerelease=false&semVerLevel=2.0.0&take=1"
+ $searchResponse = Invoke-RestMethod -Uri $searchUrl -Method Get
+ if ($searchResponse.data -and $searchResponse.data.Count -gt 0) {
+ $latestVersion = $searchResponse.data[0].version
+ Write-Host "Using verified latest version: $latestVersion" -ForegroundColor Green
+ }
+ } catch {
+ Write-Host "Could not verify package version, proceeding with $latestVersion" -ForegroundColor Yellow
+ }
+ }
+
+ dotnet add "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj" package Microsoft.Web.WebView2 --version $latestVersion
+
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "Failed to add WebView2 package to project"
+ exit 1
+ }
+
+ # Restore packages to ensure they're downloaded
+ Write-Host "Restoring NuGet packages..."
+ dotnet restore "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj"
+
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "Failed to restore NuGet packages"
+ exit 1
+ }
+
+ # Find and copy assemblies dynamically
+ $nugetBasePath = "$env:USERPROFILE\.nuget\packages\microsoft.web.webview2\$latestVersion"
+ Write-Host "Searching for WebView2 assemblies in: $nugetBasePath"
+
+ # Verify the package directory exists
+ if (-not (Test-Path $nugetBasePath)) {
+ Write-Error "NuGet package directory not found: $nugetBasePath"
+ Write-Host "Available packages:"
+ Get-ChildItem "$env:USERPROFILE\.nuget\packages\microsoft.web.webview2" -ErrorAction SilentlyContinue | ForEach-Object { Write-Host " - $($_.Name)" }
+ exit 1
+ }
+
+ # Find Core DLL
+ $coreDll = Get-ChildItem -Path $nugetBasePath -Recurse -Name "Microsoft.Web.WebView2.Core.dll" | Select-Object -First 1
+ if ($coreDll) {
+ $corePath = Join-Path $nugetBasePath $coreDll
+ if (Test-Path $corePath) {
+ Copy-Item $corePath "WebView2SDK\"
+ Write-Host "Copied Microsoft.Web.WebView2.Core.dll from: $corePath"
+ } else {
+ Write-Error "Core DLL file not found at: $corePath"
+ exit 1
+ }
+ } else {
+ Write-Error "Microsoft.Web.WebView2.Core.dll not found in package"
+ Write-Host "Available files in package:"
+ Get-ChildItem -Path $nugetBasePath -Recurse | ForEach-Object { Write-Host " - $($_.FullName)" }
+ exit 1
+ }
+
+ # Find WinForms DLL
+ $winFormsDll = Get-ChildItem -Path $nugetBasePath -Recurse -Name "Microsoft.Web.WebView2.WinForms.dll" | Select-Object -First 1
+ if ($winFormsDll) {
+ $winFormsPath = Join-Path $nugetBasePath $winFormsDll
+ if (Test-Path $winFormsPath) {
+ Copy-Item $winFormsPath "WebView2SDK\"
+ Write-Host "Copied Microsoft.Web.WebView2.WinForms.dll from: $winFormsPath"
+ } else {
+ Write-Error "WinForms DLL file not found at: $winFormsPath"
+ exit 1
+ }
+ } else {
+ Write-Error "Microsoft.Web.WebView2.WinForms.dll not found in package"
+ exit 1
+ }
+
+ # Find WebView2Loader DLL
+ $loaderDll = Get-ChildItem -Path $nugetBasePath -Recurse -Name "WebView2Loader.dll" | Select-Object -First 1
+ if ($loaderDll) {
+ $loaderPath = Join-Path $nugetBasePath $loaderDll
+ if (Test-Path $loaderPath) {
+ Copy-Item $loaderPath "WebView2SDK\"
+ Write-Host "Copied WebView2Loader.dll from: $loaderPath"
+ } else {
+ Write-Error "Loader DLL file not found at: $loaderPath"
+ exit 1
+ }
+ } else {
+ Write-Error "WebView2Loader.dll not found in package"
+ exit 1
+ }
+
+ # Verify all files were copied
+ Write-Host "WebView2 SDK setup completed. Files copied:"
+ Get-ChildItem "WebView2SDK\*.dll" | ForEach-Object { Write-Host " - $($_.Name)" }
+
+ # Remove NuGet package reference
+ Write-Host "Removing temporary NuGet package reference..."
+ dotnet remove "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj" package Microsoft.Web.WebView2
+
- name: Build
run: msbuild "Scripts/nightly.proj" /t:Rebuild /p:Configuration=Release /p:Platform="Any CPU"
diff --git a/Documents/Changelog/Changelog.md b/Documents/Changelog/Changelog.md
index f6b5bf3cb..937ad0c9a 100644
--- a/Documents/Changelog/Changelog.md
+++ b/Documents/Changelog/Changelog.md
@@ -3,6 +3,7 @@
====
## 2025-11-xx - Build 2511 (V10 - alpha) - November 2025
+* Implemented [#1026](https://github.com/Krypton-Suite/Standard-Toolkit/issues/1026), Krypton version of `WebView2`
* Resolved [#2461](https://github.com/Krypton-Suite/Standard-Toolkit/issues/2461), (feat) Add `KryptonCalcInput` edit+dropdown control.
* Resolved [#2480](https://github.com/Krypton-Suite/Standard-Toolkit/issues/2480). `KryptonForm`'s 'InternalPanel' designer issues
* Resolved [#2512](https://github.com/Krypton-Suite/Standard-Toolkit/issues/2512), Added borders with straight corners (`LinearBorder2`) and adjusted the colors in the `KryptonRibbon` in the `Microsoft365` themes. Adjusted the design of the `RibbonQATButton`
diff --git a/Scripts/Check-WebView2Version.cmd b/Scripts/Check-WebView2Version.cmd
new file mode 100644
index 000000000..6277b67da
--- /dev/null
+++ b/Scripts/Check-WebView2Version.cmd
@@ -0,0 +1,19 @@
+@echo off
+echo Checking WebView2 SDK version...
+echo.
+
+if exist "WebView2SDK\Microsoft.Web.WebView2.Core.dll" (
+ echo Current installed version:
+ powershell -Command "Get-ItemProperty 'WebView2SDK\Microsoft.Web.WebView2.Core.dll' | Select-Object -ExpandProperty VersionInfo | Select-Object -ExpandProperty FileVersion"
+ echo.
+ echo Latest available version:
+ powershell -ExecutionPolicy Bypass -File "%~dp0Get-LatestWebView2Version.ps1"
+) else (
+ echo WebView2 SDK is not installed.
+ echo.
+ echo Latest available version:
+ powershell -ExecutionPolicy Bypass -File "%~dp0Get-LatestWebView2Version.ps1"
+)
+
+echo.
+pause
diff --git a/Scripts/Get-LatestWebView2Version.ps1 b/Scripts/Get-LatestWebView2Version.ps1
new file mode 100644
index 000000000..c179a55bf
--- /dev/null
+++ b/Scripts/Get-LatestWebView2Version.ps1
@@ -0,0 +1,106 @@
+# Get-LatestWebView2Version.ps1
+# Script to get the latest stable version of Microsoft.Web.WebView2 from NuGet
+
+param(
+ [switch]$Prerelease = $false
+)
+
+try {
+ # Use NuGet API to get package information
+ $packageId = "Microsoft.Web.WebView2"
+
+ Write-Host "Fetching latest stable version information for $packageId..." -ForegroundColor Green
+
+ # Try multiple approaches to get the latest stable version
+ $latestVersion = $null
+
+ # Method 1: Try the search API first (most reliable for latest versions)
+ try {
+ Write-Host "Trying search API (most reliable)..." -ForegroundColor Cyan
+ $searchUrl = "https://azuresearch-usnc.nuget.org/query?q=$packageId&prerelease=false&semVerLevel=2.0.0&take=1"
+ $searchResponse = Invoke-RestMethod -Uri $searchUrl -Method Get
+
+ if ($searchResponse.data -and $searchResponse.data.Count -gt 0) {
+ $packageData = $searchResponse.data[0]
+ $latestVersion = $packageData.version
+ Write-Host "Found latest stable version via search API: $latestVersion" -ForegroundColor Green
+ }
+ } catch {
+ Write-Host "Search API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+
+ # Method 2: Try alternative search endpoint if primary failed
+ if (-not $latestVersion) {
+ try {
+ Write-Host "Trying alternative search endpoint..." -ForegroundColor Cyan
+ $altSearchUrl = "https://azuresearch-ussc.nuget.org/query?q=$packageId&prerelease=false&semVerLevel=2.0.0&take=1"
+ $altSearchResponse = Invoke-RestMethod -Uri $altSearchUrl -Method Get
+
+ if ($altSearchResponse.data -and $altSearchResponse.data.Count -gt 0) {
+ $packageData = $altSearchResponse.data[0]
+ $latestVersion = $packageData.version
+ Write-Host "Found latest stable version via alternative search API: $latestVersion" -ForegroundColor Green
+ }
+ } catch {
+ Write-Host "Alternative search API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+ }
+
+ # Method 3: Try the flatcontainer API (may have stale data)
+ if (-not $latestVersion) {
+ try {
+ $apiUrl = "https://api.nuget.org/v3-flatcontainer/$packageId/index.json"
+ Write-Host "Trying flatcontainer API (may have stale data)..." -ForegroundColor Cyan
+ $response = Invoke-RestMethod -Uri $apiUrl -Method Get
+
+ if ($response.versions) {
+ # Filter for stable versions only (no prerelease identifiers)
+ $stableVersions = $response.versions | Where-Object { $_ -notmatch '[-]' -and $_ -match '^\d+\.\d+\.\d+$' }
+ if ($stableVersions) {
+ # Sort by version number and get the latest
+ $latestVersion = $stableVersions | Sort-Object { [Version]$_ } -Descending | Select-Object -First 1
+ Write-Host "Found latest stable version via flatcontainer API: $latestVersion" -ForegroundColor Green
+ }
+ }
+ } catch {
+ Write-Host "Flatcontainer API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+ }
+
+ # Method 4: Try registration API (with better error handling)
+ if (-not $latestVersion) {
+ try {
+ Write-Host "Trying registration API..." -ForegroundColor Cyan
+ $regUrl = "https://api.nuget.org/v3/registration5-semver1/$($packageId.ToLower())/index.json"
+ $regResponse = Invoke-RestMethod -Uri $regUrl -Method Get
+
+ if ($regResponse.items -and $regResponse.items.Count -gt 0) {
+ # Filter out prerelease versions and sort by version
+ $stableItems = $regResponse.items | Where-Object {
+ $_.upper -notmatch '[-]' -and $_.upper -match '^\d+\.\d+\.\d+$'
+ }
+ if ($stableItems) {
+ $latestItem = $stableItems | Sort-Object { [Version]$_.upper } -Descending | Select-Object -First 1
+ if ($latestItem.items -and $latestItem.items.Count -gt 0) {
+ $latestVersion = $latestItem.items[0].catalogEntry.version
+ Write-Host "Found latest stable version via registration API: $latestVersion" -ForegroundColor Green
+ }
+ }
+ }
+ } catch {
+ Write-Host "Registration API failed: $($_.Exception.Message)" -ForegroundColor Yellow
+ }
+ }
+
+ if ($latestVersion) {
+ Write-Host "Latest version: $latestVersion" -ForegroundColor Yellow
+ return $latestVersion
+ } else {
+ Write-Error "No suitable version found"
+ return $null
+ }
+}
+catch {
+ Write-Error "Failed to fetch version information: $($_.Exception.Message)"
+ return $null
+}
diff --git a/Scripts/Setup-WebView2SDK.cmd b/Scripts/Setup-WebView2SDK.cmd
new file mode 100644
index 000000000..3f5b6871b
--- /dev/null
+++ b/Scripts/Setup-WebView2SDK.cmd
@@ -0,0 +1,101 @@
+@echo off
+echo Setting up WebView2 SDK for KryptonWebView2 control...
+echo.
+
+REM Check if WebView2SDK directory exists and has the required files
+if exist "WebView2SDK\Microsoft.Web.WebView2.Core.dll" (
+ if exist "WebView2SDK\Microsoft.Web.WebView2.WinForms.dll" (
+ if exist "WebView2SDK\WebView2Loader.dll" (
+ echo WebView2 SDK assemblies are already present!
+ echo.
+ echo Files found:
+ dir WebView2SDK\*.dll
+ echo.
+ echo The KryptonWebView2 control should compile successfully.
+ echo You can now build the solution and use the control.
+ echo.
+ pause
+ exit /b 0
+ )
+ )
+)
+
+REM Create WebView2SDK directory if it doesn't exist
+if not exist "WebView2SDK" (
+ echo Creating WebView2SDK directory...
+ mkdir WebView2SDK
+)
+
+echo.
+echo WebView2 SDK assemblies are missing. Setting up automatically...
+echo.
+
+REM Get the latest WebView2 SDK version
+echo Detecting latest WebView2 SDK version...
+for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -File "%~dp0Get-LatestWebView2Version.ps1"') do (
+ set "WEBVIEW2_VERSION=%%i"
+)
+
+if "%WEBVIEW2_VERSION%"=="" (
+ echo Failed to detect latest version, using fallback version 1.0.2478.35
+ set WEBVIEW2_VERSION=1.0.2478.35
+) else (
+ echo Using WebView2 SDK version: %WEBVIEW2_VERSION%
+)
+
+REM Try to download and setup WebView2 SDK automatically
+echo Attempting to install WebView2 SDK via NuGet...
+dotnet add "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj" package Microsoft.Web.WebView2 --version %WEBVIEW2_VERSION%
+
+if %ERRORLEVEL% EQU 0 (
+ echo.
+ echo Restoring NuGet packages to ensure WebView2 SDK is downloaded...
+ dotnet restore "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj"
+
+ if %ERRORLEVEL% NEQ 0 (
+ echo ERROR: Failed to restore NuGet packages
+ exit /b 1
+ )
+ echo.
+ echo Copying WebView2 assemblies to WebView2SDK folder...
+
+REM Copy the assemblies from NuGet cache
+echo Searching for WebView2 assemblies in NuGet cache...
+echo USERPROFILE: %USERPROFILE%
+echo WEBVIEW2_VERSION: %WEBVIEW2_VERSION%
+
+REM Use PowerShell to find and copy the assemblies
+powershell -Command "& { $nugetPath = \"$env:USERPROFILE\.nuget\packages\microsoft.web.webview2\%WEBVIEW2_VERSION%\"; Write-Host \"NuGet path: $nugetPath\"; if (Test-Path $nugetPath) { Write-Host \"Package directory found\"; $coreDll = Get-ChildItem -Path $nugetPath -Recurse -Name 'Microsoft.Web.WebView2.Core.dll' | Select-Object -First 1; if ($coreDll) { $corePath = Join-Path $nugetPath $coreDll; Copy-Item $corePath 'WebView2SDK\'; Write-Host \"Copied Microsoft.Web.WebView2.Core.dll\" } else { Write-Error \"Core DLL not found\" }; $winFormsDll = Get-ChildItem -Path $nugetPath -Recurse -Name 'Microsoft.Web.WebView2.WinForms.dll' | Select-Object -First 1; if ($winFormsDll) { $winFormsPath = Join-Path $nugetPath $winFormsDll; Copy-Item $winFormsPath 'WebView2SDK\'; Write-Host \"Copied Microsoft.Web.WebView2.WinForms.dll\" } else { Write-Error \"WinForms DLL not found\" }; $loaderDll = Get-ChildItem -Path $nugetPath -Recurse -Name 'WebView2Loader.dll' | Select-Object -First 1; if ($loaderDll) { $loaderPath = Join-Path $nugetPath $loaderDll; Copy-Item $loaderPath 'WebView2SDK\'; Write-Host \"Copied WebView2Loader.dll\" } else { Write-Error \"Loader DLL not found\" } } else { Write-Error \"Package directory not found: $nugetPath\" } }"
+
+ REM Remove the NuGet package reference since we're using local assemblies
+ dotnet remove "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj" package Microsoft.Web.WebView2
+
+ REM Update project file with the latest version
+ echo Updating project file with latest version...
+ powershell -ExecutionPolicy Bypass -File "%~dp0Update-WebView2ProjectVersion.ps1"
+
+ echo.
+ echo WebView2 SDK setup completed successfully!
+ echo.
+ echo Installed version: %WEBVIEW2_VERSION%
+ echo Files copied:
+ dir WebView2SDK\*.dll
+ echo.
+ echo You can now build the solution and use the KryptonWebView2 control.
+) else (
+ echo.
+ echo Automatic setup failed. Please follow manual setup instructions:
+ echo.
+ echo MANUAL SETUP INSTRUCTIONS:
+ echo 1. Download the WebView2 SDK from: https://developer.microsoft.com/en-us/microsoft-edge/webview2/
+ echo 2. Extract the following files to the WebView2SDK folder:
+ echo - Microsoft.Web.WebView2.Core.dll
+ echo - Microsoft.Web.WebView2.WinForms.dll
+ echo - WebView2Loader.dll
+ echo.
+ echo Alternative: Use NuGet Package Manager to install Microsoft.Web.WebView2
+ echo and copy the assemblies from the packages folder to WebView2SDK.
+)
+
+echo.
+pause
diff --git a/Scripts/Update-WebView2ProjectVersion.ps1 b/Scripts/Update-WebView2ProjectVersion.ps1
new file mode 100644
index 000000000..107c0a687
--- /dev/null
+++ b/Scripts/Update-WebView2ProjectVersion.ps1
@@ -0,0 +1,84 @@
+# Update-WebView2ProjectVersion.ps1
+# Script to update the project file with the latest WebView2 SDK version
+
+param(
+ [string]$ProjectPath = "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj",
+ [switch]$WhatIf = $false
+)
+
+function Get-LatestWebView2Version {
+ try {
+ $packageId = "Microsoft.Web.WebView2"
+ $apiUrl = "https://api.nuget.org/v3-flatcontainer/$packageId/index.json"
+
+ Write-Host "Fetching latest version information for $packageId..." -ForegroundColor Green
+
+ $response = Invoke-RestMethod -Uri $apiUrl -Method Get
+
+ # Only stable versions (no prerelease identifiers)
+ $stableVersions = $response.versions | Where-Object { $_ -notmatch '[-]' } |
+ Sort-Object { [Version]$_ } -Descending
+ $latestVersion = $stableVersions[0]
+
+ if ($latestVersion) {
+ Write-Host "Latest stable version: $latestVersion" -ForegroundColor Yellow
+ return $latestVersion
+ } else {
+ Write-Error "No stable version found"
+ return $null
+ }
+ }
+ catch {
+ Write-Error "Failed to fetch version information: $($_.Exception.Message)"
+ return $null
+ }
+}
+
+function Update-ProjectFile {
+ param(
+ [string]$ProjectPath,
+ [string]$NewVersion,
+ [switch]$WhatIf
+ )
+
+ if (-not (Test-Path $ProjectPath)) {
+ Write-Error "Project file not found: $ProjectPath"
+ return $false
+ }
+
+ $content = Get-Content $ProjectPath -Raw
+
+ # Update .NET Framework references
+ $netFrameworkPattern = 'Microsoft\.Web\.WebView2\.Core, Version=([^,]+), Culture=neutral'
+ $netFrameworkReplacement = "Microsoft.Web.WebView2.Core, Version=$NewVersion, Culture=neutral"
+
+ $updatedContent = $content -replace $netFrameworkPattern, $netFrameworkReplacement
+
+ if ($updatedContent -ne $content) {
+ if ($WhatIf) {
+ Write-Host "Would update project file with version $NewVersion" -ForegroundColor Cyan
+ } else {
+ Set-Content $ProjectPath $updatedContent -NoNewline
+ Write-Host "Updated project file with version $NewVersion" -ForegroundColor Green
+ }
+ return $true
+ } else {
+ Write-Warning "No version references found to update in project file"
+ return $false
+ }
+}
+
+# Main execution
+$latestVersion = Get-LatestWebView2Version
+
+if ($latestVersion) {
+ $updated = Update-ProjectFile -ProjectPath $ProjectPath -NewVersion $latestVersion -WhatIf:$WhatIf
+
+ if ($updated -and -not $WhatIf) {
+ Write-Host "Project file updated successfully!" -ForegroundColor Green
+ Write-Host "You may need to rebuild the solution for changes to take effect." -ForegroundColor Yellow
+ }
+} else {
+ Write-Error "Could not determine latest WebView2 version"
+ exit 1
+}
diff --git a/Scripts/Update-WebView2SDK.cmd b/Scripts/Update-WebView2SDK.cmd
new file mode 100644
index 000000000..1e7ca8209
--- /dev/null
+++ b/Scripts/Update-WebView2SDK.cmd
@@ -0,0 +1,139 @@
+@echo off
+echo Updating to latest WebView2 SDK version...
+echo.
+
+REM Check if WebView2SDK directory exists
+if not exist "WebView2SDK" (
+ echo WebView2SDK directory not found. Please run Setup-WebView2SDK.cmd first.
+ echo.
+ pause
+ exit /b 1
+)
+
+REM Get the latest WebView2 SDK version
+echo Detecting latest WebView2 SDK version...
+for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -File "%~dp0Get-LatestWebView2Version.ps1"') do (
+ set "WEBVIEW2_VERSION=%%i"
+)
+
+if "%WEBVIEW2_VERSION%"=="" (
+ echo Failed to detect latest version, using fallback version 1.0.2478.35
+ set WEBVIEW2_VERSION=1.0.2478.35
+) else (
+ echo Using WebView2 SDK version: %WEBVIEW2_VERSION%
+)
+
+echo.
+echo Current WebView2 SDK version:
+if exist "WebView2SDK\Microsoft.Web.WebView2.Core.dll" (
+ powershell -Command "Get-ItemProperty 'WebView2SDK\Microsoft.Web.WebView2.Core.dll' | Select-Object -ExpandProperty VersionInfo | Select-Object -ExpandProperty FileVersion"
+) else (
+ echo Not installed
+)
+echo.
+echo Updating WebView2 SDK to version %WEBVIEW2_VERSION%...
+
+REM Temporarily add the latest version via NuGet
+dotnet add "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj" package Microsoft.Web.WebView2 --version %WEBVIEW2_VERSION%
+
+if %ERRORLEVEL% EQU 0 (
+ echo.
+ echo Restoring NuGet packages to ensure WebView2 SDK is downloaded...
+ dotnet restore "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj"
+
+ if %ERRORLEVEL% NEQ 0 (
+ echo ERROR: Failed to restore NuGet packages
+ exit /b 1
+ )
+
+ echo Copying updated WebView2 assemblies...
+
+ REM Copy the assemblies from NuGet cache
+ echo Searching for WebView2 assemblies in NuGet cache...
+ for /f "usebackq tokens=*" %%i in (`powershell -Command "Write-Output $env:USERPROFILE"`) do set "USER_PROFILE=%%i"
+ set "NUGET_PATH=%USER_PROFILE%\.nuget\packages\microsoft.web.webview2\%WEBVIEW2_VERSION%"
+ echo NuGet path: %NUGET_PATH%
+
+ REM Verify the package directory exists
+ if not exist "%NUGET_PATH%" (
+ echo ERROR: NuGet package directory not found: %NUGET_PATH%
+ echo Available packages:
+ dir "%USERPROFILE%\.nuget\packages\microsoft.web.webview2" /b 2>nul
+ exit /b 1
+ )
+
+ REM Find and copy Core DLL
+ for /f "delims=" %%i in ('powershell -Command "Get-ChildItem -Path '%NUGET_PATH%' -Recurse -Name 'Microsoft.Web.WebView2.Core.dll' | Select-Object -First 1"') do (
+ set "CORE_DLL=%%i"
+ )
+ if defined CORE_DLL (
+ if exist "%NUGET_PATH%\%CORE_DLL%" (
+ copy "%NUGET_PATH%\%CORE_DLL%" "WebView2SDK\" >nul 2>&1
+ echo Copied Microsoft.Web.WebView2.Core.dll
+ ) else (
+ echo ERROR: Core DLL file not found at: %NUGET_PATH%\%CORE_DLL%
+ exit /b 1
+ )
+ ) else (
+ echo ERROR: Microsoft.Web.WebView2.Core.dll not found in package
+ echo Available files in package:
+ dir "%NUGET_PATH%" /s /b
+ exit /b 1
+ )
+
+ REM Find and copy WinForms DLL
+ for /f "delims=" %%i in ('powershell -Command "Get-ChildItem -Path '%NUGET_PATH%' -Recurse -Name 'Microsoft.Web.WebView2.WinForms.dll' | Select-Object -First 1"') do (
+ set "WINFORMS_DLL=%%i"
+ )
+ if defined WINFORMS_DLL (
+ if exist "%NUGET_PATH%\%WINFORMS_DLL%" (
+ copy "%NUGET_PATH%\%WINFORMS_DLL%" "WebView2SDK\" >nul 2>&1
+ echo Copied Microsoft.Web.WebView2.WinForms.dll
+ ) else (
+ echo ERROR: WinForms DLL file not found at: %NUGET_PATH%\%WINFORMS_DLL%
+ exit /b 1
+ )
+ ) else (
+ echo ERROR: Microsoft.Web.WebView2.WinForms.dll not found in package
+ exit /b 1
+ )
+
+ REM Find and copy WebView2Loader DLL
+ for /f "delims=" %%i in ('powershell -Command "Get-ChildItem -Path '%NUGET_PATH%' -Recurse -Name 'WebView2Loader.dll' | Select-Object -First 1"') do (
+ set "LOADER_DLL=%%i"
+ )
+ if defined LOADER_DLL (
+ if exist "%NUGET_PATH%\%LOADER_DLL%" (
+ copy "%NUGET_PATH%\%LOADER_DLL%" "WebView2SDK\" >nul 2>&1
+ echo Copied WebView2Loader.dll
+ ) else (
+ echo ERROR: Loader DLL file not found at: %NUGET_PATH%\%LOADER_DLL%
+ exit /b 1
+ )
+ ) else (
+ echo ERROR: WebView2Loader.dll not found in package
+ exit /b 1
+ )
+
+ REM Remove the NuGet package reference
+ dotnet remove "Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj" package Microsoft.Web.WebView2
+
+ REM Update project file with the latest version
+ echo Updating project file with latest version...
+ powershell -ExecutionPolicy Bypass -File "%~dp0Update-WebView2ProjectVersion.ps1"
+
+ echo.
+ echo WebView2 SDK updated successfully!
+ echo.
+ echo Installed version: %WEBVIEW2_VERSION%
+ echo Updated files:
+ dir WebView2SDK\*.dll
+ echo.
+ echo You may need to rebuild the solution for changes to take effect.
+) else (
+ echo.
+ echo Failed to update WebView2 SDK. Please check your internet connection and try again.
+)
+
+echo.
+pause
diff --git a/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonWebView2.cs b/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonWebView2.cs
new file mode 100644
index 000000000..8917238f6
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Toolkit/Controls Toolkit/KryptonWebView2.cs
@@ -0,0 +1,419 @@
+#region BSD License
+/*
+ *
+ * Original BSD 3-Clause License (https://github.com/ComponentFactory/Krypton/blob/master/LICENSE)
+ * © Component Factory Pty Ltd, 2006 - 2016, (Version 4.5.0.0) All rights reserved.
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac & Ahmed Abdelhameed, tobitege et al. 2025 - 2025. All rights reserved.
+ *
+ */
+#endregion
+
+#if WEBVIEW2_AVAILABLE
+// Do not remove this using statement, it is used for the WebView2 control
+using Microsoft.Web.WebView2.WinForms;
+#endif
+
+namespace Krypton.Toolkit;
+
+#if WEBVIEW2_AVAILABLE
+///
+/// Provide a WebView2 control with Krypton styling applied.
+///
+///
+/// KryptonWebView2 is a modern web browser control that integrates Microsoft's WebView2 engine
+/// with the Krypton Toolkit's theming system. It provides a consistent look and feel with other
+/// Krypton controls while offering modern web rendering capabilities.
+///
+///
+///
+/// Key Features:
+/// - Modern web engine based on Microsoft Edge Chromium
+/// - Full integration with Krypton theming system
+/// - KryptonContextMenu support for custom right-click menus
+/// - Designer support for Visual Studio
+/// - Async navigation and JavaScript execution capabilities
+/// - Customizable zoom levels and background colors
+///
+///
+///
+/// Usage Example:
+///
+/// var webView = new KryptonWebView2();
+/// webView.KryptonContextMenu = myKryptonContextMenu;
+///
+/// // Initialize and navigate
+/// await webView.EnsureCoreWebView2Async();
+/// webView.CoreWebView2?.Navigate("https://example.com");
+///
+///
+///
+///
+/// Requirements:
+/// - WebView2 Runtime must be installed on the target system
+/// - Compatible with .NET Framework 4.7.2+ and .NET 8+
+/// - Windows platform only
+///
+///
+///
+/// See also: for legacy WebBrowser control with Krypton theming.
+///
+///
+[ToolboxItem(true)]
+[ToolboxBitmap(typeof(KryptonWebView2), "ToolboxBitmaps.WebView2.bmp")]
+[Designer(typeof(KryptonWebView2Designer))]
+[DesignerCategory(@"code")]
+[Description(@"Enables the user to browse web pages using the modern WebView2 engine with Krypton theming support.")]
+[CLSCompliant(false)]
+public class KryptonWebView2 : WebView2
+{
+ #region Instance Fields
+
+ private PaletteBase _palette;
+ private readonly PaletteMode _paletteMode = PaletteMode.Global;
+ private KryptonContextMenu? _kryptonContextMenu;
+ private IRenderer _renderer;
+
+ #endregion
+
+ #region Identity
+
+ ///
+ /// Initialize a new instance of the KryptonWebView2 class.
+ ///
+ ///
+ ///
+ /// The constructor initializes the control with Krypton-specific styling and behavior:
+ ///
+ ///
+ /// - Enables double buffering for smooth rendering
+ /// - Sets up resize redraw for proper repainting
+ /// - Initializes the Krypton palette system
+ /// - Registers for global palette change notifications
+ ///
+ ///
+ /// Note: The WebView2 engine itself is not initialized until EnsureCoreWebView2Async()
+ /// is called. This allows for better error handling and async initialization.
+ ///
+ ///
+ ///
+ ///
+ /// var webView = new KryptonWebView2();
+ /// webView.Size = new Size(800, 600);
+ ///
+ /// // Initialize the WebView2 engine asynchronously
+ /// await webView.EnsureCoreWebView2Async();
+ ///
+ ///
+ public KryptonWebView2()
+ {
+ // We use double buffering to reduce drawing flicker
+ SetStyle(ControlStyles.OptimizedDoubleBuffer |
+ ControlStyles.AllPaintingInWmPaint |
+ ControlStyles.UserPaint, true);
+
+ // We need to repaint entire control whenever resized
+ SetStyle(ControlStyles.ResizeRedraw, true);
+
+ // Yes, we want to be drawn double buffered by default
+ DoubleBuffered = true;
+
+ SetPalette(KryptonManager.CurrentGlobalPalette);
+
+ // Hook into global palette changes
+ KryptonManager.GlobalPaletteChanged += OnGlobalPaletteChanged;
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ ///
+ ///
+ /// This method performs the following cleanup operations:
+ ///
+ ///
+ /// - Unhooks from global palette change notifications
+ /// - Disposes of the associated KryptonContextMenu if present
+ /// - Calls the base class Dispose method to clean up WebView2 resources
+ ///
+ ///
+ /// The WebView2 engine will automatically clean up its native resources when the control is disposed.
+ ///
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // Unhook from global palette changes
+ KryptonManager.GlobalPaletteChanged -= OnGlobalPaletteChanged;
+
+ // Dispose of the krypton context menu
+ _kryptonContextMenu?.Dispose();
+ }
+
+ base.Dispose(disposing);
+ }
+
+ #endregion
+
+ #region Public
+
+ ///
+ /// Gets and sets the KryptonContextMenu to show when right-clicked.
+ ///
+ ///
+ /// A instance that will be displayed when the user right-clicks
+ /// on the web content, or null if no custom context menu should be shown.
+ ///
+ ///
+ ///
+ /// When set to a non-null value, this property overrides the default WebView2 context menu
+ /// with a Krypton-styled context menu. This allows for consistent theming across your
+ /// application while providing custom functionality.
+ ///
+ ///
+ /// The context menu will be shown at the mouse position when right-clicking within the
+ /// WebView2 control's client area. If the menu is activated via keyboard (Menu key),
+ /// it will be centered on the control.
+ ///
+ ///
+ /// Setting this property to null will restore the default WebView2 context menu behavior.
+ ///
+ ///
+ ///
+ ///
+ /// var contextMenu = new KryptonContextMenu();
+ /// contextMenu.Items.Add(new KryptonContextMenuItem("Copy"));
+ /// contextMenu.Items.Add(new KryptonContextMenuItem("Paste"));
+ ///
+ /// webView.KryptonContextMenu = contextMenu;
+ ///
+ ///
+ [Category(@"Behavior")]
+ [Description(@"The shortcut menu to show when the user right-clicks the page.")]
+ [DefaultValue(null)]
+ public KryptonContextMenu? KryptonContextMenu
+ {
+ get => _kryptonContextMenu;
+
+ set
+ {
+ if (_kryptonContextMenu != value)
+ {
+ if (_kryptonContextMenu != null)
+ {
+ _kryptonContextMenu.Disposed -= OnKryptonContextMenuDisposed;
+ }
+
+ _kryptonContextMenu = value;
+
+ if (_kryptonContextMenu != null)
+ {
+ _kryptonContextMenu.Disposed += OnKryptonContextMenuDisposed;
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region Protected Overrides
+
+ ///
+ /// Process Windows-based messages.
+ ///
+ /// A Windows-based message.
+ ///
+ ///
+ /// This method overrides the base WndProc to intercept context menu messages and provide
+ /// custom KryptonContextMenu handling. It processes the following message types:
+ ///
+ ///
+ /// - WM_CONTEXTMENU - Context menu activation (right-click or Menu key)
+ /// - WM_PARENTNOTIFY with WM_RBUTTONDOWN - Right mouse button down
+ ///
+ ///
+ /// When a KryptonContextMenu is assigned, this method will:
+ ///
+ ///
+ /// - Extract the mouse position from the message parameters
+ /// - Handle keyboard activation by centering the menu on the control
+ /// - Adjust the position to match standard context menu behavior
+ /// - Show the KryptonContextMenu if the mouse is within the client area
+ /// - Consume the message to prevent default WebView2 context menu
+ ///
+ ///
+ /// If no KryptonContextMenu is assigned, the message is passed to the base class for
+ /// default WebView2 context menu handling.
+ ///
+ ///
+ protected override void WndProc(ref Message m)
+ {
+ if ((m.Msg == PI.WM_.CONTEXTMENU) ||
+ (m.Msg == PI.WM_.PARENTNOTIFY && PI.LOWORD(m.WParam) == PI.WM_.RBUTTONDOWN))
+ {
+ // Only interested in overriding the behavior when we have a krypton context menu
+ if (KryptonContextMenu != null)
+ {
+ // Extract the screen mouse position (if might not actually be provided)
+ var mousePt = new Point(PI.LOWORD(m.LParam), PI.HIWORD(m.LParam));
+
+ // If keyboard activated, the menu position is centered
+ if (((int)(long)m.LParam) == -1)
+ {
+ mousePt = new Point(Width / 2, Height / 2);
+ }
+ else
+ {
+ if (m.Msg == PI.WM_.CONTEXTMENU)
+ {
+ mousePt = PointToClient(mousePt);
+ }
+
+ // Mouse point up and left 1 pixel so that the mouse overlaps the top left corner
+ // of the showing context menu just like it happens for a ContextMenuStrip.
+ mousePt.X -= 1;
+ mousePt.Y -= 1;
+ }
+
+ // If the mouse position is within our client area
+ if (ClientRectangle.Contains(mousePt))
+ {
+ // Show the context menu
+ KryptonContextMenu.Show(this, PointToScreen(mousePt));
+
+ // We eat the message!
+ return;
+ }
+ }
+ }
+
+ base.WndProc(ref m);
+ }
+
+ private void OnKryptonContextMenuDisposed(object? sender, EventArgs e) =>
+ // When the current krypton context menu is disposed, we should remove
+ // it to prevent it being used again, as that would just throw an exception
+ // because it has been disposed.
+ KryptonContextMenu = null;
+
+ #endregion
+
+ #region Palette Controls
+
+ /// Sets the palette being used.
+ /// The chosen palette.
+ private void SetPalette(PaletteBase palette)
+ {
+ if (palette != _palette)
+ {
+ // Unhook from current palette events
+ if (_palette != null)
+ {
+ _palette.BasePaletteChanged -= OnBaseChanged;
+ _palette.BaseRendererChanged -= OnBaseChanged;
+ }
+
+ // Remember the new palette
+ _palette = palette;
+
+ // Get the renderer associated with the palette
+ _renderer = _palette.GetRenderer();
+
+ // Hook to new palette events
+ if (_palette != null)
+ {
+ _palette.BasePaletteChanged += OnBaseChanged;
+ _palette.BaseRendererChanged += OnBaseChanged;
+ }
+ }
+ }
+
+ /// Called when there is a change in base renderer or base palette.
+ /// The sender.
+ /// The instance containing the event data.
+ private void OnBaseChanged(object? sender, EventArgs e) =>
+ // Change in base renderer or base palette require we fetch the latest renderer
+ _renderer = _palette.GetRenderer();
+
+ ///
+ /// Occurs when the global palette has been changed.
+ ///
+ /// Source of the event.
+ /// An EventArgs that contains the event data.
+ protected virtual void OnGlobalPaletteChanged(object? sender, EventArgs e)
+ {
+ // We only care if we are using the global palette
+ if (_paletteMode == PaletteMode.Global)
+ {
+ // Update self with the new global palette
+ SetPalette(KryptonManager.CurrentGlobalPalette);
+ }
+ }
+
+ ///
+ /// Create a tool strip renderer appropriate for the current renderer/palette pair.
+ ///
+ ///
+ /// A instance that provides Krypton-themed rendering
+ /// for tool strips, or null if no renderer is available.
+ ///
+ ///
+ ///
+ /// This method creates a tool strip renderer that matches the current Krypton theme
+ /// and palette. The renderer is used internally by the control to ensure consistent
+ /// theming across all UI elements.
+ ///
+ ///
+ /// The method uses the resolved palette (either the control's specific palette or
+ /// the global palette) to create the appropriate renderer for the current theme.
+ ///
+ ///
+ /// This method is primarily used internally by the Krypton framework but can be
+ /// called by advanced users who need custom tool strip rendering.
+ ///
+ ///
+ ///
+ ///
+ /// var renderer = webView.CreateToolStripRenderer();
+ /// if (renderer != null)
+ /// {
+ /// myToolStrip.Renderer = renderer;
+ /// }
+ ///
+ ///
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public ToolStripRenderer? CreateToolStripRenderer()
+ {
+ var palette = GetResolvedPalette() ?? KryptonManager.CurrentGlobalPalette;
+ return _renderer?.RenderToolStrip(palette);
+ }
+
+ ///
+ /// Gets the resolved palette to actually use when drawing.
+ ///
+ ///
+ /// A instance that represents the currently active palette
+ /// for this control.
+ ///
+ ///
+ ///
+ /// This method returns the palette that is currently being used for rendering this control.
+ /// The resolved palette is determined by the control's palette mode and the global palette
+ /// settings.
+ ///
+ ///
+ /// This method is primarily used internally by the Krypton framework for rendering
+ /// operations and theme consistency.
+ ///
+ ///
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public PaletteBase GetResolvedPalette() => _palette;
+
+ #endregion
+}
+#endif
diff --git a/Source/Krypton Components/Krypton.Toolkit/Designers/Designers/KryptonWebView2Designer.cs b/Source/Krypton Components/Krypton.Toolkit/Designers/Designers/KryptonWebView2Designer.cs
new file mode 100644
index 000000000..aa0a4ce6b
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Toolkit/Designers/Designers/KryptonWebView2Designer.cs
@@ -0,0 +1,38 @@
+#region BSD License
+/*
+ *
+ * Original BSD 3-Clause License (https://github.com/ComponentFactory/Krypton/blob/master/LICENSE)
+ * © Component Factory Pty Ltd, 2006 - 2016, (Version 4.5.0.0) All rights reserved.
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac & Ahmed Abdelhameed et al. 2025 - 2025. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Toolkit;
+
+#if WEBVIEW2_AVAILABLE
+internal class KryptonWebView2Designer : ControlDesigner
+{
+ #region Public Overrides
+ ///
+ /// Initializes the designer with the specified component.
+ ///
+ /// The IComponent to associate the designer with.
+ public override void Initialize([DisallowNull] IComponent component)
+ {
+ // Let base class do standard stuff
+ base.Initialize(component);
+
+ Debug.Assert(component != null);
+
+ // The resizing handles around the control need to change depending on the
+ // value of the AutoSize and AutoSizeMode properties. When in AutoSize you
+ // do not get the resizing handles, otherwise you do.
+ AutoResizeHandles = true;
+ }
+
+ #endregion Public Overrides
+}
+#endif
diff --git a/Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj b/Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj
index c64288fda..622d99622 100644
--- a/Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj
+++ b/Source/Krypton Components/Krypton.Toolkit/Krypton.Toolkit 2022.csproj
@@ -1,4 +1,4 @@
-
+
@@ -57,6 +57,35 @@
+
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.Core.dll
+ True
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.WinForms.dll
+ True
+
+
+
+
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.Core.dll
+ True
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.WinForms.dll
+ True
+
+
+
+
+
+ $(DefineConstants);WEBVIEW2_AVAILABLE
+
+
Krypton.Toolkit
@@ -551,6 +580,7 @@
+
diff --git a/Source/Krypton Components/Krypton.Toolkit/ToolboxBitmaps/WebView2.bmp b/Source/Krypton Components/Krypton.Toolkit/ToolboxBitmaps/WebView2.bmp
new file mode 100644
index 000000000..ec4e033c4
Binary files /dev/null and b/Source/Krypton Components/Krypton.Toolkit/ToolboxBitmaps/WebView2.bmp differ
diff --git a/Source/Krypton Components/TestForm/KryptonWebView2Test.Designer.cs b/Source/Krypton Components/TestForm/KryptonWebView2Test.Designer.cs
new file mode 100644
index 000000000..cb72643f4
--- /dev/null
+++ b/Source/Krypton Components/TestForm/KryptonWebView2Test.Designer.cs
@@ -0,0 +1,196 @@
+#region BSD License
+/*
+ *
+ * Original BSD 3-Clause License (https://github.com/ComponentFactory/Krypton/blob/master/LICENSE)
+ * © Component Factory Pty Ltd, 2006 - 2016, (Version 4.5.0.0) All rights reserved.
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac & Ahmed Abdelhameed, tobitege et al. 2025 - 2025. All rights reserved.
+ *
+ */
+#endregion
+
+namespace TestForm
+{
+ partial class KryptonWebView2Test
+ {
+ ///
+ /// 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.kryptonPanel1 = new Krypton.Toolkit.KryptonPanel();
+ this.kryptonWebView21 = new Krypton.Toolkit.KryptonWebView2();
+ this.kryptonLabel1 = new Krypton.Toolkit.KryptonLabel();
+ this.kryptonPanel2 = new Krypton.Toolkit.KryptonPanel();
+ this.kbtnRefresh = new Krypton.Toolkit.KryptonButton();
+ this.kbtnForward = new Krypton.Toolkit.KryptonButton();
+ this.kbtnBack = new Krypton.Toolkit.KryptonButton();
+ this.kbtnNavigate = new Krypton.Toolkit.KryptonButton();
+ this.kryptonTextBox1 = new Krypton.Toolkit.KryptonTextBox();
+ this.kryptonLabel2 = new Krypton.Toolkit.KryptonLabel();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).BeginInit();
+ this.kryptonPanel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).BeginInit();
+ this.kryptonPanel2.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // kryptonPanel1
+ //
+ this.kryptonPanel1.Controls.Add(this.kryptonWebView21);
+ this.kryptonPanel1.Controls.Add(this.kryptonLabel1);
+ this.kryptonPanel1.Controls.Add(this.kryptonPanel2);
+ this.kryptonPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.kryptonPanel1.Location = new System.Drawing.Point(0, 0);
+ this.kryptonPanel1.Name = "kryptonPanel1";
+ this.kryptonPanel1.PanelBackStyle = Krypton.Toolkit.PaletteBackStyle.ControlClient;
+ this.kryptonPanel1.Size = new System.Drawing.Size(1000, 700);
+ this.kryptonPanel1.TabIndex = 0;
+ //
+ // kryptonWebView21
+ //
+ this.kryptonWebView21.AllowExternalDrop = true;
+ this.kryptonWebView21.CreationProperties = null;
+ this.kryptonWebView21.DefaultBackgroundColor = System.Drawing.Color.White;
+ this.kryptonWebView21.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.kryptonWebView21.Location = new System.Drawing.Point(0, 60);
+ this.kryptonWebView21.Name = "kryptonWebView21";
+ this.kryptonWebView21.Size = new System.Drawing.Size(1000, 640);
+ this.kryptonWebView21.TabIndex = 2;
+ this.kryptonWebView21.ZoomFactor = 1D;
+ this.kryptonWebView21.NavigationCompleted += new System.EventHandler(this.kryptonWebView21_NavigationCompleted);
+ //
+ // kryptonLabel1
+ //
+ this.kryptonLabel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.kryptonLabel1.LabelStyle = Krypton.Toolkit.LabelStyle.NormalControl;
+ this.kryptonLabel1.Location = new System.Drawing.Point(0, 60);
+ this.kryptonLabel1.Name = "kryptonLabel1";
+ this.kryptonLabel1.Size = new System.Drawing.Size(1000, 640);
+ this.kryptonLabel1.TabIndex = 1;
+ this.kryptonLabel1.Text = "Initializing WebView2...";
+ this.kryptonLabel1.Values.Text = "Initializing WebView2...";
+ this.kryptonLabel1.Visible = false;
+ //
+ // kryptonPanel2
+ //
+ this.kryptonPanel2.Controls.Add(this.kbtnRefresh);
+ this.kryptonPanel2.Controls.Add(this.kbtnForward);
+ this.kryptonPanel2.Controls.Add(this.kbtnBack);
+ this.kryptonPanel2.Controls.Add(this.kbtnNavigate);
+ this.kryptonPanel2.Controls.Add(this.kryptonTextBox1);
+ this.kryptonPanel2.Controls.Add(this.kryptonLabel2);
+ this.kryptonPanel2.Dock = System.Windows.Forms.DockStyle.Top;
+ this.kryptonPanel2.Location = new System.Drawing.Point(0, 0);
+ this.kryptonPanel2.Name = "kryptonPanel2";
+ this.kryptonPanel2.PanelBackStyle = Krypton.Toolkit.PaletteBackStyle.ControlClient;
+ this.kryptonPanel2.Size = new System.Drawing.Size(1000, 60);
+ this.kryptonPanel2.TabIndex = 0;
+ //
+ // kbtnRefresh
+ //
+ this.kbtnRefresh.Location = new System.Drawing.Point(450, 30);
+ this.kbtnRefresh.Name = "kbtnRefresh";
+ this.kbtnRefresh.Size = new System.Drawing.Size(75, 25);
+ this.kbtnRefresh.TabIndex = 5;
+ this.kbtnRefresh.Values.Text = "Refresh";
+ this.kbtnRefresh.Click += new System.EventHandler(this.kbtnRefresh_Click);
+ //
+ // kbtnForward
+ //
+ this.kbtnForward.Location = new System.Drawing.Point(370, 30);
+ this.kbtnForward.Name = "kbtnForward";
+ this.kbtnForward.Size = new System.Drawing.Size(75, 25);
+ this.kbtnForward.TabIndex = 4;
+ this.kbtnForward.Values.Text = "Forward";
+ this.kbtnForward.Click += new System.EventHandler(this.kbtnForward_Click);
+ //
+ // kbtnBack
+ //
+ this.kbtnBack.Location = new System.Drawing.Point(290, 30);
+ this.kbtnBack.Name = "kbtnBack";
+ this.kbtnBack.Size = new System.Drawing.Size(75, 25);
+ this.kbtnBack.TabIndex = 3;
+ this.kbtnBack.Values.Text = "Back";
+ this.kbtnBack.Click += new System.EventHandler(this.kbtnBack_Click);
+ //
+ // kbtnNavigate
+ //
+ this.kbtnNavigate.Location = new System.Drawing.Point(530, 30);
+ this.kbtnNavigate.Name = "kbtnNavigate";
+ this.kbtnNavigate.Size = new System.Drawing.Size(75, 25);
+ this.kbtnNavigate.TabIndex = 2;
+ this.kbtnNavigate.Values.Text = "Navigate";
+ this.kbtnNavigate.Click += new System.EventHandler(this.kbtnNavigate_Click);
+ //
+ // kryptonTextBox1
+ //
+ this.kryptonTextBox1.Location = new System.Drawing.Point(80, 32);
+ this.kryptonTextBox1.Name = "kryptonTextBox1";
+ this.kryptonTextBox1.Size = new System.Drawing.Size(200, 23);
+ this.kryptonTextBox1.TabIndex = 1;
+ this.kryptonTextBox1.Text = "https://www.microsoft.com";
+ //
+ // kryptonLabel2
+ //
+ this.kryptonLabel2.Location = new System.Drawing.Point(10, 35);
+ this.kryptonLabel2.Name = "kryptonLabel2";
+ this.kryptonLabel2.Size = new System.Drawing.Size(64, 20);
+ this.kryptonLabel2.TabIndex = 0;
+ this.kryptonLabel2.Values.Text = "Address:";
+ //
+ // KryptonWebView2Test
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1000, 700);
+ this.Controls.Add(this.kryptonPanel1);
+ this.Name = "KryptonWebView2Test";
+ this.Text = "KryptonWebView2 Test";
+ this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).EndInit();
+ this.kryptonPanel1.ResumeLayout(false);
+ this.kryptonPanel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).EndInit();
+ this.kryptonPanel2.ResumeLayout(false);
+ this.kryptonPanel2.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Krypton.Toolkit.KryptonPanel kryptonPanel1;
+ private Krypton.Toolkit.KryptonWebView2 kryptonWebView21;
+ private Krypton.Toolkit.KryptonLabel kryptonLabel1;
+ private Krypton.Toolkit.KryptonPanel kryptonPanel2;
+ private Krypton.Toolkit.KryptonButton kbtnRefresh;
+ private Krypton.Toolkit.KryptonButton kbtnForward;
+ private Krypton.Toolkit.KryptonButton kbtnBack;
+ private Krypton.Toolkit.KryptonButton kbtnNavigate;
+ private Krypton.Toolkit.KryptonTextBox kryptonTextBox1;
+ private Krypton.Toolkit.KryptonLabel kryptonLabel2;
+ }
+}
diff --git a/Source/Krypton Components/TestForm/KryptonWebView2Test.cs b/Source/Krypton Components/TestForm/KryptonWebView2Test.cs
new file mode 100644
index 000000000..e762645f8
--- /dev/null
+++ b/Source/Krypton Components/TestForm/KryptonWebView2Test.cs
@@ -0,0 +1,180 @@
+#region BSD License
+/*
+ *
+ * Original BSD 3-Clause License (https://github.com/ComponentFactory/Krypton/blob/master/LICENSE)
+ * © Component Factory Pty Ltd, 2006 - 2016, (Version 4.5.0.0) All rights reserved.
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac & Ahmed Abdelhameed, tobitege et al. 2025 - 2025. All rights reserved.
+ *
+ */
+#endregion
+
+using Microsoft.Web.WebView2.Core;
+
+namespace TestForm;
+
+///
+/// Test form demonstrating the KryptonWebView2 control functionality.
+///
+///
+/// This form showcases the key features of the KryptonWebView2 control including:
+/// - Control initialization and error handling
+/// - Navigation with address bar
+/// - Navigation controls (Back, Forward, Refresh)
+/// - Integration with Krypton theming
+/// - Proper async/await patterns for WebView2 operations
+///
+///
+///
+/// The form includes a toolbar with navigation controls and an address bar,
+/// while the main area displays the WebView2 control. Error handling is
+/// demonstrated for WebView2 initialization failures.
+///
+///
+public partial class KryptonWebView2Test : KryptonForm
+{
+ public KryptonWebView2Test()
+ {
+ InitializeComponent();
+ InitializeWebView2();
+ }
+
+ ///
+ /// Initializes the WebView2 control asynchronously and navigates to a default page.
+ ///
+ ///
+ /// This method demonstrates proper WebView2 initialization with error handling.
+ /// If initialization fails, the WebView2 control is hidden and an error message
+ /// is displayed to the user with instructions to install the WebView2 Runtime.
+ ///
+ private async void InitializeWebView2()
+ {
+ try
+ {
+ // Initialize the WebView2 control
+ await kryptonWebView21.EnsureCoreWebView2Async();
+
+ // Navigate to a test page
+ kryptonWebView21.CoreWebView2?.Navigate("https://www.microsoft.com");
+ }
+ catch (Exception ex)
+ {
+ // If WebView2 fails to initialize, show a message
+ kryptonWebView21.Visible = false;
+ kryptonLabel1.Text = $"WebView2 initialization failed: {ex.Message}\n\nPlease ensure WebView2 Runtime is installed.";
+ kryptonLabel1.Visible = true;
+ }
+ }
+
+ ///
+ /// Handles the Navigate button click event.
+ ///
+ /// The button that raised the event.
+ /// Event arguments.
+ ///
+ /// This method demonstrates navigation with URL validation and protocol handling.
+ /// If the entered URL doesn't have a protocol, HTTPS is automatically added.
+ /// Navigation errors are caught and displayed to the user.
+ ///
+ private void kbtnNavigate_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ var url = kryptonTextBox1.Text.Trim();
+ if (!string.IsNullOrEmpty(url))
+ {
+ // Add protocol if not present
+ if (!url.StartsWith("http://") && !url.StartsWith("https://"))
+ {
+ url = "https://" + url;
+ }
+
+ kryptonWebView21.CoreWebView2?.Navigate(url);
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"Navigation error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Handles the Back button click event.
+ ///
+ /// The button that raised the event.
+ /// Event arguments.
+ ///
+ /// Demonstrates navigation history management by going back to the previous page.
+ ///
+ private void kbtnBack_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ kryptonWebView21.CoreWebView2?.GoBack();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"Navigation error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Handles the Forward button click event.
+ ///
+ /// The button that raised the event.
+ /// Event arguments.
+ ///
+ /// Demonstrates navigation history management by going forward to the next page.
+ ///
+ private void kbtnForward_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ kryptonWebView21.CoreWebView2?.GoForward();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"Navigation error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Handles the Refresh button click event.
+ ///
+ /// The button that raised the event.
+ /// Event arguments.
+ ///
+ /// Demonstrates page reload functionality by refreshing the current page.
+ ///
+ private void kbtnRefresh_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ kryptonWebView21.CoreWebView2?.Reload();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"Navigation error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Handles the NavigationCompleted event from the WebView2 control.
+ ///
+ /// The WebView2 control that raised the event.
+ /// Navigation completion event arguments.
+ ///
+ /// This method demonstrates how to handle navigation completion events.
+ /// On successful navigation, the address bar is updated with the current URL.
+ /// This provides visual feedback to the user about the current page location.
+ ///
+ private void kryptonWebView21_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
+ {
+ // Update the address bar with the current URL
+ if (e.IsSuccess && kryptonWebView21.CoreWebView2 != null)
+ {
+ kryptonTextBox1.Text = kryptonWebView21.CoreWebView2.Source;
+ }
+ }
+}
diff --git a/Source/Krypton Components/TestForm/KryptonWebView2Test.resx b/Source/Krypton Components/TestForm/KryptonWebView2Test.resx
new file mode 100644
index 000000000..4f03a7d1d
--- /dev/null
+++ b/Source/Krypton Components/TestForm/KryptonWebView2Test.resx
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 17, 17
+
+
diff --git a/Source/Krypton Components/TestForm/TestForm.csproj b/Source/Krypton Components/TestForm/TestForm.csproj
index 694c1a7dd..f8fbcbe3f 100644
--- a/Source/Krypton Components/TestForm/TestForm.csproj
+++ b/Source/Krypton Components/TestForm/TestForm.csproj
@@ -24,6 +24,30 @@
+
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.Core.dll
+ True
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.WinForms.dll
+ True
+
+
+
+
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.Core.dll
+ True
+
+
+ ..\..\..\WebView2SDK\Microsoft.Web.WebView2.WinForms.dll
+ True
+
+
+
True
diff --git a/run.cmd b/run.cmd
index 6dff671f7..6cac438ce 100644
--- a/run.cmd
+++ b/run.cmd
@@ -16,19 +16,21 @@ echo 3. Create NuGet packages
echo 4. Build and Pack Toolkit
echo 5. Debug project
echo 6. NuGet Tools
-echo 7. Create Archives (ZIP/TAR)
+echo 7. WebView2 SDK Tools
+echo 8. Create Archives (ZIP/TAR)
::echo 8. Miscellaneous tasks
-echo 8. End
+echo 9. End
echo:
-set /p answer="Enter number (1 - 8): "
+set /p answer="Enter number (1 - 9): "
if %answer%==1 (goto cleanproject)
if %answer%==2 (goto buildproject)
if %answer%==3 (goto createnugetpackages)
if %answer%==4 (goto buildandpacktoolkit)
if %answer%==5 (goto debugproject)
if %answer%==6 (goto nugettools)
-if %answer%==7 (goto createarchives)
-if %answer%==8 (goto exitbuildsystem)
+if %answer%==7 (goto webview2tools)
+if %answer%==8 (goto createarchives)
+if %answer%==9 (goto exitbuildsystem)
@echo Invalid input, please try again.
@@ -48,20 +50,22 @@ echo 3. Create NuGet packages
echo 4. Build and Pack Toolkit
echo 5. Debug project
echo 6. NuGet Tools
-echo 7. Create Archives (ZIP/TAR)
+echo 7. WebView2 SDK Tools
+echo 8. Create Archives (ZIP/TAR)
::echo 8. Miscellaneous tasks
-echo 8. End
+echo 9. End
echo:
-set /p answer="Enter number (1 - 8): "
+set /p answer="Enter number (1 - 9): "
if %answer%==1 (goto cleanproject)
if %answer%==2 (goto buildproject)
if %answer%==3 (goto createnugetpackages)
if %answer%==4 (goto buildandpacktoolkit)
if %answer%==5 (goto debugproject)
if %answer%==6 (goto nugettools)
-if %answer%==7 (goto createarchives)
+if %answer%==7 (goto webview2tools)
+if %answer%==8 (goto createarchives)
::if %answer%==8 (goto miscellaneoustasks)
-if %answer%==8 (goto exitbuildsystem)
+if %answer%==9 (goto exitbuildsystem)
@echo Invalid input, please try again.
@@ -687,6 +691,84 @@ build-stable.cmd Pack
:: ===================================================================================================
+:webview2tools
+cls
+
+echo WebView2 SDK Tools
+echo.
+echo 1. Setup WebView2 SDK
+echo 2. Update WebView2 SDK
+echo 3. Check WebView2 Version
+echo 4. Go back to main menu
+echo:
+set /p answer="Enter number (1 - 4): "
+if %answer%==1 (goto setupwebview2sdk)
+if %answer%==2 (goto updatewebview2sdk)
+if %answer%==3 (goto checkwebview2version)
+if %answer%==4 (goto mainmenu)
+
+@echo Invalid input, please try again.
+
+pause
+
+goto webview2tools
+
+:: ===================================================================================================
+
+:setupwebview2sdk
+cls
+
+echo Setting up WebView2 SDK for KryptonWebView2 control...
+echo This will install the latest stable WebView2 SDK version.
+echo.
+
+cd Scripts
+
+Setup-WebView2SDK.cmd
+
+cd ..
+
+pause
+
+goto webview2tools
+
+:: ===================================================================================================
+
+:updatewebview2sdk
+cls
+
+echo Updating WebView2 SDK to latest version...
+echo This will check for updates and install the newest stable version.
+echo.
+
+cd Scripts
+
+Update-WebView2SDK.cmd
+
+cd ..
+
+pause
+
+goto webview2tools
+
+:: ===================================================================================================
+
+:checkwebview2version
+cls
+
+echo Checking WebView2 SDK version...
+echo.
+
+cd Scripts
+
+Check-WebView2Version.cmd
+
+cd ..
+
+pause
+
+goto webview2tools
+
:clearlogfiles
:clearbinaries
\ No newline at end of file