<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; AHK: аналог altTab для окон определенной программы]]></title>
	<link rel="self" href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=16202&amp;type=atom" />
	<updated>2024-09-01T12:11:31Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=16202</id>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=161547#p161547" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>Без недокументированных функций я так и не обнаружил возможность определить из-за чего наложен cloak shell - из-за того, что окно бекграундное/системное или из-за того, что оно находится на другом виртуальном дисплее.</p></blockquote></div><p>Поправил с помощью GetWindowDesktopId().<br />Особо не тестировал, но так должно возвращать список окон в alt-tab, используя только документированное апи.<br /></p><div class="codebox"><pre><code>DetectHiddenWindows On
arr := EnumerateAltTabWindows()
for k, v in arr
{
   WinGetClass, winClass, ahk_id %v%
   WinGetTitle, title, ahk_id %v%
   altTabWindows .= A_Index &quot;`nTitle: &quot; title &quot;`nClass: &quot; winClass &quot;`nhWnd: &quot; v &quot;`nLastActivePopup: &quot; format(&quot;0x{:x}&quot;, GetLastActivePopup(v)) &quot;`n`n&quot;
}
MsgBox, % altTabWindows


EnumerateAltTabWindows()
{
   AltTabList := []
   WinGet, list, List
   Loop % list
   {
      if IsAltTabWindow(list%A_Index%)
         AltTabList.Push(list%A_Index%)
   }
   Return AltTabList
}

IsAltTabWindow(hWnd)
{
   static WS_EX_APPWINDOW := 0x40000, WS_EX_TOOLWINDOW := 0x80, DWMWA_CLOAKED := 14, DWM_CLOAKED_SHELL := 2, WS_EX_NOACTIVATE := 0x8000000, GA_PARENT := 1, GW_OWNER := 4, MONITOR_DEFAULTTONULL := 0, VirtualDesktopAltTabFilter := &quot;null&quot;, VirtualDesktopExist, PropEnumProcEx := RegisterCallback(&quot;PropEnumProcEx&quot;, &quot;Fast&quot;, 4)
   if (VirtualDesktopAltTabFilter = &quot;null&quot;)
   {
      RegRead, VirtualDesktopAltTabFilter, HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, VirtualDesktopAltTabFilter
      OSbuildNumber := StrSplit(A_OSVersion, &quot;.&quot;)[3]
      if (OSbuildNumber &lt; 14393)
         VirtualDesktopExist := 0
      else
         VirtualDesktopExist := 1
   }
   if !DllCall(&quot;IsWindowVisible&quot;, &quot;uptr&quot;, hWnd)
      return
   DllCall(&quot;DwmApi\DwmGetWindowAttribute&quot;, &quot;uptr&quot;, hWnd, &quot;uint&quot;, DWMWA_CLOAKED, &quot;uint*&quot;, cloaked, &quot;uint&quot;, 4)
   if (cloaked = DWM_CLOAKED_SHELL) and (!VirtualDesktopExist or IsWindowOnCurrentVirtualDesktop(hWnd) or !GetWindowDesktopId(hWnd))
      return
   if (realHwnd(DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_PARENT, &quot;ptr&quot;)) != realHwnd(DllCall(&quot;GetDesktopWindow&quot;, &quot;ptr&quot;)))
      return
   WinGetClass, winClass, ahk_id %hWnd%
   if (winClass = &quot;Windows.UI.Core.CoreWindow&quot;)
      return
   if (winClass = &quot;ApplicationFrameWindow&quot;)
   {
      varsetcapacity(ApplicationViewCloakType, 4, 0)
      DllCall(&quot;EnumPropsEx&quot;, &quot;uptr&quot;, hWnd, &quot;ptr&quot;, PropEnumProcEx, &quot;ptr&quot;, &amp;ApplicationViewCloakType)
      if (numget(ApplicationViewCloakType, 0, &quot;int&quot;) = 1)   ; https://github.com/kvakulo/Switcheroo/commit/fa526606d52d5ba066ba0b2b5aa83ed04741390f
         return
   }
   ; if !DllCall(&quot;MonitorFromWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, MONITOR_DEFAULTTONULL, &quot;ptr&quot;)   ; test if window is shown on any monitor. alt-tab shows any window even if window is out of monitor.
   ;   return
   WinGet, exStyles, ExStyle, ahk_id %hWnd%
   if (exStyles &amp; WS_EX_APPWINDOW)
   {
      if DllCall(&quot;GetProp&quot;, &quot;uptr&quot;, hWnd, &quot;str&quot;, &quot;ITaskList_Deleted&quot;, &quot;ptr&quot;)
         return
      if !VirtualDesktopExist or (VirtualDesktopAltTabFilter = 0) or IsWindowOnCurrentVirtualDesktop(hwnd)
         return true
      else
         return
   }
   if (exStyles &amp; WS_EX_TOOLWINDOW) or (exStyles &amp; WS_EX_NOACTIVATE)
      return
   loop
   {
      hwndPrev := hwnd
      hwnd := DllCall(&quot;GetWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GW_OWNER, &quot;ptr&quot;)
      if !hwnd
      {
         if DllCall(&quot;GetProp&quot;, &quot;uptr&quot;, hwndPrev, &quot;str&quot;, &quot;ITaskList_Deleted&quot;, &quot;ptr&quot;)
            return
         if !VirtualDesktopExist or (VirtualDesktopAltTabFilter = 0) or IsWindowOnCurrentVirtualDesktop(hwndPrev)
            return true
         else
            return
      }
      if DllCall(&quot;IsWindowVisible&quot;, &quot;uptr&quot;, hwnd)
         return
      WinGet, exStyles, ExStyle, ahk_id %hwnd%
      if ((exStyles &amp; WS_EX_TOOLWINDOW) or (exStyles &amp; WS_EX_NOACTIVATE)) and !(exStyles &amp; WS_EX_APPWINDOW)
         return
   }
}

GetLastActivePopup(hwnd)
{
   static GA_ROOTOWNER := 3
   hwnd := DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_ROOTOWNER, &quot;ptr&quot;)
   hwnd := DllCall(&quot;GetLastActivePopup&quot;, &quot;uptr&quot;, hwnd, &quot;ptr&quot;)
   return hwnd
}

IsWindowOnCurrentVirtualDesktop(hwnd)
{
   static IVirtualDesktopManager
   if !IVirtualDesktopManager
      IVirtualDesktopManager := ComObjCreate(CLSID_VirtualDesktopManager := &quot;{AA509086-5CA9-4C25-8F95-589D3C07B48A}&quot;, IID_IVirtualDesktopManager := &quot;{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}&quot;)
   DllCall(NumGet(NumGet(IVirtualDesktopManager+0), 3*A_PtrSize), &quot;ptr&quot;, IVirtualDesktopManager, &quot;uptr&quot;, hwnd, &quot;int*&quot;, onCurrentDesktop)   ; IsWindowOnCurrentVirtualDesktop
   return onCurrentDesktop
}

GetWindowDesktopId(hwnd)
{
   static IVirtualDesktopManager, Guid_Empty
   if !IVirtualDesktopManager
   {
      IVirtualDesktopManager := ComObjCreate(CLSID_VirtualDesktopManager := &quot;{AA509086-5CA9-4C25-8F95-589D3C07B48A}&quot;, IID_IVirtualDesktopManager := &quot;{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}&quot;)
      VarSetCapacity(Guid_Empty, 16)
      DllCall(&quot;ole32\CLSIDFromString&quot;, &quot;wstr&quot;, &quot;{00000000-0000-0000-0000-000000000000}&quot;, &quot;ptr&quot;, &amp;Guid_Empty)
   }
   VarSetCapacity(desktopId, 16, 0)
   hr := DllCall(NumGet(NumGet(IVirtualDesktopManager+0), 4*A_PtrSize), &quot;ptr&quot;, IVirtualDesktopManager, &quot;uptr&quot;, hwnd, &quot;ptr&quot;, &amp;desktopID)   ; GetWindowDesktopId
   if (hr != 0)   ; Unknown
      return
   if DllCall(&quot;ole32\IsEqualGUID&quot;, &quot;ptr&quot;, &amp;desktopId, &quot;ptr&quot;, &amp;Guid_Empty)   ; Not Assigned
      return
   return true
}

PropEnumProcEx(hWnd, lpszString, hData, dwData)
{
   if (strget(lpszString, &quot;UTF-16&quot;) = &quot;ApplicationViewCloakType&quot;)
   {
      numput(hData, dwData+0, 0, &quot;int&quot;)
      return false
   }
   return true
}

realHwnd(hwnd)
{
   varsetcapacity(var, 8, 0)
   numput(hwnd, var, 0, &quot;uint64&quot;)
   return numget(var, 0, &quot;uint&quot;)
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2024-09-01T12:11:31Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=161547#p161547</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=161464#p161464" />
			<content type="html"><![CDATA[<p>Спасибо, забыл про неё, стало лучше! <br />С winapi пробовал варианты, намного хуже получалось.<br />И не подумал что зачем то может быть нужна тут задержка, ещё и по умолчанию.)</p>]]></content>
			<author>
				<name><![CDATA[serzh82saratov]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=27879</uri>
			</author>
			<updated>2024-08-22T14:26:13Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=161464#p161464</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=161463#p161463" />
			<content type="html"><![CDATA[<p>Setwindelay?</p>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2024-08-22T13:53:11Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=161463#p161463</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=161462#p161462" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>serzh82saratov пишет:</cite><blockquote><p>Судя по первым тестам работает как надо. Проходит список окон программы в соответствии использования.</p></blockquote></div><p>Кто нибудь пробовал? Как то немного долго окна активируются, не знаю как лечить.</p>]]></content>
			<author>
				<name><![CDATA[serzh82saratov]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=27879</uri>
			</author>
			<updated>2024-08-22T13:46:58Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=161462#p161462</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=161449#p161449" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>serzh82saratov пишет:</cite><blockquote><p>Взял твою IsAltTabWindow, не знаю вроде и без неё работает также</p></blockquote></div><p>IsAltTabWindow нужна.</p>]]></content>
			<author>
				<name><![CDATA[serzh82saratov]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=27879</uri>
			</author>
			<updated>2024-08-20T08:35:51Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=161449#p161449</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=161447#p161447" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>С этим</p></blockquote></div><p>У меня оба кода обновляют порядок использования окон, только после перезагрузки скрипта. #62.</p><br /><p>Взял твою IsAltTabWindow, не знаю вроде и без неё работает также, на всякий случай пока.<br />Судя по первым тестам работает как надо. Проходит список окон программы в соответствии использования.</p><div class="codebox"><pre><code>
1::ParseAltTab(&quot;Prev&quot;)
2::ParseAltTab(&quot;Next&quot;)
3::PrevAltTab()

ParseAltTab(dir) {  
	AltTabList := []
	source := WinExist(&quot;A&quot;)
	WinGetClass, sClass, ahk_id %source%
	WinGet, sProcess, ProcessName, ahk_id %source% 
	Winget, List, List, ahk_class %sClass% ahk_exe %sProcess%
	Loop % List
	{  
		hwnd := List%A_Index%   
		If (IsAltTabWindow(hWnd) &amp;&amp; source != hwnd) {
			AltTabList.Push(hwnd)   
		}
	}  
	If (dir = &quot;Prev&quot;)  { 
		hwnd := AltTabList[1]    
	} Else  { 
		hwnd := AltTabList[AltTabList.Count()] 
	}
	WinShow ahk_id %hwnd%
	WinActivate ahk_id %hwnd%  
	If (AltTabList.Count() &gt; 1)
		; https://learn.microsoft.com/ru-ru/windows/win32/api/winuser/nf-winuser-setwindowpos
		DllCall(&quot;SetWindowPos&quot;, &quot;Ptr&quot;, source, &quot;Ptr&quot;, AltTabList[AltTabList.Count()]
			, &quot;Int&quot;, 0, &quot;Int&quot;, 0, &quot;Int&quot;, 0, &quot;Int&quot;, 0, &quot;UInt&quot;, 0x0002|0x0001|0x0010)   
}

PrevAltTab() {   
	source := WinExist(&quot;A&quot;)
	WinGetClass, sClass, ahk_id %source%
	WinGet, sProcess, ProcessName, ahk_id %source% 
	Winget, List, List, ahk_class %sClass% ahk_exe %sProcess%
	Loop % List
	{  
		hwnd := % List%A_Index%   
		If (IsAltTabWindow(hWnd) &amp;&amp; source != hwnd) {  
			WinShow ahk_id %hwnd%
			WinActivate ahk_id %hwnd% 
			Break
		} 
	} 
}
Return
4::

; MouseGetPos
source := WinExist(&quot;A&quot;)
DetectHiddenWindows On
arr := EnumerateAltTabWindows()
for k, v in arr
{
   WinGetClass, winClass, ahk_id %v%
   WinGetTitle, title, ahk_id %v%
   altTabWindows .= A_Index &quot;`nTitle: &quot; title &quot;`nClass: &quot; winClass &quot;`nhWnd: &quot; v &quot;`nLastActivePopup: &quot; format(&quot;0x{:x}&quot;, GetLastActivePopup(v)) &quot;`n`n&quot;
}
MsgBox, % altTabWindows
Return

EnumerateAltTabWindows()
{
   AltTabList := []
   WinGet, list, List
   Loop % list
   {
      if IsAltTabWindow(list%A_Index%)
         AltTabList.Push(list%A_Index%)
   }
   Return AltTabList
}

IsAltTabWindow(hWnd)
{
   static WS_EX_APPWINDOW := 0x40000, WS_EX_TOOLWINDOW := 0x80, DWMWA_CLOAKED := 14, DWM_CLOAKED_SHELL := 2, WS_EX_NOACTIVATE := 0x8000000, GA_PARENT := 1, GW_OWNER := 4, MONITOR_DEFAULTTONULL := 0, VirtualDesktopExist, PropEnumProcEx := RegisterCallback(&quot;PropEnumProcEx&quot;, &quot;Fast&quot;, 4)
   if (VirtualDesktopExist = &quot;&quot;)
   {
      OSbuildNumber := StrSplit(A_OSVersion, &quot;.&quot;)[3]
      if (OSbuildNumber &lt; 14393)
         VirtualDesktopExist := 0
      else
         VirtualDesktopExist := 1
   }
   if !DllCall(&quot;IsWindowVisible&quot;, &quot;uptr&quot;, hWnd)
      return
   DllCall(&quot;DwmApi\DwmGetWindowAttribute&quot;, &quot;uptr&quot;, hWnd, &quot;uint&quot;, DWMWA_CLOAKED, &quot;uint*&quot;, cloaked, &quot;uint&quot;, 4)
   if (cloaked = DWM_CLOAKED_SHELL)
      return
   if (realHwnd(DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_PARENT, &quot;ptr&quot;)) != realHwnd(DllCall(&quot;GetDesktopWindow&quot;, &quot;ptr&quot;)))
      return
   WinGetClass, winClass, ahk_id %hWnd%
   if (winClass = &quot;Windows.UI.Core.CoreWindow&quot;)
      return
   if (winClass = &quot;ApplicationFrameWindow&quot;)
   {
      varsetcapacity(ApplicationViewCloakType, 4, 0)
      DllCall(&quot;EnumPropsEx&quot;, &quot;uptr&quot;, hWnd, &quot;ptr&quot;, PropEnumProcEx, &quot;ptr&quot;, &amp;ApplicationViewCloakType)
      if (numget(ApplicationViewCloakType, 0, &quot;int&quot;) = 1)   ; https://github.com/kvakulo/Switcheroo/commit/fa526606d52d5ba066ba0b2b5aa83ed04741390f
         return
   }
   ; if !DllCall(&quot;MonitorFromWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, MONITOR_DEFAULTTONULL, &quot;ptr&quot;)   ; test if window is shown on any monitor. alt-tab shows any window even if window is out of monitor.
   ;   return
   WinGet, exStyles, ExStyle, ahk_id %hWnd%
   if (exStyles &amp; WS_EX_APPWINDOW)
   {
      if DllCall(&quot;GetProp&quot;, &quot;uptr&quot;, hWnd, &quot;str&quot;, &quot;ITaskList_Deleted&quot;, &quot;ptr&quot;)
         return
      if (VirtualDesktopExist = 0) or IsWindowOnCurrentVirtualDesktop(hwnd)
         return true
      else
         return
   }
   if (exStyles &amp; WS_EX_TOOLWINDOW) or (exStyles &amp; WS_EX_NOACTIVATE)
      return
   loop
   {
      hwndPrev := hwnd
      hwnd := DllCall(&quot;GetWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GW_OWNER, &quot;ptr&quot;)
      if !hwnd
      {
         if DllCall(&quot;GetProp&quot;, &quot;uptr&quot;, hwndPrev, &quot;str&quot;, &quot;ITaskList_Deleted&quot;, &quot;ptr&quot;)
            return
         if (VirtualDesktopExist = 0) or IsWindowOnCurrentVirtualDesktop(hwndPrev)
            return true
         else
            return
      }
      if DllCall(&quot;IsWindowVisible&quot;, &quot;uptr&quot;, hwnd)
         return
      WinGet, exStyles, ExStyle, ahk_id %hwnd%
      if ((exStyles &amp; WS_EX_TOOLWINDOW) or (exStyles &amp; WS_EX_NOACTIVATE)) and !(exStyles &amp; WS_EX_APPWINDOW)
         return
   }
}

GetLastActivePopup(hwnd)
{
   static GA_ROOTOWNER := 3
   hwnd := DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_ROOTOWNER, &quot;ptr&quot;)
   hwnd := DllCall(&quot;GetLastActivePopup&quot;, &quot;uptr&quot;, hwnd, &quot;ptr&quot;)
   return hwnd
}

IsWindowOnCurrentVirtualDesktop(hwnd)
{
   static IVirtualDesktopManager
   if !IVirtualDesktopManager
      IVirtualDesktopManager := ComObjCreate(CLSID_VirtualDesktopManager := &quot;{AA509086-5CA9-4C25-8F95-589D3C07B48A}&quot;, IID_IVirtualDesktopManager := &quot;{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}&quot;)
   DllCall(NumGet(NumGet(IVirtualDesktopManager+0), 3*A_PtrSize), &quot;ptr&quot;, IVirtualDesktopManager, &quot;uptr&quot;, hwnd, &quot;int*&quot;, onCurrentDesktop)   ; IsWindowOnCurrentVirtualDesktop
   return onCurrentDesktop
}

PropEnumProcEx(hWnd, lpszString, hData, dwData)
{
   if (strget(lpszString, &quot;UTF-16&quot;) = &quot;ApplicationViewCloakType&quot;)
   {
      numput(hData, dwData+0, 0, &quot;int&quot;)
      return false
   }
   return true
}

realHwnd(hwnd)
{
   varsetcapacity(var, 8, 0)
   numput(hwnd, var, 0, &quot;uint64&quot;)
   return numget(var, 0, &quot;uint&quot;)
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[serzh82saratov]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=27879</uri>
			</author>
			<updated>2024-08-20T06:42:07Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=161447#p161447</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159366#p159366" />
			<content type="html"><![CDATA[<p>Поправил. Без недокументированных функций я так и не обнаружил возможность определить из-за чего наложен cloak shell - из-за того, что окно бекграундное/системное или из-за того, что оно находится на другом виртуальном дисплее.</p>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2023-10-17T01:06:19Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159366#p159366</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159365#p159365" />
			<content type="html"><![CDATA[<p>Только в таком варианте до того, как выдаст сообщение &quot;Your %A_OSVersion% can not handle virtual desktops&quot;, выскочит ошибка из строки<br /></p><div class="codebox"><pre><code>static IVirtualDesktopManager := ComObjCreate ...</code></pre></div>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2023-10-16T22:39:53Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159365#p159365</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159364#p159364" />
			<content type="html"><![CDATA[<p>С этим апи также приходится использовать исключения.<br /></p><div class="codebox"><pre><code>DetectHiddenWindows On
arr := EnumerateAltTabWindows()
for k, v in arr
{
   WinGetClass, winClass, ahk_id %v%
   WinGetTitle, title, ahk_id %v%
   altTabWindows .= A_Index &quot;`nTitle: &quot; title &quot;`nClass: &quot; winClass &quot;`nhWnd: &quot; v &quot;`nLastActivePopup: &quot; format(&quot;0x{:x}&quot;, GetLastActivePopup(v)) &quot;`n`n&quot;
}
MsgBox, % altTabWindows


EnumerateAltTabWindows()
{
   AltTabList := []
   WinGet, list, List
   Loop % list
   {
      if IsAltTabWindow(list%A_Index%)
         AltTabList.Push(list%A_Index%)
   }
   Return AltTabList
}

IsAltTabWindow(hwnd)
{
   static ImmersiveShell, IApplicationViewCollection, MONITOR_DEFAULTTONULL := 0, VirtualDesktopAltTabFilter := &quot;null&quot;, PropEnumProcEx := RegisterCallback(&quot;PropEnumProcEx&quot;, &quot;Fast&quot;, 4)
   if (VirtualDesktopAltTabFilter = &quot;null&quot;)
   {
      RegRead, VirtualDesktopAltTabFilter, HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, VirtualDesktopAltTabFilter
      OSbuildNumber := StrSplit(A_OSVersion, &quot;.&quot;)[3]
      if (OSbuildNumber &lt; 14393)
      {
         msgbox Your %A_OSVersion% can not handle virtual desktops
         exitapp
      }
      else if (OSbuildNumber &lt;= 17134)   ; Windows 10 1607 to 1803 and Windows Server 2016
         IID_IApplicationViewCollection := &quot;{2C08ADF0-A386-4B35-9250-0FE183476FCC}&quot;
      else
         IID_IApplicationViewCollection := &quot;{1841C6D7-4F9D-42C0-AF41-8747538F10E5}&quot;
      if !(ImmersiveShell := ComObjCreate(CLSID_ImmersiveShell := &quot;{C2F03A33-21F5-47FA-B4BB-156362A2F239}&quot;, IID_IUnknown := &quot;{00000000-0000-0000-C000-000000000046}&quot;))
      {
         MsgBox ImmersiveShell not supported.
         ExitApp
      }
      if !(IApplicationViewCollection := ComObjQuery(ImmersiveShell, IID_IApplicationViewCollection, IID_IApplicationViewCollection))
      {
         MsgBox IApplicationViewCollection interface not supported.
         ExitApp	
      }
   }
   WinGetClass, winClass, ahk_id %hWnd%
   if (winClass = &quot;Windows.UI.Core.CoreWindow&quot;)
      return
   if (winClass = &quot;ApplicationFrameWindow&quot;)
   {
      varsetcapacity(ApplicationViewCloakType, 4, 0)
      DllCall(&quot;EnumPropsEx&quot;, &quot;uptr&quot;, hWnd, &quot;ptr&quot;, PropEnumProcEx, &quot;ptr&quot;, &amp;ApplicationViewCloakType)
      if (numget(ApplicationViewCloakType, 0, &quot;int&quot;) = 1)   ; https://github.com/kvakulo/Switcheroo/commit/fa526606d52d5ba066ba0b2b5aa83ed04741390f
         return
   }
   ; if !DllCall(&quot;MonitorFromWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, MONITOR_DEFAULTTONULL, &quot;ptr&quot;)   ; test if window is shown on any monitor. alt-tab shows any window even if window is out of monitor.
   ;   return
   DllCall(NumGet(NumGet(IApplicationViewCollection+0)+6*A_PtrSize), &quot;ptr&quot;, IApplicationViewCollection, &quot;uptr&quot;, hwnd, &quot;ptr*&quot;, pView)   ; GetViewForHwnd
   if pView
   {
      DllCall(NumGet(NumGet(pView+0)+27*A_PtrSize), &quot;ptr&quot;, pView, &quot;int*&quot;, ShowInSwitchers)   ; GetShowInSwitchers
      ObjRelease(pView)
   }
   if ShowInSwitchers and ((VirtualDesktopAltTabFilter = 0) or IsWindowOnCurrentVirtualDesktop(hwnd))
      return true
   return
}

GetLastActivePopup(hwnd)
{
   static GA_ROOTOWNER := 3
   hwnd := DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_ROOTOWNER, &quot;ptr&quot;)
   hwnd := DllCall(&quot;GetLastActivePopup&quot;, &quot;uptr&quot;, hwnd, &quot;ptr&quot;)
   return hwnd
}

IsWindowOnCurrentVirtualDesktop(hwnd)
{
   static IVirtualDesktopManager
   if !IVirtualDesktopManager
      IVirtualDesktopManager := ComObjCreate(CLSID_VirtualDesktopManager := &quot;{AA509086-5CA9-4C25-8F95-589D3C07B48A}&quot;, IID_IVirtualDesktopManager := &quot;{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}&quot;)
   DllCall(NumGet(NumGet(IVirtualDesktopManager+0), 3*A_PtrSize), &quot;ptr&quot;, IVirtualDesktopManager, &quot;uptr&quot;, hwnd, &quot;int*&quot;, onCurrentDesktop)   ; IsWindowOnCurrentVirtualDesktop
   return onCurrentDesktop
}

PropEnumProcEx(hWnd, lpszString, hData, dwData)
{
   if (strget(lpszString, &quot;UTF-16&quot;) = &quot;ApplicationViewCloakType&quot;)
   {
      numput(hData, dwData+0, 0, &quot;int&quot;)
      return false
   }
   return true
}</code></pre></div><p>Вариант без использования недокументированных функций (получаем окна только на активном virtual display):<br /></p><div class="codebox"><pre><code>DetectHiddenWindows On
arr := EnumerateAltTabWindows()
for k, v in arr
{
   WinGetClass, winClass, ahk_id %v%
   WinGetTitle, title, ahk_id %v%
   altTabWindows .= A_Index &quot;`nTitle: &quot; title &quot;`nClass: &quot; winClass &quot;`nhWnd: &quot; v &quot;`nLastActivePopup: &quot; format(&quot;0x{:x}&quot;, GetLastActivePopup(v)) &quot;`n`n&quot;
}
MsgBox, % altTabWindows


EnumerateAltTabWindows()
{
   AltTabList := []
   WinGet, list, List
   Loop % list
   {
      if IsAltTabWindow(list%A_Index%)
         AltTabList.Push(list%A_Index%)
   }
   Return AltTabList
}

IsAltTabWindow(hWnd)
{
   static WS_EX_APPWINDOW := 0x40000, WS_EX_TOOLWINDOW := 0x80, DWMWA_CLOAKED := 14, DWM_CLOAKED_SHELL := 2, WS_EX_NOACTIVATE := 0x8000000, GA_PARENT := 1, GW_OWNER := 4, MONITOR_DEFAULTTONULL := 0, VirtualDesktopExist, PropEnumProcEx := RegisterCallback(&quot;PropEnumProcEx&quot;, &quot;Fast&quot;, 4)
   if (VirtualDesktopExist = &quot;&quot;)
   {
      OSbuildNumber := StrSplit(A_OSVersion, &quot;.&quot;)[3]
      if (OSbuildNumber &lt; 14393)
         VirtualDesktopExist := 0
      else
         VirtualDesktopExist := 1
   }
   if !DllCall(&quot;IsWindowVisible&quot;, &quot;uptr&quot;, hWnd)
      return
   DllCall(&quot;DwmApi\DwmGetWindowAttribute&quot;, &quot;uptr&quot;, hWnd, &quot;uint&quot;, DWMWA_CLOAKED, &quot;uint*&quot;, cloaked, &quot;uint&quot;, 4)
   if (cloaked = DWM_CLOAKED_SHELL)
      return
   if (realHwnd(DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_PARENT, &quot;ptr&quot;)) != realHwnd(DllCall(&quot;GetDesktopWindow&quot;, &quot;ptr&quot;)))
      return
   WinGetClass, winClass, ahk_id %hWnd%
   if (winClass = &quot;Windows.UI.Core.CoreWindow&quot;)
      return
   if (winClass = &quot;ApplicationFrameWindow&quot;)
   {
      varsetcapacity(ApplicationViewCloakType, 4, 0)
      DllCall(&quot;EnumPropsEx&quot;, &quot;uptr&quot;, hWnd, &quot;ptr&quot;, PropEnumProcEx, &quot;ptr&quot;, &amp;ApplicationViewCloakType)
      if (numget(ApplicationViewCloakType, 0, &quot;int&quot;) = 1)   ; https://github.com/kvakulo/Switcheroo/commit/fa526606d52d5ba066ba0b2b5aa83ed04741390f
         return
   }
   ; if !DllCall(&quot;MonitorFromWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, MONITOR_DEFAULTTONULL, &quot;ptr&quot;)   ; test if window is shown on any monitor. alt-tab shows any window even if window is out of monitor.
   ;   return
   WinGet, exStyles, ExStyle, ahk_id %hWnd%
   if (exStyles &amp; WS_EX_APPWINDOW)
   {
      if DllCall(&quot;GetProp&quot;, &quot;uptr&quot;, hWnd, &quot;str&quot;, &quot;ITaskList_Deleted&quot;, &quot;ptr&quot;)
         return
      if (VirtualDesktopExist = 0) or IsWindowOnCurrentVirtualDesktop(hwnd)
         return true
      else
         return
   }
   if (exStyles &amp; WS_EX_TOOLWINDOW) or (exStyles &amp; WS_EX_NOACTIVATE)
      return
   loop
   {
      hwndPrev := hwnd
      hwnd := DllCall(&quot;GetWindow&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GW_OWNER, &quot;ptr&quot;)
      if !hwnd
      {
         if DllCall(&quot;GetProp&quot;, &quot;uptr&quot;, hwndPrev, &quot;str&quot;, &quot;ITaskList_Deleted&quot;, &quot;ptr&quot;)
            return
         if (VirtualDesktopExist = 0) or IsWindowOnCurrentVirtualDesktop(hwndPrev)
            return true
         else
            return
      }
      if DllCall(&quot;IsWindowVisible&quot;, &quot;uptr&quot;, hwnd)
         return
      WinGet, exStyles, ExStyle, ahk_id %hwnd%
      if ((exStyles &amp; WS_EX_TOOLWINDOW) or (exStyles &amp; WS_EX_NOACTIVATE)) and !(exStyles &amp; WS_EX_APPWINDOW)
         return
   }
}

GetLastActivePopup(hwnd)
{
   static GA_ROOTOWNER := 3
   hwnd := DllCall(&quot;GetAncestor&quot;, &quot;uptr&quot;, hwnd, &quot;uint&quot;, GA_ROOTOWNER, &quot;ptr&quot;)
   hwnd := DllCall(&quot;GetLastActivePopup&quot;, &quot;uptr&quot;, hwnd, &quot;ptr&quot;)
   return hwnd
}

IsWindowOnCurrentVirtualDesktop(hwnd)
{
   static IVirtualDesktopManager
   if !IVirtualDesktopManager
      IVirtualDesktopManager := ComObjCreate(CLSID_VirtualDesktopManager := &quot;{AA509086-5CA9-4C25-8F95-589D3C07B48A}&quot;, IID_IVirtualDesktopManager := &quot;{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}&quot;)
   DllCall(NumGet(NumGet(IVirtualDesktopManager+0), 3*A_PtrSize), &quot;ptr&quot;, IVirtualDesktopManager, &quot;uptr&quot;, hwnd, &quot;int*&quot;, onCurrentDesktop)   ; IsWindowOnCurrentVirtualDesktop
   return onCurrentDesktop
}

PropEnumProcEx(hWnd, lpszString, hData, dwData)
{
   if (strget(lpszString, &quot;UTF-16&quot;) = &quot;ApplicationViewCloakType&quot;)
   {
      numput(hData, dwData+0, 0, &quot;int&quot;)
      return false
   }
   return true
}

realHwnd(hwnd)
{
   varsetcapacity(var, 8, 0)
   numput(hwnd, var, 0, &quot;uint64&quot;)
   return numget(var, 0, &quot;uint&quot;)
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2023-10-16T22:26:13Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159364#p159364</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159359#p159359" />
			<content type="html"><![CDATA[<p>Да, отличная находка.<br />Спасибо!<br />Кстати, сами майкрософтцы его не используют, а используют исключения:<br /></p><div class="codebox"><pre><code>newWindow.ClassName != &quot;Windows.UI.Core.CoreWindow&quot;</code></pre></div><p><a href="https://github.com/microsoft/PowerToys/blob/main/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs#L116">https://github.com/microsoft/PowerToys/ … ws.cs#L116</a></p>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2023-10-16T19:55:51Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159359#p159359</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159358#p159358" />
			<content type="html"><![CDATA[<p>Ну мы в начале топика говорили о получении окон в порядке активации.<br /></p><div class="quotebox"><cite>teadrinker пишет:</cite><blockquote><p>А вот GetShowInSwitchers, это не то, что надо для определения AltTab?</p></blockquote></div><p>Похоже оно самое.</p>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2023-10-16T19:35:27Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159358#p159358</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159357#p159357" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>не показать точное время активации скрипта, а сравнить это время с другими окнами</p></blockquote></div><p>В смысле, активации окна? Ну, если нужно сравнивать, то подойдёт, если точное время, тогда нет, зависит от задачи.</p>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2023-10-16T18:49:32Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159357#p159357</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159356#p159356" />
			<content type="html"><![CDATA[<p>Например для того, чтобы не держать время активаций в скрипте.<br />Но я тут не совсем тебя понимаю, у нас же цель не показать точное время активации скрипта, а сравнить это время с другими окнами.</p>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2023-10-16T18:46:57Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159356#p159356</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159355#p159355" />
			<content type="html"><![CDATA[<p>А вот GetShowInSwitchers, это не то, что надо для определения AltTab?</p>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2023-10-16T18:45:16Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159355#p159355</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: аналог altTab для окон определенной программы]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=159354#p159354" />
			<content type="html"><![CDATA[<p>Ну это уж совсем костыль. <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /> Если отслеживать время активаций, то зачем нужен этот метод.</p>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2023-10-16T18:39:44Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=159354#p159354</id>
		</entry>
</feed>
