Exemplo n.º 1
0
static void Docking_SetSize(HWND hwnd, LPRECT rc, bool query, bool move)
{
	RECT rcMonitor;
	Docking_GetMonitorRectFromPoint(
		docked == DOCKED_LEFT && !query ? (LPPOINT)&rc->right : (LPPOINT)rc, &rcMonitor);
	Docking_AdjustPosition(hwnd, &rcMonitor, rc, query, move);
}
Exemplo n.º 2
0
int Docking_ProcessWindowMessage(WPARAM wParam, LPARAM lParam)
{
	APPBARDATA abd;
	static int draggingTitle;
	MSG *msg = (MSG *)wParam;

	if (msg->message == WM_DESTROY)
		cfg::writeByte("CList", "Docked", (BYTE)docked);
	if (!docked && msg->message != WM_CREATE && msg->message != WM_MOVING && msg->message != WM_CREATEDOCKED && msg->message != WM_MOVE)
		return 0;

	switch (msg->message) {
	case WM_CREATE:
		//if (GetSystemMetrics(SM_CMONITORS)>1) return 0;
		if (cfg::getByte("CList", "Docked", 0))
			PostMessage(msg->hwnd, WM_CREATEDOCKED, 0, 0);
		draggingTitle = 0;
		return 0;

	case WM_CREATEDOCKED:
		//we need to post a message just after creation to let main message function do some work
		docked = (int)(char)cfg::getByte("CList", "Docked", 0);
		if (IsWindowVisible(msg->hwnd) && !IsIconic(msg->hwnd)) {
			RECT rc, rcMonitor;
			memset(&abd, 0, sizeof(abd));
			abd.cbSize = sizeof(abd);
			abd.hWnd = msg->hwnd;
			abd.lParam = 0;
			abd.uCallbackMessage = WM_DOCKCALLBACK;
			SHAppBarMessage(ABM_NEW, &abd);
			GetWindowRect(msg->hwnd, &rc);
			Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
			Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc);
			MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
		}
		break;

	case WM_ACTIVATE:
		memset(&abd, 0, sizeof(abd));
		abd.cbSize = sizeof(abd);
		abd.hWnd = msg->hwnd;
		SHAppBarMessage(ABM_ACTIVATE, &abd);
		return 0;

	case WM_WINDOWPOSCHANGED:
		memset(&abd, 0, sizeof(abd));
		abd.cbSize = sizeof(abd);
		abd.hWnd = msg->hwnd;
		SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
		return 0;

	case WM_MOVING:
		{
			RECT rcMonitor;
			POINT ptCursor;

			// stop early
			if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
				return 0;

			// GetMessagePos() is no good, position is always unsigned
			GetCursorPos(&ptCursor);
			Docking_GetMonitorRectFromPoint(ptCursor, &rcMonitor);

			if ((ptCursor.x < rcMonitor.left + EDGESENSITIVITY) || (ptCursor.x >= rcMonitor.right - EDGESENSITIVITY)) {
				if (!(GetWindowLongPtr(msg->hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) {
					SendMessage(msg->hwnd, CLUIINTM_REDRAW, 0, 0);
					MessageBox(0, TranslateT("The contact list cannot be docked when using the default title bar and border. Use a toolwindow or borderless style instead."),
						TranslateT("Contact list docking"), MB_OK);
					return 0;
				}
				memset(&abd, 0, sizeof(abd));
				abd.cbSize = sizeof(abd);
				abd.hWnd = msg->hwnd;
				abd.lParam = 0;
				abd.uCallbackMessage = WM_DOCKCALLBACK;
				SHAppBarMessage(ABM_NEW, &abd);
				if (ptCursor.x < rcMonitor.left + EDGESENSITIVITY)
					docked = DOCKED_LEFT;
				else
					docked = DOCKED_RIGHT;
				SendMessage(msg->hwnd, WM_LBUTTONUP, 0, MAKELPARAM(ptCursor.x, ptCursor.y));
				GetWindowRect(msg->hwnd, (LPRECT)msg->lParam);
				Docking_AdjustPosition(msg->hwnd, (LPRECT)&rcMonitor, (LPRECT)msg->lParam);
				PostMessage(msg->hwnd, CLUIINTM_REDRAW, 0, 0);
				return TRUE;
			}
		}
		return 0;

	case WM_MOVE:
		if (docked) {
			RECT rc, rcMonitor;
			Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
			GetWindowRect(msg->hwnd, &rc);
			Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc);
			MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
			return 1;
		}
		return 0;

	case WM_SIZING:
		{
			RECT rcMonitor;
			Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
			Docking_AdjustPosition(msg->hwnd, &rcMonitor, (LPRECT)msg->lParam);
			*((LRESULT *)lParam) = TRUE;
		}
		return TRUE;

	case WM_SHOWWINDOW:
		if (msg->lParam)
			return 0;
		if ((msg->wParam && docked < 0) || (!msg->wParam && docked > 0))
			docked = -docked;
		memset(&abd, 0, sizeof(abd));
		abd.cbSize = sizeof(abd);
		abd.hWnd = msg->hwnd;
		if (msg->wParam) {
			RECT rc, rcMonitor;
			Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
			abd.lParam = 0;
			abd.uCallbackMessage = WM_DOCKCALLBACK;
			SHAppBarMessage(ABM_NEW, &abd);
			GetWindowRect(msg->hwnd, &rc);
			Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc);
			MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
		}
		else SHAppBarMessage(ABM_REMOVE, &abd);
		return 0;

	case WM_NCHITTEST:
		{
			LONG result = DefWindowProc(msg->hwnd, WM_NCHITTEST, msg->wParam, msg->lParam);
			if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT || result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) {
				*((LRESULT *)lParam) = HTCLIENT; return TRUE;
			}
			if (docked == DOCKED_LEFT && result == HTLEFT) {
				*((LRESULT *)lParam) = HTCLIENT; return TRUE;
			}
			if (docked == DOCKED_RIGHT && result == HTRIGHT) {
				*((LRESULT *)lParam) = HTCLIENT; return TRUE;
			}
		}
		return 0;

	case WM_SYSCOMMAND:
		if ((msg->wParam & 0xFFF0) != SC_MOVE)
			return 0;
		SetActiveWindow(msg->hwnd);
		SetCapture(msg->hwnd);
		draggingTitle = 1;
		*((LRESULT *)lParam) = 0;
		return TRUE;

	case WM_MOUSEMOVE:
		if (!draggingTitle)
			return 0; {
			RECT rc;
			POINT pt;
			GetClientRect(msg->hwnd, &rc);
			if (((docked == DOCKED_LEFT || docked == -DOCKED_LEFT) && (short)LOWORD(msg->lParam) > rc.right) || ((docked == DOCKED_RIGHT || docked == -DOCKED_RIGHT) && (short)LOWORD(msg->lParam) < 0)) {
				ReleaseCapture();
				draggingTitle = 0;
				memset(&abd, 0, sizeof(abd));
				abd.cbSize = sizeof(abd);
				abd.hWnd = msg->hwnd;
				SHAppBarMessage(ABM_REMOVE, &abd);
				docked = 0;
				GetCursorPos(&pt);
				PostMessage(msg->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y));
				SetWindowPos(msg->hwnd, 0, pt.x - rc.right / 2, pt.y - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYSMCAPTION) / 2, cluiPos.right, cluiPos.bottom, SWP_NOZORDER);
			}
		}
		return 1;

	case WM_LBUTTONUP:
		if (draggingTitle) {
			ReleaseCapture();
			draggingTitle = 0;
		}
		return 0;

	case WM_DOCKCALLBACK:
		switch (msg->wParam) {
		case ABN_WINDOWARRANGE:
			ShowWindow(msg->hwnd, msg->lParam ? SW_HIDE : SW_SHOW);
			break;
		}
		return TRUE;

	case WM_DESTROY:
		if (docked > 0) {
			memset(&abd, 0, sizeof(abd));
			abd.cbSize = sizeof(abd);
			abd.hWnd = msg->hwnd;
			SHAppBarMessage(ABM_REMOVE, &abd);
		}
		return 0;
	}
	return 0;
}
Exemplo n.º 3
0
int Docking_ProcessWindowMessage(WPARAM wParam,LPARAM lParam)
{
	APPBARDATA abd;
	static int draggingTitle;
	MSG *msg=(MSG*)wParam;

	if(msg->message==WM_DESTROY) 
		DBWriteContactSettingByte(NULL,"CList","Docked",(BYTE)docked);
  
	if(!docked && msg->message!=WM_CREATE && msg->message!=WM_MOVING && msg->message!=WM_CREATEDOCKED && msg->message != WM_MOVE && msg->message != WM_SIZE) return 0;
	switch(msg->message) {
		case WM_CREATE:
			//if(GetSystemMetrics(SM_CMONITORS)>1) return 0;
			if(DBGetContactSettingByte(NULL,"CList","Docked",0)) 
            {
                PostMessage(msg->hwnd,WM_CREATEDOCKED,0,0);
            }
			draggingTitle=0;
			return 0;

		case WM_CREATEDOCKED:
			//we need to post a message just after creation to let main message function do some work
			docked=(int)(char)DBGetContactSettingByte(NULL,"CList","Docked",0);
			if(IsWindowVisible(msg->hwnd) && !IsIconic(msg->hwnd)) {
				RECT rc, rcMonitor;
				ZeroMemory(&abd,sizeof(abd));
				abd.cbSize=sizeof(abd);
				abd.hWnd=msg->hwnd;
				abd.lParam=0;
				abd.uCallbackMessage=WM_DOCKCALLBACK;
				SHAppBarMessage(ABM_NEW,&abd);
				GetWindowRect(msg->hwnd,&rc);
				Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
				Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
				MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);
				dock_prevent_moving=0;
				OnMoving(msg->hwnd,&rc);
				dock_prevent_moving=1;
				ReposButtons(msg->hwnd,0,NULL);
			}
			break;
    case WM_CAPTURECHANGED:
      ReposButtons(msg->hwnd,0,NULL);
      return 0;
		case WM_ACTIVATE:
			ZeroMemory(&abd,sizeof(abd));
			abd.cbSize=sizeof(abd);
			abd.hWnd=msg->hwnd;
			SHAppBarMessage(ABM_ACTIVATE,&abd);
			return 0;
   case WM_SIZE:
      ReposButtons(msg->hwnd,1,NULL);
      return 0;

		case WM_WINDOWPOSCHANGED:
			{
			 if (docked) ReposButtons(msg->hwnd,0,NULL);
			 return 0;
			ZeroMemory(&abd,sizeof(abd));
			abd.cbSize=sizeof(abd);
			abd.hWnd=msg->hwnd;
			SHAppBarMessage(ABM_WINDOWPOSCHANGED,&abd);
			ReposButtons(msg->hwnd,0,NULL);
			return 0;
			}
		case WM_MOVING:
			{
				RECT rcMonitor;
				RECT rcWindow;
				RECT *rc;
				int dx=0;
				POINT ptCursor;
                if (docked) return 0;
				// stop early
				if(!(GetAsyncKeyState(VK_CONTROL)&0x8000)) return 0;

				// GetMessagePos() is no good, position is always unsigned
				GetCursorPos(&ptCursor);
				GetWindowRect(msg->hwnd,&rcWindow);
				dock_drag_dx=rcWindow.left-ptCursor.x;
				dock_drag_dy=rcWindow.top-ptCursor.y;
				Docking_GetMonitorRectFromPoint(ptCursor,&rcMonitor);
				
				if(((ptCursor.x<rcMonitor.left+EDGESENSITIVITY) 
					|| (ptCursor.x>=rcMonitor.right-EDGESENSITIVITY))
					)
				{
					ZeroMemory(&abd,sizeof(abd));
					abd.cbSize=sizeof(abd);
					abd.hWnd=msg->hwnd;
					abd.lParam=0;
					abd.uCallbackMessage=WM_DOCKCALLBACK;
					SHAppBarMessage(ABM_NEW,&abd);
					if(ptCursor.x<rcMonitor.left+EDGESENSITIVITY) docked=DOCKED_LEFT;
					else docked=DOCKED_RIGHT;
				//	TempDock=1;				
					GetWindowRect(msg->hwnd,(LPRECT)msg->lParam);
					rc=(RECT*)msg->lParam;
					if (docked==DOCKED_RIGHT)
						dx=(rc->right>rcMonitor.right)?rc->right-rcMonitor.right:0;
					else
						dx=(rc->left<rcMonitor.left)?rc->left-rcMonitor.left:0;
					OffsetRect(rc,-dx,0);
					Docking_AdjustPosition(msg->hwnd,(LPRECT)&rcMonitor,(LPRECT)msg->lParam);
					SendMessage(msg->hwnd,WM_SIZE,0,0);				
					dock_prevent_moving=0;
                    OnMoving(msg->hwnd,(LPRECT)msg->lParam);
					dock_prevent_moving=1;
					mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
					DBWriteContactSettingByte(NULL,"CList","Docked",(BYTE)docked);
          ReposButtons(msg->hwnd,0,NULL);
					return TRUE;
				}
				return 0;
			}
        case WM_EXITSIZEMOVE:
            {
              RECT rcMonitor;
              RECT rcWindow;
			  if (TempDock) TempDock=0;
             GetWindowRect(msg->hwnd,&rcWindow);
			  Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
			  Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rcWindow);
			  *((LRESULT*)lParam)=TRUE;
			  dock_prevent_moving=0;
			  SetWindowPos(msg->hwnd,0,rcWindow.left,rcWindow.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOSENDCHANGING);
              OnMoving(msg->hwnd,&rcWindow);
              ReposButtons(msg->hwnd,0,NULL);//-=-=-=
			  dock_prevent_moving=1;		  
              return 1;
            }

		case WM_MOVE:
		{

			if(docked && 0) {
				RECT rc, rcMonitor;
				Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
				GetWindowRect(msg->hwnd,&rc);
				Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
				MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);
        OnMoving(msg->hwnd,&rc); 
        ReposButtons(msg->hwnd,0,NULL);//-=-=-=
       
				return 1;
			}
      ReposButtons(msg->hwnd,2,NULL);
			return 0;
		}
		case WM_SIZING:
			{
        
			/*RECT rcMonitor;
			Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
			Docking_AdjustPosition(msg->hwnd,&rcMonitor,(LPRECT)msg->lParam);
			*((LRESULT*)lParam)=TRUE;
            */
			RECT rc;
			int dx=0, dy=0;
			int  d=0; 
      if (docked) ReposButtons(msg->hwnd,0,NULL);
      return FALSE;
			rc=*(RECT*)(msg->lParam);
			dock_prevent_moving=0;
            OnMoving(msg->hwnd,&rc);
            //-=-=-=		
			return TRUE;
			}
		case WM_SHOWWINDOW:
			if(msg->lParam) return 0;
			if((msg->wParam && docked<0) || (!msg->wParam && docked>0)) docked=-docked;
			ZeroMemory(&abd,sizeof(abd));
			abd.cbSize=sizeof(abd);
			abd.hWnd=msg->hwnd;
			if(msg->wParam) {
				RECT rc, rcMonitor;
				Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
				abd.lParam=0;
				abd.uCallbackMessage=WM_DOCKCALLBACK;
				SHAppBarMessage(ABM_NEW,&abd);
				GetWindowRect(msg->hwnd,&rc);
				Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
				MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,FALSE);
                OnMoving(msg->hwnd,&rc);
                ReposButtons(msg->hwnd,0,NULL);//-=-=-=
			}
			else {
				SHAppBarMessage(ABM_REMOVE,&abd);
			}
			return 0;
		case WM_NCHITTEST:
		{	LONG result;
			result=DefWindowProc(msg->hwnd,WM_NCHITTEST,msg->wParam,msg->lParam);
			if(result==HTSIZE || result==HTTOP || result==HTTOPLEFT || result==HTTOPRIGHT ||
			   result==HTBOTTOM || result==HTBOTTOMRIGHT || result==HTBOTTOMLEFT) {*((LRESULT*)lParam)=HTCLIENT; return TRUE;}
			if(docked==DOCKED_LEFT && result==HTLEFT) {*((LRESULT*)lParam)=HTCLIENT; return TRUE;}
			if(docked==DOCKED_RIGHT && result==HTRIGHT) {*((LRESULT*)lParam)=HTCLIENT; return TRUE;}
		
			
			return 0;
		}
		case WM_SYSCOMMAND:
			if((msg->wParam&0xFFF0)!=SC_MOVE) return 0;
			SetActiveWindow(msg->hwnd);
			SetCapture(msg->hwnd);
			draggingTitle=1;
			*((LRESULT*)lParam)=0;
			return TRUE;
		case WM_MOUSEMOVE:

			if(!draggingTitle) return 0;
		{	RECT rc;
			POINT pt;
			GetClientRect(msg->hwnd,&rc);
			if(((docked==DOCKED_LEFT || docked==-DOCKED_LEFT) && (short)LOWORD(msg->lParam)>rc.right) ||
			   ((docked==DOCKED_RIGHT || docked==-DOCKED_RIGHT) && (short)LOWORD(msg->lParam)<0)) {
				ReleaseCapture();
				draggingTitle=0;
				ZeroMemory(&abd,sizeof(abd));
				abd.cbSize=sizeof(abd);
				abd.hWnd=msg->hwnd;
				SHAppBarMessage(ABM_REMOVE,&abd);
				docked=0;
				GetCursorPos(&pt);
				PostMessage(msg->hwnd,WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(pt.x,pt.y));
				SetWindowPos(msg->hwnd,0,pt.x-rc.right/2,pt.y-GetSystemMetrics(SM_CYFRAME)-GetSystemMetrics(SM_CYSMCAPTION)/2,DBGetContactSettingDword(NULL,"CList","Width",0),DBGetContactSettingDword(NULL,"CList","Height",0),SWP_NOZORDER);
				DBWriteContactSettingByte(NULL,"CList","Docked",(BYTE)docked);
       // ReposButtons(msg->hwnd,0);
			}
			return 1;
		}
		case WM_LBUTTONUP:
			if(draggingTitle) {
				ReleaseCapture();
				draggingTitle=0;
			}
			return 0;
		case WM_DOCKCALLBACK:
			switch(msg->wParam) {
				case ABN_WINDOWARRANGE:
					ShowWindowNew(msg->hwnd,msg->lParam?SW_HIDE:SW_SHOW);
                    {

						RECT rc, rcMonitor;
						Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
						GetWindowRect(msg->hwnd,&rc);
						Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
						OnMoving(msg->hwnd,&rc); //-=-=-=		
            ReposButtons(msg->hwnd,0,NULL);

						dock_prevent_moving=1;
					}
					break;
			}
			return TRUE;
		case WM_DESTROY:
			if(docked>0) {
				ZeroMemory(&abd,sizeof(abd));
				abd.cbSize=sizeof(abd);
				abd.hWnd=msg->hwnd;
				SHAppBarMessage(ABM_REMOVE,&abd);
        ReposButtons(msg->hwnd,0,NULL);
			}
			return 0;
	}
	return 0;
}
Exemplo n.º 4
0
int fnDocking_ProcessWindowMessage(WPARAM wParam, LPARAM lParam)
{
	static int draggingTitle;
	MSG *msg = (MSG *) wParam;

	if (msg->message == WM_DESTROY)
	{
		if (docked)
		{
			db_set_b(NULL, "CList", "Docked", (BYTE) docked);
			db_set_dw(NULL, "CList", "DockX", (DWORD) dockPos.x);
			db_set_dw(NULL, "CList", "DockY", (DWORD) dockPos.y);
		}
		else
		{
			db_unset(NULL, "CList", "Docked");
			db_unset(NULL, "CList", "DockX");
			db_unset(NULL, "CList", "DockY");
		}
	}

	if (!docked && msg->message != WM_CREATE && msg->message != WM_MOVING)
		return 0;

	switch (msg->message)
	{
	case WM_CREATE:
		draggingTitle = 0;
		docked = db_get_b(NULL, "CLUI", "DockToSides", 1) ?
			(char) db_get_b(NULL, "CList", "Docked", 0) : 0;
		dockPos.x = (int)db_get_dw(NULL, "CList", "DockX", 0);
		dockPos.y = (int)db_get_dw(NULL, "CList", "DockY", 0);
		break;

	case WM_ACTIVATE:
		Docking_Command(msg->hwnd, ABM_ACTIVATE);
		break;

	case WM_WINDOWPOSCHANGING:
	{
		LPWINDOWPOS wp = (LPWINDOWPOS)msg->lParam;

		bool vis = Docking_IsWindowVisible(msg->hwnd);
		if (wp->flags & SWP_SHOWWINDOW)
			vis = !IsIconic(msg->hwnd);
		if (wp->flags & SWP_HIDEWINDOW)
			vis = false;

		if (vis)
		{
			if (!(wp->flags & (SWP_NOMOVE | SWP_NOSIZE)))
			{
				bool addbar = Docking_Command(msg->hwnd, ABM_NEW) != 0;

				RECT rc = {0};
				GetWindowRect(msg->hwnd, &rc);

				int cx = rc.right - rc.left;
				if (!(wp->flags & SWP_NOMOVE)) { rc.left = wp->x; rc.top = wp->y; }

				if (addbar)
					Docking_RectToDock(&rc);

				if (!(wp->flags & SWP_NOSIZE))
				{
					rc.right = rc.left + wp->cx;
					rc.bottom = rc.top + wp->cy;
					addbar |= (cx != wp->cx);
				}

				Docking_SetSize(msg->hwnd, &rc, !addbar, false);

				if (!(wp->flags & SWP_NOMOVE)) { wp->x = rc.left; wp->y = rc.top; }
				if (!(wp->flags & SWP_NOSIZE)) wp->cy = rc.bottom - rc.top;

				*((LRESULT *) lParam) = TRUE;
				return TRUE;
			}
			else
			{
				if ((wp->flags & SWP_SHOWWINDOW) && Docking_Command(msg->hwnd, ABM_NEW))
				{
					RECT rc = {0};
					GetWindowRect(msg->hwnd, &rc);
					Docking_RectToDock(&rc);

					Docking_SetSize(msg->hwnd, &rc, false, false);

					wp->x = rc.left;
					wp->y = rc.top;
					wp->cy = rc.bottom - rc.top;
					wp->cx = rc.right - rc.left;
					wp->flags &= ~(SWP_NOSIZE | SWP_NOMOVE);
				}
			}
		}
		break;
	}

	case WM_WINDOWPOSCHANGED:
	{
		LPWINDOWPOS wp = (LPWINDOWPOS)msg->lParam;
		bool vis = Docking_IsWindowVisible(msg->hwnd);
		if (wp->flags & SWP_SHOWWINDOW)
			vis = !IsIconic(msg->hwnd);
		if (wp->flags & SWP_HIDEWINDOW)
			vis = false;

		if (!vis)
			Docking_Command(msg->hwnd, ABM_REMOVE);
		else
			Docking_Command(msg->hwnd, ABM_WINDOWPOSCHANGED);
		break;
	}

	case WM_DISPLAYCHANGE:
		if (Docking_IsWindowVisible(msg->hwnd))
		{
			RECT rc = {0};
			GetWindowRect(msg->hwnd, &rc);
			Docking_RectToDock(&rc);
			Docking_SetSize(msg->hwnd, &rc, false, true);
		}
		break;

	case WM_MOVING:
		if (!docked)
		{
			RECT rcMonitor;
			POINT ptCursor;

			// stop early
			if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
				return 0;

			// GetMessagePos() is no good, position is always unsigned
//			GetCursorPos(&ptCursor);
			DWORD pos = GetMessagePos();
			ptCursor.x = GET_X_LPARAM(pos);
			ptCursor.y = GET_Y_LPARAM(pos);
			Docking_GetMonitorRectFromPoint(&ptCursor, &rcMonitor);

			if (((ptCursor.x < rcMonitor.left + EDGESENSITIVITY) ||
				(ptCursor.x >= rcMonitor.right - EDGESENSITIVITY)) &&
				db_get_b(NULL, "CLUI", "DockToSides", 1))
			{
				docked = (ptCursor.x < rcMonitor.left + EDGESENSITIVITY) ? DOCKED_LEFT : DOCKED_RIGHT;
				PostMessage(msg->hwnd, WM_LBUTTONUP, 0, MAKELPARAM(ptCursor.x, ptCursor.y));

				Docking_Command(msg->hwnd, ABM_NEW);
				Docking_AdjustPosition(msg->hwnd, &rcMonitor, (LPRECT)msg->lParam, false, true);

				*((LRESULT *) lParam) = TRUE;
				return TRUE;
			}
		}
		break;

	case WM_NCHITTEST:
		switch (DefWindowProc(msg->hwnd, WM_NCHITTEST, msg->wParam, msg->lParam))
		{
		case HTSIZE: case HTTOP: case HTTOPLEFT: case HTTOPRIGHT:
		case HTBOTTOM: case HTBOTTOMRIGHT: case HTBOTTOMLEFT:
			*((LRESULT *) lParam) = HTCLIENT;
			return TRUE;

		case HTLEFT:
			if (docked == DOCKED_LEFT)
			{
				*((LRESULT *) lParam) = HTCLIENT;
				return TRUE;
			}
			break;

		case HTRIGHT:
			if (docked == DOCKED_RIGHT)
			{
				*((LRESULT *) lParam) = HTCLIENT;
				return TRUE;
			}
			break;
		}
		break;

	case WM_SYSCOMMAND:
		if ((msg->wParam & 0xFFF0) != SC_MOVE)
			return 0;

		SetActiveWindow(msg->hwnd);
		SetCapture(msg->hwnd);
		draggingTitle = 1;
		*((LRESULT *) lParam) = 0;
		return 1;

	case WM_MOUSEMOVE:
		if (draggingTitle)
		{
			RECT rc;
			POINT pt;
			GetClientRect(msg->hwnd, &rc);
			if ((docked == DOCKED_LEFT && (short) LOWORD(msg->lParam) > rc.right)  ||
				(docked == DOCKED_RIGHT && (short) LOWORD(msg->lParam) < 0))
			{
				ReleaseCapture();
				draggingTitle = 0;
				docked = 0;
				GetCursorPos(&pt);
				PostMessage(msg->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y));
				SetWindowPos(msg->hwnd, 0, pt.x - rc.right / 2,
					pt.y - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYSMCAPTION) / 2,
					db_get_dw(NULL, "CList", "Width", 0),
					db_get_dw(NULL, "CList", "Height", 0),
					SWP_NOZORDER);
				Docking_Command(msg->hwnd, ABM_REMOVE);
			}
			return 1;
		}
		break;

	case WM_LBUTTONUP:
		if (draggingTitle)
		{
			ReleaseCapture();
			draggingTitle = 0;
		}
		break;

	case WM_DOCKCALLBACK:
		switch (msg->wParam)
		{
		case ABN_WINDOWARRANGE:
			ShowWindow(msg->hwnd, msg->lParam ? SW_HIDE : SW_SHOW);
			break;

		case ABN_POSCHANGED:
			{
				RECT rc = {0};
				GetWindowRect(msg->hwnd, &rc);
				Docking_SetSize(msg->hwnd, &rc, false, true);
			}
			break;
		}
		return 1;

	case WM_DESTROY:
		Docking_Command(msg->hwnd, ABM_REMOVE);
		break;
	}
	return 0;
}