linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #02267
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2271: Support taskbar thumbnails and "Aero Peek" live previews on Win 7
------------------------------------------------------------
revno: 2271
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Fri 2010-10-29 00:43:23 +0200
message:
Support taskbar thumbnails and "Aero Peek" live previews on Win 7
added:
dwt/include/dwt/Taskbar.h
dwt/include/dwt/dwt_dwmapi.h
dwt/include/dwt/dwt_shlobj.h
dwt/src/Taskbar.cpp
modified:
changelog.txt
dwt/include/dwt/WindowsHeaders.h
dwt/include/dwt/util/win32/Version.h
dwt/include/dwt/widgets/FolderDialog.h
dwt/include/dwt/widgets/TabView.h
dwt/src/util/win32/Version.cpp
dwt/src/widgets/Notification.cpp
dwt/src/widgets/TabView.cpp
win32/MainWindow.cpp
win32/stdafx.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt 2010-10-20 20:49:31 +0000
+++ changelog.txt 2010-10-28 22:43:23 +0000
@@ -21,7 +21,8 @@
* Customize the font selection dialog, save the charset (poy)
* Blacklist rogue hub-lists (poy)
* Fix some wrong menu fonts (poy)
-* Separate IP and Country coloumn in the list of users and connections (thanks iceman50)
+* Separate IP and Country columns in users and connections lists (thanks iceman50)
+* Support taskbar thumbnails and "Aero Peek" live previews on Win 7 (poy)
-- 0.770 2010-07-05 --
* [L#550300] Catch more potential file corruptions (thanks bigmuscle)
=== added file 'dwt/include/dwt/Taskbar.h'
--- dwt/include/dwt/Taskbar.h 1970-01-01 00:00:00 +0000
+++ dwt/include/dwt/Taskbar.h 2010-10-28 22:43:23 +0000
@@ -0,0 +1,73 @@
+/*
+ DC++ Widget Toolkit
+
+ Copyright (c) 2007-2010, Jacek Sieka
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the DWT nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DWT_TASKBAR_H
+#define DWT_TASKBAR_H
+
+#include "WindowsHeaders.h"
+#include "forward.h"
+#include "resources/Bitmap.h"
+#include "resources/Icon.h"
+#include <unordered_map>
+
+namespace dwt {
+
+/** provides widgets with the ability to play with the taskbar associated with a main window. */
+class Taskbar {
+public:
+ void initTaskbar(WindowPtr window_);
+
+protected:
+ typedef std::function<void (ContainerPtr)> ActivateF;
+ /// @param activateF_ function called when the user activates a tab using the taskbar.
+ explicit Taskbar(const ActivateF& activateF_);
+ virtual ~Taskbar();
+
+ void addToTaskbar(ContainerPtr tab);
+ void removeFromTaskbar(ContainerPtr tab);
+ void moveOnTaskbar(ContainerPtr tab, ContainerPtr rightNeighbor = 0);
+ void setActiveOnTaskbar(ContainerPtr tab);
+ void setTaskbarIcon(ContainerPtr tab, const IconPtr& icon);
+
+ ITaskbarList3* taskbar;
+
+private:
+ BitmapPtr getBitmap(ContainerPtr tab, LPARAM thumbnailSize);
+
+ WindowPtr window;
+ std::unordered_map<ContainerPtr, ContainerPtr> tabs;
+
+ ActivateF activateF;
+};
+
+}
+
+#endif
=== modified file 'dwt/include/dwt/WindowsHeaders.h'
--- dwt/include/dwt/WindowsHeaders.h 2010-07-10 15:49:05 +0000
+++ dwt/include/dwt/WindowsHeaders.h 2010-10-28 22:43:23 +0000
@@ -70,6 +70,7 @@
#include <windowsx.h>
#include <shellapi.h>
#include <shlwapi.h>
+#include "dwt_shlobj.h"
#include <commctrl.h>
#include <commdlg.h>
#include <assert.h>
=== added file 'dwt/include/dwt/dwt_dwmapi.h'
--- dwt/include/dwt/dwt_dwmapi.h 1970-01-01 00:00:00 +0000
+++ dwt/include/dwt/dwt_dwmapi.h 2010-10-28 22:43:23 +0000
@@ -0,0 +1,51 @@
+/*
+ DC++ Widget Toolkit
+
+ Copyright (c) 2007-2010, Jacek Sieka
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the DWT nor SmartWin++ nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DWT_DWMAPI_H
+#define DWT_DWMAPI_H
+
+#ifdef __GNUC__
+// MinGW lacks dwmapi.h, so define what we need here
+
+#define DWMWA_FORCE_ICONIC_REPRESENTATION 7
+#define DWMWA_FORCE_ICONIC_REPRESENTATION 10
+
+#else
+#include <dwmapi.h>
+#endif
+
+// in addition, we also define the following messages that are normally only defined for Win 7
+#if(_WIN32_WINNT < 0x0601)
+#define WM_DWMSENDICONICTHUMBNAIL 0x0323
+#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326
+#endif
+
+#endif
=== added file 'dwt/include/dwt/dwt_shlobj.h'
--- dwt/include/dwt/dwt_shlobj.h 1970-01-01 00:00:00 +0000
+++ dwt/include/dwt/dwt_shlobj.h 2010-10-28 22:43:23 +0000
@@ -0,0 +1,124 @@
+/*
+ DC++ Widget Toolkit
+
+ Copyright (c) 2007-2010, Jacek Sieka
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the DWT nor SmartWin++ nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DWT_SHLOBJ_H
+#define DWT_SHLOBJ_H
+
+#include <shlobj.h>
+
+#ifdef __GNUC__
+
+// defs for ITaskbarList, ITaskbarList2, ITaskbarList3 (incomplete - just the parts that we need)
+/// @todo MinGW-w64 seems to be implementing these, they have version 1 & 2, but not 3 yet... remove this when they have it.
+
+#ifndef __ITaskbarList_FWD_DEFINED__
+#define __ITaskbarList_FWD_DEFINED__
+typedef struct ITaskbarList ITaskbarList;
+#endif
+
+#ifndef __ITaskbarList2_FWD_DEFINED__
+#define __ITaskbarList2_FWD_DEFINED__
+typedef struct ITaskbarList2 ITaskbarList2;
+#endif
+
+#ifndef __ITaskbarList_INTERFACE_DEFINED__
+#define __ITaskbarList_INTERFACE_DEFINED__
+ EXTERN_C const IID IID_ITaskbarList;
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ struct ITaskbarList : public IUnknown {
+ public:
+ virtual HRESULT WINAPI HrInit(void) = 0;
+ virtual HRESULT WINAPI AddTab(HWND hwnd) = 0;
+ virtual HRESULT WINAPI DeleteTab(HWND hwnd) = 0;
+ virtual HRESULT WINAPI ActivateTab(HWND hwnd) = 0;
+ virtual HRESULT WINAPI SetActiveAlt(HWND hwnd) = 0;
+ };
+#endif
+ HRESULT WINAPI ITaskbarList_HrInit_Proxy(ITaskbarList *This);
+ void __RPC_STUB ITaskbarList_HrInit_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList_AddTab_Proxy(ITaskbarList *This,HWND hwnd);
+ void __RPC_STUB ITaskbarList_AddTab_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList_DeleteTab_Proxy(ITaskbarList *This,HWND hwnd);
+ void __RPC_STUB ITaskbarList_DeleteTab_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList_ActivateTab_Proxy(ITaskbarList *This,HWND hwnd);
+ void __RPC_STUB ITaskbarList_ActivateTab_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList_SetActiveAlt_Proxy(ITaskbarList *This,HWND hwnd);
+ void __RPC_STUB ITaskbarList_SetActiveAlt_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+#endif
+
+#ifndef __ITaskbarList2_INTERFACE_DEFINED__
+#define __ITaskbarList2_INTERFACE_DEFINED__
+ EXTERN_C const IID IID_ITaskbarList2;
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ struct ITaskbarList2 : public ITaskbarList {
+ public:
+ virtual HRESULT WINAPI MarkFullscreenWindow(HWND hwnd,WINBOOL fFullscreen) = 0;
+ };
+#endif
+ HRESULT WINAPI ITaskbarList2_MarkFullscreenWindow_Proxy(ITaskbarList2 *This,HWND hwnd,WINBOOL fFullscreen);
+ void __RPC_STUB ITaskbarList2_MarkFullscreenWindow_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+#endif
+
+#ifndef __ITaskbarList3_INTERFACE_DEFINED__
+#define __ITaskbarList3_INTERFACE_DEFINED__
+ EXTERN_C const IID IID_ITaskbarList3;
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ struct ITaskbarList3 : public ITaskbarList2 {
+ public:
+ virtual HRESULT WINAPI RegisterTab(
+ /* [in] */ HWND hwndTab,
+ /* [in] */ HWND hwndMDI) = 0;
+
+ virtual HRESULT WINAPI UnregisterTab(
+ /* [in] */ HWND hwndTab) = 0;
+
+ virtual HRESULT WINAPI SetTabOrder(
+ /* [in] */ HWND hwndTab,
+ /* [in] */ HWND hwndInsertBefore) = 0;
+
+ virtual HRESULT WINAPI SetTabActive(
+ /* [in] */ HWND hwndTab,
+ /* [in] */ HWND hwndMDI,
+ /* [in] */ DWORD dwReserved) = 0;
+ };
+#endif
+ HRESULT WINAPI ITaskbarList3_RegisterTab_Proxy(ITaskbarList3 *This,HWND hwnd,HWND hwndMDI);
+ void __RPC_STUB ITaskbarList3_RegisterTab_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList3_UnregisterTab_Proxy(ITaskbarList3 *This,HWND hwnd);
+ void __RPC_STUB ITaskbarList3_UnregisterTab_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList3_SetTabOrder_Proxy(ITaskbarList3 *This,HWND hwnd,HWND hwndInsertBefore);
+ void __RPC_STUB ITaskbarList3_SetTabOrder_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+ HRESULT WINAPI ITaskbarList3_SetTabActive_Proxy(ITaskbarList3 *This,HWND hwnd,HWND hwndMDI,DWORD dwReserved);
+ void __RPC_STUB ITaskbarList3_SetTabActive_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);
+#endif
+
+#endif
+#endif
=== modified file 'dwt/include/dwt/util/win32/Version.h'
--- dwt/include/dwt/util/win32/Version.h 2010-02-11 21:44:13 +0000
+++ dwt/include/dwt/util/win32/Version.h 2010-10-28 22:43:23 +0000
@@ -33,7 +33,8 @@
enum Version {
XP,
- VISTA
+ VISTA,
+ SEVEN
};
bool ensureVersion(Version version);
=== modified file 'dwt/include/dwt/widgets/FolderDialog.h'
--- dwt/include/dwt/widgets/FolderDialog.h 2010-10-28 20:31:03 +0000
+++ dwt/include/dwt/widgets/FolderDialog.h 2010-10-28 22:43:23 +0000
@@ -38,7 +38,6 @@
#include "../Widget.h"
#include "../tstring.h"
-#include <shlobj>
namespace dwt {
=== modified file 'dwt/include/dwt/widgets/TabView.h'
--- dwt/include/dwt/widgets/TabView.h 2010-10-28 20:31:03 +0000
+++ dwt/include/dwt/widgets/TabView.h 2010-10-28 22:43:23 +0000
@@ -38,6 +38,7 @@
#include "../aspects/AspectSelection.h"
#include "../aspects/AspectText.h"
#include "Control.h"
+#include <dwt/Taskbar.h>
#include <dwt/Theme.h>
#include <list>
@@ -52,7 +53,8 @@
// Aspects
private AspectCollection<TabView, int>,
public AspectSelection< TabView, int >,
- public AspectText< TabView >
+ public AspectText< TabView >,
+ public Taskbar
{
typedef CommonControl BaseType;
friend class AspectCollection<TabView, int>;
=== added file 'dwt/src/Taskbar.cpp'
--- dwt/src/Taskbar.cpp 1970-01-01 00:00:00 +0000
+++ dwt/src/Taskbar.cpp 2010-10-28 22:43:23 +0000
@@ -0,0 +1,232 @@
+/*
+ DC++ Widget Toolkit
+
+ Copyright (c) 2007-2010, Jacek Sieka
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the DWT nor SmartWin++ nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dwt/Taskbar.h>
+
+#include <dwt/dwt_dwmapi.h>
+#include <dwt/LibraryLoader.h>
+#include <dwt/util/check.h>
+#include <dwt/util/win32/Version.h>
+#include <dwt/widgets/Container.h>
+#include <dwt/widgets/Window.h>
+
+namespace dwt {
+
+static const UINT taskbarButtonMsg = ::RegisterWindowMessage(_T("TaskbarButtonCreated"));
+
+typedef HRESULT (WINAPI *t_DwmInvalidateIconicBitmaps)(HWND);
+static t_DwmInvalidateIconicBitmaps DwmInvalidateIconicBitmaps;
+
+typedef HRESULT (WINAPI *t_DwmSetIconicLivePreviewBitmap)(HWND, HBITMAP, POINT*, DWORD);
+static t_DwmSetIconicLivePreviewBitmap DwmSetIconicLivePreviewBitmap;
+
+typedef HRESULT (WINAPI *t_DwmSetIconicThumbnail)(HWND, HBITMAP, DWORD);
+static t_DwmSetIconicThumbnail DwmSetIconicThumbnail;
+
+typedef HRESULT (WINAPI *t_DwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD);
+static t_DwmSetWindowAttribute DwmSetWindowAttribute;
+
+Taskbar::Taskbar(const ActivateF& activateF_) :
+taskbar(0),
+window(0),
+activateF(activateF_)
+{
+}
+
+Taskbar::~Taskbar() {
+ if(taskbar)
+ taskbar->Release();
+}
+
+void Taskbar::initTaskbar(WindowPtr window_) {
+ if(!util::win32::ensureVersion(util::win32::SEVEN))
+ return;
+
+ /// @todo call ChangeWindowMessageFilterEx on WM_DWMSENDICONICTHUMBNAIL & WM_DWMSENDICONICLIVEPREVIEWBITMAP
+
+ static LibraryLoader lib(_T("dwmapi"), true);
+ if(lib.loaded()) {
+
+#define get(name) if(!name) { if(!(name = reinterpret_cast<t_##name>(lib.getProcAddress(_T(#name))))) { return; } }
+ get(DwmInvalidateIconicBitmaps);
+ get(DwmSetIconicLivePreviewBitmap);
+ get(DwmSetIconicThumbnail);
+ get(DwmSetWindowAttribute);
+#undef get
+
+ window = window_;
+ dwtassert(window, _T("Taskbar: no widget set"));
+
+ // init the COM pointer on reception of the "TaskbarButtonCreated" message.
+ window->onRaw([this](WPARAM, LPARAM) -> LRESULT {
+ if(!taskbar) {
+ if(::CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER, IID_ITaskbarList,
+ reinterpret_cast<LPVOID*>(&taskbar)) != S_OK) { taskbar = 0; }
+ if(taskbar && taskbar->HrInit() != S_OK) {
+ taskbar->Release();
+ taskbar = 0;
+ }
+ }
+ return 0;
+ }, Message(taskbarButtonMsg));
+ }
+}
+
+void Taskbar::addToTaskbar(ContainerPtr tab) {
+ /* for Windows to acknowledge that our tab window is worthy of having its own thumbnail in the
+ taskbar, we have to create an invisible popup window that will act as a proxy between the
+ taskbar and the actual tab window.
+ this technique is illustrated in MFC as well as the Windows SDK sample at
+ "Samples\winui\shell\appshellintegration\TabThumbnails". */
+
+ ContainerPtr proxy;
+ {
+ Container::Seed seed;
+ seed.caption = tab->getText();
+ seed.style &= ~WS_VISIBLE;
+ seed.style |= WS_POPUP | WS_CAPTION;
+ seed.exStyle |= WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE;
+ seed.location = Rectangle();
+ proxy = window->addChild(seed);
+ }
+ tabs[tab] = proxy;
+
+ // keep the proxy window in sync with the actual tab window.
+ tab->onTextChanging([proxy](const tstring& text) { proxy->setText(text); });
+ tab->onSized([proxy](const SizedEvent&) { DwmInvalidateIconicBitmaps(proxy->handle()); });
+
+ proxy->onActivate([this, tab](bool activate) {
+ if(activate)
+ activateF(tab);
+ });
+ proxy->onClosing([tab]() -> bool {
+ tab->close(true);
+ return false; // don't close the proxy window just yet; wait for removeFromTaskbar.
+ });
+
+ proxy->onRaw([this, tab, proxy](WPARAM, LPARAM lParam) -> LRESULT {
+ // generate a thumbnail to be displayed in the taskbar.
+ BitmapPtr bitmap = getBitmap(tab, lParam);
+ if(bitmap) {
+ DwmSetIconicThumbnail(proxy->handle(), bitmap->handle(), 0);
+ }
+ return 0;
+ }, Message(WM_DWMSENDICONICTHUMBNAIL));
+
+ proxy->onRaw([this, tab, proxy](WPARAM, LPARAM) -> LRESULT {
+ // generate a preview of the tab to be shown in "Aero Peek" when the user hovers the thumbnail.
+ BitmapPtr bitmap = getBitmap(tab, 0);
+ if(bitmap) {
+ Point offset;
+ ::MapWindowPoints(tab->handle(), window->handle(), &offset, 1);
+ MENUBARINFO info = { sizeof(MENUBARINFO) };
+ if(::GetMenuBarInfo(window->handle(), OBJID_MENU, 0, &info))
+ offset.y += Rectangle(info.rcBar).height();
+ DwmSetIconicLivePreviewBitmap(proxy->handle(), bitmap->handle(), &offset, 0);
+ }
+ return 0;
+ }, Message(WM_DWMSENDICONICLIVEPREVIEWBITMAP));
+
+ // indicate to the window manager that it should always use the bitmaps we provide.
+ BOOL attrib = TRUE;
+ DwmSetWindowAttribute(proxy->handle(), DWMWA_FORCE_ICONIC_REPRESENTATION, &attrib, sizeof(attrib));
+ DwmSetWindowAttribute(proxy->handle(), DWMWA_HAS_ICONIC_BITMAP, &attrib, sizeof(attrib));
+
+ taskbar->RegisterTab(proxy->handle(), window->handle());
+ moveOnTaskbar(tab);
+}
+
+void Taskbar::removeFromTaskbar(ContainerPtr tab) {
+ ContainerPtr proxy = tabs[tab];
+ taskbar->UnregisterTab(proxy->handle());
+ ::DestroyWindow(proxy->handle());
+ tabs.erase(tab);
+}
+
+void Taskbar::moveOnTaskbar(ContainerPtr tab, ContainerPtr rightNeighbor) {
+ taskbar->SetTabOrder(tabs[tab]->handle(), rightNeighbor ? tabs[rightNeighbor]->handle() : 0);
+}
+
+void Taskbar::setActiveOnTaskbar(ContainerPtr tab) {
+ taskbar->SetTabActive(tabs[tab]->handle(), window->handle(), 0);
+}
+
+void Taskbar::setTaskbarIcon(ContainerPtr tab, const IconPtr& icon) {
+ tabs[tab]->sendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icon->handle()));
+}
+
+BitmapPtr Taskbar::getBitmap(ContainerPtr tab, LPARAM thumbnailSize) {
+ UpdateCanvas canvas(tab);
+
+ // get the actual size of the tab.
+ const Point size_full(tab->getClientSize());
+ if(size_full.x <= 0 || size_full.y <= 0)
+ return 0;
+
+ // this DIB will hold a full capture of the tab.
+ BITMAPINFO info = { { sizeof(BITMAPINFOHEADER), size_full.x, size_full.y, 1, 32, BI_RGB } };
+ BitmapPtr bitmap_full(new Bitmap(::CreateDIBSection(canvas.handle(), &info, DIB_RGB_COLORS, 0, 0, 0)));
+
+ FreeCanvas canvas_full(::CreateCompatibleDC(canvas.handle()));
+ Canvas::Selector select_full(canvas_full, *bitmap_full);
+
+ tab->sendMessage(WM_PRINT, reinterpret_cast<WPARAM>(canvas_full.handle()), PRF_CLIENT | PRF_NONCLIENT | PRF_CHILDREN | PRF_ERASEBKGND);
+
+ // get rid of some transparent bits.
+ ::BitBlt(canvas_full.handle(), 0, 0, size_full.x, size_full.y, canvas_full.handle(), 0, 0, MERGECOPY);
+
+ if(!thumbnailSize)
+ return bitmap_full;
+
+ // compute the size of the thumbnail, must not exceed the LPARAM values.
+ double factor = std::min(static_cast<double>(HIWORD(thumbnailSize)) / static_cast<double>(size_full.x),
+ static_cast<double>(LOWORD(thumbnailSize)) / static_cast<double>(size_full.y));
+ const Point size_thumb(size_full.x * factor, size_full.y * factor);
+ if(size_thumb.x <= 0 || size_thumb.y <= 0)
+ return 0;
+
+ // this DIB will hold a resized view of the tab, to be used as a thumbnail.
+ info.bmiHeader.biWidth = size_thumb.x;
+ info.bmiHeader.biHeight = size_thumb.y;
+ BitmapPtr bitmap_thumb(new Bitmap(::CreateDIBSection(canvas.handle(), &info, DIB_RGB_COLORS, 0, 0, 0)));
+
+ FreeCanvas canvas_thumb(::CreateCompatibleDC(canvas.handle()));
+ Canvas::Selector select_thumb(canvas_thumb, *bitmap_thumb);
+
+ ::SetStretchBltMode(canvas_thumb.handle(), HALFTONE);
+ ::SetBrushOrgEx(canvas_thumb.handle(), 0, 0, 0);
+ ::StretchBlt(canvas_thumb.handle(), 0, 0, size_thumb.x, size_thumb.y,
+ canvas_full.handle(), 0, 0, size_full.x, size_full.y, SRCCOPY);
+
+ return bitmap_thumb;
+}
+
+}
=== modified file 'dwt/src/util/win32/Version.cpp'
--- dwt/src/util/win32/Version.cpp 2010-02-11 21:44:13 +0000
+++ dwt/src/util/win32/Version.cpp 2010-10-28 22:43:23 +0000
@@ -53,6 +53,7 @@
switch(version) {
case XP: return (major == 5 && minor >= 1) || major > 5;
case VISTA: return major >= 6;
+ case SEVEN: return (major == 6 && minor >= 1) || major > 6;
default: return false;
}
}
=== modified file 'dwt/src/widgets/Notification.cpp'
--- dwt/src/widgets/Notification.cpp 2010-09-02 18:16:12 +0000
+++ dwt/src/widgets/Notification.cpp 2010-10-28 22:43:23 +0000
@@ -36,7 +36,7 @@
const UINT Notification::message = ::RegisterWindowMessage(_T("dwt::Notification"));
-static const UINT taskbar = ::RegisterWindowMessage(_T("TaskbarCreated"));
+static const UINT taskbarMsg = ::RegisterWindowMessage(_T("TaskbarCreated"));
Notification::~Notification() {
setVisible(false);
@@ -48,7 +48,7 @@
// TODO Allow more than one icon per window
parent->setCallback(Message(message), [this](const MSG& msg, LRESULT&) { return trayHandler(msg); });
- parent->setCallback(Message(taskbar), [this](const MSG&, LRESULT&) { return redisplay(); });
+ parent->setCallback(Message(taskbarMsg), [this](const MSG&, LRESULT&) { return redisplay(); });
}
void Notification::setIcon(const IconPtr& icon_) {
=== modified file 'dwt/src/widgets/TabView.cpp'
--- dwt/src/widgets/TabView.cpp 2010-09-02 18:16:12 +0000
+++ dwt/src/widgets/TabView.cpp 2010-10-28 22:43:23 +0000
@@ -60,6 +60,7 @@
TabView::TabView(Widget* w) :
BaseType(w, ChainingDispatcher::superClass<TabView>()),
+Taskbar([this](ContainerPtr tab) { setActive(tab); }),
tip(0),
toggleActive(false),
font(0),
@@ -168,6 +169,13 @@
throw Win32Exception("Error while trying to add page into Tab Sheet");
}
+ if(taskbar) {
+ addToTaskbar(w);
+ if(image != -1) {
+ setTaskbarIcon(w, icon);
+ }
+ }
+
viewOrder.push_front(w);
if(viewOrder.size() == 1 || w->hasStyle(WS_VISIBLE)) {
@@ -220,6 +228,10 @@
}
layout();
+
+ if(taskbar) {
+ removeFromTaskbar(w);
+ }
}
IconPtr TabView::getIcon(unsigned index) const {
@@ -238,6 +250,10 @@
TCITEM item = { TCIF_IMAGE };
item.iImage = image;
TabCtrl_SetItem(this->handle(), i, &item);
+
+ if(taskbar) {
+ setTaskbarIcon(w, icon);
+ }
}
}
}
@@ -312,6 +328,10 @@
if(titleChangedFunction)
titleChangedFunction(ti->w->getText());
+
+ if(taskbar) {
+ setActiveOnTaskbar(ti->w);
+ }
}
void TabView::mark(ContainerPtr w) {
@@ -377,11 +397,25 @@
Rectangle tmp = getUsableArea(true);
if(!(tmp == clientSize)) {
- int i = getSelected();
- if(i != -1) {
- getTabInfo(i)->w->layout(tmp);
- }
clientSize = tmp;
+
+ // the client area has changed, update the selected tab synchronously.
+ ContainerPtr sel = 0;
+ TabInfo* ti = getTabInfo(getSelected());
+ if(ti) {
+ sel = ti->w;
+ sel->layout(clientSize);
+ }
+
+ // update background tabs too, but only asynchronously.
+ callAsync([this, sel]() {
+ for(auto i = viewOrder.begin(); i != viewOrder.end(); ++i) {
+ ContainerPtr w = *i;
+ if(w != sel) {
+ w->layout(clientSize);
+ }
+ }
+ });
}
}
@@ -522,8 +556,7 @@
TCHAR buf[1024] = { 0 };
item.pszText = buf;
item.cchTextMax = (sizeof(buf) / sizeof(TCHAR)) - 1;
-
- TabCtrl_GetItem( this->handle(), dragPos, & item );
+ TabCtrl_GetItem(handle(), dragPos, &item);
erase(dragPos);
@@ -532,6 +565,10 @@
active = getSelected();
layout();
+
+ if(taskbar) {
+ moveOnTaskbar(getTabInfo(dropPos)->w, (dropPos < size() - 1) ? getTabInfo(dropPos + 1)->w : 0);
+ }
}
return true;
=== modified file 'win32/MainWindow.cpp'
--- win32/MainWindow.cpp 2010-10-07 17:25:06 +0000
+++ win32/MainWindow.cpp 2010-10-28 22:43:23 +0000
@@ -499,6 +499,7 @@
seed.toggleActive = BOOLSETTING(TOGGLE_ACTIVE_WINDOW);
seed.ctrlTab = true;
tabs = addChild(seed);
+ tabs->initTaskbar(this);
tabs->onTitleChanged(std::bind(&MainWindow::handleTabsTitleChanged, this, _1));
tabs->onHelp(std::bind(&WinUtil::help, _1, _2));
paned->setFirst(tabs);
=== modified file 'win32/stdafx.h'
--- win32/stdafx.h 2010-10-05 21:48:07 +0000
+++ win32/stdafx.h 2010-10-28 22:43:23 +0000
@@ -22,7 +22,6 @@
#include <dcpp/stdinc.h>
#include <dcpp/DCPlusPlus.h>
-#include <shlobj.h>
#include <libintl.h>
#include <dwt/Application.h>