Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.06.2017, 18:47   #1
Tahoma
DI HALT RET
Форумчанин
 
Аватар для Tahoma
 
Регистрация: 30.12.2010
Сообщений: 117
Вопрос Отмена при CTRL+С закрытия консоли

Доброго времени суток.
Возникла у меня проблема с закрытием консольки при нажатии CTRL+C.
Поставил ивент на нажатие:
Код:
BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{

	if (dwCtrlType == CTRL_C_EVENT ||
		dwCtrlType == CTRL_BREAK_EVENT ||
		dwCtrlType == CTRL_CLOSE_EVENT)
	{
//		std::cout << "Terminating" << std::endl;
//		SetEvent(g_hTerminateEvent);

		return TRUE;
	}
	return FALSE;
}

	g_hTerminateEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
	SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
Ивент либо разрешает закрыть окно, либо ввод строк перестает работать (даже не ждет ввода команды, а сразу идет дальше):
Код:
	while (!isExitProgram)
	{
		printf("# ");
		memset(icin, 0, sizeof(icin));
		cin.getline(icin, sizeof(icin) - 1);
		FindCommand(icin);
	}
Как же сделать копирование и вставку в консоли?

Последний раз редактировалось Tahoma; 30.06.2017 в 19:01.
Tahoma вне форума Ответить с цитированием
Старый 30.06.2017, 19:31   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Насколько я понимаю, если есть выделенный текст, тогда Ctrl-C текст и скопирует, т.е. сигнал посылаться не будет.
waleri вне форума Ответить с цитированием
Старый 30.06.2017, 19:38   #3
Tahoma
DI HALT RET
Форумчанин
 
Аватар для Tahoma
 
Регистрация: 30.12.2010
Сообщений: 117
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Насколько я понимаю, если есть выделенный текст, тогда Ctrl-C текст и скопирует, т.е. сигнал посылаться не будет.
А как быть, если в буфере нет ничего? У меня окно просто закрывается, а мне это и надо обойти
Tahoma вне форума Ответить с цитированием
Старый 01.07.2017, 03:16   #4
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

похоже нужен SetConsoleMode..

...ток это вопросы не по С, а по Виндовс АПИ.
alexzk вне форума Ответить с цитированием
Старый 27.07.2017, 18:05   #5
Tahoma
DI HALT RET
Форумчанин
 
Аватар для Tahoma
 
Регистрация: 30.12.2010
Сообщений: 117
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

похоже нужен SetConsoleMode..

...ток это вопросы не по С, а по Виндовс АПИ.


Спасибо, что подсказали направление.
Одна проблемка, почему при
SetConsoleMode(hCons, ENABLE_WINDOW_INPUT)
у меня вылетает
cin.getline
?


Идиотский вопрос. Извиняюсь! Нафига мне cin.getline, если у меня перехватываются все нажатия

Последний раз редактировалось Tahoma; 27.07.2017 в 18:11.
Tahoma вне форума Ответить с цитированием
Старый 27.07.2017, 19:16   #6
Tahoma
DI HALT RET
Форумчанин
 
Аватар для Tahoma
 
Регистрация: 30.12.2010
Сообщений: 117
По умолчанию

Получилось что-то вроде:
Код:
VOID KeyEventProc(KEY_EVENT_RECORD code)
{
	char str[2];
	str[1] = 0;
	memcpy(&str, &code.uChar, 1);
	
	if (code.bKeyDown != 1)
	{
		switch (code.wVirtualKeyCode)
		{
		case 0x43:
			if (code.dwControlKeyState == 0x28)
			{
				isBreakButton = true;
				return;
			}
			break;

		case VK_RETURN:
			isReturnButton = true;
			printf("\n");
			return;
		}		

		if (code.dwControlKeyState != 0x28)
		{
			sprintf(cLine, "%s%s", cLine, str);
			printf("%s", str);
		}
	}
}

DWORD WINAPI ThreadConsole(LPVOID lpParam)
{
	CONSOLEDATA* pData = (CONSOLEDATA*)lpParam;

	DWORD cNumRead, i;
	INPUT_RECORD irInBuf[128];

	memset(irInBuf, 0, 128);
	while (true)
	{
		memset(irInBuf, 0, 128);
		// Wait for the events. 

		if (!ReadConsoleInput(
			pData->hConsole,		// input buffer handle 
			irInBuf,				// buffer to read into 
			128,					// size of read buffer 
			&cNumRead))				// number of records read 
		{
			return -1;
		}

		// Dispatch the events to the appropriate handler. 
		for (i = 0; i < cNumRead; i++)
		{
			switch (irInBuf[i].EventType)
			{
			case KEY_EVENT: // keyboard input 
				KeyEventProc(irInBuf[i].Event.KeyEvent);
				break;
			case FOCUS_EVENT:  // disregard focus events 

			case MENU_EVENT:   // disregard menu events 
				break;

			default:
				break;
			}
		}
	}

	return 0;
}

bool StartThread(HANDLE hCons)
{
	CONSOLEDATA* pData;

	if (!SetConsoleMode(hCons, ENABLE_WINDOW_INPUT))
	{
		printf("Can't create console thread\n");
		return false;
	}

	pData = (CONSOLEDATA*) malloc (sizeof(CONSOLEDATA));
	memset(pData, 0, sizeof(CONSOLEDATA));

	pData->hConsole = hCons;

	HANDLE hThread = CreateThread(
		NULL,					// default security attributes
		0,						// use default stack size  
		ThreadConsole,			// thread function name
		pData,					// argument to thread function 
		0,                      // use default creation flags 
		NULL);					// returns the thread identifier

	return true;

}



void main()
{
	if (!StartThread(GetStdHandle(STD_INPUT_HANDLE)))
		return -1;
}
Tahoma вне форума Ответить с цитированием
Старый 28.07.2017, 10:31   #7
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

не нравится мне этот код....у вас main завершается,а поток остается...так быть не должно.

Нужно предусмотреть что-то (комбинацию клавиш) для завершения цикла потока, по окончании цикла выставить какой-то флаг (std:romise, std::conditional, std::feature, std::mutex), что поток все и можно заканчивать мейн (а мейн все это время ждет флаг) - и вот тогда все...
alexzk вне форума Ответить с цитированием
Старый 28.07.2017, 18:24   #8
Tahoma
DI HALT RET
Форумчанин
 
Аватар для Tahoma
 
Регистрация: 30.12.2010
Сообщений: 117
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
не нравится мне этот код....у вас main завершается,а поток остается...так быть не должно.

Нужно предусмотреть что-то (комбинацию клавиш) для завершения цикла потока, по окончании цикла выставить какой-то флаг (std:romise, std::conditional, std::feature, std::mutex), что поток все и можно заканчивать мейн (а мейн все это время ждет флаг) - и вот тогда все...
Вы правы. Мне надо было указать полный код, чтобы было понятно. Просто я опустил некоторый кусок кода. Как описание структуры CONSOLEDATA, так и реализацию флага isReturnButton
Tahoma вне форума Ответить с цитированием
Старый 31.07.2017, 17:47   #9
Tahoma
DI HALT RET
Форумчанин
 
Аватар для Tahoma
 
Регистрация: 30.12.2010
Сообщений: 117
По умолчанию

А хоткеи теперь вручную придется описывать? Я про CTRL+C/V/A....

Ну тут оказалось просто. Надо лишь прочитать буфер обмена и вывести, если есть, что выводить. А отменив CTRL+C (закрытие) стало работать как копирование.
Код:
		case 0x56: // Ctrl+V
			if (code.dwControlKeyState == 0x28)
			{
				if (OpenClipboard(NULL))
				{
					char* data = (char*)GetClipboardData(CF_TEXT);
					if (data)
						printf(data);
						;//делай что хочешь с данными, например - выводи на консоль
					CloseClipboard();

				}
			}
			break;

Последний раз редактировалось Tahoma; 01.08.2017 в 17:04. Причина: Нашел решение
Tahoma вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ввод EOF c консоли - это Ctrl+Z и Ctrl+M Почему? 8Observer8 Общие вопросы по программированию, компьютерный форум 10 13.01.2023 09:33
Отмена закрытия программы из панели задач Jleksern Общие вопросы Delphi 7 15.06.2013 17:32
Не работает отмена при добавлении записей в таблицу Екатерина20 БД в Delphi 4 26.05.2012 17:23
Отмена закрытия консольного окна после завершения работы приложения FeloS Общие вопросы C/C++ 21 25.02.2011 16:34
При нажатии выполнить Ctrl+F Shouldercannon Общие вопросы Delphi 10 04.02.2010 16:05