private HRESULT UpdateTaskbarThumbButtons() { Debug.Assert(null != _taskbarList); var nativeButtons = new THUMBBUTTON[c_MaximumThumbButtons]; TaskbarItemInfo taskbarInfo = TaskbarItemInfo; ThumbButtonInfoCollection thumbButtons = null; if (taskbarInfo != null) { thumbButtons = taskbarInfo.ThumbButtonInfos; } var nativeIcons = new List<NativeMethods.IconHandle>(); try { uint currentButton = 0; if (null != thumbButtons) { foreach (ThumbButtonInfo wrappedTB in thumbButtons) { var nativeTB = new THUMBBUTTON { iId = (uint)currentButton, dwMask = THB.FLAGS | THB.TOOLTIP | THB.ICON, }; switch (wrappedTB.Visibility) { case Visibility.Collapsed: // HIDDEN removes the button from layout logic. nativeTB.dwFlags = THBF.HIDDEN; break; case Visibility.Hidden: // To match WPF's notion of hidden, we want this not HIDDEN // but disabled, without background, and without icon. nativeTB.dwFlags = THBF.DISABLED | THBF.NOBACKGROUND; nativeTB.hIcon = IntPtr.Zero; break; default: case Visibility.Visible: nativeTB.szTip = wrappedTB.Description ?? ""; if (wrappedTB.ImageSource != null) { NativeMethods.IconHandle nativeIcon = IconHelper.CreateIconHandleFromImageSource(wrappedTB.ImageSource, _overlaySize); nativeTB.hIcon = nativeIcon.CriticalGetHandle(); nativeIcons.Add(nativeIcon); } if (!wrappedTB.IsBackgroundVisible) { nativeTB.dwFlags |= THBF.NOBACKGROUND; } if (!wrappedTB.IsEnabled) { nativeTB.dwFlags |= THBF.DISABLED; } else { nativeTB.dwFlags |= THBF.ENABLED; } // This is separate from enabled/disabled if (!wrappedTB.IsInteractive) { nativeTB.dwFlags |= THBF.NONINTERACTIVE; } if (wrappedTB.DismissWhenClicked) { nativeTB.dwFlags |= THBF.DISMISSONCLICK; } break; } nativeButtons[currentButton] = nativeTB; ++currentButton; if (currentButton == c_MaximumThumbButtons) { break; } } } // If we're not attached, or the list is less than the maximum number of buttons // then fill in the rest with collapsed, empty buttons. for (; currentButton < c_MaximumThumbButtons; ++currentButton) { nativeButtons[currentButton] = new THUMBBUTTON { iId = (uint)currentButton, dwFlags = THBF.NOBACKGROUND | THBF.DISABLED | THBF.HIDDEN, dwMask = THB.FLAGS | THB.ICON | THB.TOOLTIP }; } // Finally, apply the update. return _taskbarList.ThumbBarUpdateButtons(CriticalHandle, (uint)nativeButtons.Length, nativeButtons); } finally { foreach (var icon in nativeIcons) { icon.Dispose(); } } }
private HRESULT RegisterTaskbarThumbButtons() { Debug.Assert(null != _taskbarList); // The ITaskbarList3 API requires that the maximum number of buttons to ever be used // are registered at the beginning. Modifications can be made to this list later. var nativeButtons = new THUMBBUTTON[c_MaximumThumbButtons]; for (int i = 0; i < c_MaximumThumbButtons; ++i) { nativeButtons[i] = new THUMBBUTTON { iId = (uint)i, dwFlags = THBF.NOBACKGROUND | THBF.DISABLED | THBF.HIDDEN | THBF.NONINTERACTIVE, dwMask = THB.FLAGS | THB.ICON | THB.TOOLTIP }; } // If this gets called (successfully) more than once it usually returns E_INVALIDARG. It's not really // a failure and we potentially want to retry this operation. HRESULT hr = _taskbarList.ThumbBarAddButtons(CriticalHandle, (uint)nativeButtons.Length, nativeButtons); if (hr == HRESULT.E_INVALIDARG) { hr = HRESULT.S_FALSE; } return hr; }