diff options
Diffstat (limited to 'plugins/W7UI/srmmproxywindow.cpp')
| -rw-r--r-- | plugins/W7UI/srmmproxywindow.cpp | 374 | 
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  | 
