안녕하세요.. 너무나 답답한 마음에 이렇게 문의드립니다. 귀찮더라고 한번쯤 봐주시면 감사하겠습니다.
제가 현제 구현하고 있는 프로그램을 간략히 설명하면 메신저 서비스를 구현하고 있습니다. 그중 대부분은 ATL COM으로 구현을 하고 껍데기를 델파이로 구현한것입니다.
COM 오브젝트에서 이벤트처리하기 위해서 EventSinkImp 를 이용했습니다(아시겠지만 EventSinkImp 는 COM 오브젝트의 이벤트를 델파이에서 사용할수 있도록 .pas로 바꿔주는 기능이 있네요..)
그후 COM 오브젝트의 함수 SendMsg()를 호출하면 COM 오브젝트에서 RecvMsg()이벤트함수를 호출하게 합니다. 그런데 문제는 RecvMsg()에서 발생하네요...RecvMsg()함수안에서 Message_form을 동적생성 시키는데 생성되지않고 프로그램이 죽네여.... COM을 통하지 않고 동적으로 생성시킬때는 잘 됩니다. 그런데 COM이벤트를 통하여서는 생성이 안되네요............. 글로 설명할려고 너무 복잡하네요...
즉 COM 오브젝트함수인 SendMsg()를 호출하면 다음의 함수 ZmsMsgEvent1RecvMsg가 실행이 됩니다. 그런데 이 함수에서
frmMsg := TfrmMsg_0001.Create(self);
부분에서 에러가 생기네요
폼을 동적으로 생성시킬때 사용하는 방법이 Create밖에 없나요? 그리고 ActiveX에서 이벤트로 처리할때 폼을 동적으로 생성이 안되는건지...좀 알려주시면 감사하겠습니다.
관련 게시판을 찾아봤지만 마땅한 자료가 없네요....
procedure TfrmSIGN_0001.ZmsMsgEvent1RecvMsg(Sender: TObject; const p_from,
p_msg: WideString);
var
frmMsg : TfrmMsg_0001;
I:integer;
begin
for I :=0 to Screen.FormCount -1 do
if (Screen.Forms[I] is TfrmMsg_0001) and (Screen.Forms[I].Caption = String(p_from) + ' - 인스턴스 메시지') then
begin
TfrmMsg_0001(Screen.Forms[I]).MemoDisplay.Lines.Add(String(p_from) + '(받은거) : ' + String(p_msg));
Screen.Forms[I].SetFocus;
exit;
end;
Application.MessageBox(‘이부부분까정은 잘 됩니다.’,’test’,MB_OK);
frmMsg := TfrmMsg_0001.Create(self); // <-- 이부분이 에러가 남
// frmMsg.caption := String(p_from) + ' - 인스턴스 메시지';
// frmMsg.edtSenderID.Text := String(p_from);
// frmMsg.edtSenderNick.Text := String(p_from);
// frmMsg.edtSenderEmail.Text := String(p_from);
// frmMsg.MemoDisplay.Lines.Add(String(p_from) + '(받은거) : ' + String(p_msg));
frmMsg.Show;
end;
위의 소스에서
Application.MessageBox(‘이부부분까정은 잘 됩니다.’,’test’,MB_OK);
부분은 메시지박스가 잘뜹니다. 그이후로 죽네요..
다시한번 정리하면 ..
COM오브젝트를 거치지 않고 일단 폼을 동적으로 생성하는건 당연히 잘 되는데요.. COM오브젝트중 멀티쓰레드에서 발생한 이벤트에서만 문제가 생기네요..
즉 좀더 구체적으로 설명하면...
제가 COM오브젝트 함수 SendMsg()를 호출하면 이함수가 막 실행을 하면서 메시지 받는 아이디의 컴퓨터로 메세지를 보내고 그 메세지를 받는 함수가 COM오브젝트의 이벤트함수인 RecvMsg()입니다. 그런데 RecvMsg()를 호출하는 컴 내부는 멀티쓰레드로 되어있습니다. 즉 멀티쓰레드에서 RecvMsg()를 호출합니다. RecvMsg()함수는 분명 실행이 됩니다. 중간에 messagebox를 넣어서 확인했습니다. 그리고 윗부분의 IF문도 실행이 됩니다. 문제는 frmMsg폼을 동적으로 생성하는곳에서만 에러가 나는것 같습니다.
그런데 이와똑같은 코드를 다른 COM오브젝트의 이벤트에서는 잘 돌아갑니다. 즉 제가 사용하는 COM오브젝트에는 여러개의 이벤트함수가 있습니다. 그중 멀티쓰레드에서 호출하지 않는 이벤트는 frmMsg폼을 동적으로 생성시켰습니다. 그런데 멀티쓰레드에서 호출한 이벤트(RecvMsg)에서만 생성이 안되는군요....
frmMsg := TfrmMsg_0001.Create(self);
구문에서 self말고 nil, application도 다 해보았는데 역시 안되었습니다.
그리고
.
frmMsg := TfrmMsg_0001.CreateNew(self)도 해보았습니다.
또한 .
frmMsg := TfrmMsg_0001.CreateParented(WinHandle) 도 해보았는데 안되더군요..
음..폼을 동적으로 생성시키는 다른 방법이 없을까요? 아님 정말 멀티쓰레드의 문제인가요? 가령 멀티쓰레드에서 어떤 함수를 호출하고 그 함수에서 폼을 동적으로 생성이 안되는건가요? 아님 Create의 옵션을 다 몰라서 못찾은걸까요?? 음..자꾸 머리만 아파오네요...
긴글 읽어주어서 감사합니다.
frmMsg := ( frmMsg_0001 as TForm).Create(self);
<!--CodeE-->
저도 이 문제로 고민했는데, 이렇게 하면 되실겁니다. ^-^