gpt4 book ai didi

windows - 我怎样才能释放一个 Tpanel 有一个 TbitBtn 调用释放 Tpanel

转载 作者:可可西里 更新时间:2023-11-01 11:35:38 26 4
gpt4 key购买 nike

我创建了一个自定义 Tpanel 并在里面放置了各种自定义组件......

procedure Panel_Comp(Location: TWinControl; NumOfComp:     Integer;Left,Top,Height,width:Integer);  
begin
MyPanel := TsPanel.Create(Conf);
MyPanel.Name := 'MyPanel' + IntToStr(NumOfComp);
MyPanel.Parent := Location;
MyPanel.Left := Left;
MyPanel.Top := Top;
MyPanel.Height := Height;
MyPanel.Width := width;
MyPanel.Caption := '';
end;

我是这样调用它的

Panel_Comp(Conf.ScrollBox1,1,8,10,70,322);  

按照相同的逻辑,我在新面板中放入了其他自定义组件,包括具有 onclick 事件的 tBitbtn。

procedure BitBtn_Comp(Location: TWinControl; NumOfComp: Integer; Left,Top,Height,Width,ImageNum: Integer);  
begin
MyBitBtn := TBitBtn.Create(Conf);
......
MyBitBtn.tag := NumOfComp;
MyBitBtn.OnClick:= Conf.CloseCurrentPanel;
end;

在主窗体中的TConf.CloseCurrentPanel;

procedure TConf.CloseCurrentPanel(Sender: TObject);  
var
panelComp: TComponent;
begin
panelComp := FindComponentEx('Conf.MyPanel'+ IntToStr(TBitBtn(Sender).tag);
TPanel(panelComp).Free;
Application.ProcessMessages;
end;

当我调用它时,我遇到了访问冲突......我认为在释放面板之前我必须释放面板内的所有组件,但是我如何在面板之前释放 BitBtn 并继续点击事件的操作?

这是您需要的 FindComponetEx 函数...

function FindComponentEx(const Name: string): TComponent;  
var
FormName: string;
CompName: string;
P: Integer;
Found: Boolean;
Form: TForm;
I: Integer;
begin
// Split up in a valid form and a valid component name
P := Pos('.', Name);
if P = 0 then
begin
raise Exception.Create('No valid form name given');
end;
FormName := Copy(Name, 1, P - 1);
CompName := Copy(Name, P + 1, High(Integer));
Found := False;
// find the form
for I := 0 to Screen.FormCount - 1 do
begin
Form := Screen.Forms[I];
// case insensitive comparing
if AnsiSameText(Form.Name, FormName) then
begin
Found := True;
Break;
end;
end;
if Found then
begin
for I := 0 to Form.ComponentCount - 1 do
begin
Result := Form.Components[I];
if AnsiSameText(Result.Name, CompName) then Exit;
end;
end;
Result := nil;
end;

最佳答案

出现 AV 是因为您正在破坏仍在处理 Windows 消息的组件 (MyBitBtn)。解决方案是通过 PostMessage 将销毁推迟到以后,类似于这样:

unit Unit1;

interface

uses
Windows,
Messages,
SysUtils,
Variants,
Classes,
Graphics,
Controls,
Forms,
Dialogs,
ExtCtrls,
StdCtrls;

const
UM_DESTROYPANEL = WM_APP + 623; // some "unique" number; UM = user message

type
TConf = class(TForm)
Panel1: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
strict private
procedure UMDestroyPanel(var Message: TMessage); message UM_DESTROYPANEL;
public
{ Public-Deklarationen }
end;

var
Conf: TConf;

implementation

{$R *.dfm}

procedure TConf.Button1Click(Sender: TObject);
begin
PostMessage(Handle, UM_DESTROYPANEL, 0, 0);
end;

procedure TConf.UMDestroyPanel(var Message: TMessage);
begin
Panel1.Free;
end;

end.

如果需要,您可以使用 wParam 和 lParam 来传递参数,如下所示:

procedure TConf.Button1Click(Sender: TObject);
begin
PostMessage(Handle, UM_DESTROYPANEL, WPARAM(Panel1), 0);
end;

procedure TConf.UMDestroyPanel(var Message: TMessage);
begin
TObject(Message.WParam).Free;
end;

编辑:在您的情况下,我可能会像这样重写 TConf.CloseCurrentPanel:

procedure TConf.CloseCurrentPanel(Sender: TObject);
var
panelComp: TComponent;
begin
panelComp := FindComponentEx('Conf.MyPanel'+ IntToStr(TBitBtn(Sender).Tag);
PostMessage(Handle, UM_DESTROYPANEL, WPARAM(panelComp), 0);
end;

或者,您可以通过标签(可能是更好的解决方案,因为涉及的转换较少):

procedure TConf.CloseCurrentPanel(Sender: TObject);
begin
PostMessage(Handle, UM_DESTROYPANEL, TBitBtn(Sender).Tag, 0);
end;

procedure TConf.UMDestroyPanel(var Message: TMessage);
var
panelComp: TComponent;
begin
panelComp := FindComponentEx('Conf.MyPanel'+ IntToStr(Message.WParam));
panelComp.Free;
end;

AFAICT 不需要 Application.ProcessMessages

关于windows - 我怎样才能释放一个 Tpanel 有一个 TbitBtn 调用释放 Tpanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11877394/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com