That was the missing piece thanks
What I'm trying to do is enumerate the virtual deskotps. My idea is that if i can create a gui on each desktop then I can track which desktop the user is currently on using IsWindowOnCurrentVirtualDesktop. But i'm getting stuck when creating a class. I think it has something to do with how the classes memory is allocated?
This does what I expect it to, i create a GUI on 2 different virtual dekstops and I get 2 different GUIDs:
Code: Select all
CLSID := "{aa509086-5ca9-4c25-8f95-589d3c07b48a}" ;search VirtualDesktopManager clsid
IID := "{a5cd92ff-29be-454c-8d04-d82879fb3f1b}" ;search IID_IVirtualDesktopManager
iVirtualDesktopManager := ComObjCreate(CLSID, IID)
isWindowOnCurrentVirtualDesktopAddress := NumGet(NumGet(iVirtualDesktopManager+0), 3*A_PtrSize)
getWindowDesktopIdAddress := NumGet(NumGet(iVirtualDesktopManager+0), 4*A_PtrSize)
moveWindowToDesktopAddress := NumGet(NumGet(iVirtualDesktopManager+0), 5*A_PtrSize)
Gui, new
Gui, Show, x55 y66 w300 h200, New Title
Gui, +HwndMyGuiHwnd
hwnd := myGuiHwnd
Send ^#{right}
Gui, new
Gui, Show, x55 y66 w300 h200, New Title
Gui, +HwndMyGuiHwnd2
hwnd2 := myGuiHwnd2
desktopId := ""
VarSetCapacity(desktopID, 16, 0)
;IVirtualDesktopManager::GetWindowDesktopId method
;https://msdn.microsoft.com/en-us/library/windows/desktop/mt186441(v=vs.85).aspx
Error := DllCall(getWindowDesktopIdAddress, "Ptr", iVirtualDesktopManager, "Ptr", hWnd, "Ptr", &desktopID)
if(Error != 0) {
msgbox % "error in _loadVirtualDesktopId " Error "`n" this.hwnd
}
desktopId2 := ""
VarSetCapacity(desktopID2, 16, 0)
;IVirtualDesktopManager::GetWindowDesktopId method
;https://msdn.microsoft.com/en-us/library/windows/desktop/mt186441(v=vs.85).aspx
Error := DllCall(getWindowDesktopIdAddress, "Ptr", iVirtualDesktopManager, "Ptr", hWnd2, "Ptr", &desktopID2)
if(Error != 0) {
msgbox % "error in _loadVirtualDesktopId " Error "`n" this.hwnd2
}
MsgBox % _guidToStr(desktopId) "`n" _guidToStr(desktopId2)
ExitApp
; https://github.com/cocobelgica/AutoHotkey-Util/blob/master/Guid.ahk#L36
_guidToStr(ByRef VarOrAddress)
{
pGuid := IsByRef(VarOrAddress) ? &VarOrAddress : VarOrAddress
VarSetCapacity(sGuid, 78) ; (38 + 1) * 2
if !DllCall("ole32\StringFromGUID2", "Ptr", pGuid, "Ptr", &sGuid, "Int", 39)
throw Exception("Invalid GUID", -1, Format("<at {1:p}>", pGuid))
return StrGet(&sGuid, "UTF-16")
}
This however gives me the same GUID on every desktop.
Code: Select all
x := new DesktopMapperClass()
x.mapVirtualDesktops()
ExitApp
#c::ExitApp
class DesktopMapperClass
{
DesktopMarkerClass := Object()
getWindowDesktopIdAddress := ""
isWindowOnCurrentVirtualDesktopAddress := ""
moveWindowToDesktop := ""
iVirtualDesktopManager := ""
__new()
{
MsgBox creating class...
;IVirtualDesktopManager interface
;Exposes methods that enable an application to interact with groups of windows that form virtual workspaces.
;https://msdn.microsoft.com/en-us/library/windows/desktop/mt186440(v=vs.85).aspx
CLSID := "{aa509086-5ca9-4c25-8f95-589d3c07b48a}" ;search VirtualDesktopManager clsid
IID := "{a5cd92ff-29be-454c-8d04-d82879fb3f1b}" ;search IID_IVirtualDesktopManager
this.iVirtualDesktopManager := ComObjCreate(CLSID, IID)
this.isWindowOnCurrentVirtualDesktopAddress := NumGet(NumGet(this.iVirtualDesktopManager+0), 3*A_PtrSize)
this.getWindowDesktopIdAddress := NumGet(NumGet(this.iVirtualDesktopManager+0), 4*A_PtrSize)
this.moveWindowToDesktopAddress := NumGet(NumGet(this.iVirtualDesktopManager+0), 5*A_PtrSize)
return this
}
mapVirtualDesktops()
{
currentDesktop := new DesktopMarkerClass(this.getWindowDesktopIdAddress, this.isWindowOnCurrentVirtualDesktopAddress, this.iVirtualDesktopManager)
send ^#{Left 10}
this.DesktopMarkers := Object()
this._createMarkers()
this._returnToDesktop(currentDesktop)
MsgBox markers created
loop, % this.DesktopMarkers.MaxIndex()
{
MsgBox % this.DesktopMarkers[A_Index].virtualDesktopId
}
return this
}
/*
* returns the desktop number or -1 if there was an error
*
* if tryRemapping is true then if the current desktop isn't mapped we will try mapping it again
*/
getCurrentDesktopNumber(tryRemapping := true)
{
this._verifyDesktopMapping()
loop, % this.DesktopMarkers.MaxIndex()
{
if(this.DesktopMarkers[A_Index].virtualDesktopId == otherDesktop.virtualDesktopId)
{
return A_Index
}
}
;debug
if(tryRemapping)
{
this.mapVirtualDesktops()
return this.getCurrentDesktopNumber(false)
}
return -1
}
/*
* fixes up mapping by removing any markers that have moved desktop
* (this happens when the user closes a virtual desktop)
*
* does not map new desktops
*/
_verifyDesktopMapping()
{
verifiedDesktopMarkerClass := Object()
loop, % this.DesktopMarkers.MaxIndex()
{
if(this.DesktopMarkers[A_Index].isOnSameDesktop())
{
verifiedDesktopMarkerClass.Insert(this.DesktopMarkers[A_Index])
}
}
this.DesktopMarkers := verifiedDesktopMarkerClass
return this
}
_createMarkers()
{
MsgBox creating markers
while(true)
{
ToolTip, about to create a gui %A_index%
sleep 1000
nextMarker := new DesktopMarkerClass(this.getWindowDesktopIdAddress, this.isWindowOnCurrentVirtualDesktopAddress, this.iVirtualDesktopManager)
MsgBox, %A_index% just created it
sleep 1000
if(this._desktopAlreadyMapped(nextMarker))
{
ToolTip, the thing is mapped!
return this
}
this.DesktopMarkers.Insert(nextMarker)
send ^#{right}
sleep 1000
}
return
}
_desktopAlreadyMapped(otherDesktop)
{
loop, % this.DesktopMarkers.MaxIndex()
{
ToolTip % this.DesktopMarkers[A_Index].virtualDesktopId "`n" otherDesktop.virtualDesktopId
sleep 1000
if(this.DesktopMarkers[A_Index].virtualDesktopId == otherDesktop.virtualDesktopId)
{
return true
}
}
;debug
return false
}
_returnToDesktop(returnTo)
{
currentDesktop := this.getCurrentDesktopNumber()
returnToDesktopNumber := 1
loop, % this.DesktopMarkers.MaxIndex()
{
if(this.DesktopMarkers[A_Index].virtualDesktopId == returnTo.virtualDesktopId)
{
returnToDesktopNumber := A_Index
break
}
}
distanceToMove := currentDesktop - returnToDesktopNumber
absDistanceToMove := Abs(distanceToMove)
if(distanceToMove < 0)
{
send ^#{right %absDistanceToMove%}
} else
{
send ^#{left %absDistanceToMove%}
}
return this
}
}
class DesktopMarkerClass
{
hwnd := ""
virtualDesktopGuid := ""
virtualDesktopId := ""
getWindowDesktopIdAddress := ""
isWindowOnCurrentVirtualDesktopAddress := ""
iVirtualDesktopManager := ""
__new(getWindowDesktopIdAddress, isWindowOnCurrentVirtualDesktopAddress, iVirtualDesktopManager)
{
Gui, new
Gui, Show, x55 y66 w300 h200, New Title
Gui, +HwndMyGuiHwnd
this.hwnd := myGuiHwnd
this.getWindowDesktopIdAddress := getWindowDesktopIdAddress
this.isWindowOnCurrentVirtualDesktopAddress := isWindowOnCurrentVirtualDesktopAddress
this.iVirtualDesktopManager := iVirtualDesktopManager
this._loadVirtualDesktopId(desktopId)
this.virtualDesktopGuid := desktopId
this.virtualDesktopId := this._guidToStr(desktopId)
ToolTip, % "the guid is " this.virtualDesktopId "`n" this.hwnd
sleep 1000
;~ MsgBox % "is desktop active? " this.isDesktopCurrentlyActive()
return this
}
destroy()
{
hwnd := this.hwnd
MsgBox destroying! %hwnd%
if(WinExist("ahk_id " hwnd))
{
Gui %hwnd%:Destroy
}
return this
}
/*
* checks if this marker is still on the same virtual desktop it was when it was created
*
* if it isn't then it's virtual desktop was probably closed
*/
isOnSameDesktop()
{
this._loadVirtualDesktopId(desktopId)
return this.virtualDesktopId == this._guidToStr(desktopId)
}
isDesktopCurrentlyActive()
{
;IVirtualDesktopManager::IsWindowOnCurrentVirtualDesktop method
;Indicates whether the provided window is on the currently active virtual desktop.
;https://msdn.microsoft.com/en-us/library/windows/desktop/mt186442(v=vs.85).aspx
Error := DllCall(this.isWindowOnCurrentVirtualDesktopAddress, "Ptr", this.iVirtualDesktopManager, "Ptr", this.hWnd, "IntP", onCurrentDesktop)
if(Error != 0) {
msgbox error in isDesktopCurrentlyActive
}
return onCurrentDesktop
}
_loadVirtualDesktopId(desktopId)
{
VarSetCapacity(desktopID, 16, 0)
;IVirtualDesktopManager::GetWindowDesktopId method
;https://msdn.microsoft.com/en-us/library/windows/desktop/mt186441(v=vs.85).aspx
Error := DllCall(this.getWindowDesktopIdAddress, "Ptr", this.iVirtualDesktopManager, "Ptr", this.hWnd, "Ptr", &desktopID)
if(Error != 0) {
msgbox % "error in _loadVirtualDesktopId " Error "`n" this.hwnd
}
return desktopID
}
; https://github.com/cocobelgica/AutoHotkey-Util/blob/master/Guid.ahk#L36
_guidToStr(ByRef VarOrAddress)
{
ToolTip, % &VarOrAddress " address"
sleep 2000
pGuid := IsByRef(VarOrAddress) ? &VarOrAddress : VarOrAddress
VarSetCapacity(sGuid, 78) ; (38 + 1) * 2
if !DllCall("ole32\StringFromGUID2", "Ptr", pGuid, "Ptr", &sGuid, "Int", 39)
throw Exception("Invalid GUID", -1, Format("<at {1:p}>", pGuid))
return StrGet(&sGuid, "UTF-16")
}
__Delete()
{
MsgBox getting deleted
this.destroy()
return
}
}
It looks like the call to _guidToStr is access the same memory address every time. Any ideas?