Announcement

Collapse
No announcement yet.

bei später Bindung ist Objekt nicht sichtbar

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • bei später Bindung ist Objekt nicht sichtbar

    Delphi 5 UP1
    habe einen COM-Server geschrieben. Anschließend in einen Delphi-PRG werden die beiden Methoden: Entstehen lassen mit *.Create(Owner) und die späte Bindung mit CreateOleObject(MProgID) aufgerufen. Bei der späten Bindung ist das Objekt nicht sichtbar. In der Hilfe steht "einzelnes, nicht initialisiertes Objekt". Aber wie wird das Objekt initialisiert?

    procedure TForm1.Button2Click(Sender: TObject);
    var
    pDisp : IDispatch;
    begin
    pDisp:=CreateOleObject(MProgID.Text); //<== ????
    end;

  • #2
    Hallo,

    so richtig verstehe ich noch nicht, wo das Problem liegt. Was ist mit "nicht sichtbar" gemeint? Wird das COM-Objekt nicht erzeugt (Exception beim Aufruf) oder ist nur die visuelle Oberfläche nicht sichtbar? Die folgenden Beispiele demonstrieren den Aufruf beider Alternativen:

    Frühe Bindung über die CoClass-Hilfsfunktionen:
    <pre>
    procedure TForm1.ButtonCalcClick(Sender: TObject);
    var
    aMWSt : IMWSt;
    cNetto : Currency;
    cBrutto : Currency;
    begin
    aMWSt := CoMWSt.Create;
    cNetto := StrToFloat(EditNetto.Text);
    cBrutto := aMWSt.GetBrutto(cNetto);
    StaticTextBrutto.Caption := Format('%m',[cBrutto]);
    end;
    </pre>
    Späte Bindung über die APPID:
    <pre>
    procedure TForm1.ButtonCalcClick(Sender: TObject);
    var
    aMWSt : OleVariant;
    cBrutto : Currency;
    begin
    aMWSt := CreateOleObject('COMMWST.MWSt');
    if RadioGroup1.ItemIndex = 0
    then aMWSt.SetPercent(7)
    else aMWSt.SetPercent(16);
    cBrutto := aMWSt.GetBrutto(StrToFloat(EditNetto.Text));
    StaticTextBrutto.Caption := Format('%m',[cBrutto]);
    end;
    </pre>
    Die als APPID zu verwendende Zeichenkette kann zum einen in der Registry nachgeschlagen werden oder im Typbibliothekseditor von Delphi. Der Teil vor dem Punkt ist der Name der Typbibliothek, der als Wurzeleintrag anzeigt wird. Der Teil nach dem Punkt ist der Name der CoClass:
    <pre>
    typelib COMMWST
    [ uuid '{C23B4787-B377-11D1-95EA-444553540000}',
    version 1.0,
    helpstring 'COMMWST (Bibliothek)' ];

    uses stdole32.tlb, OLEPRO32.DLL, STDVCL32.DLL;

    IMWSt = interface(IDispatch)
    [ uuid '{C23B4788-B377-11D1-95EA-444553540000}',
    version 1.0,
    helpstring 'Dispatch-Interface für MWSt-Objekt',
    hidden,
    dual,
    oleautomation ]
    end;

    MWSt = coclass(IMWSt [default] )
    [ uuid '{C23B4789-B377-11D1-95EA-444553540000}',
    version 1.0,
    helpstring 'MWStObjekt' ];

    end.
    </pre>
    P.S: Eine ausführlichere Erklärung aller Zusammenhänge ist in meinem Buch <b>COM/DCOM mit Delphi</b> zu finden.
    &#10

    Comment


    • #3
      Hallo Herr Kosch,
      vielen Dank für die promte Antwort. Auch für die Beispiele, die ich auch in ihrem Buch gefunden habe. Allerdings benutzen Sie nur die Methoden des Servers, da der Server keine visuellen Anteile Besitzt.

      Zur Erklärung: Ich versuche einen Container für ActiveX-Server zur schreiben. D.h. in Delphi existiert ein ganz normales Fenster (TForm), in den ich die Server laden möchte. Dazu lese ich die Registory aus, und zeige alle vorhandenen Server an (wie in Delphi unter "ActiveX importieren")(warum Delphi weniger anzeigt wie in der Registory steht, muß ich noch herausfinden). Dann soll ein Server mittels Maus ausgewählt werden. Alle Infos (LibID, ClassID und ProgID) hole ich mir dann aus der Registory. Nun versuche ich den Server mittels CreateOleObject(ProgID) entstehen zu lassen. (Beispiel, der in Delphi beiliegende "VtChart ... VCL First Impression Library". Der Server wird zwar ohne Fehler instanziert, aber scheinbar nicht initialisiert (auf dem TForm sichtbar) ???, im Gegensatz zu "VtChart1: TVtChart; VtChart1:=TVtChart.Create(Form1); VtChard1.Parent:=Form1;". Was fehlt blos in meinen Aufruf???

      M.Süsen

      Comment


      • #4
        Ach ja, bin ein bischen schwach in der Microsoft-Sprache ... Registory erstezen mit Registry..

        Comment


        • #5
          Hallo,

          wenn ich das richtig verstehe, geht es darum, einzelne visuelle Controls bzw. Formulare aus dem COM-Server im Programmfenster des Clients einzublenden. Wenn ja, greife ich in diesen Fällen auf die folgende Implementierung zurück:

          <b>COM-Server:</b>
          Der Client übergibt beim Aufruf der Interface-Methode des Servers sein Fensterhandle, damit das Control/Formular aus dem Server korrekt dargestellt werden kann. Dazu wird dieses Fensterhandle in einer globalen Variable des Servers gesichert:
          <pre>
          ICIC = interface(IDispatch)
          ['{364A67A2-5172-11D3-BED8-005004303872}']
          procedure ShowControl(hWndParent: Integer); safecall;
          procedure HideControl(out SelectedDate: TDateTime); safecall;
          end;
          </pre>
          <pre>
          procedure TCIC.ShowControl(hWndParent: Integer);
          begin
          hControlParent := hWndParent;
          Application.Handle := hWndParent;
          if not Assigned(FormControl) then
          begin
          FormControl := TFormControl.Create(nil);
          FormControl.Top := 1;
          FormControl.Left := 1;
          FormControl.Visible := True;
          end;
          end;
          </pre>
          Das Formular aus dem COM-Server muss sich nun als Child-Fenster definieren und den Fensterhandlewert des Client-Formulars als eigenes Parent-Fenster definieren:
          <pre>
          type
          TFormControl = class(TForm)
          MonthCalendar1: TMonthCalendar;
          private
          { Private-Deklarationen }
          public
          { Public-Deklarationen }
          procedure CreateParams(var Params: TCreateParams); override;
          end;

          var
          FormControl: TFormControl;
          hControlParent : Integer;

          implementation

          {$R *.DFM}

          { TFormControl }

          procedure TFormControl.CreateParams(var Params: TCreateParams);
          begin
          inherited CreateParams(Params);
          with Params do
          begin
          Style := WS_CHILD or WS_VISIBLE;
          WndParent := hControlParent;
          end;
          end;
          </pre>
          <b>Client:</b>
          Der Client ruft nun die Interface-Methode des Servers auf und übergibt ein eigenes Fensterhandle:
          <pre>
          procedure TFormMainClt.ButtonShowClick(Sender: TObject);
          begin
          FSrv := CoCIC.Create;
          FSrv.ShowControl(Handle);
          ButtonHide.Enabled := True;
          ButtonShow.Enabled := False;
          end;
          </pre>

          P.S: Sollte es gar nicht um eigene COM-Server gehen, sondern um "fremde" ActiveX-Controls, wird es komplizierter. Viele "echte" ActiveX-Controls verwenden einen Lizenzschlüssel, so das der "Container" beim Instanzieren diese Lizenzdaten mit an das Control übertragen muss. Ein Beispiel dafür kann man sich anschauen, wenn in Delphi ein ActiveX-Control verwendet wird. Die dabei generierte Unit hat spezielle Initfunktionen

          Comment


          • #6
            Hallo Herr Kosch,
            vielen Dank, ich probiere erst mal eine weile. Melde dann das Resultat

            Comment

            Working...
            X