Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Combobox mit tag (https://www.delphipraxis.net/76151-combobox-mit-tag.html)

StTüff 30. Aug 2006 17:14


Combobox mit tag
 
Hallo zusammen!

Ich würde gerne mit jedem Eintrag in einer Combobox einen Integerwert abspeichern.
Mir ist klar, dass ich jedem Eintrag ein Objekt zuordnen kann. Da ich aber nur einen simplen Integerwert benötige, habe ich mir gedacht: Das Tolle an Objektorientierung ist, dass ich mir meine TaggedKombobox selbst bauen kann. :thumb:
Ich hab dann mal mit so was
Delphi-Quellcode:
TTaggedStrings = class (TStrings)

end;

TTaggedComboBox = class(TComboBox)
  Items:TTaggedStrings;
 
end;
angefangen, aber leider fehlt mir der Plan, wie ich jetzt jedem String einen Integerwert (tag) anhängen kann.

Natürlich kann ich doch auf die "Objektanhängvariante" ausweichen. Mich würde aber die Lösung auf diese Art interessieren. Kann mir da jemand auf die Sprünge helfen?

Gruß,

StTüff

mkinzler 30. Aug 2006 17:38

Re: Combobox mit tag
 
Delphi-Quellcode:
TTaggedStrings = class (TStrings)
  private
    FTag: Integer;
  published
    Tag: Integer read FTag write FTag;
  public
    constructor Create;
end;

Neutral General 30. Aug 2006 17:43

Re: Combobox mit tag
 
naja ich schätze er will die Strings der ComboBox durch seine Tag-Strings ersetzen so das er dann das ganze so aufrufen kann:

Delphi-Quellcode:
Combobox.Strings[x].Tag
Ehm glaube ich zumindest.. Aber das dürfte unmöglich sein so wie ichs verstehe

Gruß
Neutral General

mkinzler 30. Aug 2006 17:46

Re: Combobox mit tag
 
Zitat:

naja ich schätze er will die Strings der ComboBox durch seine Tag-Strings ersetzen
Glaube ich nicht:
Zitat:

wie ich jetzt jedem String einen Integerwert (tag) anhängen kann.

Neutral General 30. Aug 2006 17:47

Re: Combobox mit tag
 
Genau diese Zeile verstehe ich so wie ich schon gesagt habe :mrgreen:

mkinzler 30. Aug 2006 17:55

Re: Combobox mit tag
 
Er wird sich sicherlich wieder melden und uns dann aufklären, wie er es gemeint hat ;-)

Flocke 30. Aug 2006 18:06

Re: Combobox mit tag
 
Zitat:

Zitat von StTüff
Mir ist klar, dass ich jedem Eintrag ein Objekt zuordnen kann.

Du könntest es einfach so machen:
Delphi-Quellcode:
  // Schreiben
  Strings.Objects[idx] := Pointer(Wert);
  // Auslesen
  Wert := Integer(Strings.Objects[idx]);
Das Problem bei deiner Idee ist, dass die ComboBox dir zwar ein TStrings-Interface gibt, intern aber eine eigene Implementierung dieser abstrakten Klasse verwendet. Die kannst du so einfach nicht erweitern. Komponenten, bei denen das vorgesehen ist, benutzen eine virtuelle Klassenfunktion zur Ermittlung der eigentlichen Klasse der nehmen ein Ereignis dafür (z.B. TTreeView.OnCreateNodeClass).

// NACHTRAG!!!

Habe gerade gesehen, dass das bei TComboBox sogar schon vorgesehen ist! Du musst dafür GetItemsClass überschreiben:
Delphi-Quellcode:
  protected
    // ...
    function GetItemsClass: TCustomComboBoxStringsClass; virtual; abstract;

pszopp 30. Aug 2006 20:59

Re: Combobox mit tag
 
Hallo,

Delphi-Quellcode:
procedure InsertData(const aStr : String; aValue : Integer);
begin
  ComboBox1.Items.AddObject(aStr, TObject(aValue));
end;

function GetValue(aIdx : Integer) : Integer;
begin
  Result := Integer(ComboBox1.Items.Objects[aIdx]);
end;
So würde ich es programmieren.

Gruß,
pszopp

StTüff 31. Aug 2006 07:04

Re: Combobox mit tag
 
Hallo @all!

Erst mal vielen Dank für die vielen Antworten!

Noch mal zur Erklärung:
Ich hatte mir den Zugriff so vorgestellt:
Delphi-Quellcode:
 MyCombobox.Items[X].tag := EinIntegerWert;
Da "MyCombobox.Itemx[x]" aber vom Typ TStrings ist, dachte ich, dass ich hier ansetzen und einfach für jeden enthaltenen String noch einen "Tag" hinzufügen kann.

Zunächst ein mal habe ich jetzt aber registriert, dass die meisten es über die "Objektlösung" versuchen würden.
Ich habe es auch so gelöst. Ich würde aber gerne noch mal den Ansatz von Volker weiterverfolgen, da ich so was noch nie gemacht habe und gerne an diesem Beispiel etwas dazulernen möchte.

Volker schreibt:
Zitat:

Komponenten, bei denen das vorgesehen ist, benutzen eine virtuelle Klassenfunktion zur Ermittlung der eigentlichen Klasse der nehmen ein Ereignis dafür (z.B. TTreeView.OnCreateNodeClass).

// NACHTRAG!!!

Habe gerade gesehen, dass das bei TComboBox sogar schon vorgesehen ist! Du musst dafür GetItemsClass überschreiben:
Delphi-Quellcode:
protected
    // ...
    function GetItemsClass: TCustomComboBoxStringsClass; virtual; abstract;

Ich werde das mal versuchen (auch wenn ich noch keinen Plan habe wie das geht) und mich dann noch mal melden.

Wenn mir zwischenzeitlich jemand einen Vorschlag für die Unsetzung machen möchte - Ich höre gerne zu ;-)

Gruß und noch mal vielen Dank an alle!

StTüff

StTüff 31. Aug 2006 07:43

Re: Combobox mit tag
 
....so, ich möchte gerne über meine ersten Schritte berichten, damit Ihr mich gleich bremsen könnt, wenn ich was falsch mache.

So weit bin ich bis jetzt gekommen:
Delphi-Quellcode:
unit TaggedCoBo;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, StdCtrls;

type
  TTaggedComboBox = class(TComboBox)
  private
    { Private declarations }
  protected
    { Protected declarations }
    function GetItemsClass: TCustomComboBoxStringsClass; override;
  public
    { Public declarations }
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('My_Components', [TTaggedComboBox]);
end;

function TTaggedComboBox.GetItemsClass: TCustomComboBoxStringsClass;
begin
  //Hier sollte ich jetzt wohl was machen ;-)

  inherited;
end;

end.
OK, da steckt inhaltlich noch nicht viel drin, ich bin mir aber trotzdem schon unsicher, ob das alles so passt. :gruebel:

Gruß,

StTüff

Flocke 31. Aug 2006 07:57

Re: Combobox mit tag
 
Zitat:

Zitat von StTüff
Ich werde das mal versuchen (auch wenn ich noch keinen Plan habe wie das geht) und mich dann noch mal melden.

Wenn mir zwischenzeitlich jemand einen Vorschlag für die Unsetzung machen möchte - Ich höre gerne zu ;-)

Du solltest dir in der Datei StdCtrls.pas die Klassen TCustomComboBoxStrings und TComboBoxStrings ansehen (sofern du ein Delphi mit Quelltexten hast). Die müsstest du nach deinen Wünschen erweitern und dann diese Klasse in TTaggedComboBox.GetItemsClass zurückgeben.

Allerdings solltest du bedenken, dass TComboBox nur eine objektorientierte Kapselung für die normale Windows-ComboBox ist und ein TCustomComboBoxStrings-Objekt die Elemente nicht beinhaltet sondern nur verwaltet. Dazu gehört auch ein 32-Bit-Wert mit anwendungsspezifischen Daten je Eintrag, und der wird von Delphi eben für die Eigenschaft Objects "missbraucht".

StTüff 31. Aug 2006 08:03

Re: Combobox mit tag
 
Hallo Volker!

Ich habe eben schon den StdCtrls durchsucht. Das mit dem Erweitern von TComboBoxStrings war nun der entscheidende Hinweis. Ich glaube jetzt komme ich weiter.

Vielen Dank!

StTüff

StTüff 31. Aug 2006 08:33

Re: Combobox mit tag
 
Was meint Ihr dazu:

Delphi-Quellcode:
unit TaggedCoBo;

interface

uses
  Windows, Messages, SysUtils, Consts, Classes, Controls, StdCtrls;

type
  TTaggedComboBox = class(TComboBox)
  private
    { Private declarations }
  protected
    { Protected declarations }
    function GetItemsClass: TCustomComboBoxStringsClass; override;
  public
    { Public declarations }
  published
    { Published declarations }
  end;

  TTaggedComboBoxStrings = class (TCustomComboBoxStrings)
  public
    function Addnew(const S: string; tag: integer): Integer;
    //Insert ist noch nicht berücksichtigt....
    procedure Insert(Index: Integer; const S: string); override;
    function GetTag (idx: integer): integer;
  private
    TagArray: array of integer;
    function Add(const S: string): Integer; override;
  end;


procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('MyComponents', [TTaggedComboBox]);
end;

function TTaggedComboBox.GetItemsClass: TCustomComboBoxStringsClass;
begin
  //Hier die Modifizierte Stringklasse zurückgeben
  Result := TTaggedComboBoxStrings;
  //inherited;
end;

function TTaggedComboBoxStrings.Addnew(const S: string; tag: integer): Integer;
begin
  //Den Tag verwalten
  //String in das Array an der letzten Position einfügen
  SetLength(TagArray, high(TagArray)+1);
  TagArray[high(TagArray)];
  //Das eigentliche Add aufrufen
  Result:=Add(S);
end;

function TTaggedComboBoxStrings.GetTag (idx: integer): integer;
begin
  if idx <= high(TagArray) then
    Result:=TagArray[idx];
end;

function TTaggedComboBoxStrings.Add(const S: string): Integer;
begin
  Result := SendMessage(ComboBox.Handle, CB_ADDSTRING, 0, Longint(PChar(S)));
  if Result < 0 then
    raise EOutOfResources.Create(SInsertLineError);
end;

procedure TTaggedComboBoxStrings.Insert(Index: Integer; const S: string);
begin
  if SendMessage(ComboBox.Handle, CB_INSERTSTRING, Index,
    Longint(PChar(S))) < 0 then
    raise EOutOfResources.Create(SInsertLineError);
end;

end.
Mal abgesehen davon, dass "Insert" noch nicht berücksichtigt ist, könnte es doch in der Art gehen, oder?
(Ist noch nicht getestet...)

Gruß,

StTüff


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:17 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