我正在开发一个 IRC 客户端。我遇到了一个专业的障碍,直到没有我能够解决。我将在下面显示代码。我遇到的问题是在 idIRC 的事件处理程序中创建 MDI 子窗口。
例如,如果我想创建一个新的频道表单(FrmChannel),我可以通过在捕获“/join”命令时调用它的创建过程来轻松完成此操作。
但是,如果我想以正确的方式进行操作,并等到我真正加入频道,并从服务器接收确认(通过在 onjoin 事件处理程序中处理它),那么我对表单创建过程的调用会导致要挂起的应用程序。
状态窗口也是如此。例如,如果我将状态窗口创建过程调用放在 TButton 的 onclick 事件上,那很好。子窗体已创建。但是,如果我在实际收到私人消息时尝试同样的事情,通过检查事件处理程序......应用程序挂起,没有异常,也没有 MDI 子级。
这是相关代码(为了解决这个问题,我将只处理查询窗口)。
首先,实际的 MDI Child 创建过程是这样的。我在这里有一个 TComponentList 来管理此类表单的列表(以防您想知道)。这里还有一些其他的东西也可以跟踪表单,尽管将它们注释掉并不能阻止挂起(我已经尝试过)。
procedure TFrmMain.NewQuery(const Server, MsgFrom: String);
var
Child: TFrmMessage;
TN: TTreeNode;
begin
///
/// Create form, set some data so we can reference it later.
///
///
Child := TFrmMessage.Create(Application);
// QueryManager.Add(Child); //TComponent List -- Used to find the Form Later On
with Child do
begin
MyServer := Server; {What server this PM window is on}
QueryWith := MsgFrom; {nickaname of the other person}
Caption := MsgFrom; {Asthetic}
end;
Child.Echo('*** Conversation with ' + MsgFrom); //Herro World
///
/// The following code is working.
/// I'm pretty sure it's not causing the hangs.
///
TN := GetNodeByText(ChanServTree, Server, True); {Find our parent node}
with ChanServTree.Items.AddChild(TN, MsgFrom) do
begin
Selected := True;
Tag := 2; {TYPE OF QUERY}
Data := Pointer(Integer(Child)); //Pointer to Form we created
end;
end;
这是我的 IRC 组件的事件处理程序:
procedure TFrmMain.IRCPrivateMessage(ASender: TIdContext; const ANicknameFrom,
AHost, ANicknameTo, AMessage: string);
var
CheckVr: String;
aThread: TNQThread;
begin
//DEBUG:
(StatusManager[0] as TFrmStatus).Echo('From: ' + ANickNameFrom + 'AMESSAGE: ' + '''' +AMessage + '''');
///
/// Handle Drone Version Requests!
/// This is REQUIRED on servers like irc.blessed.net - or they won't let you join
/// channels! - It's part of the Registration proccess
///
{The Drones on some server's don't follow specifications, so we need to search
hard for their presence}
CheckVr := AMessage;
StringReplace(CheckVr,' ','',[rfReplaceAll, rfIgnoreCase]);
StringReplace(CheckVr,#1,'',[rfReplaceAll, rfIgnoreCase]);
(StatusManager[0] as TFrmStatus).Echo('Message was: ' + '''' + CheckVr + '''');
if Trim(CheckVr) = 'VERSION' then
begin
IRC.CTCPReply(ANickNameFrom,'VERSION','mIRC v6.01 Khaled Mardam-Bey');
(StatusManager[0] as TFrmStatus).Echo('*** Sent Version Reply to ' + ANickNameFrom);
exit; {Because if we don't, this could mess things up}
end;
///
/// The Following code sends the PM to the appropriate window.
/// If that window does not exist, we will create one first.
///
if Pos('#',Amessage) = 1 then
begin
//Handled Elsewhere
end else {is PM}
begin
if FindQueryFrm(ANickNameTo,IRC.Host) = nil then
begin
NewQuery(IRC.Host, ANickNameFrom);
exit;
end;
end;
// FindChannelFrm(ANickNameTo,IRC.Host).ChannelMessage(ANicknameFrom, AMessage);
end;
我已经尝试注释掉代码的各个部分以试图找出挂起的原因。挂起是由 Child := TFrmMessage.Create(Application); 引起的 专门打电话。是什么赋予了?
我已经尝试实现线程,看看这是否可能是一个问题。如果这就是您认为的问题所在,我将需要线程方面的帮助,因为显然尽管代码正在编译,但我仍然调用错误(因为即使我的线程版本挂起)。
提前致谢。