summaryrefslogtreecommitdiff
path: root/justtabs/win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'justtabs/win.cpp')
-rw-r--r--justtabs/win.cpp683
1 files changed, 683 insertions, 0 deletions
diff --git a/justtabs/win.cpp b/justtabs/win.cpp
new file mode 100644
index 0000000..75cb408
--- /dev/null
+++ b/justtabs/win.cpp
@@ -0,0 +1,683 @@
+#include "win.h"
+#include "options.h"
+
+HWND pluginwind = 0;
+bool first_show = true;
+
+HWND tab_ctrl;
+HIMAGELIST clist_imagelist;
+HWND active_window;
+int message_icon_index = 0;
+
+#ifdef _WIN32
+#define STATUSCLASSNAMEW L"msctls_statusbar32"
+#define STATUSCLASSNAMEA "msctls_statusbar32"
+
+#ifdef UNICODE
+#define STATUSCLASSNAME STATUSCLASSNAMEW
+#else
+#define STATUSCLASSNAME STATUSCLASSNAMEA
+#endif
+
+#else
+#define STATUSCLASSNAME "msctls_statusbar"
+#endif
+
+#define EM_SUBCLASSED (WM_USER+0x101)
+#define EM_UNSUBCLASSED (WM_USER+0x102)
+
+#define WMU_SETTAB (WM_USER+0x300)
+
+HANDLE window_list = 0;
+
+typedef struct TabCtrlDataStruct
+{
+ int lastClickTime;
+ WPARAM clickWParam;
+ LPARAM clickLParam;
+ POINT mouseLBDownPos;
+ int lastClickTab;
+ HIMAGELIST hDragImageList;
+ int bDragging;
+ int bDragged;
+ int destTab;
+ int srcTab;
+} TabCtrlData;
+
+typedef struct {
+ POINT p;
+ bool moving;
+} WindowData;
+
+typedef struct {
+ HWND hwndMsg;
+ HANDLE hContact;
+} TabData;
+
+int GetTabFromHWND(HWND tabs, HWND child)
+{
+ TCITEM tci;
+ int l, i;
+ l = TabCtrl_GetItemCount(tabs);
+ for (i = 0; i < l; i++) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(tabs, i, &tci);
+ if (((TabData *) tci.lParam)->hwndMsg == child) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int GetTabFromContact(HWND tabs, HANDLE hContact)
+{
+ TCITEM tci;
+ int l, i;
+ l = TabCtrl_GetItemCount(tabs);
+ for (i = 0; i < l; i++) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(tabs, i, &tci);
+ if (((TabData *) tci.lParam)->hContact == hContact) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+static WNDPROC OldTabCtrlProc;
+BOOL CALLBACK TabCtrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void SubclassTabCtrl(HWND hwnd) {
+ OldTabCtrlProc = (WNDPROC) SetWindowLong(hwnd, GWL_WNDPROC, (LONG) TabCtrlProc);
+ SendMessage(hwnd, EM_SUBCLASSED, 0, 0);
+}
+
+void UnsubclassTabCtrl(HWND hwnd) {
+ SendMessage(hwnd, EM_UNSUBCLASSED, 0, 0);
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG) OldTabCtrlProc);
+}
+
+//LRESULT CALLBACK FrameProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+BOOL CALLBACK FrameProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+
+ //case WM_CREATE:
+ case WM_INITDIALOG:
+ {
+ WindowData *data = new WindowData;
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG)data);
+ data->moving = false;
+
+ RECT r;
+ GetClientRect(hwnd, &r);
+ //tab_imagelist = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 0, 1);
+ //ImageList_AddIcon(tab_imagelist, LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+ //HICON hIconMsg = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ //ImageList_AddIcon(tab_imagelist, hIconMsg);
+
+ //tab_ctrl = CreateWindow(WC_TABCONTROL, "", WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | TCS_MULTILINE | TCS_FOCUSNEVER, 0, 0, r.right, r.bottom, hwnd, NULL, NULL, NULL);
+ tab_ctrl = GetDlgItem(hwnd, IDC_TABS);
+ //TabCtrl_SetImageList(tab_ctrl, tab_imagelist);
+
+ TabCtrl_SetImageList(tab_ctrl, clist_imagelist);
+
+ LOGFONT lf;
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, FALSE);
+ lf.lfHeight = -12;
+ HFONT hFont = CreateFontIndirect(&lf);
+ SendMessage(tab_ctrl, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
+
+ SubclassTabCtrl(tab_ctrl);
+ active_window = 0;
+ return FALSE;
+ }
+
+ case WM_SHOWWINDOW:
+ if((BOOL)wParam == TRUE && first_show) {
+ first_show = false;
+ Utils_RestoreWindowPosition(hwnd, 0, MODULE, "MainWin");
+ }
+ break;
+
+ case WM_SIZE:
+ {
+ RECT rc;
+
+ // Calculate the display rectangle, assuming the
+ // tab control is the size of the client area.
+ GetClientRect(hwnd, &rc);
+
+ // Size the tab control to fit the client area.
+ //SetWindowPos(tab_ctrl, NULL, 0, 5, rc.right + 3, rc.bottom + 3, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ rc.top += 2;
+ rc.right += 2;
+ rc.bottom += 2;
+
+ MoveWindow(tab_ctrl, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
+ RedrawWindow(tab_ctrl, 0, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE);
+
+ TabCtrl_AdjustRect(tab_ctrl, FALSE, &rc);
+ // Position and size the static control to fit the
+ // tab control's display area, and make sure the
+ // static control is in front of the tab control.
+ if(active_window)
+ SetWindowPos(active_window, HWND_TOP, rc.left - 3, rc.top - 1, rc.right - rc.left + 4, rc.bottom - rc.top + 2, 0);
+ }
+
+ break;
+
+ case WM_DESTROY:
+ //SendMessage(hwnd, WM_CLOSE, 0, 0);
+ {
+ TCITEM tci;
+ int l, i;
+ l = TabCtrl_GetItemCount(tab_ctrl);
+ for (i = 0; i < l; i++) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(tab_ctrl, i, &tci);
+ delete (TabData *)tci.lParam;
+ }
+ UnsubclassTabCtrl(tab_ctrl);
+ WindowData *window_data = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ delete window_data;
+
+ ImageList_Destroy(clist_imagelist);
+ }
+ break;
+
+ case WM_PREADDCHILD:
+ {
+ HWND child = (HWND)wParam;
+ LONG style = GetWindowLong(child, GWL_STYLE);
+ style &= ~(WS_THICKFRAME | WS_POPUP | WS_SYSMENU | WS_CAPTION);
+ style |= WS_CHILD;
+ SetWindowLong(child, GWL_STYLE, style);
+ SetParent(child, hwnd);
+ }
+ return TRUE;
+ case WM_ADDCHILD:
+ {
+ HWND child = (HWND)wParam;
+ HANDLE hContact = (HANDLE)lParam;
+
+ if(WindowList_Find(window_list, hContact) == 0) {
+ WindowList_Add(window_list, child, hContact);
+
+ TCHAR *contactName = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact, (LPARAM)GCDNF_TCHAR);
+
+ TCITEM tie;
+ tie.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
+ tie.iImage = options.tab_icon ? (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0) : -1;
+ tie.pszText = contactName;
+ TabData *td = new TabData;
+ td->hContact = hContact;
+ td->hwndMsg = child;
+ tie.lParam = (LPARAM)td;
+
+ int count = TabCtrl_GetItemCount(tab_ctrl);
+ TabCtrl_InsertItem(tab_ctrl, count, &tie);
+ TabCtrl_SetCurSel(tab_ctrl, count);
+ SendMessage(hwnd, WMU_SETTAB, 0, 0);
+
+ ShowWindow(hwnd, SW_SHOW);
+ }
+ }
+ return TRUE;
+ case WM_REMCHILD:
+ {
+ HWND child = (HWND)wParam;
+ int l, i = GetTabFromHWND(tab_ctrl, child);
+
+ TCITEM tie;
+ tie.mask = TCIF_PARAM;
+ SendMessage(tab_ctrl, TCM_GETITEM, (WPARAM)i, (LPARAM)&tie);
+
+ TabCtrl_DeleteItem(tab_ctrl, i);
+ WindowList_Remove(window_list, child);
+
+ delete (TabData *)tie.lParam;
+
+ l = TabCtrl_GetItemCount(tab_ctrl);
+ if(l == 0)
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ else {
+ if(i >= l) i = l - 1;
+ TabCtrl_SetCurSel(tab_ctrl, i);
+ SendMessage(hwnd, WMU_SETTAB, 0, 0);
+ }
+ }
+ return TRUE;
+ case WMU_SETTAB:
+ {
+ int iPage = TabCtrl_GetCurSel(tab_ctrl);
+ TCHAR tbuff[128];
+
+ TCITEM tie;
+ tie.pszText = tbuff;
+ tie.cchTextMax = sizeof(tbuff) / sizeof(TCHAR);
+ tie.mask = TCIF_PARAM | TCIF_TEXT | TCIF_IMAGE;
+ SendMessage(tab_ctrl, TCM_GETITEM, (WPARAM)iPage, (LPARAM)&tie);
+ SetWindowText(hwnd, tie.pszText);
+
+ HWND child = ((TabData *)tie.lParam)->hwndMsg;
+ HANDLE hContact = ((TabData *)tie.lParam)->hContact;
+ if(active_window == child) return TRUE;
+
+ // use GETCONTACTICON service instead of tie.iImage, because tie.iImage may be -1 depending on options
+ HANDLE hIcon = ImageList_GetIcon(clist_imagelist, (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0), 0);
+ SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
+ SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+
+ if(active_window) {
+ SetWindowPos(active_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ ShowWindow(active_window, SW_HIDE);
+ }
+ active_window = child;
+
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ rc.top += 2;
+ rc.right += 2;
+ rc.bottom += 2;
+ TabCtrl_AdjustRect(tab_ctrl, FALSE, &rc);
+ SetWindowPos(active_window, HWND_TOP, rc.left - 3, rc.top - 1, rc.right - rc.left + 4, rc.bottom - rc.top + 2, SWP_SHOWWINDOW);
+
+ tie.mask = TCIF_IMAGE;
+ tie.iImage = options.tab_icon ? (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0) : -1;
+ SendMessage(tab_ctrl, TCM_SETITEM, (WPARAM)iPage, (LPARAM)&tie);
+ SetFocus(active_window);
+ }
+ return TRUE;
+ case WM_NOTIFY:
+ {
+ NMHDR *nmhdr = (NMHDR *)lParam;
+ switch (nmhdr->code) {
+ case 0: // menu command processing
+ break;
+
+ case TCN_SELCHANGE:
+ SendMessage(hwnd, WMU_SETTAB, 0, 0);
+ break;
+ }
+ }
+ break;
+ case WM_CLOSE:
+ {
+ Utils_SaveWindowPosition(hwnd, 0, MODULE, "MainWin");
+ active_window = 0;
+ SetFocus(tab_ctrl); // crash if focus is in typing window when srmm closed (EN_KILLFOCUS command, null dat)
+ WindowList_Broadcast(window_list, WM_CLOSE, 0, 0);
+ ShowWindow(hwnd, SW_HIDE);
+ }
+ return TRUE;
+ case WM_HIGHLIGHTCONTACTWND:
+ {
+ HANDLE hContact = (HANDLE)wParam;
+ HWND child = WindowList_Find(window_list, hContact);
+ if(child) {
+ int t = GetTabFromHWND(tab_ctrl, child);
+ if(TabCtrl_GetCurSel(tab_ctrl) != t) {
+ //TabCtrl_HighlightItem(tab_ctrl, t, 1);
+ TCITEM tie;
+ tie.mask = TCIF_IMAGE;
+ tie.iImage = message_icon_index;
+ SendMessage(tab_ctrl, TCM_SETITEM, (WPARAM)t, (LPARAM)&tie);
+ }
+ }
+ }
+ return TRUE;
+ case WM_SHOWCONTACTWND:
+ {
+ HANDLE hContact = (HANDLE)wParam;
+ HWND child = WindowList_Find(window_list, hContact);
+ if(child) {
+ int t = GetTabFromHWND(tab_ctrl, child);
+ TabCtrl_SetCurSel(tab_ctrl, t);
+ SendMessage(hwnd, WMU_SETTAB, 0, 0);
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ }
+ }
+ return TRUE;
+ case WM_MOUSEMOVE:
+ if(wParam & MK_LBUTTON) {
+ SetCapture(hwnd);
+
+ POINT newp;
+ newp.x = (short)LOWORD(lParam);
+ newp.y = (short)HIWORD(lParam);
+
+ ClientToScreen(hwnd, &newp);
+
+ WindowData *window_data = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ if(!window_data->moving) {
+ window_data->moving = true;
+ } else {
+ RECT r;
+ GetWindowRect(hwnd, &r);
+
+ SetWindowPos(hwnd, 0, r.left + (newp.x - window_data->p.x), r.top + (newp.y - window_data->p.y), 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+ }
+ window_data->p.x = newp.x;
+ window_data->p.y = newp.y;
+ } else {
+ ReleaseCapture();
+ WindowData *window_data = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ window_data->moving = false;
+ }
+ return TRUE;
+ case WM_RESETTABICONS:
+ {
+ HANDLE hContact = (HANDLE)wParam;
+ TCITEM tci;
+ if(hContact) {
+ // wParam contains clist image list icon index from contact icon changed event - but that could be e.g. flashing online notification
+ // so we get the contact icon in ici, which is just the proto icon
+ int t = GetTabFromContact(tab_ctrl, hContact), ici = (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0);
+ if(t != -1) {
+ tci.mask = TCIF_IMAGE;
+ tci.iImage = options.tab_icon ? ici : -1;
+ SendMessage(tab_ctrl, TCM_SETITEM, (WPARAM)t, (LPARAM)&tci);
+
+ if(t == TabCtrl_GetCurSel(tab_ctrl)) {
+ // use GETCONTACTICON service instead of tie.iImage, because tie.iImage may be -1 depending on options
+ HANDLE hIcon = ImageList_GetIcon(clist_imagelist, ici, 0);
+ SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
+ SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+ }
+ }
+ } else {
+ int l, i;
+ HANDLE hContact;
+ l = TabCtrl_GetItemCount(tab_ctrl);
+ for (i = 0; i < l; i++) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(tab_ctrl, i, &tci);
+ hContact = ((TabData *)tci.lParam)->hContact;
+
+ tci.mask = TCIF_IMAGE;
+ tci.iImage = options.tab_icon ? (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0) : -1;
+ SendMessage(tab_ctrl, TCM_SETITEM, (WPARAM)i, (LPARAM)&tci);
+ }
+ }
+ }
+ return TRUE;
+ }
+
+ //return DefWindowProc(hwnd, msg, wParam, lParam);
+ return 0;
+}
+
+int CreateFrame(HWND parent, HINSTANCE hInst) {
+ InitCommonControls();
+
+ /*
+ WNDCLASS wndclass;
+ wndclass.style = 0; //CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = FrameProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = _T("TabFrame");
+ RegisterClass(&wndclass);
+ */
+
+ window_list = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+
+ //clist_imagelist = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+ HIMAGELIST iml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+ clist_imagelist = ImageList_Duplicate(iml);
+ message_icon_index = ImageList_ReplaceIcon(clist_imagelist, 0, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+
+ /*
+ pluginwind = CreateWindowEx(WS_EX_APPWINDOW, _T("TabFrame"),"",
+ 0,//options.show_titlebar ? STYLE_TITLE : STYLE_NOTITLE,
+ 0, 0, 800, 600, parent, NULL, hInst, NULL);
+ */
+ pluginwind = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CONTAINER), 0, FrameProc, 0);
+
+ EnableTitleBar();
+
+ return 0;
+}
+
+BOOL CALLBACK TabCtrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TabCtrlData *dat;
+ dat = (TabCtrlData *) GetWindowLong(hwnd, GWL_USERDATA);
+ switch(msg) {
+ case EM_SUBCLASSED:
+ dat = (TabCtrlData *) mir_alloc(sizeof(TabCtrlData));
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG) dat);
+ dat->bDragging = FALSE;
+ return 0;
+ case WM_MBUTTONDOWN:
+ {
+ TCITEM tci;
+ int tabId;
+ TabData *mwtd;
+ TCHITTESTINFO thinfo;
+ thinfo.pt.x = (lParam<<16)>>16;
+ thinfo.pt.y = lParam>>16;
+ tabId = TabCtrl_HitTest(hwnd, &thinfo);
+ if (tabId >= 0) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwnd, tabId, &tci);
+ mwtd = (TabData *) tci.lParam;
+ if (mwtd) SendMessage(mwtd->hwndMsg, WM_CLOSE, 0, 0);
+ }
+ return 0;
+ }
+ case WM_LBUTTONDBLCLK:
+ {
+ TCITEM tci;
+ TCHITTESTINFO thinfo;
+ int tabId;
+ TabData *mwtd;
+ thinfo.pt.x = (lParam<<16)>>16;
+ thinfo.pt.y = lParam>>16;
+ tabId = TabCtrl_HitTest(hwnd, &thinfo);
+ if (tabId >=0 ) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwnd, tabId, &tci);
+ mwtd = (TabData *) tci.lParam;
+ if (mwtd) SendMessage(mwtd->hwndMsg, WM_CLOSE, 0, 0);
+ }
+ dat->lastClickTab = -1;//Child = NULL;
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ {
+ if (!dat->bDragging) {
+ FILETIME ft;
+ TCHITTESTINFO thinfo;
+ GetSystemTimeAsFileTime(&ft);
+ thinfo.pt.x = (lParam<<16)>>16;
+ thinfo.pt.y = lParam>>16;
+ dat->srcTab = dat->destTab = TabCtrl_HitTest(hwnd, &thinfo);
+ if (dat->srcTab >=0 ) {
+ dat->lastClickTab = dat->srcTab; //Child = GetChildFromTab(hwnd, dat->srcTab)->hwnd;
+ } else {
+ dat->lastClickTab = -1;//Child = NULL;
+ }
+ 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) {
+ TCHITTESTINFO thinfo;
+ thinfo.pt.x = (lParam<<16)>>16;
+ thinfo.pt.y = lParam>>16;
+ 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;
+ TCHAR sBuffer[501];
+ TCITEM item;
+ int curSel;
+ curSel = TabCtrl_GetCurSel(hwnd);
+ item.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_TEXT;
+ item.pszText = sBuffer;
+ item.cchTextMax = sizeof(sBuffer)/sizeof(TCHAR);
+ TabCtrl_GetItem(hwnd, dat->srcTab, &item);
+ sBuffer[sizeof(sBuffer)/sizeof(TCHAR)-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);
+ nmh.hwndFrom = hwnd;
+ nmh.idFrom = GetDlgCtrlID(hwnd);
+ nmh.code = TCN_SELCHANGE;
+ SendMessage(GetParent(hwnd), WM_NOTIFY, nmh.idFrom, (LPARAM)&nmh);
+ UpdateWindow(hwnd);
+ } else if (GetKeyState(VK_CONTROL) & 0x8000) {
+ /*
+ MessageWindowTabData *mwtd;
+ TCITEM tci;
+ POINT pt;
+ NewMessageWindowLParam newData = { 0 };
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwnd, dat->srcTab, &tci);
+ mwtd = (MessageWindowTabData *) tci.lParam;
+ if (mwtd != NULL) {
+ HWND hChild = mwtd->hwnd;
+ HANDLE hContact = mwtd->hContact;
+ HWND hParent;
+ GetCursorPos(&pt);
+ hParent = WindowFromPoint(pt);
+ while (GetParent(hParent) != NULL) {
+ hParent = GetParent(hParent);
+ }
+ hParent = WindowList_Find(g_dat->hParentWindowList, hParent);
+ if ((hParent != NULL && hParent != GetParent(hwnd)) || (hParent == NULL && mwtd->parent->childrenCount > 1)) {
+ if (hParent == NULL) {
+ MONITORINFO mi;
+ HMONITOR hMonitor;
+ RECT rc, rcDesktop;
+ newData.hContact = hContact;
+ hParent = (HWND)CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGWIN), NULL, DlgProcParentWindow, (LPARAM) & newData);
+ 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 = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+ 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);
+
+ }
+ SetParent(hChild, hParent);
+ SendMessage(GetParent(hwnd), CM_REMOVECHILD, 0, (LPARAM) hChild);
+ SendMessage(hChild, DM_SETPARENT, 0, (LPARAM) hParent);
+ SendMessage(hParent, CM_ADDCHILD, (WPARAM)hChild, (LPARAM) hContact);
+ SendMessage(hParent, CM_ACTIVATECHILD, 0, (LPARAM) hChild);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSING);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSE);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPENING);
+ NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPEN);
+ ShowWindow(hParent, SW_SHOWNA);
+ }
+ }
+ */
+ }
+ } else {
+ SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam);
+ }
+ dat->bDragged = FALSE;
+ dat->bDragging = FALSE;
+ ReleaseCapture();
+ }
+ break;
+ case WM_MOUSEMOVE:
+ if (!(wParam & MK_LBUTTON)) break;
+ if (dat->bDragging) {
+ FILETIME ft;
+ TCHITTESTINFO thinfo;
+ GetSystemTimeAsFileTime(&ft);
+ thinfo.pt.x = (lParam<<16)>>16;
+ thinfo.pt.y = lParam>>16;
+ 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;
+ HDC hDC, hMemDC;
+ HBITMAP hBitmap, hOldBitmap;
+ 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 = GetDC(hwnd);
+ hMemDC = CreateCompatibleDC(hDC);
+ hBitmap = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
+ 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(LoadCursor(0, IDC_HAND));
+ dat->mouseLBDownPos.x = thinfo.pt.x;
+ dat->mouseLBDownPos.y = thinfo.pt.y;
+ } else {
+ POINT pt;
+ GetCursorPos(&pt);
+ ImageList_DragMove(pt.x, pt.y);
+ }
+ dat->bDragged = TRUE;
+ return 0;
+ }
+ break;
+ case EM_UNSUBCLASSED:
+ mir_free(dat);
+ return 0;
+ }
+ return CallWindowProc(OldTabCtrlProc, hwnd, msg, wParam, lParam);
+}