Delphi Dll 메시지 처리 Dll(3)

5108 단어 dllDelphi
Delphi의 DLL 메시지 처리
일의 도화선은 GIF 그림의 표시이다.응용 프로그램에서 삼방의 GIFImage를 이용한다.pas는 GIF 그림을 잘 보여 줍니다.이번에는 DLL에 GIF 그림을 표시합니다.여느 때처럼 Timage를 끌어다 창에 놓고 동적 GIF 그림을 엽니다.컴파일, 실행   
이상하다: GIF 그림은 정적입니다.델파이가 또 버그를 내는 줄 알았어요.그래서 프로그램 메인 창에 그림을 올려놓고 움직였어요.이번에는 정말 대단하다!
관련 자료를 찾았습니다. 없습니다.
일은 아직 스스로 해결해야 할 것 같다. 그래서 GIFImage에 전념하기 시작했다.pas, 먼저 본 것은 당연히 다시 그린 부분의 코드입니다(허허, 이것은 나의 일관된 스타일입니다. 문제가 생기면 먼저 어디를 보고 누구의 코드든지).한차례의 수색을 거치다.
목표를 노선에 포착하다.GIFImage.pas의 재그림은 하나의 라인을 호출하여 파일에서 해당하는 이미지 데이터를 온라인으로 읽고 목표 위치로 그리는 것입니다.
스레드 내에서 다시 그리는 것은 스레드를 호출하는 Synchronize 프로세스입니다.이전에 이 과정은 여러 라인이 같은 데이터나 대상에 동시에 접근하는 것을 피하기 위해서라는 것을 알았다.지금 그것의 집행 방법에 대해 한 번 이해해야만 한다.
샅샅이 뒤져서 해결 방법을 찾았다.DLL 창에 TTimer 컨트롤을 놓습니다.Interval은 최대한 작아요.OnTimer에서 코드 한 줄만 추가: CheckSynchronize,
운행하다.OK. 그림이 움직이기 시작했다.(이런 방법이 가지고 있는 문제는 더 이상 말할 필요가 없겠지.)
 
그러나 다음 문제는 화가 났다. DLL의 창에 Tspeed Button 컨트롤을 놓고 Flat 속성을 True로 설정했다.운행하다.마우스가 TSpeed Button에서 옮겨졌을 때, TSpeed Button은 아무리 해도 복원할 수 없습니다.그것의 다시 그리기 등의 기능을 사용해 보아라.다 소용없어.며칠 동안 줄곧 이 문제를 생각하고 있다.
나중에 응용 프로그램의 정보를 처리할 때 갑자기 생각났다. DLL은 자신의 Application이 있지만 자신의 메시지 순환이 없고 라인의 Synchronize가 실행할 수 없고 Tspeed Button이 복원할 수 없는 것은 일부 정보가 상응하는 처리를 받지 못했기 때문이다.
즉, DLL에 메시지 순환을 더하면 위의 문제들은 모두 해결될 것이다.
처음에 메인 프로그램에서 DLL에 메시지를 보내고 싶었어요.그러나 메시지 캡처의 결과는 많은 DLL에서 발생한 메시지가 메인 프로그램에 전송되지 않았다는 것이다.보아하니 이 방법은 통하지 않을 것 같다.다른 방법을 찾을 수밖에 없다.
다음 몇 줄의 익숙한 코드를 보고 생각하세요.  Application.Initialize;   Application.CreateForm(TForm1, Form1);   Application.Run; DLL에도 이 코드를 붙여주면 안 돼요?
DLL을 만듭니다. DLL에 창을 포함하는 DLLForm을 만듭니다.DLL에서 함수를 내보냅니다.위의 코드를 더하다.procedure InitDLL,stdcall; begin   Application.Initialize;   Application.CreateForm(TDLLForm, DLLForm);   Application.Run; end; 주 프로그램 창에 생성된 이벤트 코드는 다음과 같습니다:procedure TForm 1.FormCreate(Sender: TObject); begin   InitDLL; end; 운행, 결과가 잘못되었습니다.메인 창을 먼저 열었습니다.(답답하다. 그리고 InitDLL. 바로 돌아오는 것도 아니고 DLL의 메인 창이 닫힌 후에야 돌아오는 것이다. 사실은 진작에 생각했어야 했다. Oncreate 코드를 TTimer 컨트롤에 넣었다. Interval은 1. Ontimer의 코드는 다음과 같다. procedure TForm1. Timer1 Timer(Sender: TObject).begin   TTimer(Sender).Enabled := False;   InitDLL; end; 이제 됐다.DLL에 있는 창이 처음부터 보일 수는 없잖아요.얻다InitDLL 수정procedure InitDLL,stdcall; begin   Application.Initialize;   Application.ShowMainForm := False;   Application.CreateForm(TDLLForm, DLLForm);   Application.Run; end; 메인 창이 보이지 않습니다. 효과를 보십시오:) DLL에 Form (DLLChildForm) 을 추가하고 창에Tspeed Button 컨트롤을 놓으십시오.DLL에 다음 함수를 내보냅니다. procedure Create ChildForm;stdcall; begin   with TDLLChildForm.Create(Application) do   begin     Show;   end; end; 메인 창에 단추를 추가합니다.이벤트 코드를 클릭하면 아래와 같습니다.procedure TForm1.Button1Click(Sender: TObject); begin   CreateChildForm; end; 운행하다.결과 이상: Tspeed Button은 마우스를 옮긴 후에 복원할 수 있습니다.허허..정말 시원하다!
그런데 문제가 또 생겼어요.프로그램이 종료되었을 때 오류가 발생했습니다.생각해 봐, 오.DLL의 창 자원이 아직 방출되지 않았습니다.예. 다음 코드를 사용하여 DLL에서 프로세스를 내보냅니다.
procedure DestoryDLL; stdcall;
var
  i: Integer;
begin
  for i := Application.ComponentCount - 1 downto 0 do
  begin
    if Application.Components[i].ClassNameIs('TDLLChildForm') then
    begin
      TDLLChildForm(Application.Components[i]).Release;
    end;
  end;

  if DLLForm = nil then
  begin
    Exit;
  end;

  DLLForm.Release;
  DLLForm := nil;
end;


 
메인 프로그램의 메인 창의 OncloseQuery에 다음과 같은 코드를 추가합니다:procedure TForm 1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin   DestoryDLL; end; 운행하다.그래, 비록 DLL의 창이 모두 닫혔지만, 메인 프로그램은 여전히 물러설 수 없어.방법을 바꾸어 DLLForm.Release; 여기를 Application으로 변경합니다.Terminate; 해봐.그래도 안 돼.어떻게 된 일입니까?반복적으로 디버깅을 하여Terminate가 되었지만 Run은 여전히 순환하고 있음을 발견하였다.끝난 게 아니야.런 코드를 다시 연구하다.허허.있다.Application을.Terminate;PostMessage(Application.Handle, WM QUIT, 0, 0)로 변경;운행, 여전히 안 돼.런은 순환이고 퇴출이야.그럼 뭐가 문제야?설마 창문이 풀리지 않은 건 아니겠지.좋습니다. PostMessage 앞에 DLLForm을 추가하십시오.Release;DestoryDLL 프로세스의 코드는 다음과 같습니다.
procedure DestoryDLL; stdcall;
var
  i: Integer;
begin
  for i := Application.ComponentCount - 1 downto 0 do
  begin
    if Application.Components[i].ClassNameIs('TDLLChildForm') then
    begin
      TDLLChildForm(Application.Components[i]).Release;
    end;
  end;

  if DLLForm = nil then
  begin
    Exit;
  end;

  DLLForm.Release;
//  Application.Terminate;
  PostMessage(Application.Handle, WM_QUIT, 0, 0);
  DLLForm := nil;
end;


 
운행하다.OK. 완벽하게 해결하다.여기에 스레드를 더해 봅시다. (이 때 인트DLL 과정은 다음과 같이 바꿔야만 모든 정보를 진정으로 처리할 수 있습니다.)시원하다.상상과 같다.
procedure InitDLL(AHandle: Thandle); stdcall;
begin
  Application.Initialize;
  Application.ShowMainForm := False;
  Application.CreateForm(TDLLForm, DLLForm);

  //        
  DLLForm.Tag := Application.Handle;
  // DLL       (       ,               )
  //                          
  Application.Handle := AHandle;
  Application.Run;

  Application.Handle := DLLForm.Tag;
end;


좋은 웹페이지 즐겨찾기