0

I have a TreeList , with many Items , each item has it's own unique ID . I allow the user to open multiple IDs at once . But I would like to prevent the user from opening the same ID twice .

So I thought about creating a simple Dynamic Array where I store which TreeList ID is connected to which Form HWND . If I find a ID on my list with a Matching HWND, then I simply bring the Form which is already Created to Foreground.

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

This is how I create a Form . This is just a "basic" example . I just wanted to make sure that the Handle is Unique , I opened Multiple Forms the Numbers were always different. But I want to make sure.

Thank you!

2
  • 2
    Why would you go creating a new array when it seems you already have the information available in FID field/property of your TChapter form. So all you have to do is loop through all of the forms to see if form with certain FID is already open. If it is you just show it. If it is not you create a new one. Commented Oct 29, 2019 at 14:09
  • 5
    Casting HWND to Cardinal is potentially risky on 64 bit, where HWND is a 64 bit type, but you'll get away with it due to implementation details. What you won't get away with is window recreation. The unique ID for a form is its own reference. Replace Cardinal(Chapter.Handle) with NativeUInt(Chapter). Commented Oct 29, 2019 at 14:48

2 Answers 2

4

If you want to maintain your own lookup, a TDictionary would make more sense than a dynamic array. But either way, you should map the ID to the actual TForm object rather than to its HWND. The HWND is guaranteed to be unique, but not persistent, as it can change during the Form's lifetime. It would also save you from the extra step of having to get the TForm object from the HWND.

For example:

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);
Sign up to request clarification or add additional context in comments.

Comments

0

Thank you for both of you. I took SilverWariors advice , because of the simplicity :)

  for i := 0 to Screen.FormCount-1 do
  begin
    if Screen.Forms[i] is TChapter then
      if (Screen.Forms[i] as TChapter).FID = qryTreeID.Value then
      begin
        (Screen.Forms[i] as TChapter).BringToFront;
        Exit;
      end;
  end;

1 Comment

Once Screen.Forms[i] is TChapter returns true, you may as well write TChapter(Screen.Forms[i]) rather than using a checked cast with as. No point checking the type three times as your code does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.