본문 바로가기
프로그래밍/delphi

delphi DLL폼을 exe프로그램의 패널 안에 넣어볼까요? ( How to dll from embedded in exe panel )

by 메르세데쓰 2015. 4. 10.
반응형

안녕하세요 델파이 개발자 메르세데스입니다.


지난 시간에 폼을 패널 안에 넣은 방법을 해봤는데요.. 좀 더 나아가  delphi의 dll 프로그램안에 있는 특정 폼을 메인 프로그램 내 panel에 넣을 수 있는 방법이 없지 않을 것 같아 고민해봤습니다.


보통은 dll프로그램은... ShowModal로 띄워서 사용했었거든요  이곳 저곳에 붙일 수 있으니 나름대로 편하다고 생각했었는데  문제는 이렇게 띄워진 창을 닫지 않으면 아무것도 할 수 없기 때문에  불편합니다.



나름대로의 시행착오가 있었지만 됩니다. 하지만 이것이 100점짜리 정답은 아닌 것 같습니다. 차차 해결하는 것으로 하고..  좋은 의견이 있으시면 공유해주셨으면 좋겠습니다. ^^;



방법은 생각보다 간단합니다.  지난 시간에  패널 안에 폼을 넣는 방법을 조금 응용하면 되거든요..



1. dll쪽 구문입니다.


   function type으로 만들고.. 반환값을 TForm type으로 하면 되겠습니다.

   사실 저도 고정관념이 좀 있어서.. Function 이라고 하면.. true/false 혹은.. text같은 문자열만 사용했었는데 폼 자체를 반환 할 수 있습니다.



   Function  ShowDLLRTN: TForm;StdCall;


   ....


   Function  ShowDLLRTN: TForm;StdCall;

   begin


    AAAS1:= TAAAS1.Create(AAAS1);


    Result := AAAS1;


    end;

   

    




2.EXE파일쪽 구문입니다.


  호출 방식이 Function type인거 말고는 정말 별거 없죠.. 눈치채셨겠지만..    TForm Type 으로 받아서.. 이걸 패널에 넣는 것 을 구현하면 끝입니다.   사실 도전 하는 것이 쉽지 않지, 일단 해보면 별것 아닌 것이 많죠..

정말 별것 아니지만.. 구현하는 것과 이로 인해 생기는 잡다한 문제들 해결하는데 2일 정도 시간이 걸린 것 같습니다 ㅜㅜ

  

 TShowDLLRTN  = function: TForm; StdCall;

 .....


[Button구현부분]  

procedure AAAA.RzBitBtn18Click(Sender: TObject);

var LibHandle: THandle;

    ShowDLLRTNTShowDLLRTN ;

    aPN : TForm;

begin


    aPN := TForm.Create(nil);

    LibHandle := LoadLibrary('호출DLL이름');


    try

       if LibHandle = HINSTANCE_ERROR then

          raise EDLLLoadError.Create('Unable to Load DLL');

       @ShowDLLRTN:= GetProcAddress(LibHandle,'ShowDLLRTN');


       if not (@ShowDLLRTN= nil ) then

       begin

          aPN:= ShowDLLRTN;  //DLL의 결과를 aPN이라는 변수에 받는다

          aPN.ParentWindow := RzPN10.Handle;

          //aPN.Parent := RzPN10;


          aPN.Align := alClient;

          aPN.BorderStyle := bsNone;

          aPN.WindowState := wsMaximized;

          aPN.Visible := true;

          RzPN10.Visible := true;

        end

       else

          ShowMessage(IntToStr(GetLastError));

    finally


    end;



패널안에 DLL프로그램내 만들어 놨었던 폼이 들어오게 되니 참 신기하네요.. 무엇보다.. 재사용이 가능하기 때문에 훨씬 효율성이 높은 코딩이 가능해지겠죠..   여기 저기 다 붙일 수 있으니까요! 


하지만.. 큰 문제는.. 메모리 해제 방법인데요.    AAA.Parent = [패널]  이런 코딩이 안 먹힌다는 것입니다.


물론 오류는 안나지만.. 화면내에 표시가 안되는 문제가 있어 한참 찾아보니.. AAA.ParentWindow = [패널].Handle


이런 방법으로 하니 표시가 됩니다  하지만 이렇게 처리 하다 보니   dll로 부터 결과를 넘겨 받은 AAA라는 TForm type의 변수를.. 사용을 다 하고 나서 제대로 해제 처리하지 않으면  지겹도록 아래의 Code:1400 에러를 보게 될 것입니다.





저는 어쩔 수 없이.. 전역변수를 이용하여  


글로벌hWnd := aPN.Handle;


    if  글로벌hWnd <> 0 then

    begin

        SendMessage(글로벌hWnd , WM_CLOSE, 0, 0);  //특정핸들프로그램 종료

        글로벌hWnd:= 0;

    end;


FormCloseQuery와.. 버튼 시작 부분에 넣어 놓는 것으로 해결하긴 하였는데 소스가 길어지고 말았네요ㅜㅜ 


하지만.. 재사용성을 높일 수 있다는 가능성과..  dll-ModalForm의 불편함을 해결할 수 있는 방법으로.. 좋은 결과를 얻은 것 같습니다.



근데 구현해 놓고 보니 2가지 불편함이 생겼습니다.  패널 안으로 들어온 dll폼을 exe프로그램에서 제어하는 방법과 그 반대에서 제어하는 경우죠  예전엔 ModalForm이기 때문에 이런 불편함에 대해 전혀 고민을 안 해도 됐었거든요 그 창이 닫히기 전까진 어차피 아무것도 안되니까요...



다음 시간에는 이런 고민을 해결하는 방법에 대해 연구해보고 포스팅 해보도록 하겠습니다. 감사합니다.






반응형

댓글