별생각 없이 콘솔로 프로그램을 만들었는데....
기본적으로 있는 콘솔 모드들 때문에 이상한 동작을 하는 경우가 있습니다.
대표적인 것이 "빠른 편집 모드(Quick Edit Mode)"라는 것인데
콘솔 창을 클릭하거나 드레그하면 응용프로그램이 멈추는 현상입니다.
이 모드를 바꾸는 방법을 알아봅시다.
몇 가지 방법들이 있지만 결국은 WinApi를 이용하는 것이 가장 편합니다.
WinApi로 콘솔 모드를 변경하려면
1) 디바이스(여기서는 콘솔)의 핸들을 받아서
2) 콘솔 모드 설정값을 받아온 뒤
3) 받은 설정값이 원하는 설정을 추가(혹은 제거)하고
4) 콘솔 모드 설정값을 다시 설정합니다.
설정값이 uint(UInt32)로 된 플래그(flag) 값이라 비트연산으로 추가나 제거를 할 수 잇습니다.
(참고 : [.NET] 열거형 맴버(enum)의 플래그(Flags)와 비트(bit) 연산)
이제 코드를 한번 짜봅시다.
먼저 WinAPI를 임포트해야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/// <summary>
/// 디바이스의 핸들을 가지고 온다.
/// https://docs.microsoft.com/ko-kr/windows/console/getstdhandle
/// </summary>
/// <param name="nStdHandle"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
/// <summary>
/// 콘솔 모드를 가지고 온다.
/// https://docs.microsoft.com/ko-kr/windows/console/getconsolemode
/// </summary>
/// <param name="hConsoleHandle"></param>
/// <param name="lpMode"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
/// <summary>
/// 콘솔모드를 설정한다.
/// https://docs.microsoft.com/ko-kr/windows/console/setconsolemode
/// </summary>
/// <param name="hConsoleHandle"></param>
/// <param name="dwMode"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
|
cs |
'GetStdHandle'를 이용하여 수정할 콘솔의 핸들을 받아옵니다.
1
|
IntPtr consoleHandle = GetStdHandle(-10);
|
cs |
여기서 '-10'은 'STD_INPUT_HANDLE'을 의미합니다.
(참고 : MS Docs - GetStdHandle 함수 )
이렇게 받아온 핸들로 콘솔 모드를 가지고 옵니다.
1
2
3
4
|
//핸들에 설정된 콘솔 모드를 가지고 온다.
UInt32 consoleMode;
GetConsoleMode(consoleHandle, out consoleMode);
|
cs |
콘솔 모드를 설정하려면 아래와 같이 합니다.
1
2
3
4
5
6
|
//값을 넣을때
consoleMode |= ((uint)[모드 값]);
//값을 뺄때
consoleMode &= ~((uint)[모드 값]);
|
cs |
사용할 수 있는 모드값은 'MS Docs'를 참고하면 됩니다.
참고 - SetConsoleMode 함수
이제 값을 설정했으면 'SetConsoleMode'를 사용하여 수정한 설정값을 적용하면 됩니다.
1
2
|
//수정한 콘솔 모드를 설정한다.
SetConsoleMode(consoleHandle, consoleMode);
|
cs |
F11을 눌렀을 때 전체화면으로 전환되는 것을 막아 봅시다.
F11을 막기 위한 코드는 아래와 같습니다.
1
2
3
4
5
6
|
IntPtr consoleHandle = GetStdHandle((int)-10);
UInt32 consoleMode;
GetConsoleMode(consoleHandle, out consoleMode);
consoleMode &= ~((uint)0x0001);
SetConsoleMode(consoleHandle, consoleMode);
|
cs |
이제 전체화면 전환이 되지 않는 것을 알 수 있습니다.
'빠른 편집 모드'를 끄려면 '0x0040'를 입력하면 됩니다.
인터넷을 돌아다니다가 이걸 쓰기 좋게 캡슐화된 게 있습니다.
참고 : stackoverflow 'Patrick from NDepend team' 님 답변 - How to programmatic disable C# Console Application's Quick Edit mode?
제가 살짝 정리를 한 건 이겁니다.
github - dang-gun/DotNetSamples/ConsoleModeSettingTest/
윈폼(Winform)처럼 자체적인 함수를 지원해주면 좋겠다는 생각을 하는데 말이죠.....
콘솔 응용프로그램이라는 게 UI없는 만큼 퍼포먼스가 좋으라고 쓰는 거라 그런 걸까요?