├── .editorconfig
├── .gitattributes
├── .github
├── pack.bat
└── workflows
│ ├── build.yml
│ └── publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── samples
├── README.md
└── VirtualDesktop.Showcase
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ └── VirtualDesktop.Showcase.csproj
└── src
├── VirtualDesktop (LocalAppData).lnk
├── VirtualDesktop.WPF
├── ApplicationExtensions.cs
├── Properties
│ └── AssemblyInfo.cs
├── VirtualDesktop.WPF.csproj
└── WindowExtensions.cs
├── VirtualDesktop.WinForms
├── FormExtensions.cs
├── Properties
│ └── AssemblyInfo.cs
└── VirtualDesktop.WinForms.csproj
├── VirtualDesktop.sln
├── VirtualDesktop.sln.DotSettings
└── VirtualDesktop
├── Interop
├── Build10240
│ ├── .Provider.cs
│ ├── .interfaces
│ │ ├── AssemblyInfo.cs
│ │ ├── IApplicationView.cs
│ │ ├── IApplicationViewCollection.cs
│ │ ├── IVirtualDesktop.cs
│ │ ├── IVirtualDesktopManagerInternal.cs
│ │ ├── IVirtualDesktopNotification.cs
│ │ ├── IVirtualDesktopNotificationService.cs
│ │ └── IVirtualDesktopPinnedApps.cs
│ ├── ApplicationView.cs
│ ├── ApplicationViewCollection.cs
│ ├── VirtualDesktop.cs
│ ├── VirtualDesktopManagerInternal.cs
│ ├── VirtualDesktopNotificationService.cs
│ └── VirtualDesktopPinnedApps.cs
├── Build22000
│ ├── .Provider.cs
│ ├── .interfaces
│ │ ├── IVirtualDesktop.cs
│ │ ├── IVirtualDesktopManagerInternal.cs
│ │ ├── IVirtualDesktopNotification.cs
│ │ └── IVirtualDesktopNotificationService.cs
│ ├── VirtualDesktop.cs
│ ├── VirtualDesktopManagerInternal.cs
│ └── VirtualDesktopNotificationService.cs
├── CLSID.cs
├── ComInterfaceAssembly.cs
├── ComInterfaceAssemblyBuilder.cs
├── ComInterfaceAttribute.cs
├── ComWrapperBase.cs
├── ComWrapperFactory.cs
├── HResult.cs
├── HString.cs
├── IID.cs
├── Proxy
│ ├── IApplicationView.cs
│ ├── IApplicationViewCollection.cs
│ ├── IVirtualDesktop.cs
│ ├── IVirtualDesktopManagerInternal.cs
│ ├── IVirtualDesktopNotification.cs
│ ├── IVirtualDesktopNotificationService.cs
│ └── IVirtualDesktopPinnedApps.cs
├── VirtualDesktopProvider.cs
└── Win32.cs
├── Properties
├── AssemblyInfo.cs
├── Configurations.cs
├── Settings.Designer.cs
└── Settings.settings
├── Utils
├── Disposable.cs
├── ExplorerRestartListenerWindow.cs
├── RawWindow.cs
└── TransparentWindow.cs
├── VirtualDesktop.cs
├── VirtualDesktop.csproj
├── VirtualDesktop.csproj.DotSettings
├── VirtualDesktop.notification.cs
├── VirtualDesktop.system.cs
├── VirtualDesktopEventArgs.cs
├── VirtualDesktopExtensions.cs
└── app.config
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{cs,xaml}]
4 | indent_style = space
5 | indent_size = 4
6 | end_of_line = crlf
7 | insert_final_newline = true
8 | charset = utf-8-bom
9 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | #* text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/pack.bat:
--------------------------------------------------------------------------------
1 | dotnet build ..\src\VirtualDesktop.sln -c Release
2 | dotnet pack ..\src\VirtualDesktop.sln -c Release --no-build -o %CD%
3 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 |
10 | env:
11 | DOTNET_VERSION: 6.0.x
12 | BUILD_TARGET: .\src\VirtualDesktop.sln
13 |
14 |
15 | jobs:
16 | build:
17 | name: .NET Build
18 | runs-on: windows-latest
19 |
20 | steps:
21 | - uses: actions/checkout@v2
22 |
23 | - name: Use .NET ${{ env.DOTNET_VERSION }}
24 | uses: actions/setup-dotnet@v1
25 | with:
26 | dotnet-version: ${{ env.DOTNET_VERSION }}
27 |
28 | - name: Build
29 | run: dotnet build ${{ env.BUILD_TARGET }} -c Release
30 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 |
3 | on:
4 | push:
5 | branches: [ release ]
6 |
7 | env:
8 | DOTNET_VERSION: 6.0.x
9 | BUILD_TARGET: .\src\VirtualDesktop.sln
10 |
11 | jobs:
12 | build:
13 | name: .NET Build
14 | runs-on: windows-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 |
19 | - name: Use .NET ${{ env.DOTNET_VERSION }}
20 | uses: actions/setup-dotnet@v1
21 | with:
22 | dotnet-version: ${{ env.DOTNET_VERSION }}
23 |
24 | - name: Build
25 | run: dotnet build ${{ env.BUILD_TARGET }} -c Release
26 |
27 | - name: Pack
28 | run: dotnet pack ${{ env.BUILD_TARGET }} -c Release --no-build
29 |
30 | - name: Upload artifacts
31 | uses: actions/upload-artifact@v2.3.1
32 | with:
33 | name: nuget-packages
34 | path: "**/*.nupkg"
35 |
36 |
37 | publish:
38 | name: Publish to NuGet
39 | runs-on: windows-latest
40 | needs: build
41 | if: github.ref == 'refs/heads/release'
42 |
43 | steps:
44 | - name: Use NuGet
45 | uses: NuGet/setup-nuget@v1.0.5
46 | with:
47 | nuget-version: latest
48 | nuget-api-key: ${{ secrets.NUGET_API_KEY }}
49 |
50 | - name: Fetch artifacts
51 | uses: actions/download-artifact@v2.1.0
52 | with:
53 | name: nuget-packages
54 |
55 | - name: Publish
56 | run: nuget push **\*.nupkg -Source https://api.nuget.org/v3/index.json
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | *_i.c
42 | *_p.c
43 | *_i.h
44 | *.ilk
45 | *.meta
46 | *.obj
47 | *.pch
48 | *.pdb
49 | *.pgc
50 | *.pgd
51 | *.rsp
52 | *.sbr
53 | *.tlb
54 | *.tli
55 | *.tlh
56 | *.tmp
57 | *.tmp_proj
58 | *.log
59 | *.vspscc
60 | *.vssscc
61 | .builds
62 | *.pidb
63 | *.svclog
64 | *.scc
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 | # TODO: Comment the next line if you want to checkin your web deploy settings
133 | # but database connection strings (with potential passwords) will be unencrypted
134 | *.pubxml
135 | *.publishproj
136 |
137 | # NuGet Packages
138 | *.nupkg
139 | # The packages folder can be ignored because of Package Restore
140 | **/packages/*
141 | # except build/, which is used as an MSBuild target.
142 | !**/packages/build/
143 | # Uncomment if necessary however generally it will be regenerated when needed
144 | #!**/packages/repositories.config
145 |
146 | # Windows Azure Build Output
147 | csx/
148 | *.build.csdef
149 |
150 | # Windows Store app package directory
151 | AppPackages/
152 |
153 | # Others
154 | *.[Cc]ache
155 | ClientBin/
156 | [Ss]tyle[Cc]op.*
157 | ~$*
158 | *~
159 | *.dbmdl
160 | *.dbproj.schemaview
161 | *.pfx
162 | *.publishsettings
163 | node_modules/
164 | bower_components/
165 |
166 | # RIA/Silverlight projects
167 | Generated_Code/
168 |
169 | # Backup & report files from converting an old project file
170 | # to a newer Visual Studio version. Backup files are not needed,
171 | # because we have git ;-)
172 | _UpgradeReport_Files/
173 | Backup*/
174 | UpgradeLog*.XML
175 | UpgradeLog*.htm
176 |
177 | # SQL Server files
178 | *.mdf
179 | *.ldf
180 |
181 | # Business Intelligence projects
182 | *.rdl.data
183 | *.bim.layout
184 | *.bim_*.settings
185 |
186 | # Microsoft Fakes
187 | FakesAssemblies/
188 |
189 | # Node.js Tools for Visual Studio
190 | .ntvs_analysis.dat
191 |
192 | # Visual Studio 6 build log
193 | *.plg
194 |
195 | # Visual Studio 6 workspace options file
196 | *.opt
197 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Manato KAMEYA
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VirtualDesktop
2 |
3 | VirtualDesktop is C# wrapper for [IVirtualDesktopManager](https://msdn.microsoft.com/en-us/library/windows/desktop/mt186440%28v%3Dvs.85%29.aspx) on Windows 11 (and Windows 10).
4 |
5 | [](https://github.com/Grabacr07/VirtualDesktop/actions/workflows/build.yml)
6 | [](https://www.nuget.org/packages/VirtualDesktop/)
7 | [](LICENSE)
8 |
9 |
10 | ## Features
11 |
12 | * Switch, add, and remove a virtual desktop.
13 | * Move the window in the same process to any virtual desktop.
14 | * Move the window of another process to any virtual desktop (Support in version 2.0 or later).
15 | * Pin any window or application; will be display on all desktops.
16 | * Notification for switching, deletion, renaming, etc.
17 | * Change the wallpaper for each desktop.
18 |
19 |
20 | ### Sample app
21 |
22 | 
23 | [samples/VirtualDesktop.Showcase](samples/VirtualDesktop.Showcase)
24 |
25 |
26 | ## Requirements
27 |
28 | ```xml
29 | net5.0-windows10.0.19041.0
30 | ```
31 | * .NET 5 or 6
32 | * Windows 10 build 19041 (20H1) or later
33 |
34 |
35 | ## Installation
36 |
37 | Install NuGet package(s).
38 |
39 | ```powershell
40 | PM> Install-Package VirtualDesktop
41 | ```
42 |
43 | * [VirtualDesktop](https://www.nuget.org/packages/VirtualDesktop/) - Core classes for VirtualDesktop.
44 | * [VirtualDesktop.WPF](https://www.nuget.org/packages/VirtualDesktop.WPF/) - Provides extension methods for WPF [Window class](https://msdn.microsoft.com/en-us/library/system.windows.window(v=vs.110).aspx).
45 | * [VirtualDesktop.WinForms](https://www.nuget.org/packages/VirtualDesktop.WinForms/) - Provides extension methods for [Form class](https://msdn.microsoft.com/en-us/library/system.windows.forms.form(v=vs.110).aspx).
46 |
47 |
48 | ## How to use
49 |
50 | ### Preparation
51 | Because of the dependency on [C#/WinRT](https://aka.ms/cswinrt) ([repo](https://github.com/microsoft/CsWinRT)), the target framework must be set to `net5.0-windows10.0.19041.0` or later.
52 | ```xml
53 | net5.0-windows10.0.19041.0
54 | ```
55 | ```xml
56 | net6.0-windows10.0.19041.0
57 | ```
58 |
59 | If it doesn't work, try creating an `app.manifest` file and optimize to work on Windows 10.
60 | ```xml
61 |
62 |
63 |
64 |
65 |
66 |
67 | ```
68 |
69 | The namespace to use is `WindowsDesktop`.
70 | ```csharp
71 | using WindowsDesktop;
72 | ```
73 |
74 | ### Get instance of VirtualDesktop class
75 | ```csharp
76 | // Get all virtual desktops
77 | var desktops = VirtualDesktop.GetDesktops();
78 |
79 | // Get Virtual Desktop for specific window
80 | var desktop = VirtualDesktop.FromHwnd(hwnd);
81 |
82 | // Get the left/right desktop
83 | var left = desktop.GetLeft();
84 | var right = desktop.GetRight();
85 | ```
86 |
87 | ### Manage virtual desktops
88 | ```csharp
89 | // Create new
90 | var desktop = VirtualDesktop.Create();
91 |
92 | // Remove
93 | desktop.Remove();
94 |
95 | // Switch
96 | desktop.GetLeft().Switch();
97 | ```
98 |
99 | ### Subscribe virtual desktop events
100 | ```csharp
101 | // Notification of desktop switching
102 | VirtualDesktop.CurrentChanged += (_, args) => Console.WriteLine($"Switched: {args.NewDesktop.Name}");
103 |
104 | // Notification of desktop creating
105 | VirtualDesktop.Created += (_, desktop) => desktop.Switch();
106 | ```
107 |
108 | ### for WPF window
109 | ```csharp
110 | // Need to install 'VirtualDesktop.WPF' package
111 |
112 | // Check whether a window is on the current desktop.
113 | var isCurrent = window.IsCurrentVirtualDesktop();
114 |
115 | // Get Virtual Desktop for WPF window
116 | var desktop = window.GetCurrentDesktop();
117 |
118 | // Move window to specific Virtual Desktop
119 | window.MoveToDesktop(desktop);
120 |
121 | // Pin window
122 | window.Pin()
123 | ```
124 |
125 | ### See also:
126 | * [samples/README.md](samples/README.md)
127 |
128 |
129 | ## License
130 |
131 | This library is under [the MIT License](https://github.com/Grabacr07/VirtualDesktop/blob/master/LICENSE).
132 |
--------------------------------------------------------------------------------
/samples/README.md:
--------------------------------------------------------------------------------
1 | ## Samples
2 |
3 | * [VirtualDesktop.Showcase](VirtualDesktop.Showcase) … A simple application uses the VirtualDesktop library, included in this repository.
4 | * [SylphyHorn](https://github.com/Grabacr07/SylphyHorn) … Utility app for Windows by the same author.
5 |
--------------------------------------------------------------------------------
/samples/VirtualDesktop.Showcase/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/samples/VirtualDesktop.Showcase/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace VirtualDesktopShowcase;
7 |
8 | partial class App
9 | {
10 | }
11 |
--------------------------------------------------------------------------------
/samples/VirtualDesktop.Showcase/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
16 |
17 |
18 |
28 |
29 |
32 |
33 |
35 |
37 |
39 |
41 |
42 |
43 |
44 |
47 |
48 |
50 |
52 |
54 |
56 |
58 |
61 |
62 |
65 |
66 |
67 |
68 |
69 |
70 | Foreground window
71 |
72 | (seconds later)
73 |
74 |
75 |
76 |
77 |
78 |
79 |
81 |
83 |
84 |
85 |
145 |
146 |
148 |
149 |
152 |
155 |
158 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/samples/VirtualDesktop.Showcase/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Diagnostics;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Runtime.CompilerServices;
9 | using System.Runtime.InteropServices;
10 | using System.Threading.Tasks;
11 | using System.Windows;
12 | using System.Windows.Controls;
13 | using Microsoft.Win32;
14 | using WindowsDesktop;
15 | using WindowsDesktop.Properties;
16 |
17 | namespace VirtualDesktopShowcase;
18 |
19 | partial class MainWindow
20 | {
21 | private const int _delay = 2000;
22 | private IDisposable? _applicationViewChangedListener;
23 |
24 | public ObservableCollection Desktops { get; } = new();
25 |
26 | public MainWindow()
27 | {
28 | this.InitializeComponent();
29 | this.InitializeComObjects();
30 | }
31 |
32 | private void InitializeComObjects()
33 | {
34 | VirtualDesktop.Configure();
35 |
36 | VirtualDesktop.Created += (_, desktop) =>
37 | {
38 | this.Dispatcher.Invoke(() =>
39 | {
40 | this.Desktops.Add(new VirtualDesktopViewModel(desktop));
41 | Debug.WriteLine($"Created: {desktop.Name}");
42 | });
43 | };
44 |
45 | VirtualDesktop.CurrentChanged += (_, args) =>
46 | {
47 | foreach (var desktop in this.Desktops) desktop.IsCurrent = desktop.Id == args.NewDesktop.Id;
48 | Debug.WriteLine($"Switched: {args.OldDesktop.Name} -> {args.NewDesktop.Name}");
49 | };
50 |
51 | VirtualDesktop.Moved += (_, args) =>
52 | {
53 | this.Dispatcher.Invoke(() =>
54 | {
55 | this.Desktops.Move(args.OldIndex, args.NewIndex);
56 | Debug.WriteLine($"Moved: {args.OldIndex} -> {args.NewIndex}, {args.Desktop}");
57 | });
58 | };
59 |
60 | VirtualDesktop.Destroyed += (_, args) =>
61 | {
62 | this.Dispatcher.Invoke(() =>
63 | {
64 | var target = this.Desktops.FirstOrDefault(x => x.Id == args.Destroyed.Id);
65 | if (target != null) this.Desktops.Remove(target);
66 | });
67 | };
68 |
69 | VirtualDesktop.Renamed += (_, args) =>
70 | {
71 | var desktop = this.Desktops.FirstOrDefault(x => x.Id == args.Desktop.Id);
72 | if (desktop != null) desktop.Name = args.Name;
73 | Debug.WriteLine($"Renamed: {args.Desktop}");
74 | };
75 |
76 | VirtualDesktop.WallpaperChanged += (_, args) =>
77 | {
78 | var desktop = this.Desktops.FirstOrDefault(x => x.Id == args.Desktop.Id);
79 | if (desktop != null) desktop.WallpaperPath = new Uri(args.Path);
80 | Debug.WriteLine($"Wallpaper changed: {args.Desktop}, {args.Path}");
81 | };
82 |
83 | var currentId = VirtualDesktop.Current.Id;
84 |
85 | foreach (var desktop in VirtualDesktop.GetDesktops())
86 | {
87 | var vm = new VirtualDesktopViewModel(desktop);
88 | if (desktop.Id == currentId) vm.IsCurrent = true;
89 |
90 | this.Desktops.Add(vm);
91 | }
92 | }
93 |
94 | protected override void OnSourceInitialized(EventArgs e)
95 | {
96 | base.OnSourceInitialized(e);
97 |
98 | this._applicationViewChangedListener = VirtualDesktop.RegisterViewChanged(this.GetHandle(), handle =>
99 | {
100 | this.Dispatcher.Invoke(() =>
101 | {
102 | var parent = VirtualDesktop.FromHwnd(handle);
103 | foreach (var desktop in this.Desktops)
104 | {
105 | desktop.ShowcaseMessage = parent == null
106 | ? "(this window is pinned)"
107 | : desktop.Id == parent.Id
108 | ? "this window is here."
109 | : "";
110 | }
111 | });
112 | });
113 | }
114 |
115 | protected override void OnClosed(EventArgs e)
116 | {
117 | this._applicationViewChangedListener?.Dispose();
118 | base.OnClosed(e);
119 | }
120 |
121 | private void CreateNew(object sender, RoutedEventArgs e)
122 | => VirtualDesktop.Create();
123 |
124 | private async void CreateNewAndMove(object sender, RoutedEventArgs e)
125 | {
126 | var desktop = VirtualDesktop.Create();
127 |
128 | if (this.ThisWindowMenu.IsChecked ?? true)
129 | {
130 | desktop.SwitchAndMove(this);
131 | }
132 | else
133 | {
134 | await Task.Delay(_delay);
135 |
136 | var handle = GetForegroundWindow();
137 | if (VirtualDesktop.IsPinnedWindow(handle) == false) VirtualDesktop.MoveToDesktop(handle, desktop);
138 | desktop.Switch();
139 | }
140 | }
141 |
142 | private void SwitchLeft(object sender, RoutedEventArgs e)
143 | {
144 | VirtualDesktop.Current.GetLeft()?.Switch();
145 | }
146 |
147 | private async void SwitchLeftAndMove(object sender, RoutedEventArgs e)
148 | {
149 | var left = VirtualDesktop.Current.GetLeft();
150 | if (left == null) return;
151 |
152 | if (this.ThisWindowMenu.IsChecked ?? true)
153 | {
154 | left.SwitchAndMove(this);
155 | }
156 | else
157 | {
158 | await Task.Delay(_delay);
159 |
160 | var handle = GetForegroundWindow();
161 | if (VirtualDesktop.IsPinnedWindow(handle) == false) VirtualDesktop.MoveToDesktop(handle, left);
162 | left.Switch();
163 | }
164 | }
165 |
166 | private void SwitchRight(object sender, RoutedEventArgs e)
167 | {
168 | VirtualDesktop.Current.GetRight()?.Switch();
169 | }
170 |
171 | private async void SwitchRightAndMove(object sender, RoutedEventArgs e)
172 | {
173 | var right = VirtualDesktop.Current.GetRight();
174 | if (right == null) return;
175 |
176 | if (this.ThisWindowMenu.IsChecked ?? true)
177 | {
178 | right.SwitchAndMove(this);
179 | }
180 | else
181 | {
182 | await Task.Delay(_delay);
183 |
184 | var handle = GetForegroundWindow();
185 | if (VirtualDesktop.IsPinnedWindow(handle) == false) VirtualDesktop.MoveToDesktop(handle, right);
186 | right.Switch();
187 | }
188 | }
189 |
190 | private async void Pin(object sender, RoutedEventArgs e)
191 | {
192 | if (this.ThisWindowMenu.IsChecked ?? true)
193 | {
194 | this.TogglePin();
195 | }
196 | else
197 | {
198 | await Task.Delay(_delay);
199 |
200 | var handle = GetForegroundWindow();
201 | (VirtualDesktop.IsPinnedWindow(handle) ? VirtualDesktop.UnpinWindow : (Func)VirtualDesktop.PinWindow)(handle);
202 | }
203 | }
204 |
205 | private async void PinApp(object sender, RoutedEventArgs e)
206 | {
207 | if (this.ThisWindowMenu.IsChecked ?? true)
208 | {
209 | Application.Current.TogglePin();
210 | }
211 | else
212 | {
213 | await Task.Delay(_delay);
214 |
215 | if (VirtualDesktop.TryGetAppUserModelId(GetForegroundWindow(), out var appId))
216 | {
217 | (VirtualDesktop.IsPinnedApplication(appId) ? VirtualDesktop.UnpinApplication : (Func)VirtualDesktop.PinApplication)(appId);
218 | }
219 | }
220 | }
221 |
222 | private void Remove(object sender, RoutedEventArgs e)
223 | {
224 | VirtualDesktop.Current.Remove();
225 | }
226 |
227 | private void SwitchDesktop(object sender, RoutedEventArgs e)
228 | {
229 | if (sender is Button { DataContext: VirtualDesktopViewModel vm })
230 | {
231 | VirtualDesktop.FromId(vm.Id)?.SwitchAndMove(this);
232 | }
233 | }
234 |
235 | private void ChangeWallpaper(object sender, RoutedEventArgs e)
236 | {
237 | if (sender is Button { DataContext: VirtualDesktopViewModel vm })
238 | {
239 | var dialog = new OpenFileDialog()
240 | {
241 | Title = "Select wallpaper",
242 | Filter = "Desktop wallpaper (*.jpg, *.png, *.bmp)|*.jpg;*.png;*.bmp",
243 | };
244 |
245 | if ((dialog.ShowDialog(this) ?? false)
246 | && File.Exists(dialog.FileName))
247 | {
248 | var desktop = VirtualDesktop.FromId(vm.Id);
249 | if (desktop != null) desktop.WallpaperPath = dialog.FileName;
250 | }
251 | }
252 |
253 | e.Handled = true;
254 | }
255 |
256 | [DllImport("user32.dll")]
257 | private static extern IntPtr GetForegroundWindow();
258 | }
259 |
260 | public class VirtualDesktopViewModel : INotifyPropertyChanged
261 | {
262 | private string _name;
263 | private Uri? _wallpaperPath;
264 | private string _showcaseMessage;
265 | private bool _isCurrent;
266 |
267 | public event PropertyChangedEventHandler? PropertyChanged;
268 |
269 | public Guid Id { get; }
270 |
271 | public string Name
272 | {
273 | get => this._name;
274 | set
275 | {
276 | if (this._name != value)
277 | {
278 | this._name = value;
279 | this.OnPropertyChanged();
280 | }
281 | }
282 | }
283 |
284 | public Uri? WallpaperPath
285 | {
286 | get => this._wallpaperPath;
287 | set
288 | {
289 | if (this._wallpaperPath != value)
290 | {
291 | this._wallpaperPath = value;
292 | this.OnPropertyChanged();
293 | }
294 | }
295 | }
296 |
297 | public string ShowcaseMessage
298 | {
299 | get => this._showcaseMessage;
300 | set
301 | {
302 | if (this._showcaseMessage != value)
303 | {
304 | this._showcaseMessage = value;
305 | this.OnPropertyChanged();
306 | }
307 | }
308 | }
309 |
310 | public bool IsCurrent
311 | {
312 | get => this._isCurrent;
313 | set
314 | {
315 | if (this._isCurrent != value)
316 | {
317 | this._isCurrent = value;
318 | this.OnPropertyChanged();
319 | }
320 | }
321 | }
322 |
323 | public VirtualDesktopViewModel(VirtualDesktop source)
324 | {
325 | this._name = string.IsNullOrEmpty(source.Name) ? "(no name)" : source.Name;
326 | this._wallpaperPath = Uri.TryCreate(source.WallpaperPath, UriKind.Absolute, out var uri) ? uri : null;
327 | this._showcaseMessage = "";
328 | this.Id = source.Id;
329 | }
330 |
331 | protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
332 | {
333 | this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/samples/VirtualDesktop.Showcase/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using System.Windows;
3 |
4 | [assembly: ComVisible(false)]
5 | [assembly: Guid("5B4544B8-3EF0-4E9F-8D60-DD605AD99725")]
6 | [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
7 |
--------------------------------------------------------------------------------
/samples/VirtualDesktop.Showcase/VirtualDesktop.Showcase.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0-windows10.0.19041.0
6 | true
7 | enable
8 | VirtualDesktopShowcase
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/VirtualDesktop (LocalAppData).lnk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Grabacr07/VirtualDesktop/a6c69e420307e0717f296501c1e7595977e27b6b/src/VirtualDesktop (LocalAppData).lnk
--------------------------------------------------------------------------------
/src/VirtualDesktop.WPF/ApplicationExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows;
5 |
6 | namespace WindowsDesktop;
7 |
8 | public static class ApplicationExtensions
9 | {
10 | ///
11 | /// Determines whether this application is pinned.
12 | ///
13 | /// if pinned, otherwise.
14 | public static bool IsPinned(this Application app)
15 | {
16 | return VirtualDesktop.TryGetAppUserModelId(app.GetWindowHandle(), out var appId)
17 | && VirtualDesktop.IsPinnedApplication(appId);
18 | }
19 |
20 | ///
21 | /// Pins an application, showing it on all virtual desktops.
22 | ///
23 | /// if already pinned or successfully pinned, otherwise (most of the time, main window is not found).
24 | public static bool Pin(this Application app)
25 | {
26 | return VirtualDesktop.TryGetAppUserModelId(app.GetWindowHandle(), out var appId)
27 | && VirtualDesktop.PinApplication(appId);
28 | }
29 |
30 | ///
31 | /// Unpins an application.
32 | ///
33 | /// if already unpinned or successfully unpinned, otherwise (most of the time, main window is not found).
34 | public static bool Unpin(this Application app)
35 | {
36 | return VirtualDesktop.TryGetAppUserModelId(app.GetWindowHandle(), out var appId)
37 | && VirtualDesktop.UnpinApplication(appId);
38 | }
39 |
40 | ///
41 | /// Toggles an application between being pinned and unpinned.
42 | ///
43 | /// if successfully toggled, otherwise (most of the time, main window is not found).
44 | public static bool TogglePin(this Application app)
45 | {
46 | if (VirtualDesktop.TryGetAppUserModelId(app.GetWindowHandle(), out var appId) == false) return false;
47 |
48 | return VirtualDesktop.IsPinnedApplication(appId)
49 | ? VirtualDesktop.UnpinApplication(appId)
50 | : VirtualDesktop.PinApplication(appId);
51 | }
52 |
53 | private static IntPtr GetWindowHandle(this Application app)
54 | => app.MainWindow?.GetHandle()
55 | ?? throw new InvalidOperationException();
56 | }
57 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.WPF/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | [assembly: ComVisible(false)]
4 | [assembly: Guid("9dd597c6-065a-4764-a96c-1b18c4eded78")]
5 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.WPF/VirtualDesktop.WPF.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0-windows10.0.19041.0;net5.0-windows10.0.19041.0
5 | latest
6 | true
7 | enable
8 | enable
9 | 5.0.5
10 | VirtualDesktop
11 | Grabacr07
12 | grabacr.net
13 | Copyright © 2022 Manato KAMEYA
14 | C# Wrapper for the Virtual Desktop API on Windows 11 (and Windows 10).
15 | https://github.com/Grabacr07/VirtualDesktop
16 | https://github.com/Grabacr07/VirtualDesktop
17 | LICENSE
18 | README.md
19 | Windows;Windows10;Windows11;Desktop;VirtualDesktop;
20 | True
21 | WindowsDesktop
22 |
23 |
24 |
25 | 1701;1702;1591
26 |
27 |
28 |
29 | 1701;1702;1591
30 |
31 |
32 |
33 | 1701;1702;1591
34 |
35 |
36 |
37 | 1701;1702;1591
38 |
39 |
40 |
41 |
42 | True
43 |
44 |
45 |
46 | True
47 | \
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.WPF/WindowExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows;
5 | using System.Windows.Interop;
6 | using System.Windows.Media;
7 |
8 | namespace WindowsDesktop;
9 |
10 | public static class WindowExtensions
11 | {
12 | ///
13 | /// Determines whether this window is on the current virtual desktop.
14 | ///
15 | public static bool IsCurrentVirtualDesktop(this Window window)
16 | {
17 | return VirtualDesktop.IsCurrentVirtualDesktop(window.GetHandle());
18 | }
19 |
20 | ///
21 | /// Returns the virtual desktop this window is located on.
22 | ///
23 | public static VirtualDesktop? GetCurrentDesktop(this Window window)
24 | {
25 | return VirtualDesktop.FromHwnd(window.GetHandle());
26 | }
27 |
28 | ///
29 | /// Moves a window to the specified virtual desktop.
30 | ///
31 | public static void MoveToDesktop(this Window window, VirtualDesktop virtualDesktop)
32 | {
33 | VirtualDesktop.MoveToDesktop(window.GetHandle(), virtualDesktop);
34 | }
35 |
36 | ///
37 | /// Switches to a virtual desktop and moves the specified window to that desktop.
38 | ///
39 | /// The virtual desktop to move the window to.
40 | /// The window to move.
41 | public static void SwitchAndMove(this VirtualDesktop virtualDesktop, Window window)
42 | {
43 | if (window.IsPinned() == false) window.MoveToDesktop(virtualDesktop);
44 | virtualDesktop.Switch();
45 | }
46 |
47 | ///
48 | /// Determines whether this window is pinned.
49 | ///
50 | /// if pinned, otherwise.
51 | public static bool IsPinned(this Window window)
52 | {
53 | return VirtualDesktop.IsPinnedWindow(window.GetHandle());
54 | }
55 |
56 | ///
57 | /// Pins a window, showing it on all virtual desktops.
58 | ///
59 | /// if already pinned or successfully pinned, otherwise (most of the time, the target window is not found or not ready).
60 | public static bool Pin(this Window window)
61 | {
62 | return VirtualDesktop.PinWindow(window.GetHandle());
63 | }
64 |
65 | ///
66 | /// Unpins a window.
67 | ///
68 | /// if already unpinned or successfully unpinned, otherwise (most of the time, the target window is not found or not ready).
69 | public static bool Unpin(this Window window)
70 | {
71 | return VirtualDesktop.UnpinWindow(window.GetHandle());
72 | }
73 |
74 | ///
75 | /// Toggles a window between being pinned and unpinned.
76 | ///
77 | /// if successfully toggled, otherwise (most of the time, the target window is not found or not ready).
78 | public static bool TogglePin(this Window window)
79 | {
80 | var handle = window.GetHandle();
81 |
82 | return VirtualDesktop.IsPinnedWindow(handle)
83 | ? VirtualDesktop.UnpinWindow(handle)
84 | : VirtualDesktop.PinWindow(handle);
85 | }
86 |
87 | ///
88 | /// Returns the window handle for this .
89 | ///
90 | public static IntPtr GetHandle(this Visual visual)
91 | => PresentationSource.FromVisual(visual) is HwndSource hwndSource
92 | ? hwndSource.Handle
93 | : throw new ArgumentException("Unable to get a window handle. Call it after the Window.SourceInitialized event is fired.", nameof(visual));
94 | }
95 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.WinForms/FormExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace WindowsDesktop;
7 |
8 | public static class FormExtensions
9 | {
10 | ///
11 | /// Determines whether this form is on the current virtual desktop.
12 | ///
13 | public static bool IsCurrentVirtualDesktop(this Form form)
14 | {
15 | return VirtualDesktop.IsCurrentVirtualDesktop(form.Handle);
16 | }
17 |
18 | ///
19 | /// Moves a form to the specified virtual desktop.
20 | ///
21 | public static void MoveToDesktop(this Form form, VirtualDesktop virtualDesktop)
22 | {
23 | VirtualDesktop.MoveToDesktop(form.Handle, virtualDesktop);
24 | }
25 |
26 | ///
27 | /// Returns the virtual desktop this form is located on.
28 | ///
29 | public static VirtualDesktop? GetCurrentDesktop(this Form form)
30 | {
31 | return VirtualDesktop.FromHwnd(form.Handle);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.WinForms/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | [assembly: ComVisible(false)]
4 | [assembly: Guid("da586cec-2ffe-42c5-aeda-56d25984c7ad")]
5 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.WinForms/VirtualDesktop.WinForms.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0-windows10.0.19041.0;net5.0-windows10.0.19041.0
5 | latest
6 | true
7 | enable
8 | enable
9 | 5.0.5
10 | VirtualDesktop
11 | Grabacr07
12 | grabacr.net
13 | Copyright © 2022 Manato KAMEYA
14 | C# Wrapper for the Virtual Desktop API on Windows 11 (and Windows 10).
15 | https://github.com/Grabacr07/VirtualDesktop
16 | https://github.com/Grabacr07/VirtualDesktop
17 | LICENSE
18 | README.md
19 | Windows;Windows10;Windows11;Desktop;VirtualDesktop;
20 | True
21 | WindowsDesktop
22 |
23 |
24 |
25 | 1701;1702;1591
26 |
27 |
28 |
29 | 1701;1702;1591
30 |
31 |
32 |
33 | 1701;1702;1591
34 |
35 |
36 |
37 | 1701;1702;1591
38 |
39 |
40 |
41 |
42 | True
43 |
44 |
45 |
46 | True
47 | \
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.32112.339
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".samples", ".samples", "{17B4686F-1AFC-4D5E-BCD8-408DE4CEC3C3}"
7 | ProjectSection(SolutionItems) = preProject
8 | ..\samples\README.md = ..\samples\README.md
9 | EndProjectSection
10 | EndProject
11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualDesktop.WPF", "VirtualDesktop.WPF\VirtualDesktop.WPF.csproj", "{0C17C595-1669-4333-8153-A04676AA3EF3}"
12 | EndProject
13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualDesktop.Showcase", "..\samples\VirtualDesktop.Showcase\VirtualDesktop.Showcase.csproj", "{EEF46F33-3DDB-4D77-9054-4273332745B4}"
14 | EndProject
15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualDesktop.WinForms", "VirtualDesktop.WinForms\VirtualDesktop.WinForms.csproj", "{4B6FB0EB-943E-42C9-8CC9-990D84A2EEDB}"
16 | EndProject
17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualDesktop", "VirtualDesktop\VirtualDesktop.csproj", "{B8A37B59-0F48-4A44-ADF7-96C54AC6CE61}"
18 | EndProject
19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".config", ".config", "{335CE9BA-A467-4667-8707-D4B779EC8005}"
20 | ProjectSection(SolutionItems) = preProject
21 | ..\.editorconfig = ..\.editorconfig
22 | ..\.gitattributes = ..\.gitattributes
23 | ..\.gitignore = ..\.gitignore
24 | EndProjectSection
25 | EndProject
26 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{A58CDA13-2F14-4F77-AFF3-6F91C7993E5B}"
27 | ProjectSection(SolutionItems) = preProject
28 | ..\.github\workflows\build.yml = ..\.github\workflows\build.yml
29 | ..\.github\workflows\publish.yml = ..\.github\workflows\publish.yml
30 | EndProjectSection
31 | EndProject
32 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".docs", ".docs", "{8A097A9D-BF69-424A-8477-24FD5FE334EF}"
33 | ProjectSection(SolutionItems) = preProject
34 | ..\README.md = ..\README.md
35 | EndProjectSection
36 | EndProject
37 | Global
38 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
39 | Debug|Any CPU = Debug|Any CPU
40 | Release|Any CPU = Release|Any CPU
41 | EndGlobalSection
42 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
43 | {0C17C595-1669-4333-8153-A04676AA3EF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {0C17C595-1669-4333-8153-A04676AA3EF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {0C17C595-1669-4333-8153-A04676AA3EF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {0C17C595-1669-4333-8153-A04676AA3EF3}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {EEF46F33-3DDB-4D77-9054-4273332745B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {EEF46F33-3DDB-4D77-9054-4273332745B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {EEF46F33-3DDB-4D77-9054-4273332745B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {4B6FB0EB-943E-42C9-8CC9-990D84A2EEDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {4B6FB0EB-943E-42C9-8CC9-990D84A2EEDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {4B6FB0EB-943E-42C9-8CC9-990D84A2EEDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {4B6FB0EB-943E-42C9-8CC9-990D84A2EEDB}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {B8A37B59-0F48-4A44-ADF7-96C54AC6CE61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {B8A37B59-0F48-4A44-ADF7-96C54AC6CE61}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {B8A37B59-0F48-4A44-ADF7-96C54AC6CE61}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {B8A37B59-0F48-4A44-ADF7-96C54AC6CE61}.Release|Any CPU.Build.0 = Release|Any CPU
58 | EndGlobalSection
59 | GlobalSection(SolutionProperties) = preSolution
60 | HideSolutionNode = FALSE
61 | EndGlobalSection
62 | GlobalSection(NestedProjects) = preSolution
63 | {EEF46F33-3DDB-4D77-9054-4273332745B4} = {17B4686F-1AFC-4D5E-BCD8-408DE4CEC3C3}
64 | EndGlobalSection
65 | GlobalSection(ExtensibilityGlobals) = postSolution
66 | SolutionGuid = {0EDF8EBE-5CA7-414F-B7EA-04FC9D5D0FE7}
67 | EndGlobalSection
68 | EndGlobal
69 |
--------------------------------------------------------------------------------
/src/VirtualDesktop.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
3 | SUGGESTION
4 | SUGGESTION
5 | SUGGESTION
6 | SUGGESTION
7 | SUGGESTION
8 | DO_NOT_SHOW
9 | DO_NOT_SHOW
10 | DO_NOT_SHOW
11 | DO_NOT_SHOW
12 | DO_NOT_SHOW
13 | HINT
14 | HINT
15 | HINT
16 | HINT
17 | HINT
18 | HINT
19 | HINT
20 | HINT
21 | HINT
22 | HINT
23 | HINT
24 | HINT
25 | HINT
26 | HINT
27 | HINT
28 | SUGGESTION
29 | SUGGESTION
30 | SUGGESTION
31 | <?xml version="1.0" encoding="utf-16"?><Profile name="Default"><CSReorderTypeMembers>True</CSReorderTypeMembers><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="False" /><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><XMLReformatCode>True</XMLReformatCode></Profile>
32 | NEVER
33 | NEVER
34 | NEVER
35 | ALWAYS
36 | False
37 | True
38 | ZeroIndent
39 | OnSingleLine
40 | OnSingleLine
41 | False
42 | False
43 |
44 |
45 | 2
46 | True
47 | OnSingleLine
48 | 2
49 | FirstAttributeOnSingleLine
50 |
51 | False
52 | System
53 | System.Collections.Generic
54 | System.Linq
55 | ID
56 | IID
57 |
58 |
59 | OS
60 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AA_BB" /></Policy>
61 | <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
62 | <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
63 |
64 | 1
65 | 1
66 | 1
67 | ON_SINGLE_LINE
68 | False
69 |
70 |
71 |
72 | CHOP_ALWAYS
73 | CHOP_IF_LONG
74 | True
75 |
76 | False
77 | False
78 | False
79 | False
80 | False
81 | False
82 | True
83 | True
84 | True
85 | True
86 | False
87 | False
88 | True
89 | True
90 | 15
91 | 996
92 | Required
93 | Required
94 | Required
95 | NotRequired
96 |
97 |
98 | OneStep
99 | ZeroIndent
100 | <?xml version="1.0" encoding="utf-16"?>
101 | <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
102 | <TypePattern DisplayName="COM interfaces or structs">
103 | <TypePattern.Match>
104 | <Or>
105 | <And>
106 | <Kind Is="Interface" />
107 | <Or>
108 | <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" />
109 | <HasAttribute Name="System.Runtime.InteropServices.ComImport" />
110 | </Or>
111 | </And>
112 | <Kind Is="Struct" />
113 | </Or>
114 | </TypePattern.Match>
115 | </TypePattern>
116 | <TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All">
117 | <TypePattern.Match>
118 | <And>
119 | <Kind Is="Class" />
120 | <HasMember>
121 | <And>
122 | <Kind Is="Method" />
123 | <HasAttribute Name="Xunit.FactAttribute" Inherited="True" />
124 | </And>
125 | </HasMember>
126 | </And>
127 | </TypePattern.Match>
128 | <Entry DisplayName="Setup/Teardown Methods">
129 | <Entry.Match>
130 | <Or>
131 | <Kind Is="Constructor" />
132 | <And>
133 | <Kind Is="Method" />
134 | <ImplementsInterface Name="System.IDisposable" />
135 | </And>
136 | </Or>
137 | </Entry.Match>
138 | <Entry.SortBy>
139 | <Kind Order="Constructor" />
140 | </Entry.SortBy>
141 | </Entry>
142 | <Entry DisplayName="All other members" />
143 | <Entry Priority="100" DisplayName="Test Methods">
144 | <Entry.Match>
145 | <And>
146 | <Kind Is="Method" />
147 | <HasAttribute Name="Xunit.FactAttribute" />
148 | </And>
149 | </Entry.Match>
150 | <Entry.SortBy>
151 | <Name />
152 | </Entry.SortBy>
153 | </Entry>
154 | </TypePattern>
155 | <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All">
156 | <TypePattern.Match>
157 | <And>
158 | <Kind Is="Class" />
159 | <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" />
160 | </And>
161 | </TypePattern.Match>
162 | <Entry DisplayName="Setup/Teardown Methods">
163 | <Entry.Match>
164 | <And>
165 | <Kind Is="Method" />
166 | <Or>
167 | <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" />
168 | <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" />
169 | <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" />
170 | <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" />
171 | </Or>
172 | </And>
173 | </Entry.Match>
174 | </Entry>
175 | <Entry DisplayName="All other members" />
176 | <Entry Priority="100" DisplayName="Test Methods">
177 | <Entry.Match>
178 | <And>
179 | <Kind Is="Method" />
180 | <HasAttribute Name="NUnit.Framework.TestAttribute" />
181 | </And>
182 | </Entry.Match>
183 | <Entry.SortBy>
184 | <Name />
185 | </Entry.SortBy>
186 | </Entry>
187 | </TypePattern>
188 | <TypePattern DisplayName="Default Pattern">
189 | <Entry DisplayName="Namespaces">
190 | <Entry.Match>
191 | <Kind Is="Namespace" />
192 | </Entry.Match>
193 | </Entry>
194 | <Entry DisplayName="Classes">
195 | <Entry.Match>
196 | <Kind Is="Class" />
197 | </Entry.Match>
198 | </Entry>
199 | <Entry DisplayName="Structs">
200 | <Entry.Match>
201 | <Kind Is="Struct" />
202 | </Entry.Match>
203 | </Entry>
204 | <Entry DisplayName="Interfaces">
205 | <Entry.Match>
206 | <Kind Is="Interface" />
207 | </Entry.Match>
208 | </Entry>
209 | <Entry DisplayName="Delegates">
210 | <Entry.Match>
211 | <Kind Is="Delegate" />
212 | </Entry.Match>
213 | </Entry>
214 | <Entry DisplayName="Enums">
215 | <Entry.Match>
216 | <Kind Is="Enum" />
217 | </Entry.Match>
218 | </Entry>
219 | <Entry DisplayName="Constants">
220 | <Entry.Match>
221 | <Kind Is="Constant" />
222 | </Entry.Match>
223 | </Entry>
224 | <Entry DisplayName="Fields">
225 | <Entry.Match>
226 | <And>
227 | <Kind Is="Field" />
228 | <Not>
229 | <Static />
230 | </Not>
231 | </And>
232 | </Entry.Match>
233 | <Entry.SortBy>
234 | <Static />
235 | <Readonly />
236 | </Entry.SortBy>
237 | </Entry>
238 | <Entry DisplayName="Indexers">
239 | <Entry.Match>
240 | <And>
241 | <Kind Is="Indexer" />
242 | </And>
243 | </Entry.Match>
244 | <Entry.SortBy>
245 | <Static />
246 | <ImplementsInterface />
247 | </Entry.SortBy>
248 | </Entry>
249 | <Entry DisplayName="Properties">
250 | <Entry.Match>
251 | <And>
252 | <Kind Is="Property" />
253 | </And>
254 | </Entry.Match>
255 | <Entry.SortBy>
256 | <Static />
257 | <ImplementsInterface />
258 | </Entry.SortBy>
259 | </Entry>
260 | <Entry DisplayName="Events">
261 | <Entry.Match>
262 | <Kind Is="Event" />
263 | </Entry.Match>
264 | <Entry.SortBy>
265 | <Static />
266 | <ImplementsInterface />
267 | </Entry.SortBy>
268 | </Entry>
269 | <Entry DisplayName="Operators">
270 | <Entry.Match>
271 | <Kind Is="Operator" />
272 | </Entry.Match>
273 | </Entry>
274 | <Entry DisplayName="Constructors">
275 | <Entry.Match>
276 | <Kind Is="Constructor" />
277 | </Entry.Match>
278 | </Entry>
279 | <Entry DisplayName="Destructor">
280 | <Entry.Match>
281 | <Kind Is="Destructor" />
282 | </Entry.Match>
283 | </Entry>
284 | <Entry DisplayName="All other members">
285 | <Entry.SortBy>
286 | <Kind Is="Member" />
287 | <Static />
288 | <ImplementsInterface />
289 | </Entry.SortBy>
290 | </Entry>
291 | <Region Name="Implicit Implementations">
292 | <Entry Priority="100" DisplayName="Implicit Interface Implementations">
293 | <Entry.Match>
294 | <And>
295 | <Kind Is="Member" />
296 | <ImplementsInterface />
297 | <Access Is="Private" />
298 | </And>
299 | </Entry.Match>
300 | <Entry.SortBy>
301 | <ImplementsInterface Immediate="True" />
302 | </Entry.SortBy>
303 | </Entry>
304 | </Region>
305 | </TypePattern>
306 | </Patterns>
307 | True
308 | True
309 | True
310 | True
311 | True
312 | True
313 | True
314 | True
315 | True
316 | True
317 | True
318 | True
319 | (?<=\b)(?<TAG>NotImplementedException|SqlNotImplemented)(\b)(.*)
320 | True
321 | True
322 | Red
323 | True
324 | True
325 | True
326 | To be determined
327 | \bTBD\b
328 | Edit
329 | True
330 | True
331 | True
332 | True
333 | True
334 | True
335 | True
336 | True
337 | True
338 | True
339 | True
340 | True
341 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.Provider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using WindowsDesktop.Interop.Proxy;
5 | using WindowsDesktop.Properties;
6 |
7 | namespace WindowsDesktop.Interop.Build10240;
8 |
9 | internal class VirtualDesktopProvider10240 : VirtualDesktopProvider
10 | {
11 | private IVirtualDesktopManager? _virtualDesktopManager;
12 | private ApplicationViewCollection? _applicationViewCollection;
13 | private VirtualDesktopManagerInternal? _virtualDesktopManagerInternal;
14 | private VirtualDesktopPinnedApps? _virtualDesktopPinnedApps;
15 | private VirtualDesktopNotificationService? _virtualDesktopNotificationService;
16 |
17 | public override IApplicationViewCollection ApplicationViewCollection
18 | => this._applicationViewCollection ?? throw InitializationIsRequired;
19 |
20 | public override IVirtualDesktopManager VirtualDesktopManager
21 | => this._virtualDesktopManager ?? throw InitializationIsRequired;
22 |
23 | public override IVirtualDesktopManagerInternal VirtualDesktopManagerInternal
24 | => this._virtualDesktopManagerInternal ?? throw InitializationIsRequired;
25 |
26 | public override IVirtualDesktopPinnedApps VirtualDesktopPinnedApps
27 | => this._virtualDesktopPinnedApps ?? throw InitializationIsRequired;
28 |
29 | public override IVirtualDesktopNotificationService VirtualDesktopNotificationService
30 | => this._virtualDesktopNotificationService ?? throw InitializationIsRequired;
31 |
32 | private protected override void InitializeCore(ComInterfaceAssembly assembly)
33 | {
34 | var type = Type.GetTypeFromCLSID(CLSID.VirtualDesktopManager)
35 | ?? throw new Exception($"No type found for CLSID '{CLSID.VirtualDesktopManager}'.");
36 | this._virtualDesktopManager = Activator.CreateInstance(type) is IVirtualDesktopManager manager
37 | ? manager
38 | : throw new Exception($"Failed to create instance of Type '{typeof(IVirtualDesktopManager)}'.");
39 |
40 | this._applicationViewCollection = new ApplicationViewCollection(assembly);
41 | var factory = new ComWrapperFactory(
42 | x => new ApplicationView(assembly, x),
43 | x => this._applicationViewCollection.GetViewForHwnd(x),
44 | x => new VirtualDesktop(assembly, x));
45 | this._virtualDesktopManagerInternal = new VirtualDesktopManagerInternal(assembly, factory);
46 | this._virtualDesktopPinnedApps = new VirtualDesktopPinnedApps(assembly, factory);
47 | this._virtualDesktopNotificationService = new VirtualDesktopNotificationService(assembly, factory);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("VirtualDesktop.{OS_BUILD}.generated")]
5 | [assembly: AssemblyCompany("grabacr.net")]
6 | [assembly: AssemblyProduct("VirtualDesktop")]
7 | [assembly: AssemblyDescription("COM interface definitions for virtual desktop on Windows 11 build {VERSION}.")]
8 | [assembly: AssemblyCopyright("Copyright © 2022 Manato KAMEYA")]
9 |
10 | [assembly: AssemblyVersion("{ASSEMBLY_VERSION}")]
11 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IApplicationView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | // ## Fixes for breaking changes in .NET 5
7 | // * InterfaceIsIInspectable -> InterfaceIsIUnknown
8 | // * Add three dummy entries to the start of the interface; Proc3() - Proc5()
9 | //
10 | // see also: https://docs.microsoft.com/en-us/dotnet/core/compatibility/interop/5.0/casting-rcw-to-inspectable-interface-throws-exception
11 |
12 | [ComImport]
13 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
14 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
15 | public interface IApplicationView
16 | {
17 | void Proc3();
18 |
19 | void Proc4();
20 |
21 | void Proc5();
22 |
23 | void SetFocus();
24 |
25 | void SwitchTo();
26 |
27 | void TryInvokeBack(IntPtr callback);
28 |
29 | IntPtr GetThumbnailWindow();
30 |
31 | IntPtr GetMonitor();
32 |
33 | int GetVisibility();
34 |
35 | void SetCloak(ApplicationViewCloakType cloakType, int unknown);
36 |
37 | IntPtr GetPosition(in Guid guid, out IntPtr position);
38 |
39 | void SetPosition(in IntPtr position);
40 |
41 | void InsertAfterWindow(IntPtr hwnd);
42 |
43 | Rect GetExtendedFramePosition();
44 |
45 | [return: MarshalAs(UnmanagedType.LPWStr)]
46 | string GetAppUserModelId();
47 |
48 | void SetAppUserModelId([MarshalAs(UnmanagedType.LPWStr)] string id);
49 |
50 | bool IsEqualByAppUserModelId(string id);
51 |
52 | uint GetViewState();
53 |
54 | void SetViewState(uint state);
55 |
56 | int GetNeediness();
57 |
58 | ulong GetLastActivationTimestamp();
59 |
60 | void SetLastActivationTimestamp(ulong timestamp);
61 |
62 | Guid GetVirtualDesktopId();
63 |
64 | void SetVirtualDesktopId(in Guid guid);
65 |
66 | int GetShowInSwitchers();
67 |
68 | void SetShowInSwitchers(int flag);
69 |
70 | int GetScaleFactor();
71 |
72 | bool CanReceiveInput();
73 |
74 | ApplicationViewCompatibilityPolicy GetCompatibilityPolicyType();
75 |
76 | void SetCompatibilityPolicyType(ApplicationViewCompatibilityPolicy flags);
77 |
78 | IntPtr GetPositionPriority();
79 |
80 | void SetPositionPriority(IntPtr priority);
81 |
82 | void GetSizeConstraints(IntPtr monitor, out Size size1, out Size size2);
83 |
84 | void GetSizeConstraintsForDpi(uint uint1, out Size size1, out Size size2);
85 |
86 | void SetSizeConstraintsForDpi(ref uint uint1, in Size size1, in Size size2);
87 |
88 | int QuerySizeConstraintsFromApp();
89 |
90 | void OnMinSizePreferencesUpdated(IntPtr hwnd);
91 |
92 | void ApplyOperation(IntPtr operation);
93 |
94 | bool IsTray();
95 |
96 | bool IsInHighZOrderBand();
97 |
98 | bool IsSplashScreenPresented();
99 |
100 | void Flash();
101 |
102 | IApplicationView GetRootSwitchableOwner();
103 |
104 | IObjectArray EnumerateOwnershipTree();
105 |
106 | [return: MarshalAs(UnmanagedType.LPWStr)]
107 | string GetEnterpriseId();
108 |
109 | bool IsMirrored();
110 | }
111 |
112 | [StructLayout(LayoutKind.Sequential)]
113 | public struct Size
114 | {
115 | public int X;
116 | public int Y;
117 | }
118 |
119 | [StructLayout(LayoutKind.Sequential)]
120 | public struct Rect
121 | {
122 | public int Left;
123 | public int Top;
124 | public int Right;
125 | public int Bottom;
126 | }
127 |
128 | public enum ApplicationViewCloakType
129 | {
130 | AVCT_NONE = 0,
131 | AVCT_DEFAULT = 1,
132 | AVCT_VIRTUAL_DESKTOP = 2
133 | }
134 |
135 | public enum ApplicationViewCompatibilityPolicy
136 | {
137 | AVCP_NONE = 0,
138 | AVCP_SMALL_SCREEN = 1,
139 | AVCP_TABLET_SMALL_SCREEN = 2,
140 | AVCP_VERY_SMALL_SCREEN = 3,
141 | AVCP_HIGH_SCALE_FACTOR = 4
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IApplicationViewCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | [ComImport]
7 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
8 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
9 | public interface IApplicationViewCollection
10 | {
11 | IObjectArray GetViews();
12 |
13 | IObjectArray GetViewsByZOrder();
14 |
15 | IObjectArray GetViewsByAppUserModelId(string id);
16 |
17 | IApplicationView GetViewForHwnd(IntPtr hwnd);
18 |
19 | IApplicationView GetViewForApplication(object application);
20 |
21 | IApplicationView GetViewForAppUserModelId(string id);
22 |
23 | IntPtr GetViewInFocus();
24 |
25 | void RefreshCollection();
26 |
27 | int RegisterForApplicationViewChanges(object listener);
28 |
29 | int RegisterForApplicationViewPositionChanges(object listener);
30 |
31 | void UnregisterForApplicationViewChanges(int cookie);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IVirtualDesktop.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | [ComImport]
7 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
8 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
9 | public interface IVirtualDesktop
10 | {
11 | bool IsViewVisible(IApplicationView view);
12 |
13 | Guid GetID();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IVirtualDesktopManagerInternal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | [ComImport]
7 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
8 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
9 | public interface IVirtualDesktopManagerInternal
10 | {
11 | int GetCount();
12 |
13 | void MoveViewToDesktop(IApplicationView pView, IVirtualDesktop desktop);
14 |
15 | bool CanViewMoveDesktops(IApplicationView pView);
16 |
17 | IVirtualDesktop GetCurrentDesktop();
18 |
19 | IObjectArray GetDesktops();
20 |
21 | IVirtualDesktop GetAdjacentDesktop(IVirtualDesktop pDesktopReference, int uDirection);
22 |
23 | void SwitchDesktop(IVirtualDesktop desktop);
24 |
25 | IVirtualDesktop CreateDesktop();
26 |
27 | void RemoveDesktop(IVirtualDesktop pRemove, IVirtualDesktop pFallbackDesktop);
28 |
29 | IVirtualDesktop FindDesktop(in Guid desktopId);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IVirtualDesktopNotification.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | [ComImport]
7 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
8 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
9 | public interface IVirtualDesktopNotification
10 | {
11 | void VirtualDesktopCreated(IVirtualDesktop pDesktop);
12 |
13 | void VirtualDesktopDestroyBegin(IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback);
14 |
15 | void VirtualDesktopDestroyFailed(IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback);
16 |
17 | void VirtualDesktopDestroyed(IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback);
18 |
19 | void ViewVirtualDesktopChanged(IApplicationView pView);
20 |
21 | void CurrentVirtualDesktopChanged(IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew);
22 | }
23 |
24 | internal class VirtualDesktopNotification : VirtualDesktopNotificationService.EventListenerBase, IVirtualDesktopNotification
25 | {
26 | public void VirtualDesktopCreated(IVirtualDesktop pDesktop)
27 | {
28 | this.CreatedCore(pDesktop);
29 | }
30 |
31 | public void VirtualDesktopDestroyBegin(IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback)
32 | {
33 | this.DestroyBeginCore(pDesktopDestroyed, pDesktopFallback);
34 | }
35 |
36 | public void VirtualDesktopDestroyFailed(IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback)
37 | {
38 | this.DestroyFailedCore(pDesktopDestroyed, pDesktopFallback);
39 | }
40 |
41 | public void VirtualDesktopDestroyed(IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback)
42 | {
43 | this.DestroyedCore(pDesktopDestroyed, pDesktopFallback);
44 | }
45 |
46 | public void ViewVirtualDesktopChanged(IApplicationView pView)
47 | {
48 | this.ViewChangedCore(pView);
49 | }
50 |
51 | public void CurrentVirtualDesktopChanged(IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew)
52 | {
53 | this.CurrentChangedCore(pDesktopOld, pDesktopNew);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IVirtualDesktopNotificationService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | [ComImport]
7 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
8 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
9 | public interface IVirtualDesktopNotificationService
10 | {
11 | uint Register(IVirtualDesktopNotification pNotification);
12 |
13 | void Unregister(uint dwCookie);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/.interfaces/IVirtualDesktopPinnedApps.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace WindowsDesktop.Interop.Build10240
5 | {
6 | [ComImport]
7 | [Guid("00000000-0000-0000-0000-000000000000") /* replace at runtime */]
8 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
9 | public interface IVirtualDesktopPinnedApps
10 | {
11 | bool IsAppIdPinned(string appId);
12 |
13 | void PinAppID(string appId);
14 |
15 | void UnpinAppID(string appId);
16 |
17 | bool IsViewPinned(IApplicationView applicationView);
18 |
19 | void PinView(IApplicationView applicationView);
20 |
21 | void UnpinView(IApplicationView applicationView);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/ApplicationView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using WindowsDesktop.Interop.Proxy;
5 |
6 | namespace WindowsDesktop.Interop.Build10240;
7 |
8 | internal class ApplicationView : ComWrapperBase, IApplicationView
9 | {
10 | public ApplicationView(ComInterfaceAssembly assembly, object comObject)
11 | : base(assembly, comObject)
12 | {
13 | }
14 |
15 | public IntPtr GetThumbnailWindow()
16 | => this.InvokeMethod();
17 |
18 | public string GetAppUserModelId()
19 | => this.InvokeMethod() ?? throw new Exception("Failed to get AppUserModelId.");
20 |
21 | public Guid GetVirtualDesktopId()
22 | => this.InvokeMethod();
23 | }
24 |
--------------------------------------------------------------------------------
/src/VirtualDesktop/Interop/Build10240/ApplicationViewCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using WindowsDesktop.Interop.Proxy;
3 |
4 | namespace WindowsDesktop.Interop.Build10240;
5 |
6 | internal class ApplicationViewCollection : ComWrapperBase, IApplicationViewCollection
7 | {
8 | public ApplicationViewCollection(ComInterfaceAssembly assembly)
9 | : base(assembly)
10 | {
11 | }
12 |
13 | public ApplicationView GetViewForHwnd(IntPtr hWnd)
14 | {
15 | var view = this.InvokeMethod