사용자가 키를 누를 때 OnKeyPress
이벤트를 수신하려고합니다.편집 상자에서 Tab 키를 누르는 방법?
procedure TForm1.Edit1(Sender: TObject; var Key: Char);
begin
case Key of
#09:
begin
//Snip - Stuff i want to do
end;
end;
end;
내가는 Edit
상자를 서브 클래스 시도하고 WM_GETDLGCODE
메시지 처리 :
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_GETDLGCODE: Message.Result := DLGC_WANTTAB;
else
FOldAccountNumberWindowProc(Message);
end;
end;
을 그리고 (내가 희망으로) 내가 지금 이벤트 탭의 키를받을 수 있지만 지금은 왼쪽을 누르면 또는 오른쪽 커서 키를 사용하면 탭 순서에서 이전 또는 다음 컨트롤로 포커스가 이동합니다.
탭 키 을 눌러 이벤트를 수신 할 수있는 올바른 방법은 무엇입니까?
내가 MSDN 설명서를 말한다 일을 시도
보너스 읽기 :
의 wParam
문제이 통지에 윈도우를 묻는 메시지가 사용자가 누른 가상 키. 처리기는이 키를 선택적으로 처리해야합니다. 예를 들어 처리기가 VK_RETURN을 수락하고 처리하지만 소유자 창에 대리자 VK_TAB을 위임 할 수 있습니다. 값 목록은 가상 키 코드를 참조하십시오.lParam MSG 구조체에 대한 포인터입니다 (시스템에서 쿼리를 수행 할 경우 인 경우 NULL).
그러나 wParam
및 wParam
은 모두 0입니다.
업데이트 두
는 내가 같은 bug as this answer을 실현 :
if Message.Msg = WM_GETDLGCODE then
Message.Result:= Message.Result or DLGC_WANTTAB
else
if Assigned(FOldWndProc) then FOldWndProc(Message);
사실은 같은 대답에 다른 부분에서 올바른 코드에서 개념을 사용해야하는 경우 :
if Assigned(FOldWndProc) then FOldWndProc(Message);
if Message.Msg = WM_GETDLGCODE then
Message.Result:= Message.Result or DLGC_WANTTAB;
그 원래 코드가 잘못된 이유를 설명하는 데 도움이됩니다. DLGC_WANTTAB
에 Message.Result
을 설정하는 것은 잘못된 것입니다 :
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_GETDLGCODE: Message.Result := DLGC_WANTTAB;
else
FOldAccountNumberWindowProc(Message);
end;
end;
가 Message.Result
에 bitwise or
플래그 DLGC_WANTTAB
시도도 잘못, Message.Result
아직 값이 없기 때문에 :
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_GETDLGCODE: Message.Result := Message.Result or DLGC_WANTTAB;
else
FOldAccountNumberWindowProc(Message);
end;
end;
내가 먼저 전화를해야합니다 원래 창 절차, Windows 'EDIT
컨트롤을 Message.Result
의 올바른 값을 설정하십시오.,
그것이 싶은 생각하는지 행동 원본 제어를 요구 한 후 :
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage); begin FOldAccountNumberWindowProc(Message); case Message.Msg of WM_GETDLGCODE: Message.Result := Message.Result or DLGC_WANTTAB; end; end;
는 레이몬드 첸의 블로그 항목 및 추가 중점을 의역 필요 : 그런 다음 내가
DLGC_WANTTAB
결합 비트 단위 수 DLGC_WANTTAB 플래그를 설정합니다.
이렇게 좋습니다. 커서 키는 계속 포커스를 이동하는 대신 편집 컨트롤의 텍스트를 탐색하며 Tab 키에 대해 OnKeyPress
(및 OnKeyDown
및 OnKeyUp
) 이벤트를받습니다.
나머지 문제는 Tab을 누르는 사용자가 더 이상 초점을 이동하지 않는다는 것입니다.
내가 자신을 변화에 초점 해킹 수동으로 시작하도록 시작하려고 :procedure TfrmEnableVIPMode.edAccountNumberKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
#09:
begin
//Snip - Stuff i want to do
{
The DLGC_WANTTAB technique broke Windows focus change.
Keep throwing in hacks until it's no longer obviously broken
}
//Perform(CM_DialogKey, VK_TAB, 0); //doesn't work
Self.ActiveControl := Self.FindNextControl(edAccountNumber, True, True, False);
end;
end;
end;
위의 코드는 작동합니다 - 사용자가 탭 키를 누를 경우. 그러나 레이몬드 첸 (Raymond Chen)이 6 년 전에 메모 한 바에 따르면 코드가 깨졌습니다.
이 접근 방식에는 많은 문제가 있습니다. 이 코드가 대화 상자에서 포커스를 올바르게 설정하지 못하는 방법, 중첩 대화 상자를 고려하지 않는 방법, Shift + Tab 탐색 키를 처리하지 못하는 방법
내 경우에 깨 졌어요 시프트 + 입니다. 그리고 그 밖의 무엇을 알지.
그래서, 내 질문은 :
어떻게 편집 상자에 TAB 키 누름을받을 수? 그들이 먹을
은 내가 난 그냥 에 사용자가 탭 키를 누르면을 알고 싶어하지 않습니다.에 메시지를 키를 감지 할 수도 있습니다
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
CN_KEYDOWN:
if TWMKey(Message).CharCode = VK_TAB then
....
end;
FOldAccountNumberWindowProc(Message);
end;
:
['this post'] (http://stackoverflow.com/q/2363456/960757)에서 영감을 얻을 수 있습니다. – TLama
@TLama 내가 사용하고있는 접근 방법에서 (공통적 인) 버그를 찾는데 도움이되었습니다. 나는 완전히 잘못된 접근법을 사용하고 있을지 모르지만 적어도 버그가있는 잘못된 접근법을 고쳤다. –
먼저 "편집 컨트롤이 포커스를 이동하는 대신 Tab 키를 가져 오도록"라고 말한 다음 "편집 컨트롤이 포커스를 이동하는 대신 Tab 키를 가져옵니다!"라고 불평합니다. 어느 쪽을 원하니? –