summaryrefslogtreecommitdiff
path: root/plugins/w7ui/srmmproxywindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/w7ui/srmmproxywindow.cpp')
-rw-r--r--plugins/w7ui/srmmproxywindow.cpp374
1 files changed, 374 insertions, 0 deletions
diff --git a/plugins/w7ui/srmmproxywindow.cpp b/plugins/w7ui/srmmproxywindow.cpp
new file mode 100644
index 0000000000..a70ca1b672
--- /dev/null
+++ b/plugins/w7ui/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