首页 > 解决方案 > Delphi Application.CreateForm 是每个表单的唯一句柄吗?

问题描述

我有一个 TreeList ,有很多 Items ,每个项目都有它自己的唯一 ID 。我允许用户一次打开多个 ID。但我想防止用户两次打开同一个 ID。

所以我考虑创建一个简单的动态数组,在其中存储哪个 TreeList ID 连接到哪个 Form HWND 。如果我在我的列表中找到一个带有匹配 HWND 的 ID,那么我只需将已经创建的表单带到前台。

  Application.CreateForm(TChapter, Chapter);
  Chapter.PopupParent:=Main;
  Chapter.FID:=qryTreeID.Value;
  Chapter.Caption:=qryTreeName.Value+Cardinal(Chapter.Handle).ToString;
  Chapter.Show;

这就是我创建 Form 的方式。这只是一个“基本”示例。我只是想确保句柄是唯一的,我打开了多个表单,数字总是不同的。但我想确定。

谢谢!

标签: formsdelphihandle

解决方案


如果您想维护自己的查找,aTDictionary比动态数组更有意义。但无论哪种方式,您都应该将 ID 映射到实际TForm对象而不是其HWND. HWND保证是唯一的,但不是持久的,因为它可以在表单的生命周期内更改。它还可以使您免于必须TFormHWND.

例如:

var
  Chapters: TDictionary<Integer, TChapter> = nil;

procedure ChapterDestroyed(Self: Pointer; Sender: TObject);
begin
  if Chapters <> nil then
    Chapters.Remove(TChapter(Sender).FID);
end;

function FindChapterByID(ID: Integer): TChapter;
// var I: Integer;
begin
  {
  for I := 0 to Screen.FormCount-1 do
  begin
    if Screen.Forms[I] is TChapter then
    begin
      Result := TChapter(Screen.Forms[I]);
      if Result.FID = ID then Exit;
    end;
  end;
  Result := nil;
  }
  if not Chapters.TryGetValue(ID, Result) then
    Result := nil;
end;

function CreateChapter(ID: Integer): TChapter;
var
  Event: TNotifyEvent;
begin
  TMethod(Event).Data := nil;
  TMethod(Event).Code = @ChapterDestroyed;

  Result := TChapter.Create(Main);
  try
    Result.FID := ID;
    Result.PopupParent := Main;
    Result.Caption := qryTreeName.Value + ID.ToString;
    Result.OnDestroy := Event;
    Chapters.Add(ID, Result);
  except
    Result.Free;
    raise;
  end;
end;

function ShowChapterByID(ID: Integer): TChapter;
begin
  Result := FindChapterByID(ID);
  if Result = nil then Result := CreateChapter(ID);
  Result.Show;
end;

initialization
  Chapters := TDictionary<Integer, TChapter>.Create;
finalization
  FreeAndNil(Chapters);
Chapter := ShowChapterByID(qryTreeID.Value);

推荐阅读