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

C++빌더 Q&A
C++Builder Programming Q&A
[2863] Re:팝업메뉴의 아이템들을 클릭했을때 인덱스를 구별하는법....
박지훈.임프 [cbuilder] 3856 읽음    2000-01-25 00:00
문보석 님이 쓰신 글 :
: 안녕하세요... 문보석입니다...
: 팝업메뉴의 아이템들을 다음과 같이 구성했습니다...
:
: 가장 큰 목록은 a , b , c 라고 세가지로 했구요...
: 다음 a 의 서브아이템이 1 , 2 , 3 이라고 또 세가지가 있습니다...
: b 의 서브아이템은 4 , 5 가 있다고 하고
: c 의 서브아이템은 6 , 7 이 있다고 합시다...
: 이때 a,b,c 들의 서브아이템( 1 ~ 7 )이 클릭되었을때 이것들을 구분하는 인덱스를 구성하려고
: 하는데 하나 하나 클릭이벤트핸들러를 만들어서 인덱스를 표시 해줄수는 없잖아요...
: 그래서 a 의 서브아이템을 모두 한꺼번에 선택해서 클릭이벤트핸들러를 하나에 만들어주니까
: 그 핸들러의 디폴트이름은 한꺼번에 선택한 아이템중에 가장 나중에 선택한 아이템의 이름을
: 따서 N31click() 이라고 만들어지더군요...
: 이 핸들러에 다음과 같이 써넣어습니다..
:
: void __fastcall TForm1::N31Click(TObject *Sender)
: {
:   Edit1->Text = (N31->Parent)->MenuIndex;   // 클릭한 아이템의 parent 인덱스를 구함
:   Edit2->Text = N31->MenuIndex;             // 클릭한 아이템의 인덱스를 구해야함!!!
: }
:
: 당연히 여기서 에디트박스2에는 항상 일정한 인덱스 값(2)이 표시되겠죠...
: 물론 여기에서 에디트박스1에도 '0'이라는 값이 일정하지만 다른 서브아이템을 클릭하면 당근 자신의
: parent 인덱스를 구하구요...
: 결국 에디트박스2에 제가 선택한 아이템의 인덱스를 구하는 법을 못찾아내고 이렇게 질문드립니다...
: 클릭한 아이템의 핸들이나 포인터 같은 것을 어떤식으로 구해야 하는지 궁금합니다...
: 저기 저 Sender라는 놈을 통해 뭔가 알아낼수 있을것 같아 고민해보기도 했지만 모르겠더군요..^^;;;;
: 너무 장황하게 설명을 드렸는데 제 의도는 전달될것 같습니다...
: 그럼 안녕히...



임펠리테리입니다.

모든 이벤트핸들러는 기본적으로 하나 이상의 인자를 갖는데, 이 기본적인 하나의 인자가 Sender
로서, 이벤트가 발생한 객체를 의미합니다. 모든 클래스에서 공유될 수 있어야 하므로 TObject형
으로 넘어오지만 캐스팅을 하면 원래의 객체로서 사용가능합니다.

예를 들어서, 여러 버튼이 공유하고 있는 OnClick 이벤트핸들러에서, 어느 버튼에서 클릭 이벤트가
발생했는지를 알아내려면 넘어오는 Sender 인자를 TButton * 형으로 캐스팅하면 됩니다.
이때 표준 C/C++의 캐스팅을 사용해도 되고 dynamic_cast를 사용해도 되는데, 만약 표준 캐스팅을
사용할 경우라면 넘어오는 인자가 반드시 TButton *형이라는 보장이 되어 었어야 합니다.
(이벤트핸들러도 그냥 함수이므로 프로그래머가 코딩으로 임의로 실행시킬 수 있고, 인자도
맘대로 넘길 수 있으니까요.) 만약 Sender가 항상 버튼이라는 보장이 있다면, 다시 말해 임의로
그 이벤트핸들러를 호출해준 경우가 없다면 그냥 TButton으로 호출해도 됩니다.

또한 한가지 컴퍼넌트가 아닌, 여러가지의 컴퍼넌트에서 공유하는 이벤트핸들러의 경우 Sender는
발생한 컴퍼넌트의 클래스 종류에 따라 당근 달라지는데, 이때는 반드시 dynamic_cast를 사용해서
Sender가 실제로는 어떤 클래스인가를 판별해주어야 합니다.

본론으로 들어가서, 말씀하신 메뉴아이템의 OnClick 핸들러를 다른 코드에서 임의로 호출해준
경우도 없고 또 메뉴아이템 이외의 객체에 연결되어 있지 않다고 전제합시다. (당연한 것 같지만
실제로는 그런 코딩을 할 경우도 꽤 있습니다.) 그러면 다음과 같이 하면 됩니다. 단순한 표준
캐스팅을 사용한 것입니다.

void __fastcall TForm1::N31Click(TObject *Sender)
{
  Edit2->Text = ((TMenuItem *)Sender)->MenuIndex;
}

물론, 캐스팅도 연산이므로 CPU 클럭을 먹게 됩니다. 그러므로 만약 캐스팅된 포인터를 반복해서
사용해야 한다면 TMenuItem * 형의 변수를 하나 만들어 거기에 넣어놓고 사용하는 것이 좋겠죠?

여기서는 표준 캐스팅을 사용했습니다. 물론 dynamic_cast를 사용해도 됩니다만, dynamic_cast은
퍼포먼스를 상당히 감소시키는 느린 연산이므로 필요한 경우가 아니라면 피하는 것이 좋습니다.
하지만, 앞에서도 말했듯이, 여러가지 타입의 컴퍼넌트가 한 이벤트핸들러를 공유한 경우와 같이
Sender가 실제로 어떤 클래스의 객체인지를 따져야 할때는 dynamic_cast를 사용해야 합니다.

그럼 참고하시길...

+ -

관련 글 리스트
2852 팝업메뉴의 아이템들을 클릭했을때 인덱스를 구별하는법.... 문보석 3588 2000/01/25
2863     Re:팝업메뉴의 아이템들을 클릭했을때 인덱스를 구별하는법.... 박지훈.임프 3856 2000/01/25
2870         감사합니다... 이런데서 기초가 부족하다는걸 느낍니다... 문보석 3874 2000/01/26
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.