Button1->Click();
은 마우스로 누르는것과 같지 않습니다.
그냥 TControl클래스에 있는 Click이라는 함수 호출입니다.
Click함수안에서 TNotifyEvent 변수인 FOnClick에 메소드가 할당되어있으면 호출해주죠
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShowMessage("Button1Click");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Button1->Click();
}
//---------------------------------------------------------------------------
위 코드에서 Button2Click이 호출되면
어떤과정을 통해 Button1Click이 호출되는지 확인해 봤습니다.
먼저 Click이라는 함수는 TControl에 dynamic으로 선언된 함수입니다.
dynamic이란 virtual이란 비슷한놈이로 child-class에서 override해서 쓸수 있는 함수입니다.
1) 먼저 다음과 같이 Button1->Click(); 함수가 호출되면
VMT(Virtual-Method-Table)에서 상속받은 하위 클래스에서 Click함수를 override한놈이 있는지 찾아서
호출해줍니다.
TButton의 경우 Click을 override해서 사용합니다.
// procedure TControl.Click; dynamic;
2) 그래서 TButton의 Click함수가 호출됩니다.
procedure TButton.Click;
var
Form: TCustomForm;
begin
Form := GetParentForm(Self);
if Form <> nil then Form.ModalResult := ModalResult;
inherited Click; //여기서 TControl의 Click함수가 호출되구요
end;
3) 세번째로 TControl.Click에서 실제 연결된 이벤트가 호출됩니다.
procedure TControl.Click;
begin
{ Call OnClick if assigned and not equal to associated action's OnExecute.
If associated action's OnExecute assigned then call it, otherwise, call
OnClick. }
if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
FOnClick(Self)
else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
ActionLink.Execute(Self)
else if Assigned(FOnClick) then
FOnClick(Self); //대부분 이경우에서 호출되죠
end;
위코드에서 보는 바와같이 메세지로 동작되는 부분이 전혀 없습니다.
모두 그냥 함수 호출이죠
그래서 개인적으로 박영목님께서 격으신 그런 경우는 없다고 봅니다.
-----------------------------------------------------------------------------------------
그럼에도 불구하고 Button1->Click() 호출했을때
Button1의 OnClick이벤트 핸들러에 연결된 이벤트함수가 호출이 되지 않는경우가 있다면...?
1. Design-time에 OnClick이벤트에 연결된 이벤트 핸들러가 잘못연결된 경우가 있지 않나 하는 생각이 듭니다.
코딩은 100%문제가 없지만
design-time에 Button의 property설정한것이 개발자도 모르게 실수로 바꾸러 버려니는 경우가 왕왕있거둔요
아울러 design-time에 설정한것은 xxx.dfm 파일에 모두 기록되고
이 dfm파일을 컴파일하면 exe또는 dll에 리소스로 모두 포함됩니다.
만약 이 리소스에 문제가 있으면 OnClick이벤트 프로퍼티가 run-time에 제대로 연결이 되지 않을수도 있습니다.
(언어팩을 쓴다던가...)
2. 음.. 또 사용하신 컴포넌트가 기본 Button의 OnClick이벤트가 아닌 경우가에 그럴 가능성이 있지 않을까 하는
생각이 듭니다.
TControl의 멤버에 TNotifyEvent 형 FOnClick이라는 변수가 있는데..
서드파트 컴포넌트의 Click이벤트에서는 저 변수를 이용하지 안는다면.. 그런 문제가 발생할수도 있을거 같습니다.
3. 세번째로 Click메소드를 override한 Child-class에서 TControl의 Click을 다시 호출해주지 않는다면..
그런 문제가 발생할수도 있을것 같습니다.
4. 이건 거의 일어나 가능성이 희박하지만..
다른곳에서 AccessViolation이 발생했는데..
그것이 하필이면 Button의 Virtual-Method-Table을 건드려서.. VMT의 내용을 이상하게 바꿔버렸다면..
그럴 경우가 발생할수도 있을것 같습니다.
5. 기타 제가 잘 모르는 다른 경우가 분명히 더 있을것입니다..
개인적으로 1번이 가장 유력하지 않나 하는 생각이 듭니다만..
Button-Click의 경우 말고도 ..
프로퍼티가 자신도 모르게 바뀌어 문제의 원인을 찾는데.. 시간을 소비하는 경우가
저도 많이 격었구.. 또 많은 개발자들이 그러더군요...
그런 문제를 피하기 위해서는
중요한 프로퍼티인 경우에 반드시 코딩으로 프러퍼티를 설정해서 확인사살 해주곤 합니다.
다음과 같이 폼의 생성자나 OnCreate이벤트 등에서..
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Button1->OnClick = Button1Click
}
위와같이 하면 실수로 프로퍼티 변경되서 발생하는 문제도 필할수 있고..
또한 코딩만 읽어도 동작을 알수가 있죠..
프로퍼티에만 설정해두면.. 나중에 시간이 지나서 코드를 읽을때 .. 어떻게 동작되는지 이해가 안가는 경우가
왕왕있더군요...
지금시간 새벽3시반
정신이 맑지가 않네요.. 헹설수설했더라도 용서해 주세요
그럼...
박영목.월천 님이 쓰신 글 :
: Button1->Click(); 이런 형태... 요 근래... 제 프로그램에서 혹 어떤 경우에 누르지 못하는 경우를 발견했습니다.
:
: 저도 몇년을 사용했는 데... 요 근래 알았다는 것... 프로그램이 부하가 좀 되는 넘이라 그런 지... 이것을 뛰어 넘더군요... 그래서 생각했 보았습니다. 저것도 사람이 마우스로 누르는 것과 같으니... 바쁘면 윈도우가 띄어 넘을 수 있지 않을까? 인터페이스 쪽이라 그런가?
:
: 그래서... Click(); 안에 있는 놈을 그냥 함수로 하나 만들고... 이것을 Click과 다른 곳에서 호출할 때 사용하도록 바꾸었습니다.... ^^ 혹 나만 그런가? 혹 경험하신 분들 답변 부탁드립니다 ^^
:
:
: 그대의의미 님이 쓰신 글 :
: : 나그네 님이 쓰신 글 :
: : : 한 화면에 여러개의 컴포넌트가 배치 되어 있습니다.
: : : 버튼도 여러개 있고요...
: : :
: : : 그런데 Enter 키를 누르면 포커스가 어디에 있던지 무조건 한개의 버튼의 클릭이벤트를 실행하고 싶습니다.
: : :
: : : 한개의 화면상에서 Enter 는 무조건 한개의 버튼 클릭이벤트를 연결시키는 방법을 알고 싶습니다.
: :
: : void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
: : TShiftState Shift)
: : {
: : if(Shift.Empty() == true && Key == VK_RETURN)
: : Button1->Click();
: : }
: :
: : 이렇게하고 프로퍼티에 KwyPreview = true
: : 로 만들어주면 해당버튼만 눌러지는것과같습니다