summaryrefslogtreecommitdiff
path: root/plugins/Scriver/src/tabs.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2016-12-23 20:19:34 +0300
committerGeorge Hazan <ghazan@miranda.im>2016-12-23 20:19:34 +0300
commitb16718fb5ee5e3c30c73449287be3ad4ed141082 (patch)
treed2429fed4568edde12c801e2f2b2f11e2f3a64bb /plugins/Scriver/src/tabs.cpp
parent9c8409da79196441817709b590cc5152936afc56 (diff)
correct file name applied
Diffstat (limited to 'plugins/Scriver/src/tabs.cpp')
-rw-r--r--plugins/Scriver/src/tabs.cpp1520
1 files changed, 1520 insertions, 0 deletions
diff --git a/plugins/Scriver/src/tabs.cpp b/plugins/Scriver/src/tabs.cpp
new file mode 100644
index 0000000000..9c18edc424
--- /dev/null
+++ b/plugins/Scriver/src/tabs.cpp
@@ -0,0 +1,1520 @@
+/*
+Scriver
+
+Copyright (c) 2000-09 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 "stdafx.h"
+
+#define SB_CHAR_WIDTH 40
+#define SB_SENDING_WIDTH 25
+#define SB_UNICODE_WIDTH 18
+
+#define TIMEOUT_FLASHWND 900
+
+static void DrawTab(ParentWindowData *dat, HWND hwnd, WPARAM wParam, LPARAM lParam);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static const wchar_t *titleTokenNames[] = { L"%name%", L"%status%", L"%statusmsg%", L"%account%" };
+
+wchar_t* GetWindowTitle(MCONTACT hContact, const char *szProto)
+{
+ ptrW tmplt;
+ const wchar_t* tokens[4] = { 0 };
+
+ CMStringW tszTemplate, tszStatus, tszTitle;
+ if (hContact && szProto) {
+ tokens[0] = pcli->pfnGetContactDisplayName(hContact, 0);
+ tokens[1] = pcli->pfnGetStatusModeDescription(db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
+
+ tszStatus = ptrW(db_get_wsa(hContact, "CList", "StatusMsg"));
+ tszStatus.Replace(L"\r\n", L" ");
+ tokens[2] = tszStatus;
+
+ char *accModule = Proto_GetBaseAccountName(hContact);
+ if (accModule != NULL) {
+ PROTOACCOUNT* proto = Proto_GetAccount(accModule);
+ if (proto != NULL)
+ tokens[3] = mir_wstrdup(proto->tszAccountName);
+ }
+
+ tmplt = db_get_wsa(NULL, SRMMMOD, SRMSGSET_WINDOWTITLE);
+ if (tmplt != NULL)
+ tszTemplate = tmplt;
+ else {
+ if (g_dat.flags & SMF_STATUSICON)
+ tszTemplate = L"%name% - ";
+ else
+ tszTemplate = L"%name% (%status%) : ";
+ }
+ }
+
+ for (const wchar_t *p = tszTemplate; *p; p++) {
+ if (*p == '%') {
+ int i;
+ for (i = 0; i < _countof(titleTokenNames); i++) {
+ size_t tnlen = mir_wstrlen(titleTokenNames[i]);
+ if (!wcsncmp(p, titleTokenNames[i], tnlen)) {
+ if (tokens[i] != NULL)
+ tszTitle.Append(tokens[i]);
+
+ p += tnlen - 1;
+ break;
+ }
+ }
+ if (i < _countof(titleTokenNames))
+ continue;
+ }
+ tszTitle.AppendChar(*p);
+ }
+
+ if (tmplt == NULL)
+ tszTitle.Append(TranslateT("Message session"));
+
+ return tszTitle.Detach();
+}
+
+static int GetChildCount(ParentWindowData *dat)
+{
+ return TabCtrl_GetItemCount(dat->hwndTabs);
+}
+
+static void GetChildWindowRect(ParentWindowData *dat, RECT *rcChild)
+{
+ RECT rc, rcStatus, rcTabs;
+ GetClientRect(dat->hwnd, &rc);
+ GetClientRect(dat->hwndTabs, &rcTabs);
+ TabCtrl_AdjustRect(dat->hwndTabs, FALSE, &rcTabs);
+ rcStatus.top = rcStatus.bottom = 0;
+ if (dat->flags2 & SMF2_SHOWSTATUSBAR)
+ GetWindowRect(dat->hwndStatus, &rcStatus);
+
+ rcChild->left = 0;
+ rcChild->right = rc.right;
+ if (dat->flags2 & SMF2_TABSATBOTTOM) {
+ rcChild->top = 2;
+ if ((dat->flags2 & SMF2_USETABS && !(dat->flags2 & SMF2_HIDEONETAB)) || (dat->childrenCount > 1))
+ rcChild->bottom = rcTabs.bottom + 4;
+ else
+ rcChild->bottom = rc.bottom - rc.top - (rcStatus.bottom - rcStatus.top);
+ }
+ else {
+ if ((dat->flags2 & SMF2_USETABS && !(dat->flags2 & SMF2_HIDEONETAB)) || (dat->childrenCount > 1))
+ rcChild->top = rcTabs.top;
+ else
+ rcChild->top = 2;
+
+ rcChild->bottom = rc.bottom - rc.top - (rcStatus.bottom - rcStatus.top);
+ }
+}
+
+static int GetTabFromHWND(ParentWindowData *dat, HWND child)
+{
+ int l = TabCtrl_GetItemCount(dat->hwndTabs);
+ for (int i = 0; i < l; i++) {
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(dat->hwndTabs, i, &tci);
+ MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam;
+ if (mwtd->hwnd == child)
+ return i;
+ }
+ return -1;
+}
+
+static MessageWindowTabData* GetChildFromTab(HWND hwndTabs, int tabId)
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ if (TabCtrl_GetItem(hwndTabs, tabId, &tci))
+ return (MessageWindowTabData *)tci.lParam;
+
+ return NULL;
+}
+
+static MessageWindowTabData* GetChildFromHWND(ParentWindowData *dat, HWND hwnd)
+{
+ int l = TabCtrl_GetItemCount(dat->hwndTabs);
+ for (int i = 0; i < l; i++) {
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(dat->hwndTabs, i, &tci);
+ MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam;
+ if (mwtd->hwnd == hwnd)
+ return mwtd;
+ }
+ return NULL;
+}
+
+static void GetMinimunWindowSize(ParentWindowData *dat, SIZE *size)
+{
+ MINMAXINFO mmi;
+ RECT rc, rcWindow;
+ int minW = 216, minH = 80;
+ GetWindowRect(dat->hwnd, &rcWindow);
+ GetChildWindowRect(dat, &rc);
+ for (int i = 0; i < dat->childrenCount; i++) {
+ MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i);
+ SendMessage(mwtd->hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
+ if (i == 0 || mmi.ptMinTrackSize.x > minW) minW = mmi.ptMinTrackSize.x;
+ if (i == 0 || mmi.ptMinTrackSize.y > minH) minH = mmi.ptMinTrackSize.y;
+ }
+ if (dat->bMinimized) {
+ size->cx = minW;
+ size->cy = minH;
+ }
+ else {
+ size->cx = minW + (rcWindow.right - rcWindow.left) - (rc.right - rc.left);
+ size->cy = minH + (rcWindow.bottom - rcWindow.top) - (rc.bottom - rc.top);
+ }
+}
+
+static void SetupStatusBar(ParentWindowData *dat)
+{
+ int statusIconNum = GetStatusIconsCount(dat->hContact);
+ int statwidths[4];
+ RECT rc;
+ GetClientRect(dat->hwnd, &rc);
+ statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_UNICODE_WIDTH - 2 * (statusIconNum > 0) - statusIconNum * (GetSystemMetrics(SM_CXSMICON) + 2);
+ statwidths[1] = rc.right - rc.left - SB_UNICODE_WIDTH - 2 * (statusIconNum > 0) - statusIconNum * (GetSystemMetrics(SM_CXSMICON) + 2);
+ statwidths[2] = rc.right - rc.left - SB_UNICODE_WIDTH;
+ statwidths[3] = -1;
+ SendMessage(dat->hwndStatus, SB_SETPARTS, 4, (LPARAM)statwidths);
+ SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0);
+ SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_NOBORDERS) | 3, 0);
+}
+
+static int AddOrReplaceIcon(HIMAGELIST hList, int prevIndex, HICON hIcon)
+{
+ int usageIdx = -1;
+ for (int i = 0; i < g_dat.tabIconListUsageSize; i++) {
+ if (!g_dat.tabIconListUsage[i].used && usageIdx == -1)
+ usageIdx = i;
+
+ if (g_dat.tabIconListUsage[i].index == prevIndex) {
+ usageIdx = i;
+ break;
+ }
+ }
+ if (usageIdx == -1) {
+ usageIdx = g_dat.tabIconListUsageSize;
+ g_dat.tabIconListUsage = (ImageListUsageEntry*)mir_realloc(g_dat.tabIconListUsage, sizeof(ImageListUsageEntry)* (g_dat.tabIconListUsageSize + 1));
+ g_dat.tabIconListUsageSize++;
+ }
+ else prevIndex = g_dat.tabIconListUsage[usageIdx].index;
+
+ g_dat.tabIconListUsage[usageIdx].used = 1;
+ g_dat.tabIconListUsage[usageIdx].index = (int)ImageList_ReplaceIcon(hList, prevIndex, hIcon);
+ return g_dat.tabIconListUsage[usageIdx].index;
+}
+
+static void ReleaseIcon(int index)
+{
+ for (int i = 0; i < g_dat.tabIconListUsageSize; i++)
+ if (g_dat.tabIconListUsage[i].index == index)
+ g_dat.tabIconListUsage[i].used = 0;
+}
+
+static void ActivateChild(ParentWindowData *dat, HWND child)
+{
+ RECT rcChild;
+ GetChildWindowRect(dat, &rcChild);
+ SetWindowPos(child, HWND_TOP, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, SWP_NOSIZE);
+
+ int i = GetTabFromHWND(dat, child);
+ if (i == -1)
+ return;
+
+ MessageWindowTabData *mwtd;
+ if ((mwtd = GetChildFromTab(dat->hwndTabs, i)) == NULL)
+ return;
+
+ dat->hContact = mwtd->hContact;
+ if (child != dat->hwndActive) {
+ HWND prev = dat->hwndActive;
+ dat->hwndActive = child;
+ SetupStatusBar(dat);
+ SendMessage(dat->hwndActive, GC_UPDATESTATUSBAR, 0, 0);
+ SendMessage(dat->hwndActive, DM_UPDATETITLEBAR, 0, 0);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ ShowWindow(dat->hwndActive, SW_SHOWNOACTIVATE);
+ SendMessage(dat->hwndActive, DM_SCROLLLOGTOBOTTOM, 0, 0);
+ if (prev != NULL)
+ ShowWindow(prev, SW_HIDE);
+ }
+ else SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+
+ TabCtrl_SetCurSel(dat->hwndTabs, i);
+ SendMessage(dat->hwndActive, DM_ACTIVATE, WA_ACTIVE, 0);
+}
+
+static void AddChild(ParentWindowData *dat, HWND hwnd, MCONTACT hContact)
+{
+ MessageWindowTabData *mwtd = (MessageWindowTabData *)mir_alloc(sizeof(MessageWindowTabData));
+ mwtd->hwnd = hwnd;
+ mwtd->hContact = hContact;
+ mwtd->szProto = GetContactProto(hContact);
+ mwtd->parent = dat;
+
+ dat->childrenCount++;
+
+ TCITEM tci;
+ tci.mask = TCIF_PARAM | TCIF_IMAGE | TCIF_TEXT;
+ tci.lParam = (LPARAM)mwtd;
+ tci.iImage = -1;
+ tci.pszText = L"";
+ TabCtrl_InsertItem(dat->hwndTabs, dat->childrenCount - 1, &tci);
+ SetWindowPos(mwtd->hwnd, HWND_TOP, dat->childRect.left, dat->childRect.top, dat->childRect.right - dat->childRect.left, dat->childRect.bottom - dat->childRect.top, SWP_HIDEWINDOW);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+
+ EnableThemeDialogTexture(hwnd, ETDT_ENABLETAB);
+}
+
+static void RemoveChild(ParentWindowData *dat, HWND child)
+{
+ int tab = GetTabFromHWND(dat, child);
+ if (tab >= 0) {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM | TCIF_IMAGE;
+ TabCtrl_GetItem(dat->hwndTabs, tab, &tci);
+ TabCtrl_DeleteItem(dat->hwndTabs, tab);
+ mir_free((MessageWindowTabData *)tci.lParam);
+ dat->childrenCount--;
+ if (child == dat->hwndActive) {
+ if (tab == TabCtrl_GetItemCount(dat->hwndTabs)) tab--;
+ if (tab >= 0)
+ ActivateChild(dat, GetChildFromTab(dat->hwndTabs, tab)->hwnd);
+ else
+ dat->hwndActive = NULL;
+ }
+ ReleaseIcon(tci.iImage);
+ }
+}
+
+static void CloseOtherChilden(ParentWindowData *dat, HWND child)
+{
+ ActivateChild(dat, child);
+ for (int i = dat->childrenCount - 1; i >= 0; i--) {
+ MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, i);
+ if (mwtd != NULL && mwtd->hwnd != child)
+ SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0);
+ }
+ ActivateChild(dat, child);
+}
+
+static void ActivateNextChild(ParentWindowData *dat, HWND child)
+{
+ int i = GetTabFromHWND(dat, child);
+ int l = TabCtrl_GetItemCount(dat->hwndTabs);
+ i = (i + 1) % l;
+ ActivateChild(dat, GetChildFromTab(dat->hwndTabs, i)->hwnd);
+}
+
+static void ActivatePrevChild(ParentWindowData *dat, HWND child)
+{
+ int i = GetTabFromHWND(dat, child);
+ int l = TabCtrl_GetItemCount(dat->hwndTabs);
+ i = (i + l - 1) % l;
+ ActivateChild(dat, GetChildFromTab(dat->hwndTabs, i)->hwnd);
+}
+
+static void ActivateChildByIndex(ParentWindowData *dat, int index)
+{
+ int l = TabCtrl_GetItemCount(dat->hwndTabs);
+ if (index < l) {
+ MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, index);
+ if (mwtd != NULL)
+ ActivateChild(dat, mwtd->hwnd);
+ }
+}
+
+static void SetContainerWindowStyle(ParentWindowData *dat)
+{
+ ShowWindow(dat->hwndStatus, (dat->flags2 & SMF2_SHOWSTATUSBAR) ? SW_SHOW : SW_HIDE);
+
+ DWORD ws = GetWindowLongPtr(dat->hwnd, GWL_STYLE) & ~(WS_CAPTION);
+ if (dat->flags2 & SMF2_SHOWTITLEBAR)
+ ws |= WS_CAPTION;
+
+ SetWindowLongPtr(dat->hwnd, GWL_STYLE, ws);
+
+ ws = GetWindowLongPtr(dat->hwnd, GWL_EXSTYLE)& ~WS_EX_LAYERED;
+ ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0;
+ SetWindowLongPtr(dat->hwnd, GWL_EXSTYLE, ws);
+ if (dat->flags2 & SMF2_USETRANSPARENCY)
+ SetLayeredWindowAttributes(dat->hwnd, RGB(255, 255, 255), (BYTE)(255 - g_dat.inactiveAlpha), LWA_ALPHA);
+
+ ws = GetWindowLongPtr(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM | 0x2000);
+ if (dat->flags2 & SMF2_TABSATBOTTOM)
+ ws |= TCS_BOTTOM;
+
+ ws |= 0x2000;
+ if (dat->flags2 & SMF2_TABCLOSEBUTTON)
+ TabCtrl_SetPadding(dat->hwndTabs, GetSystemMetrics(SM_CXEDGE) + 12, GetSystemMetrics(SM_CYEDGE) + 1);
+ else
+ TabCtrl_SetPadding(dat->hwndTabs, GetSystemMetrics(SM_CXEDGE) + 4, GetSystemMetrics(SM_CYEDGE) + 1);
+
+ SetWindowLongPtr(dat->hwndTabs, GWL_STYLE, ws);
+
+ RECT rc;
+ GetWindowRect(dat->hwnd, &rc);
+ SetWindowPos(dat->hwnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK TabCtrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TabCtrlData *dat = (TabCtrlData*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ TCHITTESTINFO thinfo;
+ int tabId;
+
+ switch (msg) {
+ case EM_SUBCLASSED:
+ dat = (TabCtrlData*)mir_alloc(sizeof(TabCtrlData));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->bDragging = FALSE;
+ dat->bDragged = FALSE;
+ dat->srcTab = -1;
+ dat->destTab = -1;
+ return 0;
+
+ case WM_MBUTTONDOWN:
+ thinfo.pt.x = LOWORD(lParam);
+ thinfo.pt.y = HIWORD(lParam);
+ tabId = TabCtrl_HitTest(hwnd, &thinfo);
+ if (tabId >= 0) {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwnd, tabId, &tci);
+ MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam;
+ if (mwtd != NULL) {
+ SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0);
+ dat->srcTab = -1;
+ }
+ }
+ return 0;
+
+ case WM_LBUTTONDBLCLK:
+ thinfo.pt.x = LOWORD(lParam);
+ thinfo.pt.y = HIWORD(lParam);
+ tabId = TabCtrl_HitTest(hwnd, &thinfo);
+ if (tabId >= 0 && tabId == dat->srcTab) {
+ SendMessage(GetChildFromTab(hwnd, tabId)->hwnd, WM_CLOSE, 0, 0);
+ dat->srcTab = -1;
+ }
+ dat->destTab = -1;
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (!dat->bDragging) {
+ thinfo.pt.x = LOWORD(lParam);
+ thinfo.pt.y = HIWORD(lParam);
+ dat->srcTab = TabCtrl_HitTest(hwnd, &thinfo);
+
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ if (dat->srcTab >= 0) {
+ dat->bDragging = TRUE;
+ dat->bDragged = FALSE;
+ dat->clickLParam = lParam;
+ dat->clickWParam = wParam;
+ dat->lastClickTime = ft.dwLowDateTime;
+ dat->mouseLBDownPos.x = thinfo.pt.x;
+ dat->mouseLBDownPos.y = thinfo.pt.y;
+ SetCapture(hwnd);
+ }
+ return 0;
+ }
+ break;
+
+ case WM_CAPTURECHANGED:
+ case WM_LBUTTONUP:
+ if (dat->bDragging) {
+ thinfo.pt.x = LOWORD(lParam);
+ thinfo.pt.y = HIWORD(lParam);
+ if (dat->bDragged) {
+ ImageList_DragLeave(GetDesktopWindow());
+ ImageList_EndDrag();
+ ImageList_Destroy(dat->hDragImageList);
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ dat->destTab = TabCtrl_HitTest(hwnd, &thinfo);
+ if (thinfo.flags != TCHT_NOWHERE && dat->destTab != dat->srcTab) {
+ NMHDR nmh;
+ wchar_t sBuffer[501];
+ TCITEM item;
+ int curSel;
+ curSel = TabCtrl_GetCurSel(hwnd);
+ item.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_TEXT;
+ item.pszText = sBuffer;
+ item.cchTextMax = _countof(sBuffer);
+ TabCtrl_GetItem(hwnd, dat->srcTab, &item);
+ sBuffer[_countof(sBuffer) - 1] = '\0';
+
+ if (curSel == dat->srcTab)
+ curSel = dat->destTab;
+ else if (curSel > dat->srcTab && curSel <= dat->destTab)
+ curSel--;
+ else if (curSel < dat->srcTab && curSel >= dat->destTab)
+ curSel++;
+
+ TabCtrl_DeleteItem(hwnd, dat->srcTab);
+ TabCtrl_InsertItem(hwnd, dat->destTab, &item);
+ TabCtrl_SetCurSel(hwnd, curSel);
+ dat->destTab = -1;
+ nmh.hwndFrom = hwnd;
+ nmh.idFrom = GetDlgCtrlID(hwnd);
+ nmh.code = TCN_SELCHANGE;
+ SendMessage(GetParent(hwnd), WM_NOTIFY, nmh.idFrom, (LPARAM)&nmh);
+ UpdateWindow(hwnd);
+ }
+ else if (thinfo.flags == TCHT_NOWHERE) {
+ dat->destTab = -1;
+
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwnd, dat->srcTab, &tci);
+ MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam;
+ if (mwtd != NULL) {
+ HWND hChild = mwtd->hwnd;
+ MCONTACT hContact = mwtd->hContact;
+
+ POINT pt;
+ GetCursorPos(&pt);
+ HWND hParent = WindowFromPoint(pt);
+ while (GetParent(hParent) != NULL)
+ hParent = GetParent(hParent);
+
+ hParent = WindowList_Find(g_dat.hParentWindowList, (UINT_PTR)hParent);
+ if ((hParent != NULL && hParent != GetParent(hwnd)) || (hParent == NULL && mwtd->parent->childrenCount > 1 && (GetKeyState(VK_CONTROL) & 0x8000))) {
+ if (hParent == NULL) {
+ hParent = GetParentWindow(hContact, FALSE);
+
+ RECT rc;
+ GetWindowRect(hParent, &rc);
+
+ rc.right = (rc.right - rc.left);
+ rc.bottom = (rc.bottom - rc.top);
+ rc.left = pt.x - rc.right / 2;
+ rc.top = pt.y - rc.bottom / 2;
+ HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
+
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+
+ RECT rcDesktop = mi.rcWork;
+ if (rc.left < rcDesktop.left)
+ rc.left = rcDesktop.left;
+ if (rc.top < rcDesktop.top)
+ rc.top = rcDesktop.top;
+ MoveWindow(hParent, rc.left, rc.top, rc.right, rc.bottom, FALSE);
+ }
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSING);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSE);
+ SetParent(hChild, hParent);
+ SendMessage(GetParent(hwnd), CM_REMOVECHILD, 0, (LPARAM)hChild);
+ SendMessage(hChild, DM_SETPARENT, 0, (LPARAM)hParent);
+ SendMessage(hParent, CM_ADDCHILD, (WPARAM)hChild, hContact);
+ SendMessage(hChild, DM_UPDATETABCONTROL, 0, 0);
+ SendMessage(hParent, CM_ACTIVATECHILD, 0, (LPARAM)hChild);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPENING);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPEN);
+ ShowWindow(hParent, SW_SHOWNA);
+ EnableWindow(hParent, TRUE);
+ }
+ }
+ }
+ else {
+ dat->destTab = -1;
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+ }
+ else if (dat->srcTab >= 0 && g_dat.flags2 & SMF2_TABCLOSEBUTTON) {
+ IMAGEINFO info;
+ POINT pt;
+ RECT rect;
+ int atTop = (GetWindowLongPtr(hwnd, GWL_STYLE) & TCS_BOTTOM) == 0;
+ TabCtrl_GetItemRect(hwnd, dat->srcTab, &rect);
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+ ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info);
+ rect.left = rect.right - (info.rcImage.right - info.rcImage.left) - 6;
+ if (!atTop)
+ rect.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top);
+
+ if (pt.x >= rect.left && pt.x < rect.left + (info.rcImage.right - info.rcImage.left) && pt.y >= rect.top && pt.y < rect.top + (info.rcImage.bottom - info.rcImage.top)) {
+ HBITMAP hOldBitmap, hBmp;
+ HDC hdc = GetDC(NULL);
+ HDC hdcMem = CreateCompatibleDC(hdc);
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+ hBmp = CreateCompatibleBitmap(hdc, info.rcImage.right - info.rcImage.left + 1, info.rcImage.bottom - info.rcImage.top + 1);
+ hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBmp);
+ SetPixel(hdcMem, pt.x, pt.y, 0x000000);
+ ImageList_DrawEx(g_dat.hButtonIconList, 0, hdcMem, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ COLORREF color1 = GetPixel(hdcMem, pt.x, pt.y);
+ SetPixel(hdcMem, pt.x, pt.y, 0xFFFFFF);
+ ImageList_DrawEx(g_dat.hButtonIconList, 0, hdcMem, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ COLORREF color2 = GetPixel(hdcMem, pt.x, pt.y);
+ SelectObject(hdcMem, hOldBitmap);
+ DeleteDC(hdcMem);
+ DeleteObject(hBmp);
+ ReleaseDC(NULL, hdc);
+ if (color1 != 0x000000 || color2 != 0xFFFFFF) {
+ SendMessage(GetChildFromTab(hwnd, dat->srcTab)->hwnd, WM_CLOSE, 0, 0);
+ dat->srcTab = -1;
+ }
+ }
+ else SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam);
+ }
+ else SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam);
+
+ dat->bDragged = dat->bDragging = FALSE;
+ dat->destTab = -1;
+ ReleaseCapture();
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if (wParam & MK_LBUTTON) {
+ if (dat->bDragging) {
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ thinfo.pt.x = LOWORD(lParam);
+ thinfo.pt.y = HIWORD(lParam);
+ if (!dat->bDragged) {
+ if ((abs(thinfo.pt.x - dat->mouseLBDownPos.x) < 3 && abs(thinfo.pt.y - dat->mouseLBDownPos.y) < 3)
+ || (ft.dwLowDateTime - dat->lastClickTime) < 10 * 1000 * 150)
+ break;
+ }
+ if (!dat->bDragged) {
+ POINT pt;
+ RECT rect;
+ RECT rect2;
+ HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 254));
+ GetCursorPos(&pt);
+ TabCtrl_GetItemRect(hwnd, dat->srcTab, &rect);
+ rect.right -= rect.left - 1;
+ rect.bottom -= rect.top - 1;
+ rect2.left = 0; rect2.right = rect.right; rect2.top = 0; rect2.bottom = rect.bottom;
+ dat->hDragImageList = ImageList_Create(rect.right, rect.bottom, ILC_COLOR | ILC_MASK, 0, 1);
+ HDC hDC = GetDC(hwnd);
+ HDC hMemDC = CreateCompatibleDC(hDC);
+ HBITMAP hBitmap = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
+ HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
+ FillRect(hMemDC, &rect2, hBrush);
+ SetWindowOrgEx(hMemDC, rect.left, rect.top, NULL);
+ SendMessage(hwnd, WM_PRINTCLIENT, (WPARAM)hMemDC, PRF_CLIENT);
+ SelectObject(hMemDC, hOldBitmap);
+ ImageList_AddMasked(dat->hDragImageList, hBitmap, RGB(255, 0, 254));
+ DeleteObject(hBitmap);
+ DeleteObject(hBrush);
+ ReleaseDC(hwnd, hDC);
+ DeleteDC(hMemDC);
+ ImageList_BeginDrag(dat->hDragImageList, 0, dat->mouseLBDownPos.x - rect.left, dat->mouseLBDownPos.y - rect.top);
+ ImageList_DragEnter(GetDesktopWindow(), pt.x, pt.y);
+ SetCursor(hDragCursor);
+ dat->mouseLBDownPos.x = thinfo.pt.x;
+ dat->mouseLBDownPos.y = thinfo.pt.y;
+ }
+ else {
+ POINT pt;
+ GetCursorPos(&pt);
+ thinfo.pt = pt;
+ ScreenToClient(hwnd, &thinfo.pt);
+ int newDest = TabCtrl_HitTest(hwnd, &thinfo);
+ if (thinfo.flags == TCHT_NOWHERE)
+ newDest = -1;
+
+ if (newDest != dat->destTab) {
+ dat->destTab = newDest;
+ ImageList_DragLeave(GetDesktopWindow());
+ RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
+ ImageList_DragEnter(GetDesktopWindow(), pt.x, pt.y);
+ }
+ else ImageList_DragMove(pt.x, pt.y);
+ }
+ dat->bDragged = TRUE;
+ return 0;
+ }
+ }
+ break;
+
+ case EM_UNSUBCLASSED:
+ mir_free(dat);
+ return 0;
+ }
+ return mir_callNextSubclass(hwnd, TabCtrlProc, msg, wParam, lParam);
+}
+
+__forceinline void SubclassTabCtrl(HWND hwnd)
+{
+ mir_subclassWindow(hwnd, TabCtrlProc);
+ SendMessage(hwnd, EM_SUBCLASSED, 0, 0);
+}
+
+__forceinline void UnsubclassTabCtrl(HWND hwnd)
+{
+ SendMessage(hwnd, EM_UNSUBCLASSED, 0, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int ScriverRestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags, int showCmd)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwnd, &wp);
+
+ char szSettingName[64];
+ mir_snprintf(szSettingName, "%sx", szNamePrefix);
+ int x = db_get_dw(hContact, szModule, szSettingName, -1);
+ mir_snprintf(szSettingName, "%sy", szNamePrefix);
+ int y = db_get_dw(hContact, szModule, szSettingName, -1);
+ if (x == -1)
+ return 1;
+
+ if (flags & RWPF_NOSIZE)
+ OffsetRect(&wp.rcNormalPosition, x - wp.rcNormalPosition.left, y - wp.rcNormalPosition.top);
+ else {
+ wp.rcNormalPosition.left = x;
+ wp.rcNormalPosition.top = y;
+ mir_snprintf(szSettingName, "%swidth", szNamePrefix);
+ wp.rcNormalPosition.right = wp.rcNormalPosition.left + db_get_dw(hContact, szModule, szSettingName, -1);
+ mir_snprintf(szSettingName, "%sheight", szNamePrefix);
+ wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + db_get_dw(hContact, szModule, szSettingName, -1);
+ }
+ wp.flags = 0;
+ wp.showCmd = showCmd;
+
+ HMONITOR hMonitor = MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+ RECT rcDesktop = mi.rcWork;
+ if (wp.rcNormalPosition.left > rcDesktop.right || wp.rcNormalPosition.top > rcDesktop.bottom ||
+ wp.rcNormalPosition.right < rcDesktop.left || wp.rcNormalPosition.bottom < rcDesktop.top) return 1;
+ SetWindowPlacement(hwnd, &wp);
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcParentWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ParentWindowData *dat = (ParentWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (!dat && msg != WM_INITDIALOG)
+ return FALSE;
+
+ DWORD ws;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ int savePerContact = db_get_b(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT);
+ NewMessageWindowLParam *newData = (NewMessageWindowLParam *)lParam;
+ dat = (ParentWindowData *)mir_alloc(sizeof(ParentWindowData));
+ dat->hContact = newData->hContact;
+ dat->nFlash = 0;
+ dat->nFlashMax = db_get_b(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT);
+ dat->childrenCount = 0;
+ dat->hwnd = hwndDlg;
+ dat->mouseLBDown = 0;
+ dat->windowWasCascaded = 0;
+ dat->bMinimized = 0;
+ dat->bVMaximized = 0;
+ dat->flags2 = g_dat.flags2;
+ dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL);
+ dat->isChat = newData->isChat;
+ SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
+ //SetupStatusBar(dat);
+ dat->hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
+ dat->hwndActive = NULL;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ if (g_dat.hTabIconList != NULL)
+ TabCtrl_SetImageList(dat->hwndTabs, g_dat.hTabIconList);
+
+ dat->next = NULL;
+ if (!newData->isChat) {
+ dat->prev = g_dat.lastParent;
+ g_dat.lastParent = dat;
+ }
+ else {
+ dat->prev = g_dat.lastChatParent;
+ g_dat.lastChatParent = dat;
+ }
+ if (dat->prev != NULL)
+ dat->prev->next = dat;
+
+ WindowList_Add(g_dat.hParentWindowList, hwndDlg, (UINT_PTR)hwndDlg);
+ SubclassTabCtrl(dat->hwndTabs);
+
+ SetContainerWindowStyle(dat);
+
+ MCONTACT hSContact = savePerContact ? dat->hContact : NULL;
+ dat->bTopmost = db_get_b(hSContact, SRMMMOD, SRMSGSET_TOPMOST, SRMSGDEFSET_TOPMOST);
+ if (ScriverRestoreWindowPosition(hwndDlg, hSContact, SRMMMOD, (newData->isChat && !savePerContact) ? "chat" : "", 0, SW_HIDE))
+ SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_HIDEWINDOW);
+
+ if (!savePerContact && db_get_b(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE))
+ WindowList_Broadcast(g_dat.hParentWindowList, DM_CASCADENEWWINDOW, (WPARAM)hwndDlg, (LPARAM)&dat->windowWasCascaded);
+
+ HMENU hMenu = GetSystemMenu(hwndDlg, FALSE);
+ InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
+ if (dat->bTopmost) {
+ InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED | MF_CHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always on top"));
+ SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+ else InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always on top"));
+ }
+ return TRUE;
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO *mmi = (MINMAXINFO *)lParam;
+ if (dat->bVMaximized) {
+ MONITORINFO mi;
+ HMONITOR hMonitor;
+ WINDOWPLACEMENT wp;
+ RECT rcDesktop;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwndDlg, &wp);
+ hMonitor = MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST);
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+ rcDesktop = mi.rcWork;
+
+ mmi->ptMaxSize.x = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
+ mmi->ptMaxSize.y = rcDesktop.bottom - rcDesktop.top;
+ mmi->ptMaxPosition.x = wp.rcNormalPosition.left;
+ if (IsIconic(hwndDlg))
+ mmi->ptMaxPosition.y = rcDesktop.top;
+ else
+ mmi->ptMaxPosition.y = 0;
+ }
+ SIZE size;
+ GetMinimunWindowSize(dat, &size);
+ mmi->ptMinTrackSize.x = size.cx;
+ mmi->ptMinTrackSize.y = size.cy;
+ }
+ return FALSE;
+
+ case WM_SIZE:
+ if (wParam == SIZE_MINIMIZED)
+ dat->bMinimized = 1;
+
+ if (IsIconic(hwndDlg))
+ MoveWindow(dat->hwndActive, dat->childRect.left, dat->childRect.top, dat->childRect.right - dat->childRect.left, dat->childRect.bottom - dat->childRect.top, TRUE);
+ else {
+ RECT rcStatus, rcChild, rcWindow, rc;
+ SIZE size;
+ dat->bMinimized = 0;
+ GetClientRect(hwndDlg, &rc);
+ GetWindowRect(hwndDlg, &rcWindow);
+ rcStatus.top = rcStatus.bottom = 0;
+ if (dat->flags2 & SMF2_SHOWSTATUSBAR) {
+ GetWindowRect(dat->hwndStatus, &rcStatus);
+ SetupStatusBar(dat);
+ }
+ MoveWindow(dat->hwndTabs, 0, 2, (rc.right - rc.left), (rc.bottom - rc.top) - (rcStatus.bottom - rcStatus.top) - 2, FALSE);
+ RedrawWindow(dat->hwndTabs, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE);
+ GetMinimunWindowSize(dat, &size);
+ if ((rcWindow.bottom - rcWindow.top) < size.cy || (rcWindow.right - rcWindow.left) < size.cx) {
+ if ((rcWindow.bottom - rcWindow.top) < size.cy)
+ rcWindow.bottom = rcWindow.top + size.cy;
+ if ((rcWindow.right - rcWindow.left) < size.cx)
+ rcWindow.right = rcWindow.left + size.cx;
+ MoveWindow(hwndDlg, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
+ }
+ GetChildWindowRect(dat, &rcChild);
+ memcpy(&dat->childRect, &rcChild, sizeof(RECT));
+ MoveWindow(dat->hwndActive, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, TRUE);
+ RedrawWindow(GetDlgItem(dat->hwndActive, IDC_LOG), NULL, NULL, RDW_INVALIDATE);
+ if (dat->flags2 & SMF2_SHOWSTATUSBAR) {
+ SendMessage(dat->hwndStatus, WM_SIZE, 0, 0);
+ RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
+ }
+ }
+ return FALSE;
+
+ case WM_SETFOCUS:
+ if (dat->hwndActive != NULL)
+ SetFocus(dat->hwndActive);
+ return TRUE;
+
+ case WM_CLOSE:
+ if (g_dat.flags2 & SMF2_HIDECONTAINERS && dat->childrenCount > 0)
+ ShowWindow(hwndDlg, SW_HIDE);
+ else
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case WM_MEASUREITEM:
+ return Menu_MeasureItem(lParam);
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
+ if (dat && dat->hwndActive && dis->hwndItem == dat->hwndStatus) {
+ MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive);
+ if (mwtd != NULL)
+ DrawStatusIcons(mwtd->hContact, dis->hDC, dis->rcItem, 2);
+ return TRUE;
+ }
+ if (dis->hwndItem == dat->hwndTabs) {
+ DrawTab(dat, dat->hwndTabs, wParam, lParam);
+ return TRUE;
+ }
+ }
+ return Menu_DrawItem(lParam);
+
+ case WM_COMMAND:
+ if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
+ break;
+
+ if (LOWORD(wParam) == IDCANCEL)
+ return TRUE;
+ break;
+
+ case WM_NOTIFY:
+ {
+ NMHDR *pNMHDR = (NMHDR*)lParam;
+ if (pNMHDR->hwndFrom == dat->hwndTabs) {
+ switch (pNMHDR->code) {
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci = { 0 };
+ int iSel = TabCtrl_GetCurSel(dat->hwndTabs);
+ tci.mask = TCIF_PARAM;
+ if (TabCtrl_GetItem(dat->hwndTabs, iSel, &tci)) {
+ MessageWindowTabData * mwtd = (MessageWindowTabData *)tci.lParam;
+ ActivateChild(dat, mwtd->hwnd);
+ SetFocus(dat->hwndActive);
+ }
+ }
+ break;
+
+ case NM_RCLICK:
+ TCHITTESTINFO thinfo;
+ GetCursorPos(&thinfo.pt);
+
+ int x = thinfo.pt.x;
+ int y = thinfo.pt.y;
+ ScreenToClient(dat->hwndTabs, &thinfo.pt);
+ int tabId = TabCtrl_HitTest(dat->hwndTabs, &thinfo);
+ if (tabId != -1) {
+ MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, tabId);
+ HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ HMENU hSubMenu = GetSubMenu(hMenu, 3);
+ TranslateMenu(hSubMenu);
+ HMENU hUserMenu = (HMENU)SendMessage(mwtd->hwnd, DM_GETCONTEXTMENU, 0, 0);
+ if (hUserMenu != NULL) {
+ InsertMenu(hSubMenu, 0, MF_POPUP | MF_BYPOSITION, (UINT_PTR)hUserMenu, TranslateT("User menu"));
+ InsertMenu(hSubMenu, 1, MF_SEPARATOR | MF_BYPOSITION, 0, 0);
+ }
+ BOOL menuResult = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, x, y, 0, hwndDlg, NULL);
+ switch (menuResult) {
+ case IDM_CLOSETAB:
+ SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0);
+ break;
+ case IDM_CLOSEOTHERTABS:
+ CloseOtherChilden(dat, mwtd->hwnd);
+ break;
+ default:
+ Clist_MenuProcessCommand(LOWORD(menuResult), MPCF_CONTACTMENU, mwtd->hContact);
+ }
+ if (hUserMenu != NULL)
+ DestroyMenu(hUserMenu);
+ DestroyMenu(hMenu);
+ }
+ }
+ break;
+ }
+ else if (pNMHDR->hwndFrom == dat->hwndStatus) {
+ switch (pNMHDR->code) {
+ case NM_CLICK:
+ RECT rc;
+ NMMOUSE *nm = (NMMOUSE*)lParam;
+ SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 2, (LPARAM)&rc);
+ if (nm->pt.x >= rc.left) {
+ MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive);
+ if (mwtd != NULL)
+ CheckStatusIconClick(mwtd->hContact, dat->hwndStatus, nm->pt, rc, 2, (pNMHDR->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0));
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+
+ case WM_DROPFILES:
+ SendMessage(dat->hwndActive, WM_DROPFILES, wParam, lParam);
+ break;
+
+ case WM_TIMER:
+ if (wParam == TIMERID_FLASHWND) {
+ if (dat->nFlash < 2 * dat->nFlashMax) {
+ FlashWindow(hwndDlg, TRUE);
+ dat->nFlash++;
+ }
+ else {
+ KillTimer(hwndDlg, TIMERID_FLASHWND);
+ FlashWindow(hwndDlg, FALSE);
+ }
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ if (dat->hwndStatus && dat->hwndStatus == (HWND)wParam) {
+ POINT pt, pt2;
+ GetCursorPos(&pt);
+ pt2 = pt;
+ ScreenToClient(dat->hwndStatus, &pt);
+
+ RECT rc;
+ SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 2, (LPARAM)&rc);
+ if (pt.x >= rc.left) {
+ MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive);
+ if (mwtd != NULL)
+ CheckStatusIconClick(mwtd->hContact, dat->hwndStatus, pt, rc, 2, MBCF_RIGHTBUTTON);
+ break;
+ }
+ else SendMessage(dat->hwndActive, WM_CONTEXTMENU, (WPARAM)hwndDlg, 0);
+ }
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE) {
+ ws = GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
+ ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0;
+ SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, ws);
+ if (dat->flags2 & SMF2_USETRANSPARENCY)
+ SetLayeredWindowAttributes(hwndDlg, RGB(255, 255, 255), (BYTE)(255 - g_dat.inactiveAlpha), LWA_ALPHA);
+ break;
+ }
+ if (dat->hwndActive != NULL) {
+ ActivateChild(dat, dat->hwndActive);
+ g_dat.hFocusWnd = dat->hwndActive;
+ PostMessage(dat->hwndActive, DM_SETFOCUS, 0, msg);
+ }
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND)) {
+ FlashWindow(hwndDlg, FALSE);
+ dat->nFlash = 0;
+ }
+ ws = GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
+ ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0;
+ SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, ws);
+ if (dat->flags2 & SMF2_USETRANSPARENCY)
+ SetLayeredWindowAttributes(hwndDlg, RGB(255, 255, 255), (BYTE)(255 - g_dat.activeAlpha), LWA_ALPHA);
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (!IsZoomed(hwndDlg)) {
+ POINT pt;
+ GetCursorPos(&pt);
+ return SendMessage(hwndDlg, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y));
+ }
+ break;
+
+ case WM_MOVING:
+ if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
+ int snapPixels = 10;
+ RECT *pRect = (RECT *)lParam;
+ HMONITOR hMonitor = MonitorFromRect(pRect, MONITOR_DEFAULTTONEAREST);
+ SIZE szSize = { pRect->right - pRect->left, pRect->bottom - pRect->top };
+
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+
+ POINT pt;
+ GetCursorPos(&pt);
+
+ RECT rcDesktop = mi.rcWork;
+ pRect->left = pt.x - dat->mouseLBDownPos.x;
+ pRect->top = pt.y - dat->mouseLBDownPos.y;
+ pRect->right = pRect->left + szSize.cx;
+ pRect->bottom = pRect->top + szSize.cy;
+ if (pRect->top < rcDesktop.top + snapPixels && pRect->top > rcDesktop.top - snapPixels) {
+ pRect->top = rcDesktop.top;
+ pRect->bottom = rcDesktop.top + szSize.cy;
+ }
+ if (pRect->left < rcDesktop.left + snapPixels && pRect->left > rcDesktop.left - snapPixels) {
+ pRect->left = rcDesktop.left;
+ pRect->right = rcDesktop.left + szSize.cx;
+ }
+ if (pRect->right < rcDesktop.right + snapPixels && pRect->right > rcDesktop.right - snapPixels) {
+ pRect->right = rcDesktop.right;
+ pRect->left = rcDesktop.right - szSize.cx;
+ }
+ if (pRect->bottom < rcDesktop.bottom + snapPixels && pRect->bottom > rcDesktop.bottom - snapPixels) {
+ pRect->bottom = rcDesktop.bottom;
+ pRect->top = rcDesktop.bottom - szSize.cy;
+ }
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ if ((wParam & 0xFFF0) == SC_MAXIMIZE) {
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ dat->bVMaximized = 1;
+ else
+ dat->bVMaximized = 0;
+ }
+ else if ((wParam & 0xFFF0) == SC_MOVE) {
+ RECT rc;
+ GetWindowRect(hwndDlg, &rc);
+ dat->mouseLBDownPos.x = LOWORD(lParam) - rc.left;
+ dat->mouseLBDownPos.y = HIWORD(lParam) - rc.top;
+ }
+ else if (wParam == IDM_TOPMOST) {
+ HMENU hMenu = GetSystemMenu(hwndDlg, FALSE);
+ if (dat->bTopmost) {
+ CheckMenuItem(hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_UNCHECKED);
+ SetWindowPos(hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ dat->bTopmost = FALSE;
+ }
+ else {
+ CheckMenuItem(hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_CHECKED);
+ SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ dat->bTopmost = TRUE;
+ }
+ }
+ break;
+ case WM_DESTROY:
+ char szSettingName[64];
+
+ for (int i = dat->childrenCount; i >= 0; i--) {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM | TCIF_IMAGE;
+ if (TabCtrl_GetItem(dat->hwndTabs, i, &tci)) {
+ mir_free((MessageWindowTabData *)tci.lParam);
+ ReleaseIcon(tci.iImage);
+ TabCtrl_DeleteItem(dat->hwndTabs, i);
+ }
+ }
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ WindowList_Remove(g_dat.hParentWindowList, hwndDlg);
+ {
+ int savePerContact = db_get_b(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT);
+ MCONTACT hContact = (savePerContact) ? dat->hContact : NULL;
+
+ WINDOWPLACEMENT wp = { sizeof(wp) };
+ GetWindowPlacement(hwndDlg, &wp);
+
+ char *szNamePrefix = (!savePerContact && dat->isChat) ? "chat" : "";
+ if (!dat->windowWasCascaded) {
+ mir_snprintf(szSettingName, "%sx", szNamePrefix);
+ db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.left);
+ mir_snprintf(szSettingName, "%sy", szNamePrefix);
+ db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.top);
+ }
+ mir_snprintf(szSettingName, "%swidth", szNamePrefix);
+ db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.right - wp.rcNormalPosition.left);
+ mir_snprintf(szSettingName, "%sheight", szNamePrefix);
+ db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
+ db_set_b(hContact, SRMMMOD, SRMSGSET_TOPMOST, (BYTE)dat->bTopmost);
+ if (g_dat.lastParent == dat)
+ g_dat.lastParent = dat->prev;
+
+ if (g_dat.lastChatParent == dat)
+ g_dat.lastChatParent = dat->prev;
+
+ if (dat->prev != NULL)
+ dat->prev->next = dat->next;
+
+ if (dat->next != NULL)
+ dat->next->prev = dat->prev;
+
+ UnsubclassTabCtrl(dat->hwndTabs);
+ mir_free(dat);
+ }
+ break;
+
+ case DM_ERRORDECIDED:
+ break;
+
+ case CM_STARTFLASHING:
+ if ((GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg)) {// && !(g_dat.flags2 & SMF2_STAYMINIMIZED)) {
+ dat->nFlash = 0;
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ break;
+
+ case CM_POPUPWINDOW:
+ EnableWindow(hwndDlg, TRUE);
+ if (wParam) { /* incoming message */
+ if (g_dat.flags & SMF_STAYMINIMIZED) {
+ if (!IsWindowVisible(hwndDlg))
+ ShowWindow(hwndDlg, SW_SHOWMINNOACTIVE);
+
+ if (dat->childrenCount == 1 || ((g_dat.flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(hwndDlg) || GetForegroundWindow() != hwndDlg)))
+ SendMessage(hwndDlg, CM_ACTIVATECHILD, 0, (LPARAM)lParam);
+ }
+ else {
+ ShowWindow(hwndDlg, IsIconic(hwndDlg) ? SW_SHOWNORMAL : SW_SHOWNA);
+
+ if (dat->childrenCount == 1 || ((g_dat.flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(hwndDlg) || GetForegroundWindow() != hwndDlg)))
+ SendMessage(hwndDlg, CM_ACTIVATECHILD, 0, (LPARAM)lParam);
+
+ SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+ }
+ }
+ else { /* outgoing message */
+ ShowWindow(hwndDlg, IsIconic(hwndDlg) ? SW_SHOWNORMAL : SW_SHOW);
+ SetForegroundWindow(hwndDlg);
+ SetFocus((HWND)lParam);
+ }
+ break;
+
+ case CM_REMOVECHILD:
+ RemoveChild(dat, (HWND)lParam);
+ if (dat->childrenCount != 0)
+ SetFocus(dat->hwndActive);
+ else
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ return TRUE;
+
+ case CM_ADDCHILD:
+ AddChild(dat, (HWND)wParam, lParam);
+ return TRUE;
+
+ case CM_ACTIVATECHILD:
+ ActivateChild(dat, (HWND)lParam);
+ return TRUE;
+
+ case CM_ACTIVATEPREV:
+ ActivatePrevChild(dat, (HWND)lParam);
+ SetFocus(dat->hwndActive);
+ return TRUE;
+
+ case CM_ACTIVATENEXT:
+ ActivateNextChild(dat, (HWND)lParam);
+ SetFocus(dat->hwndActive);
+ return TRUE;
+
+ case CM_ACTIVATEBYINDEX:
+ ActivateChildByIndex(dat, (int)lParam);
+ SetFocus(dat->hwndActive);
+ return TRUE;
+
+ case CM_GETCHILDCOUNT:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetChildCount(dat));
+ return TRUE;
+
+ case CM_GETACTIVECHILD:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)dat->hwndActive);
+ return TRUE;
+
+ case CM_GETTOOLBARSTATUS:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(dat->flags2 & SMF2_SHOWTOOLBAR) != 0);
+ return TRUE;
+
+ case DM_SENDMESSAGE:
+ for (int i = 0; i < dat->childrenCount; i++) {
+ MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i);
+ SendMessage(mwtd->hwnd, DM_SENDMESSAGE, wParam, lParam);
+ }
+ break;
+
+ case DM_OPTIONSAPPLIED:
+ dat->flags2 = g_dat.flags2;
+ SetContainerWindowStyle(dat);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case CM_UPDATETITLEBAR:
+ {
+ HWND hwnd = (HWND)lParam;
+ TitleBarData *tbd = (TitleBarData *)wParam;
+ if (tbd != NULL && dat->hwndActive == hwnd) {
+ if (tbd->iFlags & TBDF_TEXT) {
+ wchar_t oldtitle[256];
+ GetWindowText(hwndDlg, oldtitle, _countof(oldtitle));
+ if (mir_wstrcmp(tbd->pszText, oldtitle))
+ SetWindowText(hwndDlg, tbd->pszText);
+ }
+ if (tbd->iFlags & TBDF_ICON) {
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)tbd->hIcon);
+ if (tbd->hIconBig != NULL)
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)tbd->hIconBig);
+ if (pTaskbarInterface)
+ pTaskbarInterface->SetOverlayIcon(hwndDlg, tbd->hIconNot, L"");
+ }
+ }
+ }
+ break;
+
+ case CM_UPDATESTATUSBAR:
+ {
+ HWND hwnd = (HWND)lParam;
+ StatusBarData *sbd = (StatusBarData *)wParam;
+ if (sbd != NULL) {
+ if ((sbd->iFlags & SBDF_TEXT) && dat->hwndActive == hwnd)
+ SendMessage(dat->hwndStatus, SB_SETTEXT, sbd->iItem, (LPARAM)sbd->pszText);
+ if ((sbd->iFlags & SBDF_ICON) && dat->hwndActive == hwnd)
+ SendMessage(dat->hwndStatus, SB_SETICON, sbd->iItem, (LPARAM)sbd->hIcon);
+ RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+ }
+ break;
+
+ case DM_STATUSICONCHANGE:
+ SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0);
+ SetupStatusBar(dat);
+ RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
+ break;
+
+ case CM_UPDATETABCONTROL:
+ {
+ TabControlData *tcd = (TabControlData*)wParam;
+ int tabId = GetTabFromHWND(dat, (HWND)lParam);
+ if (tabId >= 0 && tcd != NULL) {
+ wchar_t *ptszTemp = NULL;
+
+ TCITEM tci;
+ tci.mask = 0;
+ if (tcd->iFlags & TCDF_TEXT) {
+ tci.mask |= TCIF_TEXT;
+ tci.pszText = tcd->pszText;
+ if (g_dat.flags2 & SMF2_LIMITNAMES) {
+ wchar_t *ltext = limitText(tcd->pszText, g_dat.limitNamesLength);
+ if (ltext != tcd->pszText)
+ tci.pszText = ptszTemp = ltext;
+ }
+ }
+ if (tcd->iFlags & TCDF_ICON) {
+ int iconIdx = -1;
+ if (tcd->hIcon != NULL) {
+ TCITEM tci2;
+ tci2.mask = TCIF_IMAGE;
+ TabCtrl_GetItem(dat->hwndTabs, tabId, &tci2);
+ iconIdx = AddOrReplaceIcon(g_dat.hTabIconList, tci2.iImage, tcd->hIcon);
+ }
+ tci.mask |= TCIF_IMAGE;
+ tci.iImage = iconIdx;
+ }
+ TabCtrl_SetItem(dat->hwndTabs, tabId, &tci);
+ mir_free(ptszTemp);
+ }
+ }
+ break;
+
+ case DM_SWITCHINFOBAR:
+ dat->flags2 ^= SMF2_SHOWINFOBAR;
+
+ for (int i = 0; i < dat->childrenCount; i++) {
+ MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i);
+ SendMessage(mwtd->hwnd, DM_SWITCHINFOBAR, 0, 0);
+ }
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case DM_SWITCHSTATUSBAR:
+ dat->flags2 ^= SMF2_SHOWSTATUSBAR;
+ ShowWindow(dat->hwndStatus, (dat->flags2 & SMF2_SHOWSTATUSBAR) ? SW_SHOW : SW_HIDE);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case DM_SWITCHTOOLBAR:
+ dat->flags2 ^= SMF2_SHOWTOOLBAR;
+
+ for (int i = 0; i < dat->childrenCount; i++) {
+ MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i);
+ SendMessage(mwtd->hwnd, DM_SWITCHTOOLBAR, 0, 0);
+ }
+
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case DM_SWITCHTITLEBAR:
+ dat->flags2 ^= SMF2_SHOWTITLEBAR;
+ ws = GetWindowLongPtr(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
+ if (dat->flags2 & SMF2_SHOWTITLEBAR)
+ ws |= WS_CAPTION;
+
+ SetWindowLongPtr(hwndDlg, GWL_STYLE, ws);
+ RECT rc;
+ GetWindowRect(hwndDlg, &rc);
+ SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING);
+ RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+ break;
+
+ case DM_CASCADENEWWINDOW:
+ if ((HWND)wParam != hwndDlg) {
+ RECT rcThis, rcNew;
+ GetWindowRect(hwndDlg, &rcThis);
+ GetWindowRect((HWND)wParam, &rcNew);
+ if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) {
+ int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
+ SetWindowPos((HWND)wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+ *(int *)lParam = 1;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static void DrawTab(ParentWindowData *dat, HWND hwnd, WPARAM, LPARAM lParam)
+{
+ LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
+ int iTabIndex = lpDIS->itemID;
+ if (iTabIndex < 0)
+ return;
+
+ TabCtrlData *tcdat = (TabCtrlData*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ HANDLE hTheme = NULL;
+ int tstate = 0;
+ wchar_t szLabel[1024];
+ TCITEM tci;
+ tci.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE;
+ tci.pszText = szLabel;
+ tci.cchTextMax = _countof(szLabel);
+ tci.dwStateMask = TCIS_HIGHLIGHTED;
+ if (TabCtrl_GetItem(hwnd, iTabIndex, &tci)) {
+ IMAGEINFO info;
+ RECT rIcon = lpDIS->rcItem;
+ RECT rect = lpDIS->rcItem;
+ RECT rectTab = lpDIS->rcItem;
+ int bSelected = lpDIS->itemState & ODS_SELECTED;
+ int atTop = (GetWindowLongPtr(hwnd, GWL_STYLE) & TCS_BOTTOM) == 0;
+ UINT dwFormat;
+ if (!IsAppThemed())
+ FillRect(lpDIS->hDC, &rect, GetSysColorBrush(COLOR_BTNFACE));
+ else {
+ if (lpDIS->itemState & ODS_SELECTED)
+ tstate = TTIS_SELECTED;
+ else if (lpDIS->itemState & ODS_FOCUS)
+ tstate = TTIS_FOCUSED;
+ else if (lpDIS->itemState & ODS_HOTLIGHT)
+ tstate = TTIS_HOT;
+ else
+ tstate = TTIS_NORMAL;
+
+ if (!bSelected)
+ InflateRect(&rectTab, 1, 1);
+
+ hTheme = OpenThemeData(hwnd, L"TAB");
+ if (IsThemeBackgroundPartiallyTransparent(hTheme, TABP_TABITEM, tstate))
+ DrawThemeParentBackground(hwnd, lpDIS->hDC, &rectTab);
+ DrawThemeBackground(hTheme, lpDIS->hDC, TABP_TABITEM, tstate, &rectTab, NULL);
+ }
+ if (atTop) {
+ dwFormat = DT_SINGLELINE | DT_TOP | DT_CENTER | DT_NOPREFIX | DT_NOCLIP;
+ rIcon.top = rect.top + GetSystemMetrics(SM_CYEDGE);
+ if (tci.iImage >= 0) {
+ rIcon.left = rect.left + GetSystemMetrics(SM_CXEDGE) + (bSelected ? 6 : 2);
+ ImageList_GetImageInfo(g_dat.hTabIconList, tci.iImage, &info);
+ ImageList_DrawEx(g_dat.hTabIconList, tci.iImage, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rect.left = rIcon.left + (info.rcImage.right - info.rcImage.left);
+ }
+ if (dat->flags2 & SMF2_TABCLOSEBUTTON) {
+ ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info);
+ rIcon.left = rect.right - GetSystemMetrics(SM_CXEDGE) - (bSelected ? 6 : 2) - (info.rcImage.right - info.rcImage.left);
+ ImageList_DrawEx(g_dat.hButtonIconList, 0, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rect.right = rIcon.left - 1;
+ }
+ rect.top += GetSystemMetrics(SM_CYEDGE) + 2;
+ }
+ else {
+ dwFormat = DT_SINGLELINE | DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_NOCLIP;
+ rIcon.left = rect.left + GetSystemMetrics(SM_CXEDGE) + (bSelected ? 6 : 2);
+ if (tci.iImage >= 0) {
+ ImageList_GetImageInfo(g_dat.hTabIconList, tci.iImage, &info);
+ rIcon.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top) - 1;
+ ImageList_DrawEx(g_dat.hTabIconList, tci.iImage, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rect.left = rIcon.left + (info.rcImage.right - info.rcImage.left);
+ }
+ if (dat->flags2 & SMF2_TABCLOSEBUTTON) {
+ ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info);
+ rIcon.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top) - 2;
+ rIcon.left = rect.right - GetSystemMetrics(SM_CXEDGE) - (bSelected ? 6 : 2) - (info.rcImage.right - info.rcImage.left);
+ ImageList_DrawEx(g_dat.hButtonIconList, 0, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rect.right = rIcon.left - 1;
+ }
+ rect.bottom -= GetSystemMetrics(SM_CYEDGE) + 2;
+ }
+
+ if (hTheme)
+ DrawThemeText(hTheme, lpDIS->hDC, TABP_TABITEM, tstate, szLabel, -1, dwFormat, 0, &rect);
+ else
+ DrawText(lpDIS->hDC, szLabel, -1, &rect, dwFormat);
+
+ if (tcdat->bDragged && iTabIndex == tcdat->destTab && iTabIndex != tcdat->srcTab) {
+ RECT hlRect = lpDIS->rcItem;
+ if (bSelected) {
+ hlRect.bottom -= GetSystemMetrics(SM_CYEDGE);
+ hlRect.top += GetSystemMetrics(SM_CYEDGE);
+ hlRect.left += GetSystemMetrics(SM_CXEDGE);
+ hlRect.right -= GetSystemMetrics(SM_CXEDGE);
+ }
+ else {
+ if (atTop) {
+ hlRect.top += GetSystemMetrics(SM_CYEDGE);
+ hlRect.bottom += GetSystemMetrics(SM_CYEDGE);
+ }
+ else {
+ hlRect.top -= GetSystemMetrics(SM_CYEDGE);
+ hlRect.bottom -= GetSystemMetrics(SM_CYEDGE);
+ }
+ }
+ FrameRect(lpDIS->hDC, &hlRect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ hlRect.left++;
+ hlRect.top++;
+ hlRect.right--;
+ hlRect.bottom--;
+ FrameRect(lpDIS->hDC, &hlRect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
+ if (hTheme)
+ CloseThemeData(hTheme);
+ }
+}
+
+HWND GetParentWindow(MCONTACT hContact, BOOL bChat)
+{
+ NewMessageWindowLParam newData = { 0 };
+ newData.hContact = hContact;
+ newData.isChat = bChat;
+ if (g_dat.flags2 & SMF2_USETABS) {
+ if (!bChat || !(g_dat.flags2 & SMF2_SEPARATECHATSCONTAINERS)) {
+ if (g_dat.lastParent != NULL) {
+ int tabsNum = (int)SendMessage(g_dat.lastParent->hwnd, CM_GETCHILDCOUNT, 0, 0);
+ if (!(g_dat.flags2 & SMF2_LIMITTABS) || tabsNum < g_dat.limitTabsNum)
+ return g_dat.lastParent->hwnd;
+ }
+ }
+ else {
+ if (g_dat.lastChatParent != NULL) {
+ int tabsNum = (int)SendMessage(g_dat.lastChatParent->hwnd, CM_GETCHILDCOUNT, 0, 0);
+ if (!(g_dat.flags2 & SMF2_LIMITCHATSTABS) || tabsNum < g_dat.limitChatsTabsNum) {
+ return g_dat.lastChatParent->hwnd;
+ }
+ }
+ }
+ }
+ if (!(g_dat.flags2 & SMF2_SEPARATECHATSCONTAINERS))
+ newData.isChat = FALSE;
+
+ return CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGWIN), NULL, DlgProcParentWindow, (LPARAM)&newData);
+}