Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fenster einer anderen Delphi Anwendung in das eigene einbinden (https://www.delphipraxis.net/184656-fenster-einer-anderen-delphi-anwendung-das-eigene-einbinden.html)

MyRealName 12. Apr 2015 16:40

Delphi-Version: XE5

Fenster einer anderen Delphi Anwendung in das eigene einbinden
 
Hallo, mal 'ne Frage..

meine Hauptanwendung ist in Delphi 2007 und ich kann sie nicht updaten auf XE5, weil ich einen Reportgenerator drin habe, der seit Delphi 3 nicht mehr geupdated wird und unter unicode einfach alles verbockt. Will darin aber auch nicht rumbasteln. Problem ist, dass aus irgendeinem Grund die Kunden von uns den nicht verlieren wollen. Die wissen halt mittlerweile wie sie damit Sachen machen können.
Jetzt habe ich mir einen kleinen Report-Server gebastelt, dem ich über tcp/ip den Namen und die Parameter des Reports sende und er zeigt ihn in einem extra-Fenster an. Damit kann ich ihn aus der Hauptanwendung "rausoperieren", aber wäre natürlich besser, wenn ich das Fenster in meine Anwendung reinkriegen würde, also sozugane "den Parent" auf ein leeres MD FEnster in meiner Anwendung setzen...
Die Hauptanwendung wurde dann erstmal in Delphi XE laufen und dann XE5, der Report-Server auf Delphi 2007 bleiben...

Weiss einer, ob das geht und wie ?
Einfach Parenthandle auf das handle vom eigenen mdi setzen ?

Besser wäre natürlich, wenn es eine DLL wäre die ich in dem Kontext laden kann und die mir ein fenster macht, dessen ParentHandle ich setzen kann...

Danke schonmal

Sigi55 12. Apr 2015 19:05

AW: Fenster einer anderen Delphi Anwendung in das eigene einbinden
 
Hallo,

schön, ich kann auch mal etwas beitragen. :-D
Ich bin mal irgendwo über diese Demo gestolpert, also nicht von
mir ...

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    MainMenu1: TMainMenu;
    Window1: TMenuItem;
    Show1: TMenuItem;
    Hide1: TMenuItem;
    N1: TMenuItem;
    ArrangeAll1: TMenuItem;
    Cascade1: TMenuItem;
    ile1: TMenuItem;
    NewWindow1: TMenuItem;
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    procedure NewWindow1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


function RunProcess(FileName: string; ShowCmd: DWORD; wait: Boolean; ProcID: PCardinal): Longword;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  FillChar(StartupInfo, SizeOf(StartupInfo), #0);
  StartupInfo.cb := SizeOf(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
  StartupInfo.wShowWindow := ShowCmd;
  if not CreateProcess(nil,
    @Filename[1],
    nil,
    nil,
    False,
    CREATE_NEW_CONSOLE or
    NORMAL_PRIORITY_CLASS,
    nil,
    nil,
    StartupInfo,
    ProcessInfo)
    then
      Result := WAIT_FAILED
  else
  begin
    try
      if not wait then
      begin
        if ProcID <> nil then ProcID^ := ProcessInfo.dwProcessId;
        Result := S_OK;
        exit;
      end;
      WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
      GetExitCodeProcess(ProcessInfo.hProcess, Result);
    finally
      CloseHandle(ProcessInfo.hProcess);
      CloseHandle(ProcessInfo.hThread);
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ProcID: PCardinal;
begin
  if OpenDialog1.Execute then
    RunProcess(OpenDialog1.FileName, SW_MINIMIZE, TRUE, ProcID);
  Messagebox(0, 'fertig', @OpenDialog1.Filename[1], 0);
end;

procedure TForm1.NewWindow1Click(Sender: TObject);
var
  hNotepad: hWnd; //Handle auf das Window welches man einsperren möchte

begin
  hNotepad := FindWindow('Notepad','Unbenannt - Editor'); //In diesem Fall sperren wir das gute alte Notepad ein
  Windows.SetParent(hNotepad, form1.panel1.Handle); //Wir setzen das Parent mit Windows.SetParent, da ein Aufruf
                                        //von SetParent zur Folge hätte, dass wir die Methode von
                                        //TWinControl aufrufen würden, was wir nicht wollen
  ShowWindow(hNotepad, SW_MAXIMIZE); //Einmal ShowWindow mit SW_MAXIMIZE als Parameter damit das Fenster
                                     //sich über die ganze Form erstreckt
end;

end.
Isses das ?

Gruß

Sigi

Sherlock 13. Apr 2015 07:33

AW: Fenster einer anderen Delphi Anwendung in das eigene einbinden
 
Das dürfte die korrekte Methode sein (der Kern ist eigentlich die eine Zeile mit dem SetParent). Das Problem daran ist, das Du Dir damit die Hölle auf Erden (in Windows) schaffst. Folgendes funktioniert danach nicht mehr wie erwartet:
  • Dialoge des eingefangenen Programms sind nicht modal gegenüber der Host-Applikation, sie können also "versehentlich" in den Hintergrund geklickt werden, und damit hängt alles
  • Tooltips werden nicht mehr angezeigt
  • Resize-Events werden unzuverlässig bemerkt
  • Unter Umständen wird der Windows-Style ignoriert (habe ich aber nur selten gesehen)
Und das ist nur die Spitze des Eisbergs. Da gibt es noch so viele kleine Problemchen, die folgen - das will man einfach nciht freiwillig durchmachen.

Sherlock

MyRealName 13. Apr 2015 12:45

AW: Fenster einer anderen Delphi Anwendung in das eigene einbinden
 
Ich habe gestern mal probiert mit einem Delphi 2007 Fenster in einer DLL gehostet in einer XE5 app. Das ging ganz gut, damit brauch ich scheinbar keine extra exe die ich laden muss, nur die DLL, Frage wird dann sein, inwieweit ich die Kommandos bekomme vom Host Fenster, das will ich heute mal probieren


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:33 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz