프로그램을 작성할 때는 항상 양식 (tform)과 스레드 (tthread) 메시지 사이의 의사 소통에 문제가 발생합니다. 성가신 것은 양식이 스레드에 메시지를 보낼 수 없다는 것입니다 (TTHREAD) (스레드에는 창 핸들이 없음). 며칠 동안 열심히 일한 후, 나는 두 가지 해결책을 제시하여 당신과 토론하기 위해 그들을 데려 갔다.
첫 번째. VC ++의 MFC 클래스 라이브러리는 MFC에서 메시지 처리를 캡슐화했습니다 매핑 테이블 (메시지 처리는 본질적으로 메소드 또는 프로세스로의 호출)과 메시지 배포 메커니즘과 메시지의 수신 및 전송을 실현하는 메시지 배포 메커니즘 <vc ++ 기술 내부자 참조> 자세한 내용은. 따라서 스레드에 대한 메시지 매핑 테이블을 설정하고 해당 메시지 배포 메커니즘을 설정하면됩니다. 이를 통해 양식별로 스레드에 전송 된 메시지를 처리 할 수 있습니다. 다음 코드는 메시지 매핑 테이블 및 메시지 배포를 구현하는 클래스입니다 (<../ 메시지 처리 설계 (스레드) 1/MessageHandle.pas> 참조)
단위 메시지 처리;
인터페이스
메시지, 클래스, 시스템, 대화 상자를 사용합니다.
const PMSG_BASE = $BE00; //自定义消息基址;
pmsg_num = 200; // 메시지 테이블 크기;
{** 사용자 정의 메시지 처리 클래스
*; function = 사용자 정의 메시지 테이블 생성 및 스레드간에 프로세스
* 및 기본 양식 (매크로)이있는 사용자 정의 메시지
*}
// 메시지 처리 핸들
tmessageHandle = 객체의 절차 (var 메시지 : tmessage);
tpdispatcher = class (tobject)
사적인
// 메시지 대응 테이블 (메시지 id는 배열 첨자입니다);
MessageHandles : TmessageHandle의 배열;
// 메시지 ID에서 배열 ID를 가져옵니다
함수 getIndexFrommsGid (const AmessageId : Cardinal) : 정수;
공공의
constructor Create;
소멸자 파괴;
// 메시지를 보냅니다
절차 sendmessage (var 메시지 : tmessage);
// 해당 테이블에 사용자 정의 메시지를 추가합니다.
프로 시저 addhandle (const AmessageId : 추기경; AmessageHandle : tmessageHandle);
끝;
//
구현
{tpdispatcher}
생성자 tpdispatcher.create;
var i : 정수;
시작하다
setLength (MessageHandles, pmsg_num); // 200 메시지의 메시지 서신 테이블
// 메시지 큐를 초기화합니다.
i : = 0 to pred (pmsg_num)
MessageHandles [i] : = nil;
끝;
소멸자 tpdispatcher.destroy;
시작하다
{릴리스 메시지 서신 테이블}
FreeAndnil (MessageHandles);
끝;
절차 tpdispatcher.addhandle (const AmessageId : 추기경;
AmessageHandle : tmessageHandle);
var tid : 정수;
시작하다
TID : = getIndexFrommsGid (AmessageId);
assert ((tid> 0) 또는 (tid <pred (pmsg_num)));
assert (할당 된 (AmessageHandle));
MessageHandles [tid] : = AmessageHandle;
끝;
함수 TPDISPATCHER.GETINDEXFROMMSGID (const AmessageId : 추기경) : 정수;
시작하다
결과 : = AmessageId -PMSG_BASE;
끝;
절차 tpdispatcher.sendMessage (var 메시지 : tmessage);
var tid : 정수;
tmsghandle : tmessagehandle;
시작하다
tid : = getIndexFrommsGid (message.msg);
assert ((tid> 0) 또는 (tid <pred (pmsg_num)));
tmsghandle : = messageHandles [tid];
할당 된 경우 (tmsghandle)
tmsghandle (메시지);
끝;
이제 사용자 정의 메시지 만 등록한 다음 메시지 배포 클래스 (tpdispatcher)를 사용하여 스레드 메시지를 처리하면됩니다. 코드는 다음과 같습니다. <see ../ 메시지 처리 설계 (스레드) 1/test/init1.pas> 세부 사항은 다음과 같습니다.
Unit1
Const
{사용자 정의 장기 스레드 메시지}
my_message2 = pmsg_base + 02;
유형
tform1 = 클래스 (tform)
addmsglist : tbutton;
Sendthehead : Tbutton;
sendform : tbutton;
센트 : Tbutton;
절차 sendTheadClick (sender : tobject);
프로 시저 Formcreate (sender : tobject);
절차 formdestroy (sender : tobject);
사적인
FDISPATCHER : TPDISPATCHER;
Fhandle : Tphandler;
FTHREAD : TPTHREAD;
공공의
{공개 선언}
끝;
var
form1 : tform1;
구현
{$ r *.dfm}
procedure TForm1.SendTheadClick(Sender: TObject);
var Amessage : tmessage;
Amessage.msg : = my_message2;
Amessage.wparam : = 1;
fdispatcher.sendmessage (Amessage);
끝;
끝;
절차 tform1. formcreate (sender : tobject);
시작하다
{메시지 맵 작성}}
fdispatcher : = tpdispatcher.create;
fhandle : = tphandler.create;
{스레드 만들기}
fthread : = tpthread.create (false);
{매핑 테이블에 메시지 추가}
fdispatcher.addhandle (my_message2, fthread.domessage);
끝;
절차 tform1.formdestroy (sender : tobject);
var i : 정수;
시작하다
FreeAndnil (Fdispatcher);
FreeAndnil (fhandle);
i : = 0 ~ 3 do
FreeAndnil (fthread [i]);
끝;
두번째. 창은 창 핸들이 있으므로 메시지를 처리 할 수 있습니다. 스레드가 메시지를 처리하려면 해당 창 클래스의 스레드에 창 핸들을 추가 할 수 있습니다. (소스 코드는 <../ 메시지 처리 설계 (스레드) 2 / pthread.pas>에 있습니다)
단위 pthread;
인터페이스
클래스, sysutils, Windows, 메시지, 대화 상자를 사용합니다.
const my_message1 = $ bd00 + 01;
유형
{** 메시지 처리 스레드 클래스
*; function = 스레드 처리 기능 추가,
*}
tpmsgthread = class (tthread)
사적인
// 창 핸들
fwndhandle : hwnd;
// 창 데이터 정보
fwndclass : wndclass;
// 윈도우 콜백 함수에 대한 포인터
fobjectinstance : 포인터;
// 창 데이터를 초기화합니다
절차 initwnd;
// 숨겨진 창을 만듭니다
절차 생성;
// 숨겨진 창을 등록합니다
절차 registwnd;
절차 파괴;
// 윈도우 콜백 함수
절차 pwndproc (var 메시지 : tmessage);
보호
절차 실행; 우정;
절차는 doterminate;
공공의
constructor Create(CreateSuspended: Boolean); virtual;
속성 wndhandle : hwnd 읽기 fwndhandle 쓰기 fwndhandle;
끝;
구현
const wnd_name = 'py20';
{tpmsgthread}
생성자 tpmsgthread.create (CreateSuspended : boolean);
시작하다
상속 된 생성 (CreateSuspended);
fwndhandle : = 정수 (nil);
initwnd;
registwnd;
생물;
끝;
절차 tpmsgthread.createwnd;
시작하다
if (wndhandle = integer (nil))
wndhandle : = createWindow (fwndclass.lpszclassName, fwndclass.lpszclassname,
ws_popup 또는 ws_caption 또는 ws_clipsiblings 또는 ws_sysmenu
또는 ws_minimizebox,
getsystemmetrics (SM_CXSCREEN) DIV 2,
getsystemmetrics (sm_cyscreen) div 2,
0, 0, 0, 0, fwndclass.hinstance, nil);
// 윈도우 콜백 함수를 교체합니다
setwindowlong (wndhandle, gwl_wndproc, longint (fobjectinstance));
끝;
절차 tpmsgthread.destroywnd;
시작하다
UnregisterClass (fwndclass.lpszclassname, fwndclass.hinstance);
DestroyWindow (wndhandle);
끝;
절차 tpmsgthread.doterminate;
시작하다
상속;
파괴;
끝;
절차 tpmsgthread.execute;
시작하다
끝;
절차 tpmsgthread.initwnd;
시작하다
fwndclass.lpszclassname : = pchar (wnd_name);
fwndclass.hinstance : = 핸들;
fwndclass.lpfnwndproc : = @defwindowproc;
끝;
절차 tpmsgthread.pwndproc (var 메시지 : tmessage);
시작하다
끝;
절차 tpmsgthread.registwnd;
시작하다
fobjectinstance : = class.makeobjectinstance (pwndproc);
if (fwndclass.hinstance <> integer (nil))
RegisterClass (fwndclass);
끝;