Exemple #1
0
int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
{
    TC_HITTESTINFO hitTestInfo;
    hitTestInfo.pt.x = pt.x;
    hitTestInfo.pt.y = pt.y;
    int item = TabCtrl_HitTest(GetHwnd(), &hitTestInfo);

    if ( flags )
    {
        *flags = 0;

        if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
            *flags |= wxBK_HITTEST_NOWHERE;
        if ((hitTestInfo.flags & TCHT_ONITEM) == TCHT_ONITEM)
            *flags |= wxBK_HITTEST_ONITEM;
        if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
            *flags |= wxBK_HITTEST_ONICON;
        if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
            *flags |= wxBK_HITTEST_ONLABEL;
        if ( item == wxNOT_FOUND && GetPageSize().Contains(pt) )
            *flags |= wxBK_HITTEST_ONPAGE;
    }

    return item;
}
/// Function name  : onDocumentsControl_ContextMenu
// Description     : Displays the tab context menu and implements it's commands
// 
// DOCUMENTS_DATA*  pWindowData  : [in] Documents data
// CONST POINT*     ptClick      : [in] Cursor position (in screen co-ordinates)
// 
BOOL  onDocumentsControl_ContextMenu(DOCUMENTS_DATA*  pWindowData, CONST POINT*  ptClick)
{
   TCHITTESTINFO  oHitTest;            // Document tab HitTest
   CUSTOM_MENU*   pCustomMenu;         // Custom menu
   DOCUMENT*      pDocument;           // Document that was clicked, if any
   INT            iDocumentIndex;      // Index of the document that was clicked

   // Prepare
   oHitTest.pt    = *ptClick;
   oHitTest.flags = TCHT_ONITEM;

   /// [CHECK] Has the user clicked a tab heading?
   ScreenToClient(pWindowData->hTabCtrl, &oHitTest.pt);
   iDocumentIndex = TabCtrl_HitTest(pWindowData->hTabCtrl, &oHitTest);

   // Lookup document (Will fails if user did not click a tab heading)
   if (findDocumentByIndex(pWindowData->hTabCtrl, iDocumentIndex, pDocument))
   {
      CONSOLE_ACTION();

      // Generate custom menu
      pCustomMenu = createCustomMenu(TEXT("DIALOG_MENU"), TRUE, IDM_DOCUMENT_POPUP);

      /// Enable/Disable menu items
      EnableMenuItem(pCustomMenu->hPopup, IDM_FILE_SAVE,                    isModified(pDocument) ? MF_ENABLED : MF_DISABLED);
      EnableMenuItem(pCustomMenu->hPopup, IDM_WINDOW_CLOSE_OTHER_DOCUMENTS, getDocumentCount() > 1 ? MF_ENABLED : MF_DISABLED);

      // Enable/Disable project items
      EnableMenuItem(pCustomMenu->hPopup, IDM_DOCUMENT_ADD_PROJECT,    getActiveProject() AND !isDocumentInProject(pDocument) ? MF_ENABLED : MF_DISABLED);
      EnableMenuItem(pCustomMenu->hPopup, IDM_DOCUMENT_REMOVE_PROJECT, getActiveProject() AND isDocumentInProject(pDocument)  ? MF_ENABLED : MF_DISABLED);

      /// Display context menu and return choice immediately
      switch (TrackPopupMenu(pCustomMenu->hPopup, TPM_RETURNCMD WITH TPM_TOPALIGN WITH TPM_LEFTALIGN, ptClick->x, ptClick->y, NULL, pWindowData->hTabCtrl, NULL))
      {
      // [SAVE/CLOSE/CLOSE-OTHER] Perform relevant command
      case IDM_FILE_SAVE:                     commandSaveDocument(getMainWindowData(), pDocument, FALSE, NULL);  break;
      case IDM_FILE_CLOSE:                    closeDocumentByIndex(pWindowData->hTabCtrl, iDocumentIndex);       break;
      case IDM_WINDOW_CLOSE_OTHER_DOCUMENTS:  closeAllDocuments(pWindowData->hTabCtrl, TRUE);                    break;

      // [ADD/REMOVE PROJECT] TODO
      case IDM_DOCUMENT_ADD_PROJECT:          addDocumentToProject(pDocument);         break;
      case IDM_DOCUMENT_REMOVE_PROJECT:       removeDocumentFromProject(pDocument);    break;
         break;
      }

      // Cleanup
      deleteCustomMenu(pCustomMenu);
   }
   
   // Return TRUE if handled, otherwise FALSE
   return (iDocumentIndex != -1);
}
Exemple #3
0
// Hit test
int wxTabCtrl::HitTest(const wxPoint& pt, long& flags)
{
    TC_HITTESTINFO hitTestInfo;
    hitTestInfo.pt.x = pt.x;
    hitTestInfo.pt.y = pt.y;
    int item = TabCtrl_HitTest( (HWND) GetHWND(), & hitTestInfo ) ;
    flags = 0;

    if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
        flags |= wxTAB_HITTEST_NOWHERE;
    if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
        flags |= wxTAB_HITTEST_ONICON;
    if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
        flags |= wxTAB_HITTEST_ONLABEL;

    return item;
}
HRESULT _stdcall CContainer::Drop(IDataObject *pDataObject,DWORD grfKeyState,
POINTL pt,DWORD *pdwEffect)
{
	TCHITTESTINFO tchi;
	TCITEM tcItem;
	TCHAR szDestDirectory[MAX_PATH];
	int iTab;

	m_pDropTargetHelper->Drop(pDataObject,(POINT *)&pt,*pdwEffect);

	tchi.pt.x = pt.x;
	tchi.pt.y = pt.y;
	ScreenToClient(m_hTabCtrl,&tchi.pt);
	iTab = TabCtrl_HitTest(m_hTabCtrl,&tchi);

	if(iTab != -1)
	{
		tcItem.mask = TCIF_PARAM;
		TabCtrl_GetItem(m_hTabCtrl,iTab,&tcItem);

		m_pShellBrowser[(int)tcItem.lParam]->QueryCurrentDirectory(SIZEOF_ARRAY(szDestDirectory),
			szDestDirectory);
	}
	else
	{
		return S_OK;
	}
	
	if(m_bDataAccept)
	{
		IDropHandler *pDropHandler = NULL;

		pDropHandler = new CDropHandler();

		pDropHandler->Drop(pDataObject,
			grfKeyState,pt,pdwEffect,m_hTabCtrl,
			m_DragType,szDestDirectory,
			NULL,FALSE);

		pDropHandler->Release();
	}

	return S_OK;
}
Exemple #5
0
// Screen coordinates, if bScreen==true
// -2 - out of control, -1 - out of tab-labels, 0+ - tab index 0-based
int CTabPanelWin::GetTabFromPoint(POINT ptCur, bool bScreen /*= true*/, bool bOverTabHitTest /*= true*/)
{
	int iTabIndex = -2; // Вообще вне контрола

	if (IsTabbarCreated())
	{
		RECT rcWnd = {}; GetWindowRect(mh_Tabbar, &rcWnd);
		RECT rcBar = {}; GetWindowRect(mh_Rebar, &rcBar);
		// 130911 - Let allow switching tabs by clicking over tabs headers (may be useful with fullscreen)
		RECT rcFull = {0, rcBar.top - rcWnd.top, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top};

		TCHITTESTINFO tch = {ptCur};
		if (bScreen)
		{
			tch.pt.x -= rcWnd.left;
			tch.pt.y -= rcWnd.top;
		}

		if (PtInRect(&rcFull, tch.pt))
		{
			LRESULT nTest = TabCtrl_HitTest(mh_Tabbar, &tch);

			iTabIndex = (nTest <= -1) ? -1 : (int)nTest;

			if (iTabIndex == -1 && bOverTabHitTest)
			{
				// Clicked over tab?
				tch.pt.y = (rcWnd.bottom - rcWnd.top)/2;
				nTest = SendMessage(mh_Tabbar, TCM_HITTEST, 0, (LPARAM)&tch);
				if (nTest >= 0)
				{
					iTabIndex = (int)nTest;
				}
			}

		}
	}

	return iTabIndex;
}
LRESULT CALLBACK Explorerplusplus::TabSubclassProc(HWND hTab,UINT msg,WPARAM wParam,LPARAM lParam)
{
	switch(msg)
	{
		case WM_INITMENU:
			OnInitTabMenu(wParam);
			SendMessage(m_hContainer,WM_INITMENU,wParam,lParam);
			break;

		case WM_MENUSELECT:
			/* Forward the message to the main window so it can
			handle menu help. */
			SendMessage(m_hContainer,WM_MENUSELECT,wParam,lParam);
			break;

		case WM_MEASUREITEM:
			SendMessage(m_hContainer,WM_MEASUREITEM,wParam,lParam);
			break;

		case WM_DRAWITEM:
			SendMessage(m_hContainer,WM_DRAWITEM,wParam,lParam);
			break;

		case WM_LBUTTONDOWN:
			OnTabCtrlLButtonDown(wParam,lParam);
			break;

		case WM_LBUTTONUP:
			OnTabCtrlLButtonUp();
			break;

		case WM_MOUSEMOVE:
			OnTabCtrlMouseMove(wParam,lParam);
			break;

		case WM_MBUTTONUP:
			SendMessage(m_hContainer,WM_APP_TABMCLICK,wParam,lParam);
			break;

		case WM_RBUTTONUP:
			OnTabCtrlRButtonUp(wParam,lParam);
			break;

		case WM_CAPTURECHANGED:
			{
				if((HWND)lParam != hTab)
					ReleaseCapture();

				m_bTabBeenDragged = FALSE;
			}
			break;

		case WM_LBUTTONDBLCLK:
			{
				TCHITTESTINFO info;
				int ItemNum;
				DWORD dwPos;
				POINT MousePos;

				dwPos = GetMessagePos();
				MousePos.x = GET_X_LPARAM(dwPos);
				MousePos.y = GET_Y_LPARAM(dwPos);
				ScreenToClient(hTab,&MousePos);

				/* The cursor position will be tested to see if
				there is a tab beneath it. */
				info.pt.x	= LOWORD(lParam);
				info.pt.y	= HIWORD(lParam);

				ItemNum = TabCtrl_HitTest(m_hTabCtrl,&info);

				if(info.flags != TCHT_NOWHERE && m_bDoubleClickTabClose)
				{
					CloseTab(ItemNum);
				}
			}
			break;

		case WM_NCDESTROY:
			RemoveWindowSubclass(m_hTabCtrl,TabSubclassProcStub,0);
			break;
	}

	return DefSubclassProc(hTab,msg,wParam,lParam);
}
HRESULT _stdcall CContainer::DragOver(DWORD grfKeyState,POINTL pt,DWORD *pdwEffect)
{
	TCHITTESTINFO HitTestInfo;
	BOOL bOnSameDrive;
	int iTab;

	HitTestInfo.pt.x	= pt.x;
	HitTestInfo.pt.y	= pt.y;

	ScreenToClient(m_hTabCtrl,&HitTestInfo.pt);

	iTab = TabCtrl_HitTest(m_hTabCtrl,&HitTestInfo);

	if(iTab == -1)
	{
		*pdwEffect = DROPEFFECT_NONE;
	}
	else
	{
		TCITEM tcItem;

		tcItem.mask	= TCIF_PARAM;
		TabCtrl_GetItem(m_hTabCtrl,iTab,&tcItem);

		if(iTab != m_iTabSelectedItem)
		{
			/* Set a timer. If the mouse does not move
			outside this tab before the timer expires,
			and the item is still been dragged, switch
			focus to this tab.
			The timer will be set if the tab the item
			is currently above does not match the
			tab it was above initially (when the timer
			was previously set). */
			if(iTab != m_iTabDragTab)
			{
				SetTimer(m_hTabCtrl,TABDRAG_TIMER_ID,TABDRAG_TIMER_ELAPSED,TabDragTimerProc);

				m_iTabDragTab = iTab;
			}
			else if(g_bTabDragTimerElapsed)
			{
				m_iTabSelectedItem = iTab;

				TabCtrl_SetCurSel(m_hTabCtrl,m_iTabSelectedItem);

				OnTabChangeInternal(TRUE);

				g_bTabDragTimerElapsed = FALSE;
			}
		}
		else
		{
			KillTimer(m_hTabCtrl,TABDRAG_TIMER_ID);
			m_iTabDragTab = iTab;
		}

		/* If the tab contains a virtual folder,
		then files cannot be dropped. */
		if(m_pShellBrowser[(int)tcItem.lParam]->InVirtualFolder())
		{
			*pdwEffect = DROPEFFECT_NONE;
		}
		else
		{
			bOnSameDrive = CheckItemLocations((int)tcItem.lParam);

			*pdwEffect = DetermineCurrentDragEffect(grfKeyState,
				*pdwEffect,m_bDataAccept,bOnSameDrive);
		}
	}

	m_pDropTargetHelper->DragOver((LPPOINT)&pt,*pdwEffect);

	return S_OK;
}
HRESULT _stdcall CContainer::DragEnter(IDataObject *pDataObject,
DWORD grfKeyState,POINTL pt,DWORD *pdwEffect)
{
	m_iTabDragTab = m_iTabSelectedItem;
	g_bTabDragTimerElapsed = FALSE;

	std::list<FORMATETC> ftcList;
	CDropHandler::GetDropFormats(&ftcList);

	BOOL bDataAccept = FALSE;

	/* Check whether the drop source has the type of data
	that is needed for this drag operation. */
	for each(auto ftc in ftcList)
	{
		if(pDataObject->QueryGetData(&ftc) == S_OK)
		{
			bDataAccept = TRUE;
			break;
		}
	}

	if(bDataAccept)
	{
		m_bDataAccept	= TRUE;

		GetSourceFileName(pDataObject);

		TCHITTESTINFO	tchi;
		TCITEM			tcItem;
		BOOL			bOnSameDrive;
		int				iTab;

		tchi.pt.x = pt.x;
		tchi.pt.y = pt.y;
		ScreenToClient(m_hTabCtrl,&tchi.pt);
		iTab = TabCtrl_HitTest(m_hTabCtrl,&tchi);

		if(iTab != -1)
		{
			tcItem.mask = TCIF_PARAM;
			TabCtrl_GetItem(m_hTabCtrl,iTab,&tcItem);

			bOnSameDrive = CheckItemLocations((int)tcItem.lParam);

			*pdwEffect = DetermineCurrentDragEffect(grfKeyState,
				*pdwEffect,m_bDataAccept,bOnSameDrive);
		}
		else
		{
			*pdwEffect = DROPEFFECT_NONE;
		}
	}
	else
	{
		m_bDataAccept	= FALSE;
		*pdwEffect		= DROPEFFECT_NONE;
	}

	if(grfKeyState & MK_LBUTTON)
		m_DragType = DRAG_TYPE_LEFTCLICK;
	else if(grfKeyState & MK_RBUTTON)
		m_DragType = DRAG_TYPE_RIGHTCLICK;

	m_pDropTargetHelper->DragEnter(m_hTabCtrl,pDataObject,(POINT *)&pt,*pdwEffect);

	return S_OK;
}
BOOL CALLBACK TabCtrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	struct TabCtrlData *dat;
	dat = (struct TabCtrlData *) GetWindowLong(hwnd, GWL_USERDATA);
    switch(msg) {
        case WM_MBUTTONDOWN:
		{
			TCITEM tci;
			int tabId;
			struct MessageWindowData *mwd;
			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);
				mwd = (struct MessageWindowData *) tci.lParam;
				if (mwd != NULL) {
					SendMessage(mwd->hwnd, WM_CLOSE, 0, 0);
    			}
			}
	        return TRUE;
        }
		case WM_LBUTTONDBLCLK:
		{
			TCHITTESTINFO thinfo;
			int tabId;
			thinfo.pt.x = (lParam<<16)>>16;
			thinfo.pt.y = lParam>>16;
			tabId = TabCtrl_HitTest(hwnd, &thinfo);
			if (tabId >=0 ) {
				void * clickChild = GetChildFromTab(hwnd, tabId)->hwnd;
				if (clickChild == dat->lastClickChild) {
					SendMessage(clickChild, WM_CLOSE, 0, 0);
				}
			}
			dat->lastClickChild = 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->lastClickChild = GetChildFromTab(hwnd, dat->srcTab)->hwnd;
				} else {
					dat->lastClickChild = 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 {
					SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam);
				}
				dat->bDragged = FALSE;
				dat->bDragging = FALSE;
				ReleaseCapture();
			}
BOOL CALLBACK DlgProcParentWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	DWORD ws;
	struct ParentWindowData *dat;
	dat = (struct ParentWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA);
	if (!dat && msg!=WM_INITDIALOG) return FALSE;
	switch (msg) {
	case WM_INITDIALOG:
		{
			HMENU hMenu;
			HANDLE hSContact;
			int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT);
			struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam;
			dat = (struct ParentWindowData *) malloc(sizeof(struct ParentWindowData));
			dat->foregroundWindow = GetForegroundWindow();
			dat->hContact = newData->hContact;
			dat->nFlash = 0;
			dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT);
			dat->childrenCount = 0;
			dat->children = NULL;
			dat->hwnd = hwndDlg;
			dat->flags = g_dat->flags;// | SMF_SHOWTITLEBAR;
			dat->mouseLBDown = 0;
			dat->windowWasCascaded = 0;
			dat->bMinimized = 0;
			dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL);
			{
				int statwidths[4];
				RECT rc;
				SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
				GetWindowRect(dat->hwndStatus, &rc);
				/*
				statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_TYPING_WIDTH - SB_SENDING_WIDTH;
				statwidths[1] = rc.right - rc.left - SB_TYPING_WIDTH - SB_SENDING_WIDTH; //rc.right - rc.left - SB_CHAR_WIDTH;
				statwidths[2] = rc.right - rc.left - SB_TYPING_WIDTH; //rc.right - rc.left - SB_CHAR_WIDTH;
				statwidths[3] = -1;
				SendMessage(dat->hwndStatus, SB_SETPARTS, 4, (LPARAM) statwidths);
				*/
				statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_TYPING_WIDTH;
				statwidths[1] = rc.right - rc.left - SB_TYPING_WIDTH;
				statwidths[2] = -1;
				SendMessage(dat->hwndStatus, SB_SETPARTS, 3, (LPARAM) statwidths);
			}
			dat->hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
			dat->hwndActive = NULL;
			SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) dat);
			if (g_dat->hIconList != NULL) {
				TabCtrl_SetImageList(dat->hwndTabs, g_dat->hIconList);
			}
			WindowList_Add(g_dat->hParentWindowList, hwndDlg, 0);
			dat->tabCtrlDat = (struct TabCtrlData *) malloc(sizeof(struct TabCtrlData));
			dat->tabCtrlDat->bDragging = FALSE;
			SetWindowLong(dat->hwndTabs, GWL_USERDATA, (LONG) dat->tabCtrlDat);
			OldTabCtrlProc = (WNDPROC) SetWindowLong(dat->hwndTabs, GWL_WNDPROC, (LONG) TabCtrlProc);
			ws = GetWindowLong(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM);
			if (dat->flags & SMF_TABSATBOTTOM) {
				ws |= TCS_BOTTOM;
			}
			SetWindowLong(dat->hwndTabs, GWL_STYLE, ws);
			ws = GetWindowLong(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
			if (dat->flags & SMF_SHOWTITLEBAR) {
				ws |= WS_CAPTION;
				SetWindowLong(hwndDlg, GWL_STYLE, ws);
			} else {
				RECT rc;
				SetWindowLong(hwndDlg, GWL_STYLE, ws);
				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);
			}
			ws = GetWindowLong(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
			ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
			SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
			if (dat->flags & SMF_USETRANSPARENCY) {
   				pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->inactiveAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}
			if (!(dat->flags & SMF_SHOWSTATUSBAR)) {
				ShowWindow(dat->hwndStatus, SW_HIDE);
			}
			hSContact = !(dat->flags & SMF_USETABS) && savePerContact ? dat->hContact : NULL;
			dat->bTopmost = DBGetContactSettingByte(hSContact, SRMMMOD, SRMSGSET_TOPMOST, SRMSGDEFSET_TOPMOST);
			if (ScriverRestoreWindowPosition(hwndDlg, hSContact, SRMMMOD, "", 0, SW_HIDE)) {
				if (ScriverRestoreWindowPosition(hwndDlg, hSContact, SRMMMOD, "", RWPF_NOSIZE, SW_HIDE)) {
					SetWindowPos(GetParent(hwndDlg), 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_HIDEWINDOW);
				} else {
					SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_HIDEWINDOW);
				}
			}
			if (!(dat->flags & SMF_USETABS)) {
				if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE))
					WindowList_Broadcast(g_dat->hParentWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded);
			}
			hMenu = GetSystemMenu( hwndDlg, FALSE );
			AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
			if (dat->bTopmost) {
				AppendMenu( hMenu, 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 {
				AppendMenu( hMenu, MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always On Top"));
			}
		}
		return TRUE;
	case WM_GETMINMAXINFO:
	{
		MINMAXINFO *mmi = (MINMAXINFO *) lParam;
		SIZE size;
		if (GetKeyState(VK_CONTROL) & 0x8000) {
			WINDOWPLACEMENT wp;
			RECT rcDesktop;
			wp.length = sizeof(wp);
			GetWindowPlacement(hwndDlg, &wp);
			SystemParametersInfo(SPI_GETWORKAREA, 0, &rcDesktop, 0);
			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;
			}
		}
		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 {
//		}
//		if (!IsIconic(hwndDlg)) {
			int i;
			RECT rc, rcStatus, rcChild, rcWindow;
			SIZE size;
			dat->bMinimized = 0;
			GetClientRect(hwndDlg, &rc);
			GetWindowRect(hwndDlg, &rcWindow);
			rcStatus.top = rcStatus.bottom = 0;
			if (dat->flags & SMF_SHOWSTATUSBAR) {
				int statwidths[4];
				GetWindowRect(dat->hwndStatus, &rcStatus);
				statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_TYPING_WIDTH;
				statwidths[1] = rc.right - rc.left - SB_TYPING_WIDTH;
				statwidths[2] = -1;
				SendMessage(dat->hwndStatus, SB_SETPARTS, 3, (LPARAM) statwidths);
				SendMessage(dat->hwndStatus, WM_SIZE, 0, 0);
			}
			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));
			for (i=0;i<dat->childrenCount;i++) {
				if (dat->children[i] == dat->hwndActive) {
					MoveWindow(dat->children[i], rcChild.left, rcChild.top, rcChild.right-rcChild.left, rcChild.bottom - rcChild.top, TRUE);
					RedrawWindow(GetDlgItem(dat->children[i], IDC_LOG), NULL, NULL, RDW_INVALIDATE);
				}
			}
			if (dat->flags & SMF_SHOWSTATUSBAR) {
				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:
		DestroyWindow(hwndDlg);
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDCANCEL:
			//DestroyWindow(hwndDlg);
			return TRUE;
		}
	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)) {
							struct MessageWindowData * mdat = (struct MessageWindowData *) tci.lParam;
							ActivateChild(dat, mdat->hwnd);
							SetFocus(dat->hwndActive);
						}
					}
					break;
				case NM_RCLICK:
					{
						TCHITTESTINFO thinfo;
						int tabId, x, y;
						GetCursorPos(&thinfo.pt);
						x = thinfo.pt.x;
						y = thinfo.pt.y;
						ScreenToClient(dat->hwndTabs, &thinfo.pt);
						tabId = TabCtrl_HitTest(dat->hwndTabs, &thinfo);
						if (tabId != -1) {
							struct MessageWindowData * mwd = GetChildFromTab(dat->hwndTabs, tabId);
							//CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) mwd->hContact, 0);
							HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) mwd->hContact, 0);
							TrackPopupMenu(hMenu, 0, x, y, 0, mwd->hwnd, NULL);
							DestroyMenu(hMenu);
						}
					}
					break;
				}
			} else if (pNMHDR->hwndFrom == dat->hwndStatus)  {
				switch (pNMHDR->code) {
				case NM_CLICK:
					{
						NMMOUSE *nm=(NMMOUSE*)lParam;
						RECT rc;
						SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
						if (nm->pt.x >= rc.left)
							SendMessage(dat->hwndActive, DM_SWITCHUNICODE, 0, 0);
					}
				}
				break;
			}
		}
		break;
	case WM_DROPFILES:
		SendMessage(dat->hwndActive, WM_DROPFILES, wParam, lParam);
		break;
	case WM_TIMER:
		if (wParam == TIMERID_FLASHWND) {
			if ((dat->nFlash > dat->nFlashMax)) {// || ((GetActiveWindow() == hwndDlg) && (GetForegroundWindow() == hwndDlg))) {
				KillTimer(hwndDlg, TIMERID_FLASHWND);
				FlashWindow(hwndDlg, FALSE);
			} else if (dat->nFlash < dat->nFlashMax) {
				FlashWindow(hwndDlg, TRUE);
				dat->nFlash++;
			}
		}
		break;
	case WM_CONTEXTMENU:
	{
		if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) {
			RECT rc;
			POINT pt, pt2;
			GetCursorPos(&pt);
			pt2.x = pt.x;
			pt2.y = pt.y;
			ScreenToClient(dat->hwndStatus, &pt);
			SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
			if (pt.x >= rc.left && dat->hwndActive != NULL) {
				int codePage = (int) SendMessage(dat->hwndActive, DM_GETCODEPAGE, 0, 0);
				int i, iSel;
				for(i = 0; i < GetMenuItemCount(g_dat->hMenuANSIEncoding); i++) {
					CheckMenuItem (g_dat->hMenuANSIEncoding, i, MF_BYPOSITION | MF_UNCHECKED);
				}
				if(codePage == CP_ACP) {
					CheckMenuItem(g_dat->hMenuANSIEncoding, 0, MF_BYPOSITION | MF_CHECKED);
				} else {
					CheckMenuItem(g_dat->hMenuANSIEncoding, codePage, MF_BYCOMMAND | MF_CHECKED);
				}
				iSel = TrackPopupMenu(g_dat->hMenuANSIEncoding, TPM_RETURNCMD, pt2.x, pt2.y, 0, hwndDlg, NULL);
				if (iSel >= 500) {
					if (iSel == 500) iSel = CP_ACP;
					SendMessage(dat->hwndActive, DM_SETCODEPAGE, 0, iSel);
				}
			}
			else
				SendMessage(dat->hwndActive, WM_CONTEXTMENU, (WPARAM)hwndDlg, 0);
		}
		break;
	}

	case WM_ACTIVATE:
		if (LOWORD(wParam) == WA_INACTIVE) {
			ws = GetWindowLong(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
			ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
			SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
			if (dat->flags & SMF_USETRANSPARENCY) {
   				pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->inactiveAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}
		}
		if (LOWORD(wParam) != WA_ACTIVE)
			break;
		if (dat->hwndActive == NULL) { // do not set foreground window at all (always stay in the background !)
//			SendMessage(hwndDlg, DM_DEACTIVATE, 0, 0);
		} else {
			PostMessage(hwndDlg, WM_SETFOCUS, 0, 0);
		}
	case WM_MOUSEACTIVATE:
		if (KillTimer(hwndDlg, TIMERID_FLASHWND)) {
			FlashWindow(hwndDlg, FALSE);
			dat->nFlash = 0;
		}
		ws = GetWindowLong(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
		ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
		SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
		if (dat->flags & SMF_USETRANSPARENCY) {
   			pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->activeAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
		}
		break;
	case WM_LBUTTONDOWN:
		if (!IsZoomed(hwndDlg)) {
			POINT pt;
			GetCursorPos(&pt);
		//	dat->mouseLBDown = 1;
		//	GetCursorPos(&dat->mouseLBDownPos);
			return SendMessage(hwndDlg, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y));
		//	SetCapture(hwndDlg);

		}
		break;
	case WM_LBUTTONUP:
		//if (dat->mouseLBDown) {
		//	dat->mouseLBDown = 0;
		//	ReleaseCapture();
		//}
		break;
	case WM_MOUSEMOVE:/*
		if (dat->mouseLBDown) {
			POINT pt;
			RECT  rc;
			GetCursorPos(&pt);
			GetWindowRect(hwndDlg, &rc);
			SetWindowPos(hwndDlg, 0, rc.left - (dat->mouseLBDownPos.x - pt.x), rc.top - (dat->mouseLBDownPos.y - pt.y), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			dat->mouseLBDownPos = pt;
		}*/
		break;
	case WM_MOVING:
		{
			int snapPixels = 10;
			RECT rcDesktop;
			RECT *pRect = (RECT *)lParam;
			POINT pt;
			SIZE szSize = {pRect->right-pRect->left,pRect->bottom-pRect->top};
			GetCursorPos(&pt);
			SystemParametersInfo(SPI_GETWORKAREA, 0, &rcDesktop, 0);
			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 (!(GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
				if(pRect->top < snapPixels && pRect->top > -snapPixels) {
					pRect->top = 0;
					pRect->bottom = szSize.cy;
				}
				if(pRect->left < snapPixels && pRect->left > -snapPixels) {
					pRect->left = 0;
					pRect->right = 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_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:
		{
			WINDOWPLACEMENT wp = { 0 };
			HANDLE hContact;
			g_dat->hParent = NULL;
			SetWindowLong(hwndDlg, GWL_USERDATA, 0);
			WindowList_Remove(g_dat->hParentWindowList, hwndDlg);
			if (dat->children!=NULL) free (dat->children);
			free(dat->tabCtrlDat);
			free(dat);
			if (!(dat->flags & SMF_USETABS) && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT))
				hContact = dat->hContact;
			else
				hContact = NULL;
			wp.length = sizeof(wp);
			GetWindowPlacement(hwndDlg, &wp);
			if (!dat->windowWasCascaded) {
				DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left);
				DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top);
			}
			DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left);
			DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
			DBWriteContactSettingByte(hContact, SRMMMOD, SRMSGSET_TOPMOST, (BYTE)dat->bTopmost);
		}
		break;
	case DM_DEACTIVATE:
		SetForegroundWindow(dat->foregroundWindow);
		break;
	case DM_ERRORDECIDED:
		break;
	case DM_STARTFLASHING:
		if (GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg) {
			dat->nFlash = 0;
			SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
		}
		break;
	case DM_REMOVECHILD:
		{
			RemoveChild(dat, (HWND) lParam);
			if (dat->childrenCount != 0) {
				SetFocus(dat->hwndActive);
			} else {
				DestroyWindow(hwndDlg);
			}
		}
		return TRUE;
	case DM_ADDCHILD:
		{
			struct MessageWindowData * mdat = (struct MessageWindowData *) lParam;
			AddChild(dat, mdat);
		}
		return TRUE;
	case DM_ACTIVATECHILD:
//		if((HWND) lParam != dat->hwndActive) {
			ActivateChild(dat, (HWND) lParam);
//		}
		return TRUE;
	case DM_ACTIVATEPREV:
		ActivatePrevChild(dat, (HWND) lParam);
		SetFocus(dat->hwndActive);
		return TRUE;
	case DM_ACTIVATENEXT:
		ActivateNextChild(dat, (HWND) lParam);
		SetFocus(dat->hwndActive);
		return TRUE;
	case DM_SENDMESSAGE:
		{
			int i;
			for (i=0;i<dat->childrenCount;i++) {
				SendMessage(dat->children[i], DM_SENDMESSAGE, wParam, lParam);
			}
		}
		break;
	case DM_OPTIONSAPPLIED:
		{
			RECT rc;
			dat->flags = g_dat->flags;
			if (!(dat->flags & SMF_SHOWSTATUSBAR)) {
				ShowWindow(dat->hwndStatus, SW_HIDE);
			} else {
				ShowWindow(dat->hwndStatus, SW_SHOW);
			}
			ws = GetWindowLong(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
			if (dat->flags & SMF_SHOWTITLEBAR) {
				ws |= WS_CAPTION;
			}
			SetWindowLong(hwndDlg, GWL_STYLE, ws);

			ws = GetWindowLong(hwndDlg, GWL_EXSTYLE)& ~WS_EX_LAYERED;
			ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
			SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
			if (dat->flags & SMF_USETRANSPARENCY) {
   				pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->inactiveAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}

			ws = GetWindowLong(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM);
			if (dat->flags & SMF_TABSATBOTTOM) {
				ws |= TCS_BOTTOM;
			}
			SetWindowLong(dat->hwndTabs, GWL_STYLE, ws);
			RedrawWindow(dat->hwndTabs, NULL, NULL, RDW_INVALIDATE);
			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);
			SendMessage(hwndDlg, WM_SIZE, 0, 0);
			//RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			break;
		}
	case DM_UPDATETITLE:
		{
			struct MessageWindowData * mdat = (struct MessageWindowData *) lParam;
			TCITEM tci;
			int tabId;
			TCHAR *tContactName;
			if (mdat && mdat->hwnd == dat->hwndActive) {
				TCHAR *newtitle, oldtitle[256];
#if defined ( _UNICODE )
				newtitle = GetWindowTitle(mdat->hContact, mdat->szProto);
#else
				newtitle = GetWindowTitle(mdat->hContact, mdat->szProto);
#endif
				GetWindowText(hwndDlg, oldtitle, sizeof(oldtitle));
				if (lstrcmp(newtitle, oldtitle)) { //swt() flickers even if the title hasn't actually changed
					SetWindowText(hwndDlg, newtitle);
					//SendMessage(hwndDlg, WM_SIZE, 0, 0);
				}
				free(newtitle);
			}
			tabId = GetTabFromHWND(dat, mdat->hwnd);
			tContactName = GetTabName(mdat->hContact);
			tci.mask = TCIF_TEXT;
			tci.pszText = tContactName;
			TabCtrl_SetItem(dat->hwndTabs, tabId, &tci);
			free(tContactName);
			break;
		}
	case DM_UPDATEWINICON:
		{
			struct MessageWindowData * mdat = (struct MessageWindowData *) lParam;
			if (mdat) {
				if (mdat->szProto) {
					int i, icoIdx = 0;
					WORD wStatus;
					char *szProto = mdat->szProto;
					HANDLE hContact = mdat->hContact;
					if (strcmp(mdat->szProto, "MetaContacts") == 0 && DBGetContactSettingByte(NULL,"CLC","Meta",0) == 0) {
						hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(UINT)mdat->hContact, 0);
						if (hContact != NULL) {
							szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(UINT)hContact,0);
						} else {
							hContact = mdat->hContact;
						}
					}
					wStatus = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
					mdat->wStatus = wStatus;
					if (mdat->hwnd == dat->hwndActive) {
						if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) {
							if (mdat->showTyping && (g_dat->flags&SMF_SHOWTYPINGWIN)) {
								SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) g_dat->hIcons[SMF_ICON_TYPING]);
							} else if (mdat->showUnread && (GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg)) {
								SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
							} else {
								SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedProtoIcon(szProto, wStatus));
							}
						} else {
							SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
						}
					}
					SendDlgItemMessage(mdat->hwnd, IDC_USERMENU, BM_SETIMAGE, IMAGE_ICON, (LPARAM) LoadSkinnedProtoIcon(szProto, wStatus));
					icoIdx = 0;
					for (i = 0; i < g_dat->protoNum; i++) {
						if (!strcmp(g_dat->protoNames[i], szProto)) {
							icoIdx = wStatus - ID_STATUS_OFFLINE + (ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1) * (i +1) + 2;
							break;
						}
					}
					if (mdat->hwnd != dat->hwndActive) {
						if (mdat->showTyping) {
							icoIdx = 1;
						} else if (mdat->showUnread & 1) {
							icoIdx = 0;
						}
					}
					i = GetTabFromHWND(dat, mdat->hwnd);
					if (i>=0) {
						TCITEM tci;
						tci.mask = TCIF_IMAGE;
						tci.iImage = icoIdx;
						TabCtrl_SetItem(dat->hwndTabs, i, &tci);
					}
				}
			}
			break;
		}
	case DM_UPDATESTATUSBAR:
		break;
	case DM_SWITCHSTATUSBAR:
		dat->flags ^= SMF_SHOWSTATUSBAR;
		if (!(dat->flags & SMF_SHOWSTATUSBAR)) {
			ShowWindow(dat->hwndStatus, SW_HIDE);
		} else {
			ShowWindow(dat->hwndStatus, SW_SHOW);
		}
		SendMessage(hwndDlg, WM_SIZE, 0, 0);
		break;
	case DM_SWITCHTOOLBAR:
		{
			int i;
			dat->flags ^= SMF_SHOWBTNS;
			for (i=0;i<dat->childrenCount;i++) {
				SendMessage(dat->children[i], DM_SWITCHTOOLBAR, 0, 0);
			}
			SendMessage(hwndDlg, WM_SIZE, 0, 0);
		}
		break;
	case DM_SWITCHTITLEBAR:
		{
			RECT rc;
			dat->flags ^= SMF_SHOWTITLEBAR;
			ws = GetWindowLong(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
			if (dat->flags & SMF_SHOWTITLEBAR) {
				ws |= WS_CAPTION;
			}
			SetWindowLong(hwndDlg, GWL_STYLE, ws);
			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);
//			SendMessage(hwndDlg, WM_SIZE, 0, 0);
			RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
		}
		break;
	case DM_CASCADENEWWINDOW:
		if ((HWND) wParam == hwndDlg)
			break;
		{
			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;
	//case DM_MESSAGESENDING:
	//	dat->messagesInProgress += wParam ? -1 : 1;
	//	if (dat->messagesInProgress < 0) dat->messagesInProgress = 0;
	//	break;
	}
	return FALSE;
}
BOOL CALLBACK DlgProcParentWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 
{
	DWORD ws;
	struct ParentWindowData *dat;
	dat = (struct ParentWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA);
	if (!dat && msg!=WM_INITDIALOG) return FALSE;
	switch (msg) {
	case WM_INITDIALOG:
		{
			struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam;
			dat = (struct ParentWindowData *) malloc(sizeof(struct ParentWindowData));
			dat->hContact = newData->hContact;
			dat->nFlash = 0;
			dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT);
			dat->childrenCount = 0;
			dat->children = NULL;
			dat->hwnd = hwndDlg;
			dat->flags = g_dat->flags;// | SMF_SHOWTITLEBAR;
			dat->mouseLBDown = 0;
			dat->windowWasCascaded = 0;
			dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL);
			{
				int statwidths[4];
				RECT rc;
				SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
				GetWindowRect(dat->hwndStatus, &rc);
				/*
				statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_TYPING_WIDTH - SB_SENDING_WIDTH;
				statwidths[1] = rc.right - rc.left - SB_TYPING_WIDTH - SB_SENDING_WIDTH; //rc.right - rc.left - SB_CHAR_WIDTH;
				statwidths[2] = rc.right - rc.left - SB_TYPING_WIDTH; //rc.right - rc.left - SB_CHAR_WIDTH;
				statwidths[3] = -1;
				SendMessage(dat->hwndStatus, SB_SETPARTS, 4, (LPARAM) statwidths);
				*/
				statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_TYPING_WIDTH;
				statwidths[1] = rc.right - rc.left - SB_TYPING_WIDTH;
				statwidths[2] = -1;
				SendMessage(dat->hwndStatus, SB_SETPARTS, 3, (LPARAM) statwidths);
			}
			dat->hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
			dat->hwndActive = NULL;
			SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) dat);
			if (g_dat->hIconList != NULL) {
				TabCtrl_SetImageList(dat->hwndTabs, g_dat->hIconList);
			}
			WindowList_Add(g_dat->hParentWindowList, hwndDlg, 0);
			dat->tabCtrlDat = (struct TabCtrlData *) malloc(sizeof(struct TabCtrlData));
			dat->tabCtrlDat->bDragging = FALSE;
			SetWindowLong(dat->hwndTabs, GWL_USERDATA, (LONG) dat->tabCtrlDat);
			OldTabCtrlProc = (WNDPROC) SetWindowLong(dat->hwndTabs, GWL_WNDPROC, (LONG) TabCtrlProc);
			ws = GetWindowLong(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM);
			if (dat->flags & SMF_TABSATBOTTOM) {
				ws |= TCS_BOTTOM;
			}
			SetWindowLong(dat->hwndTabs, GWL_STYLE, ws);
			ws = GetWindowLong(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
			if (dat->flags & SMF_SHOWTITLEBAR) {
				ws |= WS_CAPTION;
				SetWindowLong(hwndDlg, GWL_STYLE, ws);
			} else {
				RECT rc;
				SetWindowLong(hwndDlg, GWL_STYLE, ws);
				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); 
			}
			ws = GetWindowLong(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
			ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
			SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
			if (dat->flags & SMF_USETRANSPARENCY) {
   				pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->inactiveAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}

			//SetWindowPos(dat->hwndTabs, 0, 0, -10, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
			if (!(dat->flags & SMF_SHOWSTATUSBAR)) {
				ShowWindow(dat->hwndStatus, SW_HIDE);
			}
			if (dat->flags & SMF_USETABS) {
				if (ScriverRestoreWindowPosition(hwndDlg, NULL, SRMMMOD, "", 0, SW_HIDE)) {
					SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE  | SWP_HIDEWINDOW);
				}
			} else {
				int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT);
				if (ScriverRestoreWindowPosition(hwndDlg, savePerContact ? dat->hContact : NULL, SRMMMOD, "", 0, SW_HIDE)) {
				//if (Utils_RestoreWindowPosition(GetParent(hwndDlg), savePerContact ? dat->hContact : NULL, SRMMMOD, "")) {
					if (savePerContact) {
						if (ScriverRestoreWindowPosition(hwndDlg, NULL, SRMMMOD, "", RWPF_NOSIZE, SW_HIDE))
					//	if (Utils_RestoreWindowPositionNoMove(GetParent(hwndDlg), NULL, SRMMMOD, ""))
						SetWindowPos(GetParent(hwndDlg), 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE);
					}
					else
						SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE);
				}
				if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE))
					WindowList_Broadcast(g_dat->hParentWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded);
			}
		}
		return TRUE;
	case WM_GETMINMAXINFO:
	{
		MINMAXINFO *mmi = (MINMAXINFO *) lParam;
		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 {
//		}
//		if (!IsIconic(hwndDlg)) {
			int i;
			RECT rc, rcStatus, rcChild, rcWindow;
			SIZE size;
			dat->bMinimized = 0;
			GetClientRect(hwndDlg, &rc);
			GetWindowRect(hwndDlg, &rcWindow);
			rcStatus.top = rcStatus.bottom = 0;
			if (dat->flags & SMF_SHOWSTATUSBAR) {
				int statwidths[4];
				GetWindowRect(dat->hwndStatus, &rcStatus);
				statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_TYPING_WIDTH;
				statwidths[1] = rc.right - rc.left - SB_TYPING_WIDTH;
				statwidths[2] = -1;
				SendMessage(dat->hwndStatus, SB_SETPARTS, 3, (LPARAM) statwidths);
				SendMessage(dat->hwndStatus, WM_SIZE, 0, 0);
			}
			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));
			for (i=0;i<dat->childrenCount;i++) {
				if (dat->children[i] == dat->hwndActive) {
					MoveWindow(dat->children[i], rcChild.left, rcChild.top, rcChild.right-rcChild.left, rcChild.bottom - rcChild.top, TRUE);
					RedrawWindow(GetDlgItem(dat->children[i], IDC_LOG), NULL, NULL, RDW_INVALIDATE);
				} 
			}
			if (dat->flags & SMF_SHOWSTATUSBAR) {
				RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
			}
		}
		return FALSE;
	case WM_SETFOCUS:
		SetFocus(dat->hwndActive);
		return TRUE;
	case WM_CLOSE:
		DestroyWindow(hwndDlg);
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDCANCEL:
			//DestroyWindow(hwndDlg);
			return TRUE;
		}
	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)) {
							struct MessageWindowData * mdat = (struct MessageWindowData *) tci.lParam;
							ActivateChild(dat, mdat->hwnd);
						}
					}
					break;
				case NM_RCLICK:
					{
						TCHITTESTINFO thinfo;
						int tabId, x, y;
						GetCursorPos(&thinfo.pt);
						x = thinfo.pt.x; 
						y = thinfo.pt.y;
						ScreenToClient(dat->hwndTabs, &thinfo.pt);
						tabId = TabCtrl_HitTest(dat->hwndTabs, &thinfo);
						if (tabId != -1) {
							struct MessageWindowData * mwd = GetChildFromTab(dat->hwndTabs, tabId);
							//CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) mwd->hContact, 0);
							HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) mwd->hContact, 0);
							TrackPopupMenu(hMenu, 0, x, y, 0, mwd->hwnd, NULL);
							DestroyMenu(hMenu);
						}
					}
					break;
				}
			} else if (pNMHDR->hwndFrom == dat->hwndStatus)  {
				switch (pNMHDR->code) {
				case NM_CLICK:
					{
						NMMOUSE *nm=(NMMOUSE*)lParam;
						RECT rc;
						SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
						if (nm->pt.x >= rc.left) 
							SendMessage(dat->hwndActive, DM_SWITCHUNICODE, 0, 0);
					}
				}
				break;
			}
		}
		break;
	case WM_DROPFILES:
		SendMessage(dat->hwndActive, WM_DROPFILES, wParam, lParam);
		break;
	case WM_TIMER:
		if (wParam == TIMERID_FLASHWND) {
			if ((dat->nFlash > dat->nFlashMax)) {// || ((GetActiveWindow() == hwndDlg) && (GetForegroundWindow() == hwndDlg))) {
				KillTimer(hwndDlg, TIMERID_FLASHWND);
				FlashWindow(hwndDlg, FALSE);
			} else if (dat->nFlash < dat->nFlashMax) {
				FlashWindow(hwndDlg, TRUE);
				dat->nFlash++;
			}
		}
		break;
	case WM_CONTEXTMENU:
	{
		if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) {
			RECT rc;
			POINT pt, pt2;
			GetCursorPos(&pt);
			pt2.x = pt.x;
			pt2.y = pt.y;
			ScreenToClient(dat->hwndStatus, &pt);
			SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
			if (pt.x >= rc.left && dat->hwndActive != NULL) {
				int codePage = (int) SendMessage(dat->hwndActive, DM_GETCODEPAGE, 0, 0);
				int i, iSel;
				for(i = 0; i < GetMenuItemCount(g_dat->hMenuANSIEncoding); i++) {
					CheckMenuItem (g_dat->hMenuANSIEncoding, i, MF_BYPOSITION | MF_UNCHECKED);
				}
				if(codePage == CP_ACP) {
					CheckMenuItem(g_dat->hMenuANSIEncoding, 0, MF_BYPOSITION | MF_CHECKED);
				} else {
					CheckMenuItem(g_dat->hMenuANSIEncoding, codePage, MF_BYCOMMAND | MF_CHECKED);
				}
				iSel = TrackPopupMenu(g_dat->hMenuANSIEncoding, TPM_RETURNCMD, pt2.x, pt2.y, 0, hwndDlg, NULL);
				if (iSel >= 500) {
					if (iSel == 500) iSel = CP_ACP;
					SendMessage(dat->hwndActive, DM_SETCODEPAGE, 0, iSel);
				}
			}
			else 
				SendMessage(dat->hwndActive, WM_CONTEXTMENU, (WPARAM)hwndDlg, 0);
		}
		break;
	}
	case WM_ACTIVATE:
		if (LOWORD(wParam) == WA_INACTIVE) {
			ws = GetWindowLong(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
			ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
			SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
			if (dat->flags & SMF_USETRANSPARENCY) {
   				pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->inactiveAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}
		}
		if (LOWORD(wParam) != WA_ACTIVE)
			break;
	case WM_MOUSEACTIVATE:
		if (KillTimer(hwndDlg, TIMERID_FLASHWND)) {
			FlashWindow(hwndDlg, FALSE);
			dat->nFlash = 0;
		}
		ws = GetWindowLong(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED;
		ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
		SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
		if (dat->flags & SMF_USETRANSPARENCY) {
   			pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->activeAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
		}
		SendMessage(dat->hwndActive, WM_ACTIVATE, WA_ACTIVE, 0);
		break;
	case WM_LBUTTONDOWN:
		dat->mouseLBDown = 1;
		GetCursorPos(&dat->mouseLBDownPos);
		SetCapture(hwndDlg);
		break;
	case WM_LBUTTONUP:
		dat->mouseLBDown = 0;
		ReleaseCapture();
		break;
	case WM_MOUSEMOVE:
		if (dat->mouseLBDown) { 
			POINT pt;
			RECT  rc;
			GetCursorPos(&pt);
			GetWindowRect(hwndDlg, &rc);
			SetWindowPos(hwndDlg, 0, rc.left - (dat->mouseLBDownPos.x - pt.x), rc.top - (dat->mouseLBDownPos.y - pt.y), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			dat->mouseLBDownPos = pt;
		}
		break;
	case WM_DESTROY:
		{
			g_dat->hParent = NULL;
			SetWindowLong(hwndDlg, GWL_USERDATA, 0);
			WindowList_Remove(g_dat->hParentWindowList, hwndDlg);
			if (dat->children!=NULL) free (dat->children);
			free(dat->tabCtrlDat);
			free(dat);
			if (dat->flags & SMF_USETABS) {
				WINDOWPLACEMENT wp = { 0 };
				wp.length = sizeof(wp);
				GetWindowPlacement(hwndDlg, &wp);
				DBWriteContactSettingDword(NULL, SRMMMOD, "x", wp.rcNormalPosition.left);
				DBWriteContactSettingDword(NULL, SRMMMOD, "y", wp.rcNormalPosition.top);
				DBWriteContactSettingDword(NULL, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left);
				DBWriteContactSettingDword(NULL, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
			} else {
				WINDOWPLACEMENT wp = { 0 };
				HANDLE hContact;
				if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT))
					hContact = dat->hContact;
				else
					hContact = NULL;
				wp.length = sizeof(wp);
				GetWindowPlacement(hwndDlg, &wp);
				if (!dat->windowWasCascaded) {
					DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left);
					DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top);
				}
				DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left);
				DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
			}

		}
		break;
	case DM_ERRORDECIDED:
		break;
	case DM_STARTFLASHING:
		if (GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg) {
			dat->nFlash = 0;
			SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
		}
		break;
	case DM_REMOVECHILD:
		{
			RemoveChild(dat, (HWND) lParam);
			if (dat->childrenCount == 0) {
				DestroyWindow(hwndDlg);
			} else {
			}
		}
		return TRUE;
	case DM_ADDCHILD:
		{
			struct MessageWindowData * mdat = (struct MessageWindowData *) lParam;
			AddChild(dat, mdat);
		}
		return TRUE;
	case DM_ACTIVATECHILD:
		if((HWND) lParam != dat->hwndActive) {
			ActivateChild(dat, (HWND) lParam);
		}
		return TRUE;
	case DM_ACTIVATEPREV:
		ActivatePrevChild(dat, (HWND) lParam);
		return TRUE;
	case DM_ACTIVATENEXT:
		ActivateNextChild(dat, (HWND) lParam);
		return TRUE;
	case DM_SENDMESSAGE:
		{
			int i;
			for (i=0;i<dat->childrenCount;i++) {
				SendMessage(dat->children[i], DM_SENDMESSAGE, wParam, lParam);
			}
		}
		break;
	case DM_OPTIONSAPPLIED:
		{
			RECT rc;
			dat->flags = g_dat->flags;
			if (!(dat->flags & SMF_SHOWSTATUSBAR)) {
				ShowWindow(dat->hwndStatus, SW_HIDE);
			} else {
				ShowWindow(dat->hwndStatus, SW_SHOW);
			}
			ws = GetWindowLong(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
			if (dat->flags & SMF_SHOWTITLEBAR) {
				ws |= WS_CAPTION;
			} 
			SetWindowLong(hwndDlg, GWL_STYLE, ws);

			ws = GetWindowLong(hwndDlg, GWL_EXSTYLE)& ~WS_EX_LAYERED;
			ws |= dat->flags & SMF_USETRANSPARENCY ? WS_EX_LAYERED : 0;
			SetWindowLong(hwndDlg , GWL_EXSTYLE , ws);
			if (dat->flags & SMF_USETRANSPARENCY) {
   				pSetLayeredWindowAttributes(hwndDlg, RGB(255,255,255), (BYTE)(255-g_dat->inactiveAlpha), LWA_ALPHA);
//				RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}

			ws = GetWindowLong(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM);
			if (dat->flags & SMF_TABSATBOTTOM) {
				ws |= TCS_BOTTOM;
			} 
			SetWindowLong(dat->hwndTabs, GWL_STYLE, ws);
			RedrawWindow(dat->hwndTabs, NULL, NULL, RDW_INVALIDATE);
			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);
			SendMessage(hwndDlg, WM_SIZE, 0, 0);
			//RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			break;
		}
	case DM_UPDATETITLE:
		{
			struct MessageWindowData * mdat = (struct MessageWindowData *) lParam;
			TCITEM tci;
			int tabId;
			char newtitle[256], oldtitle[256];
			char *szStatus, *contactName, *pszNewTitleEnd;
			TCHAR *tContactName;
			if (mdat && mdat->hwnd == dat->hwndActive) {
				pszNewTitleEnd = "Message Session";
				if (mdat->hContact) {
					if (mdat->szProto) {
						CONTACTINFO ci;
						char buf[128];
						int statusIcon = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON);

						buf[0] = 0;
						mdat->wStatus = DBGetContactSettingWord(mdat->hContact, mdat->szProto, "Status", ID_STATUS_OFFLINE);
						contactName = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) mdat->hContact, 0);
						ZeroMemory(&ci, sizeof(ci));
						ci.cbSize = sizeof(ci);
						ci.hContact = mdat->hContact;
						ci.szProto = mdat->szProto;
						ci.dwFlag = CNF_UNIQUEID;
						if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
							switch (ci.type) {
							case CNFT_ASCIIZ:
								mir_snprintf(buf, sizeof(buf), "%s", ci.pszVal);
								miranda_sys_free(ci.pszVal);
								break;
							case CNFT_DWORD:
								mir_snprintf(buf, sizeof(buf), "%u", ci.dVal);
								break;
							}
						}
						szStatus = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mdat->szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord(mdat->hContact, mdat->szProto, "Status", ID_STATUS_OFFLINE), 0);
						if (statusIcon)
							mir_snprintf(newtitle, sizeof(newtitle), "%s - %s", contactName, Translate(pszNewTitleEnd));
						else
							mir_snprintf(newtitle, sizeof(newtitle), "%s (%s): %s", contactName, szStatus, Translate(pszNewTitleEnd));

					}
				}
				else
					lstrcpynA(newtitle, pszNewTitleEnd, sizeof(newtitle));
				GetWindowTextA(hwndDlg, oldtitle, sizeof(oldtitle));
				if (lstrcmpA(newtitle, oldtitle)) { //swt() flickers even if the title hasn't actually changed
					SetWindowTextA(hwndDlg, newtitle);
					//SendMessage(hwndDlg, WM_SIZE, 0, 0);
				}
			}
			tabId = GetTabFromHWND(dat, mdat->hwnd);
			tContactName = GetTabName(mdat->hContact);
			tci.mask = TCIF_TEXT;
			tci.pszText = tContactName;
			TabCtrl_SetItem(dat->hwndTabs, tabId, &tci);
			free(tContactName);
			break;
		}
	case DM_UPDATEWINICON:
		{
			struct MessageWindowData * mdat = (struct MessageWindowData *) lParam;
			if (mdat) {
				if (mdat->szProto) {
					int i, icoIdx = 0;
					WORD wStatus;
					wStatus = DBGetContactSettingWord(mdat->hContact, mdat->szProto, "Status", ID_STATUS_OFFLINE);
					if (mdat->hwnd == dat->hwndActive) {
						if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) {
							if (mdat->showTyping && (dat->flags&SMF_SHOWTYPINGWIN)) {
								SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) g_dat->hIcons[SMF_ICON_TYPING]);
							} else if (mdat->showUnread && (GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg)) {
								SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));	
							} else {
								SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedProtoIcon(mdat->szProto, wStatus));
							}
						} else {
							SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
						}
					}
					icoIdx = 0;
					for (i = 0; i < g_dat->protoNum; i++) {
						if (!strcmp(g_dat->protoNames[i], mdat->szProto)) {
							icoIdx = wStatus - ID_STATUS_OFFLINE + (ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1) * (i +1) + 2;
							break;
						}
					}
					if (mdat->hwnd != dat->hwndActive) {
						if (mdat->showTyping) {
							icoIdx = 1;
						} else if (mdat->showUnread & 1) {
							icoIdx = 0;
						}
					}
					i = GetTabFromHWND(dat, mdat->hwnd);
					if (i>=0) {
						TCITEM tci;
						tci.mask = TCIF_IMAGE;
						tci.iImage = icoIdx;
						TabCtrl_SetItem(dat->hwndTabs, i, &tci);
					}
				} 
			} 
			break;
		}
	case DM_UPDATESTATUSBAR:
		break;
	case DM_SWITCHSTATUSBAR:
		dat->flags ^= SMF_SHOWSTATUSBAR;
		if (!(dat->flags & SMF_SHOWSTATUSBAR)) {
			ShowWindow(dat->hwndStatus, SW_HIDE);
		} else {
			ShowWindow(dat->hwndStatus, SW_SHOW);
		}
		SendMessage(hwndDlg, WM_SIZE, 0, 0);
		break;
	case DM_SWITCHTOOLBAR:
		{
			int i;
			dat->flags ^= SMF_SHOWBTNS;
			for (i=0;i<dat->childrenCount;i++) {
				SendMessage(dat->children[i], DM_SWITCHTOOLBAR, 0, 0);
			}
			SendMessage(hwndDlg, WM_SIZE, 0, 0);
		}
		break;
	case DM_SWITCHTITLEBAR:
		{
			RECT rc;
			dat->flags ^= SMF_SHOWTITLEBAR;
			ws = GetWindowLong(hwndDlg, GWL_STYLE) & ~(WS_CAPTION);
			if (dat->flags & SMF_SHOWTITLEBAR) {
				ws |= WS_CAPTION;
			} 
			SetWindowLong(hwndDlg, GWL_STYLE, ws);
			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); 
//			SendMessage(hwndDlg, WM_SIZE, 0, 0);
			RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
		}
		break;
	case DM_CASCADENEWWINDOW:
		if ((HWND) wParam == hwndDlg)
			break;
		{
			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;
	//case DM_MESSAGESENDING:
	//	dat->messagesInProgress += wParam ? -1 : 1;
	//	if (dat->messagesInProgress < 0) dat->messagesInProgress = 0;
	//	break;
	}
	return FALSE;
}
BOOL CALLBACK ContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	ChatContainer *container;
	container = (ChatContainer *) GetWindowLong(hwndDlg, GWL_USERDATA);
	if (container==NULL && msg!=WM_INITDIALOG) return FALSE;
	switch (msg) {
		case WM_INITDIALOG:
			SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) muccIcon[MUCC_IDI_CHAT]);
			container = (ChatContainer *) lParam;
			container->setHWND(hwndDlg);
			TabCtrl_SetImageList(GetDlgItem(hwndDlg, IDC_TABS), hImageList);
			SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) container);
			ShowWindow(hwndDlg, SW_SHOW);
			SetEvent(container->getEvent());
			return TRUE;
		case WM_GETMINMAXINFO:
			MINMAXINFO *mmi;
			RECT rcChild, rcWindow;
			mmi = (MINMAXINFO *) lParam;
			GetWindowRect(hwndDlg, &rcWindow);
			container->getChildWindowRect(&rcChild);
			mmi->ptMinTrackSize.x = 380;
			mmi->ptMinTrackSize.y = 130 + (rcWindow.bottom - rcWindow.top) - (rcChild.bottom - rcChild.top);
			return FALSE;
		case WM_SIZE:
			if (IsIconic(hwndDlg) || wParam == SIZE_MINIMIZED) break;
			{
				RECT rc, rcChild, rcWindow;
				GetClientRect(hwndDlg, &rc);
				HWND hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
				MoveWindow(hwndTabs, 0, 0, (rc.right - rc.left), (rc.bottom - rc.top) - 0,	FALSE);
				RedrawWindow(hwndTabs, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE);
				container->getChildWindowRect(&rcChild);
				if ((rcChild.bottom-rcChild.top) < 130 || (rcChild.right-rcChild.left) < 380) {
					GetWindowRect(hwndDlg, &rcWindow);
					if ((rcChild.bottom-rcChild.top) < 130) {
						rcWindow.bottom = rcWindow.top + 130 + (rcWindow.bottom - rcWindow.top) - (rcChild.bottom - rcChild.top);
					} 
					if ((rcChild.right-rcChild.left) < 380) {
						rcWindow.right = rcWindow.left + 380;
					}
					MoveWindow(hwndDlg, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
					container->getChildWindowRect(&rcChild);
				}
				if (container->getActive()!=NULL) {
					MoveWindow(container->getActive()->getHWND(), rcChild.left, rcChild.top, rcChild.right-rcChild.left, rcChild.bottom - rcChild.top, TRUE);
				}
			}
			return TRUE;
		case DM_CREATECHILD:
			SetWindowLong(hwndDlg, DWL_MSGRESULT, (LONG)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_GROUPCHAT_LOG), hwndDlg, (DLGPROC) wParam, (LPARAM) lParam));
			return TRUE;
		case DM_ADDCHILD:
			container->addChild((ChatWindow *) lParam);
			return TRUE;
		case DM_REMOVECHILD:
			container->removeChild((ChatWindow *) lParam);
			return TRUE;
		case DM_CHANGECHILDDATA:
			container->removeChild((ChatWindow *) lParam);
			return TRUE;
		case DM_SETUNREAD:
			container->setUnread((ChatWindow *) lParam, (int)wParam);
			return TRUE;
		case DM_FLASHWINDOW:
			if (GetActiveWindow() != hwndDlg && GetForegroundWindow() != hwndDlg) {
				container->setFlash(0);
				SetTimer(hwndDlg, TIMERID_FLASHWND, container->getFlashTimeout(), NULL);
			}
			return TRUE;
		case WM_NOTIFY:
			{
				NMHDR* pNMHDR = (NMHDR*) lParam;
				switch (pNMHDR->code) {
				case TCN_SELCHANGE:
					{
						TCITEM tci = {0};
						HWND hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
						int iSel = TabCtrl_GetCurSel(hwndTabs);
						tci.mask = TCIF_PARAM;
						if (TabCtrl_GetItem(hwndTabs, iSel, &tci)) {
							ChatWindow * chatWindow = (ChatWindow *) tci.lParam;
							container->activateChild(chatWindow);
						}
					}
					break;
				case NM_CLICK:
					{
						FILETIME ft;
						TCHITTESTINFO thinfo;
						int tabId;
						HWND hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
						GetSystemTimeAsFileTime(&ft);
						GetCursorPos(&thinfo.pt);
						ScreenToClient(hwndTabs, &thinfo.pt);
						tabId = TabCtrl_HitTest(hwndTabs, &thinfo);
						if (tabId != -1 && tabId == container->lastClickTab &&
							(ft.dwLowDateTime - container->lastClickTime) < (GetDoubleClickTime() * 10000)) {
							SendMessage(container->getChildFromTab(tabId)->getHWND(), WM_CLOSE, 0, 0);
							container->lastClickTab = -1;
						} else {
							container->lastClickTab = tabId;
						}
						container->lastClickTime = ft.dwLowDateTime;
					}
					break;
				}

			}
			break;
		case WM_ACTIVATE:
			if (LOWORD(wParam) != WA_ACTIVE)
				break;
		case WM_MOUSEACTIVATE:
			if (KillTimer(hwndDlg, TIMERID_FLASHWND)) {
				FlashWindow(hwndDlg, FALSE);
			}
			/*
			if (container->getActive()!=NULL) {
				container->setUnread(container->getActive(), 0);
				SendMessage(container->getActive()->getHWND(), WM_ACTIVATE, WA_ACTIVE, 0);
			}*/
			break;
		case WM_CLOSE:
			EndDialog(hwndDlg, 0);
			return FALSE;
		case WM_TIMER:
			if (wParam == TIMERID_FLASHWND) {
				if ((container->getFlash() > container->getFlashMax()) || (GetActiveWindow() == hwndDlg) || (GetForegroundWindow() == hwndDlg)) {
					KillTimer(hwndDlg, TIMERID_FLASHWND);
					FlashWindow(hwndDlg, FALSE);
				} else if (container->getFlash() < container->getFlashMax()) {
					FlashWindow(hwndDlg, TRUE);
					container->setFlash(container->getFlash()+1);
				}
			}
			break;
		case WM_DESTROY:
			SetWindowLong(hwndDlg, GWL_USERDATA, 0);
			delete container;
			return TRUE;

	}
	return FALSE;
}
HRESULT STDMETHODCALLTYPE playlists_tabs_extension::playlists_tabs_drop_target::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
{
	POINT pt = { ptl.x, ptl.y };
	bool isAltDown = (grfKeyState & MK_ALT) != 0;
	if (m_DropTargetHelper.is_valid()) m_DropTargetHelper->DragOver(&pt, *pdwEffect);

	if (ui_drop_item_callback::g_is_accepted_type(m_DataObject.get_ptr(), pdwEffect))
		return S_OK;

	*pdwEffect = DROPEFFECT_COPY;
	m_last_rmb = ((grfKeyState & MK_RBUTTON) != 0);

	if (last_over.x != pt.x || last_over.y != pt.y)
	{
		last_over = ptl;

		if (!m_is_accepted_type)
		{
			*pdwEffect = DROPEFFECT_NONE;
			mmh::ole::SetDropDescription(m_DataObject.get_ptr(), DROPIMAGE_INVALID, "", "");
			return S_OK;
		}

		static_api_ptr_t<playlist_manager> playlist_api;
		POINT pti, ptm;
		pti.y = pt.y;
		pti.x = pt.x;

		ptm = pti;
		ScreenToClient(p_list->get_wnd(), &ptm);

		HWND wnd = ChildWindowFromPointEx(p_list->get_wnd(), ptm, CWP_SKIPINVISIBLE);

		//	RECT plist;

		//	GetWindowRect(g_plist, &plist);
		//	RECT tabs;

		//	GetWindowRect(g_tab, &tabs);

		if (p_list->wnd_tabs)
		{

			POINT pttab;
			pttab = pti;


			if (wnd == p_list->wnd_tabs && ScreenToClient(p_list->wnd_tabs, &pttab))
			{
				TCHITTESTINFO hittest;
				hittest.pt.x = pttab.x;
				hittest.pt.y = pttab.y;
				int idx = TabCtrl_HitTest(p_list->wnd_tabs, &hittest);
				int old = playlist_api->get_active_playlist();
				if (cfg_drag_autoswitch && idx >= 0 && old != idx && !isAltDown) p_list->switch_to_playlist_delayed2(idx);//playlist_switcher::get()->set_active_playlist(idx);
				else p_list->kill_switch_timer();

				if (idx != -1 && !isAltDown)
				{
					pfc::string8 name;
					static_api_ptr_t<playlist_manager>()->playlist_get_name(idx, name);
					mmh::ole::SetDropDescription(m_DataObject.get_ptr(), DROPIMAGE_COPY, "Add to %1", name);
				}
				else
					mmh::ole::SetDropDescription(m_DataObject.get_ptr(), DROPIMAGE_COPY, "Add to new playlist", "");
			}
			else
				mmh::ole::SetDropDescription(m_DataObject.get_ptr(), DROPIMAGE_COPY, "Add to new playlist", "");

		}
		if ((!p_list->wnd_tabs || wnd != p_list->wnd_tabs))  p_list->kill_switch_timer();
	}

	return S_OK;



}
HRESULT STDMETHODCALLTYPE playlists_tabs_extension::playlists_tabs_drop_target::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
{
	POINT pt = { ptl.x, ptl.y };
	bool isAltDown = (grfKeyState & MK_ALT) != 0;
	if (m_DropTargetHelper.is_valid()) m_DropTargetHelper->Drop(pDataObj, &pt, *pdwEffect);

	p_list->kill_switch_timer();
	m_DataObject.release();
	last_over.x = 0;
	last_over.y = 0;

	if (!m_is_accepted_type)
	{
		mmh::ole::SetDropDescription(m_DataObject.get_ptr(), DROPIMAGE_INVALID, "", "");
		return S_OK;
	}

	static_api_ptr_t<playlist_manager> playlist_api;

	POINT pti, ptm;
	pti.y = pt.y;
	pti.x = pt.x;

	ptm = pti;
	ScreenToClient(p_list->get_wnd(), &ptm);

	HWND wnd = ChildWindowFromPointEx(p_list->get_wnd(), ptm, CWP_SKIPINVISIBLE);

	if (wnd)
	{

		bool process = !ui_drop_item_callback::g_on_drop(pDataObj);

		bool send_new_playlist = false;

		if (process && m_last_rmb)
		{
			process = false;
			enum { ID_DROP = 1, ID_NEW_PLAYLIST, ID_CANCEL };

			HMENU menu = CreatePopupMenu();

			uAppendMenu(menu, (MF_STRING), ID_DROP, "&Add files here");
			uAppendMenu(menu, (MF_STRING), ID_NEW_PLAYLIST, "&Add files to new playlist");
			uAppendMenu(menu, MF_SEPARATOR, 0, 0);
			uAppendMenu(menu, MF_STRING, ID_CANCEL, "&Cancel");

			int cmd = TrackPopupMenu(menu, TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, pt.x, pt.y, 0, p_list->get_wnd(), 0);
			DestroyMenu(menu);

			if (cmd)
			{
				switch (cmd)
				{
				case ID_DROP:
					process = true;
					break;
				case ID_NEW_PLAYLIST:
					process = true;
					send_new_playlist = true;
					break;
				}
			}
		}

		if (process)
		{
			metadb_handle_list data;
			static_api_ptr_t<playlist_incoming_item_filter> incoming_api;
			incoming_api->process_dropped_files(pDataObj, data, true, p_list->get_wnd());

			POINT pttab, ptpl;
			pttab = pti;
			ptpl = pti;


			int idx = -1;
			t_size newPlaylistIndex = pfc_infinite;
			//	if ((g_tab && wnd == g_tab) || g_plist && wnd == g_plist)


			//	bool processed = false;
			t_size target_index = playlist_api->get_active_playlist();


			if (p_list->wnd_tabs && wnd == p_list->wnd_tabs)
			{
				RECT tabs;

				GetWindowRect(p_list->wnd_tabs, &tabs);
				if (ScreenToClient(p_list->wnd_tabs, &pttab))
				{
					TCHITTESTINFO hittest;
					hittest.pt.x = pttab.x;
					hittest.pt.y = pttab.y;
					int idx = TabCtrl_HitTest(p_list->wnd_tabs, &hittest);
					int old = playlist_api->get_active_playlist();
					if (send_new_playlist || idx < 0 || isAltDown)
					{
						send_new_playlist = true;
						if (idx >= 0)
							newPlaylistIndex = idx;
					}
					else target_index = idx;
				}

			}


			if (send_new_playlist)
			{
				pfc::string8 playlist_name("Untitled");

				bool named = false;

				if (1 || 1)
				{
					FORMATETC   fe;
					STGMEDIUM   sm;
					HRESULT     hr = E_FAIL;

					//					memset(&sm, 0, sizeof(0));

					fe.cfFormat = CF_HDROP;
					fe.ptd = NULL;
					fe.dwAspect = DVASPECT_CONTENT;
					fe.lindex = -1;
					fe.tymed = TYMED_HGLOBAL;

					// User has dropped on us. Get the data from drag source
					hr = pDataObj->GetData(&fe, &sm);
					if (SUCCEEDED(hr))
					{

						// Display the data and release it.
						pfc::string8 temp;

						unsigned int /*n,*/t = uDragQueryFileCount((HDROP)sm.hGlobal);
						if (t == 1)
						{
							{
								uDragQueryFile((HDROP)sm.hGlobal, 0, temp);
								if (uGetFileAttributes(temp) & FILE_ATTRIBUTE_DIRECTORY)
								{
									playlist_name.set_string(pfc::string_filename_ext(temp));
									named = true;
								}
								else
								{
									playlist_name.set_string(pfc::string_filename(temp));
									named = true;
#if 0
									pfc::string_extension ext(temp);

									service_enum_t<playlist_loader> e;
									service_ptr_t<playlist_loader> l;
									if (e.first(l))
										do
										{
											if (!strcmp(l->get_extension(), ext))
											{
												playlist_name.set_string(pfc::string_filename(temp));
												named = true;
												l.release();
												break;
											}
											l.release();
										} while (e.next(l));
#endif
								}

							}
						}

						ReleaseStgMedium(&sm);
					}
				}

				unsigned new_idx;
				if (newPlaylistIndex == pfc_infinite)
					newPlaylistIndex = playlist_api->get_playlist_count();

				if (named && cfg_replace_drop_underscores) playlist_name.replace_char('_', ' ', 0);
				if (!named && cfg_pgen_tf) new_idx = playlist_api->create_playlist(string_pn(data, cfg_pgenstring), pfc_infinite, newPlaylistIndex);

				else  new_idx = playlist_api->create_playlist(playlist_name, pfc_infinite, newPlaylistIndex);

				playlist_api->playlist_add_items(new_idx, data, bit_array_false());
				if (main_window::config_get_activate_target_playlist_on_dropped_items())
					playlist_api->set_active_playlist(new_idx);

			}
			else
			{
				playlist_api->playlist_clear_selection(target_index);
				playlist_api->playlist_insert_items(target_index, idx, data, bit_array_true());
				if (main_window::config_get_activate_target_playlist_on_dropped_items())
					playlist_api->set_active_playlist(target_index);
			}

			data.remove_all();
		}
	}

	return S_OK;
}