|
문보석 님이 쓰신 글 :
: 안녕하세요... 문보석입니다...
: 팝업메뉴의 아이템들을 다음과 같이 구성했습니다...
:
: 가장 큰 목록은 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를 사용해야 합니다.
그럼 참고하시길...
|