C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[703] [DesignPattern] Enter 를 Tab 처럼 사용하기
장성호 [nasilso] 16193 읽음    2007-08-23 17:55
아래 내용은 이미 많이들 알고있는 방법이고
Q&A에 검색하면 나오는 것이지만 한번 정리해 봅니다.


제목 : Enter를 Tab 처럼 사용하기


[방법1]

    1. 위 기능을 적용하고 싶은 Control의 OnKeyPress  이벤트에서
    2. Key를 확인한후에 SendMessage로 Form에 WM_NEXTDLGCTL을 날리면 됩니다

//C++Builder
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
    if(Key==VK_RETURN) 
        Perform(WM_NEXTDLGCTL,0,0);
}


 //Dephi
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
    if Key = Char(VK_RETURN) then
        Perform(WM_NEXTDLGCTL,0,0);
end;


    * 문제점
      그런데 이방법의 문제점은 적용하고 싶은 Control이 많은 경우에 문제가 됩니다.
      원하는 모든 Control에 해당 위 code를 copy하거나
      아니면 모든 Control이 이벤트 핸들러를 하나의 Method로 걸어두거나 하는 방법이 있지만
      귀찮고 불편할것입니다.


[방법2]
     그래서 Form전체에 한번에 적용하는 방법으로 해봅니다.
     1. Form의 KeyPerview = true 로 해두시구요
     2. Form의 OnKeyPress 이벤트에 방법1에서와 같은식으로 코딩해 둡니다.

//c++Builder
void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)
{
     if(Key==VK_RETURN)
     {
          Perform(WM_NEXTDLGCTL,0,0);
          Key=0;
     }
}


     
//Dephi
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = Char(VK_RETURN) then
    Perform(WM_NEXTDLGCTL,0,0);
end;


     * 근데 위 방법은 TMemo같이 Enter키에 다음 라인으로 넘어가야 하는 Control에는 적용되면 문제가 되겠죠

     * 그래서 아래와같이 현재 Focus가 되어있는 Control이 무엇인지 확인해 보구 적용합니다.

//c++Builder
void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)
{
    if(Key==VK_RETURN)
    {
        String sClsName=ActiveControl->ClassName();
        if(sClsName=="TEdit" || sClsName=="TComboBox")
        {
            Perform(WM_NEXTDLGCTL,0,0);
            Key=0;
        }
    }
}


//Dephi
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = Char(VK_RETURN)) then
    if ActiveControl is TEdit  then
      Perform(WM_NEXTDLGCTL,0,0);
end;


     * 문제점:
       방법2에도 문제점이 있는데 Form이 여러개 있는경우가 그렇겠죠
        문론 해당코드를 모두 copy - paste하시면 됩니다만..

[방법3]

     방법2의 문제점은 Application의 OnMessage이벤트를 이용해 해결할수 있습니다.

     1. Application의 OnMessage 에 이벤트 핸들러를 걸어두시구
     2. 해당 핸들러 함수에서 Screen의 ActiveForm과 ActiveContol을 확인하여 처리하면 됩니다.

//c++Builder
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
        Application->OnMessage = AppMessage;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::AppMessage(tagMSG &Msg, bool &Handled)
    {
        if(Msg.message == WM_KEYDOWN)
        {
            if(Msg.wParam == VK_RETURN)
            {
                String sClsName=Screen->ActiveControl->ClassName();
                if(sClsName=="TEdit" || sClsName=="TComboBox")
                {
                    Screen->ActiveForm->Perform(WM_NEXTDLGCTL,0,0);
                    Msg.wParam=0;
                }
            }
        }
    }


//Dephi
procedure TForm1.FormCreate(Sender: TObject);
begin
   Application.OnMessage := AppMessage;
end;

procedure TForm1.AppMessage(var Msg:tagMSG;var Handled: boolean);
var
  sClsName: String;
begin
    if Msg.message = WM_KEYDOWN then
    begin
        if Msg.wParam = VK_RETURN then
        begin
            sClsName:=Screen.ActiveControl.ClassName();
            if (sClsName='TEdit') or  (sClsName='TComboBox') then
            begin
                Screen.ActiveForm.Perform(WM_NEXTDLGCTL,0,0);
                Msg.wParam:=0;
            end;
        end;
    end;
end;


    3.위와같이 하면 전체 application에 적용되는데 해당기능을 원하지 않는 Form이 있다면
     Screen->ActiveForm이 무엇인지 확인해본후 적용하면 되겠죠

    
//=========================================================================================

[응용]

   위 방법3은 다양하게 응용이 가능합니다.

   개인적으로 MainForm이 아닌 Form들은 Esc 키에 Close하고 싶은데...
   방법2로 모든 Form의 OnKeypress이벤트에 적용해도 되지만

   방법3의 Application->OnMessage 를 이용하면 간단하게 되죠
//c++Builder
    void __fastcall TForm1::AppMessage(tagMSG &Msg, bool &Handled)
    {
        if(Msg.message == WM_KEYDOWN)
        {
            if(Msg.wParam == VK_ESCAPE)
            {
                if( Screen->ActiveForm != Application->MainForm) // 메인폼이 아닌경우 
                {
                    Screen->ActiveForm->Close();
                }
            }
        }
    }


//Dephi
procedure TForm1.AppMessage(var Msg:tagMSG;var Handled: boolean);
begin
  if (Msg.message = WM_KEYDOWN) and (Msg.wParam = VK_ESCAPE) then
      if Screen.ActiveForm <> Application.MainForm then // 메인폼이 아닌경우
          Screen.ActiveForm.Close();
end;


   * 그밖에도 여러가지로 응용할수 있습니다.



* 앗참 한가지더..

Tab 키가 다음 Control로 Focus가 이동되구 Shift + Tab이  이전 Control로 Focus가 이동되듯이
Shift + Enter 키에 이전 Control로 Focus가 이동하려면
     Perform(WM_NEXTDLGCTL,VK_SHIFT,0); // 이렇게 메세지를 날리면 됩니다.


* 앗참 또 한가지
     Form의  Perform(WM_NEXTDLGCTL,0,0); 는 
     Form의  SelectNext(ActiveControl,true,0) 함수로 해도 됩니다.

     오히려 SelectNext가 좋겠네요.
     
     SelectNext(ActiveControl,false,0); 하면 Shift + Tab 과 같습니다.

 
그럼..
김태선 [cppbuilder]   2007-08-23 19:17 X
좋은 자료네요.

이런 많이 쓰이는 기법은 자료 정리가 되어 있는게 무척 중요합니다.
정작 쓰려고 찾을때 시간이 꽤 걸리기도 하거든요.
장성호 [nasilso]   2007-08-29 18:08 X
[추신] 폼이 포함된 dll에 관해

runtime-packages를  un-check 하시면 dll에서도 위코딩을 해야하구요
runtime-packages가  checked 되어 컴파일하셨으면 exe에서만 구현하면
dll에도 똑같이 적용됩니다.

왜냐하면 runtime-packages 설정에따라 Application객체가 같은놈이 될수도 있고
다른놈이 될수도 있으니까요

그럼...
쏘세지 [hacker004]   2007-11-15 14:15 X
완전 감사합니다... 장성호님의 위에 설명도~~굿뜨...^^
장성호 [nasilso]   2008-05-19 15:33 X
델파이 코드로..

    if(Msg.wParam= VK_RETURN) then
    begin
        sClsName:=Screen.ActiveControl.ClassName();
        if(sClsName='TEdit') or (sClsName='TMemo') or (sClsName='TComboBox') then
        begin
          Screen.ActiveForm.Perform(WM_NEXTDLGCTL,0,0);
          Msg.wParam:=0;
        end;
    end;
배고픈 홍콩토끼 [jyroe]   2008-11-25 12:06 X
이야.. 정말 제가 이런 자료를 찾아서 3일을 돌아다녔는데.. 꼭 알고 싶었던 내용이 몽땅 한번에 정리가 되어 있네요.. 예제코드까지 친절하게 다 적어주시니 정말 엄청난 자산을 얻은 거 같습니다.
너무 친절하십니다. 복 받으실 거에요.
아폴론 [apollon]   2009-02-04 15:53 X
장성호님..감사합니다.
한번쯤 이 글을 본 듯 싶은데...ㅎㅎ
좋은 자료입니다.
복사해 갑니다.. 리이코스메일 바꾸지 말자고요..라이코스를 지원하지 않을 때 까지..ㅎㅎ

+ -

관련 글 리스트
703 [DesignPattern] Enter 를 Tab 처럼 사용하기 장성호 16193 2007/08/23
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.