Mam AdvOfficePager - rozbudowana wersja TPageControl z kolekcji TMS, w którym w aplikacji głównej tworzę na żądanie DLL zakładkę, następnie przesyłam jej uchwyt z powrotem do DLL i tam tworzę formę, a następnie przypisuję jako parenta uchwyt zakładki. Wygląda to następująco:
DLL:
var
TabH: HWND;
OrderList: TfrmMobileOrderList;
begin
// ap to interfejs aplikacji głównej
ap.AddTabPage(tabh, 'Oczekujące na wizytę'); // Tworzy zakładkę w głównym programie o nazwie 'Oczekujące na wizytę' i zwraca jej uchwyt w zmiennej tabh
OrderList := TfrmMobileOrderList.CreateP(TabH); // Tworzy okno
OrderList.show;
end;
Okno frmMobileOrderList w DLL
private
FParent: THandle;
end;
...
constructor TfrmMobileOrderList.CreateP(Parent: THandle);
begin
FParent := Parent;
inherited Create(nil);
end;
procedure TfrmMobileOrderList.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WndParent := FParent;
Params.Style := WS_CHILD or WS_CLIPSIBLINGS or WS_BORDER;
Align := alClient;
end;
W aplikacji głównej mam listę obiektów w której trzymam listę zakładek, oraz rozróżniam, które należą do aplikacji głównej, a które do bibliotek DLL:
type
TPages = class(TAdvOfficePage) // Dziedziczy po komponencie zakładki
private
Name: string;
Form: TForm; // Tylko dla apliakacji głównej, aby przy zamykaniu zakładki, zwolnić również okno
DLL: boolean; // Czy pochodzi z DLL
end;
// Tutaj trzymam obiekty zakładek
FPageList: TObjectList<TPages>;
// A tak wygląda funkcja, wywoływana po kliknięciu w X na zakładce TAdvOfficePager
procedure TFormManager.CloseForm(APage: TAdvOfficePage);
var
i: Integer;
begin
for i := 0 to FPageList.Count -1 do
if (FPageList.Items[i].Caption = APage.Caption) then
begin
// Okna zwalniamy tylko dla zakładek z aplikacji głównej
// Dla DLL trzeba inaczej (JAK??)
if not FPageList.Items[i].DLL then
begin
FPageList.Items[i].Form.Free;
FPageList.Items[i].Form := nil;
end;
FPageList.Delete(i);
break;
end;
if FPageList.Count = 0 then
FNotebook.ActivePage := 'Wallper';
end;
Funkcja dodająca zakładki w programie głównym:
function TfrmMain.AddTabPage(out ATabH: HWND; ACaption: PAnsiChar): HRESULT;
begin
ATabH := FormManager.ShowFormDLL(ATabH, ACaption);
end;
function TFormManager.ShowFormDLL(ATabH: HWND; ACaption: PAnsiChar): HWND;
var
I: Integer;
LPageExists: boolean;
begin
Result := 0;
LPageExists := False;
for I := 0 to FPageList.Count -1 do
begin
if FPageList.Items[i].Caption = ACaption then
begin
// Ustaw aktywna zakladke
FPageControl.ActivePage := FPageControl.PageByCaption(ACaption);
LPageExists := True;
Result := FPageControl.ActivePage.Handle;
break;
end;
end;
if not LPageExists then
begin
FPageList.Add(TPages.Create(nil)); // CreateParented(ATabH)); nie pomaga
FPageList.Last.ParentWindow := ATabH; // nie pomaga
FPageList.Last.Caption := ACaption;
FPageList.Last.DLL := True;
FPageControl.AddAdvPage(FPageList.Last);
Result := FPageList.Last.Handle;
FPageControl.ActivePage := FPageList.Last;
FNotebook.ActivePage := 'Forms';
end;
end;
Pytanie: Jak po kliknięciu X na zakładce AdvOfficePage w funkcji CloseForm zwolnić również formę z DLL?
ap.AddTabPage(tabh, 'Oczekujące na wizytę'); // Tworzy zakładkę w głównym programie o nazwie 'Oczekujące na wizytę' i zwraca jej uchwyt w zmiennej tabh
OrderList := TfrmMobileOrderList.CreateP(TabH); // Tworzy okno
OrderList.show;
Jak widać w powyższym kodzie, uchwyt do okna tworzony jest później niż zakładka, bo gdybym miał uchwyt okna od razu, to mógłbym wysłać komunikat WM_CLOSE i chyba byłoby po problemie. Z tego co się orientuję, to muszę tworzyć okno po utworzeniu zakładki, bo muszę najpierw mieć uchwyt zakładki, żeby przypisać go do tworzonego okna.