bootybay Posted March 11, 2015 Share Posted March 11, 2015 There is a main GUI and some secondary GUIs. I want to prevent the secondary GUIs to combine with the main GUI in the taskbar. The secondary GUIs can stack with eachother in the taskbar as usual. Is this even possible or does Windows not allow it since it is a single process? If the question is unclear, tell me what I should specify. Link to comment Share on other sites More sharing options...
mpower Posted March 11, 2015 Share Posted March 11, 2015 Are you talking about interfacing with another GUI here or one that you're creating via Autoit? Link to comment Share on other sites More sharing options...
bootybay Posted March 11, 2015 Author Share Posted March 11, 2015 (edited) No just multiple GUIs created via Autoit. Imagine a main window with some information and some buttons. There will spawn more GUI windows with detailed info depending on what you used the specific functions on. And I don't want those additional windows to be combined in the taskbar with the main window. I want them to split as if the main windows and the secondary windows are 2 different applications. So it basically looks like this with all windows stacking together: But I would like the main window be seperated like this: (The SciTE icon represents the main window and the autoit Icon the secondary windows. Everything from the same .au3) Edited March 11, 2015 by bootybay Link to comment Share on other sites More sharing options...
spudw2k Posted March 12, 2015 Share Posted March 12, 2015 I think that's just Win 7 behavior for when a given process has multiple windows. The only way I know of not having overlapped icons like that is to have separate processes with unique process names. There may be a way to do what you want, but I don't know how other than having a second process handle the secondary windows. Anyone else know another method to accomplish what bootybay wants? Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF Link to comment Share on other sites More sharing options...
Solution binhnx Posted March 13, 2015 Solution Share Posted March 13, 2015 (edited) Spend a few minutes to search the internet and found this article by Microsoft: https://msdn.microsoft.com/en-us/magazine/dd942846.aspx According to it, your problem can be solve if you are using Windows 7 or later, using its new 'Taskbar Button' feature. It seems that you are currently using Windows 7, so all we need to do is start writting (porting) code. Yep, porting 6 lines of code in C++ to AutoIt PROPVARIANT pv; InitPropVariantFromString(L"MyAppID", &pv); IPropertyStore* pps; VERIFY(SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&pps))); VERIFY(pps->SetValue(PKEY_AppUserModel_ID, pv)); VERIFY(pps->Commit()); Unluckily, its not easy as it seems to be. Using COM interface in C++ is fast and easy but convert to AutoIt is quite complex. But thanks to tracexx's great ObjCreateInterface function, we can do it much easier. But since it is an experimental function, we want a fallback, which is the boring work. Addition to that, a function is inlined so we cannot using DllCall but rewrite from C++ source. Not much difficult but take a little more time. But here is all you need: expandcollapse popup#include <StructureConstants.au3> #include <WinAPI.au3> Global Enum $VT_EMPTY, $VT_NULL, $VT_I2, $VT_I4, $VT_R4, $VT_R8, _ $VT_CY, $VT_DATE, $VT_BSTR, $VT_DISPATCH, $VT_ERROR, _ $VT_BOOL, $VT_VARIANT, $VT_UNKNOWN, $VT_DECIMAL, _ $VT_I1 = 16, $VT_UI1, $VT_UI2, $VT_UI4, $VT_I8, $VT_UI8, $VT_INT, $VT_UINT, _ $VT_VOID, $VT_HRESULT, $VT_PTR, $VT_SAFEARRAY, $VT_CARRAY, $VT_USERDEFINED, _ $VT_LPSTR, $VT_LPWSTR, _ $VT_RECORD = 36, $VT_INT_PTR, $VT_UINT_PTR, _ $VT_FILETIME = 64, $VT_BLOB, $VT_STREAM, $VT_STORAGE, _ $VT_STREAMED_OBJECT, $VT_STORED_OBJECT, $VT_BLOB_OBJECT, _ $VT_CF, $VT_CLSID, $VT_VERSIONED_STREAM, $VT_BSTR_BLOB = 0XFFF, _ $VT_VECTOR = 0X1000, $VT_ARRAY = 0X2000, $VT_BYREF = 0X4000, $VT_RESERVED = 0X8000, _ $VT_ILLEGAL = 0XFFFF, $VT_ILLEGALMASKED = 0XFFF, $VT_TYPEMASK = 0XFFF Global $tagPROPVARIANT = 'USHORT vt;' & _ ;typedef unsigned short VARTYPE; - in WTypes.h 'WORD wReserved1;' & _ 'WORD wReserved2;' & _ 'WORD wReserved3;' & _ 'LONG;PTR' ;union, use the largest member (BSTRBLOB, which is 96-bit in x64) Global Const $tagPROPERTYKEY = $tagGUID & ';DWORD pid' ; Optinal setting. Default to True (use newer, experimental method). Set to False to use old, stupid but safe method. Global Const $__OPT_EXPERIMENTAL_OBJCREATEINTERFACE = True ; This function is not exposed in any dll, but inlined in propvarutil.h so we need to rewrite it entirely in AutoIt Func _WinAPI_InitPropVariantFromString($sUnicodeString, ByRef $tPROPVARIANT) Static $nPropVariantDataIndex = 8 ; = DllStructGetSize(DllStructCreate('USHORT vt;WORD wReserved1;WORD wReserved2;WORD wReserved3')) DllStructSetData($tPROPVARIANT, 'vt', $VT_LPWSTR) Local $aRet = DllCall('Shlwapi.dll', 'LONG', 'SHStrDupW', _ 'WSTR', $sUnicodeString, 'PTR', DllStructGetPtr($tPROPVARIANT) + $nPropVariantDataIndex) If @error Then Return SetError(@error, @extended, False) Local $bSuccess = $aRet[0] = 0? True : False ; If fails, zero memory of the current PROPVARIANT struct If (Not $bSuccess) Then $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) Return SetExtended($aRet[0], $bSuccess) EndFunc Func _WinAPI_SHGetPropertyStoreForWindow($hWnd, $sIID, ByRef $tPointer) Local $tIID = _WinAPI_GUIDFromString($sIID) Local $pp = IsPtr($tPointer)? $tPointer : DllStructGetPtr($tPointer) Local $aRet = DllCall('Shell32.dll', 'LONG', 'SHGetPropertyStoreForWindow', _ 'HWND', $hWnd, 'STRUCT*', $tIID, 'PTR', $pp) If @error Then Return SetError(@error, @extended, False) Return SetExtended($aRet[0], ($aRet[0] = 0)) EndFunc Global Const $tagPointer = 'PTR' Global Const $tagIUnknown = 'PTR QueryInterface;PTR AddRef;PTR Release' Global Const $tagIPropertyStore = $tagIUnknown & _ ';PTR GetCount;' & _ ;HRESULT GetCount([Out] DWORD* cProps) 'PTR GetAt;' & _ ;HRESULT GetAt([In] DWORD iProp, [Out] PROPERTYKEY* pKey) 'PTR GetValue;' & _ ;HRESULT GetValue([In] PROPERTYKEY& key, [Out] PROPVARIANT * pv) 'PTR SetValue;' & _ ;HRESULT SetValue([In] PROPERTYKEY& key, [In] PROPVARIANT& propvar) 'PTR Commit' ;HRESULT Commit() Func _Win7Helper_PKEY_AppUserModel_ID() Local $tPROPERTYKEY = DllStructCreate($tagPROPERTYKEY) ;PKEY_AppUserModel_ID = { {0x9F4C2855, 0x9F79, 0x4B39, ; {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 5 } _WinAPI_GUIDFromStringEx('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}', _ DllStructGetPtr($tPROPERTYKEY)) DllStructSetData($tPROPERTYKEY, 'pid', 5) Return $tPROPERTYKEY EndFunc ; The application id is an up-to-128-characters string Func _Win7Helper_SetWindowAppId($hWnd, $sId) ; This variable is not change. You can use a global const but a local static is prefered due to it scope Local Static $tPROPERTYKEY = _Win7Helper_PKEY_AppUserModel_ID() ; Create and int PROPVARIANT variable Local $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) _WinAPI_InitPropVariantFromString($sId, $tPROPVARIANT) ; Now create an instance of IPropertyStore interface. We must pass a void** (pointer to pointer) ; We can do it in AutoIt by using a pointer to a struct which have only 1 pointer member. Local $tpIPropertyStore = DllStructCreate($tagPointer) $ret = _WinAPI_SHGetPropertyStoreForWindow($hWnd, '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', $tpIPropertyStore) ; Retrieve the IPropertyStore pointer from result Local $pPropertyStoreObject = DllStructGetData($tpIPropertyStore, 1) ; Now we have a pointer to an IPropertyStore object. ; If you use a new AutoIt version, thank to elegant ObjCreateInterface by tracexx,; ; we can easily call method from the pointer we have If ($__OPT_EXPERIMENTAL_OBJCREATEINTERFACE) Then Local $oPropertyStoreObject = ObjCreateInterface($pPropertyStoreObject, _ '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', _ 'GetCount HRESULT(PTR);GetAt HRESULT(DWORD; PTR);GetValue HRESULT(PTR; PTR);' & _ 'SetValue HRESULT(PTR; PTR);Commit HRESULT()') $oPropertyStoreObject.SetValue(DllStructGetPtr($tPROPERTYKEY), DllStructGetPtr($tPROPVARIANT)) $oPropertyStoreObject.Commit() Else ; But if you don't want to use an experimental function, we can do it manually ; First retrieve the v-table of the object. IPropertyStore is directly inherited from IUnknown ; so we have only one v-table data, merge of IUnknown and IPropertyStore, ; located at the beginning of the object address Local $pIPropertyStore = DllStructGetData(DllStructCreate($tagPointer, $pPropertyStoreObject), 1) Local $tIPropertyStore = DllStructCreate($tagIPropertyStore, $pIPropertyStore) ; With the v-table, we can call methods (yes we use another advanced function, ; but not a beta function so its safe as much as we use it correctly ; We simulate a c++ method, first parameter should be pointer to object itself. ; SetValue DllCallAddress('LONG', DllStructGetData($tIPropertyStore, 'SetValue'), _ 'PTR', $pPropertyStoreObject, _ ; pThis 'PTR', DllStructGetPtr($tPROPERTYKEY), _ 'PTR', DllStructGetPtr($tPROPVARIANT)) DllCallAddress('LONG', DllStructGetData($tIPropertyStore, 'Commit'), 'PTR', $pPropertyStoreObject) EndIf EndFunc ; Demo $hWnd1 = GUICreate('Test1') $hWnd2 = GUICreate('Test2') $hWnd3 = GUICreate('Test3') ; The application id should be unique so it not effect any other application. ; Better use a format like MyCompany(orMyName).MyApplication.WindowId _Win7Helper_SetWindowAppId($hWnd1, 'MyGreatCompany.MyAwesomeApplication.MyElegantWindow1') _Win7Helper_SetWindowAppId($hWnd2, 'MyGreatCompany.MyAwesomeApplication.OhImNotAWindowImAnAlien') _Win7Helper_SetWindowAppId($hWnd3, 'MyGreatCompany.MyAwesomeApplication.MyElegantWindow1') GUISetState(@SW_SHOW, $hWnd1) GUISetState(@SW_SHOW, $hWnd2) GUISetState(@SW_SHOW, $hWnd3) Sleep(10000) Edited March 14, 2015 by binhnx jackchen 1 99 little bugs in the code 99 little bugs! Take one down, patch it around 117 little bugs in the code! Link to comment Share on other sites More sharing options...
bootybay Posted March 13, 2015 Author Share Posted March 13, 2015 (edited) Thank you for your elaborate response. I have some trouble executing the code though since shows me following errors: "C:\TEST.au3"(86,47) : error: _WinAPI_SHGetPropertyStoreForWindow() called with Const or expression on ByRef-param(s). DllStructGetPtr($tpIPropertyStore)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ "C:\TEST.au3"(45,72) : REF: definition of _WinAPI_SHGetPropertyStoreForWindow(). Func _WinAPI_SHGetPropertyStoreForWindow($hWnd, $sIID, ByRef $tPointer) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ C:\TEST.au3 - 1 error(s), 0 warning(s) And thanks to your formatting I just learned that you can connect multiple lines with underscore. EDIT: Small change made it work: ; Now create an instance of IPropertyStore interface. We must pass a void** (pointer to pointer) ; We can do it in AutoIt by using a pointer to a struct which have only 1 pointer member. Local $tpIPropertyStore = DllStructCreate($tagPointer) Local $DLLtpIPropertyStore = DllStructGetPtr($tpIPropertyStore) $ret = _WinAPI_SHGetPropertyStoreForWindow($hWnd, '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', _ $DLLtpIPropertyStore) This is exactly what I was looking for. Thank you very much for making that effort. I will have to spend some time understanding your code. Please fix the few lines in your code and I'll mark the topic as solved. Edited March 13, 2015 by bootybay Link to comment Share on other sites More sharing options...
binhnx Posted March 14, 2015 Share Posted March 14, 2015 Edited I didn't notice that since my AutoIt version can run my script without problems 99 little bugs in the code 99 little bugs! Take one down, patch it around 117 little bugs in the code! Link to comment Share on other sites More sharing options...
mpower Posted March 14, 2015 Share Posted March 14, 2015 Edited I didn't notice that since my AutoIt version can run my script without problems have no idea what you're saying there lol Link to comment Share on other sites More sharing options...
jackchen Posted July 6, 2015 Share Posted July 6, 2015 (edited) Edited I didn't notice that since my AutoIt version can run my script without problemsbinhnx,I'd like to get a window's appid by it's hWnd,is it possible?It would be appreciated if you would add the udf,let's say, _Win7Helper_GetWindowAppId($hWnd). Edited July 6, 2015 by jackchen Link to comment Share on other sites More sharing options...
Zedna Posted July 6, 2015 Share Posted July 6, 2015 (edited) If I understand it right ...I use much simpler way to achieve what OP wants.I just use hWnd of my main GUI as Parent parameter in GUICreate() of another GUI forms in my application ;-)The same apply also for standard Win32 dialogs, for example MessageBox() - use your main GUI's hWnd as Parent parameter for it to avoid multiple icons in taskbar. Edited July 6, 2015 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
jackchen Posted July 10, 2015 Share Posted July 10, 2015 (edited) I've added a Func _Win7Helper_GetWindowAppId($hWnd) to binhnx's codes to get a window's AppId.Func _Win7Helper_GetWindowAppId($hWnd) Local Static $tPROPERTYKEY = _Win7Helper_PKEY_AppUserModel_ID() Local $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) Local $tpIPropertyStore = DllStructCreate('ptr') _WinAPI_SHGetPropertyStoreForWindow($hWnd, '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', $tpIPropertyStore) Local $pPropertyStoreObject = DllStructGetData($tpIPropertyStore, 1) Local $oPropertyStoreObject = ObjCreateInterface($pPropertyStoreObject, _ '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', _ 'GetCount HRESULT(PTR);GetAt HRESULT(DWORD; PTR);GetValue HRESULT(PTR; PTR);' & _ 'SetValue HRESULT(PTR; PTR);Commit HRESULT()') If Not IsObj($oPropertyStoreObject) Then Return SetError(1, 0, '') $oPropertyStoreObject.GetValue(DllStructGetPtr($tPROPERTYKEY), DllStructGetPtr($tPROPVARIANT)) ; Extracts a string value from a PROPVARIANT structure ; http://deletethis.net/dave/dev/setappusermodelid/ ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb776559(v=vs.85).aspx Local $buf = DllStructCreate('wchar[128]') DllCall('Propsys.dll', 'long', 'PropVariantToString', _ 'ptr', DllStructGetPtr($tPROPVARIANT), _ 'ptr', DllStructGetPtr($buf), _ 'uint', DllStructGetSize($buf)) If @error Then Return SetError(@error, @extended, "") Else Return DllStructGetData($buf, 1) EndIf EndFunc And below is the full codes with examples:expandcollapse popup; https://www.autoitscript.com/forum/topic/168099-how-to-prevent-multiple-guis-from-combining-in-the-taskbar/ ; http://stackoverflow.com/questions/28228042/shgetpropertystoreforwindow-how-to-set-properties-on-existing-system-appusermo #include <StructureConstants.au3> #include <WinAPI.au3> Global Enum $VT_EMPTY, $VT_NULL, $VT_I2, $VT_I4, $VT_R4, $VT_R8, _ $VT_CY, $VT_DATE, $VT_BSTR, $VT_DISPATCH, $VT_ERROR, _ $VT_BOOL, $VT_VARIANT, $VT_UNKNOWN, $VT_DECIMAL, _ $VT_I1 = 16, $VT_UI1, $VT_UI2, $VT_UI4, $VT_I8, $VT_UI8, $VT_INT, $VT_UINT, _ $VT_VOID, $VT_HRESULT, $VT_PTR, $VT_SAFEARRAY, $VT_CARRAY, $VT_USERDEFINED, _ $VT_LPSTR, $VT_LPWSTR, _ $VT_RECORD = 36, $VT_INT_PTR, $VT_UINT_PTR, _ $VT_FILETIME = 64, $VT_BLOB, $VT_STREAM, $VT_STORAGE, _ $VT_STREAMED_OBJECT, $VT_STORED_OBJECT, $VT_BLOB_OBJECT, _ $VT_CF, $VT_CLSID, $VT_VERSIONED_STREAM, $VT_BSTR_BLOB = 0XFFF, _ $VT_VECTOR = 0X1000, $VT_ARRAY = 0X2000, $VT_BYREF = 0X4000, $VT_RESERVED = 0X8000, _ $VT_ILLEGAL = 0XFFFF, $VT_ILLEGALMASKED = 0XFFF, $VT_TYPEMASK = 0XFFF Global $tagPROPVARIANT = 'USHORT vt;' & _ ;typedef unsigned short VARTYPE; - in WTypes.h 'WORD wReserved1;' & _ 'WORD wReserved2;' & _ 'WORD wReserved3;' & _ 'LONG;PTR' ;union, use the largest member (BSTRBLOB, which is 96-bit in x64) Global Const $tagPROPERTYKEY = $tagGUID & ';DWORD pid' ; Optinal setting. Default to True (use newer, experimental method). Set to False to use old, stupid but safe method. Global Const $__OPT_EXPERIMENTAL_OBJCREATEINTERFACE = True ; This function is not exposed in any dll, but inlined in propvarutil.h so we need to rewrite it entirely in AutoIt Func _WinAPI_InitPropVariantFromString($sUnicodeString, ByRef $tPROPVARIANT) Static $nPropVariantDataIndex = 8 ; = DllStructGetSize(DllStructCreate('USHORT vt;WORD wReserved1;WORD wReserved2;WORD wReserved3')) DllStructSetData($tPROPVARIANT, 'vt', $VT_LPWSTR) Local $aRet = DllCall('Shlwapi.dll', 'LONG', 'SHStrDupW', _ 'WSTR', $sUnicodeString, 'PTR', DllStructGetPtr($tPROPVARIANT) + $nPropVariantDataIndex) If @error Then Return SetError(@error, @extended, False) Local $bSuccess = $aRet[0] = 0? True : False ; If fails, zero memory of the current PROPVARIANT struct If (Not $bSuccess) Then $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) Return SetExtended($aRet[0], $bSuccess) EndFunc Func _WinAPI_SHGetPropertyStoreForWindow($hWnd, $sIID, ByRef $tPointer) Local $tIID = _WinAPI_GUIDFromString($sIID) Local $pp = IsPtr($tPointer)? $tPointer : DllStructGetPtr($tPointer) Local $aRet = DllCall('Shell32.dll', 'LONG', 'SHGetPropertyStoreForWindow', _ 'HWND', $hWnd, 'STRUCT*', $tIID, 'PTR', $pp) If @error Then Return SetError(@error, @extended, False) Return SetExtended($aRet[0], ($aRet[0] = 0)) EndFunc Global Const $tagIUnknown = 'PTR QueryInterface;PTR AddRef;PTR Release' Global Const $tagIPropertyStore = $tagIUnknown & _ ';PTR GetCount;' & _ ;HRESULT GetCount([Out] DWORD* cProps) 'PTR GetAt;' & _ ;HRESULT GetAt([In] DWORD iProp, [Out] PROPERTYKEY* pKey) 'PTR GetValue;' & _ ;HRESULT GetValue([In] PROPERTYKEY& key, [Out] PROPVARIANT * pv) 'PTR SetValue;' & _ ;HRESULT SetValue([In] PROPERTYKEY& key, [In] PROPVARIANT& propvar) 'PTR Commit' ;HRESULT Commit() Func _Win7Helper_PKEY_AppUserModel_ID() Local $tPROPERTYKEY = DllStructCreate($tagPROPERTYKEY) ;PKEY_AppUserModel_ID = { {0x9F4C2855, 0x9F79, 0x4B39, ; {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 5 } _WinAPI_GUIDFromStringEx('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}', _ DllStructGetPtr($tPROPERTYKEY)) DllStructSetData($tPROPERTYKEY, 'pid', 5) Return $tPROPERTYKEY EndFunc ; The application id is an up-to-128-characters string Func _Win7Helper_SetWindowAppId($hWnd, $sId) ; This variable is not change. You can use a global const but a local static is prefered due to it scope Local Static $tPROPERTYKEY = _Win7Helper_PKEY_AppUserModel_ID() ; Create and int PROPVARIANT variable Local $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) _WinAPI_InitPropVariantFromString($sId, $tPROPVARIANT) ; Now create an instance of IPropertyStore interface. We must pass a void** (pointer to pointer) ; We can do it in AutoIt by using a pointer to a struct which have only 1 pointer member. Local $tpIPropertyStore = DllStructCreate('PTR') $ret = _WinAPI_SHGetPropertyStoreForWindow($hWnd, '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', $tpIPropertyStore) ; Retrieve the IPropertyStore pointer from result Local $pPropertyStoreObject = DllStructGetData($tpIPropertyStore, 1) ; Now we have a pointer to an IPropertyStore object. ; If you use a new AutoIt version, thank to elegant ObjCreateInterface by tracexx,; ; we can easily call method from the pointer we have If ($__OPT_EXPERIMENTAL_OBJCREATEINTERFACE) Then Local $oPropertyStoreObject = ObjCreateInterface($pPropertyStoreObject, _ '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', _ 'GetCount HRESULT(PTR);GetAt HRESULT(DWORD; PTR);GetValue HRESULT(PTR; PTR);' & _ 'SetValue HRESULT(PTR; PTR);Commit HRESULT()') If Not IsObj($oPropertyStoreObject) Then Return SetError(1, 0, '') $oPropertyStoreObject.SetValue(DllStructGetPtr($tPROPERTYKEY), DllStructGetPtr($tPROPVARIANT)) $oPropertyStoreObject.Commit() Else ; But if you don't want to use an experimental function, we can do it manually ; First retrieve the v-table of the object. IPropertyStore is directly inherited from IUnknown ; so we have only one v-table data, merge of IUnknown and IPropertyStore, ; located at the beginning of the object address Local $pIPropertyStore = DllStructGetData(DllStructCreate('PTR', $pPropertyStoreObject), 1) Local $tIPropertyStore = DllStructCreate($tagIPropertyStore, $pIPropertyStore) ; With the v-table, we can call methods (yes we use another advanced function, ; but not a beta function so its safe as much as we use it correctly ; We simulate a c++ method, first parameter should be pointer to object itself. ; SetValue DllCallAddress('LONG', DllStructGetData($tIPropertyStore, 'SetValue'), _ 'PTR', $pPropertyStoreObject, _ ; pThis 'PTR', DllStructGetPtr($tPROPERTYKEY), _ 'PTR', DllStructGetPtr($tPROPVARIANT)) DllCallAddress('LONG', DllStructGetData($tIPropertyStore, 'Commit'), 'PTR', $pPropertyStoreObject) EndIf EndFunc Func _Win7Helper_GetWindowAppId($hWnd) Local Static $tPROPERTYKEY = _Win7Helper_PKEY_AppUserModel_ID() Local $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) Local $tpIPropertyStore = DllStructCreate('ptr') _WinAPI_SHGetPropertyStoreForWindow($hWnd, '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', $tpIPropertyStore) Local $pPropertyStoreObject = DllStructGetData($tpIPropertyStore, 1) Local $oPropertyStoreObject = ObjCreateInterface($pPropertyStoreObject, _ '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', _ 'GetCount HRESULT(PTR);GetAt HRESULT(DWORD; PTR);GetValue HRESULT(PTR; PTR);' & _ 'SetValue HRESULT(PTR; PTR);Commit HRESULT()') If Not IsObj($oPropertyStoreObject) Then Return SetError(1, 0, '') $oPropertyStoreObject.GetValue(DllStructGetPtr($tPROPERTYKEY), DllStructGetPtr($tPROPVARIANT)) ; Extracts a string value from a PROPVARIANT structure ; http://deletethis.net/dave/dev/setappusermodelid/ ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb776559(v=vs.85).aspx Local $buf = DllStructCreate('wchar[128]') DllCall('Propsys.dll', 'long', 'PropVariantToString', _ 'ptr', DllStructGetPtr($tPROPVARIANT), _ 'ptr', DllStructGetPtr($buf), _ 'uint', DllStructGetSize($buf)) If @error Then Return SetError(@error, @extended, "") Else Return DllStructGetData($buf, 1) EndIf EndFunc #cs ; SetCurrentProcessExplicitAppUserModelID DllCall("Shell32.dll", "long", "SetCurrentProcessExplicitAppUserModelID", _ "wstr", "MyGreatCompany.MyAwesomeApplication.MyElegantWindow1") #ce ; Demo $hWnd1 = GUICreate('Test1', 400, 200, 0, 100) $hWnd2 = GUICreate('Test2', 400, 200, 500, 100) $hWnd3 = GUICreate('Test3', 400, 200, 1000, 100) ; The application id should be unique so it not effect any other application. ; Better use a format like MyCompany(orMyName).MyApplication.WindowId _Win7Helper_SetWindowAppId($hWnd1, 'MyGreatCompany.MyAwesomeApplication.MyElegantWindow1') _Win7Helper_SetWindowAppId($hWnd2, 'MyGreatCompany.MyAwesomeApplication.OhImNotAWindowImAnAlien') _Win7Helper_SetWindowAppId($hWnd3, 'MyGreatCompany.MyAwesomeApplication.MyElegantWindow1') GUISetState(@SW_SHOW, $hWnd1) GUISetState(@SW_SHOW, $hWnd2) GUISetState(@SW_SHOW, $hWnd3) $appid1 = _Win7Helper_GetWindowAppId($hWnd1) $appid3 = _Win7Helper_GetWindowAppId($hWnd3) MsgBox(0, 'AppUserModelId', 'AppId of Test1 Window: ' & @CRLF & $appid1 & @CRLF & @CRLF & _ 'AppId of Test3 Window: ' & $appid3 & @CRLF & @CRLF & _ 'Their AppIds are the same, so their icons should be grouped together.', 0, $hWnd1) Do Until GUIGetMsg() = -3 #cs ; Another example -- get Google Chrome's AppId ; Start Chrome and use AU3Info to get the handle $hWnd = HWnd('0x00000000001002CC') $appid = _Win7Helper_GetWindowAppId($hWnd) ConsoleWrite('Old AppId = ' & $appid & @CRLF) _Win7Helper_SetWindowAppId($hWnd, 'chrome.123456') $appid = _Win7Helper_GetWindowAppId($hWnd) ConsoleWrite('New AppId = ' & $appid & @CRLF) #ceThis Func can get AppId of a window created by Autoit in this example.I tried to get other window's AppId,such as IE, Google Chrome, Firefox, successfully got Google Chrome's AppId , "Chrome.ZABMGAMPWEKMYFXAM6OVHWYM.UserData.Default", while others failed.I don't know why. Edited July 10, 2015 by jackchen Link to comment Share on other sites More sharing options...
UEZ Posted July 10, 2015 Share Posted July 10, 2015 (edited) An example:$hGUI_Parent = GUICreate("Parent", 600, 400) GUISetState() $hGUI_Child1 = GUICreate("Child1", 300, 200, 100) GUISetState() $hGUI_Child2 = GUICreate("Child2", 300, 200, 1200) GUISetState() Do Until GUIGetMsg() = -3 GUIDelete($hGUI_Child2) GUIDelete($hGUI_Child1) GUIDelete($hGUI_Parent) Sleep(1000) $hGUI_Parent = GUICreate("Parent", 600, 400) GUISetState() $hGUI_Child1 = GUICreate("Child1", 300, 200, 100, -1, -1, -1, $hGUI_Parent) GUISetState() $hGUI_Child2 = GUICreate("Child2", 300, 200, 1200, -1, -1, -1, $hGUI_Parent) GUISetState() MsgBox(0, "Info", "Only one GUI in the task bar", 0, $hGUI_Parent) Do Until GUIGetMsg() = -3 Edited July 10, 2015 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
jackchen Posted July 10, 2015 Share Posted July 10, 2015 (edited) An example:$hGUI_Parent = GUICreate("Parent", 600, 400) GUISetState() $hGUI_Child1 = GUICreate("Child1", 300, 200, 100) GUISetState() $hGUI_Child2 = GUICreate("Child2", 300, 200, 1200) GUISetState() Do Until GUIGetMsg() = -3 GUIDelete($hGUI_Child2) GUIDelete($hGUI_Child1) GUIDelete($hGUI_Parent) Sleep(1000) $hGUI_Parent = GUICreate("Parent", 600, 400) GUISetState() $hGUI_Child1 = GUICreate("Child1", 300, 200, 100, -1, -1, -1, $hGUI_Parent) GUISetState() $hGUI_Child2 = GUICreate("Child2", 300, 200, 1200, -1, -1, -1, $hGUI_Parent) GUISetState() MsgBox(0, "Info", "Only one GUI in the task bar", 0, $hGUI_Parent) Do Until GUIGetMsg() = -3 UEZ,Thanks for your example which is exactly what the OP needs.Actually my request is maybe the reverse, I need combine other window's icon with my loader icon. I made a chrome_portable_loader.exe in autoit.If I pin the loader to taskbar and click the icon to launch Google Chrome browser,the browser's icon will on the right side of loader.I hope the browser's icon can combine with my loader's icon on taskbar.It's absolutley possible.I got the appid of chrome window via _Win7Helper_GetWindowAppId($hWnd) in Autoit, set the same appid for chrome_portable_loader.lnk in @AppDataDir & "\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar", then both icons were combined.I set .lnk file's appid using Win7AppId which is coded in c++.I should convert those code to Autoit,but that's not easy for me. Edited July 10, 2015 by jackchen Link to comment Share on other sites More sharing options...
jackchen Posted July 12, 2015 Share Posted July 12, 2015 (edited) I'v made a UDF based on some codes of binhnx and solved my problem, Group different Apps on Win 7+ taskbar.Thanks to binhnx, LarsJ and others. Edited July 13, 2015 by jackchen Link to comment Share on other sites More sharing options...
ITplain Posted December 7, 2019 Share Posted December 7, 2019 Not sure what changed but example 1 works fine but example 2 doesn't seem to be doing anything in Window 10 x64. Checking or unchecking all the checkboxes does nothing. 🤕 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now