본문 바로가기

TechLog

Windows Forms 기반의 프로그램 폼에서 컨트롤의 키 입력을 가로채기

Windows Forms 기반의 프로그램 폼에서 컨트롤의 입력을 가로채기

윈폼 기반의 프로그램을 작성하다보면, 컨트롤들이 특정키 입력을 받지 않도록 만들어야 할 상황이 있습니다. 이 아티클은 그런 상황을 몇 안되는 간단한 코드로 처리하는 방법을 보여줍니다.

 

 

:)

사실 뭐 소개하고 할 내용도 없는 것 같군요. 곧바로 들어가겠습니다아~

 

 

키보드 메시지는 어디로 갔는가?

 

Kenial 은 아직 예전 Win32 API MFC에서 윈도 메시지를 가지고 이런 저런 기능을 만들어내는데에 익숙하다. 최근 들어서는 개발속도의 이점 및 배포시의 편리함 때문에 닷넷 기반의 프로그램을 많이 만들어내고 있는데, 이번에 만들어야 하는 프로그램은 이런 기능이 필요했다 :

 

  Alt + F4로 프로그램이 종료되지 않아야 한다.

 

이 문장을 보고 거의 반사적으로 WM_KEYDOWN을 떠올리는 것이 Kenial에게는 당연한 일인 것이지만, 닷넷에는 닷넷의 방법이 있다.

 

. Alt + F4를 막아보도록 하자.

 

 

KeyPress 이벤트, KeyPreview 속성

 

닷넷 프레임워크의 이벤트에 익숙해 있다면, KeyPress 이벤트로 키보드의 입력을 받을 수 있다는 것을 알고 있을 것이다. 먼저 다음과 같은 간단한 폼을 만들어 보자 :

 

clip_image001

 

그리고 다음과 같이 폼의 KeyPress 이벤트 핸들러를 코딩해보자 :

 

 

 

 

private void Form1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
            System.Diagnostics.Debug.WriteLine("Form1_KeyPress");
}

 

 

 

 

프 로그램을 실행하고 뭔가 키보드 입력을 해 보면 출력창에 "Form1_KeyPress"라는 내용이 나와야 할텐데, 출력되지 않는다. 어째서일까? 간단하게 설명하자면, 키보드 메시지를 텍스트 박스가 먼저 받아서 처리해 버려서 폼의 이벤트 핸들러는 해당 메시지를 받지 못하기 때문이다.

 

이는 KeyPreview 속성을 true로 설정함으로써, 해당 폼의 이벤트 핸들러가 해당 메시지를 먼저 처리하도록 해서 해결할 수 있다. 앞의 프로그램에서 KeyPreview 속성을 true로 설정하면, 텍스트박스에 글자가 입력되면서 출력창에 "Form1_KeyPress"가 출력되는 것을 확인할 수 있다.

 

 

KeyDown 이벤트

 

하지만 KeyPress 만으로는 단지 눌려진 키의 char 코드만 받을 수 있을 뿐이고, Alt, Ctrl 등의 조합키의 입력까지 알아내려면 KeyDown 이벤트를 사용해야 한다. 다음과 같이 이벤트 핸들러를 만들자 :

 

 

 

 

private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    //
폼에서 종료 가능한 키 조합을 막아버리자
    if(e.KeyData == (Keys.Alt | Keys.F4))
        e.Handled = true;
}

 

 

 

 

 

KeyData 속성은 금방 이해된다. 그럼 Handled 속성은?

이 속성은 아까 위에서 설명한 '이 키보드 메시지가 처리되었음' 나타내는 속성이다. false로 설정되어 있으면 Form1에서 포커스를 갖고 있는 자식 컨트롤(여기서는 텍스트박스)에 해당 키보드 메시지를 전달해 주겠지만, true로 설정하면 키보드 메시지를 텍스트박스에도 전달하지 않고 자신의 부모(=System.Windows.Forms.Form, 그리고 그 부모 클래스)에게도 전달하지 않는다.

 

결과적으로, Alt + F4 키 입력으로 프로그램이 종료되지 않게 된다.

 

 

정리

 

사 실 키보드 입력을 막는 방법은 이것으로 끝이 아닙니다. 최상위 윈도우가 받는 키보드 메시지(ctrl + alt + del, alt + tab) 등은 이것만으로는 막을 수 없고, 키보드 입력과 관련된 dll을 후킹해야 가능한 일입니다.

 

하지만 Kenial은 아직 닷넷 기반에서의 후킹은 해본적이 없어서 ;

사실 VC++에서 구현하는 것과 별다른 차이는 없을 거라고 생각하긴 합니다만, 뭐 천천히 적어나가도록 하겠습니다 : )

 

그럼 : )

 

 

p.s:이번 아티클은 분량도 적고.. 캡처할게 별로 없다보니 너무 편하네요 ;

 

p.s2:그리고, 이벤트에 익숙하지 않으신 분이라면 차라리 KeyDown 이벤트보다는 ProcessCmdKey 함수를 오버라이딩해서 사용하시는 편이 더 나을듯도 합니다 : )