So I use a clock replacement program. The problem is it also hijack clicks on the clock. So whenever I click on the clock in the notification area, program's popup menu launch rather than the default windows clock widget.
I also tried "ControlClick" on "TrayClockWClass". I still didn't get original widget. Is there any way to launch the original widget programmatically? I use Windows 10 1607.
Show Windows 10 native clock widget programmatically Topic is solved
Re: Show Windows 10 native clock widget programmatically
If you're running a 64-bit version of AutoHotkey (this doesn't work with 32-bit; I guess I'm doing something wrong with the VARIANT structure somewhere) - fixed thanks to Eidola, this works with the clock replacement program I use to show the original clock hosted by the Explorer process:
or if you're using the same program as I do, you could try
Code: Select all
ControlGet, hClock, Hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd ; https://autohotkey.com/board/topic/70770-win7-taskbar-clock-toggle/
if (hClock) {
VarSetCapacity(IID_IAccessible, 16), DllCall("ole32\CLSIDFromString", "WStr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "Ptr", &IID_IAccessible)
if (DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hClock, "UInt", OBJID_CLIENT := 0xFFFFFFFC, "Ptr", &IID_IAccessible, "Ptr*", accTrayClock))
return
VarSetCapacity(variant, A_PtrSize == 8 ? 24 : 16, 0), NumPut(VT_I4 := 3, variant,, "UShort")
if (A_PtrSize == 4) ; https://autohotkey.com/boards/viewtopic.php?p=111355#p111355
DllCall(NumGet(NumGet(accTrayClock+0)+25*A_PtrSize), "Ptr", accTrayClock, "Int64", NumGet(variant, 0, "Int64"), Int64, NumGet(variant, 8, "Int64")) ; IAccessible::DoDefaultAction
else
DllCall(NumGet(NumGet(accTrayClock+0)+25*A_PtrSize), "Ptr", accTrayClock, "Ptr", &variant) ; IAccessible::DoDefaultAction
ObjRelease(accTrayClock)
}
Code: Select all
ControlGet, hClock, Hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd ; https://autohotkey.com/board/topic/70770-win7-taskbar-clock-toggle/
PostMessage, 0x466, 1, 0,, ahk_id %hClock%
Last edited by qwerty12 on 19 Oct 2016, 09:28, edited 1 time in total.
Re: Show Windows 10 native clock widget programmatically
Thanks a lot! It worked perfectlyqwerty12 wrote:If you're running a 64-bit version of AutoHotkey (this doesn't work with 32-bit; I guess I'm doing something wrong with the VARIANT structure somewhere), this works with the clock replacement program I use to show the original clock hosted by the Explorer process:
Code: Select all
ControlGet, hClock, Hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd ; https://autohotkey.com/board/topic/70770-win7-taskbar-clock-toggle/ if (hClock) { VarSetCapacity(IID_IAccessible, 16), DllCall("ole32\CLSIDFromString", "WStr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "Ptr", &IID_IAccessible) if (DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hClock, "UInt", OBJID_CLIENT := 0xFFFFFFFC, "Ptr", &IID_IAccessible, "Ptr*", accTrayClock)) return VarSetCapacity(variant, A_PtrSize == 8 ? 24 : 16, 0), NumPut(VT_I4 := 3, variant,, "UShort") DllCall(NumGet(NumGet(accTrayClock+0)+25*A_PtrSize), "Ptr", accTrayClock, "Ptr", &variant) ; IAccessible::DoDefaultAction ObjRelease(accTrayClock) }
Re: Show Windows 10 native clock widget programmatically
Hello, Sadly the code is broken now. AHK crash whenever I call this function on this statement "DllCall(NumGet(NumGet(accTrayClock+0)+25*A_PtrSize), "Ptr", accTrayClock, "Ptr", &variant)". If you get a chance, can you please look into it.qwerty12 wrote: ↑11 Aug 2016, 10:57If you're running a 64-bit version of AutoHotkey(this doesn't work with 32-bit; I guess I'm doing something wrong with the VARIANT structure somewhere)- fixed thanks to Eidola, this works with the clock replacement program I use to show the original clock hosted by the Explorer process:
or if you're using the same program as I do, you could tryCode: Select all
ControlGet, hClock, Hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd ; https://autohotkey.com/board/topic/70770-win7-taskbar-clock-toggle/ if (hClock) { VarSetCapacity(IID_IAccessible, 16), DllCall("ole32\CLSIDFromString", "WStr", "{618736e0-3c3d-11cf-810c-00aa00389b71}", "Ptr", &IID_IAccessible) if (DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hClock, "UInt", OBJID_CLIENT := 0xFFFFFFFC, "Ptr", &IID_IAccessible, "Ptr*", accTrayClock)) return VarSetCapacity(variant, A_PtrSize == 8 ? 24 : 16, 0), NumPut(VT_I4 := 3, variant,, "UShort") if (A_PtrSize == 4) ; https://autohotkey.com/boards/viewtopic.php?p=111355#p111355 DllCall(NumGet(NumGet(accTrayClock+0)+25*A_PtrSize), "Ptr", accTrayClock, "Int64", NumGet(variant, 0, "Int64"), Int64, NumGet(variant, 8, "Int64")) ; IAccessible::DoDefaultAction else DllCall(NumGet(NumGet(accTrayClock+0)+25*A_PtrSize), "Ptr", accTrayClock, "Ptr", &variant) ; IAccessible::DoDefaultAction ObjRelease(accTrayClock) }
Code: Select all
ControlGet, hClock, Hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd ; https://autohotkey.com/board/topic/70770-win7-taskbar-clock-toggle/ PostMessage, 0x466, 1, 0,, ahk_id %hClock%
Re: Show Windows 10 native clock widget programmatically
I recommend You to load all dlls that You use except of User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll.
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Show Windows 10 native clock widget programmatically Topic is solved
For me this works:
Code: Select all
ControlGet, hClock, hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd
accClock := AccObjectFromWindow(hClock, OBJID_CLIENT := 0xFFFFFFFC)
accClock.accDoDefaultAction(0)
AccObjectFromWindow(hWnd, idObject = 0) {
static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}"
, IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
, OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID)
if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0
Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}
Re: Show Windows 10 native clock widget programmatically
Without using comobject it also works.
Just need to add
Just need to add
Code: Select all
DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Show Windows 10 native clock widget programmatically
I do not know too.
But I think that it is good example for understanding how to work with com interfaces.
But I think that it is good example for understanding how to work with com interfaces.
- JoeWinograd
- Posts: 2206
- Joined: 10 Feb 2014, 20:00
- Location: U.S. Central Time Zone
Re: Show Windows 10 native clock widget programmatically
Hi teadrinker,
That is superb code! It works perfectly here on W10 V1909 and V2004. Would you be able to modify that code to expose the W10 horizontal volume slider instead of the clock? You've helped me before with code to enhance my own GUI horizontal volume slider, but I'm wondering if it is possible to expose the native horizontal volume slider programmatically. Thanks again for your help. Regards, Joe
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Show Windows 10 native clock widget programmatically
Hi Joe,
I think it's possible, but I'm not sure that an universal method exists. It depends on what process is associated with the icon, clicking on which you can call up a window with a slider. For me it's RtkNGUI64.exe. You need to know yours.
I think it's possible, but I'm not sure that an universal method exists. It depends on what process is associated with the icon, clicking on which you can call up a window with a slider. For me it's RtkNGUI64.exe. You need to know yours.
- JoeWinograd
- Posts: 2206
- Joined: 10 Feb 2014, 20:00
- Location: U.S. Central Time Zone
Re: Show Windows 10 native clock widget programmatically
Hi teadrinker,
I need a universal method that works on all W10 systems without having to know what each user's EXE is. I'll stick with my own GUI, which is working beautifully since I added your code...does not crash...does not freeze. Regards, Joe
I need a universal method that works on all W10 systems without having to know what each user's EXE is. I'll stick with my own GUI, which is working beautifully since I added your code...does not crash...does not freeze. Regards, Joe
Re: Show Windows 10 native clock widget programmatically
If You need universal method then it will be better to use UI Automation because there You can find elements with AutomationID property.
Or You can find position of volume button with its guid (it is equal AutomationID) and then sending clicks with postmessage, but at this case You have to run ahk with the same bitness as Your system.
Or You can find position of volume button with its guid (it is equal AutomationID) and then sending clicks with postmessage, but at this case You have to run ahk with the same bitness as Your system.
- JoeWinograd
- Posts: 2206
- Joined: 10 Feb 2014, 20:00
- Location: U.S. Central Time Zone
Re: Show Windows 10 native clock widget programmatically
Hi malcev,
Thanks for the comment. What I'm looking for is a way to expose the W10 horizontal volume slider programmatically. A simple left-click on the speaker icon in the system tray does it, but what I want is to do that with AHK code. Once it's exposed, left and right arrow keys will adjust the volume. Regards, Joe
Thanks for the comment. What I'm looking for is a way to expose the W10 horizontal volume slider programmatically. A simple left-click on the speaker icon in the system tray does it, but what I want is to do that with AHK code. Once it's exposed, left and right arrow keys will adjust the volume. Regards, Joe
Re: Show Windows 10 native clock widget programmatically
With UIA it can be done like this:
Code: Select all
f11::
if !hVolume
{
ControlGet, hVolume, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", hVolume, "ptr*", tray) ; IUIAutomation::ElementFromHandle
VOLUME_GUID := DllCall("oleaut32\SysAllocString", "str", "{7820AE73-23E3-4229-82C1-E41CB67D5B9C}", "ptr")
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_BSTR := 8, variant, 0, "ushort")
NumPut(VOLUME_GUID, variant, 8, "ptr")
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
else
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "ptr", &variant, "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
DllCall("oleaut32\SysFreeString", "ptr", VOLUME_GUID)
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", IID_IUIAutomationLegacyIAccessiblePattern := "{828055ad-355b-4435-86d5-3b51c14a9b1b}", "ptr", &GUID)
}
DllCall(NumGet(NumGet(tray+0)+5*A_PtrSize), "ptr", tray, "int", TreeScope_Descendants := 0x4, "ptr", condition, "ptr*", element) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(element+0)+14*A_PtrSize), "ptr", element, "int", UIA_LegacyIAccessiblePatternId := 10018, "ptr", &GUID, "ptr*", legacy) ; IUIAutomationElement::GetCurrentPatternAs
DllCall(NumGet(NumGet(legacy+0)+4*A_PtrSize), "ptr", legacy) ; IUIAutomationLegacyIAccessiblePattern::DoDefaultAction
ObjRelease(element)
ObjRelease(legacy)
- JoeWinograd
- Posts: 2206
- Joined: 10 Feb 2014, 20:00
- Location: U.S. Central Time Zone
Re: Show Windows 10 native clock widget programmatically
Thanks very much, malcev, tested on W10 V1909 and V2004...works perfectly! Regards, Joe
Re: Show Windows 10 native clock widget programmatically
May be it is better to use invoke method instead of legacy dodefaultaction.
Code: Select all
f11::
if !hVolume
{
ControlGet, hVolume, hwnd,, ToolbarWindow323, ahk_class Shell_TrayWnd
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", hVolume, "ptr*", tray) ; IUIAutomation::ElementFromHandle
VOLUME_GUID := DllCall("oleaut32\SysAllocString", "str", "{7820AE73-23E3-4229-82C1-E41CB67D5B9C}", "ptr")
VarSetCapacity(variant, 8+A_PtrSize*2, 0)
NumPut(VT_BSTR := 8, variant, 0, "ushort")
NumPut(VOLUME_GUID, variant, 8, "ptr")
if (A_PtrSize = 4)
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "int64", NumGet(variant, 0, "int64"), "int64", NumGet(variant, 8, "int64"), "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
else
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", UIA_AutomationIdPropertyId := 30011, "ptr", &variant, "ptr*", condition) ; IUIAutomation::CreatePropertyCondition
DllCall("oleaut32\SysFreeString", "ptr", VOLUME_GUID)
}
DllCall(NumGet(NumGet(tray+0)+5*A_PtrSize), "ptr", tray, "int", TreeScope_Descendants := 0x4, "ptr", condition, "ptr*", element) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(element+0)+16*A_PtrSize), "ptr", element, "int", UIA_InvokePatternId := 10000, "ptr*", invoke) ; IUIAutomationElement::GetCurrentPattern
DllCall(NumGet(NumGet(invoke+0)+3*A_PtrSize), "ptr", invoke) ; IInvokeProvider::Invoke
ObjRelease(element)
ObjRelease(invoke)
- JoeWinograd
- Posts: 2206
- Joined: 10 Feb 2014, 20:00
- Location: U.S. Central Time Zone
Re: Show Windows 10 native clock widget programmatically
Hi malcev,
I tested the Invoke method script on V1909. It works perfectly, but so does the legacy DoDefaultAction one. I don't know if one is better to use than the other, but, generally speaking, you're right that it's better to use a current method than a legacy method. Thanks for your follow-up and extra effort on this...very much appreciated! Regards, Joe
I tested the Invoke method script on V1909. It works perfectly, but so does the legacy DoDefaultAction one. I don't know if one is better to use than the other, but, generally speaking, you're right that it's better to use a current method than a legacy method. Thanks for your follow-up and extra effort on this...very much appreciated! Regards, Joe
Re: Show Windows 10 native clock widget programmatically
Thank you for the answer. It worked!teadrinker wrote: ↑05 May 2020, 07:28For me this works:Code: Select all
ControlGet, hClock, hwnd,, TrayClockWClass1, ahk_class Shell_TrayWnd accClock := AccObjectFromWindow(hClock, OBJID_CLIENT := 0xFFFFFFFC) accClock.accDoDefaultAction(0) AccObjectFromWindow(hWnd, idObject = 0) { static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}" , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}" , OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1 , h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr") VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID) if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0 Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE) }
Re: Show Windows 10 native clock widget programmatically
I am wondering if it's possible to update this code for Windows 11 clock widget? Thanks
Who is online
Users browsing this forum: Bing [Bot] and 216 guests