Explorer column interaction (get/set: which appear, width, ascending/descending order)

Post your working scripts, libraries and tools
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Explorer column interaction (get/set: which appear, width, ascending/descending order)

14 Jun 2017, 20:23

The IColumnManager and IFolderView2 interfaces offer methods to interact with columns in Explorer folder windows.

IColumnManager interface (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776149(v=vs.85).aspx
IFolderView2 interface (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/bb775541(v=vs.85).aspx

These functions make it possible to: count/list and add/remove columns programmatically, to get/set which columns are used to sort the files, and to get/set whether the order is ascending/descending.

The JEE_ExpGetInterfaces function for getting access to the interfaces is based on code by and mainly thanks to qwerty12:
Explorer: jump to first file/folder - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=33007&p=153513#p153513

I obtained the offset for each method, for both interfaces by using:
C:\Program Files (x86)\Windows Kits\8.1\Include\um\ShObjIdl.h
which came with Visual Studio.

It seems that with some objects/interfaces you can specify '.MethodName()' but with others you need to use DllCall and NumGet to refer to the methods. There are some details here:
COM interface tutorial
https://maul-esel.github.io/tutorials/COM-Interfaces.html

I also made some comments about retrieving the list of methods for an interface at 'INTERFACES: GET METHOD LIST' at:
jeeswg's objects tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=29232

Note some information can be retrieved, and interaction done, e.g. listing and simulating clicking column headers, via the Acc library, there is an e.g. lower down:
Acc library (MSAA) and AccViewer download links - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=26201

Btw it appears that to uniquely identify a column header you need a CLSID and a property identifier, (these are shown in example lower down,) and that some column headers share the same CLSID.

==================================================

[Links: (IColumnManager)]
How to obtain the list of visible columns in a shell view – Windows SDK Support Team Blog
https://blogs.msdn.microsoft.com/winsdk/2015/05/18/how-to-obtain-the-list-of-visible-columns-in-a-shell-view/
windows - Copying file details from Explorer as tabular text - Stack Overflow
https://stackoverflow.com/questions/26633794/copying-file-details-from-explorer-as-tabular-text

[Links: (StringFromCLSID)]
DllCall to get idle time until computer sleeps - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=25935
[AHK_L] Custom AutoCompletion for edit control, with drop down list - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/96129-ahk-l-custom-autocompletion-for-edit-control-with-drop-down-list/

==================================================
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

15 Jun 2017, 23:21

Note: the functions are finished except for JEE_ICMGetColumnWidth which isn't working (if anyone can help identify what the problem is), although I do provide a method below to retrieve a column width via the Acc library.

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



Additional code that doesn't use the functions:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

Last edited by jeeswg on 16 Jun 2017, 04:40, edited 2 times in total.
just me
Posts: 4454
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

16 Jun 2017, 01:46

Edit: I tried your version now, and this is working here:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



I didn't try, but I'm pretty sure that you have to pass the PROPERTYKEY returned by GetColumns to GetColumnWidth.
Also:
PSGetNameFromPropertyKey wrote:It is the responsibility of the calling application to use CoTaskMemFree to release the string referred to by ppszCanonicalName when it is no longer needed.
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

16 Jun 2017, 09:58

Thanks just me. I tried your version of the function, but it still doesn't seem to work, unless you also made some other edits. I'm using Windows 7, and I tried the latest AHK v1.1 x32 and x64.

I will check up on CoTaskMemFree, btw are there are any other common dll functions used for freeing up memory? What does AHK use for freeing up variables/memory/objects? Cheers. [EDIT: I will start this as a new thread, after I finish collecting some of the dll functions I already know about.]
Last edited by jeeswg on 16 Jun 2017, 21:13, edited 1 time in total.
wyagd
Posts: 1
Joined: 01 Jun 2017, 09:59

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

16 Jun 2017, 21:08

@just me
your code I tested work in windows 10 32bit.but can't work in windows 7 32bit.
my mistake.

just me's version I change

Code: [Select all] [Download] GeSHi © Codebox Plus

return NumGet(CM_COLUMNINFO, 12, "UInt")


just me's version and jeeswg's version of JEE_ICMGetColumnWidth both works for me on Windows 10, The two methods are not working properly on Windows 7.

in other words,The following code both can work on windows 10 ,but can't work on windows 7.

Code: [Select all] [Download] GeSHi © Codebox Plus

NumPut(0x5, CM_COLUMNINFO, 4, "UInt")

Code: [Select all] [Download] GeSHi © Codebox Plus

NumPut(0x1F, CM_COLUMNINFO, 4, "UInt")

Code: [Select all] [Download] GeSHi © Codebox Plus

return NumGet(CM_COLUMNINFO, 12, "UInt")
Last edited by wyagd on 17 Jun 2017, 01:12, edited 1 time in total.
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

16 Jun 2017, 21:16

Thanks for your response wyagd. So just me's version of JEE_ICMGetColumnWidth works for you on Windows 10, but not on Windows 7? Do let me know if you have any problems with any other bits of code or functions above.

Btw do you think these functions might be useful to you? Cheers.
just me
Posts: 4454
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 05:04

wyagd wrote:just me's version I change ...
Yes, I confused the offsets. Sorry!


@jeeswg:
Did you try other combinations of the CM_MASK enumeration? Are all failing on Win 7?
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 05:57

@wyagd Thanks again for the clarification.

@just me Yes I tried that, and I tried your version of the function. I'm getting blanks on NumGet and StrGet, and I think it's because the DllCall is failing.

If you check the return value from DllCall, it suggests an error. When the DllCall works, for other ICM/IFV2 functions, it's usually 0, but in this case I got 0x8000FFFF.
qwerty12
Posts: 381
Joined: 04 Mar 2016, 04:33
GitHub: qwerty12

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 12:47

jeeswg wrote:If you check the return value from DllCall, it suggests an error. When the DllCall works, for other ICM/IFV2 functions, it's usually 0, but in this case I got 0x8000FFFF.


just me's code also works for me on Windows 10 x64. The code from the link you provided also works to show the column widths of all the windows open on my 10 laptop (well, after adding a call to GetColumnInfo).

With Windows 7, however, the only way I was able to get a window's column widths was by taking the code from that link, compiling it into a DLL, making said code run on the same thread as the window and injecting the DLL into Explorer. I guess Windows 8 onwards does some marshalling or something.
(Although, not knowing much about COM, I wonder why GetColumns succeeds outside of Explorer to get the property key names of open windows on Windows 7...)

If this is really that important to you, you could adapt the "get opened common file dialogs' selected files" script I wrote that uses LibTCC, but IMO, unless someone figures out another way, I don't think it's worth it (going to such extremes to find out the width of columns on an OS that has its support cut off in ~3 years isn't worth anybody's time IMO).
Last edited by qwerty12 on 16 Aug 2017, 12:17, edited 1 time in total.
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 14:46

Cheers, well I'll test getting column widths on Windows 10, and possibly improve the function slightly, when I get the chance.

I'll also try and develop a workaround function, to retrieve column widths, that uses the Acc library, see above an for Acc library example. @qwerty12: I'll try Acc, rather than inject a dll, but that is a great suggestion and cheers for testing that approach.

Further points:
- What is the 'ideal' width? Is it possible to retrieve a column's 'Size Column to Fit' width without applying it.
- Is it possible to invoke 'Size Column to Fit'/'Size All Columns to Fit', via a window message e.g. WM_COMMAND, or via objects. I was able to apply 'Size All Columns to Fit', above, via ControlSend, and I did try some tests with WM_COMMAND.
- Is it possible to convert descriptions like 'System.ItemNameDisplay' to their localised name e.g. 'Name'? Preferably without using another interface.
- Does IColumnManager have to be retrieved through IFolderView2, or can it be retrieved more directly from the Window object?
- I found that sometimes DoRename worked when applied directly to a Window object, without having to use any other interfaces. Any explanation of why this sometimes works, would be quite interesting. Although, I don't really need DoRename because you can use SelectItem and SVSI_EDIT.

Thanks for the responses, it would be interesting to know if these functions work on Windows XP/Vista/8. You can use a Window object on Windows XP, but on MSDN it says that the minimum supported client for both IFolderView2 and IColumnManager is Windows Vista.
qwerty12
Posts: 381
Joined: 04 Mar 2016, 04:33
GitHub: qwerty12

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 16:32

jeeswg wrote:@qwerty12: I'll try Acc, rather than inject a dll, but that is a great suggestion and cheers for testing that approach.


I think that would be the more prudent (and far less time consuming!) approach.

- Is it possible to invoke 'Size Column to Fit'/'Size All Columns to Fit', via a window message e.g. WM_COMMAND, or via objects. I was able to apply 'Size All Columns to Fit', above, via ControlSend, and I did try some tests with WM_COMMAND.


I didn't go all the way testing it, but the only way I could think of that might work once again involves running code on the same thread as the window through injection to be able to get the CDefView. My knowledge of the shell API isn't great; perhaps there is a documented way somewhere on MSDN... But I don't think WM_COMMAND will work as the size columns etc. menu is created then and there when you right-click a column. TrackPopupMenu is called only then.

- Is it possible to convert descriptions like 'System.ItemNameDisplay' to their localised name e.g. 'Name'? Preferably without using another interface.


The code provided in this thread already does that (call GetColumnInfo with CM_MASK_NAME set and read out wszName), but I can also see that might not be an option on Windows 7... I haven't tested it, but SHGetNameFromPropertyKey might work.

- Does IColumnManager have to be retrieved through IFolderView2, or can it be retrieved more directly from the Window object?


The earliest I got it was from the IShellView.

Thanks for the responses, it would be interesting to know if these functions work on Windows XP/Vista/8. You can use a Window object on Windows XP, but on MSDN it says that the minimum supported client for both IFolderView2 and IColumnManager is Windows Vista.


https://stackoverflow.com/a/35463918
User avatar
jeeswg
Posts: 1726
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 16:41

Cheers re.:

c++ - WTSGetActiveConsoleSessionId - Minimum supported client / server incorrect? - Stack Overflow
https://stackoverflow.com/questions/35457903/wtsgetactiveconsolesessionid-minimum-supported-client-server-incorrect/35463918#35463918

Windows XP and Windows Server 2003 are no longer supported, so the minimum supported client/server is Windows Vista and Windows Server 2008, respectively. A common mistake is, that developers read the information to mean "introduced in". This is not the case.


I did expect that 'supported' would literally mean 'supported' rather than 'introduced', the only problem with that though, is presumably all MSDN articles should thus say 'minimum supported client' as Windows Vista at a minimum, but for example this states Windows 2000 as the minimum supported client, unless lots of articles are just 'out-of-date' or unless Windows 2000 is still 'semi-supported' in some way:

WideCharToMultiByte function (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx

Then again, 'introduced' dates would be far more useful, if available somewhere.

==================================================

SHGetNameFromPropertyKey appears to give the same result as PSGetNameFromPropertyKey, giving the canonical name.

Btw there is PSGetPropertyKeyFromName, but there doesn't appear to be a SHGetPropertyKeyFromName.

Note: I tried to implement CoTaskMemFree, but it crashed AHK, although I appear to be using it in the same way that other people have in other scripts.

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

qwerty12
Posts: 381
Joined: 04 Mar 2016, 04:33
GitHub: qwerty12

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

17 Jun 2017, 19:50

jeeswg wrote:I did expect that 'supported' would literally mean 'supported' rather than 'introduced', the only problem with that though, is presumably all MSDN articles should thus say 'minimum supported client' as Windows Vista at a minimum, but for example this states Windows 2000 as the minimum supported client, unless lots of articles are just 'out-of-date' or unless Windows 2000 is still 'semi-supported' in some way:


I thought the same as you, but given in the inconsistency across the pages wrt. the last supported version, In all honesty I'm more inclined to believing changing the versions are done when there's nothing else to do. For example, the current page for ConvertSidToStringSid says the minimum supported version is XP, but if you go back to the 2011 version, it says Windows 2000. But then at the same time, there's the example you linked.

SHGetNameFromPropertyKey appears to give the same result as PSGetNameFromPropertyKey, giving the canonical name.


Oops. Didn't realise what canonical name meant. Try this:

Code: [Select all] [Download] GeSHi © Codebox Plus

VarSetCapacity(IID_IPropertyDescription, 16)
DllCall("ole32\CLSIDFromString", "WStr", "{6f79d558-3e96-4549-a1d1-7d75d2288814}", "Ptr", &IID_IPropertyDescription)

; use PSGetPropertyDescription for the same from an already-initialised PROPERTYKEY
if (!DllCall("propsys\PSGetPropertyDescriptionByName", "WStr", "System.ItemNameDisplay", "Ptr", &IID_IPropertyDescription, "Ptr*", iprop)) {
if (!DllCall(NumGet(NumGet(iprop+0)+6*A_PtrSize), "Ptr", iprop, "Ptr*", pszDisplayName)) { ; IPropertyDescription::GetDisplayName
MsgBox % StrGet(pszDisplayName, "UTF-16")
DllCall("ole32\CoTaskMemFree", "Ptr", pszDisplayName)
}
ObjRelease(iprop)
}
just me
Posts: 4454
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

18 Jun 2017, 05:16

Though somewhat off-topic:

SHGetNameFromPropertyKey doesn't seem to be included in /exported by the shell32.dll of the latest Win 10 version (ErrorLevel = -4). Can anyone confirm this? Thanks!
qwerty12
Posts: 381
Joined: 04 Mar 2016, 04:33
GitHub: qwerty12

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

18 Jun 2017, 09:29

just me wrote:SHGetNameFromPropertyKey doesn't seem to be included in /exported by the shell32.dll of the latest Win 10 version (ErrorLevel = -4). Can anyone confirm this? Thanks!


Yes, I can confirm this. In addition, in the Windows 8.1 and 10.0.15063.0 SDKs, SHGetNameFromPropertyKey isn't present in any header files.

(Also, glad to see you around :-))
just me
Posts: 4454
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Explorer column interaction (get/set: which appear, width, ascending/descending order)

19 Jun 2017, 03:01

qwerty12 wrote:Yes, I can confirm this.

Weird, I didn't expect to find documented functions on the MSDN which have been removed silently.

(Also, the same to you :))

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 16 guests