示例#1
0
BOOL ProcessInputMessage(MSG64::MsgStr &msg, INPUT_RECORD &r)
{
	memset(&r, 0, sizeof(r));
	BOOL lbOk = FALSE;

	if (!UnpackInputRecord(&msg, &r))
	{
		_ASSERT(FALSE);
	}
	else
	{
		TODO("Сделать обработку пачки сообщений, вдруг они накопились в очереди?");
		//#ifdef _DEBUG
		//if (r.EventType == KEY_EVENT && (r.Event.KeyEvent.wVirtualKeyCode == 'C' || r.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL))
		//{
		//	DEBUGSTR(L"  ---  CtrlC/CtrlBreak recieved\n");
		//}
		//#endif
		bool lbProcessEvent = false;
		bool lbIngoreKey = false;

		if (r.EventType == KEY_EVENT && r.Event.KeyEvent.bKeyDown &&
		        (r.Event.KeyEvent.wVirtualKeyCode == 'C' || r.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL)
		        && (      // Удерживается ТОЛЬКО Ctrl
		            (r.Event.KeyEvent.dwControlKeyState & CTRL_MODIFIERS) &&
		            ((r.Event.KeyEvent.dwControlKeyState & ALL_MODIFIERS)
		             == (r.Event.KeyEvent.dwControlKeyState & CTRL_MODIFIERS))
		        )
		  )
		{
			lbProcessEvent = true;
			DEBUGSTR(L"  ---  CtrlC/CtrlBreak recieved\n");
			DWORD dwMode = 0;
			GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwMode);

			// CTRL+C (and Ctrl+Break?) is processed by the system and is not placed in the input buffer
			if ((dwMode & ENABLE_PROCESSED_INPUT) == ENABLE_PROCESSED_INPUT)
				lbIngoreKey = lbProcessEvent = true;
			else
				lbProcessEvent = false;

			if (lbProcessEvent)
			{
				//BOOL lbRc = FALSE;
				#if 0
				DWORD dwEvent = (r.Event.KeyEvent.wVirtualKeyCode == 'C') ? CTRL_C_EVENT : CTRL_BREAK_EVENT;
				#endif
				//&& (gpSrv->dwConsoleMode & ENABLE_PROCESSED_INPUT)

				#if 1
				// Issue 590: GenerateConsoleCtrlEvent нифига не прерывает функцию ReadConsoleW
				SendMessage(ghConWnd, WM_KEYDOWN, r.Event.KeyEvent.wVirtualKeyCode, 0);
				//lbRc = TRUE;
				#endif

				#if 0
				//The SetConsoleMode function can disable the ENABLE_PROCESSED_INPUT mode for a console's input buffer,
				//so CTRL+C is reported as keyboard input rather than as a signal.
				// CTRL+BREAK is always treated as a signal
				if (  // Удерживается ТОЛЬКО Ctrl
				    (r.Event.KeyEvent.dwControlKeyState & CTRL_MODIFIERS) &&
				    ((r.Event.KeyEvent.dwControlKeyState & ALL_MODIFIERS)
				     == (r.Event.KeyEvent.dwControlKeyState & CTRL_MODIFIERS))
				)
				{
					// Вроде работает, Главное не запускать процесс с флагом CREATE_NEW_PROCESS_GROUP
					// иначе у микрософтовской консоли (WinXP SP3) сносит крышу, и она реагирует
					// на Ctrl-Break, но напрочь игнорирует Ctrl-C
					lbRc = GenerateConsoleCtrlEvent(dwEvent, 0);
					// Это событие (Ctrl+C) в буфер помещается(!) иначе до фара не дойдет собственно клавиша C с нажатым Ctrl
				}
				#endif
			}

			if (lbIngoreKey)
				return FALSE;

			// CtrlBreak отсылаем СРАЗУ, мимо очереди, иначе макросы FAR нельзя стопнуть
			if (r.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL)
			{
				// При получении CtrlBreak в реальной консоли - буфер ввода очищается
				// иначе фар, при попытке считать ввод получит старые,
				// еще не обработанные нажатия, и CtrlBreak проигнорирует
				FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
				SendConsoleEvent(&r, 1);
				return FALSE;
			}
		}

#ifdef _DEBUG

		if (r.EventType == KEY_EVENT && r.Event.KeyEvent.bKeyDown &&
		        r.Event.KeyEvent.wVirtualKeyCode == VK_F11)
		{
			DEBUGSTR(L"  ---  F11 recieved\n");
		}

#endif
#ifdef _DEBUG

		if (r.EventType == MOUSE_EVENT)
		{
			static DWORD nLastEventTick = 0;

			if (nLastEventTick && (GetTickCount() - nLastEventTick) > 2000)
			{
				OutputDebugString(L".\n");
			}

			wchar_t szDbg[60];
			_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"    ConEmuC.MouseEvent(X=%i,Y=%i,Btns=0x%04x,Moved=%i)\n", r.Event.MouseEvent.dwMousePosition.X, r.Event.MouseEvent.dwMousePosition.Y, r.Event.MouseEvent.dwButtonState, (r.Event.MouseEvent.dwEventFlags & MOUSE_MOVED));
			DEBUGLOGINPUT(szDbg);
			nLastEventTick = GetTickCount();
		}

#endif

		// Запомнить, когда была последняя активность пользователя
		if (r.EventType == KEY_EVENT
		        || (r.EventType == MOUSE_EVENT
		            && (r.Event.MouseEvent.dwButtonState || r.Event.MouseEvent.dwEventFlags
		                || r.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)))
		{
			gpSrv->dwLastUserTick = GetTickCount();
		}

		lbOk = TRUE;
		//SendConsoleEvent(&r, 1);
	}

	return lbOk;
}
示例#2
0
BOOL ProcessInputMessage(MSG64::MsgStr &msg, INPUT_RECORD &r)
{
	memset(&r, 0, sizeof(r));
	BOOL lbOk = FALSE;

	if (!UnpackInputRecord(&msg, &r))
	{
		_ASSERT(FALSE);
	}
	else
	{
		TODO("Сделать обработку пачки сообщений, вдруг они накопились в очереди?");
		//#ifdef _DEBUG
		//if (r.EventType == KEY_EVENT && (r.Event.KeyEvent.wVirtualKeyCode == 'C' || r.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL))
		//{
		//	DEBUGSTR(L"  ---  CtrlC/CtrlBreak recieved\n");
		//}
		//#endif
		bool lbProcessEvent = false;
		bool lbIngoreKey = false;

		if (r.EventType == KEY_EVENT && r.Event.KeyEvent.bKeyDown &&
		        (r.Event.KeyEvent.wVirtualKeyCode == 'C' || r.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL)
		        && (      // Удерживается ТОЛЬКО Ctrl
		            (r.Event.KeyEvent.dwControlKeyState & CTRL_MODIFIERS) &&
		            ((r.Event.KeyEvent.dwControlKeyState & ALL_MODIFIERS)
		             == (r.Event.KeyEvent.dwControlKeyState & CTRL_MODIFIERS))
		        )
		  )
		{
			wchar_t szLog[100];
			lbProcessEvent = true;
			LogString(L"  ---  CtrlC/CtrlBreak recieved");
			DWORD dwMode = 0;
			GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwMode);

			// CTRL+C (and Ctrl+Break?) is processed by the system and is not placed in the input buffer
			if ((dwMode & ENABLE_PROCESSED_INPUT) == ENABLE_PROCESSED_INPUT)
				lbIngoreKey = lbProcessEvent = true;
			else
				lbProcessEvent = false;

			if (RELEASEDEBUGTEST((gpLogSize!=NULL),true))
			{
			bool bAlt = isPressed(VK_MENU), bShift = isPressed(VK_SHIFT), bCtrl = isPressed(VK_CONTROL);
			if (bAlt || bShift || !bCtrl)
			{
				msprintf(szLog, countof(szLog), L"  ---  CtrlC/CtrlBreak may fails because of bad Alt/Shift/Ctrl state (%u,%u,%u)!", (UINT)bAlt, (UINT)bShift, (UINT)bCtrl);
				LogString(szLog);
			}
			if (!lbProcessEvent)
			{
				LogString(L"  ---  CtrlC/CtrlBreak may fails because of disabled ENABLE_PROCESSED_INPUT!");
			}
			}

			if (lbProcessEvent)
			{
				// Issue 590: GenerateConsoleCtrlEvent does not break ReadConsole[A|W] function!
				SetLastError(0);
				LRESULT lSendRc =
				SendMessage(ghConWnd, WM_KEYDOWN, r.Event.KeyEvent.wVirtualKeyCode, 0);
				DWORD nErrCode = GetLastError();
				msprintf(szLog, countof(szLog), L"  ---  CtrlC/CtrlBreak sent (%u,%u)", LODWORD(lSendRc), nErrCode);
				LogString(szLog);
			}

			if (lbIngoreKey)
				return FALSE;

			// In the real console, when CtrlBreak is received, input buffer is cleared.
			// Otherwise, in Far Manager for example, it's impossible to stop some operation,
			// it will try to peek old data and CtrlBreak may be left unread
			if (r.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL)
			{
				LogString(L"  ---  VK_CANCEL received, flushing, sending...");
				FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
				SendConsoleEvent(&r, 1);
				return FALSE;
			}
		}

		#ifdef _DEBUG
		if (r.EventType == KEY_EVENT && r.Event.KeyEvent.bKeyDown &&
		        r.Event.KeyEvent.wVirtualKeyCode == VK_F11)
		{
			LogString(L"  ---  F11 recieved\n");
		}
		#endif

		#ifdef _DEBUG
		if (r.EventType == MOUSE_EVENT)
		{
			static DWORD nLastEventTick = 0;

			if (nLastEventTick && (GetTickCount() - nLastEventTick) > 2000)
			{
				OutputDebugString(L".\n");
			}

			wchar_t szDbg[60];
			_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"    ConEmuC.MouseEvent(X=%i,Y=%i,Btns=0x%04x,Moved=%i)\n", r.Event.MouseEvent.dwMousePosition.X, r.Event.MouseEvent.dwMousePosition.Y, r.Event.MouseEvent.dwButtonState, (r.Event.MouseEvent.dwEventFlags & MOUSE_MOVED));
			DEBUGLOGINPUT(szDbg);
			nLastEventTick = GetTickCount();
		}
		#endif

		// Запомнить, когда была последняя активность пользователя
		if (r.EventType == KEY_EVENT
		        || (r.EventType == MOUSE_EVENT
		            && (r.Event.MouseEvent.dwButtonState || r.Event.MouseEvent.dwEventFlags
		                || r.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)))
		{
			gpSrv->dwLastUserTick = GetTickCount();
		}

		lbOk = TRUE;
		//SendConsoleEvent(&r, 1);
	}

	return lbOk;
}