Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

JumpList library for Windows 7


  • Please log in to reply
9 replies to this topic
SL55 AMG
  • Members
  • 5 posts
  • Last active: Jan 31 2012 09:00 PM
  • Joined: 30 Jan 2012
JumpLists for Windows 7

Hi, I've just started using ahk and I just wanted to contribute something back since I've been using alot of scripts from others here.

This is a simple library to use the Jump List feature in Windows 7. This requires AHK_L, the latest version with support for super-global variables, and works with both 32 bit and 64 bit OS. Jump lists require instantiating various Shell COM objects, so this is mostly just a bunch of simple class wrappers for those. Download the lib here:

Library: https://ahknet.autoh...MG/JumpList.ahk

Here is a quick demo script:

Posted Image

#include JumpList.ahk

szAppID:="customappid"
DllCall("Shell32.dll\SetCurrentProcessExplicitAppUserModelID", str, szAppID)

; create a ShellLink object for Notepad
shelllink1 := new ShellLink()
shelllink1.SetPath("c:\\windows\\notepad.exe")
shelllink1.SetIconLocation("c:\\windows\\notepad.exe", 0)
shelllink1.SetDescription("launches notepad")
InitVariantFromString("Notepad", vt)
shelllink1.SetValue(PKEY_Title,vt)
shelllink1.Commit()

; create a ShellLink object for Regedit
shelllink2 := new ShellLink()
shelllink2.SetPath("c:\\windows\\regedit.exe")
shelllink2.SetIconLocation("c:\\windows\\regedit.exe", 0)
shelllink2.SetDescription("launches regedit")
InitVariantFromString("Regedit", vt)
shelllink2.SetValue(PKEY_Title,vt)
shelllink2.Commit()

; create a ShellLink object for a task list seperator
shelllinkseperator := new ShellLink()
InitVariantFromBoolean(-1, vtbool)
shelllinkseperator.SetValue(PKEY_AppUserModel_IsDestListSeparator,vtbool)
shelllinkseperator.Commit()

; create an ObjectCollection object to represent our User Tasks category
enumerableobjectcollection1 := new EnumerableObjectCollection()
enumerableobjectcollection1.AddObject(shelllink1.pShellLinkW)
enumerableobjectcollection1.AddObject(shelllinkseperator.pShellLinkW)
enumerableobjectcollection1.AddObject(shelllink2.pShellLinkW)

; create an ObjectCollection object to represent our Custom Category
enumerableobjectcollection2 := new EnumerableObjectCollection()
enumerableobjectcollection2.AddObject(shelllink1.pShellLinkW)
enumerableobjectcollection2.AddObject(shelllink2.pShellLinkW)

; create a DestinationList object to represent the complete Jump List
destinationlist1:= new DestinationList()
destinationlist1.SetAppId(szAppID)
destinationlist1.BeginList(minslots,premovedlist)
destinationlist1.AddUserTasks(enumerableobjectcollection1.pObjectCollection)
destinationlist1.AppendCategory("My Custom Category",enumerableobjectcollection2.pObjectCollection)
destinationlist1.CommitList()

; create a main window, which will assume the appid we specified for the current process
Gui, +LastFound
hwnd := WinExist()
Gui, Show, w300 h300
hdc := DllCall("GetDC", ptr, hwnd)
DllCall("gdi32.dll\TextOut", ptr, hdc, int, 30, int, 60, str, "Right-click taskbar to see the jumplist", uint, 40)
return
GuiClose:
	ExitApp

Basic Overview
ShellLink objects: All jumplist items are represented by ShellLink objects. So start by creating a bunch of ShellLinks for whatever programs or folders you wish.

EnumerableObjectCollection objects: The Windows 7 Jumplist is structured in "categories". Each category is represented by an EnumerableObjectCollection object. So create one for each section you desire. Then add your ShellLinks into these collection objects. You can create custom categories and name it whatever you want. But Microsoft also predefines a category called "Tasks". The only real special thing about this category is that you can insert divders between task items. A divider is just a ShellLink object with a predefined property "PKEY_AppUserModel_IsDestListSeparator" set to True.

DestinationList object: The Jumplist itself is represented by a single DestinationList object. Instantiate one of these, and then add in each of your categories. To append a custom category call "AppendCategory()". To append a Tasks category, call "AddUserTasks().

How to get the jumplist to show? Windows associates Jumplists with taskbar buttons whenever they have the same "AppID" (you can choose any string name for this). To set the AppID for your program, use win32's SetCurrentProcessExplicitAppUserModelID(). Then any windows (and hence taskbar buttons) spawned afterwards will have that AppID. When you create your DestinationList jumplist object, set it to the same appid with SetAppID(). Finally, call the DestinationList object's CommitList() function when you're done adding everything to your jumplist.

Since I'm new to ahk, there could be bugs or better ways of using ahk's features, but I hope that someone finds this helpful, if anything at least as a reference. And feel free to modify this any way you see fit. Enjoy.

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
Although I didn't yet try to, one should be able to do similar using my CCF (see sginature) and its CustomDestinationList, ShellLink and other classes.

However, using the whole framework just for a single task might be a bit of overkill sometimes ;-) Thanks for your lib.
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

SL55 AMG
  • Members
  • 5 posts
  • Last active: Jan 31 2012 09:00 PM
  • Joined: 30 Jan 2012
Thanks for letting me know about it -- it looks like a really great idea especially since all the new Windows functions use COM-based API, as opposed to the flat API used for the older functions. I'm trying it out and at the same time trying to figure out how to use AHK class inheritance.

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
2 questions:[*:14vm7csb]is there a specific reason why you call "CoCreateInstance" and not use ComObjCreate() :?:
[*:14vm7csb]Why do you call gdi to write text to the window :?: Why not just use
Gui Font, s10
Gui Add, Text, x30 y60, Right-click taskbar to see the jumplist
Gui Show, w300 h300
If you have questions on CCF, just ask (PM or CCF thread).
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
Tip: you needn't use DllCall("ole32\CoCreateInstance", ...) to create non-IDispatch COM objects. Use this:
pObj := ComObjCreate("{CLSID-here}", "{IID-here}")
Same goes for QueryInterface:
pObj2 := ComObjQuery(pObj, "{IID-here}")


SL55 AMG
  • Members
  • 5 posts
  • Last active: Jan 31 2012 09:00 PM
  • Joined: 30 Jan 2012
Hey sorry about the delay, I'm in the middle of moving.

(1) ComObjCreate
- the reason I didn't use ComObjCreate was that it didn't seem to accept CLSIDs or IIDs in the 16-byte binary format. It only accepts string format. And the reason I wanted to stick with the 16-byte binary format was because the Win32 API uses that the binary format everywhere rather than string format.

For example, when using shell objects, you often have to QueryInterface to access the functions from other interfaces, and you have to use that 16-byte binary format to specify which interface you want. Similarly, sometimes you have to group objects together with ObjectCollections or ObjectArrays, and the functions that use these collections require you to specify which type of collection you're passing with that 16-byte binary format.

So rather than converting back and forth all over the place, I defined the interface identifier once, in the 16-byte format. In fact, in the Win32 header files, the string format isn't defined anywhere (none of the windows api natively take the string format).

On that note, I was thinking it would be really great if ComObjCreate and ComObjQuery could be modified to accept the 16-byte format. That would eliminate alot of the unsightly DllCalls!

(2) GDI Text
- oh that was just a force of habit from win32 C++ programming, because in win32 C++, it is a huge pain to add a Static or Edit control. GDI lets you write or draw into any window with a single DLL call.

I'm currently figuring out how to do ahk multiple inheritance as I'm currently trying to get some of my DirectShow scripts into objects -- and some of the objects like CLSID_VideoMixingRenderer have several interfaces!

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
very nice, thank you for sharing

yourbuddypal
  • Members
  • 32 posts
  • Last active: May 17 2013 06:50 AM
  • Joined: 29 Jun 2009
This is really great, thank you for sharing!

  • Guests
  • Last active:
  • Joined: --
Anyone got the library?

lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013

In case anyone was wondering you can find the library at https://github.com/r...master/JumpList.


My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm