Jump to content


Photo

JumpList library for Windows 7


  • Please log in to reply
8 replies to this topic

#1 SL55 AMG

SL55 AMG
  • Members
  • 5 posts

Posted 30 January 2012 - 07:24 PM

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: http://www.autohotke...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.

#2 maul.esel

maul.esel
  • Members
  • 790 posts

Posted 30 January 2012 - 07:45 PM

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.

#3 SL55 AMG

SL55 AMG
  • Members
  • 5 posts

Posted 31 January 2012 - 02:54 AM

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.

#4 maul.esel

maul.esel
  • Members
  • 790 posts

Posted 05 February 2012 - 03:52 PM

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).

#5 fincs

fincs
  • Fellows
  • 1554 posts

Posted 05 February 2012 - 03:55 PM

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}")


#6 SL55 AMG

SL55 AMG
  • Members
  • 5 posts

Posted 10 February 2012 - 12:42 AM

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!

#7 Deo

Deo
  • Members
  • 199 posts

Posted 11 February 2012 - 04:24 AM

very nice, thank you for sharing

#8 yourbuddypal

yourbuddypal
  • Members
  • 32 posts

Posted 08 March 2012 - 10:05 PM

This is really great, thank you for sharing!

#9 Guests

  • Guests

Posted 15 August 2012 - 07:48 PM

Anyone got the library?