Einzelnen Beitrag anzeigen

ruedigeruwe

Registriert seit: 19. Okt 2006
7 Beiträge
 
Delphi 6 Enterprise
 
#1

Problem: ComboBox über 2.Unit wird nicht korrekt dargestellt

  Alt 7. Apr 2008, 13:18
Folgendes Problem:

Ich habe eine Hauptform (Form1) und möchte nun über eine ausgelagerte Unit eine modifizierte ComboBox TEnhComboBox bei Bedarf dynamisch auf die Form1 erstellen lassen. Zusätzlich wird dieser ComboBox ein DrawItem- Ereignis mitgeschickt, welches die Item-Inhalte "mehrspaltig" darstellt. Das erstellen und anzeigen der ComboBox- Inhalte funktioniert einwandfrei, hier aber nun mein Problem was mir zur Zeit den letzten Nerv raubt:

Beim erstellen der dynamischen ComboBox und dem Vorfüllen der Item-Werte wird ein DropwDown-Ereignis ausgelöst, damit die ComboBox via dem OnDrawItem initialisiert wird. Danach soll zB. jeweils ein entsprechender Datensatz via ItemIndex als Standard ausgewählt werden. Hier tritt mein Problem auf: Sobald ein ItemIndex ausgewählt ist und dieser zur nächsten dynamische ComboBox geht, welche das ItemIndex-Ereignis auslöst, wird bei der vorherigen ComboBox der ItemIndex herausgenommen und der DropDown-Pfeil mit einem weißen Balken übelagert (wahrscheinlich wird der Textbereich über den DropDown-Pfeil als Overlay gezogen). Wird dann wieder auf eine "fehlerhaft" gezeichnete ComboBox geklickt, so wird diese wieder "richtig" gezeichnet, bis man wieder auf die nächste ComboBox klickt.

Vielleicht hat einer eine Idee, die mir weiterhelfen könnte.

UNIT1-FORM1:
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;

    procedure ComboBoxDrawItem(Control: TWinControl;
                        Index: Integer; Rect: TRect; State: TOwnerDrawState);
    procedure Button1Click(Sender: TObject);
    procedure RunTimeEditClick(Sender:TObject);

  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

Type
  TEnhComboBox = Class (TComboBox)

    Private
      fTagParam : Integer;
      fComboBoxDrawn : Boolean;
    Protected

    Published
      Property TagParam: Integer read fTagParam write fTagParam;
      Property ComboBoxDrawn: Boolean read fComboBoxDrawn write fComboBoxDrawn default false;
  End;

const FeldTr : string[1] = '|';
      RowTr : string[1] = ';';
      CboWidth : integer = 400;

var
  Form1: TForm1;
  RunTimeCombo : array[0..100] of array[0..20] of TEnhComboBox;
  Sender1:^TObject; //Übergabe des SenderObjects via Zeiger, anders geht es nicht !!!
  RunTimeEditX1,RunTimeEditX2 : integer;

implementation

uses unit2;

{$R *.dfm}

procedure TForm1.RunTimeEditClick(Sender:TObject);
begin
  //der Sender wird via ZEIGER übergeben, da nur so der Sender in der Unit empfangen wird!!!
  Sender1:=@Sender;
  unit2.RunTimeEditClick;
                                              
end;

procedure TForm1.ComboBoxDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);

var
  x,pos1,AnzCol : integer;
  strVal, strAll: string;
  rc: TRect;
  arrWidth: array of Integer;

begin

  with RunTimeCombo[RunTimeEditX2,RunTimeEditX1] do
  begin
    Canvas.Brush.Style := bsSolid;
    Canvas.FillRect(Rect);
    //Anzahl der Spalten suchen
    AnzCol := 1;
    for x:=0 to length(RunTimeCombo[RunTimeEditX2,RunTimeEditX1].Items[index]) do
      if copy(RunTimeCombo[RunTimeEditX2,RunTimeEditX1].Items[index],x,1)=FeldTr then inc(AnzCol);

    //Spaltenarray anlegen
    //wichtig: hier wird eine Zeile mehr angelegt, da diese benötigt wird
    //um die abschließende Breite zu setzen
    SetLength(arrWidth,AnzCol+1);

    //Spaltenarray aufteilen
    for x:=0 to AnzCol -1 do
      arrWidth[x] := 0+((CboWidth div AnzCol)*x);

    //Wichtig: abschließende Breite setzen
    arrWidth[AnzCol] := CboWidth;

    //aktuellen ArrayString des jeweiligen Index übergeben
    strAll := RunTimeCombo[RunTimeEditX2,RunTimeEditX1].Items[Index];

    rc.Top := Rect.Top;
    rc.Bottom := Rect.Bottom;

    for x:=0 to AnzCol-1 do
    begin
      // Zeichenbereich für die einzelnen Spalten anlegen
      rc.Left := Rect.Left + arrWidth[x] + 2;
      rc.Right := Rect.Left + arrWidth[x+1] - 2;

      // Text für die jeweilige Spalte ausfiltern
      pos1 := Pos(FeldTr, strAll);
      if pos1 > 0 then
        strVal := Copy(strAll, 1, pos1 - 1)
      else
        strVal := strAll;

      strAll := Copy(strAll, pos1 + 1, Length(strAll) - pos1);
      // Text ausgeben
      Canvas.TextRect(rc, rc.Left, rc.Top, strVal);
      // Trennlinie zwischen Spalten zeichnen
      Canvas.MoveTo(rc.Right, rc.Top);
      Canvas.LineTo(rc.Right, rc.Bottom);
    end;
  end;


end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  unit2.ButtonsErstellen(Form1);
end;

end.
UNIT2-DYNAMISCHES ERZEUGEN DER COMBOBOX AUF FORM1
Delphi-Quellcode:
unit Unit2;

interface

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

procedure ButtonsErstellen(Sender:TObject);
procedure RunTimeEditClick;

implementation

uses unit1;


procedure RunTimeEditClick;
var Sender1:TObject;

begin

  Sender1 := unit1.Sender1^;

  if sender1.ClassName = 'TEnhComboBoxthen
  begin
    RunTimeEditX2 := (Sender1 as TEnhComboBox).TagParam;
    RunTimeEditX1 := (Sender1 as TEnhComboBox).Tag-1;
  end;


end;


procedure ButtonsErstellen(Sender:TObject);
var xEdit,x,hoehe,edtLaenge : integer;

begin
  x := 0;
  hoehe := 20;
  edtLaenge := 100;

  for xEdit := 0 to 2 do
  begin
    RunTimeCombo[xEdit,x] := TEnhComboBox.Create(Form1);
    with RunTimeCombo[xEdit,x] do
    begin
      Parent := Form1;
      Style := csOwnerDrawFixed;
      Top := (Hoehe+2) + (45*(x+1));
      Tag := x+1;
      TagParam := xEdit;
      Width := edtLaenge;
      Left := 160 + ((edtLaenge+5)*(xEdit));
      enabled:= true;
      visible := true;
      RunTimeCombo[xEdit,x].Items.Add('A|AAAA'+inttostr(xEdit));
      RunTimeCombo[xEdit,x].Items.Add('B|BBBB'+inttostr(xEdit));
      RunTimeCombo[xEdit,x].Items.Add('C|CCCC'+inttostr(xEdit));

      OnDrawItem := Form1.ComboBoxDrawItem;
      OnDropDown := Form1.RunTimeEditClick;

      if unit1.RunTimeCombo[xEdit,x].Items.Count > 0 then
      begin
        unit1.RunTimeCombo[xEdit,x].Perform(CB_SETDROPPEDWIDTH,400,0);
        unit1.RunTimeCombo[xEdit,x].DroppedDown := true;
        unit1.RunTimeCombo[xEdit,x].DroppedDown := false;

        unit1.RunTimeCombo[xEdit,x].ItemIndex := 0;
      end;
    end;
  end;
end;

end.
Uwe R.
  Mit Zitat antworten Zitat