네..
원래 그렇습니다.
VCL Control에서 발생하는 메세지 종류 3가지
1. WM_xxx 로 시작하는 메세지
WM 으로 시작하는 메세지는 System에 정의 되어져 있는 메세지 입니다.
2. CM_xxx 로 시작하는 메세지
3. CN_xxx 로 시작하는 메세지
( 더있나?)
그런데 VCL에서는 WM 으로 시작하는 메세지 말고
CM 또는 CN 으로 시작하는 메세지들이 있습니다.
CM 그리고 CN으로 시작하는 메세지는 VCL에만 있는것들입니다.
다시말해 시스템에서 메세지가 발생해서 메세지큐에서 메세지를 가져오는게 아니라
VCL에서 적당한 상황에 메세지를 발생시켜주는것입니다.
그중에 CM_MOUSEENTER, CM_MOUSELEAVE 메세지도 있는데요
CM_MOUSEENTER, CM_MOUSELEAVE 메세지는 언제 발생하나?
아시는 바와같이 CM_MOUSEENTER, CM_MOUSELEAVE 메세지는
어떤 Control의 영역에 마우스가 들어가거나 벗어날때 발생하는 메세지 입니다.
그런데 이 메세지는 앞에서 설명했듯이 시스템에서 발생하는 메세지가 아니라
VCL에서 직접 만들어서 Control에 던져주는데요
언제 만들어주냐?
그것은 System메세지큐에 메세지가 없을때..
즉 휴지(Idle)상태일때 마우스의 위치를 확인해보고 ..
마우스위치가 이전에 있던 위치에서 움직여 다른 control영역으로 넘어가면
메세지를 해당control에 던져줍니다.
님코드에서 문제점
Application->ProcessMessage(); 라는 코드는
시스템 메세지 큐에서 메세지만 가져와서 처리해주는 코드입니다.
시스템 메세지큐에 메세지가 없는 Idle상태일때 처리루틴은 없는것이죠
Idle상태일때 처리는
Idle상태일때 처리는
procedure TApplication.Idle(const Msg: TMsg); 함수에서 처리하고 있습니다.
그런데 이 Idle함수는 protected 로 되어있네요
시스템큐 메세지와 Idle상태일때 모두다 처리해주려면?
함수내 while문에서
시스템 메세지큐 메세지 처리와 Idle상태의 vcl동작까지 함께 하려면 어떻게 해야할까요?
while(1){
Application->ProcessMessage();
Application->Idle(); //이 함수는 procted 임
//... 다른 작업
}
위와깉이 해줄수 있으면 좋겠지만.
앞에 얘기했듯이 Idle함수는 protected입니다.
테스트 해보진 않았지만
다음과 같이 하면 Idle상태에 vcl동작도 함께 처리할것입니다.
while(1){
Application->ProcessMessage();
Application->HandleMessage();
//.... 다른 작업..
}
다음은 vcl의 TApplication클래스의
ProcessMessages 함수와 HandleMessage함수의 코드입니다.
procedure TApplication.ProcessMessages;
var
Msg: TMsg;
begin
while ProcessMessage(Msg) do {loop};
end;
procedure TApplication.HandleMessage;
var
Msg: TMsg;
begin
if not ProcessMessage(Msg) then Idle(Msg);
end;
ProcessMessages와 HandleMessage 의 중요한 차이점
위 코드를 잘 보시면 아시겠지만
ProcessMessages와 HandleMessage 의 중요한 차이점이 있습니다.
차이점 1. ProcessMessages 는 메세지 큐에 메세지가 빌때까지 모두 더 처리해줍니다.
반면 HandleMessage 는 하나의 메세지만 처리합니ㅏㄷ.
차이점2. 앞에서 얘기했듯이 HandleMessage는 메세지큐에 메세지가 없으면
Application->Idle을 호출해줘서 Idle상태일때 동작을 처리해주는데 ProcessMessage는 그런게 없습니다.
위 차이점을 잘 알고 사용하면 될것 같습니다.
그럼..
happymin 님이 쓰신 글 :
: 안녕하세요...
:
: while(1){
: Application->ProcessMessage();
:
: }
: 자동 숨김할 폼에서 MESSAGE_MAP에서 CM_MOUSELEAVE처리를 하고 있습니다.
:
: while문이 돌고 있을때는 CMMOUSELEAVE가 들어오지를 않습니다.
: 방법이 없을까요?