├── .gitignore
├── LICENSE.txt
├── README.markdown
├── TestVirtualDesktopAccessorWin32
    ├── TestVirtualDesktopAccessorWin32.cpp
    ├── TestVirtualDesktopAccessorWin32.h
    ├── TestVirtualDesktopAccessorWin32.vcxproj
    ├── TestVirtualDesktopAccessorWin32.vcxproj.filters
    ├── stdafx.cpp
    ├── stdafx.h
    └── targetver.h
├── VirtualDesktopAccessor.sln
├── VirtualDesktopAccessor
    ├── VirtualDesktopAccessor.vcxproj
    ├── VirtualDesktopAccessor.vcxproj.filters
    ├── Win10Desktops.h
    ├── dllmain.cpp
    ├── dllmain.def
    ├── dllmain.h
    ├── stdafx.cpp
    ├── stdafx.h
    └── targetver.h
└── x64
    └── Release
        └── VirtualDesktopAccessor.dll
/.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 | *VC.*
 25 | 
 26 | # Visual Studio 2015 cache/options directory
 27 | .vs/
 28 | # Uncomment if you have tasks that create the project's static files in wwwroot
 29 | #wwwroot/
 30 | 
 31 | # MSTest test Results
 32 | [Tt]est[Rr]esult*/
 33 | [Bb]uild[Ll]og.*
 34 | 
 35 | # NUNIT
 36 | *.VisualState.xml
 37 | TestResult.xml
 38 | 
 39 | # Build Results of an ATL Project
 40 | [Dd]ebugPS/
 41 | [Rr]eleasePS/
 42 | dlldata.c
 43 | 
 44 | # DNX
 45 | project.lock.json
 46 | artifacts/
 47 | 
 48 | *_i.c
 49 | *_p.c
 50 | *_i.h
 51 | *.ilk
 52 | *.meta
 53 | *.obj
 54 | *.pch
 55 | *.pdb
 56 | *.pgc
 57 | *.pgd
 58 | *.rsp
 59 | *.sbr
 60 | *.tlb
 61 | *.tli
 62 | *.tlh
 63 | *.tmp
 64 | *.tmp_proj
 65 | *.log
 66 | *.vspscc
 67 | *.vssscc
 68 | .builds
 69 | *.pidb
 70 | *.svclog
 71 | *.scc
 72 | 
 73 | # Chutzpah Test files
 74 | _Chutzpah*
 75 | 
 76 | # Visual C++ cache files
 77 | ipch/
 78 | *.aps
 79 | *.ncb
 80 | *.opensdf
 81 | *.sdf
 82 | *.cachefile
 83 | 
 84 | # Visual Studio profiler
 85 | *.psess
 86 | *.vsp
 87 | *.vspx
 88 | *.sap
 89 | 
 90 | # TFS 2012 Local Workspace
 91 | $tf/
 92 | 
 93 | # Guidance Automation Toolkit
 94 | *.gpState
 95 | 
 96 | # ReSharper is a .NET coding add-in
 97 | _ReSharper*/
 98 | *.[Rr]e[Ss]harper
 99 | *.DotSettings.user
100 | 
101 | # JustCode is a .NET coding add-in
102 | .JustCode
103 | 
104 | # TeamCity is a build add-in
105 | _TeamCity*
106 | 
107 | # DotCover is a Code Coverage Tool
108 | *.dotCover
109 | 
110 | # NCrunch
111 | _NCrunch_*
112 | .*crunch*.local.xml
113 | nCrunchTemp_*
114 | 
115 | # MightyMoose
116 | *.mm.*
117 | AutoTest.Net/
118 | 
119 | # Web workbench (sass)
120 | .sass-cache/
121 | 
122 | # Installshield output folder
123 | [Ee]xpress/
124 | 
125 | # DocProject is a documentation generator add-in
126 | DocProject/buildhelp/
127 | DocProject/Help/*.HxT
128 | DocProject/Help/*.HxC
129 | DocProject/Help/*.hhc
130 | DocProject/Help/*.hhk
131 | DocProject/Help/*.hhp
132 | DocProject/Help/Html2
133 | DocProject/Help/html
134 | 
135 | # Click-Once directory
136 | publish/
137 | 
138 | # Publish Web Output
139 | *.[Pp]ublish.xml
140 | *.azurePubxml
141 | # TODO: Comment the next line if you want to checkin your web deploy settings 
142 | # but database connection strings (with potential passwords) will be unencrypted
143 | *.pubxml
144 | *.publishproj
145 | 
146 | # NuGet Packages
147 | *.nupkg
148 | # The packages folder can be ignored because of Package Restore
149 | **/packages/*
150 | # except build/, which is used as an MSBuild target.
151 | !**/packages/build/
152 | # Uncomment if necessary however generally it will be regenerated when needed
153 | #!**/packages/repositories.config
154 | 
155 | # Windows Azure Build Output
156 | csx/
157 | *.build.csdef
158 | 
159 | # Windows Azure Emulator
160 | efc/
161 | rfc/
162 | 
163 | # Windows Store app package directory
164 | AppPackages/
165 | 
166 | # Visual Studio cache files
167 | # files ending in .cache can be ignored
168 | *.[Cc]ache
169 | # but keep track of directories ending in .cache
170 | !*.[Cc]ache/
171 | 
172 | # Others
173 | ClientBin/
174 | [Ss]tyle[Cc]op.*
175 | ~$*
176 | *~
177 | *.dbmdl
178 | *.dbproj.schemaview
179 | *.pfx
180 | *.publishsettings
181 | node_modules/
182 | orleans.codegen.cs
183 | 
184 | # RIA/Silverlight projects
185 | Generated_Code/
186 | 
187 | # Backup & report files from converting an old project file
188 | # to a newer Visual Studio version. Backup files are not needed,
189 | # because we have git ;-)
190 | _UpgradeReport_Files/
191 | Backup*/
192 | UpgradeLog*.XML
193 | UpgradeLog*.htm
194 | 
195 | # SQL Server files
196 | *.mdf
197 | *.ldf
198 | 
199 | # Business Intelligence projects
200 | *.rdl.data
201 | *.bim.layout
202 | *.bim_*.settings
203 | 
204 | # Microsoft Fakes
205 | FakesAssemblies/
206 | 
207 | # GhostDoc plugin setting file
208 | *.GhostDoc.xml
209 | 
210 | # Node.js Tools for Visual Studio
211 | .ntvs_analysis.dat
212 | 
213 | # Visual Studio 6 build log
214 | *.plg
215 | 
216 | # Visual Studio 6 workspace options file
217 | *.opt
218 | 
219 | # Visual Studio LightSwitch build output
220 | **/*.HTMLClient/GeneratedArtifacts
221 | **/*.DesktopClient/GeneratedArtifacts
222 | **/*.DesktopClient/ModelManifest.xml
223 | **/*.Server/GeneratedArtifacts
224 | **/*.Server/ModelManifest.xml
225 | _Pvt_Extensions
226 | 
227 | # Paket dependency manager
228 | .paket/paket.exe
229 | 
230 | # FAKE - F# Make
231 | .fake/
232 | 
233 | !x64/Release/VirtualDesktopAccessor.dll
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
 1 | Copyright (c) 2015, 2016 Jari Pennanen
 2 | 
 3 | Permission is hereby granted, free of charge, to any person obtaining a copy
 4 | of this software and associated documentation files (the "Software"), to deal
 5 | in the Software without restriction, including without limitation the rights
 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 7 | copies of the Software, and to permit persons to whom the Software is
 8 | furnished to do so, subject to the following conditions:
 9 | 
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 | 
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
  1 | # VirtualDesktopAccessor.dll
  2 | 
  3 | DLL for accessing Windows 10 (tested with build 17134.48) Virtual Desktop features from e.g. AutoHotkey. MIT Licensed, see LICENSE.txt (c) Jari Pennanen, 2015-2018
  4 | 
  5 | Download the VirtualDesktopAccessor.dll from directory x64\Release\VirtualDesktopAccessor.dll in the repository. This DLL works only on 64 bit Windows 10.
  6 | 
  7 | You probably first need the [VS 2017 runtimes vc_redist.x64.exe and/or vc_redist.x86.exe](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), if they are not installed already. I've built the DLL using VS 2017, and Microsoft is not providing those runtimes (who knows why) with Windows 10 yet.
  8 | 
  9 | ## AutoHotkey script as example:
 10 | 
 11 | ```AutoHotkey
 12 | DetectHiddenWindows, On
 13 | hwnd:=WinExist("ahk_pid " . DllCall("GetCurrentProcessId","Uint"))
 14 | hwnd+=0x1000<<32
 15 | 
 16 | hVirtualDesktopAccessor := DllCall("LoadLibrary", Str, "C:\Source\CandCPP\VirtualDesktopAccessor\x64\Release\VirtualDesktopAccessor.dll", "Ptr") 
 17 | GoToDesktopNumberProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "GoToDesktopNumber", "Ptr")
 18 | GetCurrentDesktopNumberProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "GetCurrentDesktopNumber", "Ptr")
 19 | IsWindowOnCurrentVirtualDesktopProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "IsWindowOnCurrentVirtualDesktop", "Ptr")
 20 | MoveWindowToDesktopNumberProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "MoveWindowToDesktopNumber", "Ptr")
 21 | RegisterPostMessageHookProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "RegisterPostMessageHook", "Ptr")
 22 | UnregisterPostMessageHookProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "UnregisterPostMessageHook", "Ptr")
 23 | IsPinnedWindowProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "IsPinnedWindow", "Ptr")
 24 | RestartVirtualDesktopAccessorProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "RestartVirtualDesktopAccessor", "Ptr")
 25 | ; GetWindowDesktopNumberProc := DllCall("GetProcAddress", Ptr, hVirtualDesktopAccessor, AStr, "GetWindowDesktopNumber", "Ptr")
 26 | activeWindowByDesktop := {}
 27 | 
 28 | ; Restart the virtual desktop accessor when Explorer.exe crashes, or restarts (e.g. when coming from fullscreen game)
 29 | explorerRestartMsg := DllCall("user32\RegisterWindowMessage", "Str", "TaskbarCreated")
 30 | OnMessage(explorerRestartMsg, "OnExplorerRestart")
 31 | OnExplorerRestart(wParam, lParam, msg, hwnd) {
 32 |     global RestartVirtualDesktopAccessorProc
 33 |     DllCall(RestartVirtualDesktopAccessorProc, UInt, result)
 34 | }
 35 | 
 36 | MoveCurrentWindowToDesktop(number) {
 37 | 	global MoveWindowToDesktopNumberProc, GoToDesktopNumberProc, activeWindowByDesktop
 38 | 	WinGet, activeHwnd, ID, A
 39 | 	activeWindowByDesktop[number] := 0 ; Do not activate
 40 | 	DllCall(MoveWindowToDesktopNumberProc, UInt, activeHwnd, UInt, number)
 41 | 	DllCall(GoToDesktopNumberProc, UInt, number)
 42 | }
 43 | 
 44 | GoToPrevDesktop() {
 45 | 	global GetCurrentDesktopNumberProc, GoToDesktopNumberProc
 46 | 	current := DllCall(GetCurrentDesktopNumberProc, UInt)
 47 | 	if (current = 0) {
 48 | 		GoToDesktopNumber(7)
 49 | 	} else {
 50 | 		GoToDesktopNumber(current - 1)      
 51 | 	}
 52 | 	return
 53 | }
 54 | 
 55 | GoToNextDesktop() {
 56 | 	global GetCurrentDesktopNumberProc, GoToDesktopNumberProc
 57 | 	current := DllCall(GetCurrentDesktopNumberProc, UInt)
 58 | 	if (current = 7) {
 59 | 		GoToDesktopNumber(0)
 60 | 	} else {
 61 | 		GoToDesktopNumber(current + 1)    
 62 | 	}
 63 | 	return
 64 | }
 65 | 
 66 | GoToDesktopNumber(num) {
 67 | 	global GetCurrentDesktopNumberProc, GoToDesktopNumberProc, IsPinnedWindowProc, activeWindowByDesktop
 68 | 
 69 | 	; Store the active window of old desktop, if it is not pinned
 70 | 	WinGet, activeHwnd, ID, A
 71 | 	current := DllCall(GetCurrentDesktopNumberProc, UInt) 
 72 | 	isPinned := DllCall(IsPinnedWindowProc, UInt, activeHwnd)
 73 | 	if (isPinned == 0) {
 74 | 		activeWindowByDesktop[current] := activeHwnd
 75 | 	}
 76 | 
 77 | 	; Try to avoid flashing task bar buttons, deactivate the current window if it is not pinned
 78 | 	if (isPinned != 1) {
 79 | 		WinActivate, ahk_class Shell_TrayWnd
 80 | 	}
 81 | 
 82 | 	; Change desktop
 83 | 	DllCall(GoToDesktopNumberProc, Int, num)
 84 | 	return
 85 | }
 86 | 
 87 | ; Windows 10 desktop changes listener
 88 | DllCall(RegisterPostMessageHookProc, Int, hwnd, Int, 0x1400 + 30)
 89 | OnMessage(0x1400 + 30, "VWMess")
 90 | VWMess(wParam, lParam, msg, hwnd) {
 91 | 	global IsWindowOnCurrentVirtualDesktopProc, IsPinnedWindowProc, activeWindowByDesktop
 92 | 
 93 | 	desktopNumber := lParam + 1
 94 | 	
 95 | 	; Try to restore active window from memory (if it's still on the desktop and is not pinned)
 96 | 	WinGet, activeHwnd, ID, A 
 97 | 	isPinned := DllCall(IsPinnedWindowProc, UInt, activeHwnd)
 98 | 	oldHwnd := activeWindowByDesktop[lParam]
 99 | 	isOnDesktop := DllCall(IsWindowOnCurrentVirtualDesktopProc, UInt, oldHwnd, UInt)
100 | 	if (isOnDesktop == 1 && isPinned != 1) {
101 | 		WinActivate, ahk_id %oldHwnd%
102 | 	}
103 | 
104 | 	; Menu, Tray, Icon, Icons/icon%desktopNumber%.ico
105 | 	
106 | 	; When switching to desktop 1, set background pluto.jpg
107 | 	; if (lParam == 0) {
108 | 		; DllCall("SystemParametersInfo", UInt, 0x14, UInt, 0, Str, "C:\Users\Jarppa\Pictures\Backgrounds\saturn.jpg", UInt, 1)
109 | 	; When switching to desktop 2, set background DeskGmail.png
110 | 	; } else if (lParam == 1) {
111 | 		; DllCall("SystemParametersInfo", UInt, 0x14, UInt, 0, Str, "C:\Users\Jarppa\Pictures\Backgrounds\DeskGmail.png", UInt, 1)
112 | 	; When switching to desktop 7 or 8, set background DeskMisc.png
113 | 	; } else if (lParam == 2 || lParam == 3) {
114 | 		; DllCall("SystemParametersInfo", UInt, 0x14, UInt, 0, Str, "C:\Users\Jarppa\Pictures\Backgrounds\DeskMisc.png", UInt, 1)
115 | 	; Other desktops, set background to DeskWork.png
116 | 	; } else {
117 | 		; DllCall("SystemParametersInfo", UInt, 0x14, UInt, 0, Str, "C:\Users\Jarppa\Pictures\Backgrounds\DeskWork.png", UInt, 1)
118 | 	; }
119 | }
120 | 
121 | ; Switching desktops:
122 | ; Win + Ctrl + 1 = Switch to desktop 1
123 | *#1::GoToDesktopNumber(0)
124 | 
125 | ; Win + Ctrl + 2 = Switch to desktop 2
126 | *#2::GoToDesktopNumber(1)
127 | 
128 | ; Moving windowes:
129 | ; Win + Shift + 1 = Move current window to desktop 1, and go there
130 | +#2::MoveCurrentWindowToDesktop(1)
131 | ```
132 | 
133 | ## All functions exported by DLL:
134 | 
135 |     * int GetCurrentDesktopNumber()
136 |     * int GetDesktopCount()
137 |     * GUID GetDesktopIdByNumber(int number) // Returns zeroed GUID with invalid number found
138 |     * int GetDesktopNumber(IVirtualDesktop *pDesktop) 
139 |     * int GetDesktopNumberById(GUID desktopId)
140 |     * GUID GetWindowDesktopId(HWND window)
141 |     * int GetWindowDesktopNumber(HWND window)
142 |     * int IsWindowOnCurrentVirtualDesktop(HWND window)
143 |     * BOOL MoveWindowToDesktopNumber(HWND window, int number) 
144 |     * void GoToDesktopNumber(int number)
145 |     * void RegisterPostMessageHook(HWND listener, int messageOffset)
146 |     * void UnregisterPostMessageHook(HWND hwnd)
147 | 	* int IsPinnedWindow(HWND hwnd) // Returns 1 if pinned, 0 if not pinned, -1 if not valid
148 | 	* void PinWindow(HWND hwnd)
149 | 	* void UnPinWindow(HWND hwnd)
150 | 	* int IsPinnedApp(HWND hwnd) // Returns 1 if pinned, 0 if not pinned, -1 if not valid
151 | 	* void PinApp(HWND hwnd)
152 | 	* void UnPinApp(HWND hwnd)
153 | 	* int IsWindowOnDesktopNumber(HWND window, int number) / 
154 | 	* void RestartVirtualDesktopAccessor() // Call this during taskbar created message
155 | 
156 | 	* void EnableKeepMinimized() // Deprecated, does nothing
157 | 	* void RestoreMinimized() // Deprecated, does nothing
158 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/TestVirtualDesktopAccessorWin32.cpp:
--------------------------------------------------------------------------------
  1 | // TestVirtualDesktopAccessorWin32.cpp : Defines the entry point for the application.
  2 | //
  3 | 
  4 | #include "stdafx.h"
  5 | #include "TestVirtualDesktopAccessorWin32.h"
  6 | #include "dllmain.h"
  7 | 
  8 | WCHAR szClassName[] = L"TestVirtualDesktopAccesorWin32";
  9 | 
 10 | #define MESSAGE_OFFSET WM_USER + 60
 11 | 
 12 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 13 | {
 14 | 
 15 | 	switch (message) {
 16 | 		case WM_DESTROY:
 17 | 			PostQuitMessage(0);
 18 | 			break;
 19 | 		case MESSAGE_OFFSET + VDA_CurrentVirtualDesktopChanged:
 20 | 			std::wcout << L"CurrentVirtualDesktopChanged old: " << wParam << " new:" << lParam << "\r\n";
 21 | 			break;
 22 | 		case MESSAGE_OFFSET + VDA_ViewVirtualDesktopChanged:
 23 | 			std::wcout << L"CurrentVirtualDesktopChanged old: " << wParam << " new:" << lParam << "\r\n";
 24 | 			break;
 25 | 		case MESSAGE_OFFSET + VDA_VirtualDesktopCreated:
 26 | 			std::wcout << L"CurrentVirtualDesktopChanged old: " << wParam << " new:" << lParam << "\r\n";
 27 | 			break;
 28 | 		case MESSAGE_OFFSET + VDA_VirtualDesktopDestroyBegin:
 29 | 			std::wcout << L"CurrentVirtualDesktopChanged old: " << wParam << " new:" << lParam << "\r\n";
 30 | 			break;
 31 | 		case MESSAGE_OFFSET + VDA_VirtualDesktopDestroyed:
 32 | 			std::wcout << L"CurrentVirtualDesktopChanged old: " << wParam << " new:" << lParam << "\r\n";
 33 | 			break;
 34 | 		case MESSAGE_OFFSET + VDA_VirtualDesktopDestroyFailed:
 35 | 			std::wcout << L"CurrentVirtualDesktopChanged old: " << wParam << " new:" << lParam << "\r\n";
 36 | 			break;
 37 | 		default:
 38 | 			return DefWindowProc(hWnd, message, wParam, lParam);
 39 | 	}
 40 | 	return 0;
 41 | }
 42 | 
 43 | int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
 44 | 					 _In_opt_ HINSTANCE hPrevInstance,
 45 | 					 _In_ LPWSTR    lpCmdLine,
 46 | 					 _In_ int       nCmdShow)
 47 | {
 48 | 	HWND hwnd;
 49 | 	MSG messages;
 50 | 	WNDCLASSEX wincl;
 51 | 
 52 | 	wincl.hInstance = hInstance;
 53 | 	wincl.lpszClassName = szClassName;
 54 | 	wincl.lpfnWndProc = WndProc;
 55 | 	wincl.style = CS_DBLCLKS;
 56 | 	wincl.cbSize = sizeof(WNDCLASSEX);
 57 | 	wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 58 | 	wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
 59 | 	wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
 60 | 	wincl.lpszMenuName = NULL;
 61 | 	wincl.cbClsExtra = 0;
 62 | 	wincl.cbWndExtra = 0;
 63 | 	wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
 64 | 
 65 | 	if (!RegisterClassEx(&wincl))
 66 | 		return 0;
 67 | 
 68 | 	hwnd = CreateWindowEx(0, 
 69 | 		szClassName, 
 70 | 		L"TestVirtualDesktopAccesorWin32",
 71 | 		WS_OVERLAPPEDWINDOW,
 72 | 		CW_USEDEFAULT,
 73 | 		CW_USEDEFAULT,
 74 | 		544,          
 75 | 		375,          
 76 | 		HWND_DESKTOP, 
 77 | 		NULL,         
 78 | 		hInstance,    
 79 | 		NULL          
 80 | 		);
 81 | 
 82 | 	ShowWindow(hwnd, SW_HIDE);
 83 | 	_OpenDllWindow(hInstance);
 84 | 
 85 | 	RegisterPostMessageHook(hwnd, MESSAGE_OFFSET);
 86 | 	std::wcout << "Desktops: " << GetDesktopCount() << "\r\n";
 87 | 	std::wcout << "Console Window's Desktop Number: " << GetWindowDesktopNumber(GetConsoleWindow()) << std::endl;
 88 | 	std::wcout << "Current Desktop Number: " << GetCurrentDesktopNumber() << "\r\n";
 89 | 
 90 | 	HWND notepad = FindWindow(_T("Notepad"), NULL);
 91 | 	if (notepad != 0) {
 92 | 		int number = GetCurrentDesktopNumber();
 93 | 
 94 | 		std::wcout << "Is notepad on this desktop: " << IsWindowOnDesktopNumber(notepad, number) << std::endl;
 95 | 
 96 | 		// Test pinning it
 97 | 		std::wcout << "Try pinning the notepad (the window)." << std::endl;
 98 | 		PinWindow(notepad);
 99 | 		std::wcout << "Is notepad pinned?" << IsPinnedWindow(notepad) << std::endl;
100 | 		GoToDesktopNumber(number + 1);
101 | 		Sleep(2000);
102 | 		GoToDesktopNumber(number);
103 | 		UnPinWindow(notepad);
104 | 		std::wcout << "Is notepad pinned?" << IsPinnedWindow(notepad) << std::endl;
105 | 
106 | 		Sleep(2000);
107 | 
108 | 		// Test pinning the whole app!
109 | 		std::wcout << "Try pinning the notepad (the app executable)." << std::endl;
110 | 		PinApp(notepad);
111 | 		std::wcout << "Is notepad pinned app?" << IsPinnedApp(notepad) << std::endl;
112 | 		GoToDesktopNumber(number + 1);
113 | 		Sleep(2000);
114 | 		GoToDesktopNumber(number);
115 | 		UnPinApp(notepad);
116 | 		std::wcout << "Is notepad pinned app?" << IsPinnedApp(notepad) << std::endl;
117 | 
118 | 		// Test moving it
119 | 		if (!IsWindowOnCurrentVirtualDesktop(notepad)) {
120 | 			MoveWindowToDesktopNumber(notepad, number);
121 | 		}
122 | 		std::wcout << "Notepad is on on the current desktop. " << std::endl;
123 | 		Sleep(1000);
124 | 		MoveWindowToDesktopNumber(notepad, number + 1);
125 | 		std::wcout << "Notepad should now have been moved to the next desktop." << std::endl;
126 | 		Sleep(1000);
127 | 		MoveWindowToDesktopNumber(notepad, number);		
128 | 	}
129 | 	else {
130 | 		std::wcout << "Start notepad to try moving a window, or pinning it" << std::endl;
131 | 	}
132 | 	
133 | 
134 | 	GUID g = GetDesktopIdByNumber(GetCurrentDesktopNumber());
135 | 	WCHAR text[255];
136 | 	StringFromGUID2(g, &text[0], 255);
137 | 	std::wcout << "Current Desktop GUID: " << text << std::endl;
138 | 
139 | 	GUID g2 = GetWindowDesktopId(GetConsoleWindow());
140 | 	WCHAR text2[255];
141 | 	StringFromGUID2(g2, &text2[0], 255);
142 | 	std::wcout << "Console Window's Desktop GUID: " << text2 << std::endl;
143 | 	while (GetMessage(&messages, NULL, 0, 0))
144 | 	{
145 | 		TranslateMessage(&messages);
146 | 		DispatchMessage(&messages);
147 | 	}
148 | 
149 | 	UnregisterPostMessageHook(hwnd);
150 | 	
151 | 	return messages.wParam;
152 | }
153 | 
154 | 
155 | int main() {
156 | 	return wWinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), SW_SHOW);
157 | }
158 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/TestVirtualDesktopAccessorWin32.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/TestVirtualDesktopAccessorWin32.vcxproj:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |   
  4 |     
  5 |       Debug
  6 |       Win32
  7 |     
  8 |     
  9 |       Release
 10 |       Win32
 11 |     
 12 |     
 13 |       Debug
 14 |       x64
 15 |     
 16 |     
 17 |       Release
 18 |       x64
 19 |     
 20 |   
 21 |   
 22 |     {FA401C23-A170-45D0-BB2C-9F21A8E07B2C}
 23 |     Win32Proj
 24 |     TestVirtualDesktopAccessorWin32
 25 |     10.0
 26 |   
 27 |   
 28 |   
 29 |     Application
 30 |     true
 31 |     v143
 32 |     Unicode
 33 |   
 34 |   
 35 |     Application
 36 |     false
 37 |     v143
 38 |     true
 39 |     Unicode
 40 |   
 41 |   
 42 |     Application
 43 |     true
 44 |     v143
 45 |     Unicode
 46 |   
 47 |   
 48 |     Application
 49 |     false
 50 |     v143
 51 |     true
 52 |     Unicode
 53 |   
 54 |   
 55 |   
 56 |   
 57 |   
 58 |   
 59 |   
 60 |     
 61 |   
 62 |   
 63 |     
 64 |   
 65 |   
 66 |     
 67 |   
 68 |   
 69 |     
 70 |   
 71 |   
 72 |   
 73 |     true
 74 |   
 75 |   
 76 |     true
 77 |   
 78 |   
 79 |     false
 80 |   
 81 |   
 82 |     false
 83 |     $(SolutionDir)$(Platform)\$(Configuration)\
 84 |   
 85 |   
 86 |     
 87 |       Use
 88 |       Level3
 89 |       Disabled
 90 |       WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
 91 |       true
 92 |       ..\VirtualDesktopAccessor;%(AdditionalIncludeDirectories)
 93 |     
 94 |     
 95 |       Console
 96 |       true
 97 |     
 98 |   
 99 |   
100 |     
101 |       Use
102 |       Level3
103 |       Disabled
104 |       _DEBUG;_WINDOWS;%(PreprocessorDefinitions)
105 |       true
106 |       ..\VirtualDesktopAccessor;%(AdditionalIncludeDirectories)
107 |     
108 |     
109 |       Console
110 |       true
111 |     
112 |   
113 |   
114 |     
115 |       Level3
116 |       Use
117 |       MaxSpeed
118 |       true
119 |       true
120 |       WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
121 |       true
122 |       ..\VirtualDesktopAccessor;%(AdditionalIncludeDirectories)
123 |     
124 |     
125 |       Console
126 |       true
127 |       true
128 |       true
129 |     
130 |   
131 |   
132 |     
133 |       Level3
134 |       Use
135 |       MaxSpeed
136 |       true
137 |       true
138 |       NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
139 |       true
140 |       ..\VirtualDesktopAccessor;%(AdditionalIncludeDirectories)
141 |     
142 |     
143 |       Console
144 |       true
145 |       true
146 |       true
147 |     
148 |   
149 |   
150 |     
151 |     
152 |     
153 |   
154 |   
155 |     
156 |       Create
157 |       Create
158 |       Create
159 |       Create
160 |     
161 |     
162 |   
163 |   
164 |   
165 |   
166 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/TestVirtualDesktopAccessorWin32.vcxproj.filters:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     
 5 |       {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
 6 |       cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
 7 |     
 8 |     
 9 |       {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 |       h;hh;hpp;hxx;hm;inl;inc;xsd
11 |     
12 |     
13 |       {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 |       rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |     
16 |   
17 |   
18 |     
19 |       Header Files
20 |     
21 |     
22 |       Header Files
23 |     
24 |     
25 |       Header Files
26 |     
27 |   
28 |   
29 |     
30 |       Source Files
31 |     
32 |     
33 |       Source Files
34 |     
35 |   
36 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // TestVirtualDesktopAccessorWin32.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 | 
5 | #include "stdafx.h"
6 | 
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/stdafx.h:
--------------------------------------------------------------------------------
 1 | // stdafx.h : include file for standard system include files,
 2 | // or project specific include files that are used frequently, but
 3 | // are changed infrequently
 4 | //
 5 | 
 6 | #pragma once
 7 | 
 8 | #include "targetver.h"
 9 | 
10 | #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
11 | // Windows Header Files:
12 | #include 
13 | 
14 | // C RunTime Header Files
15 | #include 
16 | #include 
17 | #include 
18 | #include 
19 | 
20 | 
21 | // TODO: reference additional headers your program requires here
22 | 
--------------------------------------------------------------------------------
/TestVirtualDesktopAccessorWin32/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | 
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 | 
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 | 
8 | #include 
9 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor.sln:
--------------------------------------------------------------------------------
 1 | 
 2 | Microsoft Visual Studio Solution File, Format Version 12.00
 3 | # Visual Studio 16
 4 | VisualStudioVersion = 15.0.27703.2018
 5 | MinimumVisualStudioVersion = 10.0.40219.1
 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualDesktopAccessor", "VirtualDesktopAccessor\VirtualDesktopAccessor.vcxproj", "{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}"
 7 | EndProject
 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestVirtualDesktopAccessorWin32", "TestVirtualDesktopAccessorWin32\TestVirtualDesktopAccessorWin32.vcxproj", "{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}"
 9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{88DF21E3-B4B2-4CE5-A9B2-C4A60BF898B5}"
11 | 	ProjectSection(SolutionItems) = preProject
12 | 		README.markdown = README.markdown
13 | 	EndProjectSection
14 | EndProject
15 | Global
16 | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | 		Debug|x64 = Debug|x64
18 | 		Debug|x86 = Debug|x86
19 | 		Release|x64 = Release|x64
20 | 		Release|x86 = Release|x86
21 | 	EndGlobalSection
22 | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Debug|x64.ActiveCfg = Debug|x64
24 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Debug|x64.Build.0 = Debug|x64
25 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Debug|x86.ActiveCfg = Debug|Win32
26 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Debug|x86.Build.0 = Debug|Win32
27 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Release|x64.ActiveCfg = Release|x64
28 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Release|x64.Build.0 = Release|x64
29 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Release|x86.ActiveCfg = Release|Win32
30 | 		{75640BB7-FA6D-4DED-A074-E4758CCEF7D1}.Release|x86.Build.0 = Release|Win32
31 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Debug|x64.ActiveCfg = Debug|x64
32 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Debug|x64.Build.0 = Debug|x64
33 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Debug|x86.ActiveCfg = Debug|Win32
34 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Debug|x86.Build.0 = Debug|Win32
35 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Release|x64.ActiveCfg = Release|x64
36 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Release|x64.Build.0 = Release|x64
37 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Release|x86.ActiveCfg = Release|Win32
38 | 		{FA401C23-A170-45D0-BB2C-9F21A8E07B2C}.Release|x86.Build.0 = Release|Win32
39 | 	EndGlobalSection
40 | 	GlobalSection(SolutionProperties) = preSolution
41 | 		HideSolutionNode = FALSE
42 | 	EndGlobalSection
43 | 	GlobalSection(ExtensibilityGlobals) = postSolution
44 | 		SolutionGuid = {762C7D7B-DF75-46B0-9409-DE72C96B2A3F}
45 | 	EndGlobalSection
46 | EndGlobal
47 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/VirtualDesktopAccessor.vcxproj:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |   
  4 |     
  5 |       Debug
  6 |       Win32
  7 |     
  8 |     
  9 |       Release
 10 |       Win32
 11 |     
 12 |     
 13 |       Debug
 14 |       x64
 15 |     
 16 |     
 17 |       Release
 18 |       x64
 19 |     
 20 |   
 21 |   
 22 |     {75640BB7-FA6D-4DED-A074-E4758CCEF7D1}
 23 |     Win32Proj
 24 |     VirtualDesktopAccessor
 25 |     10.0
 26 |   
 27 |   
 28 |   
 29 |     DynamicLibrary
 30 |     true
 31 |     v143
 32 |     Unicode
 33 |   
 34 |   
 35 |     DynamicLibrary
 36 |     false
 37 |     v143
 38 |     true
 39 |     Unicode
 40 |   
 41 |   
 42 |     DynamicLibrary
 43 |     true
 44 |     v143
 45 |     Unicode
 46 |   
 47 |   
 48 |     DynamicLibrary
 49 |     false
 50 |     v143
 51 |     true
 52 |     Unicode
 53 |   
 54 |   
 55 |   
 56 |   
 57 |   
 58 |   
 59 |   
 60 |     
 61 |   
 62 |   
 63 |     
 64 |   
 65 |   
 66 |     
 67 |   
 68 |   
 69 |     
 70 |   
 71 |   
 72 |   
 73 |     true
 74 |   
 75 |   
 76 |     true
 77 |   
 78 |   
 79 |     false
 80 |   
 81 |   
 82 |     false
 83 |     $(SolutionDir)$(Platform)\$(Configuration)\
 84 |     $(Platform)\$(Configuration)\
 85 |   
 86 |   
 87 |     
 88 |       Use
 89 |       Level3
 90 |       Disabled
 91 |       WIN32;_DEBUG;_WINDOWS;_USRDLL;VIRTUALDESKTOPACCESSOR_EXPORTS;%(PreprocessorDefinitions)
 92 |       true
 93 |     
 94 |     
 95 |       Windows
 96 |       true
 97 |       dllmain.def
 98 |     
 99 |   
100 |   
101 |     
102 |       Use
103 |       Level3
104 |       Disabled
105 |       _DEBUG;_WINDOWS;_USRDLL;VIRTUALDESKTOPACCESSOR_EXPORTS;%(PreprocessorDefinitions)
106 |       true
107 |     
108 |     
109 |       Windows
110 |       true
111 |       dllmain.def
112 |     
113 |   
114 |   
115 |     
116 |       Level3
117 |       Use
118 |       MaxSpeed
119 |       true
120 |       true
121 |       WIN32;NDEBUG;_WINDOWS;_USRDLL;VIRTUALDESKTOPACCESSOR_EXPORTS;%(PreprocessorDefinitions)
122 |       true
123 |     
124 |     
125 |       Windows
126 |       true
127 |       true
128 |       true
129 |       dllmain.def
130 |     
131 |   
132 |   
133 |     
134 |       Level3
135 |       Use
136 |       MaxSpeed
137 |       true
138 |       true
139 |       NDEBUG;_WINDOWS;_USRDLL;VIRTUALDESKTOPACCESSOR_EXPORTS;%(PreprocessorDefinitions)
140 |       true
141 |     
142 |     
143 |       Windows
144 |       true
145 |       true
146 |       true
147 |       dllmain.def
148 |     
149 |   
150 |   
151 |     
152 |     
153 |     
154 |     
155 |   
156 |   
157 |     
158 |       false
159 |       
160 |       
161 |       false
162 |       
163 |       
164 |       false
165 |       
166 |       
167 |       false
168 |       
169 |       
170 |     
171 |     
172 |       Create
173 |       Create
174 |       Create
175 |       Create
176 |     
177 |   
178 |   
179 |     
180 |   
181 |   
182 |   
183 |   
184 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/VirtualDesktopAccessor.vcxproj.filters:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     
 5 |       {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
 6 |       cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
 7 |     
 8 |     
 9 |       {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 |       h;hh;hpp;hxx;hm;inl;inc;xsd
11 |     
12 |     
13 |       {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 |       rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |     
16 |   
17 |   
18 |     
19 |       Header Files
20 |     
21 |     
22 |       Header Files
23 |     
24 |     
25 |       Header Files
26 |     
27 |     
28 |       Header Files
29 |     
30 |   
31 |   
32 |     
33 |       Source Files
34 |     
35 |     
36 |       Source Files
37 |     
38 |   
39 |   
40 |     
41 |       Source Files
42 |     
43 |   
44 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/Win10Desktops.h:
--------------------------------------------------------------------------------
  1 | #pragma once
  2 | 
  3 | #include "stdafx.h"
  4 | 
  5 | // Status
  6 | // Up to date with ae16abb6
  7 | 
  8 | const IID IID_IServiceProvider = {
  9 |     0x6D5140C1, 0x7436, 0x11CE, 0x80, 0x34, 0x00, 0xAA, 0x00, 0x60, 0x09, 0xFA };
 10 | 
 11 | const CLSID CLSID_ImmersiveShell = {
 12 |     0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39 };
 13 | 
 14 | // SID_VirtualDesktopManager
 15 | const CLSID CLSID_VirtualDesktopManagerInternal = {
 16 |     0xC5E0CDCA, 0x7B6E, 0x41B2, 0x9F, 0xC4, 0xD9, 0x39, 0x75, 0xCC, 0x46, 0x7B };
 17 | 
 18 | // SID_VirtualDesktopNotificationService
 19 | const CLSID CLSID_IVirtualNotificationService = {
 20 | 	0xA501FDEC, 0x4A09, 0x464C, 0xAE, 0x4E, 0x1B, 0x9C, 0x21, 0xB8, 0x49, 0x18 
 21 | };
 22 | 
 23 | const CLSID CLSID_IVirtualDesktopManager = {
 24 |     0xAA509086, 0x5CA9, 0x4C25, { 0x8f, 0x95, 0x58, 0x9d, 0x3c, 0x07, 0xb4, 0x8a }
 25 | };
 26 | 
 27 | const CLSID CLSID_VirtualDesktopPinnedApps = {
 28 |     0xb5a399e7, 0x1c87, 0x46b8, 0x88, 0xe9, 0xfc, 0x57, 0x47, 0xb1, 0x71, 0xbd
 29 | };
 30 | 
 31 | // IID same as in MIDL IVirtualDesktopNotification
 32 | const IID IID_IVirtualDesktopNotification = {
 33 |     0xB287FA1C, 0x7771, 0x471A, { 0xA2, 0xDF, 0x9B, 0x6B, 0x21, 0xF0, 0xD6, 0x75 }
 34 | };
 35 | 
 36 | // Ignore following API's:
 37 | #define IAsyncCallback UINT
 38 | #define IImmersiveMonitor UINT
 39 | #define APPLICATION_VIEW_COMPATIBILITY_POLICY UINT
 40 | #define IShellPositionerPriority UINT
 41 | #define IApplicationViewOperation UINT
 42 | #define APPLICATION_VIEW_CLOAK_TYPE UINT
 43 | #define IApplicationViewPosition UINT
 44 | 
 45 | DECLARE_INTERFACE_IID_(IApplicationView, IInspectable, "372E1D3B-38D3-42E4-A15B-8AB2B178F513")
 46 | {
 47 |     /*** IUnknown methods ***/
 48 |     STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObject) PURE;
 49 |     STDMETHOD_(ULONG, AddRef)(THIS) PURE;
 50 |     STDMETHOD_(ULONG, Release)(THIS) PURE;
 51 | 
 52 |     /*** IInspectable methods ***/
 53 |     STDMETHOD(GetIids)(__RPC__out ULONG * iidCount, __RPC__deref_out_ecount_full_opt(*iidCount) IID * *iids) PURE;
 54 |     STDMETHOD(GetRuntimeClassName)(__RPC__deref_out_opt HSTRING * className) PURE;
 55 |     STDMETHOD(GetTrustLevel)(__RPC__out TrustLevel * trustLevel) PURE;
 56 | 
 57 |     /*** IApplicationView methods ***/
 58 |     STDMETHOD(SetFocus)(THIS) PURE;
 59 |     STDMETHOD(SwitchTo)(THIS) PURE;
 60 |     STDMETHOD(TryInvokeBack)(THIS_ IAsyncCallback*) PURE;
 61 |     STDMETHOD(GetThumbnailWindow)(THIS_ HWND*) PURE;
 62 |     STDMETHOD(GetMonitor)(THIS_ IImmersiveMonitor**) PURE;
 63 |     STDMETHOD(GetVisibility)(THIS_ int*) PURE;
 64 |     STDMETHOD(SetCloak)(THIS_ APPLICATION_VIEW_CLOAK_TYPE, int) PURE;
 65 |     STDMETHOD(GetPosition)(THIS_ REFIID, void**) PURE;
 66 |     STDMETHOD(SetPosition)(THIS_ IApplicationViewPosition*) PURE;
 67 |     STDMETHOD(InsertAfterWindow)(THIS_ HWND) PURE;
 68 |     STDMETHOD(GetExtendedFramePosition)(THIS_ RECT*) PURE;
 69 |     STDMETHOD(GetAppUserModelId)(THIS_ PWSTR*) PURE;
 70 |     STDMETHOD(SetAppUserModelId)(THIS_ PCWSTR) PURE;
 71 |     STDMETHOD(IsEqualByAppUserModelId)(THIS_ PCWSTR, int*) PURE;
 72 |     STDMETHOD(GetViewState)(THIS_ UINT*) PURE;
 73 |     STDMETHOD(SetViewState)(THIS_ UINT) PURE;
 74 |     STDMETHOD(GetNeediness)(THIS_ int*) PURE;
 75 |     STDMETHOD(GetLastActivationTimestamp)(THIS_ ULONGLONG*) PURE;
 76 |     STDMETHOD(SetLastActivationTimestamp)(THIS_ ULONGLONG) PURE;
 77 |     STDMETHOD(GetVirtualDesktopId)(THIS_ GUID*) PURE;
 78 |     STDMETHOD(SetVirtualDesktopId)(THIS_ REFGUID) PURE;
 79 |     STDMETHOD(GetShowInSwitchers)(THIS_ int*) PURE;
 80 |     STDMETHOD(SetShowInSwitchers)(THIS_ int) PURE;
 81 |     STDMETHOD(GetScaleFactor)(THIS_ int*) PURE;
 82 |     STDMETHOD(CanReceiveInput)(THIS_ BOOL*) PURE;
 83 |     STDMETHOD(GetCompatibilityPolicyType)(THIS_ APPLICATION_VIEW_COMPATIBILITY_POLICY*) PURE;
 84 |     STDMETHOD(SetCompatibilityPolicyType)(THIS_ APPLICATION_VIEW_COMPATIBILITY_POLICY) PURE;
 85 |     //STDMETHOD(GetPositionPriority)(THIS_ IShellPositionerPriority**) PURE; // removed in 1803
 86 |     //STDMETHOD(SetPositionPriority)(THIS_ IShellPositionerPriority*) PURE; // removed in 1803
 87 |     STDMETHOD(GetSizeConstraints)(THIS_ IImmersiveMonitor*, SIZE*, SIZE*) PURE;
 88 |     STDMETHOD(GetSizeConstraintsForDpi)(THIS_ UINT, SIZE*, SIZE*) PURE;
 89 |     STDMETHOD(SetSizeConstraintsForDpi)(THIS_ const UINT*, const SIZE*, const SIZE*) PURE;
 90 |     //STDMETHOD(QuerySizeConstraintsFromApp)(THIS) PURE; // removed in 1803
 91 |     STDMETHOD(OnMinSizePreferencesUpdated)(THIS_ HWND) PURE;
 92 |     STDMETHOD(ApplyOperation)(THIS_ IApplicationViewOperation*) PURE;
 93 |     STDMETHOD(IsTray)(THIS_ BOOL*) PURE;
 94 |     STDMETHOD(IsInHighZOrderBand)(THIS_ BOOL*) PURE;
 95 |     STDMETHOD(IsSplashScreenPresented)(THIS_ BOOL*) PURE;
 96 |     STDMETHOD(Flash)(THIS) PURE;
 97 |     STDMETHOD(GetRootSwitchableOwner)(THIS_ IApplicationView**) PURE;
 98 |     STDMETHOD(EnumerateOwnershipTree)(THIS_ IObjectArray**) PURE;
 99 | 
100 |     STDMETHOD(GetEnterpriseId)(THIS_ PWSTR*) PURE;
101 |     STDMETHOD(IsMirrored)(THIS_ BOOL*) PURE;
102 | 
103 |     // Unsure
104 |     STDMETHOD(Unknown1)(THIS_ int*) PURE;
105 |     STDMETHOD(Unknown2)(THIS_ int*) PURE;
106 |     STDMETHOD(Unknown3)(THIS_ int*) PURE;
107 |     STDMETHOD(Unknown4)(THIS_ int) PURE;
108 | 
109 |     // 17661?
110 |     //STDMETHOD(Unknown5)(THIS) PURE;
111 |     //STDMETHOD(Unknown6)(THIS_ int*) PURE;
112 |     //STDMETHOD(Unknown7)(THIS_ int) PURE;
113 |     //STDMETHOD(Unknown8)(THIS_ int, THIS_ int) PURE;
114 | 
115 | };
116 | 
117 | const __declspec(selectany) IID& IID_IApplicationView = __uuidof(IApplicationView);
118 | 
119 | DECLARE_INTERFACE_IID_(IVirtualDesktopPinnedApps, IUnknown, "4ce81583-1e4c-4632-a621-07a53543148f")
120 | {
121 |     /*** IUnknown methods ***/
122 |     STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObject) PURE;
123 |     STDMETHOD_(ULONG, AddRef)(THIS) PURE;
124 |     STDMETHOD_(ULONG, Release)(THIS) PURE;
125 | 
126 |     /*** IVirtualDesktopPinnedApps methods ***/
127 |     STDMETHOD(IsAppIdPinned)(THIS_ PCWSTR appId, BOOL*) PURE;
128 |     STDMETHOD(PinAppID)(THIS_ PCWSTR appId) PURE;
129 |     STDMETHOD(UnpinAppID)(THIS_ PCWSTR appId) PURE;
130 |     STDMETHOD(IsViewPinned)(THIS_ IApplicationView*, BOOL*) PURE;
131 |     STDMETHOD(PinView)(THIS_ IApplicationView*) PURE;
132 |     STDMETHOD(UnpinView)(THIS_ IApplicationView*) PURE;
133 | 
134 | };
135 | 
136 | // Ignore following API's:
137 | #define IImmersiveApplication UINT
138 | #define IApplicationViewChangeListener UINT
139 | 
140 | DECLARE_INTERFACE_IID_(IApplicationViewCollection, IUnknown, "1841C6D7-4F9D-42C0-AF41-8747538F10E5")
141 | {
142 |     /*** IUnknown methods ***/
143 |     STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObject) PURE;
144 |     STDMETHOD_(ULONG, AddRef)(THIS) PURE;
145 |     STDMETHOD_(ULONG, Release)(THIS) PURE;
146 | 
147 |     /*** IApplicationViewCollection methods ***/
148 |     STDMETHOD(GetViews)(THIS_ IObjectArray**) PURE;
149 |     STDMETHOD(GetViewsByZOrder)(THIS_ IObjectArray**) PURE;
150 |     STDMETHOD(GetViewsByAppUserModelId)(THIS_ PCWSTR, IObjectArray**) PURE;
151 |     STDMETHOD(GetViewForHwnd)(THIS_ HWND, IApplicationView**) PURE;
152 |     STDMETHOD(GetViewForApplication)(THIS_ IImmersiveApplication*, IApplicationView**) PURE;
153 |     STDMETHOD(GetViewForAppUserModelId)(THIS_ PCWSTR, IApplicationView**) PURE;
154 |     STDMETHOD(GetViewInFocus)(THIS_ IApplicationView**) PURE;
155 |     STDMETHOD(TryGetLastActiveVisibleView)(IApplicationView**) PURE;
156 |     STDMETHOD(RefreshCollection)(THIS) PURE;
157 |     STDMETHOD(RegisterForApplicationViewChanges)(THIS_ IApplicationViewChangeListener*, DWORD*) PURE;
158 |     // STDMETHOD(RegisterForApplicationViewPositionChanges)(THIS_ IApplicationViewChangeListener*, DWORD*) PURE;
159 |     STDMETHOD(UnregisterForApplicationViewChanges)(THIS_ DWORD) PURE;
160 | };
161 | 
162 | MIDL_INTERFACE("3F07F4BE-B107-441A-AF0F-39D82529072C")
163 | IVirtualDesktop : public IUnknown
164 | {
165 | public:
166 |     virtual HRESULT STDMETHODCALLTYPE IsViewVisible(IApplicationView * pView, int* pfVisible) = 0;
167 |     virtual HRESULT STDMETHODCALLTYPE GetID(GUID* pGuid) = 0;
168 |     virtual HRESULT STDMETHODCALLTYPE GetName(HSTRING* name) = 0;
169 |     virtual HRESULT STDMETHODCALLTYPE GetWallpaper(HSTRING* wallpaperPath) = 0;
170 | };
171 | 
172 | MIDL_INTERFACE("A871910E-6CC0-4E65-8B9B-458CE9115E30")
173 | IVirtualDesktop2 : public IUnknown
174 | {
175 | public:
176 |     virtual HRESULT STDMETHODCALLTYPE IsRemote(BOOL * isRemote) = 0;
177 | };
178 | 
179 | enum AdjacentDesktop
180 | {
181 |     LeftDirection = 3,
182 |     RightDirection = 4
183 | };
184 | 
185 | MIDL_INTERFACE("4970BA3D-FD4E-4647-BEA3-D89076EF4B9C")
186 | IVirtualDesktopManagerInternal : public IUnknown
187 | {
188 | public:
189 |     virtual HRESULT STDMETHODCALLTYPE GetCount(UINT * pCount) = 0;
190 | 
191 |     virtual HRESULT STDMETHODCALLTYPE MoveViewToDesktop(
192 |         IApplicationView* pView,
193 |         IVirtualDesktop* pDesktop) = 0;
194 | 
195 |     // Since build 10240
196 |     virtual HRESULT STDMETHODCALLTYPE CanViewMoveDesktops(
197 |         IApplicationView* pView,
198 |         int* pfCanViewMoveDesktops) = 0;
199 | 
200 |     virtual HRESULT STDMETHODCALLTYPE GetCurrentDesktop(
201 |         IVirtualDesktop** desktop) = 0;
202 | 
203 |     virtual HRESULT STDMETHODCALLTYPE GetDesktops(
204 |         IObjectArray** ppDesktops) = 0;
205 | 
206 |     virtual HRESULT STDMETHODCALLTYPE GetAdjacentDesktop(
207 |         IVirtualDesktop* pDesktopReference,
208 |         AdjacentDesktop uDirection,
209 |         IVirtualDesktop** ppAdjacentDesktop) = 0;
210 | 
211 |     virtual HRESULT STDMETHODCALLTYPE SwitchDesktop(
212 |         IVirtualDesktop* pDesktop) = 0;
213 | 
214 |     virtual HRESULT STDMETHODCALLTYPE CreateDesktop(
215 |         IVirtualDesktop** ppNewDesktop) = 0;
216 | 
217 |     virtual HRESULT STDMETHODCALLTYPE MoveDesktop(
218 |         IVirtualDesktop* desktop,
219 |         INT32 index);
220 | 
221 |     virtual HRESULT STDMETHODCALLTYPE RemoveDesktop(
222 |         IVirtualDesktop* pRemove,
223 |         IVirtualDesktop* pFallbackDesktop) = 0;
224 | 
225 |     // Since build 10240
226 |     virtual HRESULT STDMETHODCALLTYPE FindDesktop(
227 |         GUID* desktopId,
228 |         IVirtualDesktop** ppDesktop) = 0;
229 | 
230 |     /*
231 |     HRESULT GetDesktopSwitchIncludeExcludeViews([in] IVirtualDesktop *pTargetDesktop, [out] IObjectArray **ppIncludeViews, [out] IObjectArray **ppExcludeViews);
232 |     HRESULT SetDesktopName([in] IVirtualDesktop* desktop, [in] HSTRING name);
233 |     HRESULT SetDesktopWallpaper([in] IVirtualDesktop* desktop, [in] HSTRING wallpaperPath);
234 |     HRESULT UpdateWallpaperPathForAllDesktops([in] HSTRING wallpaperPath);
235 |     HRESULT CopyDesktopState([in] IApplicationView* target, [in] IApplicationView* source);
236 |     */
237 | };
238 | 
239 | MIDL_INTERFACE("A3175F2D-239C-4BD2-8AA0-EEBA8B0B138E")
240 | IVirtualDesktopManagerInternal2 : public IUnknown
241 | {
242 | public:
243 |     virtual HRESULT STDMETHODCALLTYPE CreateRemoteDesktop(HSTRING name, IVirtualDesktop * *ppNewDesktop) = 0;
244 |     virtual HRESULT STDMETHODCALLTYPE SwitchRemoteDesktop(IVirtualDesktop* pDesktop) = 0;
245 |     virtual HRESULT STDMETHODCALLTYPE SwitchDesktopWithAnimation(IVirtualDesktop* pDesktop) = 0;
246 |     virtual HRESULT STDMETHODCALLTYPE GetLastActiveDesktop(IVirtualDesktop** lastActiveVirtualDesktop) = 0;
247 | };
248 | 
249 | MIDL_INTERFACE("a5cd92ff-29be-454c-8d04-d82879fb3f1b")
250 | IVirtualDesktopManager : public IUnknown
251 | {
252 | public:
253 |     virtual HRESULT STDMETHODCALLTYPE IsWindowOnCurrentVirtualDesktop(
254 |         /* [in] */ __RPC__in HWND topLevelWindow,
255 |         /* [out] */ __RPC__out BOOL * onCurrentDesktop) = 0;
256 | 
257 |     virtual HRESULT STDMETHODCALLTYPE GetWindowDesktopId(
258 |         /* [in] */ __RPC__in HWND topLevelWindow,
259 |         /* [out] */ __RPC__out GUID* desktopId) = 0;
260 | 
261 |     virtual HRESULT STDMETHODCALLTYPE MoveWindowToDesktop(
262 |         /* [in] */ __RPC__in HWND topLevelWindow,
263 |         /* [in] */ __RPC__in REFGUID desktopId) = 0;
264 | };
265 | 
266 | MIDL_INTERFACE("B287FA1C-7771-471A-A2DF-9B6B21F0D675")
267 | IVirtualDesktopNotification : public IUnknown
268 | {
269 | public:
270 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopCreated(
271 |         IVirtualDesktop * pDesktop) = 0;
272 | 
273 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopDestroyBegin(
274 |         IVirtualDesktop* pDesktopDestroyed,
275 |         IVirtualDesktop* pDesktopFallback) = 0;
276 | 
277 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopDestroyFailed(
278 |         IVirtualDesktop* pDesktopDestroyed,
279 |         IVirtualDesktop* pDesktopFallback) = 0;
280 | 
281 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopDestroyed(
282 |         IVirtualDesktop* pDesktopDestroyed,
283 |         IVirtualDesktop* pDesktopFallback) = 0;
284 | 
285 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopMoved(
286 |         IVirtualDesktop* pDesktop,
287 |         UINT64 oldIndex,
288 |         UINT64 newIndex) = 0;
289 | 
290 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopNameChanged(
291 |         IVirtualDesktop* pDesktop,
292 |         HSTRING name) = 0;
293 | 
294 |     virtual HRESULT STDMETHODCALLTYPE ViewVirtualDesktopChanged(
295 |         IApplicationView* pView) = 0;
296 | 
297 |     virtual HRESULT STDMETHODCALLTYPE CurrentVirtualDesktopChanged(
298 |         IVirtualDesktop* pDesktopOld,
299 |         IVirtualDesktop* pDesktopNew) = 0;
300 | 
301 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopWallpaperChanged(
302 |         IVirtualDesktop* pDesktop,
303 |         HSTRING name) = 0;
304 | 
305 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopSwitched(
306 |         IVirtualDesktop* pDesktopNew) = 0;
307 | 
308 |     virtual HRESULT STDMETHODCALLTYPE RemoteVirtualDesktopConnected(
309 |         IVirtualDesktop* remoteVirtualDesktop) = 0;
310 | };
311 | 
312 | MIDL_INTERFACE("0CD45E71-D927-4F15-8B0A-8FEF525337BF")
313 | IVirtualDesktopNotificationService : public IUnknown
314 | {
315 | public:
316 |     virtual HRESULT STDMETHODCALLTYPE Register(
317 |         IVirtualDesktopNotification * pNotification,
318 |         DWORD * pdwCookie) = 0;
319 | 
320 |     virtual HRESULT STDMETHODCALLTYPE Unregister(
321 |         DWORD dwCookie) = 0;
322 | };
323 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/dllmain.cpp:
--------------------------------------------------------------------------------
 1 | // dllmain.cpp : Defines the entry point for the DLL application.
 2 | #include "stdafx.h"
 3 | #include "dllmain.h"
 4 | 
 5 | BOOL APIENTRY DllMain( HMODULE hModule,
 6 |                        DWORD  ul_reason_for_call,
 7 |                        LPVOID lpReserved
 8 | 					 )
 9 | {
10 | 	switch (ul_reason_for_call)
11 | 	{
12 | 	case DLL_PROCESS_ATTACH:
13 | 		_OpenDllWindow(hModule);
14 | 		break;
15 | 	case DLL_THREAD_ATTACH:
16 | 	case DLL_THREAD_DETACH:
17 | 	case DLL_PROCESS_DETACH:
18 | 		break;
19 | 	}
20 | 	return TRUE;
21 | }
22 | 
23 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/dllmain.def:
--------------------------------------------------------------------------------
 1 | LIBRARY DLLMAIN
 2 | EXPORTS
 3 |     GetCurrentDesktopNumber @8
 4 |     GetDesktopCount @1
 5 | 	GetDesktopIdByNumber @12
 6 |     GetDesktopNumber @7
 7 |     GetDesktopNumberById @2
 8 |     GetWindowDesktopId @3
 9 |     GetWindowDesktopNumber @4
10 |     IsWindowOnCurrentVirtualDesktop @5
11 |     MoveWindowToDesktopNumber @6
12 |     GoToDesktopNumber @9
13 |     RegisterPostMessageHook @10
14 |     UnregisterPostMessageHook @11
15 |     IsPinnedWindow @13
16 |     PinWindow @14
17 |     UnPinWindow @15
18 |     IsPinnedApp @16
19 |     PinApp @17
20 |     UnPinApp @18
21 | 
22 | 	EnableKeepMinimized @19
23 | 	RestoreMinimized @20
24 | 	IsWindowOnDesktopNumber @21
25 | 	RestartVirtualDesktopAccessor @22
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/dllmain.h:
--------------------------------------------------------------------------------
  1 | #pragma once
  2 | #include "stdafx.h"
  3 | #include "Win10Desktops.h"
  4 | 
  5 | #define DllExport   __declspec( dllexport )
  6 | 
  7 | #define VDA_VirtualDesktopCreated 5
  8 | #define VDA_VirtualDesktopDestroyBegin 4
  9 | #define VDA_VirtualDesktopDestroyFailed 3
 10 | #define VDA_VirtualDesktopDestroyed 2
 11 | #define VDA_ViewVirtualDesktopChanged 1
 12 | #define VDA_CurrentVirtualDesktopChanged 0
 13 | 
 14 | #define VDA_IS_NORMAL 1
 15 | #define VDA_IS_MINIMIZED 2
 16 | #define VDA_IS_MAXIMIZED 3
 17 | 
 18 | std::map listeners;
 19 | IServiceProvider* pServiceProvider = nullptr;
 20 | IVirtualDesktopManagerInternal* pDesktopManagerInternal = nullptr;
 21 | IVirtualDesktopManager* pDesktopManager = nullptr;
 22 | IApplicationViewCollection* viewCollection = nullptr;
 23 | IVirtualDesktopPinnedApps* pinnedApps = nullptr;
 24 | IVirtualDesktopNotificationService* pDesktopNotificationService = nullptr;
 25 | BOOL registeredForNotifications = FALSE;
 26 | 
 27 | DWORD idNotificationService = 0;
 28 | 
 29 | struct ChangeDesktopAction {
 30 |     GUID newDesktopGuid;
 31 |     GUID oldDesktopGuid;
 32 | };
 33 | 
 34 | void _PostMessageToListeners(int msgOffset, WPARAM wParam, LPARAM lParam) {
 35 |     for each (std::pair listener in listeners) {
 36 |         PostMessage(listener.first, listener.second + msgOffset, wParam, lParam);
 37 |     }
 38 | }
 39 | 
 40 | void _RegisterService(BOOL force = FALSE) {
 41 |     if (force) {
 42 |         pServiceProvider = nullptr;
 43 |         pDesktopManagerInternal = nullptr;
 44 |         pDesktopManager = nullptr;
 45 |         viewCollection = nullptr;
 46 |         pinnedApps = nullptr;
 47 |         pDesktopNotificationService = nullptr;
 48 |         registeredForNotifications = FALSE;
 49 |     }
 50 | 
 51 |     if (pServiceProvider != nullptr) {
 52 |         return;
 53 |     }
 54 |     ::CoInitialize(NULL);
 55 |     ::CoCreateInstance(
 56 |         CLSID_ImmersiveShell, NULL, CLSCTX_LOCAL_SERVER,
 57 |         __uuidof(IServiceProvider), (PVOID*)&pServiceProvider);
 58 | 
 59 |     if (pServiceProvider == nullptr) {
 60 |         std::wcout << L"FATAL ERROR: pServiceProvider is null";
 61 |         return;
 62 |     }
 63 |     pServiceProvider->QueryService(__uuidof(IApplicationViewCollection), &viewCollection);
 64 | 
 65 |     pServiceProvider->QueryService(__uuidof(IVirtualDesktopManager), &pDesktopManager);
 66 | 
 67 |     pServiceProvider->QueryService(
 68 |         CLSID_VirtualDesktopPinnedApps,
 69 |         __uuidof(IVirtualDesktopPinnedApps), (PVOID*)&pinnedApps);
 70 | 
 71 |     pServiceProvider->QueryService(
 72 |         CLSID_VirtualDesktopManagerInternal,
 73 |         __uuidof(IVirtualDesktopManagerInternal), (PVOID*)&pDesktopManagerInternal);
 74 | 
 75 |     if (viewCollection == nullptr) {
 76 |         std::wcout << L"FATAL ERROR: viewCollection is null";
 77 |         return;
 78 |     }
 79 | 
 80 |     if (pDesktopManagerInternal == nullptr) {
 81 |         std::wcout << L"FATAL ERROR: pDesktopManagerInternal is null";
 82 |         return;
 83 |     }
 84 | 
 85 |     // Notification service
 86 |     HRESULT hrNotificationService = pServiceProvider->QueryService(
 87 |         CLSID_IVirtualNotificationService,
 88 |         __uuidof(IVirtualDesktopNotificationService),
 89 |         (PVOID*)&pDesktopNotificationService);
 90 | }
 91 | 
 92 | 
 93 | IApplicationView* _GetApplicationViewForHwnd(HWND hwnd) {
 94 |     if (hwnd == 0)
 95 |         return nullptr;
 96 |     IApplicationView* app = nullptr;
 97 |     viewCollection->GetViewForHwnd(hwnd, &app);
 98 |     return app;
 99 | }
100 | 
101 | void DllExport EnableKeepMinimized() {
102 |     //_keepMinimized = true;
103 | }
104 | 
105 | void DllExport RestoreMinimized() {
106 | }
107 | 
108 | int DllExport GetDesktopCount()
109 | {
110 |     _RegisterService();
111 | 
112 |     IObjectArray* pObjectArray = nullptr;
113 |     HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray);
114 | 
115 |     if (SUCCEEDED(hr))
116 |     {
117 |         UINT count;
118 |         hr = pObjectArray->GetCount(&count);
119 |         pObjectArray->Release();
120 |         return count;
121 |     }
122 | 
123 |     return -1;
124 | }
125 | 
126 | int DllExport GetDesktopNumberById(GUID desktopId) {
127 |     _RegisterService();
128 | 
129 |     IObjectArray* pObjectArray = nullptr;
130 |     HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray);
131 |     int found = -1;
132 | 
133 |     if (SUCCEEDED(hr))
134 |     {
135 |         UINT count;
136 |         hr = pObjectArray->GetCount(&count);
137 | 
138 |         if (SUCCEEDED(hr))
139 |         {
140 |             for (UINT i = 0; i < count; i++)
141 |             {
142 |                 IVirtualDesktop* pDesktop = nullptr;
143 | 
144 |                 if (FAILED(pObjectArray->GetAt(i, __uuidof(IVirtualDesktop), (void**)&pDesktop)))
145 |                     continue;
146 | 
147 |                 GUID id = { 0 };
148 |                 if (SUCCEEDED(pDesktop->GetID(&id)) && id == desktopId)
149 |                 {
150 |                     found = i;
151 |                     pDesktop->Release();
152 |                     break;
153 |                 }
154 | 
155 |                 pDesktop->Release();
156 |             }
157 |         }
158 | 
159 |         pObjectArray->Release();
160 |     }
161 | 
162 |     return found;
163 | }
164 | 
165 | IVirtualDesktop* _GetDesktopByNumber(int number) {
166 |     _RegisterService();
167 | 
168 |     IObjectArray* pObjectArray = nullptr;
169 |     HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray);
170 |     IVirtualDesktop* found = nullptr;
171 | 
172 |     if (SUCCEEDED(hr))
173 |     {
174 |         UINT count;
175 |         hr = pObjectArray->GetCount(&count);
176 |         pObjectArray->GetAt(number, __uuidof(IVirtualDesktop), (void**)&found);
177 |         pObjectArray->Release();
178 |     }
179 | 
180 |     return found;
181 | }
182 | 
183 | GUID DllExport GetWindowDesktopId(HWND window) {
184 |     _RegisterService();
185 | 
186 |     GUID pDesktopId = {};
187 |     pDesktopManager->GetWindowDesktopId(window, &pDesktopId);
188 | 
189 |     return pDesktopId;
190 | }
191 | 
192 | int DllExport GetWindowDesktopNumber(HWND window) {
193 |     _RegisterService();
194 | 
195 |     GUID* pDesktopId = new GUID({ 0 });
196 |     if (SUCCEEDED(pDesktopManager->GetWindowDesktopId(window, pDesktopId))) {
197 |         return GetDesktopNumberById(*pDesktopId);
198 |     }
199 | 
200 |     return -1;
201 | }
202 | 
203 | int DllExport IsWindowOnCurrentVirtualDesktop(HWND window) {
204 |     _RegisterService();
205 | 
206 |     BOOL b;
207 |     if (SUCCEEDED(pDesktopManager->IsWindowOnCurrentVirtualDesktop(window, &b))) {
208 |         return b;
209 |     }
210 | 
211 |     return -1;
212 | }
213 | 
214 | GUID DllExport GetDesktopIdByNumber(int number) {
215 |     GUID id;
216 |     IVirtualDesktop* pDesktop = _GetDesktopByNumber(number);
217 |     if (pDesktop != nullptr) {
218 |         pDesktop->GetID(&id);
219 |         pDesktop->Release();
220 |     }
221 |     return id;
222 | }
223 | 
224 | 
225 | int DllExport IsWindowOnDesktopNumber(HWND window, int number) {
226 |     _RegisterService();
227 |     IApplicationView* app = nullptr;
228 |     if (window == 0) {
229 |         return -1;
230 |     }
231 |     viewCollection->GetViewForHwnd(window, &app);
232 |     GUID desktopId = { 0 };
233 |     app->GetVirtualDesktopId(&desktopId);
234 |     GUID desktopCheckId = GetDesktopIdByNumber(number);
235 |     app->Release();
236 |     if (desktopCheckId == GUID_NULL || desktopId == GUID_NULL) {
237 |         return -1;
238 |     }
239 | 
240 |     if (GetDesktopIdByNumber(number) == desktopId) {
241 |         return 1;
242 |     }
243 |     else {
244 |         return 0;
245 |     }
246 | 
247 |     return -1;
248 | }
249 | 
250 | BOOL DllExport MoveWindowToDesktopNumber(HWND window, int number) {
251 |     _RegisterService();
252 |     IVirtualDesktop* pDesktop = _GetDesktopByNumber(number);
253 |     if (pDesktopManager == nullptr) {
254 |         std::wcout << L"ARRGH?";
255 |         return false;
256 |     }
257 |     if (window == 0) {
258 |         return false;
259 |     }
260 |     if (pDesktop != nullptr) {
261 |         GUID id = { 0 };
262 |         if (SUCCEEDED(pDesktop->GetID(&id))) {
263 |             IApplicationView* app = nullptr;
264 |             viewCollection->GetViewForHwnd(window, &app);
265 |             if (app != nullptr) {
266 |                 pDesktopManagerInternal->MoveViewToDesktop(app, pDesktop);
267 |                 return true;
268 |             }
269 |         }
270 |     }
271 |     return false;
272 | }
273 | 
274 | int DllExport GetDesktopNumber(IVirtualDesktop* pDesktop) {
275 |     _RegisterService();
276 | 
277 |     if (pDesktop == nullptr) {
278 |         return -1;
279 |     }
280 | 
281 |     GUID guid;
282 | 
283 |     if (SUCCEEDED(pDesktop->GetID(&guid))) {
284 |         return GetDesktopNumberById(guid);
285 |     }
286 | 
287 |     return -1;
288 | }
289 | IVirtualDesktop* GetCurrentDesktop() {
290 |     _RegisterService();
291 | 
292 |     if (pDesktopManagerInternal == nullptr) {
293 |         return nullptr;
294 |     }
295 |     IVirtualDesktop* found = nullptr;
296 |     pDesktopManagerInternal->GetCurrentDesktop(&found);
297 |     return found;
298 | }
299 | 
300 | int DllExport GetCurrentDesktopNumber() {
301 |     IVirtualDesktop* virtualDesktop = GetCurrentDesktop();
302 |     int number = GetDesktopNumber(virtualDesktop);
303 |     virtualDesktop->Release();
304 |     return number;
305 | }
306 | 
307 | void DllExport GoToDesktopNumber(int number) {
308 |     _RegisterService();
309 | 
310 |     if (pDesktopManagerInternal == nullptr) {
311 |         return;
312 |     }
313 | 
314 |     IVirtualDesktop* oldDesktop = GetCurrentDesktop();
315 |     GUID oldId = { 0 };
316 |     oldDesktop->GetID(&oldId);
317 |     oldDesktop->Release();
318 | 
319 |     IObjectArray* pObjectArray = nullptr;
320 |     HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray);
321 |     int found = -1;
322 | 
323 |     if (SUCCEEDED(hr))
324 |     {
325 |         UINT count;
326 |         hr = pObjectArray->GetCount(&count);
327 | 
328 |         if (SUCCEEDED(hr))
329 |         {
330 |             for (UINT i = 0; i < count; i++)
331 |             {
332 |                 IVirtualDesktop* pDesktop = nullptr;
333 | 
334 |                 if (FAILED(pObjectArray->GetAt(i, __uuidof(IVirtualDesktop), (void**)&pDesktop)))
335 |                     continue;
336 | 
337 |                 GUID id = { 0 };
338 |                 pDesktop->GetID(&id);
339 |                 if (i == number) {
340 |                     pDesktopManagerInternal->SwitchDesktop(pDesktop);
341 |                 }
342 | 
343 |                 pDesktop->Release();
344 |             }
345 |         }
346 |         pObjectArray->Release();
347 |     }
348 | }
349 | 
350 | struct ShowWindowOnDesktopAction {
351 |     int desktopNumber;
352 |     int cmdShow;
353 | };
354 | 
355 | LPWSTR _GetApplicationIdForHwnd(HWND hwnd) {
356 |     if (hwnd == 0)
357 |         return nullptr;
358 |     IApplicationView* app = _GetApplicationViewForHwnd(hwnd);
359 |     if (app != nullptr) {
360 |         LPWSTR appId = new TCHAR[1024];
361 |         app->GetAppUserModelId(&appId);
362 |         app->Release();
363 |         return appId;
364 |     }
365 |     return nullptr;
366 | }
367 | 
368 | int DllExport IsPinnedWindow(HWND hwnd) {
369 |     if (hwnd == 0)
370 |         return -1;
371 |     _RegisterService();
372 |     IApplicationView* pView = _GetApplicationViewForHwnd(hwnd);
373 |     BOOL isPinned = false;
374 |     if (pView != nullptr) {
375 |         pinnedApps->IsViewPinned(pView, &isPinned);
376 |         pView->Release();
377 |         if (isPinned) {
378 |             return 1;
379 |         }
380 |         else {
381 |             return 0;
382 |         }
383 |     }
384 | 
385 |     return -1;
386 | }
387 | 
388 | void DllExport PinWindow(HWND hwnd) {
389 |     if (hwnd == 0)
390 |         return;
391 |     _RegisterService();
392 |     IApplicationView* pView = _GetApplicationViewForHwnd(hwnd);
393 |     if (pView != nullptr) {
394 |         pinnedApps->PinView(pView);
395 |         pView->Release();
396 |     }
397 | }
398 | 
399 | void DllExport UnPinWindow(HWND hwnd) {
400 |     if (hwnd == 0)
401 |         return;
402 |     _RegisterService();
403 |     IApplicationView* pView = _GetApplicationViewForHwnd(hwnd);
404 |     if (pView != nullptr) {
405 |         pinnedApps->UnpinView(pView);
406 |         pView->Release();
407 |     }
408 | }
409 | 
410 | int DllExport IsPinnedApp(HWND hwnd) {
411 |     if (hwnd == 0)
412 |         return -1;
413 |     _RegisterService();
414 |     LPWSTR appId = _GetApplicationIdForHwnd(hwnd);
415 |     if (appId != nullptr) {
416 |         BOOL isPinned = false;
417 |         pinnedApps->IsAppIdPinned(appId, &isPinned);
418 |         if (isPinned) {
419 |             return 1;
420 |         }
421 |         else {
422 |             return 0;
423 |         }
424 |     }
425 |     return -1;
426 | }
427 | 
428 | void DllExport PinApp(HWND hwnd) {
429 |     if (hwnd == 0)
430 |         return;
431 |     _RegisterService();
432 |     LPWSTR appId = _GetApplicationIdForHwnd(hwnd);
433 |     if (appId != nullptr) {
434 |         pinnedApps->PinAppID(appId);
435 |     }
436 | }
437 | 
438 | void DllExport UnPinApp(HWND hwnd) {
439 |     if (hwnd == 0)
440 |         return;
441 |     _RegisterService();
442 |     LPWSTR appId = _GetApplicationIdForHwnd(hwnd);
443 |     if (appId != nullptr) {
444 |         pinnedApps->UnpinAppID(appId);
445 |     }
446 | }
447 | 
448 | class _Notifications : public IVirtualDesktopNotification {
449 | private:
450 |     ULONG _referenceCount;
451 | public:
452 |     // Inherited via IVirtualDesktopNotification
453 |     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
454 |     {
455 |         // Always set out parameter to NULL, validating it first.
456 |         if (!ppvObject)
457 |             return E_INVALIDARG;
458 |         *ppvObject = NULL;
459 | 
460 |         if (riid == IID_IUnknown || riid == IID_IVirtualDesktopNotification)
461 |         {
462 |             // Increment the reference count and return the pointer.
463 |             *ppvObject = (LPVOID)this;
464 |             AddRef();
465 |             return S_OK;
466 |         }
467 |         return E_NOINTERFACE;
468 |     }
469 | 
470 |     virtual ULONG STDMETHODCALLTYPE AddRef() override
471 |     {
472 |         return InterlockedIncrement(&_referenceCount);
473 |     }
474 | 
475 |     virtual ULONG STDMETHODCALLTYPE Release() override
476 |     {
477 |         ULONG result = InterlockedDecrement(&_referenceCount);
478 |         if (result == 0)
479 |         {
480 |             delete this;
481 |         }
482 |         return 0;
483 |     }
484 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopCreated(IVirtualDesktop* pDesktop) override
485 |     {
486 |         _PostMessageToListeners(VDA_VirtualDesktopCreated, GetDesktopNumber(pDesktop), 0);
487 |         return S_OK;
488 |     }
489 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopDestroyBegin(IVirtualDesktop* pDesktopDestroyed,
490 |         IVirtualDesktop* pDesktopFallback) override
491 |     {
492 |         _PostMessageToListeners(VDA_VirtualDesktopDestroyBegin,
493 |             GetDesktopNumber(pDesktopDestroyed),
494 |             GetDesktopNumber(pDesktopFallback));
495 |         return S_OK;
496 |     }
497 | 
498 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopDestroyFailed(
499 |         IVirtualDesktop* pDesktopDestroyed, IVirtualDesktop* pDesktopFallback) override
500 |     {
501 |         _PostMessageToListeners(VDA_VirtualDesktopDestroyFailed,
502 |             GetDesktopNumber(pDesktopDestroyed),
503 |             GetDesktopNumber(pDesktopFallback));
504 |         return S_OK;
505 |     }
506 | 
507 |     virtual HRESULT STDMETHODCALLTYPE VirtualDesktopDestroyed(
508 |         IVirtualDesktop* pDesktopDestroyed, IVirtualDesktop* pDesktopFallback) override
509 |     {
510 |         _PostMessageToListeners(VDA_VirtualDesktopDestroyed,
511 |             GetDesktopNumber(pDesktopDestroyed),
512 |             GetDesktopNumber(pDesktopFallback));
513 |         return S_OK;
514 |     }
515 | 
516 |     virtual HRESULT STDMETHODCALLTYPE ViewVirtualDesktopChanged(IApplicationView* pView) override
517 |     {
518 |         _PostMessageToListeners(VDA_ViewVirtualDesktopChanged, 0, 0);
519 |         return S_OK;
520 |     }
521 | 
522 |     virtual HRESULT STDMETHODCALLTYPE CurrentVirtualDesktopChanged(
523 |         IVirtualDesktop* pDesktopOld,
524 |         IVirtualDesktop* pDesktopNew) override
525 |     {
526 |         // not sure how/why this happens but have crash dump where it did. 
527 |         if (pDesktopOld == nullptr && pDesktopNew == nullptr) {
528 |             return S_OK;
529 |         }
530 | 
531 |         viewCollection->RefreshCollection();
532 | 
533 |         ChangeDesktopAction act;
534 |         if (pDesktopOld != nullptr) {
535 |             pDesktopOld->GetID(&act.oldDesktopGuid);
536 |         }
537 | 
538 |         if (pDesktopNew != nullptr) {
539 |             pDesktopNew->GetID(&act.newDesktopGuid);
540 |         }
541 | 
542 |         _PostMessageToListeners(VDA_CurrentVirtualDesktopChanged,
543 |             GetDesktopNumberById(act.oldDesktopGuid),
544 |             GetDesktopNumberById(act.newDesktopGuid));
545 |         return S_OK;
546 |     }
547 | 
548 |     virtual HRESULT __stdcall VirtualDesktopMoved(
549 |         IVirtualDesktop* pDesktop, UINT64 oldIndex, UINT64 newIndex) override {
550 |         return S_OK;
551 |     }
552 | 
553 |     virtual HRESULT __stdcall VirtualDesktopNameChanged(IVirtualDesktop* pDesktop, HSTRING name) override {
554 |         return S_OK;
555 |     }
556 | 
557 |     virtual HRESULT __stdcall VirtualDesktopWallpaperChanged(IVirtualDesktop* pDesktop, HSTRING name) override {
558 |         return S_OK;
559 |     }
560 | 
561 |     virtual HRESULT __stdcall VirtualDesktopSwitched(IVirtualDesktop* pDesktopNew) override {
562 |         return S_OK;
563 |     }
564 | 
565 |     virtual HRESULT __stdcall  RemoteVirtualDesktopConnected(IVirtualDesktop* remoteVirtualDesktop) override {
566 |         return S_OK;
567 |     }
568 | };
569 | 
570 | void _RegisterDesktopNotifications() {
571 |     _RegisterService();
572 |     if (pDesktopNotificationService == nullptr) {
573 |         return;
574 |     }
575 |     if (registeredForNotifications) {
576 |         return;
577 |     }
578 |     _Notifications* nf = new _Notifications();
579 |     HRESULT res = pDesktopNotificationService->Register(nf, &idNotificationService);
580 |     if (SUCCEEDED(res)) {
581 |         registeredForNotifications = TRUE;
582 |     }
583 | }
584 | 
585 | void DllExport RestartVirtualDesktopAccessor() {
586 |     _RegisterService(TRUE);
587 |     _RegisterDesktopNotifications();
588 | }
589 | 
590 | void DllExport RegisterPostMessageHook(HWND listener, int messageOffset) {
591 |     _RegisterService();
592 | 
593 |     listeners.insert(std::pair(listener, messageOffset));
594 |     if (listeners.size() != 1) {
595 |         return;
596 |     }
597 |     _RegisterDesktopNotifications();
598 | }
599 | 
600 | void DllExport UnregisterPostMessageHook(HWND hwnd) {
601 |     _RegisterService();
602 | 
603 |     listeners.erase(hwnd);
604 |     if (listeners.size() != 0) {
605 |         return;
606 |     }
607 | 
608 |     if (pDesktopNotificationService == nullptr) {
609 |         return;
610 |     }
611 | 
612 |     if (idNotificationService > 0) {
613 |         registeredForNotifications = TRUE;
614 |         pDesktopNotificationService->Unregister(idNotificationService);
615 |     }
616 | }
617 | 
618 | VOID _OpenDllWindow(HINSTANCE injModule) {
619 | }
620 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // VirtualDesktopAccessor.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 | 
5 | #include "stdafx.h"
6 | 
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 | 
--------------------------------------------------------------------------------
/VirtualDesktopAccessor/stdafx.h:
--------------------------------------------------------------------------------
 1 | // stdafx.h : include file for standard system include files,
 2 | // or project specific include files that are used frequently, but
 3 | // are changed infrequently
 4 | //
 5 | 
 6 | #pragma once
 7 | 
 8 | #include "targetver.h"
 9 | 
10 | #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
11 | // Windows Header Files:
12 | #include 
13 | #include 
14 | 
15 | #include 
16 | #include 
17 | 
18 | #include 
19 | #include 
20 | #include 
21 | #include 
22 | #include