Windows Forms 응용 프로그램에서 키보드 단축키를 구현하는 가장 좋은 방법은 무엇입니까?


280

C #의 Windows Forms 응용 프로그램에서 일반적인 Windows 키보드 단축키 (예 : Ctrl+ F, Ctrl+ N) 를 구현하는 가장 좋은 방법을 찾고 있습니다.

이 응용 프로그램에는 많은 하위 양식을 한 번에 하나씩 호스팅하는 기본 양식이 있습니다. 사용자가 Ctrl+를 누르면 F맞춤 검색 양식을 표시하고 싶습니다. 검색 양식은 응용 프로그램의 현재 열려있는 자식 양식에 따라 다릅니다.

ChildForm_KeyDown 이벤트 에서 이와 같은 것을 사용하려고 생각 했습니다.

   if (e.KeyCode == Keys.F && Control.ModifierKeys == Keys.Control)
        // Show search form

그러나 이것은 작동하지 않습니다. 키를 눌러도 이벤트가 시작되지 않습니다. 해결책은 무엇인가?


Winforms에 기본 Windows API와 같은 특정 기능이없는 것 같습니다.
스튜어트

답변:


460

폼의 KeyPreview 속성을 True 로 설정하지 않은 것 같습니다 . ProcessCmdKey () 메서드를 재정의하는 것이 일반적인 솔루션입니다.

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
  if (keyData == (Keys.Control | Keys.F)) {
    MessageBox.Show("What the Ctrl+F?");
    return true;
  }
  return base.ProcessCmdKey(ref msg, keyData);
}

이것은 잘 작동하지만 양식이 활성 창 인 경우에만 감지합니다. 누구나 창보기에서 바인딩하는 방법을 알고 있습니까?
Gaʀʀʏ

어떤 상황 KeyPreview에서는 매우 필수적입니다. 예를 들어, 입력을 억제하기 위해 단축키를 눌러야하지만 별도의 MenuStrip이벤트가 발생 하도록해야합니다 . ProcessCmdKey접근은 이벤트 발생 로직의 복제를 강요합니다.
사울

1
흠, 폼의 KeyDown 이벤트 처리기는 메뉴 항목의 Click 이벤트 처리기와는 상당히 다릅니다. 이벤트 핸들러 메소드를 직접 호출하거나 (이벤트에 의해 독점적으로 호출 할 필요는 없음) 공통 로직을 별도의 메소드로 리팩터링하는 것과 동일한 방법으로 여전히 동일한 방법을 수행합니다.
Hans Passant 2016 년

14
"Ctrl + F 란 무엇입니까?" LOL
kchad

73

메인 양식

  1. KeyPreviewTrue로 설정
  2. 다음 코드로 KeyDown 이벤트 핸들러 추가

    private void MainForm_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.N)
        {
            SearchForm searchForm = new SearchForm();
            searchForm.Show();
        }
    }
    

4
+ for, KeyPreview를 True로 설정하십시오.
Usman Younas

20

가장 좋은 방법은 메뉴 니모닉을 사용하는 것입니다. 즉, 원하는 바로 가기 키가 할당 된 기본 양식의 메뉴 항목을 갖는 것입니다. 그런 다음 다른 모든 것은 내부적으로 처리되며 해당 Click메뉴 항목 의 이벤트 핸들러 에서 실행되는 적절한 조치를 구현하기 만하면됩니다.


1
문제는 메인 폼이 일반적인 윈도우 메뉴를 사용하지 않는다는 것입니다. 하위 양식을 표시하는 데 사용되는 사용자 정의 탐색 패널을 사용합니다. 하위 양식에서 ToolStripButton을 클릭하면 검색 양식이 호출됩니다.
Rockcoder

menu mnemonics실제 샘플?
Kiquenet


1
니모닉은 바로 가기 키와 구별되는 개념이며 작동 방식에 중요한 차이점이 있습니다. 간단히 말해 니모닉은 키보드를 사용하여 메뉴, 메뉴 명령 및 대화 상자 컨트롤에 액세스하는 데 사용되는 밑줄이 그어진 문자입니다. OTOH, 바로 가기 키는 메뉴를 거치지 않고 명령에 액세스하는 방법이며, 문자 키로 제한되지 않고 Ctrl + F 또는 F5와 같은 임의의 키 입력이 될 수 있습니다.
스튜어트

1
@Stewart 맞습니다! 내 대답은 모든 키보드 단축키가 니모닉임을 암시하려는 것이 아니라 메뉴 니모닉 이이 기능을 얻는 가장 쉬운 방법이라는 것을 의미했습니다. 불행히도 Rockcoder의 의견에서 알 수 있듯이이 솔루션은 여기에 적합하지 않습니다. 가능한 한 여전히 바람직한 솔루션으로 권장합니다. 일반적인 해결책으로 Hans의 대답은 앞으로 나아갈 것입니다.
Konrad Rudolph

11

이 예제를 시도해 볼 수도 있습니다.

public class MDIParent : System.Windows.Forms.Form
{
    public bool NextTab()
    {
         // some code
    }

    public bool PreviousTab()
    {
         // some code
    }

    protected override bool ProcessCmdKey(ref Message message, Keys keys)
    {
        switch (keys)
        {
            case Keys.Control | Keys.Tab:
              {
                NextTab();
                return true;
              }
            case Keys.Control | Keys.Shift | Keys.Tab:
              {
                PreviousTab();
                return true;
              }
        }
        return base.ProcessCmdKey(ref message, keys);
    }
}

public class mySecondForm : System.Windows.Forms.Form
{
    // some code...
}

8

메뉴가있는 경우 ShortcutKeys속성 을 변경 ToolStripMenuItem하면 트릭을 수행해야합니다.

그렇지 않은 경우 하나를 작성하고 해당 visible특성을 false로 설정할 수 있습니다 .


아니요 메뉴가 없습니다. 검색을위한 ToolStripButton은 실제로 BindingNavigator 컨트롤에 있으므로 메뉴를 추가하는 것은 옵션이 아닙니다.
Rockcoder

6

기본 양식에서 다음을 수행해야합니다.

  • KeyPreviewtrue로 설정했는지 확인하십시오 (기본적으로 TRUE).
  • MainForm_KeyDown (..)을 추가하십시오 -여기에서 원하는 단축키를 설정할 수 있습니다.

또한, 나는 이것을 구글에서 발견했으며 여전히 답을 찾고있는 사람들에게 이것을 공유하고 싶었습니다. (전세계)

user32.dll을 사용해야한다고 생각합니다.

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == 0x0312)
    {
        /* Note that the three lines below are not needed if you only want to register one hotkey.
         * The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */

        Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);                  // The key of the hotkey that was pressed.
        KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);       // The modifier of the hotkey that was pressed.
        int id = m.WParam.ToInt32();                                        // The id of the hotkey that was pressed.


        MessageBox.Show("Hotkey has been pressed!");
        // do something
    }
}

http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/를 더 읽으십시오 .


4

Hans의 답변 은이 새로운 사람에게는 조금 더 쉬울 수 있으므로 여기 내 버전이 있습니다.

당신은 바보로 KeyPreview설정할 필요가 없습니다 false. 아래 코드를 사용하려면 아래 코드를 붙여 form1_load넣고 작동 F5하는지 확인하십시오.

protected override void OnKeyPress(KeyPressEventArgs ex)
{
    string xo = ex.KeyChar.ToString();

    if (xo == "q") //You pressed "q" key on the keyboard
    {
        Form2 f2 = new Form2();
        f2.Show();
    }
}

7
먼저 ProcessCmdKey를 재정의하는 것이 OP와 관련하여 명령과 같은 작업을 수행하기위한 키 입력을 처리하는 데 권장되는 방법입니다. 둘째, KeyPreview를 true로 설정하는 것에 대한 Hans의 의견을 오해했습니다. 그는 방금 OP에게 자신의 기술이 작동하지 않는 이유를 말하고있었습니다. ProcessCmdKey를 사용하려면 KeyPreview를 true로 설정하지 않아도됩니다.
RenniePet

2

WinForm에서는 항상 다음을 통해 제어 키 상태를 얻을 수 있습니다.

bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.