summaryrefslogtreecommitdiff
path: root/plugins/W7UI/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/W7UI/src')
-rw-r--r--plugins/W7UI/src/clistproxywindow.cpp292
-rw-r--r--plugins/W7UI/src/clistproxywindow.h64
-rw-r--r--plugins/W7UI/src/dwmwindow.cpp209
-rw-r--r--plugins/W7UI/src/dwmwindow.h59
-rw-r--r--plugins/W7UI/src/headers.h78
-rw-r--r--plugins/W7UI/src/jumplist.cpp123
-rw-r--r--plugins/W7UI/src/jumplist.h7
-rw-r--r--plugins/W7UI/src/jumplistarray.cpp214
-rw-r--r--plugins/W7UI/src/jumplistarray.h29
-rw-r--r--plugins/W7UI/src/jumplistbuilder.cpp127
-rw-r--r--plugins/W7UI/src/jumplistbuilder.h47
-rw-r--r--plugins/W7UI/src/main.cpp79
-rw-r--r--plugins/W7UI/src/srmmproxywindow.cpp374
-rw-r--r--plugins/W7UI/src/srmmproxywindow.h42
-rw-r--r--plugins/W7UI/src/subclassmgr.cpp0
-rw-r--r--plugins/W7UI/src/subclassmgr.h71
-rw-r--r--plugins/W7UI/src/w7ui.cpp180
-rw-r--r--plugins/W7UI/src/win7api.cpp25
-rw-r--r--plugins/W7UI/src/win7api.h38
-rw-r--r--plugins/W7UI/src/win7api_ICustomDestinationList.h34
-rw-r--r--plugins/W7UI/src/win7api_IObjectArray.h15
-rw-r--r--plugins/W7UI/src/win7api_IObjectCollection.h16
-rw-r--r--plugins/W7UI/src/win7api_ITaskbarList3.h65
23 files changed, 2188 insertions, 0 deletions
diff --git a/plugins/W7UI/src/clistproxywindow.cpp b/plugins/W7UI/src/clistproxywindow.cpp
new file mode 100644
index 0000000000..12e5b476ed
--- /dev/null
+++ b/plugins/W7UI/src/clistproxywindow.cpp
@@ -0,0 +1,292 @@
+#include "headers.h"
+
+CClistProxyWindow *g_clistProxyWnd = 0;
+extern ITaskbarList3 *g_pTaskbarList;
+
+CClistProxyWindow::CClistProxyWindow() : m_overlayEvents(5)
+{
+ g_clistProxyWnd = this;
+
+ m_activeOverlay = 0;
+ m_overlayIcon = 0;
+ m_overlayText = 0;
+
+ SetWindowText(hwnd(), _T("Miranda IM"));
+ SendMessage(hwnd(), WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+ SendMessage(hwnd(), WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+
+ SetEventHook(ME_CLIST_STATUSMODECHANGE, &CClistProxyWindow::OnStatusModeChanged);
+ SetEventHook(ME_AV_MYAVATARCHANGED, &CClistProxyWindow::OnAvatarChanged);
+ SetEventHook(ME_SYSTEM_MODULESLOADED, &CClistProxyWindow::OnModulesLoaded);
+ SetEventHook(ME_PROTO_ACCLISTCHANGED, &CClistProxyWindow::OnAccListChanged);
+
+ SetTimer(1, 500);
+}
+
+CClistProxyWindow::~CClistProxyWindow()
+{
+ KillObjectEventHooks(this);
+}
+
+int __cdecl CClistProxyWindow::OnStatusModeChanged(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+int __cdecl CClistProxyWindow::OnAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+int __cdecl CClistProxyWindow::OnModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+int __cdecl CClistProxyWindow::OnAccListChanged(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+
+HANDLE CClistProxyWindow::SetEventHook(char *evt, int (__cdecl CClistProxyWindow::*fn)(WPARAM, LPARAM))
+{
+ return HookEventObj(evt, *(MIRANDAHOOKOBJ *)&fn, this);
+}
+
+void CClistProxyWindow::Flash()
+{
+ FlashWindow(hwnd(), TRUE);
+}
+
+void CClistProxyWindow::SetOverlayIcon(HICON hIcon)
+{
+ m_overlayIcon = hIcon;
+ m_overlayIconHandle = 0;
+}
+
+void CClistProxyWindow::SetOverlayIconHandle(HANDLE hIcolibIcon)
+{
+ m_overlayIcon = 0;
+ m_overlayIconHandle = hIcolibIcon;
+}
+
+void CClistProxyWindow::AddOverlayEvent(int idx)
+{
+ m_overlayEvents[idx].Push();
+}
+
+void CClistProxyWindow::RemoveOverlayEvent(int idx)
+{
+ m_overlayEvents[idx].Pop();
+}
+
+int CClistProxyWindow::AllocateOverlayEvent(HANDLE hIcolibIcon)
+{
+ m_overlayEvents.insert(new COverlayEventSlot(hIcolibIcon, _T("")), m_overlayEvents.getCount());
+ return m_overlayEvents.getCount() - 1;
+}
+
+void CClistProxyWindow::Update()
+{
+ AddButton(LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), TranslateT("Menu"), -1);
+
+ int nAccounts = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&nAccounts, &accounts);
+ for (int i = 0; i < nAccounts; ++i)
+ {
+ if (!accounts[i]->bIsEnabled || !accounts[i]->bIsVisible || !accounts[i]->ppro || !(accounts[i]->ppro->GetCaps(PFLAGNUM_1) & PF1_IM))
+ continue;
+
+ HICON hIcon = LoadSkinnedProtoIcon(accounts[i]->szModuleName, CallProtoService(accounts[i]->szModuleName, PS_GETSTATUS, 0, 0));
+ AddButton(hIcon, accounts[i]->tszAccountName, (INT_PTR)accounts[i]->tszAccountName);
+ }
+ UpdateButtons(g_pTaskbarList);
+
+ InvalidateThumbnail();
+}
+
+void CClistProxyWindow::OnActivate(HWND hwndFrom)
+{
+ CallService(MS_CLIST_SHOWHIDE, 0, 0);
+
+ HWND hwndClui = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+ if (hwndFrom != hwndClui && !IsIconic(hwndClui) && IsWindowVisible(hwndClui))
+ SetForegroundWindow(hwndClui);
+ else
+ SetForegroundWindow(NULL);
+}
+
+void CClistProxyWindow::OnToolbar(int id, INT_PTR data)
+{
+ POINT pt; GetCursorPos(&pt);
+ HMENU hMenu = NULL;
+ HWND hwndClui = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+
+ switch (data)
+ {
+ case -1:
+ {
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDMAIN, 0, 0);
+ break;
+ }
+
+ default:
+ {
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0);
+ int nItems = GetMenuItemCount(hMenu);
+ for (int i = 0; i < nItems; ++i)
+ {
+ TCHAR buf[128];
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STRING|MIIM_SUBMENU;
+ mii.dwTypeData = buf;
+ mii.cch = SIZEOF(buf);
+ GetMenuItemInfo(hMenu, i, TRUE, &mii);
+
+ if (mii.hSubMenu && !lstrcmp(mii.dwTypeData, (TCHAR*)data))
+ {
+ hMenu = mii.hSubMenu;
+ break;
+ }
+ }
+ }
+ }
+
+ SetForegroundWindow(hwndClui);
+ TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwndClui, NULL);
+}
+
+void CClistProxyWindow::OnRenderThumbnail(int width, int height)
+{
+ HBITMAP hbmp = CreateDwmBitmap(width, height);
+ HDC hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hbmp);
+
+ RGBQUAD rgb0, rgb1;
+ rgb0.rgbRed = 0; rgb0.rgbGreen = 0; rgb0.rgbBlue = 0;
+ rgb1.rgbRed = 19; rgb1.rgbGreen = 58; rgb1.rgbBlue = 89;
+ DrawGradient(hdc, 0, 0, width, height, &rgb0, &rgb1);
+
+ HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ SetTextColor(hdc, RGB(255, 255, 255));
+ SetBkMode(hdc, TRANSPARENT);
+
+ RECT rc;
+ SIZE sz;
+ SetRect(&rc, 5, 5, width-10, height-10);
+
+ int avatarWidth = 0;
+ int avatarHeight = 0;
+ if (true)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETMYAVATAR, 0, (LPARAM)"");
+ if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND))
+ {
+ if (ace->bmWidth < width / 4)
+ {
+ avatarWidth = ace->bmWidth;
+ avatarHeight = ace->bmHeight;
+ } else
+ {
+ avatarWidth = width / 4;
+ avatarHeight = avatarWidth * ace->bmHeight / ace->bmWidth;
+ }
+
+ AVATARDRAWREQUEST avdr = {0};
+ avdr.cbSize = sizeof(avdr);
+ avdr.hContact = NULL;
+ avdr.hTargetDC = hdc;
+ avdr.rcDraw = rc;
+ avdr.rcDraw.bottom = avdr.rcDraw.top + avatarHeight;
+ avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth;
+ avdr.dwFlags = AVDRQ_FALLBACKPROTO | AVDRQ_FORCEALPHA | AVDRQ_OWNPIC;
+ avdr.szProto = "";
+
+ avdr.alpha = 255;
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr);
+
+ rc.left += avatarWidth + 5;
+ }
+ }
+
+ int nAccounts = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&nAccounts, &accounts);
+ for (int i = 0; i < nAccounts; ++i)
+ {
+ if (!accounts[i]->bIsEnabled /*|| !accounts[i]->ppro || !(accounts[i]->ppro->GetCaps(PFLAGNUM_1) & PF1_IM)*/)
+ continue;
+
+ char *proto = accounts[i]->szModuleName;
+
+ if (true)
+ {
+ TCHAR name[128]; name[0] = 0;
+
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = NULL;
+ ci.szProto = proto;
+ ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci))
+ {
+ switch (ci.type)
+ {
+ case CNFT_ASCIIZ:
+ mir_sntprintf(name, SIZEOF(name), _T("%s - %s"), accounts[i]->tszAccountName, ci.pszVal);
+ mir_free((void *)ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_sntprintf(name, SIZEOF(name), _T("%s - %u"), accounts[i]->tszAccountName, ci.dVal);
+ break;
+ }
+
+ } else
+ {
+ lstrcpyn(name, accounts[i]->tszAccountName, SIZEOF(name));
+ }
+
+ RECT rcText = rc;
+ rcText.left += 20;
+ DrawText(hdc, name, -1, &rcText, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP|DT_SINGLELINE);
+ GetTextExtentPoint32(hdc, name, lstrlen(name), &sz);
+ }
+
+ if (true)
+ {
+ HICON hIcon = LoadSkinnedProtoIcon(proto, CallProtoService(proto, PS_GETSTATUS, 0, 0));
+ DrawIconEx(hdc, rc.left, rc.top + (sz.cy - 16) / 2, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ }
+
+ rc.top += sz.cy + 5;
+ }
+
+ SelectObject(hdc, hfntSave);
+
+ DeleteDC(hdc);
+ MakeBitmapOpaque(hbmp);
+ SetThumbnail(hbmp);
+ DeleteObject(hbmp);
+}
+
+void CClistProxyWindow::OnClose()
+{
+ CallService("CloseAction", NULL, NULL);
+}
+
+void CClistProxyWindow::OnTimer(int id)
+{
+ HANDLE hIcolibItem = m_overlayIconHandle;
+ for (m_activeOverlay = (m_activeOverlay + 1) % (m_overlayEvents.getCount() + 1); m_activeOverlay < m_overlayEvents.getCount(); ++m_activeOverlay)
+ if (m_overlayEvents[m_activeOverlay])
+ {
+ hIcolibItem = m_overlayEvents[m_activeOverlay].GetIcon();
+ break;
+ }
+
+ HICON hIcon = hIcolibItem ? (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)hIcolibItem) : m_overlayIcon;
+ if (hIcon) g_pTaskbarList->SetOverlayIcon(hwnd(), hIcon, L"");
+}
diff --git a/plugins/W7UI/src/clistproxywindow.h b/plugins/W7UI/src/clistproxywindow.h
new file mode 100644
index 0000000000..153c59089b
--- /dev/null
+++ b/plugins/W7UI/src/clistproxywindow.h
@@ -0,0 +1,64 @@
+#ifndef clistproxywindow_h__
+#define clistproxywindow_h__
+
+class CClistProxyWindow: public CDwmWindow
+{
+public:
+ CClistProxyWindow();
+ ~CClistProxyWindow();
+
+ void Flash();
+ void SetOverlayIcon(HICON hIcon);
+ void SetOverlayIconHandle(HANDLE hIcolibIcon);
+ void AddOverlayEvent(int idx);
+ void RemoveOverlayEvent(int idx);
+ int AllocateOverlayEvent(HANDLE hIcolibIcon);
+
+private:
+ class COverlayEventSlot
+ {
+ private:
+ HANDLE m_hIcolibItem;
+ TCHAR *m_overlayText;
+ int m_level;
+
+ public:
+ COverlayEventSlot(HANDLE hIcolibItem, TCHAR *overlayText)
+ {
+ m_hIcolibItem = hIcolibItem;
+ m_overlayText = mir_tstrdup(overlayText);
+ m_level = 0;
+ }
+ ~COverlayEventSlot() { mir_free(m_overlayText); }
+ void Push() { m_level++; }
+ void Pop() { if (m_level > 0) m_level--; }
+ operator bool() { return m_level > 0; }
+ HANDLE GetIcon() { return m_hIcolibItem; }
+ };
+
+ int m_activeOverlay;
+ HICON m_overlayIcon;
+ HANDLE m_overlayIconHandle;
+ TCHAR *m_overlayText;
+ OBJLIST<COverlayEventSlot> m_overlayEvents;
+
+ int __cdecl OnStatusModeChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnAvatarChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnModulesLoaded(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnAccListChanged(WPARAM wParam, LPARAM lParam);
+
+ HANDLE SetEventHook(char *evt, int (__cdecl CClistProxyWindow::*fn)(WPARAM, LPARAM));
+
+ void Update();
+
+protected:
+ void OnActivate(HWND hwndFrom);
+ void OnToolbar(int id, INT_PTR data);
+ void OnRenderThumbnail(int width, int height);
+ void OnClose();
+ void OnTimer(int id);
+};
+
+extern CClistProxyWindow *g_clistProxyWnd;
+
+#endif // clistproxywindow_h__
diff --git a/plugins/W7UI/src/dwmwindow.cpp b/plugins/W7UI/src/dwmwindow.cpp
new file mode 100644
index 0000000000..2d8dd6e9e4
--- /dev/null
+++ b/plugins/W7UI/src/dwmwindow.cpp
@@ -0,0 +1,209 @@
+#include "headers.h"
+
+#define WNDCLASSNAME _T("W7DwmWndClass")
+
+CDwmWindow::CDwmWindow()
+{
+ GlobalInitWndClass();
+
+ m_btnInitialized = false;
+ m_btnCount = 0;
+ for (int i = 0; i < SIZEOF(m_btnInfo); ++i)
+ {
+ m_btnInfo[i].iId = i;
+ m_btnInfo[i].dwMask = THUMBBUTTONMASK(THB_FLAGS);
+ m_btnInfo[i].dwFlags = THUMBBUTTONFLAGS(THBF_HIDDEN);
+ m_btnData[i] = 0;
+ }
+
+ m_hwnd = CreateWindowEx(WS_EX_APPWINDOW|WS_EX_NOACTIVATE, WNDCLASSNAME, NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL);
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this);
+ SetWindowPos(m_hwnd, 0, -100000, -100000, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW);
+
+ BOOL val = 1;
+ DwmSetWindowAttribute(m_hwnd, DWMWA_HAS_ICONIC_BITMAP, &val, 4);
+ DwmSetWindowAttribute(m_hwnd, DWMWA_FORCE_ICONIC_REPRESENTATION, &val, 4);
+ dwmInvalidateIconicBitmaps(m_hwnd);
+}
+
+HBITMAP CDwmWindow::CreateDwmBitmap(int width, int height)
+{
+ BITMAPINFO bi;
+ bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+ bi.bmiHeader.biWidth = width;
+ bi.bmiHeader.biHeight = -height;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ return CreateDIBSection(0, &bi, DIB_RGB_COLORS, NULL, 0, 0);
+}
+
+void CDwmWindow::MakeBitmapOpaque(HBITMAP hBmp)
+{
+ BITMAP bmp;
+ GetObject(hBmp, sizeof(bmp), &bmp);
+ if (bmp.bmBitsPixel != 32) return;
+ if (bmp.bmHeight < 0) bmp.bmHeight *= -1;
+
+ int size = bmp.bmWidth * bmp.bmHeight * 4;
+ BYTE *data = new BYTE[size];
+ GetBitmapBits(hBmp, size, data);
+ for (int i = 3; i < size; i += 4)
+ data[i] = 255;
+ SetBitmapBits(hBmp, size, data);
+ delete [] data;
+
+}
+
+void CDwmWindow::DrawGradient(HDC hdc, int x, int y, int width, int height, RGBQUAD *rgb0, RGBQUAD *rgb1)
+{
+ int oldMode = SetBkMode(hdc, OPAQUE);
+ COLORREF oldColor = SetBkColor(hdc, 0);
+
+ RECT rc; SetRect(&rc, x, 0, x+width, 0);
+ for (int i=y+height; --i >= y; ) {
+ COLORREF color = RGB(
+ ((height-i-1)*rgb0->rgbRed + i*rgb1->rgbRed) / height,
+ ((height-i-1)*rgb0->rgbGreen + i*rgb1->rgbGreen) / height,
+ ((height-i-1)*rgb0->rgbBlue + i*rgb1->rgbBlue) / height);
+ rc.top = rc.bottom = i;
+ ++rc.bottom;
+ SetBkColor(hdc, color);
+ ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rc, "", 0, 0);
+ }
+
+ SetBkMode(hdc, oldMode);
+ SetBkColor(hdc, oldColor);
+}
+
+bool CDwmWindow::AddButton(HICON hIcon, TCHAR *text, INT_PTR data, DWORD flags)
+{
+ if (m_btnCount == SIZEOF(m_btnInfo)) return false;
+ m_btnInfo[m_btnCount].dwMask = THUMBBUTTONMASK(THB_ICON|THB_TOOLTIP|THB_FLAGS);
+ m_btnInfo[m_btnCount].hIcon = hIcon;
+ lstrcpyn(m_btnInfo[m_btnCount].szTip, text, SIZEOF(m_btnInfo[m_btnCount].szTip));
+ m_btnInfo[m_btnCount].dwFlags = THUMBBUTTONFLAGS(flags);
+ m_btnData[m_btnCount] = data;
+ m_btnCount++;
+ return true;
+}
+
+void CDwmWindow::UpdateButtons(ITaskbarList3 *p)
+{
+ if (m_btnInitialized)
+ p->ThumbBarUpdateButtons(hwnd(), SIZEOF(m_btnInfo), m_btnInfo);
+ else
+ p->ThumbBarAddButtons(hwnd(), SIZEOF(m_btnInfo), m_btnInfo);
+
+ m_btnCount = 0; // reset this for next iteration
+ m_btnInitialized = true;
+}
+
+void CDwmWindow::SetTimer(int id, int timeout)
+{
+ ::SetTimer(m_hwnd, id, timeout, NULL);
+}
+
+void CDwmWindow::KillTimer(int id)
+{
+ ::KillTimer(m_hwnd, id);
+}
+
+void CDwmWindow::InvalidateThumbnail()
+{
+ dwmInvalidateIconicBitmaps(m_hwnd);
+}
+
+void CDwmWindow::SetPreview(HBITMAP hbmp, int x, int y)
+{
+ POINT pt = { x, y };
+ dwmSetIconicLivePreviewBitmap(m_hwnd, hbmp, &pt, 0);
+}
+
+void CDwmWindow::SetThumbnail(HBITMAP hbmp)
+{
+ dwmSetIconicThumbnail(m_hwnd, hbmp, 0);
+}
+
+LRESULT CDwmWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_ACTIVATE:
+ {
+ if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
+ {
+ OnActivate((HWND)wParam);
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ OnClose();
+ return FALSE;
+ }
+
+ case WM_DWMSENDICONICLIVEPREVIEWBITMAP:
+ {
+ OnRenderPreview();
+ break;
+ }
+
+ case WM_DWMSENDICONICTHUMBNAIL:
+ {
+ int width = HIWORD(lParam);
+ int height = LOWORD(lParam);
+ OnRenderThumbnail(width, height);
+ break;
+ }
+
+ case WM_TIMER:
+ {
+ OnTimer(wParam);
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == THBN_CLICKED)
+ OnToolbar(LOWORD(wParam), m_btnData[LOWORD(wParam)]);
+ break;
+ }
+ }
+
+ return DefWindowProc(m_hwnd, msg, wParam, lParam);
+}
+
+void CDwmWindow::GlobalInitWndClass()
+{
+ static bool bInitialized = false;
+ if (bInitialized) return;
+
+ WNDCLASSEX wcl = {0};
+ wcl.cbSize = sizeof(wcl);
+ wcl.lpfnWndProc = GlobalWndProc;
+ wcl.style = 0;
+ wcl.cbClsExtra = 0;
+ wcl.cbWndExtra = 0;
+ wcl.hInstance = g_hInst;
+ wcl.hIcon = NULL;
+ wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
+ wcl.lpszMenuName = NULL;
+ wcl.lpszClassName = WNDCLASSNAME;
+ wcl.hIconSm = NULL;
+ RegisterClassEx(&wcl);
+}
+
+LRESULT CALLBACK CDwmWindow::GlobalWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CDwmWindow *wnd = (CDwmWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (!wnd) return DefWindowProc(hwnd, msg, wParam, lParam);
+ if (msg == WM_DESTROY)
+ {
+ delete wnd;
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return wnd->WndProc(msg, wParam, lParam);
+} \ No newline at end of file
diff --git a/plugins/W7UI/src/dwmwindow.h b/plugins/W7UI/src/dwmwindow.h
new file mode 100644
index 0000000000..e795823247
--- /dev/null
+++ b/plugins/W7UI/src/dwmwindow.h
@@ -0,0 +1,59 @@
+#ifndef dwmwindow_h__
+#define dwmwindow_h__
+
+class CDwmWindow
+{
+public:
+ CDwmWindow();
+ virtual ~CDwmWindow() {}
+
+ HWND hwnd() { return m_hwnd; }
+
+ template<class TWindow>
+ static TWindow *GetWindow(HWND hwnd)
+ {
+ return (TWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ }
+
+protected:
+ // events
+ virtual void OnActivate(HWND hwndFrom) {}
+ virtual void OnClose() {}
+ virtual void OnRenderThumbnail(int mzxWidth, int maxHeight) {}
+ virtual void OnRenderPreview() {}
+ virtual void OnTimer(int id) {}
+ virtual void OnToolbar(int id, INT_PTR data) {}
+
+ // timer stuff
+ void SetTimer(int id, int timeout);
+ void KillTimer(int id);
+
+ // manage thumbnail and aero peek
+ void InvalidateThumbnail();
+ void SetPreview(HBITMAP hbmp, int x, int y);
+ void SetThumbnail(HBITMAP hbmp);
+
+ // manage toolbar
+ bool AddButton(HICON hIcon, TCHAR *text, INT_PTR data, DWORD flags = THBF_ENABLED);
+ void UpdateButtons(ITaskbarList3 *p);
+
+ //utilities
+ static HBITMAP CreateDwmBitmap(int width, int height);
+ static void MakeBitmapOpaque(HBITMAP hBmp);
+ static void DrawGradient(HDC hdc, int x, int y, int width, int height, RGBQUAD *rgb0, RGBQUAD *rgb1);
+
+private:
+ HWND m_hwnd;
+
+ bool m_btnInitialized;
+ int m_btnCount;
+ THUMBBUTTON m_btnInfo[7];
+ INT_PTR m_btnData[7];
+
+ LRESULT CALLBACK WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
+
+ static void GlobalInitWndClass();
+ static LRESULT CALLBACK GlobalWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+};
+
+#endif // dwmwindow_h__ \ No newline at end of file
diff --git a/plugins/W7UI/src/headers.h b/plugins/W7UI/src/headers.h
new file mode 100644
index 0000000000..7d28902466
--- /dev/null
+++ b/plugins/W7UI/src/headers.h
@@ -0,0 +1,78 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+
+#include <tchar.h>
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <stdio.h>
+
+#include <dwmapi.h>
+#include <propkey.h>
+#include <propvarutil.h>
+
+#define MIRANDA_VER 0x0A00
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_clist.h>
+#include <m_clc.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_userinfo.h>
+#include <m_history.h>
+#include <m_addcontact.h>
+#include <m_message.h>
+#include <m_file.h>
+#include <m_icolib.h>
+#include <m_idle.h>
+#include <m_awaymsg.h>
+#include <m_system_cpp.h>
+#include <m_avatars.h>
+#include <m_clistint.h>
+#include <m_protoint.h>
+#include "m_w7ui.h"
+
+#include "win7api.h"
+
+#include "jumplistarray.h"
+#include "jumplistbuilder.h"
+#include "jumplist.h"
+
+#include "subclassmgr.h"
+#include "dwmwindow.h"
+#include "clistproxywindow.h"
+#include "srmmproxywindow.h"
+
+extern HINSTANCE g_hInst;
diff --git a/plugins/W7UI/src/jumplist.cpp b/plugins/W7UI/src/jumplist.cpp
new file mode 100644
index 0000000000..4fd1a68e9d
--- /dev/null
+++ b/plugins/W7UI/src/jumplist.cpp
@@ -0,0 +1,123 @@
+#include "headers.h"
+
+static HANDLE hProcessJumpList = 0;
+
+static void ProcessJumpListImpl(char *arg)
+{
+ char *prefix = mir_strdup(arg);
+ char *argument = strchr(prefix, ':');
+ if (argument) *argument++ = 0;
+ NotifyEventHooks(hProcessJumpList, (WPARAM)prefix, (LPARAM)argument);
+ mir_free(prefix);
+}
+
+static LRESULT CALLBACK MirandaJumpListProcessorWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_COPYDATA:
+ {
+ COPYDATASTRUCT *data = (COPYDATASTRUCT *)lParam;
+ ProcessJumpListImpl((char *)data->lpData);
+ break;
+ }
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+extern "C" __declspec(dllexport) void ProcessJumpList(HWND, HINSTANCE, LPSTR arg, UINT)
+{
+ char miranda_path[MAX_PATH];
+ GetModuleFileNameA(g_hInst, miranda_path, SIZEOF(miranda_path));
+ lstrcpyA(strstr(_strlwr(miranda_path), "plugins\\w7ui.dll"), "miranda32.exe");
+
+ if (HWND hwnd = FindWindowA("MirandaJumpListProcessor", miranda_path))
+ {
+ COPYDATASTRUCT data = {0};
+ data.dwData = 0;
+ data.cbData = lstrlenA(arg) + 1;
+ data.lpData = arg;
+ SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data);
+ } else
+ {
+ char command[MAX_PATH * 2];
+ wsprintfA(command, "\"%s\" -jump %s", miranda_path, arg);
+ WinExec(command, SW_SHOWNORMAL);
+ }
+}
+
+static int OnJumpListItems(WPARAM, LPARAM lParam)
+{
+ WCHAR *category = (WCHAR *)lParam;
+
+ if (!category)
+ {
+ MJumpList_AddItem(SKINICON_STATUS_ONLINE, TranslateT("Online"), L"status", L"online");
+ MJumpList_AddItem(SKINICON_STATUS_DND, TranslateT("Do not disturb"), L"status", L"dnd");
+ MJumpList_AddItem(SKINICON_STATUS_INVISIBLE, TranslateT("Invisible"), L"status", L"invisible");
+ MJumpList_AddItem(SKINICON_STATUS_OFFLINE, TranslateT("Offline"), L"status", L"offline");
+ return 0;
+ }
+
+ return 0;
+}
+
+static int OnJumpListProcess(WPARAM wParam, LPARAM lParam)
+{
+ char *prefix = (char *)wParam;
+ char *argument = (char *)lParam;
+
+ if (!lstrcmpA(prefix, "status"))
+ {
+ if (!lstrcmpA(argument, "online"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_ONLINE, 0);
+ } else
+ if (!lstrcmpA(argument, "dnd"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_DND, 0);
+ } else
+ if (!lstrcmpA(argument, "invisible"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_INVISIBLE, 0);
+ } else
+ if (!lstrcmpA(argument, "offline"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_OFFLINE, 0);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+void LoadJumpList()
+{
+ hProcessJumpList = CreateHookableEvent(ME_JUMPLIST_PROCESS);
+}
+
+void InitJumpList()
+{
+ HookEvent(ME_JUMPLIST_BUILDITEMS, OnJumpListItems);
+ HookEvent(ME_JUMPLIST_PROCESS, OnJumpListProcess);
+
+ if (char *cmd = strstr(GetCommandLineA(), " -jump "))
+ ProcessJumpListImpl(cmd + 7);
+
+ WNDCLASSEX wcx = {0};
+ wcx.cbSize = sizeof(wcx);
+ wcx.lpfnWndProc = MirandaJumpListProcessorWndProc;
+ wcx.hInstance = g_hInst;
+ wcx.lpszClassName = _T("MirandaJumpListProcessor");
+ RegisterClassEx(&wcx);
+
+ char miranda_path[MAX_PATH];
+ GetModuleFileNameA(g_hInst, miranda_path, SIZEOF(miranda_path));
+ lstrcpyA(strstr(_strlwr(miranda_path), "plugins\\w7ui.dll"), "miranda32.exe");
+
+ HWND hwnd = CreateWindowA("MirandaJumpListProcessor", miranda_path, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL);
+ ShowWindow(hwnd, SW_HIDE);
+
+ CJumpListBuilder::Rebuild();
+}
diff --git a/plugins/W7UI/src/jumplist.h b/plugins/W7UI/src/jumplist.h
new file mode 100644
index 0000000000..de5a6f0548
--- /dev/null
+++ b/plugins/W7UI/src/jumplist.h
@@ -0,0 +1,7 @@
+#ifndef jumplist_h__
+#define jumplist_h__
+
+void LoadJumpList();
+void InitJumpList();
+
+#endif // jumplist_h__
diff --git a/plugins/W7UI/src/jumplistarray.cpp b/plugins/W7UI/src/jumplistarray.cpp
new file mode 100644
index 0000000000..669a7784ef
--- /dev/null
+++ b/plugins/W7UI/src/jumplistarray.cpp
@@ -0,0 +1,214 @@
+#include "headers.h"
+
+#pragma pack(push, 1)
+typedef struct
+{
+ BYTE bWidth; // Width, in pixels, of the image
+ BYTE bHeight; // Height, in pixels, of the image
+ BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
+ BYTE bReserved; // Reserved ( must be 0)
+ WORD wPlanes; // Color Planes
+ WORD wBitCount; // Bits per pixel
+ DWORD dwBytesInRes; // How many bytes in this resource?
+ DWORD dwImageOffset; // Where in the file is this image?
+} ICONDIRENTRY, *LPICONDIRENTRY;
+
+typedef struct
+{
+ WORD idReserved; // Reserved (must be 0)
+ WORD idType; // Resource Type (1 for icons)
+ WORD idCount; // How many images?
+ ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
+} ICONDIR, *LPICONDIR;
+#pragma pack(pop)
+
+static void SaveIconToFile(HICON hIcon, TCHAR *szFile)
+{
+ ICONINFO iconInfo = {0};
+ BITMAP bmpColor, bmpMask;
+ HANDLE hFile = 0;
+ HANDLE hMap = 0;
+ BYTE *pFile = 0;
+
+ GetIconInfo(hIcon, &iconInfo);
+ GetObject(iconInfo.hbmColor, sizeof(bmpColor), &bmpColor);
+ GetObject(iconInfo.hbmMask, sizeof(bmpMask), &bmpMask);
+
+ do
+ {
+ if (bmpColor.bmBitsPixel <= 8) break;
+
+ DWORD dwColorSize = bmpColor.bmWidthBytes * bmpColor.bmHeight;
+ DWORD dwMaskSize = bmpMask.bmWidthBytes * bmpMask.bmHeight;
+ DWORD dwFileSize = sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + dwColorSize + dwMaskSize;
+
+ hFile = CreateFile(szFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) break;
+ hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize, NULL);
+ if (!hMap) break;
+ pFile = (BYTE *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0 ,0);
+ if (!pFile) break;
+
+ ICONDIR iconDir = {0};
+ iconDir.idCount = 1;
+ iconDir.idType = 1;
+ iconDir.idEntries[0].bWidth = bmpColor.bmWidth;
+ iconDir.idEntries[0].bHeight = bmpColor.bmHeight;
+ iconDir.idEntries[0].bColorCount = 0;
+ iconDir.idEntries[0].wPlanes = bmpColor.bmPlanes;
+ iconDir.idEntries[0].wBitCount = bmpColor.bmBitsPixel;
+ iconDir.idEntries[0].dwBytesInRes = sizeof(BITMAPINFOHEADER) + dwColorSize + dwMaskSize;
+ iconDir.idEntries[0].dwImageOffset = sizeof(ICONDIR);
+ MoveMemory(pFile, &iconDir, sizeof(ICONDIR));
+
+ BITMAPINFOHEADER iconBmp = {0};
+ iconBmp.biSize = sizeof(iconBmp);
+ iconBmp.biWidth = bmpColor.bmWidth;
+ iconBmp.biHeight = bmpColor.bmHeight + bmpMask.bmHeight;
+ iconBmp.biPlanes = bmpColor.bmPlanes;
+ iconBmp.biBitCount = bmpColor.bmBitsPixel;
+ iconBmp.biSizeImage = dwColorSize + dwMaskSize;
+ MoveMemory(pFile + sizeof(ICONDIR), &iconBmp, sizeof(BITMAPINFOHEADER));
+
+ BYTE *buf = (BYTE *)mir_alloc(dwColorSize);
+ GetBitmapBits(iconInfo.hbmColor, dwColorSize, buf);
+ for (int row = 0; row < bmpColor.bmHeight; ++row)
+ {
+ MoveMemory(
+ pFile + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + row * bmpColor.bmWidthBytes,
+ buf + (bmpColor.bmHeight - row - 1) * bmpColor.bmWidthBytes,
+ bmpColor.bmWidthBytes);
+ }
+ mir_free(buf);
+
+ GetBitmapBits(iconInfo.hbmMask, dwMaskSize, pFile + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + dwColorSize);
+ } while(0);
+
+ DeleteObject(iconInfo.hbmColor);
+ DeleteObject(iconInfo.hbmMask);
+
+ if (pFile) UnmapViewOfFile(pFile);
+ if (hMap) CloseHandle(hMap);
+ if (hFile && hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
+}
+
+CJumpListArray::CJumpListArray()
+{
+ CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, IID_IObjectCollection, (void **)&m_pObjects);
+}
+
+CJumpListArray::~CJumpListArray()
+{
+ if (m_pObjects) m_pObjects->Release();
+}
+
+void CJumpListArray::AddItemImpl(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ IShellLink *link = NewShellLink(icon, iIcon, title, path, args);
+ m_pObjects->AddObject(link);
+ link->Release();
+}
+
+void CJumpListArray::AddItem(char *mir_icon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ TCHAR icon[MAX_PATH]; int iIcon;
+ LoadMirandaIcon(mir_icon, icon, &iIcon);
+ AddItemImpl(icon, iIcon, title, path, args);
+}
+
+void CJumpListArray::AddItem(int skinicon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ TCHAR icon[MAX_PATH]; int iIcon;
+ LoadMirandaIcon(skinicon, icon, &iIcon);
+ AddItemImpl(icon, iIcon, title, path, args);
+}
+
+void CJumpListArray::AddItem(char *proto, int status, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ TCHAR icon[MAX_PATH]; int iIcon;
+ LoadMirandaIcon(proto, status, icon, &iIcon);
+ AddItemImpl(icon, iIcon, title, path, args);
+}
+
+IObjectArray *CJumpListArray::GetArray()
+{
+ IObjectArray *result = NULL;
+ m_pObjects->QueryInterface(IID_IObjectArray, (void **)&result);
+ return result;
+}
+
+bool CJumpListArray::LoadMirandaIcon(char *mir_icon, TCHAR *icon, int *id)
+{
+ *id = 0;
+
+ TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path);
+
+ TCHAR *name = mir_a2t(mir_icon);
+ for (TCHAR *ch = name; *ch; ++ch) if (_tcschr(_T("\\/:*?<>|"), *ch)) *ch = _T('_');
+ mir_sntprintf(icon, MAX_PATH, _T("%s\\%s.ico"), path, name);
+
+ mir_free(name);
+ mir_free(path);
+
+ HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)mir_icon);
+ SaveIconToFile(hIcon, icon);
+
+ return true;
+}
+
+bool CJumpListArray::LoadMirandaIcon(int skinicon, TCHAR *icon, int *id)
+{
+ *id = 0;
+
+ TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path);
+ mir_sntprintf(icon, MAX_PATH, _T("%s\\skinicon$%d.ico"), path, skinicon);
+ mir_free(path);
+
+ HICON hIcon = LoadSkinnedIcon(skinicon);
+ SaveIconToFile(hIcon, icon);
+
+ return true;
+}
+
+bool CJumpListArray::LoadMirandaIcon(char *proto, int status, TCHAR *icon, int *id)
+{
+ *id = 0;
+
+ TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path);
+ mir_sntprintf(icon, MAX_PATH, _T("%s\\skinprotoicon$") _T(TCHAR_STR_PARAM) _T("$%d.ico"), path, proto, status);
+ mir_free(path);
+
+ HICON hIcon = LoadSkinnedProtoIcon(proto, status);
+ SaveIconToFile(hIcon, icon);
+
+ return true;
+}
+
+IShellLink *CJumpListArray::NewShellLink(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ IShellLink *pShellLink = NULL;
+ CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
+
+ pShellLink->SetPath(path);
+ pShellLink->SetIconLocation(icon, iIcon);
+ pShellLink->SetArguments(args);
+ pShellLink->SetShowCmd(SW_SHOWDEFAULT);
+
+ IPropertyStore *pPropStore = NULL;
+ if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPropStore)))
+ {
+ PROPVARIANT pv;
+
+ InitPropVariantFromString(title, &pv);
+ pPropStore->SetValue(PKEY_Title, pv);
+ PropVariantClear(&pv);
+
+ pPropStore->Commit();
+ pPropStore->Release();
+ }
+
+ return pShellLink;
+} \ No newline at end of file
diff --git a/plugins/W7UI/src/jumplistarray.h b/plugins/W7UI/src/jumplistarray.h
new file mode 100644
index 0000000000..c9f2a8b979
--- /dev/null
+++ b/plugins/W7UI/src/jumplistarray.h
@@ -0,0 +1,29 @@
+#ifndef jumplistarray_h__
+#define jumplistarray_h__
+
+class CJumpListArray
+{
+private:
+ IObjectCollection *m_pObjects;
+
+public:
+ CJumpListArray();
+ ~CJumpListArray();
+
+ void AddItem(char *mir_icon, TCHAR *title, TCHAR *path, TCHAR *args);
+ void AddItem(int skinicon, TCHAR *title, TCHAR *path, TCHAR *args);
+ void AddItem(char *proto, int skinicon, TCHAR *title, TCHAR *path, TCHAR *args);
+
+ IObjectArray *GetArray();
+
+private:
+ void AddItemImpl(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args);
+
+ bool LoadMirandaIcon(char *mir_icon, TCHAR *icon, int *id);
+ bool LoadMirandaIcon(int skinicon, TCHAR *icon, int *id);
+ bool LoadMirandaIcon(char *proto, int status, TCHAR *icon, int *id);
+
+ static IShellLink *NewShellLink(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args);
+};
+
+#endif // jumplistarray_h__
diff --git a/plugins/W7UI/src/jumplistbuilder.cpp b/plugins/W7UI/src/jumplistbuilder.cpp
new file mode 100644
index 0000000000..5e5f1d9f65
--- /dev/null
+++ b/plugins/W7UI/src/jumplistbuilder.cpp
@@ -0,0 +1,127 @@
+#include "headers.h"
+
+CJumpListBuilder *CJumpListBuilder::m_instance = 0;
+
+CJumpListBuilder::CJumpListBuilder()
+{
+ m_hBuildCategories = CreateHookableEvent(ME_JUMPLIST_BUILDCATEGORIES);
+ m_hBuildItems = CreateHookableEvent(ME_JUMPLIST_BUILDITEMS);
+ CreateSvc(MS_JUMPLIST_REBUILD, &CJumpListBuilder::Rebuild);
+ CreateSvc(MS_JUMPLIST_ADDCATEGORY, &CJumpListBuilder::AddCategory);
+ CreateSvc(MS_JUMPLIST_ADDITEM, &CJumpListBuilder::AddItem);
+}
+
+CJumpListBuilder::~CJumpListBuilder()
+{
+ KillObjectServices(this);
+ DestroyHookableEvent(m_hBuildCategories);
+ DestroyHookableEvent(m_hBuildItems);
+}
+
+void CJumpListBuilder::BuildJumpList()
+{
+ m_lists = new LIST<TCHAR>(5, _tcscmp);
+ NotifyEventHooks(m_hBuildCategories, 0, 0);
+
+ UINT maxSlots;
+ IObjectArray *pRemoved;
+ CoCreateInstance(CLSID_CustomDestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void **)&m_pList);
+ m_pList->BeginList(&maxSlots, IID_IObjectArray, (void **)&pRemoved);
+ BuildCategory(NULL);
+ for (int i = 0; i < m_lists->getCount(); ++i)
+ BuildCategory((*m_lists)[i]);
+ m_pList->CommitList();
+ m_pList->Release();
+ pRemoved->Release();
+
+ m_lists->destroy();
+ delete m_lists;
+}
+
+int __cdecl CJumpListBuilder::Rebuild(WPARAM wParam, LPARAM lParam)
+{
+ BuildJumpList();
+ return 0;
+}
+
+int __cdecl CJumpListBuilder::AddCategory(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *category = (TCHAR *)lParam;
+ if (!m_lists->find(category)) m_lists->insert(mir_wstrdup(category));
+ return 0;
+}
+
+int __cdecl CJumpListBuilder::AddItem(WPARAM wParam, LPARAM lParam)
+{
+ MIRANDAJUMPLISTITEM *item = (MIRANDAJUMPLISTITEM *)lParam;
+ switch (item->iconSource)
+ {
+ case MIS_ICOLIB:
+ m_pCurrentList->AddItem(item->iconName, item->szTitle, _T("rundll32.exe"), BuildJumpListCommand(item->szPrefix, item->szArgument));
+ break;
+ case MIS_GENERAL:
+ m_pCurrentList->AddItem(item->iconIdx, item->szTitle, _T("rundll32.exe"), BuildJumpListCommand(item->szPrefix, item->szArgument));
+ break;
+ case MIS_PROTOCOL:
+ m_pCurrentList->AddItem(item->iconName, item->iconIdx, item->szTitle, _T("rundll32.exe"), BuildJumpListCommand(item->szPrefix, item->szArgument));
+ break;
+ }
+ return 0;
+}
+
+void CJumpListBuilder::BuildCategory(TCHAR *category)
+{
+ m_pCurrentList = new CJumpListArray;
+ NotifyEventHooks(m_hBuildItems, 0, (LPARAM)category);
+
+ if (category)
+ m_pList->AppendCategory(category, m_pCurrentList->GetArray());
+ else
+ m_pList->AddUserTasks(m_pCurrentList->GetArray());
+ delete m_pCurrentList;
+
+}
+
+TCHAR *CJumpListBuilder::BuildJumpListCommand(TCHAR *prefix, TCHAR *argument)
+{
+ TCHAR path[MAX_PATH];
+ GetModuleFileName(g_hInst, path, SIZEOF(path));
+ mir_sntprintf(m_cmdBuf, SIZEOF(m_cmdBuf), _T("\"%s\",ProcessJumpList %s:%s"), path, prefix, argument);
+ return m_cmdBuf;
+}
+
+HANDLE CJumpListBuilder::CreateSvc(char *svc, int (__cdecl CJumpListBuilder::*fn)(WPARAM, LPARAM))
+{
+ return CreateServiceFunctionObj(svc, *(MIRANDASERVICEOBJ *)&fn, this);
+}
+
+/*
+static TCHAR *BuildJumpListCommand(TCHAR *buf, int size, TCHAR *arg);
+
+static void SetupTasks()
+{
+ TCHAR buf[MAX_PATH * 2];
+
+ CJumpListArray tasks;
+ tasks.AddItem(SKINICON_STATUS_ONLINE, TranslateT("Online"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:online")));
+ tasks.AddItem(SKINICON_STATUS_DND, TranslateT("Do not disturb"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:dnd")));
+ tasks.AddItem(SKINICON_STATUS_INVISIBLE, TranslateT("Invisible"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:invisible")));
+ tasks.AddItem(SKINICON_STATUS_OFFLINE, TranslateT("Offline"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:offline")));
+
+// CJumpListArray contacts;
+// contacts.AddItem("core_status_*0", TranslateT("Nickname"), L"taskhost.exe", L"profile.dat -contact:hcontact");
+
+ UINT maxSlots;
+ IObjectArray *pRemoved;
+
+ ICustomDestinationList *pList;
+ CoCreateInstance(CLSID_CustomDestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void **)&pList);
+ pList->BeginList(&maxSlots, IID_IObjectArray, (void **)&pRemoved);
+ pList->AddUserTasks(tasks.GetArray());
+// pList->AppendCategory(L"Contacts", contacts.GetArray());
+ pList->CommitList();
+ pList->Release();
+
+ pRemoved->Release();
+}
+*/ \ No newline at end of file
diff --git a/plugins/W7UI/src/jumplistbuilder.h b/plugins/W7UI/src/jumplistbuilder.h
new file mode 100644
index 0000000000..6a0bde2fd4
--- /dev/null
+++ b/plugins/W7UI/src/jumplistbuilder.h
@@ -0,0 +1,47 @@
+#ifndef jumplistbuilder_h__
+#define jumplistbuilder_h__
+
+class CJumpListBuilder
+{
+public:
+ static void Load(void)
+ {
+ m_instance = new CJumpListBuilder;
+ }
+
+ static void Unload()
+ {
+ delete m_instance;
+ }
+
+ static void Rebuild()
+ {
+ m_instance->BuildJumpList();
+ }
+
+private:
+ static CJumpListBuilder *m_instance;
+
+ LIST<TCHAR> *m_lists;
+ ICustomDestinationList *m_pList;
+ CJumpListArray *m_pCurrentList;
+ TCHAR m_cmdBuf[MAX_PATH * 2];
+
+ HANDLE m_hBuildCategories;
+ HANDLE m_hBuildItems;
+
+ CJumpListBuilder();
+ ~CJumpListBuilder();
+ void BuildJumpList();
+
+ int __cdecl Rebuild(WPARAM wParam, LPARAM lParam);
+ int __cdecl AddCategory(WPARAM wParam, LPARAM lParam);
+ int __cdecl AddItem(WPARAM wParam, LPARAM lParam);
+
+ void BuildCategory(TCHAR *category);
+
+ TCHAR *BuildJumpListCommand(TCHAR *prefix, TCHAR *argument);
+ HANDLE CreateSvc(char *svc, int (__cdecl CJumpListBuilder::*fn)(WPARAM, LPARAM));
+};
+
+#endif // jumplistbuilder_h__
diff --git a/plugins/W7UI/src/main.cpp b/plugins/W7UI/src/main.cpp
new file mode 100644
index 0000000000..d9c6898338
--- /dev/null
+++ b/plugins/W7UI/src/main.cpp
@@ -0,0 +1,79 @@
+/*
+Miranda core extensions
+
+Copyright 2000-2007 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "headers.h"
+#include <win2k.h>
+
+int LoadW7UI();
+int UnloadW7UI();
+
+HINSTANCE g_hInst;
+int hLangpack;
+
+// {3625ACB8-794C-4727-88EA-76DBBAC6D200}
+#define MIID_W7UI { 0x3625acb8, 0x794c, 0x4727, { 0x88, 0xea, 0x76, 0xdb, 0xba, 0xc6, 0xd2, 0x0 } }
+
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Windows 7 UI",
+ PLUGIN_MAKE_VERSION(0, 0, 0, 1),
+ "Provides support for Windows 7 Taskbar feautures such as Aero Peek, Overlay icons, Jump Lists, Progress Bar",
+ "nullbie, persei",
+ "nullbie@miranda.im",
+ "2009 Victor Pavlychko, Vitaliy Igonin",
+ "http://nullbie.miranda.im",
+ UNICODE_AWARE, // replace internal version (if any)
+ // {D38EEB0B-B8EE-4177-B9E5-91EBE101E054}
+ { 0xd38eeb0b, 0xb8ee, 0x4177, { 0xb9, 0xe5, 0x91, 0xeb, 0xe1, 0x1, 0xe0, 0x54 } }
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_W7UI, MIID_LAST };
+
+extern "C" __declspec(dllexport) int Load(void)
+{
+ if (!IsWinVer7Plus()) return 1;
+
+
+ mir_getLP(&pluginInfo);
+
+ LoadW7UI();
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ UnloadW7UI();
+ return 0;
+}
diff --git a/plugins/W7UI/src/srmmproxywindow.cpp b/plugins/W7UI/src/srmmproxywindow.cpp
new file mode 100644
index 0000000000..a70ca1b672
--- /dev/null
+++ b/plugins/W7UI/src/srmmproxywindow.cpp
@@ -0,0 +1,374 @@
+#include "headers.h"
+
+extern int g_eventSlotMessage;
+extern ITaskbarList3 *g_pTaskbarList;
+
+///////////////////////////////////////////////////////////////////////////////
+// srmm processing
+
+CSrmmProxyWindow::CSrmmProxyWindow(HANDLE hContact, HWND hwndWindow, HWND hwndParent)
+{
+ m_hContact = hContact;
+ m_hwndWindow = hwndWindow;
+ m_hwndParent = hwndParent;
+
+ m_hbmpPreview = NULL;
+ m_refreshPreview = true;
+
+ m_bActive = false;
+ m_bUnread = false;
+ m_bTyping = false;
+
+ UpdateIcon();
+ SetWindowText(hwnd(), (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)m_hContact, GCDNF_TCHAR));
+ SetTimer(1, 1000);
+
+ SetEventHook(ME_DB_EVENT_ADDED, &CSrmmProxyWindow::OnDbEventAdded);
+ SetEventHook(ME_DB_CONTACT_SETTINGCHANGED, &CSrmmProxyWindow::OnDbSettingChanged);
+ SetEventHook(ME_AV_AVATARCHANGED, &CSrmmProxyWindow::OnAvatarChanged);
+ SetEventHook(ME_PROTO_CONTACTISTYPING, &CSrmmProxyWindow::OnContactTyping);
+
+ AddButton(LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS), TranslateT("User Details"), 1, THBF_DISMISSONCLICK);
+ AddButton(LoadSkinnedIcon(SKINICON_OTHER_HISTORY), TranslateT("History"), 2, THBF_DISMISSONCLICK);
+ AddButton(LoadSkinnedIcon(SKINICON_EVENT_FILE), TranslateT("File"), 3, THBF_DISMISSONCLICK);
+ UpdateButtons(g_pTaskbarList);
+}
+
+CSrmmProxyWindow::~CSrmmProxyWindow()
+{
+ DeleteObject(m_hbmpPreview);
+ KillObjectEventHooks(this);
+}
+
+
+void CSrmmProxyWindow::Refresh()
+{
+ InvalidateThumbnail();
+ m_refreshPreview = true;
+}
+
+int __cdecl CSrmmProxyWindow::OnDbEventAdded(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ {
+ Refresh();
+
+ if (!m_bUnread && !IsActive())
+ {
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ if (!CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&dbei))
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & (DBEF_READ|DBEF_SENT)))
+ {
+ g_clistProxyWnd->Flash();
+ g_clistProxyWnd->AddOverlayEvent(g_eventSlotMessage);
+ m_bUnread = true;
+ UpdateIcon();
+ }
+ }
+ }
+ return 0;
+}
+
+int __cdecl CSrmmProxyWindow::OnDbSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ {
+ UpdateIcon();
+ Refresh();
+ }
+ return 0;
+}
+
+int __cdecl CSrmmProxyWindow::OnAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ Refresh();
+ return 0;
+}
+
+int __cdecl CSrmmProxyWindow::OnContactTyping(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ {
+ m_bTyping = lParam ? true : false;
+ UpdateIcon();
+ }
+ return 0;
+}
+
+HANDLE CSrmmProxyWindow::SetEventHook(char *evt, int (__cdecl CSrmmProxyWindow::*fn)(WPARAM, LPARAM))
+{
+ return HookEventObj(evt, *(MIRANDAHOOKOBJ *)&fn, this);
+}
+
+void CSrmmProxyWindow::OnTabActive()
+{
+ m_bActive = true;
+ if (m_bUnread)
+ {
+ g_clistProxyWnd->RemoveOverlayEvent(g_eventSlotMessage);
+ m_bUnread = false;
+ UpdateIcon();
+ }
+}
+
+void CSrmmProxyWindow::OnTabInactive()
+{
+ m_bActive = false;
+}
+
+bool CSrmmProxyWindow::IsActive()
+{
+ for (HWND hwnd = GetFocus(); hwnd; hwnd = GetParent(hwnd))
+ if (hwnd == m_hwndWindow)
+ return m_bActive = true;
+ return m_bActive = false;
+}
+
+void CSrmmProxyWindow::UpdateIcon()
+{
+ HICON hIcon;
+ if (m_bTyping)
+ {
+ hIcon = LoadSkinnedIcon(SKINICON_OTHER_TYPING);
+ } else
+ if (m_bUnread)
+ {
+ hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ } else
+ {
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)m_hContact, 0);
+ if (!szProto) return;
+ int iStatus = DBGetContactSettingWord(m_hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ hIcon = (HICON)LoadSkinnedProtoIcon(szProto, iStatus);
+ }
+
+ SendMessage(hwnd(), WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+ SendMessage(hwnd(), WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
+}
+
+void CSrmmProxyWindow::OnActivate(HWND hwndFrom)
+{
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)m_hContact, 0);
+}
+
+void CSrmmProxyWindow::OnToolbar(int id, INT_PTR data)
+{
+ POINT pt; GetCursorPos(&pt);
+ HMENU hMenu = NULL;
+ HWND hwndClui = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+
+ switch (data)
+ {
+ case 1:
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)m_hContact, 0);
+ break;
+
+ case 2:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)m_hContact, 0);
+ break;
+
+ case 3:
+ CallService(MS_FILE_SENDFILE, (WPARAM)m_hContact, 0);
+ break;
+ }
+}
+
+void CSrmmProxyWindow::OnRenderThumbnail(int width, int height)
+{
+ HBITMAP hbmp = CreateDwmBitmap(width, height);
+ HDC hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hbmp);
+
+ RGBQUAD rgb0, rgb1;
+ rgb0.rgbRed = 0; rgb0.rgbGreen = 0; rgb0.rgbBlue = 0;
+ rgb1.rgbRed = 19; rgb1.rgbGreen = 58; rgb1.rgbBlue = 89;
+ DrawGradient(hdc, 0, 0, width, height, &rgb0, &rgb1);
+
+ HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ SetTextColor(hdc, RGB(255, 255, 255));
+ SetBkMode(hdc, TRANSPARENT);
+
+ RECT rc;
+ SIZE sz;
+ SetRect(&rc, 5, 5, width-10, height-10);
+
+ int avatarWidth = 0;
+ int avatarHeight = 0;
+ if (true)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)m_hContact, 0);
+ if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND))
+ {
+ if (ace->bmWidth < width / 4)
+ {
+ avatarWidth = ace->bmWidth;
+ avatarHeight = ace->bmHeight;
+ } else
+ {
+ avatarWidth = width / 4;
+ avatarHeight = avatarWidth * ace->bmHeight / ace->bmWidth;
+ }
+
+ AVATARDRAWREQUEST avdr = {0};
+ avdr.cbSize = sizeof(avdr);
+ avdr.hContact = m_hContact;
+ avdr.hTargetDC = hdc;
+ avdr.rcDraw = rc;
+ avdr.rcDraw.bottom = avdr.rcDraw.top + avatarHeight;
+ avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth;
+ avdr.dwFlags = AVDRQ_FALLBACKPROTO | AVDRQ_FORCEALPHA;
+
+ avdr.alpha = 255;
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr);
+
+ rc.left += avatarWidth + 5;
+ }
+ }
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)m_hContact, 0);
+
+ if (true)
+ {
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = m_hContact;
+ ci.szProto = proto;
+ ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci))
+ {
+ TCHAR name[128]; name[0] = 0;
+ switch (ci.type)
+ {
+ case CNFT_ASCIIZ:
+ mir_sntprintf(name, SIZEOF(name), _T("%s"), ci.pszVal);
+ mir_free((void *)ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_sntprintf(name, SIZEOF(name), _T("%u"), ci.dVal);
+ break;
+ }
+
+ TextOut(hdc, rc.left + 20, rc.top, name, lstrlen(name));
+ GetTextExtentPoint32(hdc, name, lstrlen(name), &sz);
+ }
+ }
+
+ if (true)
+ {
+ HIMAGELIST hIml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+ int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM)m_hContact, 0);
+ ImageList_Draw(hIml, iIcon, hdc, rc.left, rc.top + (sz.cy - 16) / 2, ILD_TRANSPARENT);
+ }
+
+ rc.top += sz.cy + 5;
+
+ rc.left += 10;
+
+ struct
+ {
+ TCHAR *text;
+ bool out;
+ } msgs[10] = {0};
+
+ if (true)
+ {
+ int hMsgs = 0;
+ int n = 0;
+ HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)m_hContact, 0);
+ while (hEvent)
+ {
+ BYTE buf[1024];
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = sizeof(buf);
+ dbei.pBlob = buf;
+ if (!CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei))
+ {
+ if (dbei.eventType == EVENTTYPE_MESSAGE)
+ {
+ msgs[n].text = DbGetEventTextT(&dbei, CP_ACP);
+ msgs[n].out = dbei.flags & DBEF_SENT ? true : false;
+
+ RECT rcCopy = rc;
+ hMsgs += DrawText(hdc, msgs[n].text, -1, &rcCopy, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP|DT_CALCRECT);
+ if (n && hMsgs > rc.bottom - rc.top)
+ {
+ mir_free(msgs[n].text);
+ msgs[n].text = 0;
+ break;
+ }
+
+ hMsgs += 3;
+
+ if (++n >= SIZEOF(msgs)) break;
+ }
+ }
+ hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hEvent, 0);
+ }
+ }
+
+ if (true)
+ {
+ for (int i = SIZEOF(msgs); i--; )
+ {
+ if (!msgs[i].text) continue;
+
+ TCHAR szDir[] = { (msgs[i].out ? (WCHAR)0xbb : (WCHAR)0xab), 0 };
+ rc.left -= 10;
+ DrawText(hdc, szDir, -1, &rc, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP);
+ rc.left += 10;
+
+ rc.top += 3 + DrawText(hdc, msgs[i].text, -1, &rc, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP);
+ mir_free(msgs[i].text);
+ }
+ }
+
+ SelectObject(hdc, hfntSave);
+
+ DeleteDC(hdc);
+ MakeBitmapOpaque(hbmp);
+ SetThumbnail(hbmp);
+ DeleteObject(hbmp);
+}
+
+void CSrmmProxyWindow::OnRenderPreview()
+{
+ if (!m_hbmpPreview) return;
+
+ RECT rc;
+ GetWindowRect(m_hwndWindow, &rc);
+ MapWindowPoints(NULL, m_hwndParent, (POINT *)&rc, 2);
+ SetPreview(m_hbmpPreview, rc.left, rc.top);
+}
+
+void CSrmmProxyWindow::OnTimer(int)
+{
+ g_pTaskbarList->UnregisterTab(m_hwndParent);
+
+ if (!m_refreshPreview) return;
+ if (!IsWindowVisible(m_hwndWindow) || !IsWindowVisible(m_hwndParent) || IsIconic(m_hwndParent)) return;
+ if (m_hbmpPreview) DeleteObject(m_hbmpPreview);
+
+ m_refreshPreview = false;
+
+ RECT rc;
+ GetWindowRect(m_hwndWindow, &rc);
+
+ m_hbmpPreview = CreateDwmBitmap(rc.right - rc.left, rc.bottom - rc.top);
+ HDC hdc = CreateCompatibleDC(0);
+ HBITMAP hbmpSave = (HBITMAP)SelectObject(hdc, m_hbmpPreview);
+ PrintWindow(m_hwndWindow, hdc, PW_CLIENTONLY);
+ SelectObject(hdc, hbmpSave);
+ DeleteDC(hdc);
+
+ MakeBitmapOpaque(m_hbmpPreview);
+
+ InvalidateThumbnail();
+}
+
+void CSrmmProxyWindow::OnClose()
+{
+ SendMessage(m_hwndWindow, WM_CLOSE, 1, 0);
+} \ No newline at end of file
diff --git a/plugins/W7UI/src/srmmproxywindow.h b/plugins/W7UI/src/srmmproxywindow.h
new file mode 100644
index 0000000000..f1c447d4e8
--- /dev/null
+++ b/plugins/W7UI/src/srmmproxywindow.h
@@ -0,0 +1,42 @@
+#ifndef srmmproxywindow_h__
+#define srmmproxywindow_h__
+
+class CSrmmProxyWindow: public CDwmWindow
+{
+public:
+ CSrmmProxyWindow(HANDLE hContact, HWND hwndWindow, HWND hwndParent);
+ ~CSrmmProxyWindow();
+
+ void OnTabActive();
+ void OnTabInactive();
+
+private:
+ HANDLE m_hContact;
+ HWND m_hwndWindow, m_hwndParent;
+ HBITMAP m_hbmpPreview;
+ bool m_refreshPreview;
+ bool m_bActive, m_bUnread, m_bTyping;
+
+ void Refresh();
+
+ int __cdecl OnDbEventAdded(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnDbSettingChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnAvatarChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnContactTyping(WPARAM wParam, LPARAM lParam);
+
+ HANDLE SetEventHook(char *evt, int (__cdecl CSrmmProxyWindow::*fn)(WPARAM, LPARAM));
+
+ void UpdateIcon();
+
+ bool IsActive();
+
+protected:
+ void OnActivate(HWND hwndFrom);
+ void OnToolbar(int id, INT_PTR data);
+ void OnRenderThumbnail(int width, int height);
+ void OnRenderPreview();
+ void OnTimer(int);
+ void OnClose();
+};
+
+#endif // srmmproxywindow_h__
diff --git a/plugins/W7UI/src/subclassmgr.cpp b/plugins/W7UI/src/subclassmgr.cpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/W7UI/src/subclassmgr.cpp
diff --git a/plugins/W7UI/src/subclassmgr.h b/plugins/W7UI/src/subclassmgr.h
new file mode 100644
index 0000000000..1cf2433254
--- /dev/null
+++ b/plugins/W7UI/src/subclassmgr.h
@@ -0,0 +1,71 @@
+#ifndef subclassmgr_h__
+#define subclassmgr_h__
+
+struct TSubclassData
+{
+ WNDPROC oldWndProc;
+ LPARAM lParam;
+};
+
+typedef LRESULT (*TSubclassProc)(MSG *msg, TSubclassData *data);
+
+class CSubclassMgr
+{
+public:
+ static void Subclass(HWND hwnd, TSubclassProc newWndProc, LPARAM lParam)
+ {
+ TWindowInfo *wi = new TWindowInfo;
+ wi->hwnd = hwnd;
+ wi->newWndProc = newWndProc;
+ wi->lParam = lParam;
+ Instance().m_windows.insert(wi);
+ wi->oldWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)GlobalSubclassProc);
+ }
+
+private:
+ CSubclassMgr(): m_windows(5, TWindowInfo::Compare) {}
+ CSubclassMgr(const CSubclassMgr &);
+ CSubclassMgr &operator=(const CSubclassMgr &);
+
+ static CSubclassMgr &Instance()
+ {
+ static CSubclassMgr theInstance;
+ return theInstance;
+ }
+
+ struct TWindowInfo
+ {
+ HWND hwnd;
+ WNDPROC oldWndProc;
+ TSubclassProc newWndProc;
+ LPARAM lParam;
+
+ static int Compare(const TWindowInfo *p1, const TWindowInfo *p2)
+ {
+ return (int)p1->hwnd - (int)p2->hwnd;
+ }
+ };
+
+ OBJLIST<TWindowInfo> m_windows;
+
+ static LRESULT CALLBACK GlobalSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+ {
+ TWindowInfo search = { hwnd };
+ TWindowInfo *wnd = Instance().m_windows.find(&search);
+ if (!wnd) return DefWindowProc(hwnd, message, wParam, lParam);
+
+ MSG msg = { hwnd, message, wParam, lParam };
+ TSubclassData data = { wnd->oldWndProc, wnd->lParam };
+ LRESULT result = wnd->newWndProc(&msg, &data);
+
+ if (message == WM_DESTROY)
+ {
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wnd->oldWndProc);
+ Instance().m_windows.remove(wnd);
+ }
+
+ return result;
+ }
+};
+
+#endif // subclassmgr_h__
diff --git a/plugins/W7UI/src/w7ui.cpp b/plugins/W7UI/src/w7ui.cpp
new file mode 100644
index 0000000000..c94f7b31ca
--- /dev/null
+++ b/plugins/W7UI/src/w7ui.cpp
@@ -0,0 +1,180 @@
+#include "headers.h"
+
+ITaskbarList3 *g_pTaskbarList = NULL;
+UINT g_wm_TaskbarButtonCreated = 0;
+HANDLE hSrmmWindows = NULL;
+
+int g_eventSlotTyping = 0;
+int g_eventSlotMessage = 0;
+
+void InitJumpList();
+
+static LRESULT CALLBACK W7UIHostWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK W7SrmmProxyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static int OnModulesLoaded(WPARAM, LPARAM);
+static int OnProcessSrmmEvent(WPARAM, LPARAM lParam);
+static int OnStatusModeChanged(WPARAM wParam, LPARAM);
+
+int LoadW7UI()
+{
+ CoInitialize(NULL);
+
+ CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&g_pTaskbarList);
+ g_pTaskbarList->HrInit();
+
+ g_wm_TaskbarButtonCreated = RegisterWindowMessage(_T("TaskbarButtonCreated"));
+
+ CJumpListBuilder::Load();
+ LoadJumpList();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ HookEvent(ME_CLIST_STATUSMODECHANGE, OnStatusModeChanged);
+
+ hSrmmWindows = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ new CClistProxyWindow();
+
+ return 0;
+}
+
+int UnloadW7UI()
+{
+ CJumpListBuilder::Unload();
+ return 0;
+}
+
+static int OnContactIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ if (!wParam) return 0;
+
+ if (lParam) g_clistProxyWnd->AddOverlayEvent(g_eventSlotTyping);
+ else g_clistProxyWnd->RemoveOverlayEvent(g_eventSlotTyping);
+
+ return 0;
+}
+
+static int OnModulesLoaded(WPARAM, LPARAM)
+{
+ InitJumpList();
+ g_eventSlotMessage = g_clistProxyWnd->AllocateOverlayEvent(LoadSkinnedIconHandle(SKINICON_EVENT_MESSAGE));
+ g_eventSlotTyping = g_clistProxyWnd->AllocateOverlayEvent(LoadSkinnedIconHandle(SKINICON_OTHER_TYPING));
+ OnStatusModeChanged(CallService(MS_CLIST_GETSTATUSMODE, 0, 0), 0);
+ HookEvent(ME_MSG_WINDOWEVENT, OnProcessSrmmEvent);
+ HookEvent(ME_PROTO_CONTACTISTYPING, OnContactIsTyping);
+ return 0;
+}
+
+static LRESULT SrmmSubclassProc(MSG *msg, TSubclassData *data)
+{
+ HWND hwndProxy = WindowList_Find(hSrmmWindows, (HANDLE)data->lParam);
+ CSrmmProxyWindow *wnd = CDwmWindow::GetWindow<CSrmmProxyWindow>(hwndProxy);
+
+ if (wnd)
+ {
+ switch (msg->message)
+ {
+ case WM_SETFOCUS:
+ wnd->OnTabActive();
+ break;
+ case WM_ACTIVATE:
+ switch (msg->wParam)
+ {
+ case WA_ACTIVE:
+ case WA_CLICKACTIVE:
+ wnd->OnTabActive();
+ break;
+ case WA_INACTIVE:
+ wnd->OnTabInactive();
+ }
+ break;
+ case WM_NCACTIVATE:
+ if (msg->wParam)
+ wnd->OnTabActive();
+ else
+ wnd->OnTabInactive();
+ break;
+ }
+ }
+
+ return CallWindowProc(data->oldWndProc, msg->hwnd, msg->message, msg->wParam, msg->lParam);
+}
+
+static HWND FindParent(HWND hwnd)
+{
+ while (1)
+ {
+ HWND hwndParent = GetParent(hwnd);
+ if (hwndParent == NULL)
+ return hwnd;
+ hwnd = hwndParent;
+ }
+}
+
+int OnProcessSrmmEvent(WPARAM, LPARAM lParam)
+{
+ MessageWindowEventData *evt = (MessageWindowEventData *)lParam;
+
+ switch (evt->uType)
+ {
+ case MSG_WINDOW_EVT_OPENING:
+ {
+ CSubclassMgr::Subclass(evt->hwndWindow, SrmmSubclassProc, (LPARAM)evt->hContact);
+ break;
+ }
+
+ case MSG_WINDOW_EVT_OPEN:
+ {
+ HWND hwndParent = FindParent(evt->hwndWindow);
+ if (hwndParent != evt->hwndWindow)
+ {
+ SetWindowLongPtr(hwndParent, GWL_EXSTYLE, GetWindowLongPtr(hwndParent, GWL_EXSTYLE) & ~WS_EX_APPWINDOW);
+ CSrmmProxyWindow *wnd = new CSrmmProxyWindow(evt->hContact, evt->hwndWindow, hwndParent);
+ HWND hwndProxy = wnd->hwnd();
+ g_pTaskbarList->UnregisterTab(hwndParent);
+ g_pTaskbarList->RegisterTab(hwndProxy, hwndParent);
+ g_pTaskbarList->SetTabOrder(hwndProxy, 0);
+ g_pTaskbarList->SetTabActive(hwndProxy, hwndParent, TBATF_USEMDITHUMBNAIL);
+ WindowList_Add(hSrmmWindows, hwndProxy, evt->hContact);
+ }
+ break;
+ }
+
+ case MSG_WINDOW_EVT_CLOSING:
+ {
+ HWND hwndProxy = WindowList_Find(hSrmmWindows, evt->hContact);
+ if (hwndProxy)
+ {
+ WindowList_Remove(hSrmmWindows, hwndProxy);
+ g_pTaskbarList->UnregisterTab(hwndProxy);
+ DestroyWindow(hwndProxy);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// status processing
+
+int OnStatusModeChanged(WPARAM wParam, LPARAM)
+{
+ static int icons[] =
+ {
+ SKINICON_STATUS_OFFLINE,
+ SKINICON_STATUS_ONLINE,
+ SKINICON_STATUS_AWAY,
+ SKINICON_STATUS_DND,
+ SKINICON_STATUS_NA,
+ SKINICON_STATUS_OCCUPIED,
+ SKINICON_STATUS_FREE4CHAT,
+ SKINICON_STATUS_INVISIBLE,
+ SKINICON_STATUS_ONTHEPHONE,
+ SKINICON_STATUS_OUTTOLUNCH,
+ };
+
+ g_clistProxyWnd->SetOverlayIcon(LoadSkinnedIcon(icons[wParam - ID_STATUS_OFFLINE]));
+
+ return 0;
+}
diff --git a/plugins/W7UI/src/win7api.cpp b/plugins/W7UI/src/win7api.cpp
new file mode 100644
index 0000000000..dcfb6058ec
--- /dev/null
+++ b/plugins/W7UI/src/win7api.cpp
@@ -0,0 +1,25 @@
+#include <windows.h>
+
+//extern "C" const CLSID CLSID_TaskbarList = {0x56fdf344,0xfd6d,0x11d0,{0x95,0x8a,0x00,0x60,0x97,0xc9,0xa0,0x90}}; // 56fdf344-fd6d-11d0-958a-006097c9a090;
+//extern "C" const IID IID_ITaskbarList = {0x56FDF342,0xFD6D,0x11d0,{0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90}}; // 56FDF342-FD6D-11d0-958A-006097C9A090;
+//extern "C" const IID IID_ITaskbarList2 = {0x602D4995,0xB13A,0x429b,{0xA6,0x6E,0x19,0x35,0xE4,0x4F,0x43,0x17}}; // 602D4995-B13A-429b-A66E-1935E44F4317;
+//extern "C" const IID IID_ICustomDestinationList = {0x6332debf,0x87b5,0x4670,{0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}}; // 6332debf-87b5-4670-90c0-5e57b408a49e
+//extern "C" const IID IID_IObjectArray = {0x92CA9DCD,0x5622,0x4bba,{0xA8,0x05,0x5E,0x9F,0x54,0x1B,0xD8,0xC9}}; // 92CA9DCD-5622-4bba-A805-5E9F541BD8C9
+//extern "C" const IID IID_IObjectCollection = {0x5632b1a4,0xe38a,0x400a,{0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}}; // 5632b1a4-e38a-400a-928a-d4cd63230295
+//extern "C" const IID IID_ITaskbarList3 = {0xea1afb91,0x9e28,0x4b86,{0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf}}; // ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf
+extern "C" const CLSID CLSID_CustomDestinationList = {0x77f10cf0,0x3db5,0x4966,{0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}};
+//extern "C" const CLSID CLSID_EnumerableObjectCollection = {0x2d3468c1,0x36a7,0x43b6,{0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}};
+
+HRESULT (WINAPI *dwmInvalidateIconicBitmaps)(HWND) =
+ (HRESULT (WINAPI *)(HWND))GetProcAddress(LoadLibraryA("dwmapi.dll"), "DwmInvalidateIconicBitmaps");
+HRESULT (WINAPI *dwmSetIconicThumbnail)(HWND, HBITMAP, DWORD) =
+ (HRESULT (WINAPI *)(HWND, HBITMAP, DWORD))GetProcAddress(LoadLibraryA("dwmapi.dll"), "DwmSetIconicThumbnail");
+HRESULT (WINAPI *dwmSetIconicLivePreviewBitmap)(HWND, HBITMAP, LPPOINT, DWORD) =
+ (HRESULT (WINAPI *)(HWND, HBITMAP, LPPOINT, DWORD))GetProcAddress(LoadLibraryA("dwmapi.dll"), "DwmSetIconicLivePreviewBitmap");
+
+HANDLE (STDAPICALLTYPE *openThemeData)(HWND, LPCWSTR) =
+ (HANDLE (STDAPICALLTYPE *)(HWND, LPCWSTR))GetProcAddress(LoadLibraryA("uxtheme.dll"), "OpenThemeData");
+HRESULT (STDAPICALLTYPE *drawThemeTextEx)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const struct _DTTOPTS *) =
+ (HRESULT (STDAPICALLTYPE *)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const struct _DTTOPTS *))GetProcAddress(LoadLibraryA("uxtheme.dll"), "DrawThemeTextEx");
+HRESULT (STDAPICALLTYPE *closeThemeData)(HANDLE) =
+ (HRESULT (STDAPICALLTYPE *)(HANDLE))GetProcAddress(LoadLibraryA("uxtheme.dll"), "CloseThemeData");
diff --git a/plugins/W7UI/src/win7api.h b/plugins/W7UI/src/win7api.h
new file mode 100644
index 0000000000..f9fa806335
--- /dev/null
+++ b/plugins/W7UI/src/win7api.h
@@ -0,0 +1,38 @@
+#ifndef win7api_h__
+#define win7api_h__
+
+#define WM_DWMSENDICONICTHUMBNAIL 0x0323
+#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326
+
+#define DWMWA_HAS_ICONIC_BITMAP 10
+
+#define DWM_SIT_DISPLAYFRAME 0x00000001
+
+enum TBATFLAG
+{ TBATF_USEMDITHUMBNAIL = 0x1,
+ TBATF_USEMDILIVEPREVIEW = 0x2
+};
+
+#define THBN_CLICKED 0x1800
+
+extern HRESULT (WINAPI *dwmInvalidateIconicBitmaps)(HWND);
+extern HRESULT (WINAPI *dwmSetIconicThumbnail)(HWND, HBITMAP, DWORD);
+extern HRESULT (WINAPI *dwmSetIconicLivePreviewBitmap)(HWND, HBITMAP, LPPOINT, DWORD);
+
+extern HANDLE (STDAPICALLTYPE *openThemeData)(HWND, LPCWSTR);
+extern HRESULT (STDAPICALLTYPE *drawThemeTextEx)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const struct _DTTOPTS *);
+extern HRESULT (STDAPICALLTYPE *closeThemeData)(HANDLE);
+
+extern "C" const IID IID_ICustomDestinationList;
+extern "C" const IID IID_IObjectArray;
+extern "C" const IID IID_IObjectCollection;
+extern "C" const IID IID_ITaskbarList3;
+extern "C" const CLSID CLSID_CustomDestinationList;
+extern "C" const CLSID CLSID_EnumerableObjectCollection;
+
+#include "win7api_IObjectArray.h"
+#include "win7api_IObjectCollection.h"
+#include "win7api_ICustomDestinationList.h"
+//#include "win7api_ITaskbarList3.h"
+
+#endif // win7api_h__
diff --git a/plugins/W7UI/src/win7api_ICustomDestinationList.h b/plugins/W7UI/src/win7api_ICustomDestinationList.h
new file mode 100644
index 0000000000..6d3f770d29
--- /dev/null
+++ b/plugins/W7UI/src/win7api_ICustomDestinationList.h
@@ -0,0 +1,34 @@
+#ifndef __ICustomDestinationList_INTERFACE_DEFINED__
+#define __ICustomDestinationList_INTERFACE_DEFINED__
+
+typedef /* [v1_enum] */ enum tagKNOWNDESTCATEGORY {
+ KDC_FREQUENT = 1,
+ KDC_RECENT = (KDC_FREQUENT + 1)
+} KNOWNDESTCATEGORY;
+
+MIDL_INTERFACE("6332debf-87b5-4670-90c0-5e57b408a49e")
+ICustomDestinationList : public IUnknown {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetAppID(
+ /* [string][in] */__RPC__in_string LPCWSTR pszAppID) = 0;
+ virtual HRESULT STDMETHODCALLTYPE BeginList(
+ /* [out] */ __RPC__out UINT *pcMaxSlots,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AppendCategory(
+ /* [string][in] */ __RPC__in_string LPCWSTR pszCategory,
+ /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AppendKnownCategory(
+ /* [in] */ KNOWNDESTCATEGORY category) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AddUserTasks(
+ /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
+ virtual HRESULT STDMETHODCALLTYPE CommitList(void) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetRemovedDestinations(
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+ virtual HRESULT STDMETHODCALLTYPE DeleteList(
+ /* [string][in] */ __RPC__in_string LPCWSTR pszAppID) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AbortList(void) = 0;
+};
+
+#endif // __ICustomDestinationList_INTERFACE_DEFINED__
diff --git a/plugins/W7UI/src/win7api_IObjectArray.h b/plugins/W7UI/src/win7api_IObjectArray.h
new file mode 100644
index 0000000000..2102276989
--- /dev/null
+++ b/plugins/W7UI/src/win7api_IObjectArray.h
@@ -0,0 +1,15 @@
+#ifndef __IObjectArray_INTERFACE_DEFINED__
+#define __IObjectArray_INTERFACE_DEFINED__
+
+MIDL_INTERFACE("92CA9DCD-5622-4bba-A805-5E9F541BD8C9")
+IObjectArray : public IUnknown {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetCount(
+ /* [out] */ __RPC__out UINT *pcObjects) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetAt(
+ /* [in] */ UINT uiIndex,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+};
+
+#endif // __IObjectArray_INTERFACE_DEFINED__
diff --git a/plugins/W7UI/src/win7api_IObjectCollection.h b/plugins/W7UI/src/win7api_IObjectCollection.h
new file mode 100644
index 0000000000..71b37d0e99
--- /dev/null
+++ b/plugins/W7UI/src/win7api_IObjectCollection.h
@@ -0,0 +1,16 @@
+#ifndef __IObjectCollection_INTERFACE_DEFINED__
+#define __IObjectCollection_INTERFACE_DEFINED__
+
+MIDL_INTERFACE("5632b1a4-e38a-400a-928a-d4cd63230295")
+IObjectCollection : public IObjectArray {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AddObject(
+ /* [in] */ __RPC__in_opt IUnknown *punk) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AddFromArray(
+ /* [in] */ __RPC__in_opt IObjectArray *poaSource) = 0;
+ virtual HRESULT STDMETHODCALLTYPE RemoveObjectAt(
+ /* [in] */ UINT uiIndex) = 0;
+ virtual HRESULT STDMETHODCALLTYPE Clear(void) = 0;
+};
+
+#endif // __IObjectCollection_INTERFACE_DEFINED__
diff --git a/plugins/W7UI/src/win7api_ITaskbarList3.h b/plugins/W7UI/src/win7api_ITaskbarList3.h
new file mode 100644
index 0000000000..8c39fb5c41
--- /dev/null
+++ b/plugins/W7UI/src/win7api_ITaskbarList3.h
@@ -0,0 +1,65 @@
+#ifndef __ITaskbarList3_FWD_DEFINED__
+#define __ITaskbarList3_FWD_DEFINED__
+typedef interface ITaskbarList3 ITaskbarList3;
+#endif /* __ITaskbarList3_FWD_DEFINED__ */
+
+/* interface ITaskbarList3 */
+/* [object][uuid] */
+
+MIDL_INTERFACE("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")
+ITaskbarList3 : public ITaskbarList2
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetProgressValue(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ ULONGLONG ullCompleted,
+ /* [in] */ ULONGLONG ullTotal) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetProgressState(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ TBPFLAG tbpFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RegisterTab(
+ /* [in] */ __RPC__in HWND hwndTab,
+ /* [in] */ __RPC__in HWND hwndMDI) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE UnregisterTab(
+ /* [in] */ __RPC__in HWND hwndTab) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTabOrder(
+ /* [in] */ __RPC__in HWND hwndTab,
+ /* [in] */ __RPC__in HWND hwndInsertBefore) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTabActive(
+ /* [in] */ __RPC__in HWND hwndTab,
+ /* [in] */ __RPC__in HWND hwndMDI,
+ /* [in] */ TBATFLAG tbatFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ThumbBarAddButtons(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ UINT cButtons,
+ /* [size_is][in] */ __RPC__in_ecount_full(cButtons) LPTHUMBBUTTON pButton) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ThumbBarUpdateButtons(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ UINT cButtons,
+ /* [size_is][in] */ __RPC__in_ecount_full(cButtons) LPTHUMBBUTTON pButton) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ThumbBarSetImageList(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ __RPC__in_opt HIMAGELIST himl) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetOverlayIcon(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ __RPC__in HICON hIcon,
+ /* [string][in] */ __RPC__in_string LPCWSTR pszDescription) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetThumbnailTooltip(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [string][in] */ __RPC__in_string LPCWSTR pszTip) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ __RPC__in RECT *prcClip) = 0;
+
+};