Is there a way to put an icon outside the hidden tray icons by default?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
JoeWinograd
Posts: 2200
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Is there a way to put an icon outside the hidden tray icons by default?

30 Jun 2020, 16:24

teadrinker wrote:but on my Windows 10 2004 returns an error
Same here on my W10 v2004. The error 0x80070490 appeared in a tooltip near the mouse pointer and did not go away until a reboot.
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Is there a way to put an icon outside the hidden tray icons by default?

30 Jun 2020, 23:01

JoeWinograd wrote:
30 Jun 2020, 16:04
I keep a keen eye out for this issue and don't recollect anything from this morning, although it's possible that I missed it...but I just checked all my emails from the group yesterday and today...no dice. Regards, Joe
very weird, I must have been looking at an old post thinking it was new, but I still can't find what I thought I saw in a search (maybe I'm just losing it!) anyway somehow my memory got sparked to revisit this thread, the interface is there i think its just a matter of handling the expanded exported functions list... I'm still trying to understand how this works

Callback handling...
https://gist.github.com/ysc3839/25e8ed113c4e975b6781c9759ed4ee87

Code: Select all

//Win7
 NotificationMgr<ITrayNotify> NotiMgr(pTrayNotify);
 hr = pTrayNotify->RegisterCallback(&NotiMgr);
 pTrayNotify->RegisterCallback(nullptr);

//Win8
 ULONG callback_id = 0;
 NotificationMgr<ITrayNotifyWin8> NotiMgr8(pTrayNotifyW8);
 hr = pTrayNotifyW8->RegisterCallback(&NotiMgr8, &callback_id);
 hr = pTrayNotifyW8->UnregisterCallback(&callback_id);
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
User avatar
JoeWinograd
Posts: 2200
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Is there a way to put an icon outside the hidden tray icons by default?

02 Jul 2020, 17:50

vondess wrote:Just drag the said script's tray icon from the system stray pop-up and put it on the task bar.
Hi vondess,
You're not understanding the issue on two fronts. First, we're looking for a programmatic solution, so having the user drag the icon is not what we want. Second, we're not talking about the taskbar...we're talking about the system tray and its two components...the main/primary notification area, which is technically called "Shell_TrayWnd", and the overflow/secondary notification area, which is technically called "NotifyIconOverflowWindow". What we're looking for is a programmatic method either to (1) move an icon from NotifyIconOverflowWindow to Shell_TrayWnd or (2) force Windows to create the icon in Shell_TrayWnd, not NotifyIconOverflowWindow. Regards, Joe
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Is there a way to put an icon outside the hidden tray icons by default?

02 Jul 2020, 18:16

i think he is only mistaken on the fact that we want a programmatic solution

its common terminology to call the entire full width bar the "task bar" including the system tray, so it makes perfect sense when he says from the system stray pop-up and put it on the task bar that he means drag the icon to the always visible system tray and it will stay there...


but yes, we want to do it via the windows API, so no dragging, no moving icons manually from parent to parent, there is an "undocumented" winAPI method called iTrayNotify that is documented well on the web by those other than Microsoft... the oldest version from windows 7 works as designed, proven fully functional above by teadrinker/jeeswg. I will be the first to admit that Microsoft made a correct decision by making not publishing this functionality, as I HATE apps that I install that do this... but I don't see any reason it can't be optional for elective software, and in a corporate environment is where I really need it (i use the color of my tray icon to reflect different information so I can monitor things throughout the shop without touching)

so the only outstanding part of the scripted solution is to figure out the differences needed to make the newer Windows 8+ version, iTrayNotifyWindows8 function similarly... I documented the differences above as best I understand, but I believe the way the exported function list has changed needs to be addressed, including UnRegisterCallback and the extra parameter on the RegisterCB
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
jadams
Posts: 73
Joined: 13 Mar 2020, 10:48

Re: Is there a way to put an icon outside the hidden tray icons by default?

13 Jul 2020, 14:56

I also really need this.

Thought I would share a link for a solution using powershell and GPO:

https://4sysops.com/archives/forcing-notification-area-icons-to-always-show-in-windows-7-or-windows-8/

Understanding that code well enough to convert it to autohotkey is well above my pay grade, but I thought somebody here might be able to use that to come up with a workable solution.

Really hoping somebody can come up with a working class.
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there a way to put an icon outside the hidden tray icons by default?

14 Jul 2020, 14:34

@jadams
Of course, I can translate this script to AHK. But there is one issue:
Micah Rowland wrote:So we have our script, but there’s one last wrinkle. The IconStreams registry value is read into memory by Explorer.exe when explorer loads and all changes to the notification area are stored in memory, then written to the registry on shutdown. This means that if we run our script, not only will we see no results right away, those results will be overwritten with the current settings when we restart the computer. Not good. It’s a simple fix though. We launch our script from a batch file and we execute taskkill /im explorer.exe /f then we execute our script, then we restart explorer.exe.
So, first you have to kill explorer.exe, then run the script, then restart the explorer. It's not a problem?
jadams
Posts: 73
Joined: 13 Mar 2020, 10:48

Re: Is there a way to put an icon outside the hidden tray icons by default?

26 Aug 2020, 14:46

Sorry for being so slow to reply... I missed this message.

I would be quite happy to accept restarting Explorer as part of the fix. If you can post working code, I'd be grateful :-) 
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there a way to put an icon outside the hidden tray icons by default?

28 Aug 2020, 18:43

@jadams
As I understood, this code changes existing register entries, but can't add new ones, so you can't use it for a new application.
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Is there a way to put an icon outside the hidden tray icons by default?

27 Sep 2020, 11:55

note to self and interested parties, here are some references to digest to help understand what is needed to convert iTrayNotify (functioning on Win7 thanks to @teadrinker above) to iTrayNotifyWin8 with these changes, id passed as second param to registercallback, new unregistercallback method using that id, new DoAction

Code: Select all

HRESULT RegisterCallback (INotificationCB *,unsigned long *)
HRESULT UnregisterCallback (unsigned long *)
HRESULT DoAction (Dummy) //Look at virtual function table for correct signature
GUID 25DEAD04-1EAC-4911-9E3A-AD0A4AB560FD
Google Chrome source with good comments:
https://chromium.googlesource.com/chrom ... ger_win.cc
https://hianz.wordpress.com/
https://gist.github.com/ysc3839/25e8ed113c4e975b6781c9759ed4ee87
https://gist.github.com/anaisbetts/e90c7d89624d1b1adc72
https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/TrayHelper.cs
https://jira.reactos.org/secure/attachment/33858/traynotify.cpp
https://titanwolf.org/Network/Articles/Article?AID=126520c2-c115-4f90-b529-5f9642912564#gsc.tab=0

Edit: https://thread0.wordpress.com/2014/11/09/workaround-windows-tray-area-item-preference/
* callback is to INotificationCB* not iTrayNotify instance?
http://www.geoffchappell.com/studies/windows/shell/explorer/interfaces/inotificationcb/index.htm?tx=30-32
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
jadams
Posts: 73
Joined: 13 Mar 2020, 10:48

Re: Is there a way to put an icon outside the hidden tray icons by default?

28 Sep 2020, 15:36

I have a script that I desperately want this functionality for :-) there is a $100 PayPal donation to whoever can provide working code! 
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Is there a way to put an icon outside the hidden tray icons by default?

28 Sep 2020, 16:08

I'm still trying to make sense of it, but because of the differences between the two interfaces i think we need to use iNotificationCB for the callback (somehow) with iTrayNotifyWin8
MIDL_INTERFACE("D782CCBA-AFB0-43F1-94DB-FDA3779EACCB") INotificationCB : public IUnknown

I think teadrinker got the pointers set right, and that we can ignore the new DoAction method, but I haven't quite made sense of the UnregisterCallback and the new ID and if we need to use them...

Edit: or if we need to ComObjCreate a second time with iNotificationCB? obviously I'm out of my element
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there a way to put an icon outside the hidden tray icons by default?

29 Sep 2020, 00:02

@gwarble
Why do you think that a working solution does exist for the latest Windows version?
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Is there a way to put an icon outside the hidden tray icons by default?

29 Sep 2020, 04:44

I think it does not exist.
teadrinker, Your error check is not right.

Code: Select all

msgbox % Format("{:#x}", "") ; must be 0
Function can be called something like this:

Code: Select all

CLSID_TrayNotify := "{25DEAD04-1EAC-4911-9E3A-AD0A4AB560FD}"
IID_ITrayNotify8 := "{D133CE13-3537-48BA-93A7-AFCD5D2053B4}"
t := 1

q::
   pITrayNotify8 := ComObjCreate(CLSID_TrayNotify, IID_ITrayNotify8)
   VarSetCapacity(NOTIFYITEM, A_PtrSize*4 + 8 + 16 + A_PtrSize*8, 0)
   str := "AutoHotkey.exe"
   NumPut(&str, NOTIFYITEM)
   NumPut(A_ScriptHwnd, NOTIFYITEM, A_PtrSize*3)
   NumPut((t := !t) + 1, NOTIFYITEM, A_PtrSize*4, "UInt")
   NumPut(0x404, NOTIFYITEM, A_PtrSize*4 + 4, "UInt")
   msgbox % DllCall(NumGet(NumGet(pITrayNotify8+0) + 5*A_PtrSize), "Ptr", pITrayNotify8, "Ptr", &NOTIFYITEM, "UInt") ; SetPreference
   ObjRelease(pITrayNotify8)
Return
2147943568 = 0x80070490 = Element not found.
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Is there a way to put an icon outside the hidden tray icons by default?

29 Sep 2020, 08:31

malcev wrote:

Code: Select all

VarSetCapacity(NOTIFYITEM, A_PtrSize*4 + 8 + 16 + A_PtrSize*8, 0)

Code: Select all

typedef struct tagNOTIFYITEM
{
	PWSTR pszExeName;
	PWSTR pszTip;
	HICON hIcon;
	HWND hWnd;
	NOTIFYITEM_PREFERENCE dwPreference;
	UINT uID;
	GUID guidItem;
} NOTIFYITEM, *PNOTIFYITEM;
Why A_PtrSize*4 + 8 + 16 + A_PtrSize*8 ?
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Is there a way to put an icon outside the hidden tray icons by default?

29 Sep 2020, 09:11

teadrinker wrote:
29 Sep 2020, 00:02
@gwarble
Why do you think that a working solution does exist for the latest Windows version?
only because of the linked examples above. I know there is a new interface for iTrayNotify as of Windows 8 that replaced the working version for Windows 7, so from the examples above I would only conclude that there is a working solution for Windows 8 and was hopeful that it would work in Windows 10. I do not currently have a Windows 8 setup to test on but I can if you think there actually is no solution on Windows 10 we could at least prove the interface working on WIndows 8. (anyone care to test in Win8?)

Edit: comment from malcev's link:
// Attention: This code DOES NOT work in Win10 Fall Creators Update or later. (2017/10/26)
Thanks for pointing that out guys, too bad, I wonder if they created a new hidden/undocumented interface
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Is there a way to put an icon outside the hidden tray icons by default?

06 Nov 2020, 06:11

You can try to force to add icon to Shell_TrayWnd like this:

Code: Select all

DetectHiddenWindows on
CoordMode, Mouse, Screen
SetBatchLines -1
ControlGet, hwndOverflowNotificationArea, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
ControlGet, hwndSystemPromotedNotificationArea, hwnd,, ToolbarWindow322, ahk_class Shell_TrayWnd
ControlGet, hwndUserPromotedNotificationArea, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
accOverflowNotificationArea := Acc_ObjectFromWindow(hwndOverflowNotificationArea)
accSystemPromotedNotificationArea := Acc_ObjectFromWindow(hwndSystemPromotedNotificationArea)
accUserPromotedNotificationArea := Acc_ObjectFromWindow(hwndUserPromotedNotificationArea)
loop
{
   loop % accSystemPromotedNotificationArea.accChildCount
   {
      if (accSystemPromotedNotificationArea.accName(A_Index) = A_ScriptName)
         break 2
   }
   loop % accUserPromotedNotificationArea.accChildCount
   {
      if (accUserPromotedNotificationArea.accName(A_Index) = A_ScriptName)
         break 2
   }
   loop % accOverflowNotificationArea.accChildCount
   {
      if (accOverflowNotificationArea.accName(A_Index) = A_ScriptName)
      {
         MouseGetPos, xpos, ypos
         location := Acc_Location(accOverflowNotificationArea, A_Index)
         WinGetPos, WinX, WinY, WinW, WinH, ahk_id %hwndOverflowNotificationArea%
         WinGetPos, taskbarWinX, taskbarWinY, taskbarWinW, taskbarWinH, ahk_class Shell_TrayWnd
         x := location.x + location.w//2 - WinX
         y := location.y + location.h//2 - WinY
         PostMessage, WM_LBUTTONDOWN := 0x201, 1, ((y<<16)^x),, ahk_id %hwndOverflowNotificationArea%
         sleep 150
         if (taskbarWinY != 0)   ; taskbar down
            MouseMove, location.x+location.w//1.4, taskbarWinY+location.h, 0
         else if (taskbarWinH < A_ScreenHeight)   ; taskbar up
            MouseMove, location.x+location.w//1.4, taskbarWinH-location.h, 0
         else if (taskbarWinX != 0)   ; taskbar right
            MouseMove, taskbarWinX+location.w, location.y+location.h//1.4, 0
         else   ; taskbar left
            MouseMove, taskbarWinW-location.w, location.y+location.h//1.4, 0
         PostMessage, WM_LBUTTONUP := 0x202 , 0, ((y<<16)^x),, ahk_id %hwndOverflowNotificationArea%
         MouseMove, xpos, ypos, 0
         break 2
      }
   }
}
msgbox done
ExitApp





; http://www.autohotkey.com/board/topic/77303-acc-library-ahk-l-updated-09272012/
; https://dl.dropbox.com/u/47573473/Web%20Server/AHK_L/Acc.ahk
;------------------------------------------------------------------------------
; Acc.ahk Standard Library
; by Sean
; Updated by jethrow:
; 	Modified ComObjEnwrap params from (9,pacc) --> (9,pacc,1)
; 	Changed ComObjUnwrap to ComObjValue in order to avoid AddRef (thanks fincs)
; 	Added Acc_GetRoleText & Acc_GetStateText
; 	Added additional functions - commented below
; 	Removed original Acc_Children function
; last updated 2/25/2010
;------------------------------------------------------------------------------

Acc_Init()
{
	Static	h
	If Not	h
		h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "")
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromWindow(hWnd, idObject = -4)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return	ComObjEnwrap(9,pacc,1)
}

Acc_WindowFromObject(pacc)
{
	If	DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
	Return	hWnd
}

Acc_GetRoleText(nRole)
{
	nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
	Return	sRole
}

Acc_GetStateText(nState)
{
	nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
	Return	sState
}

Acc_SetWinEventHook(eventMin, eventMax, pCallback)
{
	Return	DllCall("SetWinEventHook", "Uint", eventMin, "Uint", eventMax, "Uint", 0, "Ptr", pCallback, "Uint", 0, "Uint", 0, "Uint", 0)
}

Acc_UnhookWinEvent(hHook)
{
	Return	DllCall("UnhookWinEvent", "Ptr", hHook)
}
/*	Win Events:
	pCallback := RegisterCallback("WinEventProc")
	WinEventProc(hHook, event, hWnd, idObject, idChild, eventThread, eventTime)
	{
		Critical
		Acc := Acc_ObjectFromEvent(_idChild_, hWnd, idObject, idChild)
		; Code Here:
	}
*/

; Written by jethrow
Acc_Role(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_State(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
	try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
	catch
		return
	Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
	return	{x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
}
Acc_Parent(Acc) { 
	try parent:=Acc.accParent
	return parent?Acc_Query(parent):
}
Acc_Child(Acc, ChildId=0) {
	try child:=Acc.accChild(ChildId)
	return child?Acc_Query(child):
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
	try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
	static setting:=0
	return p=""?setting:setting:=p
}
Acc_Children(Acc) {
	if ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			return Children.MaxIndex()?Children:
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_ChildrenByRole(Acc, Role) {
	if ComObjType(Acc,"Name")!="IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren% {
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
				if NumGet(varChildren,i-8)=9
					AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
				else
					Acc_Role(Acc, child)=Role?Children.Insert(child):
			}
			return Children.MaxIndex()?Children:, ErrorLevel:=0
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
	static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
	AccObj :=   IsObject(WinTitle)? WinTitle
			:   Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
	if ComObjType(AccObj, "Name") != "IAccessible"
		ErrorLevel := "Could not access an IAccessible Object"
	else {
		StringReplace, ChildPath, ChildPath, _, %A_Space%, All
		AccError:=Acc_Error(), Acc_Error(true)
		Loop Parse, ChildPath, ., %A_Space%
			try {
				if A_LoopField is digit
					Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
				else
					RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
				if Not Children.HasKey(m2)
					throw
				AccObj := Children[m2]
			} catch {
				ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
				if Acc_Error()
					throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
				return
			}
		Acc_Error(AccError)
		StringReplace, Cmd, Cmd, %A_Space%, , All
		properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
		try {
			if (Cmd = "Location")
				AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
			  , ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
			else if (Cmd = "Object")
				ret_val := AccObj
			else if Cmd in Role,State
				ret_val := Acc_%Cmd%(AccObj, ChildID+0)
			else if Cmd in ChildCount,Selection,Focus
				ret_val := AccObj["acc" Cmd]
			else
				ret_val := AccObj["acc" Cmd](ChildID+0)
		} catch {
			ErrorLevel := """" Cmd """ Cmd Not Implemented"
			if Acc_Error()
				throw Exception("Cmd Not Implemented", -1, Cmd)
			return
		}
		return ret_val, ErrorLevel:=0
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
User avatar
JoeWinograd
Posts: 2200
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Is there a way to put an icon outside the hidden tray icons by default?

06 Nov 2020, 13:32

malcev wrote:You can try to force to add icon to Shell_TrayWnd like this
Hi malcev,
First, thanks very much for this code! I have high hopes of getting it to work for me. In that regard, I tried to turn your code into a function so that I can call it from my programs. Here's what I did:

Code: Select all

ShellTrayWnd(EXEname)
{
  ControlGet, hwndOverflowNotificationArea, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
  ControlGet, hwndSystemPromotedNotificationArea, hwnd,, ToolbarWindow322, ahk_class Shell_TrayWnd
  ControlGet, hwndUserPromotedNotificationArea, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
  accOverflowNotificationArea := Acc_ObjectFromWindow(hwndOverflowNotificationArea)
  accSystemPromotedNotificationArea := Acc_ObjectFromWindow(hwndSystemPromotedNotificationArea)
  accUserPromotedNotificationArea := Acc_ObjectFromWindow(hwndUserPromotedNotificationArea)
  loop
  {
     loop % accSystemPromotedNotificationArea.accChildCount
     {
        if (accSystemPromotedNotificationArea.accName(A_Index) = EXEname)
           break 2
     }
     loop % accUserPromotedNotificationArea.accChildCount
     {
        if (accUserPromotedNotificationArea.accName(A_Index) = EXEname)
           break 2
     }
     loop % accOverflowNotificationArea.accChildCount
     {
        if (accOverflowNotificationArea.accName(A_Index) = EXEname)
*****
***** all the rest of your code is here
*****
The only changes that I made to your code are (1) turning it into a function with one parameter...EXEname and (2) changing all occurrences of A_ScriptName to EXEname. I then tested it with calls like this:

Code: Select all

DetectHiddenWindows on
CoordMode, Mouse, Screen
SetBatchLines -1
ShellTrayWnd("MyCompiledScript.exe")
The compiled program (such as MyCompiledScript.exe) is in NotifyIconOverflowWindow, but after the call to ShellTrayWnd, it is not moved to Shell_TrayWnd. Would really appreciate your help in sorting this. Btw, AHK v1.1.33.02 U64 on W10 Pro v20H2 x64. Thanks, Joe
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Is there a way to put an icon outside the hidden tray icons by default?

06 Nov 2020, 15:21

You can try this code
f11 - from overflow
f12 - to overflow

Code: Select all

program := "file.exe"

DetectHiddenWindows on
CoordMode, Mouse, Screen
SetBatchLines -1
SetWinDelay -1
ControlGet, hwndOverflowNotificationArea, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
ControlGet, hwndSystemPromotedNotificationArea, hwnd,, ToolbarWindow322, ahk_class Shell_TrayWnd
ControlGet, hwndUserPromotedNotificationArea, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
ControlGet, hwndButton, hwnd,, Button2, ahk_class Shell_TrayWnd
accOverflowNotificationArea := Acc_ObjectFromWindow(hwndOverflowNotificationArea)
accSystemPromotedNotificationArea := Acc_ObjectFromWindow(hwndSystemPromotedNotificationArea)
accUserPromotedNotificationArea := Acc_ObjectFromWindow(hwndUserPromotedNotificationArea)
accButton := Acc_ObjectFromWindow(hwndButton)
return

f11::
loop % accOverflowNotificationArea.accChildCount
{
   if (accOverflowNotificationArea.accName(A_Index) = program)
   {
      MouseGetPos, xpos, ypos
      location := Acc_Location(accOverflowNotificationArea, A_Index)
      WinGetPos, WinX, WinY,,, ahk_id %hwndOverflowNotificationArea%
      WinGetPos, taskbarWinX, taskbarWinY, taskbarWinW, taskbarWinH, ahk_class Shell_TrayWnd
      x := location.x + location.w//2 - WinX
      y := location.y + location.h//2 - WinY
      PostMessage, WM_LBUTTONDOWN := 0x201, 1, ((y<<16)^x),, ahk_id %hwndOverflowNotificationArea%
      if (taskbarWinY != 0)   ; taskbar down
         MouseMove, location.x+location.w//1.4, taskbarWinY+location.h, 0
      else if (taskbarWinH < A_ScreenHeight)   ; taskbar up
         MouseMove, location.x+location.w//1.4, taskbarWinH-location.h, 0
      else if (taskbarWinX != 0)   ; taskbar right
         MouseMove, taskbarWinX+location.w, location.y+location.h//1.4, 0
      else   ; taskbar left
         MouseMove, taskbarWinW-location.w, location.y+location.h//1.4, 0
      PostMessage, WM_LBUTTONUP := 0x202 , 0, ((y<<16)^x),, ahk_id %hwndOverflowNotificationArea%
      MouseMove, xpos, ypos, 0
      break
   }
}
return

f12::
loop 2
{
   if (A_Index = 1)
      accToolbar := accUserPromotedNotificationArea
   else
      accToolbar := accSystemPromotedNotificationArea
   loop % accToolbar.accChildCount
   {
      if (accToolbar.accName(A_Index) = program)
      {
         CurrentWindow := WinExist("A")
         MouseGetPos, xpos, ypos
         location := Acc_Location(accToolbar, A_Index)
         WinGetPos, taskbarWinX, taskbarWinY, taskbarWinW, taskbarWinH, ahk_class Shell_TrayWnd
         WinActivate, ahk_class Shell_TrayWnd
         x := location.x + location.w//2
         y := location.y + location.h//2
         if (taskbarWinY != 0)   ; taskbar down
            MouseClickDrag, left, x, y, x, taskbarWinY-location.h, 0
         else if (taskbarWinH < A_ScreenHeight)   ; taskbar up
            MouseClickDrag, left, x, y, x, taskbarWinH+location.h, 0
         else if (taskbarWinX != 0)   ; taskbar right
            MouseClickDrag, left, x, y, taskbarWinX-location.w, y, 0
         else   ; taskbar left
            MouseClickDrag, left, x, y, taskbarWinW+location.w, y, 0
         if (accOverflowNotificationArea.accChildCount != 1)
            accButton.accDoDefaultAction(0)
         WinActivate, ahk_id %CurrentWindow%
         MouseMove, xpos, ypos, 0
         break 2
     }
   }
}
return





; http://www.autohotkey.com/board/topic/77303-acc-library-ahk-l-updated-09272012/
; https://dl.dropbox.com/u/47573473/Web%20Server/AHK_L/Acc.ahk
;------------------------------------------------------------------------------
; Acc.ahk Standard Library
; by Sean
; Updated by jethrow:
; 	Modified ComObjEnwrap params from (9,pacc) --> (9,pacc,1)
; 	Changed ComObjUnwrap to ComObjValue in order to avoid AddRef (thanks fincs)
; 	Added Acc_GetRoleText & Acc_GetStateText
; 	Added additional functions - commented below
; 	Removed original Acc_Children function
; last updated 2/25/2010
;------------------------------------------------------------------------------

Acc_Init()
{
	Static	h
	If Not	h
		h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "")
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromWindow(hWnd, idObject = -4)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return	ComObjEnwrap(9,pacc,1)
}

Acc_WindowFromObject(pacc)
{
	If	DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
	Return	hWnd
}

Acc_GetRoleText(nRole)
{
	nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
	Return	sRole
}

Acc_GetStateText(nState)
{
	nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
	Return	sState
}

Acc_SetWinEventHook(eventMin, eventMax, pCallback)
{
	Return	DllCall("SetWinEventHook", "Uint", eventMin, "Uint", eventMax, "Uint", 0, "Ptr", pCallback, "Uint", 0, "Uint", 0, "Uint", 0)
}

Acc_UnhookWinEvent(hHook)
{
	Return	DllCall("UnhookWinEvent", "Ptr", hHook)
}
/*	Win Events:
	pCallback := RegisterCallback("WinEventProc")
	WinEventProc(hHook, event, hWnd, idObject, idChild, eventThread, eventTime)
	{
		Critical
		Acc := Acc_ObjectFromEvent(_idChild_, hWnd, idObject, idChild)
		; Code Here:
	}
*/

; Written by jethrow
Acc_Role(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_State(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
	try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
	catch
		return
	Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
	return	{x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
}
Acc_Parent(Acc) { 
	try parent:=Acc.accParent
	return parent?Acc_Query(parent):
}
Acc_Child(Acc, ChildId=0) {
	try child:=Acc.accChild(ChildId)
	return child?Acc_Query(child):
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
	try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
	static setting:=0
	return p=""?setting:setting:=p
}
Acc_Children(Acc) {
	if ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			return Children.MaxIndex()?Children:
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_ChildrenByRole(Acc, Role) {
	if ComObjType(Acc,"Name")!="IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren% {
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
				if NumGet(varChildren,i-8)=9
					AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
				else
					Acc_Role(Acc, child)=Role?Children.Insert(child):
			}
			return Children.MaxIndex()?Children:, ErrorLevel:=0
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
	static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
	AccObj :=   IsObject(WinTitle)? WinTitle
			:   Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
	if ComObjType(AccObj, "Name") != "IAccessible"
		ErrorLevel := "Could not access an IAccessible Object"
	else {
		StringReplace, ChildPath, ChildPath, _, %A_Space%, All
		AccError:=Acc_Error(), Acc_Error(true)
		Loop Parse, ChildPath, ., %A_Space%
			try {
				if A_LoopField is digit
					Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
				else
					RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
				if Not Children.HasKey(m2)
					throw
				AccObj := Children[m2]
			} catch {
				ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
				if Acc_Error()
					throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
				return
			}
		Acc_Error(AccError)
		StringReplace, Cmd, Cmd, %A_Space%, , All
		properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
		try {
			if (Cmd = "Location")
				AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
			  , ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
			else if (Cmd = "Object")
				ret_val := AccObj
			else if Cmd in Role,State
				ret_val := Acc_%Cmd%(AccObj, ChildID+0)
			else if Cmd in ChildCount,Selection,Focus
				ret_val := AccObj["acc" Cmd]
			else
				ret_val := AccObj["acc" Cmd](ChildID+0)
		} catch {
			ErrorLevel := """" Cmd """ Cmd Not Implemented"
			if Acc_Error()
				throw Exception("Cmd Not Implemented", -1, Cmd)
			return
		}
		return ret_val, ErrorLevel:=0
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
User avatar
JoeWinograd
Posts: 2200
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Is there a way to put an icon outside the hidden tray icons by default?

06 Nov 2020, 16:05

malcev wrote:You can try this code
Hi malcev,
I tried the f11 - from overflow code...did not move the icon from overflow. Regards, Joe

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada, Google [Bot], jaka1, mikeyww, Rohwedder and 292 guests