KeyDown 이벤트에 응답하지 않는 양식


82

저는 Windows Forms 프로젝트에서 한동안 작업 해 왔으며 키보드 단축키를 실험하기로 결정했습니다. 조금 읽은 후 이벤트 핸들러를 작성하고 폼의 KeyDown 이벤트에 바인딩해야한다고 생각했습니다.

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.Alt && e.KeyCode == Keys.O)
    {
        MessageBox.Show("Ctrl+Alt+O: magic!");
    }
}

Visual Studio 디자이너의 속성 패널을 연 다음 양식의 KeyDown 이벤트를 두 번 클릭하여 Form1_KeyDown이벤트 처리기 를 생성하는 좋은 방법을 사용했습니다 . 그러나 내 응용 프로그램을 테스트 할 때 양식이 Ctrl+ Alt+ O키보드 단축키에 전혀 응답하지 않습니다 . Visual Studio 디자이너는 이벤트 처리기를 폼에 바인딩하는 코드를 생성했습니다.

private void InitializeComponent()
{
    // ...

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

    // ...
}

그래서 나는 Console.WriteLine()그것이 호출되고 있는지 확인하기 위해 핸들러에 호출을 추가하려고 시도 했지만 운이 없었습니다.

또한 이벤트 바인딩 호출 (위에 표시됨)에 중단 점을 설정하려고 시도했으며 프로그램이 해당 중단 점에 제대로 도달한다는 것을 발견했습니다. 그러나 메서드 정의 자체 내에서 설정 한 중단 점에는 도달하지 않습니다.

처음 몇 단계를 올바르게 수행했는지 확인하기 위해 다음과 같이 반복 해 보았습니다.

  • 동일한 솔루션의 새로운 양식.
    같은 문제 : Ctrl+ Alt+ O키보드 바로 가기를 누르면 양식이 응답하지 않고 디버거가 이벤트 처리기로 들어오지 않습니다. 이것을 다시 시도하고 작동합니다.

  • 완전히 새로운 WinForms 솔루션.
    완벽하게 작동합니다. 메시지 대화 상자가 나타납니다 ( Console.WriteLine()통화도 작동 함).

그래서 저는 여기서 길을 잃었습니다. 이 하나의 프로젝트에있는 모든 양식이 KeyDown 이벤트를받지 못하게하는 이유는 무엇입니까?

답변:


173

양식에 KeyPreview 속성이 true로 설정되어 있습니까?

Form.KeyPreview 속성

포커스가있는 컨트롤에 이벤트가 전달되기 전에 폼에서 키 이벤트를 받을지 여부를 나타내는 값을 가져 오거나 설정합니다.

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx


19
VB6 프로그래머를 행복하게 유지하기 위해 사용할 수있는 해킹입니다. 실행 순서 문제가 있으므로 대신 ProcessCmdKey ()를 재정의하십시오.
Hans Passant

@HansPassant, 실행 순서 문제를 설명하는 것을 찾을 수 없습니다. KeyDown + KeyPreview가 모든 키를 볼 수는 없지만 문제는 충분하지만 실행 순서 문제는 무엇입니까?
kdbanman 2015

1
바로 가기 키 입력을 감지하는 재정의가 많이 있습니다. 순서대로 실행하면 KeyPreview + KeyDown이 마지막에 종료됩니다.
Hans Passant 2015

54

StackOverflow 및 MSDN 1 , 2 (여기에 허용 된 답변 포함) 에서이 문제에 대한 가장 일반적인 조언 은 빠르고 쉽습니다.

KeyDown이벤트가 트리거되어 Form그만큼 KeyPreview속성이 설정되어true

대부분의 목적에 적합하지만 두 가지 이유로 위험합니다.

  1. KeyDown핸들러 는 모든 키를 볼 수 없습니다 . 특히 "탐색에 사용되는 키 입력의 종류를 볼 수 없습니다. 대화 상자의 커서 키와 Tab, Escape 및 Enter처럼."

  2. 주요 이벤트를 가로채는 몇 가지 방법이 있으며 모두 순서대로 발생합니다. 마지막KeyDown 으로 처리 됩니다. 따라서 미리보기가 아니고 이벤트는 도중에 몇 정거장에서 침묵 할 수 있습니다.KeyPreview

(이 포인트에 대한 @HansPassant에 대한 크레딧.)

대신 다음을 재정의 ProcessCmdKey하십시오 Form.

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (keyData == Keys.Up)
    {
        // Handle key at form level.
        // Do not send event to focused control by returning true.
        return true;
    }
  return base.ProcessCmdKey(ref msg, keyData);
}

이렇게하면 모든 키가 메서드에 표시되고 메서드가 이벤트를보기 위해 첫 번째 줄에 표시됩니다.

포커스 된 컨트롤이 KeyDown이벤트 를 볼지 여부를 여전히 제어 할 수 있습니다 . 이벤트 처리기 에서 설정 하는 대신 true다음 KeyDown이벤트 를 차단하기 위해 돌아갑니다 . 자세한 내용은 다음과 같습니다 .KeyPressEventArgs.HandledtrueKeyDown


1
특히 KeyPreview가 true로 설정된 상태에서 PreviewKeyDown이 전혀 실행되지 않는 경우 정답입니다.
Tim

23

KeyPreview양식 의 속성을 true로 설정하십시오 . 이것은 키 프레스를 등록하는 데 도움이되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.