#include "stdafx.h"
#include "MouseAssist.h"

MouseAssist::MouseAssist()
{
	_hWnd = NULL;
	_nMode = -1;
	_curpt = {0,0};
}

MouseAssist::~MouseAssist()
{
	_hWnd = NULL;
	_nMode = -1;
}

void MouseAssist::BindWnd(HWND hWnd, int nMode)
{
	_hWnd = hWnd;
	_nMode = nMode;
}

void MouseAssist::UnBindWnd()
{
	_hWnd = NULL;
	_nMode = -1;
}


BOOL MouseAssist::GetCursorPos()
{
	BOOL bRet = ::GetCursorPos(&_curpt);
	if (_nMode == PT_TYPE::WINDOW_POINT) {
		// 窗口句柄判断;
		if (_hWnd) {
			bRet = ScreenToClient(_hWnd, &_curpt);
			if (!bRet)
				OutputDebugString("坐标转窗口失败\n");
		}
	}

	return bRet;
}

BOOL MouseAssist::GetCursorPos(long& x, long& y)
{
	BOOL bRet = GetCursorPos();

	x = _curpt.x;
	y = _curpt.y;

	return bRet;
}

BOOL MouseAssist::SetCursorPos(long x, long y)
{
	_curpt = {x, y};
	return ::SetCursorPos(x, y);
}

BOOL MouseAssist::MoveTo(int x, int y)
{
	_curpt = {x, y};
	BOOL bRet = FALSE;
	if ( _nMode == PT_TYPE::SCREEN_POINT) {
		if ( _hWnd )
			::ClientToScreen(_hWnd, &_curpt);
#if 0 // mouse_event处理
		::SetCursorPos(_curpt.x, _curpt.y);
		// MOUSEEVENTF_ABSOLUTE 使用绝对鼠标位置;
		mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, _curpt.x, _curpt.y, 0, 0);
#else // setinput处理;
		static long fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN) - 1;
		static long fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN) - 1;
		double fx = (double)_curpt.x * (65535.0f / fScreenWidth);
		double fy = (double)_curpt.y * (65535.0f / fScreenHeight);
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
		Input.mi.dx = static_cast<LONG>(fx);
		Input.mi.dy = static_cast<LONG>(fy);
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	} 
	else if ( _nMode == PT_TYPE::WINDOW_POINT ) { 
		// 有时PostMessage才生效;
		bRet = ::PostMessage(_hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
	}

	return bRet;
}

BOOL MouseAssist::MoveToEx(int x, int y, int w, int h)
{
	if (w >= 2 && h >= 2)
		return MoveTo(x + rand() % w, y + rand() % h);
	else
		return MoveTo(x, y);
}

BOOL MouseAssist::LeftClick()
{
	BOOL bDown = FALSE;
	BOOL bUp = FALSE;
	if ( _nMode == PT_TYPE::SCREEN_POINT ) {
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
		bDown = ::SendInput(1, &Input, sizeof(INPUT));

		::ZeroMemory(&Input, sizeof(INPUT));
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
		bUp = ::SendInput(1, &Input, sizeof(INPUT));
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		//bDown = ::SendMessageTimeout(_hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_curpt.x, _curpt.y), SMTO_BLOCK, 2000, nullptr);
		//bUp = ::SendMessageTimeout(_hWnd, WM_LBUTTONUP, 0, MAKELPARAM(_curpt.x, _curpt.y), SMTO_BLOCK, 2000, nullptr);
		bDown = ::PostMessage(_hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
		::PostMessage(_hWnd, WM_NCHITTEST, 0, MAKELPARAM(_curpt.x, _curpt.y));
		::PostMessage(_hWnd, WM_NCHITTEST, HTCLIENT, 0);
		bUp = ::PostMessage(_hWnd, WM_LBUTTONUP, 0, MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bDown & bUp;
}

BOOL MouseAssist::LeftDoubleClick()
{
	BOOL bDown = LeftClick();
	::Sleep(1);
	BOOL bUp = LeftClick();

	return bDown & bUp;
}

BOOL MouseAssist::LeftDown()
{
	BOOL bRet = FALSE;
	if ( _nMode == PT_TYPE::SCREEN_POINT ) {
#if 0
		::SetCursorPos(_curpt.x, _curpt.y);
		mouse_event(MOUSEEVENTF_LEFTDOWN, _curpt.x, _curpt.y, 0, 0);
#else
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	}
	else if ( _nMode == PT_TYPE::WINDOW_POINT ) { 
		bRet = ::PostMessage(_hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bRet;
}

BOOL MouseAssist::LeftUp()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
#if 0
		::SetCursorPos(_curpt.x, _curpt.y);
		mouse_event(MOUSEEVENTF_LEFTUP, _curpt.x, _curpt.y, 0, 0);
#else
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bRet;
}

BOOL MouseAssist::MiddleClick()
{
	BOOL bDown = FALSE;
	BOOL bUp = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
		bDown = ::SendInput(1, &Input, sizeof(INPUT));

		::ZeroMemory(&Input, sizeof(INPUT));
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
		bUp = ::SendInput(1, &Input, sizeof(INPUT));
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bDown = ::SendMessageTimeout(_hWnd, WM_MBUTTONDOWN, MK_MBUTTON, MAKELPARAM(_curpt.x, _curpt.y), SMTO_BLOCK, 2000, nullptr);
		bUp = ::SendMessageTimeout(_hWnd, WM_MBUTTONUP, MK_MBUTTON, MAKELPARAM(_curpt.x, _curpt.y), SMTO_BLOCK, 2000, nullptr);
	}

	return bDown & bUp;
}

BOOL MouseAssist::MiddleDown()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_MBUTTONDOWN, MK_MBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
	}
	return bRet;
}

BOOL MouseAssist::MiddleUp()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_MBUTTONUP, MK_MBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
	}
	return bRet;
}

BOOL MouseAssist::RightClick()
{
	BOOL bDown = FALSE;
	BOOL bUp = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
		bDown = ::SendInput(1, &Input, sizeof(INPUT));

		::ZeroMemory(&Input, sizeof(INPUT));
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
		bUp = ::SendInput(1, &Input, sizeof(INPUT));
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bDown = ::SendMessageTimeout(_hWnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(_curpt.x, _curpt.y), SMTO_BLOCK, 2000, nullptr);
		bUp = ::SendMessageTimeout(_hWnd, WM_RBUTTONUP, MK_RBUTTON, MAKELPARAM(_curpt.x, _curpt.y), SMTO_BLOCK, 2000, nullptr);
	}

	return bDown & bUp;
}

BOOL MouseAssist::RightDown()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
#if 0
		::SetCursorPos(_curpt.x, _curpt.y);
		mouse_event(MOUSEEVENTF_RIGHTDOWN, _curpt.x, _curpt.y, 0, 0);
#else
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bRet;
}

BOOL MouseAssist::RightUp()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
#if 0
		::SetCursorPos(_curpt.x, _curpt.y);
		mouse_event(MOUSEEVENTF_RIGHTUP, _curpt.x, _curpt.y, 0, 0);
#else
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_RBUTTONUP, MK_RBUTTON, MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bRet;
}

BOOL MouseAssist::WheelDown()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
#if 0
		::SetCursorPos(_curpt.x, _curpt.y);
		mouse_event(MOUSEEVENTF_RIGHTUP, _curpt.x, _curpt.y, 0, 0);
#else
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_WHEEL;
		Input.mi.mouseData = WHEEL_DELTA;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_MOUSEWHEEL, MAKEWPARAM(-WHEEL_DELTA, 0), MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bRet;
}

BOOL MouseAssist::WheelUp()
{
	BOOL bRet = FALSE;
	if (_nMode == PT_TYPE::SCREEN_POINT) {
#if 0
		::SetCursorPos(_curpt.x, _curpt.y);
		mouse_event(MOUSEEVENTF_RIGHTUP, _curpt.x, _curpt.y, 0, 0);
#else
		INPUT Input = { 0 };
		Input.type = INPUT_MOUSE;
		Input.mi.dwFlags = MOUSEEVENTF_WHEEL;
		Input.mi.mouseData = -WHEEL_DELTA;
		bRet = ::SendInput(1, &Input, sizeof(INPUT));
#endif
	}
	else if (_nMode == PT_TYPE::WINDOW_POINT) {
		bRet = ::PostMessage(_hWnd, WM_MOUSEWHEEL, MAKEWPARAM(WHEEL_DELTA, 0), MAKELPARAM(_curpt.x, _curpt.y));
	}

	return bRet;
}

