728x90
아래 문서는 다른 곳에서 copy 한 것이며, Test 해 보지 않음
1 Ctrl+C, Ctrl+Break, Close 버튼 막기
- SetConsoleCtrlHandler 함수를 통해 컨트롤 핸들러를 등록한 다음 무시하기 원하는 이벤트일 경우 TRUE를 반환하면 된다.
BOOL WINAPI DisableConsoleWindowClose(DWORD event) { BOOL handled = FALSE; switch (event) { case CTRL_C_EVENT: handled = TRUE; break; case CTRL_BREAK_EVENT: handled = TRUE; break; case CTRL_CLOSE_EVENT: handled = TRUE; break; default: break; } return handled; } SetConsoleCtrlHandler(DisableConsoleWindowClose, TRUE); |
세 이벤트를 모두 막아버릴 경우, 윈도우를 정상적으로 닫을 방법이 없어지기 때문에 유의. 강제 종료해야 한다.
2 콘솔창 입력
- GetNumberOfConsoleInputEvents 함수와 ReadConsoleInput 함수를 사용하면 간단히 처리할 수 있다. ReadConsoleInput 함수가 입력이 들어오기 전까지 블로킹되는 함수이기 때문에, GetNumberOfConsoleInputEvents 함수를 이용해 이미 들어와있는 입력이 있는지 체크해야 한다.
커서 위치 처리가 좀 난감한데,
![[WWW]](http://serious-code.net/img/moin-www.gif)
void ReadConsoleInput() { HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); INPUT_RECORD inRecord = {0, }; TCHAR readChar[2] = {0, }; DWORD eventCount = 0; DWORD numRecordsRead = 0; GetNumberOfConsoleInputEvents(hIn, &eventCount); while (eventCount > 0) { if (ReadConsoleInput(hIn, &inRecord, 1, &numRecordsRead) && numRecordsRead == 1) { if (inRecord.EventType == KEY_EVENT && inRecord.Event.KeyEvent.bKeyDown) { if (inRecord.Event.KeyEvent.wVirtualKeyCode != VK_RETURN) { readChar[0] = inRecord.Event.KeyEvent.uChar.AsciiChar; std::cout << readChar << std::endl; } else { std::cout << _T("\r\n") << std::endl; } } --eventCount; } else { break; } } } int main(int argc, TCHAR** argv) { while (true) { ...do something else... ReadConsoleInput(); } } |
3 콘솔창 출력
3.1 콘솔창 열기
bool OpenConsole() { if (!::AllocConsole()) { return false; } HANDLE hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE); if (INVALID_HANDLE_VALUE == hConsole) { ::FreeConsole(); return false; } return true; } |
3.2 콘솔창 닫기
void CloseConsole() { ::FreeConsole(); ::CloseHandle(hConsole); hConsole = INVALID_HANDLE_VALUE; }
3.3 콘솔창에다 출력하기
void WriteConsole(const char* szMsg) { DWORD dwBytes = 0; ::WriteFile(m_hConsole, szMsg, ::strlen(szMsg), &dwBytes, NULL); ::WriteFile(m_hConsole, "\n", ::strlen("\n"), &dwBytes, NULL); } |
3.4 STDOUT, STDIN, STDERR 리다이렉션
#include <fcntl.h> #include <io.h> #include <iostream> #include <fstream> // STDOUT, STDIN, STDERR redirection void RedirectStandardIo(HANDLE hConsole) { long StdHandle = 0; int ConHandle = 0; FILE* fp = NULL; // STDOUT redirection StdHandle = PtrToLong(hConsole); ConHandle = _open_osfhandle(StdHandle, _O_TEXT); fp = _fdopen(ConHandle, "w"); *stdout = *fp; setvbuf(stdout, NULL, _IONBF, 0); // STDIN redirection StdHandle = PtrToLong(::GetStdHandle(STD_INPUT_HANDLE)); ConHandle = _open_osfhandle(StdHandle, _O_TEXT); fp = _fdopen(ConHandle, "r"); *stdin = *fp; setvbuf(stdin, NULL, _IONBF, 0); // STDERR redirection StdHandle = PtrToLong(::GetStdHandle(STD_ERROR_HANDLE)); ConHandle = _open_osfhandle(StdHandle, _O_TEXT); fp = _fdopen( ConHandle, "w" ); *stderr = *fp; setvbuf(stderr, NULL, _IONBF, 0); // cout, wcout, cin, wcin, wcerr, cerr, wclog, clog sync std::ios::sync_with_stdio(); } |
3.5 듀얼 모니터일때 옆모니터에 콘솔창 띄우기 by 쑥갓
#define _WIN32_WINNT 0x0500 ... bool bDualMonitor = GetSystemMetrics( SM_CMONITORS ) > 1; if ( bDualMonitor == true ) { HWND hConsoleWindow = GetConsoleWindow(); const int screenWidth = GetSystemMetrics( SM_CXSCREEN ); RECT rect; GetWindowRect( hConsoleWindow, &rect ); // 아래의 +- 코드는 주모니터가 어느 쪽에 있느냐에 따라 변경해줘야한다. // 주모니터가 어느 쪽에 있는지 알아내는 방법이 있을 듯 한데... int windowX = rect.left; if( windowX > screenWidth ) { windowX -= screenWidth; // 주모니터가 왼쪽에 있는 경우 //windowX += screenWidth; // 주모니터가 오른쪽에 있는 경우 } else { windowX += screenWidth; // 주모니터가 왼쪽에 있는 경우 //windowX -= screenWidth; // 주모니터가 오른쪽에 있는 경우 } SetWindowPos( hConsoleWindow, NULL, windowX, rect.top, 0, 0, SWP_NOSIZE ); // 콘솔 윈도우를 최대화해주기 위해서는 위의 SetWindowPos 대신에 아래를 사용한다. //const int screenHeight = GetSystemMetrics( SM_CYSCREEN ); //SetWindowPos( hConsoleWindow, NULL, windowX, 0, screenWidth, screenHeight, 0 ); } |
4 콘솔창을 띄우지 않은 상태에서 콘솔 프로그램을 실행하고, 그 결과를 파일에다 쓰기
void CTttDlg::OnOK() { // TODO: Add extra validation here PROCESS_INFORMATION pInfo; STARTUPINFO sInfo; DWORD exitCode; HANDLE hOut = CreateFile("stdinout.txt", GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); sInfo.cb = sizeof(STARTUPINFO); sInfo.lpReserved = NULL; sInfo.lpReserved2 = NULL; sInfo.cbReserved2 = 0; sInfo.lpDesktop = NULL; sInfo.lpTitle = NULL; sInfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; sInfo.dwX = 0; sInfo.dwY = 0; sInfo.dwFillAttribute = 0; sInfo.wShowWindow = SW_HIDE; sInfo.hStdOutput = hOut; if (!CreateProcess(NULL, "command.com /c lha a tt", NULL, NULL, TRUE, 0, NULL, "c:\\", &sInfo, &pInfo)) { printf("ERROR: Cannot launch child process\n"); exit(1); } // Give the process time to execute and finish WaitForSingleObject(pInfo.hProcess, INFINITE); if (GetExitCodeProcess(pInfo.hProcess, &exitCode)) { switch(exitCode) { case STILL_ACTIVE: printf("Process is still active\n"); break; default: printf("Exit code = %d\n", exitCode); break; } } else { printf("GetExitCodeProcess() failed\n"); } CloseHandle(hOut); } |
위의 CreateProcess를 호출하는 부분에서 "Command.com /c"를 호출하는 부분이 있는데 이렇게 해주지 않으면, 호출하는 프로그램이 DOS 프로그램인 경우 자동으로 창이 닫히지 않는 문제가 발생하기 때문.
728x90
'언어 > MFC Program' 카테고리의 다른 글
char <-> TCHAR 사이 형변환 (0) | 2013.01.08 |
---|---|
C/C++ 현재 경로 얻기 (1) | 2013.01.08 |
MFC에서 Console 프로그램 실행하기 (0) | 2013.01.08 |
MFC에서 특정 작업 중에 모래시계 넣기 (0) | 2012.12.20 |