델파이(Delphi)는 볼랜드가 제공하는 새로운 WINDOWS 프로그래밍 개발 도구로, 유연하고 재사용 가능한 객체지향 파스칼(Object-Oriented Pascal) 언어를 사용하고 강력한 데이터베이스 엔진(BDE)을 탑재하고 있기 때문에 빠른 코드를 제공하는 컴파일러도 많습니다. 이는 대다수의 프로그래머가 선호하는 언어입니다(예: VB, PowerBuilder, Powerpoint 등).
다른 프로그래밍 언어(예: VB4.0)에 비해 DELPHI의 장점 중 하나는 DELPHI에서 메시지를 사용자 정의하고 직접 처리할 수 있다는 것입니다. 또는 메시지를 가로채고 필터링하려는 사용자에게 필수적입니다. 일반적으로 구성 요소를 작성하려면 해당 메시지를 처리해야 하기 때문입니다. 다음은 Delphi의 메시지 처리 메커니즘에 대한 소개입니다.
1. DELPHI VCL의 메시지 전달
Delphi의 각 VCL(Visual Component Library) 구성 요소(예: Tbutton, Tedit 등)에는 고유한 메시지 처리 메커니즘이 있습니다. 기본 요점은 구성 요소 클래스가 특정 메시지를 수신하여 적절한 처리 방법으로 보내는 것입니다. 특정 처리 방법이 없으면 기본 메시지 처리 핸들이 호출됩니다. 그 중 mainwndPROc는 Twincontrol 클래스에 정의된 정적 메소드이므로 오버로드(Override)할 수 없습니다. 메시지를 직접 처리하지 않고 wndproc 메서드에 처리를 맡기고 wndproc 메서드에 대한 예외 처리 모듈을 제공합니다. Mainwndproc 메서드는 다음과 같이 선언됩니다.
절차 MainWndProc(var 메시지: TMessage);
Wndproc는 메시지를 배포하기 위해 디스패치 메서드를 호출하는 Tcontrol 클래스에 정의된 가상 메서드입니다.
절차 WndProc(var 메시지: TMessage);
디스패치 메서드는 Tobject 루트 클래스에 정의되며 다음과 같이 선언됩니다.
Procedure Tobject.dispatch(var Message); 디스패치에 전달된 메시지 매개변수는 레코드 유형이어야 하며, 이 레코드의 첫 번째 진입점은 배포할 메시지의 메시지를 포함하는 기본 유형 필드(필드)여야 합니다. . 예를 들어:
유형
Tmessage=기록
메시지:추기경;
wparam:단어;
lparam:longint;
결과:longint;
끝;
Dispatch 메서드는 메시지 번호를 기준으로 이 메시지를 처리하는 구성 요소의 마지막 세대 클래스의 핸들 메서드를 호출합니다. 이 구성 요소와 해당 조상 클래스에 이 메시지에 해당하는 핸들러가 없으면 Dispatch 메서드는 Defaulthandler를 호출합니다. Defaulthandler 메소드는 Tobject에 정의된 가상 메소드는 다음과 같이 선언됩니다.
절차 Defaulthandler(var Message);virtual;
Tobject 클래스의 Defaulthandler 메서드는 메시지 처리 없이 간단한 반환만 구현합니다. 이 가상 메서드를 오버로드하여 하위 클래스에서 메시지의 기본 처리를 구현할 수 있습니다. VCL의 경우 해당 Defaulthandler 메서드가 창을 시작합니다. 메시지를 처리하는 API 함수 Defwindowproc입니다.
2. DELPHI의 메시지 처리 핸들
DELPHI에서 사용자는 메시지 및 메시지 처리 핸들을 사용자 정의할 수 있습니다. 메시지 처리 핸들의 정의에는 다음과 같은 원칙이 있습니다.
메시지 처리 핸들 메서드는 프로시저여야 하며 하나의 Tmessage 유형 변수 매개 변수만 전달할 수 있습니다.
메서드 선언 뒤에는 메시지 명령이 오고 그 뒤에는 0에서 32767 사이의 메시지 레이블(정수 상수)이 와야 합니다.
메시지 핸들러 메소드는 조상의 메시지 핸들러를 오버라이드한다는 것을 명시적으로 나타내기 위해 override 명령을 사용할 필요가 없습니다. 또한 일반적으로 컴포넌트의 보호 영역 또는 비공개 영역에 선언됩니다.
메시지 처리 핸들에서 사용자는 일반적으로 메시지를 먼저 처리하고 마지막으로 상속된 명령을 사용하여 조상 클래스에서 이 메시지에 해당하는 처리 핸들을 호출합니다(어떤 경우에는 반대일 수 있음). 조상 클래스의 이 메시지는 이름과 매개변수 유형이 불분명하며, 상속된 명령을 호출하면 이 문제를 피할 수 있습니다. 마찬가지로 조상 클래스에 이 메시지에 해당하는 핸들러가 없으면 상속은 자동으로 Defaulthandler 메서드를 호출합니다. (물론 이 메시지를 차단하고 싶다면, 상속된 명령을 사용할 필요가 없습니다.)
메시지 처리기 메서드는 다음과 같이 선언됩니다.
절차 Mymsgmethod(var message:Tmessage); 메시지 Msgtype;
마찬가지로 사용자는 자신의 메시지를 정의할 수도 있습니다. 사용자 정의 메시지는 WM_USER로 시작해야 합니다.
사용자 정의 메시지 및 메시지 처리 핸들의 예는 다음과 같습니다.
const my_paint=Wm_user+1;
유형
Tmypaint=기록
msgid:추기경;
msize:단어;
mcolor:longint;
msgresult:longint;
끝;
유형
Tmycontrol=클래스(TCustomControl)
보호됨
프로시저 변경(var message:Tmypaint); message my_paint;
.....
끝;
...
절차 Tmycontrol.change(var message:Tmypaint);
시작하다
size:=message.msize; {Tmybutton 크기 속성 설정}
color:=message.mcolor; {Tmybutton 색상 속성 설정}
{다른 일을 하세요}
상속됨; {Tcustomcontrol에 넘겨짐}
끝;
3. 메시지 필터링
메시지 필터링을 메시지 트랩이라고도 합니다. 특정 상황에서는 사용자가 처리를 위해 특정 메시지를 차단하거나 특정 메시지를 가로채야 할 수도 있습니다. 위의 소개에서 메시지를 필터링하는 방법에는 일반적으로 세 가지가 있음을 알 수 있습니다. (1) 구성 요소에 의해 상속된 가상 메서드 wndproc를 오버로드합니다(3). 메시지가 처리되는 구성 요소에 의해 상속된 가상 메서드 Defhandler를 오버로드합니다. 가장 일반적으로 사용되는 방법은 이전 섹션에서 소개한 방법(2)입니다. 방법(1)은 방법(3)과 유사합니다. 여기서는 방법(1)만 간략하게 소개합니다.
가상 메서드 wndproc를 오버로드하는 일반적인 프로세스는 다음과 같습니다.
절차 Tmyobject.wndproc(var message:Tmessage);
시작하다
{... 이 메시지를 처리해야 하는지 결정합니다..}
상속된 wndproc(메시지);
{처리되지 않은 메시지는 상위 wndproc 메소드에 의해 처리됩니다.}
끝;
이를 통해 wndproc 메소드에서 메시지를 처리할 때의 장점은 각 메시지에 대한 처리 핸들을 지정하지 않고도 전체 메시지 범위를 필터링할 수 있다는 점을 알 수 있습니다. 실제로 Tcontrol 구성요소에서 필터링하고 필터링하는 데 사용됩니다. 모든 마우스 메시지를 처리합니다(다음 코드에 표시된 대로 WM_mousefirst에서 WM_mouselast까지). 특정 메시지가 처리기로 전송되는 것을 방지하는 데에도 사용할 수 있습니다.
절차 TControl.WndProc(var 메시지: TMessage);
시작하다
if (Message.Msg>=WM_MOUSEFIRST) 및
(메시지.Msg <= WM_MOUSELAST)
그 다음에
드래그하는 경우 {드래그 이벤트 처리}
DragMouseMsg(TWMMouse(메시지))
또 다른
... {다른 마우스 메시지 처리}
끝;
파견(메시지);
{그렇지 않으면 정상적으로 메시지를 보냅니다.}
끝;
다음 예는 간단한 사용자 정의 구성요소 예입니다.
Tmyedit 클래스는 Tedit 클래스에서 파생된 새로운 클래스입니다. 그 특징은 작업 중에 포커스를 얻을 수 없고 키보드로 입력할 수 없다는 것입니다(Tlabel 구성 요소와 다소 유사). wndproc 메서드 및 수행 위의 요구 사항을 달성하기 위한 소스 프로그램은 다음과 같습니다.
단위 myedit;
인터페이스
용도
Windows, 메시지, SysUtils, 클래스, 그래픽,
컨트롤, 양식, 대화 상자,
StdCtrls;
유형
Tmyedit = 클래스(TEdit)
사적인
{비공개 선언}
보호됨
{ 보호된 선언 }
{ 기타 필드 및 방법}
절차 wndproc(var message:Tmessage);재정의;
공공의
{공개 선언}
출판됨
{ 게시된 선언 }
끝;
절차 등록;
구현
절차 등록;
시작하다
RegisterComponents('샘플', [Tmyedit]);
끝;
절차 Tmyedit.wndproc(var message:tmessage);
시작하다
message.msg=wm_mousemove인 경우
시작하다
커서:=까마귀;
{기본 crBeam 커서 대신 커서를 크롤링하도록 설정}
출구;
끝;
message.msg=wm_SetFocus이면 종료합니다.
{WM_setfocus 메시지를 보호하고 Tmyedit 컨트롤이 입력 포커스를 얻지 못하도록 방지}
상속된 wndproc(메시지);
{다른 메시지는 처리를 위해 상위 wndproc에 전달됩니다.}
끝;
끝.
Tmyedit를 Component Palette에 추가하여 성능을 테스트할 수 있습니다.
위의 소개에서 볼 수 있듯이 Delphi VCL의 메시지 처리 메커니즘을 이해하고 다양한 메시지를 처리하는 방법과 타이밍을 숙지하고(필요한 경우 winsight32, spy 등 다양한 도구 사용) 특성을 결합해야 합니다. OOP 언어의 경우 고품질 컴포넌트를 컴파일할 수 있습니다. 물론 이를 위해서는 독자들이 실무 경험을 끊임없이 탐색하고 축적해야 합니다.