Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Komponente vor dem Platzieren umbenennen / OpenTools API (https://www.delphipraxis.net/77517-komponente-vor-dem-platzieren-umbenennen-opentools-api.html)

CG2003 20. Sep 2006 16:46


Komponente vor dem Platzieren umbenennen / OpenTools API
 
Hallo liebe DP,

ich versuche mich gerade an einem kleinen IDE-Experten, mit dem ich Komponenten umbenennen kann, während ich sie auf die Form ziehe. Sowas gibt es ja schon: CNA - Component Naming Assistant,
aber ich will mein eigenes schreiben!

Dazu habe ich folgenden Code im Internet gefunden:

Delphi-Quellcode:
unit ComponentPrefixExpert;

interface

procedure Register;

implementation

uses Windows, SysUtils, Controls, Classes, ToolsAPI, Dialogs;

type
  TPPWIdeNotifier = class( TNotifierObject, IOTANotifier, IOTAIDENotifier)
  public
    constructor Create;
    destructor Destroy; override;
    { IOTAIDENotifier } 
    procedure FileNotification(NotifyCode: TOTAFileNotification;
      const FileName: string; var Cancel: Boolean);
    procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean); overload;
    procedure AfterCompile(Succeeded: Boolean); //overload;
  end;

  TPPWFormNotifier = class( TNotifierObject, IOTANotifier, IOTAFormNotifier )
  private
    FFileName : String;
  public
    constructor Create( FileName : String );
    destructor Destroy; override;
    procedure FormActivated;
    procedure FormSaving;
    procedure ComponentRenamed(ComponentHandle: TOTAHandle;
      const OldName, NewName: string);
    { IOTAModuleNotifier } 
  end;

  TPPWModuleNotifier = class( TNotifierObject, IOTANotifier, IOTAModuleNotifier )
  private
    FOldFileName : String;
    FFileName   : String;
  public
    constructor Create (Const FileName : String);
    destructor destroy; override;
    { IOTAModuleNotifier } 
    function CheckOverwrite : Boolean;
    procedure ModuleRenamed(const NewName: string);
  end;

var
  Index : Integer;
  NotifierList : TStringList;

procedure Register;
begin
  Index := (BorlandIDEServices as IOTAServices).AddNotifier(TPPWIdeNotifier.Create);
end;


{ TPPWIdeNotifier } 

procedure TPPWIdeNotifier.AfterCompile(Succeeded: Boolean);
begin
end;

procedure TPPWIdeNotifier.BeforeCompile(const Project: IOTAProject;
  var Cancel: Boolean);
begin
end;

constructor TPPWIdeNotifier.Create;
begin
  Inherited Create;
  ShowMessage ('TPPWIdeNotifier created');
end;

destructor TPPWIdeNotifier.Destroy;
begin
  ShowMessage (' Destroying TPPWIdeNotifier ');
  ShowMessage (' Notifiers Left : ' + inttostr(NotifierList.Count));
  inherited Destroy;
end;

procedure TPPWIdeNotifier.FileNotification( 
  NotifyCode: TOTAFileNotification; const FileName: string;
  var Cancel: Boolean);
var
  Module        : IOTAModule;
  Editor        : IOTAEditor;
  FormEditor    : IOTAFormEditor;
  ModuleNotifier : TPPWModuleNotifier;
  FormNotifier  : TPPWFormNotifier;

  IModuleNotifier : Integer;
  FormNotifierI, ListI, I : Integer;
begin
  Case NotifyCode of
    ofnFileOpened :
    begin
      { Get the IOTAModule associated to this File } 
      Module := ( BorlandIDEServices as IOTAModuleServices ).FindModule(FileName);
      { Loop over the number of associated File } 
      for i := 0 to Module.GetModuleFileCount - 1 do
      begin
        { Get the FileEditor } 
        Editor := Module.GetModuleFileEditor(i);
        if Editor.QueryInterface( IOTAFormEditor, FormEditor ) = S_OK then
        begin
          { If the File Editor is a FormEditor then Add Our Notifier } 
          FormNotifier := TPPWFormNotifier.Create( FileName );
          FormNotifierI := FormEditor.AddNotifier ( FormNotifier );
          if FormNotifierI < 0 then
          begin
            FormNotifier.Free;
          end
          else
          begin
            ShowMessage( 'Notifier Index' + inttostr( FormNotifierI ));
            NotifierList.AddObject(FileName, Pointer(FormNotifierI));
          end;
          { Also Add a module Notifier } 
          ModuleNotifier := TPPWModuleNotifier.Create( FileName );
          IModuleNotifier := Module.AddNotifier( ModuleNotifier );
          if IModuleNotifier < 0 then
          begin
            ModuleNotifier.Free;
          end;
        end
      end;
    end;
    ofnFileClosing :
    begin
      if NotifierList.Find(FileName, ListI) then
      begin
        Module := ( BorlandIDEServices as IOTAModuleServices ).FindModule(FileName);
        FormNotifierI := Integer(NotifierList.Objects[ListI]);
        for i := 0 to Module.GetModuleFileCount - 1 do
        begin
          Editor := Module.GetModuleFileEditor(i);
          if Editor.QueryInterface( IOTAFormEditor, FormEditor ) = S_OK then
          begin
            FormEditor.RemoveNotifier ( FormNotifierI );
            NotifierList.Delete(ListI);
          end;
        end;
      end;
    end;
  end;
end;

{ TPPWFormNotifier } 

procedure TPPWFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
var
  Module        : IOTAModule;
  Editor        : IOTAEditor;
  FormEditor    : IOTAFormEditor;
  OTAComponent: IOTAComponent;
  Component: IComponent;
  I: Integer;
 
begin
  if not FRenaming then
  try
    FRenaming := True;
    Module := ( BorlandIDEServices as IOTAModuleServices ).FindModule(FFileName);
    for i := 0 to Module.GetModuleFileCount - 1 do
    begin
      Editor := Module.GetModuleFileEditor(i);
      if Editor.QueryInterface( IOTAFormEditor, FormEditor ) = S_OK then
      begin
        OTAComponent := FormEditor.FindComponent(OldName);
        if OTAComponent = nil then ShowMessage('OTAComponent not found.')
                              else
        begin
          Component := OTAComponent.GetIComponent;
          if Component = nil then ShowMessage('IComponent not found')
                             else Component.Name := 'Test' + NewName;
        end;
      end
    end;
  finally
    FRenaming := False;
  end;
end;
constructor TPPWFormNotifier.Create( FileName : String );
begin
  inherited Create;
  FFileName := FileName;
  ShowMessage ('Form Notifier Created for File : ' + FileName );
end;

destructor TPPWFormNotifier.destroy;
begin
  ShowMessage ('Form Notifier Destroyed for File : ' + FFileName );
  inherited Destroy;
end;

procedure TPPWFormNotifier.FormActivated;
begin
{} 
end;

procedure TPPWFormNotifier.FormSaving;
begin
{} 
end;

{ TPPWModuleNotifier } 

function TPPWModuleNotifier.CheckOverwrite: Boolean;
begin
  Result := True;
end;

constructor TPPWModuleNotifier.Create(const FileName: String);
begin
  inherited Create;
  FOldFileName := FileName;
  FFileName := FileName;
  ShowMessage ('Module Notifier Created for file : ' + FOldFileName);
end;

destructor TPPWModuleNotifier.destroy;
begin
  ShowMessage ('Module Notifier Destroyed for file : ' + FFileName);
  inherited;
end;

procedure TPPWModuleNotifier.ModuleRenamed(const NewName: string);
var
  ListI        : Integer;
  FormNotifierI : Integer;
begin
  if NotifierList.Find(FOldFileName, ListI) then
  begin
    FormNotifierI := Integer(NotifierList.Objects[ListI]);
    NotifierList.Delete(ListI);
    NotifierList.AddObject(NewName, Pointer(FormNotifierI));
  end;
  FOldFileName := NewName;
  FFileName := NewName;
  inherited ;
end;

initialization
  NotifierList := TStringList.Create;
  NotifierList.Sorted := True;

finalization
  (BorlandIDEServices as IOTAServices).RemoveNotifier(Index);
  NotifierList.Free;
end.
Das Problem ist nur, das er weder "FRenaming" noch "IComponent" findet/kennt.
Oder gibt es eine einfachere Variante eine Art "on the fly Komponenten-Umbenenner" zu entwickeln?

Bin für jeden Hinweis/Tip dankbar!

CG2003 21. Sep 2006 10:38

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
*push* ;)

mkinzler 21. Sep 2006 10:41

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Wird ja auch von anderen Extensions gemacht, da diese teilweise OS sind (JVCL, CnExperts ) kannst du dir ja mal die Quellcodes anschauen.

CG2003 21. Sep 2006 10:48

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von mkinzler
Wird ja auch von anderen Extensions gemacht, da diese teilweise OS sind (JVCL, CnExperts ) kannst du dir ja mal die Quellcodes anschauen.

ja, ich weiß, doch das Problem ist, das diese viel zu unübersichtlich und viel zu sehr ineinander verstrickt sind, so dass ich da ehrlich gesagt die o.g. gesuchte Funktionalität leider nicht nachvollziehen kann.

CG2003 21. Sep 2006 12:24

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
So, habe jetzt meinen FormNotifier soweit geändert, das er erkennt, das eine Komponente umbenannt wird/werden soll, bzw. er erkennt auch, das eine Komponente auf das Formular gezogen wird.

Mit dem Aufruf

Delphi-Quellcode:
SetPropValue(Instance, 'Caption', 'Test');
will ich nun das Property "Name", also die Komponentenbezeichnung in "Test" ändern.
Er durchläuft zwar diesen Aufruf und führt Ihn aus, jedoch wird der Name nicht geändert.


Hier nochmal der FormNotifier:


Delphi-Quellcode:
procedure TPPWFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
var
  Module        : IOTAModule;
  Editor        : IOTAEditor;
  FormEditor    : IOTAFormEditor;
  OTAComponent: IOTAComponent;
  Component: IOTAComponent;
  I: Integer;
  Instance : TComponent;
  C1, C2: TPersistentClass;
  Match: Boolean;
  begin
  if not FRenaming then
  try
    FRenaming := True;
    Module := ( BorlandIDEServices as IOTAModuleServices ).FindModule(FFileName);
        ShowMessage('Module FindModule OK');
    Instance := TComponent(ComponentHandle);
            ShowMessage('Instance = ComponentHandle');
  if not Assigned(ComponentHandle) then begin
    ShowMessage('ComponentHandle not assignes!');
    Exit;
      end;
  Instance := TComponent(ComponentHandle);
  begin
        SetPropValue(Instance, 'Name', 'Test');
        ShowMessage('SetPropValue OK');
//    end;
        end;
//      end
  finally
    FRenaming := False;
  end;
end;
Hoffe, es kann mir einer helfen!

CG2003 22. Sep 2006 11:53

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
~push~ ;)

chaosben 22. Sep 2006 12:02

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Irgendwie hab ich Lust einfach nur "ooooooch" drunter zu schreiben. :-D

Aber was solls: Wir erreichen das von dir gewünschte mit der Prozedur "SetPropByName(...)".

CG2003 22. Sep 2006 12:33

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von chaosben
Irgendwie hab ich Lust einfach nur "ooooooch" drunter zu schreiben. :-D

Aber was solls: Wir erreichen das von dir gewünschte mit der Prozedur "SetPropByName(...)".

Danke. ;)
Aber hättest Du vielleicht ein kleines Codebeispiel für mich?
Ich weiß ja noch nicht einmal, ob der Notifier so richtig definiert ist und vielleicht nur durch Zufall funktioniert?!

chaosben 22. Sep 2006 12:38

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
also ein Beispiel:

Delphi-Quellcode:
var
  Compo : IOTAComponent
begin
  Compo:=Editor.FindComponent(OldName); //Editor ist der IOTAFormEditor
  Compo.SetPropByName('Name','NewName');
end;

CG2003 22. Sep 2006 12:50

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Erstmal danke für Dein Beispiel. Mein Aufruf für "ComponentRenamed" sieht jetzt so aus:

Delphi-Quellcode:
procedure TPPWFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
var
  Module        : IOTAModule;
  Editor        : IOTAEditor;
  FormEditor    : IOTAFormEditor;
  Compo: IOTAComponent;
  I: Integer;

begin
  if not FRenaming then
  try
    FRenaming := True;
    Module := ( BorlandIDEServices as IOTAModuleServices ).FindModule(FFileName);
    for i := 0 to Module.GetModuleFileCount - 1 do
    begin
      Editor := Module.GetModuleFileEditor(i);
      if Editor.QueryInterface( IOTAFormEditor, FormEditor ) = S_OK then begin
        Compo := FormEditor.FindComponent(OldName);
        Compo.SetPropByName('Name','Testname');
      end
    end;
  finally
    FRenaming := False;
  end;
end;
Wenn ich das Ganze jetzt aber als Package installieren, und eine Komponente aufs Formular ziehe, bekomme ich eine Zugriffsverletzung.

Habe ich vielleicht was falsch gemacht?

CG2003 22. Sep 2006 22:58

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
~push~ ;)
Kann mir denn keiner helfen?

CG2003 24. Sep 2006 11:07

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Und nochmal: ~push~ :)

Irgendwer wird mir doch helfen können, oder?!

chaosben 24. Sep 2006 18:39

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Ich werd morgen mal in unsere Sourcen sehen und hoffentlich den Fehler finden. :)

CG2003 24. Sep 2006 18:56

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von chaosben
Ich werd morgen mal in unsere Sourcen sehen und hoffentlich den Fehler finden. :)

Das wäre super. Vielen Dank!
Wie gesagt, ich möchte ja nur "erkennen", das eine Komponente auf dem Form plaziert wird, und die dann direkt umbenennen. So wie es die GExperts oder auch Euer CNA machen.

chaosben 25. Sep 2006 06:12

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Gib doch mal zum Spass den aktuellen Namen der Komponente aus. Wenn du den hast, klappt auch das umbennen. Wenn das nicht klappt, musst du mal prüfen ob der Editor der ist, den du zu finden hoffst. (Entweder per Messagebox oder per "Logdatei schreiben") Das ist ne langwierige Prozedur aber es geht imho nicht anders. :)

CG2003 25. Sep 2006 19:19

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von chaosben
Gib doch mal zum Spass den aktuellen Namen der Komponente aus. Wenn du den hast, klappt auch das umbennen. Wenn das nicht klappt, musst du mal prüfen ob der Editor der ist, den du zu finden hoffst. (Entweder per Messagebox oder per "Logdatei schreiben") Das ist ne langwierige Prozedur aber es geht imho nicht anders. :)

Hallo, das klappt leider nicht. Ich bekomme jedesmal, wenn ich eine Komponente auf dem Form plaziere eine AV. Erbitte Hilfe... :wall: :?:

CG2003 25. Sep 2006 20:19

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, hier nochmal die aktuelle Variante. Diese funktioniert leider noch nicht.
Anscheinend hat er Probleme, beim Zuordnen der Variable "Compo", welches die platzierte Komponente sein soll.

Oder liegt der Fehler evtl. doch ganz woanders?
Ich hoffe, es kann mir einer helfen, denn mir scheint, ich bin nah dran...

chaosben 26. Sep 2006 05:51

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Also, bei mir geht dein Code wunderbar unter einer Voraussetzung: Das CNA-Package ist nicht installiert. Da gibt es scheinbar "Antipathien" :-D zwischen deinem Package und dem CNA. Die ComponentRenamed-Procedure hab ich zu Testzwecken mal eingekürzt: :)
Delphi-Quellcode:
procedure TPPWFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
begin
  ShowMessage('"'+OldName+'" wird zu "'+NewName+'"');
end;
Da sieht man schön, wann man welche Aktion ausführen kann.

CG2003 26. Sep 2006 06:10

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von chaosben
Also, bei mir geht dein Code wunderbar unter einer Voraussetzung: Das CNA-Package ist nicht installiert. Da gibt es scheinbar "Antipathien" :-D zwischen deinem Package und dem CNA. Die ComponentRenamed-Procedure hab ich zu Testzwecken mal eingekürzt: :)
Delphi-Quellcode:
procedure TPPWFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
begin
  ShowMessage('"'+OldName+'" wird zu "'+NewName+'"');
end;
Da sieht man schön, wann man welche Aktion ausführen kann.

Danke.
Hättest Du denn auch noch die Güte, mal zu prüfen, ob die Registrierung und Zuordnun meines FormEditors stimmt?

chaosben 26. Sep 2006 06:24

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Das schien alles in Ordnung.

CG2003 26. Sep 2006 06:34

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
So, habe das mit Deiner "ShowMessage" ausprobiert. Die Showmessage bekomme ich ja noch angezeigt, doch wenn der die Komponente umbenennen soll, via

Delphi-Quellcode:
Compo := SetPropByName('Name', 'NeuerTestName');
bekomme ich eine AV.

chaosben 26. Sep 2006 06:41

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Du darfst die Komponente erst umbennen, wenn sie initialisiert ist. Das erkennst du daran, das NewName schon einen Wert hat.
Auszug aus dem CNA:
Delphi-Quellcode:
procedure TFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
begin
  if (Wizard.FSettings.ExpertActive) then
  begin
    if (OldName='') and (NewName<>'') then
    begin
      FRenameTimer.Enabled:=false;
      FInsertedComponents.AddObject(NewName,ComponentHandle);
      FRenameTimer.Enabled:=true;
    end;
  end;
end;

CG2003 26. Sep 2006 06:50

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von chaosben
Du darfst die Komponente erst umbennen, wenn sie initialisiert ist. Das erkennst du daran, das NewName schon einen Wert hat.
Auszug aus dem CNA:
Delphi-Quellcode:
procedure TFormNotifier.ComponentRenamed(ComponentHandle: TOTAHandle;
  const OldName, NewName: string);
begin
  if (Wizard.FSettings.ExpertActive) then
  begin
    if (OldName='') and (NewName<>'') then
    begin
      FRenameTimer.Enabled:=false;
      FInsertedComponents.AddObject(NewName,ComponentHandle);
      FRenameTimer.Enabled:=true;
    end;
  end;
end;

Hmm, müsste ich mal ausprobieren, doch was bedeutet in diesem Falle

Delphi-Quellcode:
FInstertedComponents.AddObject(NewName, ComponentHandle);
Ich denke das eigentlich Umbenennen mache ich mit

Delphi-Quellcode:
SetPropByName('Name', 'NeuerName');
Und was ist "Wizard", "FSettings" und "FRenameTimer" ?

chaosben 26. Sep 2006 07:19

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Das war nur ein Beispiel. Das einzig interessante an dem Code war die Abfrage von OldName und NewName. Die anderen Objekte kümmern sich nur um das Cachen der Komponenten. (muss man nicht machen, kann man aber :) )

CG2003 26. Sep 2006 08:15

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Ich weiss, es ist wahrscheinlich zuviel verlangt, aber wärst Du so nett, mir ein kleines Beispiel zu geben?
Irgendwie habe ich momentan in meinem Code wohl den Wurm drin und ich finde einfach nicht die Ursache, warum es nicht läuft.

Ich will doch nur Komponenten umbenennen, wenn sie auf einem Form platziert werden.

Es wäre jedenfalls sehr nett von Dir und ich wäre Dir sehr dankbar.

chaosben 26. Sep 2006 10:13

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Liste der Anhänge anzeigen (Anzahl: 1)
Anbei hab ich deinen Code ein wenig umgestrickt. Leider hab ich in meiner Arbeitswut vergessen an die entsprechenden Zeilen Kommentare zu schreiben. Sorry :(

CG2003 26. Sep 2006 10:58

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von chaosben
Anbei hab ich deinen Code ein wenig umgestrickt. Leider hab ich in meiner Arbeitswut vergessen an die entsprechenden Zeilen Kommentare zu schreiben. Sorry :(

Super, vielen Dank! Das funktioniert einwandfrei! Glaub' mir, ich bin Dir sehr dankbar!

chaosben 26. Sep 2006 11:05

Re: Komponente vor dem Platzieren umbenennen / OpenTools API
 
Zitat:

Zitat von CG2003
Super, vielen Dank! Das funktioniert einwandfrei! Glaub' mir, ich bin Dir sehr dankbar!

:-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:57 Uhr.

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