I'm trying to move a top level window to another virtual desktop without switching virtual desktop (not to easy it seems)
examples:
(VirtualDesktop.ps1)
(VirtualDesktop is C# wrapper for IVirtualDesktopManager on Windows 10.)
after finding those two examples above i continued searching the interwebz and what i found is 'MoveWindowToDesktop' only works on windows owned by the current process (IVirtualDesktopManager::MoveWindowToDesktop method)
and what i'm trying to do is move a window of another process (in the script below it is a GUI window the script owns but did also try with a notepad window)
So online i found that others had luck doing that using the undocumented method 'MoveViewToDesktop' from 'IVirtualDesktopManagerInternal' (Requesting API calls for Windows 10's virtual desktops) (IVirtualDesktopManagerInternal instance not returned) (You can move a window not owned by the executing process, but it requires the use of additional, undocumented COM objects.)
so i tried piecing something together both from what was already on the forum (How to call a Win32 API with UUID [IVirtualDesktopManager]) and from what i was able to google
Currently I've taken a step back and am trying to use the 'view' returned from the method 'GetViewForHwnd' from 'IApplicationViewCollection' (Win10Desktops.h)
using 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInternal' (Updated interfaces in Windows 10 build 17134, 17661, and 17666)
so when i run the code below i end op getting an ErrorLevel of '0xC0000005' (normally means 'Access Violation') from the 'CanViewMoveDesktops' call
Code: Select all
#SingleInstance, force
; create a new virtual desktop with ctrl + win + d
Gui, new, +hwndhwnd
Gui, add, text,, let us try and move this window to another virtual desktop
Gui, add, button, w100, Ok
Gui, show
return
Cancel:
ExitApp
return
buttonok:
; IVirtualDesktopManager interface
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager
IVirtualDesktopManager := ComObjCreate("{AA509086-5CA9-4C25-8F95-589D3C07B48A}", "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}")
IsWindowOnCurrentVirtualDesktop := vtable(IVirtualDesktopManager, 3)
GetWindowDesktopId := vtable(IVirtualDesktopManager, 4)
MoveWindowToDesktop := vtable(IVirtualDesktopManager, 5)
; internal interface IVirtualDesktopManagerInternal14328
; https://sourceforge.net/p/virtual-desktop-grid-switcher/src/ci/d85ff70ced929d161bd45d10a47ebb0c0f2a1f68/tree/VirtualDesktop-master/source/VirtualDesktop/Interop/IVirtualDesktopManagerInternal.cs#l71
IServiceProvider := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{6D5140C1-7436-11CE-8034-00AA006009FA}")
IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{F31574D6-B682-4CDC-BD56-1827860ABEC6}")
GetCount := vtable(IVirtualDesktopManagerInternal, 3)
MoveViewToDesktop := vtable(IVirtualDesktopManagerInternal, 4)
CanViewMoveDesktops := vtable(IVirtualDesktopManagerInternal, 5)
GetCurrentDesktop := vtable(IVirtualDesktopManagerInternal, 6)
GetDesktops := vtable(IVirtualDesktopManagerInternal, 7)
GetAdjacentDesktop := vtable(IVirtualDesktopManagerInternal, 8)
SwitchDesktop := vtable(IVirtualDesktopManagerInternal, 9)
CreateDesktopW := vtable(IVirtualDesktopManagerInternal, 10)
RemoveDesktop := vtable(IVirtualDesktopManagerInternal, 11)
FindDesktop := vtable(IVirtualDesktopManagerInternal, 12)
ImmersiveShell := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{00000000-0000-0000-C000-000000000046}")
;~ try
;~ ppDesktopManager := ComObjQuery(ImmersiveShell, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{f31574d6-b682-4cdc-bd56-1827860abec6}")
;~ if (!ppDesktopManager)
;~ ppDesktopManager := ComObjQuery(ImmersiveShell, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{AF8DA486-95BB-4460-B3B7-6E7A6B2962B5}")
; HKEY_CLASSES_ROOT\Interface\{2C08ADF0-A386-4B35-9250-0FE183476FCC}
if !(IApplicationViewCollection := ComObjQuery(ImmersiveShell,"{2C08ADF0-A386-4B35-9250-0FE183476FCC}","{2C08ADF0-A386-4B35-9250-0FE183476FCC}" ) )
{
MsgBox IApplicationViewCollection interface not supported.
ExitApp
}
GetViews := vtable(IApplicationViewCollection, 3) ; (out IObjectArray array);
GetViewsByZOrder := vtable(IApplicationViewCollection, 4) ; (out IObjectArray array);
GetViewsByAppUserModelId := vtable(IApplicationViewCollection, 5) ; (string id, out IObjectArray array);
GetViewForHwnd := vtable(IApplicationViewCollection, 6) ; (IntPtr hwnd, out IApplicationView view);
GetViewForApplication := vtable(IApplicationViewCollection, 7) ; (object application, out IApplicationView view);
GetViewForAppUserModelId := vtable(IApplicationViewCollection, 8) ; (string id, out IApplicationView view);
GetViewInFocus := vtable(IApplicationViewCollection, 9) ; (out IntPtr view);
;Unknown1 := NumGet(NumGet(IApplicationViewCollection+0)+10*A_PtrSize) ; (out IntPtr view);
;outreshCollection := NumGet(NumGet(IApplicationViewCollection+0)+11*A_PtrSize) ; ();
;RegisterForApplicationViewChanges := NumGet(NumGet(IApplicationViewCollection+0)+12*A_PtrSize) ; (object listener, out int cookie);
;//int RegisterForApplicationViewPositionChanges(object listener, out int cookie); //Removed in 17661
;UnregisterForApplicationViewChanges := NumGet(NumGet(IApplicationViewCollection+0)+13*A_PtrSize) ; (int cookie);
; IApplicationViewCollection::GetViews method
IObjectArray := 0
DllCall(GetViews, "UPtr", IApplicationViewCollection, "UPtrP", IObjectArray, "UInt")
; IObjectArray::GetCount method
; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getcount
ViewCount := 0
DllCall( vtable(IObjectArray, 3), "UPtr", IObjectArray, "UIntP", ViewCount, "UInt")
VirtualDesktopCount := 0
DllCall(GetCount, "UPtr", IVirtualDesktopManagerInternal, "UIntP", VirtualDesktopCount, "UInt")
msgbox % "Number of views = " ViewCount "`nNumber of VDs = " VirtualDesktopCount "`n`nLet's contuine with the moving action of windows id: " hwnd
; IApplicationViewCollection::GetViewForHwnd method
pView := 0
GetViewForHwnd_return_value := DllCall(GetViewForHwnd, "UPtr", IApplicationViewCollection, "Ptr", hwnd, "Ptr*", pView, "UInt")
dllcall_errorlevel := errorlevel
if GetViewForHwnd_return_value
msgbox % "GetViewForHwnd did not work - return value = " ok
if dllcall_errorlevel
msgbox % "GetViewForHwnd errorlevel = " errorlevel
pfCanViewMoveDesktops := 0
CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "Ptr*", pView, "Uint", pfCanViewMoveDesktops, "UInt") ; return value BOOL
dllcall_errorlevel := errorlevel
if CanViewMoveDesktops_return_value
msgbox % "CanViewMoveDesktops did not work - return value = " ok
if dllcall_errorlevel
msgbox % "CanViewMoveDesktops errorlevel = " errorlevel
msgbox % "pfCanViewMoveDesktops = " pfCanViewMoveDesktops
ExitApp
return
; Errors
; Errorlevel := -2 ; The return type or one of the specified arg types is invalid.
; RPC_X_NULL_REF_POINTER := -2147023116
; E_NOTIMPL := -2147467263 ; Not implemented 0x80004001
; 0xC0000005 means "access violation"
vtable(ptr, n) {
; NumGet(ptr+0) returns the address of the object's virtual function
; table (vtable for short). The remainder of the expression retrieves
; the address of the nth function's address from the vtable.
return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
hopefully someone will have a bit of insight they can share on this