/// <summary> /// Creates a new instance of the JumpList class with the specified /// appId. The JumpList is associated with the given window. /// </summary> /// <param name="appID">Application Id to use for this instace.</param> /// <param name="windowHandle">Window handle for the window that is associated with this JumpList</param> private JumpList(string appID, IntPtr windowHandle) { // Throw exception if not running on Win7 or newer CoreHelpers.ThrowIfNotWin7(); // Native implementation of destination list customDestinationList = (ICustomDestinationList) new CDestinationList(); // Set application user model ID if (!string.IsNullOrEmpty(appID)) { ApplicationId = appID; // If the user hasn't yet set the application id for the whole process, // use the first JumpList's AppId for the whole process. This will ensure // we have the same JumpList for all the windows (unless user overrides and creates a new // JumpList for a specific child window) if (!TaskbarManager.Instance.ApplicationIdSetProcessWide) { TaskbarManager.Instance.ApplicationId = appID; } TaskbarManager.Instance.SetApplicationIdForSpecificWindow(windowHandle, appID); } }
private static void AddUserTasks(ICustomDestinationList custom_destinationd_list) { IObjectCollection object_collection = (IObjectCollection)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID.EnumerableObjectCollection)); IShellLink search_notes = CreateShellLink(Catalog.GetString("Search All Notes"), tomboy_path, "--search", System.IO.Path.Combine(icons_path, SearchIcon), -1); if (search_notes != null) { object_collection.AddObject(search_notes); } //IShellLink new_notebook = CreateShellLink("New Notebook", topmboy_path, "--new-notebook", // icons_path, (int)TomboyIcons.NewNotebook); //if (new_notebook != null) // object_collection.AddObject(new_notebook); IShellLink new_note = CreateShellLink(Catalog.GetString("Create New Note"), tomboy_path, "--new-note", System.IO.Path.Combine(icons_path, NewNoteIcon), -1); if (new_note != null) { object_collection.AddObject(new_note); } custom_destinationd_list.AddUserTasks((IObjectArray)object_collection); Marshal.ReleaseComObject(object_collection); object_collection = null; }
private static void AddCategory(ICustomDestinationList cdl, string category, List <_ShellObjectPair> jumpItems, List <JumpItem> successList, List <_RejectedJumpItemPair> rejectionList, bool isHeterogenous = true) { Debug.Assert(jumpItems.Count != 0); Debug.Assert(cdl != null); var shellObjectCollection = (IObjectCollection)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.EnumerableObjectCollection))); foreach (var itemMap in jumpItems) { shellObjectCollection.AddObject(itemMap.ShellObject); } var hr = string.IsNullOrEmpty(category) ? cdl.AddUserTasks(shellObjectCollection) : cdl.AppendCategory(category, shellObjectCollection); if (hr.Succeeded) { for (var i = jumpItems.Count; --i >= 0;) { successList.Add(jumpItems[i].JumpItem); } } else { if (isHeterogenous && hr == HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER) { Utility.SafeRelease(ref shellObjectCollection); var linksOnlyList = new List <_ShellObjectPair>(); foreach (var itemMap in jumpItems) { if (itemMap.JumpItem is JumpPath) { rejectionList.Add(new _RejectedJumpItemPair { JumpItem = itemMap.JumpItem, Reason = JumpItemRejectionReason.NoRegisteredHandler }); } else { linksOnlyList.Add(itemMap); } } if (linksOnlyList.Count > 0) { Debug.Assert(jumpItems.Count != linksOnlyList.Count); AddCategory(cdl, category, linksOnlyList, successList, rejectionList, false); } } else { Debug.Assert(HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER != hr); foreach (var item in jumpItems) { rejectionList.Add(new _RejectedJumpItemPair { JumpItem = item.JumpItem, Reason = JumpItemRejectionReason.InvalidItem }); } } } }
public JumpList(string appId, IntPtr handle) { tasks = new List <IJumpTask>(); list = (ICustomDestinationList) new CDestinationList(); if (!string.IsNullOrEmpty(appId)) { //WindowProperties.SetAppUserModelID(handle, appId); list.SetAppID(appId); } }
public static void CreateJumpList(NoteManager note_manager) { ICustomDestinationList custom_destinationd_list = null; IObjectArray removed_objects = null; try { custom_destinationd_list = (ICustomDestinationList)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID.DestinationList)); uint slots; Guid riid = CLSID.IObjectArray; Logger.Debug("Windows Taskbar: Begin jump list"); custom_destinationd_list.BeginList(out slots, ref riid, out removed_objects); try { AddUserTasks(custom_destinationd_list); } catch (UnauthorizedAccessException uae) { Logger.Warn("Access denied adding user tasks to jump list: {0}\n{1}", uae.Message, uae.StackTrace); } try { AddRecentNotes(custom_destinationd_list, note_manager, slots); } catch (UnauthorizedAccessException uae) { Logger.Warn("Access denied adding recent notes to jump list: {0}\n{1}", uae.Message, uae.StackTrace); } Logger.Debug("Windows Taskbar: Commit jump list"); custom_destinationd_list.CommitList(); } catch (Exception e) { Logger.Error("Error creating jump list: {0}\n{1}", e.Message, e.StackTrace); if (custom_destinationd_list != null) { custom_destinationd_list.AbortList(); } } finally { if (removed_objects != null) { Marshal.FinalReleaseComObject(removed_objects); removed_objects = null; } if (custom_destinationd_list != null) { Marshal.FinalReleaseComObject(custom_destinationd_list); custom_destinationd_list = null; } } }
public static void DeleteJumpList() { try { ICustomDestinationList custom_destinationd_list = (ICustomDestinationList)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID.DestinationList)); Logger.Debug("Windows Taskbar: Remove jump list"); custom_destinationd_list.DeleteList(null); Marshal.FinalReleaseComObject(custom_destinationd_list); custom_destinationd_list = null; } catch (Exception e) { Logger.Error("Error removing jump list: {0}\n{1}", e.Message, e.StackTrace); } }
internal void RefreshTasks(ICustomDestinationList destinationList) { if (_tasks.Count == 0) { return; } IObjectCollection taskCollection = (IObjectCollection) new CEnumerableObjectCollection(); foreach (IJumpListTask task in _tasks) { taskCollection.AddObject(task.GetShellRepresentation()); } destinationList.AddUserTasks((IObjectArray)taskCollection); }
// Builds the collection of task items and adds them to the Task section of the Jump List. All tasks should be added to the canonical // "Tasks" category by calling ICustomDestinationList::AddUserTasks. private static void _AddTasksToList(ICustomDestinationList pcdl) { var poc = new IObjectCollection(); var psl = _CreateShellLink("/Task1", "Task 1"); poc.AddObject(psl); psl = _CreateShellLink("/Task2", "Second Task"); poc.AddObject(psl); psl = _CreateSeparatorLink(); poc.AddObject(psl); psl = _CreateShellLink("/Task3", "Task 3"); poc.AddObject(psl); var poa = (IObjectArray)poc; // Add the tasks to the Jump List. Tasks always appear in the canonical "Tasks" category that is displayed at the bottom of the // Jump List, after all other categories. pcdl.AddUserTasks(poa); }
internal void RefreshDestinations(ICustomDestinationList destinationList) { if (_categorizedDestinations.Count == 0) return; foreach (int key in _categorizedDestinations.Keys) { IObjectCollection categoryContents = (IObjectCollection)new CEnumerableObjectCollection(); var destinations = _categorizedDestinations[key]; foreach (IJumpListDestination destination in destinations) { categoryContents.AddObject(destination.GetShellRepresentation()); } destinationList.AppendCategory( destinations.First().Category, (IObjectArray)categoryContents); } }
public JumpListManager(string appId) { _appId = appId; _destinations = new JumpListDestinations(); _tasks = new JumpListTasks(); _customDestinationList = (ICustomDestinationList)new CDestinationList(); if (String.IsNullOrEmpty(_appId)) { _appId = Windows7Taskbar.ProcessAppId; } if (!String.IsNullOrEmpty(_appId)) { _customDestinationList.SetAppID(_appId); } _displaySettingsChangeHandler = delegate { RefreshMaxSlots(); }; SystemEvents.DisplaySettingsChanged += _displaySettingsChangeHandler; }
internal void RefreshDestinations(ICustomDestinationList destinationList) { if (_categorizedDestinations.Count == 0) { return; } foreach (int key in _categorizedDestinations.Keys) { IObjectCollection categoryContents = (IObjectCollection) new CEnumerableObjectCollection(); var destinations = _categorizedDestinations[key]; foreach (IJumpListDestination destination in destinations) { categoryContents.AddObject(destination.GetShellRepresentation()); } destinationList.AppendCategory( destinations.First().Category, (IObjectArray)categoryContents); } }
// Adds a custom category to the Jump List. Each item that should be in the category is added to an ordered collection, and then the // category is appended to the Jump List as a whole. private static void _AddCategoryToList(ICustomDestinationList pcdl, IObjectArray poaRemoved) { var poc = new IObjectCollection(); foreach (var fn in c_rgpszFiles) { if (SHCreateItemInKnownFolder(KNOWNFOLDERID.FOLDERID_Documents.Guid(), KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT, fn, typeof(IShellItem).GUID, out var ppv).Succeeded) { var psi = ppv as IShellItem; // Items listed in the removed list may not be re-added to the Jump List during this list-building transaction. They // should not be re-added to the Jump List until the user has used the item again. The AppendCategory call below will // fail if an attempt to add an item in the removed list is made. if (!_IsItemInArray(psi, poaRemoved)) { poc.AddObject(psi); } } // Add the category to the Jump List. If there were more categories, they would appear from top to bottom in the order they // were appended. pcdl.AppendCategory("Custom Category", poc); } }
/// <summary> /// Initializes a new instance of the jump list manager /// with the specified application id. /// </summary> /// <param name="appId">The application id.</param> public JumpListManager(string appId) { _appId = appId; _destinations = new JumpListDestinations(); _tasks = new JumpListTasks(); _customDestinationList = (ICustomDestinationList) new CDestinationList(); if (String.IsNullOrEmpty(_appId)) { _appId = Windows7Taskbar.GetCurrentProcessAppId(); } if (!String.IsNullOrEmpty(_appId)) { _customDestinationList.SetAppID(_appId); } _displaySettingsChangeHandler = delegate { RefreshMaxSlots(); }; SystemEvents.DisplaySettingsChanged += _displaySettingsChangeHandler; }
private static void AddUserTasks (ICustomDestinationList custom_destinationd_list) { IObjectCollection object_collection = (IObjectCollection) Activator.CreateInstance (Type.GetTypeFromCLSID (CLSID.EnumerableObjectCollection)); IShellLink search_notes = CreateShellLink (Catalog.GetString ("Search All Notes"), tomboy_path, "--search", System.IO.Path.Combine (icons_path, SearchIcon), -1); if (search_notes != null) object_collection.AddObject (search_notes); //IShellLink new_notebook = CreateShellLink("New Notebook", topmboy_path, "--new-notebook", // icons_path, (int)TomboyIcons.NewNotebook); //if (new_notebook != null) // object_collection.AddObject(new_notebook); IShellLink new_note = CreateShellLink (Catalog.GetString ("Create New Note"), tomboy_path, "--new-note", System.IO.Path.Combine (icons_path, NewNoteIcon), -1); if (new_note != null) object_collection.AddObject (new_note); custom_destinationd_list.AddUserTasks ((IObjectArray) object_collection); Marshal.ReleaseComObject (object_collection); object_collection = null; }
private static void AddRecentNotes (ICustomDestinationList custom_destinationd_list, NoteManager note_manager, uint slots) { IObjectCollection object_collection = (IObjectCollection) Activator.CreateInstance (Type.GetTypeFromCLSID (CLSID.EnumerableObjectCollection)); // Prevent template notes from appearing in the menu Tag template_tag = TagManager.GetOrCreateSystemTag (TagManager.TemplateNoteSystemTag); uint index = 0; foreach (Note note in note_manager.Notes) { if (note.IsSpecial) continue; // Skip template notes if (note.ContainsTag (template_tag)) continue; string note_title = note.Title; if (note.IsNew) { note_title = String.Format (Catalog.GetString ("{0} (new)"), note_title); } IShellLink note_link = CreateShellLink (note_title, tomboy_path, "--open-note " + note.Uri, System.IO.Path.Combine (icons_path, NoteIcon), -1); if (note_link != null) object_collection.AddObject (note_link); if (++index == slots - 1) break; } // Add Start Here note Note start_note = note_manager.FindByUri (NoteManager.StartNoteUri); if (start_note != null) { IShellLink start_note_link = CreateShellLink (start_note.Title, tomboy_path, "--open-note " + NoteManager.StartNoteUri, System.IO.Path.Combine (icons_path, NoteIcon), -1); if (start_note_link != null) object_collection.AddObject (start_note_link); } custom_destinationd_list.AppendCategory (Catalog.GetString ("Recent Notes"), (IObjectArray) object_collection); Marshal.ReleaseComObject (object_collection); object_collection = null; }
private static void AddCategory(ICustomDestinationList cdl, string category, List <JumpList._ShellObjectPair> jumpItems, List <JumpItem> successList, List <JumpList._RejectedJumpItemPair> rejectionList, bool isHeterogenous) { IObjectCollection objectCollection = (IObjectCollection)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("2d3468c1-36a7-43b6-ac24-d3f02fd9607a"))); foreach (JumpList._ShellObjectPair shellObjectPair in jumpItems) { objectCollection.AddObject(shellObjectPair.ShellObject); } HRESULT hrLeft; if (string.IsNullOrEmpty(category)) { hrLeft = cdl.AddUserTasks(objectCollection); } else { hrLeft = cdl.AppendCategory(category, objectCollection); } if (hrLeft.Succeeded) { int num = jumpItems.Count; while (--num >= 0) { successList.Add(jumpItems[num].JumpItem); } return; } if (isHeterogenous && hrLeft == HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER) { Utility.SafeRelease <IObjectCollection>(ref objectCollection); List <JumpList._ShellObjectPair> list = new List <JumpList._ShellObjectPair>(); foreach (JumpList._ShellObjectPair shellObjectPair2 in jumpItems) { if (shellObjectPair2.JumpItem is JumpPath) { rejectionList.Add(new JumpList._RejectedJumpItemPair { JumpItem = shellObjectPair2.JumpItem, Reason = JumpItemRejectionReason.NoRegisteredHandler }); } else { list.Add(shellObjectPair2); } } if (list.Count > 0) { JumpList.AddCategory(cdl, category, list, successList, rejectionList, false); return; } } else { foreach (JumpList._ShellObjectPair shellObjectPair3 in jumpItems) { rejectionList.Add(new JumpList._RejectedJumpItemPair { JumpItem = shellObjectPair3.JumpItem, Reason = JumpItemRejectionReason.InvalidItem }); } } }
private static void AddCategory(ICustomDestinationList cdl, string category, List <JumpList._ShellObjectPair> jumpItems, List <JumpItem> successList, List <JumpList._RejectedJumpItemPair> rejectionList) { JumpList.AddCategory(cdl, category, jumpItems, successList, rejectionList, true); }
private void _BuildShellLists(out List <JumpItem> successList, out List <JumpList._RejectedJumpItemPair> rejectedList, out List <JumpList._ShellObjectPair> removedList) { List <List <JumpList._ShellObjectPair> > list = null; removedList = null; ICustomDestinationList customDestinationList = CLSID.CoCreateInstance <ICustomDestinationList>("77f10cf0-3db5-4966-b520-b7c54fd35ed6"); try { string runtimeId = JumpList._RuntimeId; if (!string.IsNullOrEmpty(runtimeId)) { customDestinationList.SetAppID(runtimeId); } Guid guid = new Guid("92CA9DCD-5622-4bba-A805-5E9F541BD8C9"); uint num; IObjectArray shellObjects = (IObjectArray)customDestinationList.BeginList(out num, ref guid); removedList = JumpList.GenerateJumpItems(shellObjects); successList = new List <JumpItem>(this.JumpItems.Count); rejectedList = new List <JumpList._RejectedJumpItemPair>(this.JumpItems.Count); list = new List <List <JumpList._ShellObjectPair> > { new List <JumpList._ShellObjectPair>() }; foreach (JumpItem jumpItem in this.JumpItems) { if (jumpItem == null) { rejectedList.Add(new JumpList._RejectedJumpItemPair { JumpItem = jumpItem, Reason = JumpItemRejectionReason.InvalidItem }); } else { object obj = null; try { obj = JumpList.GetShellObjectForJumpItem(jumpItem); if (obj == null) { rejectedList.Add(new JumpList._RejectedJumpItemPair { Reason = JumpItemRejectionReason.InvalidItem, JumpItem = jumpItem }); } else if (JumpList.ListContainsShellObject(removedList, obj)) { rejectedList.Add(new JumpList._RejectedJumpItemPair { Reason = JumpItemRejectionReason.RemovedByUser, JumpItem = jumpItem }); } else { JumpList._ShellObjectPair item = new JumpList._ShellObjectPair { JumpItem = jumpItem, ShellObject = obj }; if (string.IsNullOrEmpty(jumpItem.CustomCategory)) { list[0].Add(item); } else { bool flag = false; foreach (List <JumpList._ShellObjectPair> list2 in list) { if (list2.Count > 0 && list2[0].JumpItem.CustomCategory == jumpItem.CustomCategory) { list2.Add(item); flag = true; break; } } if (!flag) { list.Add(new List <JumpList._ShellObjectPair> { item }); } } obj = null; } } finally { Utility.SafeRelease <object>(ref obj); } } } list.Reverse(); if (this.ShowFrequentCategory) { customDestinationList.AppendKnownCategory(KDC.FREQUENT); } if (this.ShowRecentCategory) { customDestinationList.AppendKnownCategory(KDC.RECENT); } foreach (List <JumpList._ShellObjectPair> list3 in list) { if (list3.Count > 0) { string customCategory = list3[0].JumpItem.CustomCategory; JumpList.AddCategory(customDestinationList, customCategory, list3, successList, rejectedList); } } customDestinationList.CommitList(); successList.Reverse(); } finally { Utility.SafeRelease <ICustomDestinationList>(ref customDestinationList); if (list != null) { foreach (List <JumpList._ShellObjectPair> list4 in list) { JumpList._ShellObjectPair.ReleaseShellObjects(list4); } } JumpList._ShellObjectPair.ReleaseShellObjects(removedList); } }
private static void AddCategory(ICustomDestinationList cdl, string category, List<_ShellObjectPair> jumpItems, List<JumpItem> successList, List<_RejectedJumpItemPair> rejectionList, bool isHeterogenous) { Debug.Assert(jumpItems.Count != 0); Debug.Assert(cdl != null); HRESULT hr; var shellObjectCollection = (IObjectCollection)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.EnumerableObjectCollection))); foreach (var itemMap in jumpItems) { shellObjectCollection.AddObject(itemMap.ShellObject); } if (string.IsNullOrEmpty(category)) { hr = cdl.AddUserTasks((IObjectArray)shellObjectCollection); } else { hr = cdl.AppendCategory(category, (IObjectArray)shellObjectCollection); } if (hr.Succeeded) { // Woot! Add these items to the list. // Do it in reverse order so Apply has the items in the correct order. for (int i = jumpItems.Count; --i >= 0;) { successList.Add(jumpItems[i].JumpItem); } } else { // If the list contained items that could not be added because this object isn't a handler // then drop all ShellItems and retry without them. if (isHeterogenous && hr == HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER) { Utility.SafeRelease(ref shellObjectCollection); var linksOnlyList = new List<_ShellObjectPair>(); foreach (var itemMap in jumpItems) { if (itemMap.JumpItem is JumpPath) { rejectionList.Add(new _RejectedJumpItemPair { JumpItem = itemMap.JumpItem, Reason = JumpItemRejectionReason.NoRegisteredHandler }); } else { linksOnlyList.Add(itemMap); } } if (linksOnlyList.Count > 0) { // There's not a reason I know of that we should reject a list of only links... Debug.Assert(jumpItems.Count != linksOnlyList.Count); AddCategory(cdl, category, linksOnlyList, successList, rejectionList, false); } } else { Debug.Assert(HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER != hr); // If we failed for some other reason, just reject everything. foreach (var item in jumpItems) { rejectionList.Add(new _RejectedJumpItemPair { JumpItem = item.JumpItem, Reason = JumpItemRejectionReason.InvalidItem }); } } } }
private static void AddCategory(ICustomDestinationList cdl, string category, List<_ShellObjectPair> jumpItems, List<JumpItem> successList, List<_RejectedJumpItemPair> rejectionList) { AddCategory(cdl, category, jumpItems, successList, rejectionList, true); }
private void _BuildShellLists(out List <JumpItem> successList, out List <_RejectedJumpItemPair> rejectedList, out List <_ShellObjectPair> removedList) { // Declare these outside the try block so we can cleanup native resources in the _ShellObjectPairs. List <List <_ShellObjectPair> > categories = null; removedList = null; ICustomDestinationList destinationList = CLSID.CoCreateInstance <ICustomDestinationList>(CLSID.DestinationList); try { // Even though we're not exposing Shell's AppModelId concept, we'll still respect it // since it's easy to clients to p/invoke to set it for Application and Window, but not for JumpLists string appId = _RuntimeId; if (!string.IsNullOrEmpty(appId)) { destinationList.SetAppID(appId); } // The number ot items visible on a jump list is a user setting. Shell doesn't reject items based on overflow. // We don't bother checking against it because the app can query the setting and manage overflow based on it // if they really care. We'll happily add too many items with the hope that if the user changes the setting // items will be recovered from the overflow. uint slotsVisible; Guid removedIid = new Guid(IID.ObjectArray); var objectsRemoved = (IObjectArray)destinationList.BeginList(out slotsVisible, ref removedIid); // Keep track of the items that were previously removed by the user. // We don't want to pend any items that are contained in this list. // It's possible that this contains null JumpItems when we were unable to do the conversion. removedList = GenerateJumpItems(objectsRemoved); // Keep track of the items that have been successfully pended. // IMPORTANT: Ensure at the end of this that if the list is applied again that it would // result in items being added to the JumpList in the same order. // This doesn't mean that they'll be ordered the same as how the user added them // (e.g. categories will be coalesced), but the categories should appear in the same order. // Since when we call AddCategory we're doing it in reverse order, AddCategory augments // the items in the list in reverse as well. At the end the final list is reversed. successList = new List <JumpItem>(JumpItems.Count); // Keep track of the items that we couldn't pend, and why. rejectedList = new List <_RejectedJumpItemPair>(JumpItems.Count); // Need to group the JumpItems based on their categories. // The special "Tasks" category doesn't actually have a name and should be first so it's unconditionally added. categories = new List <List <_ShellObjectPair> >() { new List <_ShellObjectPair>() }; // This is not thread-safe. // We're traversing the original list so we're vulnerable to another thread modifying it during the enumeration. foreach (var jumpItem in JumpItems) { if (jumpItem == null) { // App added a null jump item? Just go through the normal failure mechanisms. rejectedList.Add(new _RejectedJumpItemPair { JumpItem = jumpItem, Reason = JumpItemRejectionReason.InvalidItem }); continue; } object shellObject = null; try { shellObject = GetShellObjectForJumpItem(jumpItem); // If for some reason we couldn't create the item add it to the rejected list. if (shellObject == null) { rejectedList.Add(new _RejectedJumpItemPair { Reason = JumpItemRejectionReason.InvalidItem, JumpItem = jumpItem }); continue; } // Don't add this item if it's in the list of items previously removed by the user. if (ListContainsShellObject(removedList, shellObject)) { rejectedList.Add(new _RejectedJumpItemPair { Reason = JumpItemRejectionReason.RemovedByUser, JumpItem = jumpItem }); continue; } var shellMap = new _ShellObjectPair { JumpItem = jumpItem, ShellObject = shellObject }; if (string.IsNullOrEmpty(jumpItem.CustomCategory)) { // No custom category, so add to the Tasks list. categories[0].Add(shellMap); } else { // Find the appropriate category and add to that list. // If it doesn't exist, add a new category for it. bool categoryExists = false; foreach (var list in categories) { // The first item in the category list can be used to check the name. if (list.Count > 0 && list[0].JumpItem.CustomCategory == jumpItem.CustomCategory) { list.Add(shellMap); categoryExists = true; break; } } if (!categoryExists) { categories.Add(new List <_ShellObjectPair>() { shellMap }); } } // Shell interface is now owned by the category list. shellObject = null; } finally { Utility.SafeRelease(ref shellObject); } } // Jump List categories get added top-down, except for "Tasks" which is special and always at the bottom. // We want the Recent/Frequent to always be at the top so they get added first. // Logically the categories are added bottom-up, but their contents are top-down, // so we reverse the order we add the categories to the destinationList. // To preserve the item ordering AddCategory also adds items in reverse. // We need to reverse the final list when everything is done. categories.Reverse(); if (ShowFrequentCategory) { destinationList.AppendKnownCategory(KDC.FREQUENT); } if (ShowRecentCategory) { destinationList.AppendKnownCategory(KDC.RECENT); } // Now that all the JumpItems are grouped add them to the custom destinations list. foreach (List <_ShellObjectPair> categoryList in categories) { if (categoryList.Count > 0) { string categoryHeader = categoryList[0].JumpItem.CustomCategory; AddCategory(destinationList, categoryHeader, categoryList, successList, rejectedList); } } destinationList.CommitList(); // Swap the current list with what we were able to successfully place into the JumpList. // Reverse it first to ensure that the items are in a repeatable order. successList.Reverse(); } finally { // Deterministically release native resources. Utility.SafeRelease(ref destinationList); if (categories != null) { foreach (List <_ShellObjectPair> list in categories) { _ShellObjectPair.ReleaseShellObjects(list); } } // Note that this only clears the ShellObjects, not the JumpItems. // We still need the JumpItems out of this list for the JumpItemsRemovedByUser event. _ShellObjectPair.ReleaseShellObjects(removedList); } }
/// <summary> /// Creates a new instance of the JumpList class with the specified /// appId. The JumpList is associated with the given window. /// </summary> /// <param name="appID">Application Id to use for this instace.</param> /// <param name="windowHandle">Window handle for the window that is associated with this JumpList</param> protected JumpList(string appID, IntPtr windowHandle) { // Throw exception if not running on Win7 or newer PlatformHelper.ThrowIfNotWin7OrHigher(); // Native implementation of destination list customDestinationList = (ICustomDestinationList)new CDestinationList(); // Set application user model ID if (!string.IsNullOrEmpty(appID)) { ApplicationId = appID; // If the user hasn't yet set the application id for the whole process, // use the first JumpList's AppId for the whole process. This will ensure // we have the same JumpList for all the windows (unless user overrides and creates a new // JumpList for a specific child window) if (!TaskbarManager.Instance.ApplicationIdSetProcessWide) TaskbarManager.Instance.ApplicationId = appID; if (windowHandle != IntPtr.Zero) TaskbarManager.Instance.SetApplicationIdForSpecificWindow(windowHandle, appID); } }
private static void AddCategory(ICustomDestinationList cdl, string category, List <_ShellObjectPair> jumpItems, List <JumpItem> successList, List <_RejectedJumpItemPair> rejectionList, bool isHeterogenous) { Debug.Assert(jumpItems.Count != 0); Debug.Assert(cdl != null); HRESULT hr; var shellObjectCollection = (IObjectCollection)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.EnumerableObjectCollection))); foreach (var itemMap in jumpItems) { shellObjectCollection.AddObject(itemMap.ShellObject); } if (string.IsNullOrEmpty(category)) { hr = cdl.AddUserTasks((IObjectArray)shellObjectCollection); } else { hr = cdl.AppendCategory(category, (IObjectArray)shellObjectCollection); } if (hr.Succeeded) { // Woot! Add these items to the list. // Do it in reverse order so Apply has the items in the correct order. for (int i = jumpItems.Count; --i >= 0;) { successList.Add(jumpItems[i].JumpItem); } } else { // If the list contained items that could not be added because this object isn't a handler // then drop all ShellItems and retry without them. if (isHeterogenous && hr == HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER) { if (TraceShell.IsEnabled) { TraceShell.Trace(TraceEventType.Error, TraceShell.RejectingJumpListCategoryBecauseNoRegisteredHandler(category)); } Utilities.SafeRelease(ref shellObjectCollection); var linksOnlyList = new List <_ShellObjectPair>(); foreach (var itemMap in jumpItems) { if (itemMap.JumpItem is JumpPath) { rejectionList.Add(new _RejectedJumpItemPair { JumpItem = itemMap.JumpItem, Reason = JumpItemRejectionReason.NoRegisteredHandler }); } else { linksOnlyList.Add(itemMap); } } if (linksOnlyList.Count > 0) { // There's not a reason I know of that we should reject a list of only links... Debug.Assert(jumpItems.Count != linksOnlyList.Count); AddCategory(cdl, category, linksOnlyList, successList, rejectionList, false); } } else { Debug.Assert(HRESULT.DESTS_E_NO_MATCHING_ASSOC_HANDLER != hr); // If we failed for some other reason, just reject everything. foreach (var item in jumpItems) { rejectionList.Add(new _RejectedJumpItemPair { JumpItem = item.JumpItem, Reason = JumpItemRejectionReason.InvalidItem }); } } } }
private static void AddRecentNotes(ICustomDestinationList custom_destinationd_list, NoteManager note_manager, uint slots) { IObjectCollection object_collection = (IObjectCollection)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID.EnumerableObjectCollection)); // Prevent template notes from appearing in the menu Tag template_tag = TagManager.GetOrCreateSystemTag(TagManager.TemplateNoteSystemTag); uint index = 0; foreach (Note note in note_manager.Notes) { if (note.IsSpecial) { continue; } // Skip template notes if (note.ContainsTag(template_tag)) { continue; } string note_title = note.Title; if (note.IsNew) { note_title = String.Format(Catalog.GetString("{0} (new)"), note_title); } IShellLink note_link = CreateShellLink(note_title, tomboy_path, "--open-note " + note.Uri, System.IO.Path.Combine(icons_path, NoteIcon), -1); if (note_link != null) { object_collection.AddObject(note_link); } if (++index == slots - 1) { break; } } // Add Start Here note Note start_note = note_manager.FindByUri(NoteManager.StartNoteUri); if (start_note != null) { IShellLink start_note_link = CreateShellLink(start_note.Title, tomboy_path, "--open-note " + NoteManager.StartNoteUri, System.IO.Path.Combine(icons_path, NoteIcon), -1); if (start_note_link != null) { object_collection.AddObject(start_note_link); } } custom_destinationd_list.AppendCategory(Catalog.GetString("Recent Notes"), (IObjectArray)object_collection); Marshal.ReleaseComObject(object_collection); object_collection = null; }
internal void RefreshTasks(ICustomDestinationList destinationList) { if (_tasks.Count == 0) return; IObjectCollection taskCollection = (IObjectCollection)new CEnumerableObjectCollection(); foreach (IJumpListTask task in _tasks) { HResult addObjectResult = taskCollection.AddObject(task.GetShellRepresentation()); addObjectResult.ThrowIf(); } HResult addUserTasksResult = destinationList.AddUserTasks((IObjectArray)taskCollection); addUserTasksResult.ThrowIf(); }
private void ApplyList() { Verify.IsApartmentState(ApartmentState.STA); if (!Utilities.IsOSWindows7OrNewer) { this.RejectEverything(); return; } List <List <JumpList._ShellObjectPair> > list = null; List <JumpList._ShellObjectPair> list2 = null; ICustomDestinationList customDestinationList = (ICustomDestinationList)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("77f10cf0-3db5-4966-b520-b7c54fd35ed6"))); List <JumpItem> list3; List <JumpList._RejectedJumpItemPair> list4; try { string runtimeId = JumpList._RuntimeId; if (!string.IsNullOrEmpty(runtimeId)) { customDestinationList.SetAppID(runtimeId); } Guid guid = new Guid("92CA9DCD-5622-4bba-A805-5E9F541BD8C9"); uint num; IObjectArray shellObjects = (IObjectArray)customDestinationList.BeginList(out num, ref guid); list2 = JumpList.GenerateJumpItems(shellObjects); list3 = new List <JumpItem>(this.JumpItems.Count); list4 = new List <JumpList._RejectedJumpItemPair>(this.JumpItems.Count); list = new List <List <JumpList._ShellObjectPair> > { new List <JumpList._ShellObjectPair>() }; foreach (JumpItem jumpItem in this.JumpItems) { if (jumpItem == null) { list4.Add(new JumpList._RejectedJumpItemPair { JumpItem = jumpItem, Reason = JumpItemRejectionReason.InvalidItem }); } else { object obj = null; try { obj = JumpList.GetShellObjectForJumpItem(jumpItem); if (obj == null) { list4.Add(new JumpList._RejectedJumpItemPair { Reason = JumpItemRejectionReason.InvalidItem, JumpItem = jumpItem }); } else if (JumpList.ListContainsShellObject(list2, obj)) { list4.Add(new JumpList._RejectedJumpItemPair { Reason = JumpItemRejectionReason.RemovedByUser, JumpItem = jumpItem }); } else { JumpList._ShellObjectPair item = new JumpList._ShellObjectPair { JumpItem = jumpItem, ShellObject = obj }; if (string.IsNullOrEmpty(jumpItem.CustomCategory)) { list[0].Add(item); } else { bool flag = false; foreach (List <JumpList._ShellObjectPair> list5 in list) { if (list5.Count > 0 && list5[0].JumpItem.CustomCategory == jumpItem.CustomCategory) { list5.Add(item); flag = true; break; } } if (!flag) { list.Add(new List <JumpList._ShellObjectPair> { item }); } } obj = null; } } finally { Utilities.SafeRelease <object>(ref obj); } } } list.Reverse(); if (this.ShowFrequentCategory) { customDestinationList.AppendKnownCategory(KDC.FREQUENT); } if (this.ShowRecentCategory) { customDestinationList.AppendKnownCategory(KDC.RECENT); } foreach (List <JumpList._ShellObjectPair> list6 in list) { if (list6.Count > 0) { string customCategory = list6[0].JumpItem.CustomCategory; JumpList.AddCategory(customDestinationList, customCategory, list6, list3, list4); } } customDestinationList.CommitList(); } catch { if (TraceShell.IsEnabled) { TraceShell.Trace(TraceEventType.Error, TraceShell.RejectingJumpItemsBecauseCatastrophicFailure); } this.RejectEverything(); return; } finally { Utilities.SafeRelease <ICustomDestinationList>(ref customDestinationList); if (list != null) { foreach (List <JumpList._ShellObjectPair> list7 in list) { JumpList._ShellObjectPair.ReleaseShellObjects(list7); } } JumpList._ShellObjectPair.ReleaseShellObjects(list2); } list3.Reverse(); this._jumpItems = list3; EventHandler <JumpItemsRejectedEventArgs> jumpItemsRejected = this.JumpItemsRejected; EventHandler <JumpItemsRemovedEventArgs> jumpItemsRemovedByUser = this.JumpItemsRemovedByUser; if (list4.Count > 0 && jumpItemsRejected != null) { List <JumpItem> list8 = new List <JumpItem>(list4.Count); List <JumpItemRejectionReason> list9 = new List <JumpItemRejectionReason>(list4.Count); foreach (JumpList._RejectedJumpItemPair rejectedJumpItemPair in list4) { list8.Add(rejectedJumpItemPair.JumpItem); list9.Add(rejectedJumpItemPair.Reason); } jumpItemsRejected(this, new JumpItemsRejectedEventArgs(list8, list9)); } if (list2.Count > 0 && jumpItemsRemovedByUser != null) { List <JumpItem> list10 = new List <JumpItem>(list2.Count); foreach (JumpList._ShellObjectPair shellObjectPair in list2) { if (shellObjectPair.JumpItem != null) { list10.Add(shellObjectPair.JumpItem); } } if (list10.Count > 0) { jumpItemsRemovedByUser(this, new JumpItemsRemovedEventArgs(list10)); } } }