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/)
-   -   Möchte TPanel mit Image von ImageList koppeln (https://www.delphipraxis.net/174203-moechte-tpanel-mit-image-von-imagelist-koppeln.html)

Jumpy 9. Apr 2013 11:17

Möchte TPanel mit Image von ImageList koppeln
 
Hallo,

ich möchte ein eigenes Panel erstellen, das optisch wie z.B. ein BitBtn aufgebaut ist: Links ein Icon und daran anschließend eine Caption. Das Icon soll zur Laufzeit änderbar sein und ich könnte mir vorstellen, die Icons in einer ImageList zu verwalten, diese dem Panel zuzuweisen und über den ImageIndex zur Laufzeit das Icon zu ändern.

- Ginge die grundsätzliche Konstruktion oder kann man die Idee mit der Imagelist vergessen? Sollte man stattdessen jedes mal das Image von Irgendwoher laden?
- Wie bekommt man überhaupt ein Icon/Image auf das Panel? TImage erzeugen und auf dem Panel platzieren oder doch direkt als bmp o.ä. auf dem Panel direkt zeichenen, da ich ja eh eine eigenes Panel dafür ableite, könnte ich mir doch Zugriff auf den Canvas besorgen (hab in der DP schon für beides Threads gefunden, mein ich).
- Alle Icons sollen gleich groß sein, aber um deren Breite versetzt müsste ich doch den Text dann selber zeichnen. Gibt es sowas wie OwnerDraw für TPanel?

- Oder gibt es vllt. schon eine ähnliche Komponente? Hab mal bei Torry gesucht und ein paar ganze nette Panel-Erweiterungen gefunden wo ich mir vllt. auch was abgucken kann, aber nicht das, was mir hier vorschwebt.

DeddyH 9. Apr 2013 11:56

AW: Möchte TPanel mit Image von ImageList koppeln
 
TPanel verfügt bereits über eine Canvas-Property, man sieht die nur deshalb im Normalfall nicht, weil sie protected ist. Du kannst also auf Deiner Komponente herumzeichnen, wie Du magst.

stahli 9. Apr 2013 11:58

AW: Möchte TPanel mit Image von ImageList koppeln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also soll es eine eigene Komponente werden?
Anbei mal, wie ich das gelöst habe. Das TImage ignoriert einfach Mausereignisse (Hittest).

Die Zuweisung der Bilder kannst Du dann klassisch regeln (in meinem Fall werden die Daten über ein Framework geholt).

Von Deinem Panel kannst Du die Methode Paint überschreiben und an Deine Bedürfnisse anpassen (im Grunde nur den Platz für den Text ändern) oder rechts einfach ein Label einsetzen und dort den Text zuweisen.
Ok da stellt sich sich die gleiche Frage wieder.

Ist halt die Frage, wie oft Du dieses Panel brauchst und wo die Daten herkommen bzw. wie diese zugewiesen werden.

Bummi 9. Apr 2013 12:10

AW: Möchte TPanel mit Image von ImageList koppeln
 
ganz kurz angerissen

Delphi-Quellcode:
unit Unit2;

interface

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

type
  TMyPanel=Class(TCustomPanel)
    Procedure Paint;override;
    private
      FImageList:TImageList;
    FImageIndex: Integer;
    procedure SetImageIndex(const Value: Integer);
    procedure SetImageList(const Value: TImageList);
    published
    Property ImageList:TImageList read FImageList Write SetImageList;
    Property ImageIndex:Integer Read FImageIndex Write SetImageIndex;

  End;

  TForm2 = class(TForm)
    ImageList1: TImageList;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TMyPanel }

procedure TMyPanel.Paint;
const
 C_LOFS=10;
var
 ico:TIcon;
 Toffs:Integer;
begin
 // inherited; nicht aufrufen
  Canvas.Brush.Color := clSilver;
  Canvas.FillRect(ClientRect);
  Toffs := C_LOFS;
  if Assigned(FImageList) and (FImageList.Count>ImageIndex )then
    try
      ico:=TIcon.Create;
      FImageList.GetIcon(ImageIndex,ico);
      Canvas.Draw(C_LOFS,(Height - FImageList.Height) div 2,ico);
      Toffs := Toffs +  FImageList.Width + 5;
    finally
       ico.Free;
    end;
  Canvas.TextOut(Toffs,(Height - Canvas.TextHeight('X')) div 2, Caption);
end;

procedure TMyPanel.SetImageIndex(const Value: Integer);
begin
  FImageIndex := Value;
  invalidate;
end;

procedure TMyPanel.SetImageList(const Value: TImageList);
begin
  FImageList := Value;
  invalidate;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
   With TMyPanel.Create(self) do
    begin
      Parent := Self;
      Caption := 'Mein Testpanel';
      Width := 200;
      Height := 50;
      Left := 50;
      Top := 50;
      Imagelist := IMagelist1;
      ImageIndex := 0;
    end;
end;

end.

Jumpy 9. Apr 2013 13:38

AW: Möchte TPanel mit Image von ImageList koppeln
 
Hallo und natürlich erstmal danke für's Antworten!
Warum ich gerne auf Canvas malen würde ist, damit ich so MouseOver/Click usw. direkt im Panel verarbeiten kann und nicht erst noch das darauf platzierte Image so umschreiben muss, dass es das ans Panel durchreicht. Hab glaub ich Beispiele gesehen, dass das auch geht, aber so ist's mir lieber.

stahlis odImage wäre glaub ich so was wie ich im obigen Satz meinte, wobei ich mich noch Frage, da TodImage von TodPanel abgeleitet ist, was ist an TodPanel interessant gegenüber TPanel.

Bummis "kurz angerissenes" sieht doch so aus, wie ich mir das gedacht habe, mal gucken, ob ich das nachvollzogen bekomme. Interessant da noch, das im Paint das inherited bewußt nicht aufgerufen wird. In den Beispielen, die ich z.B. auf Tory gefunden habe, wurde das drin gelassen und dann scheinbar noch was "dazugemalt".

Und dann noch eine andere Frage dazu: Wenn ich das Ganze erstmal nur für ein Projekt brauchen möchte und diesem nur die .Pas beilegen und die Panels nur zur Laufzeit erzeugen möchte, dann brauch ich doch diese RegisterComponents-Geschichte nicht, oder?

DeddyH 9. Apr 2013 13:51

AW: Möchte TPanel mit Image von ImageList koppeln
 
RegisterComponents ist nur für die Installation in die IDE (Komponentenpalette) zuständig, Du kannst die Komponente natürlich auch ohne Installation zur Laufzeit erzeugen und benutzen.

stahli 9. Apr 2013 14:42

AW: Möchte TPanel mit Image von ImageList koppeln
 
DeddyH erklärt das korrekt. :-)

Statt von einen TodPanel könntest Du von einem TPanel ableiten. TodPanel beinhaltet Erweiterungen bzgl. der Datenbindung.

Jumpy 15. Apr 2013 10:35

AW: Möchte TPanel mit Image von ImageList koppeln
 
Hallo,

hier jetzt mal mein fertiges TStatusPanel nach Bummis Anriss, danke aber auch an alle anderen.
- Man kann das Bild als Icon oder Bitmap malen
- Bei MausUp bekommt das Panel den Fokus
- Hintergrund und Font können anders gefärbt werden, wenn es den Fokus hat
- Man kann eine Rahmenfarbe und -Breite definieren
- Man kann eine zweite Rahmenfarbe definieren um das Panel zu "Highlighten".

Delphi-Quellcode:
unit uStatusPanel;

interface

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

type TImageMode = (Icon,Bitmap);

type
  TStatusPanel=Class(TPanel)
    Procedure Paint;override;
   private
     FOnMouseDown: TNotifyEvent;
     FImageList:TImageList;
     FImageIndex: Integer;
     FImageMode:TImageMode;
     FImageBorder:integer;
     FBorderSize:integer;
     FBackColor:TColor;
     FFontColor:TColor;
     FBorderColor:TColor;
     FShowBorder:Boolean;
     FHighColor:TColor;
     FFontHighColor:TColor;
     FBorderHighColor:TColor;
     FShowBorderHighlighted:Boolean;
     FActive:Boolean;
    procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
    procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
    procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
    procedure SetImageIndex(const Value: Integer);
    procedure SetImageList(const Value: TImageList);
    function GetBackColor: TColor;
    procedure SetBackColor(const Value: TColor);
    function GetBorderColor: TColor;
    function GetHighColor: TColor;
    function GetShowBorder: Boolean;
    procedure SetBorderColor(const Value: TColor);
    procedure SetHighColor(const Value: TColor);
    procedure SetShowBorder(const Value: Boolean);
    function GetBorderHighColor: TColor;
    procedure SetBorderHighColor(const Value: TColor);
    function GetShowBorderHigh: Boolean;
    procedure SetShowBorderHigh(const Value: Boolean);
    function GetBorderSize: integer;
    procedure SetBorderSize(const Value: integer);
    function GetFontColor: TColor;
    function GetFontHighColor: TColor;
    procedure SetFontColor(const Value: TColor);
    procedure SetFontHighColor(const Value: TColor);
   public
    constructor create(AOwner:TComponent); override;
   published
    Property ImageList:TImageList read FImageList Write SetImageList;
    Property ImageIndex:Integer Read FImageIndex Write SetImageIndex;
    Property ImageMode:TImageMode Read FImageMode Write FImageMode;
    Property ImageBorderSize:integer Read FImageBorder Write FImageBorder;
    Property BackGroundColor:TColor Read GetBackColor Write SetBackColor;
    Property HighlightColor:TColor Read GetHighColor Write SetHighColor;
    Property BorderColor:TColor Read GetBorderColor Write SetBorderColor;
    Property BorderSize:integer Read GetBorderSize Write SetBorderSize;
    Property BorderHighlightColor:TColor Read GetBorderHighColor Write SetBorderHighColor;
    Property FontColor:TColor Read GetFontColor Write SetFontColor;
    Property FontHighlightColor:TColor Read GetFontHighColor Write SetFontHighColor;
    Property ShowBorder:Boolean Read GetShowBorder Write SetShowBorder;
    Property ShowBorderHighlighted:Boolean Read GetShowBorderHigh Write SetShowBorderHigh;
  End;

implementation

{ TStatusPanel }

procedure TStatusPanel.CMFocusChanged(var Message: TCMFocusChanged);
begin
  if Message.Sender is TStatusPanel then
    FActive := Message.Sender = Self
  else
    FActive:=false;
  Repaint;
  inherited;
end;

constructor TStatusPanel.create(AOwner: TComponent);
begin
  inherited;
  FImageIndex:=-1;
  FImageBorder:=5;
  FBackColor:=clBtnFace;
  FHighColor:=clSilver;
  FBorderHighColor:=clRed;
  FBorderColor:=clBlack;
  FShowBorder:=False;
  FShowBorderHighlighted:=False;
  FActive:=false;
  FFontColor:=Font.Color;
  FFontHighColor:=Font.Color;
end;

function TStatusPanel.GetBackColor: TColor;
begin
  Result:=FBAckColor;
end;

function TStatusPanel.GetBorderColor: TColor;
begin
  Result:=FBorderColor;
end;

function TStatusPanel.GetBorderHighColor: TColor;
begin
  Result:=FBorderHighColor;
end;

function TStatusPanel.GetBorderSize: integer;
begin
  Result:=FBorderSize;
end;

function TStatusPanel.GetFontColor: TColor;
begin
  Result:=FFontColor;
end;

function TStatusPanel.GetFontHighColor: TColor;
begin
  Result:=FFontHighColor;
end;

function TStatusPanel.GetHighColor: TColor;
begin
  Result:=FHighColor;
end;

function TStatusPanel.GetShowBorder: Boolean;
begin
  Result:=FShowBorder;
end;

function TStatusPanel.GetShowBorderHigh: Boolean;
begin
  Result:=FShowBorderHighlighted;
end;

procedure TStatusPanel.Paint;
var
 ico:TIcon;
 btm:TBitmap;
 graph:TGraphic;
 Toffs:Integer;
begin
  // inherited; nicht aufrufen
  // Background:
  if FActive then
    Canvas.Brush.Color := HighlightColor
  else
    Canvas.Brush.Color := BackGroundColor;
  Canvas.FillRect(ClientRect);
  // Border:
  if ShowBorder or ShowBorderHighlighted then
  with Canvas do
  begin
    if ShowBorderHighlighted then
      Canvas.pen.color:=BorderHighlightColor
    else
    Canvas.pen.color:=BorderColor;
    Canvas.Pen.Width:=BorderSize;
    Canvas.moveto(0,0);
    Canvas.lineto(width-1,0);
    Canvas.lineto(width-1,height-1);
    Canvas.lineto(0,height-1);
    Canvas.lineto(0,0);
  end;

  // Image:
  Toffs := ImageBorderSize;
  if Assigned(FImageList) and (FImageList.Count>ImageIndex )then
    begin
    Case ImageMode of
      Icon:  begin
              ico:=TIcon.Create;
              FImageList.GetIcon(ImageIndex,ico);
              Canvas.Draw(Toffs,(Height - FImageList.Height) div 2,ico);
              ico.Free;
              end;
      Bitmap: begin
              btm:=TBitmap.Create;
              FImageList.GetBitmap(ImageIndex,btm);
              Canvas.Draw(Toffs,(Height - FImageList.Height) div 2,btm);
              btm.Free;
              end;
      end;
    Toffs := Toffs + FImageList.Width + Toffs;
    end;
  // Text ausgeben
  if FActive then
    Canvas.Font.Color:=FontHighlightColor
  else
    Canvas.Font.Color:=FontColor;
  Canvas.TextOut(Toffs,(Height - Canvas.TextHeight('X')) div 2, Caption);
end;

procedure TStatusPanel.SetBackColor(const Value: TColor);
begin
  FBackColor:=value;
  invalidate;
end;

procedure TStatusPanel.SetBorderColor(const Value: TColor);
begin
  FBorderColor:=value;
  invalidate;
end;

procedure TStatusPanel.SetBorderHighColor(const Value: TColor);
begin
  FBorderHighColor:=value;
  invalidate;
end;

procedure TStatusPanel.SetBorderSize(const Value: integer);
begin
  FBorderSize:=value;
end;

procedure TStatusPanel.SetFontColor(const Value: TColor);
begin
  FFontColor:=Value;
  invalidate;
end;

procedure TStatusPanel.SetFontHighColor(const Value: TColor);
begin
  FFontHighColor:=value;
  invalidate;
end;

procedure TStatusPanel.SetHighColor(const Value: TColor);
begin
  FHighColor:=value;
  invalidate;
end;

procedure TStatusPanel.SetImageIndex(const Value: Integer);
begin
  FImageIndex := Value;
  invalidate;
end;

procedure TStatusPanel.SetImageList(const Value: TImageList);
begin
  FImageList := Value;
  invalidate;
end;

procedure TStatusPanel.SetShowBorder(const Value: Boolean);
begin
  FShowBorder:=value;
  invalidate;
end;

procedure TStatusPanel.SetShowBorderHigh(const Value: Boolean);
begin
  FShowBorderHighlighted:=value;
  invalidate;
end;

procedure TStatusPanel.WMLButtonUp(var Message: TWMLButtonUp);
begin
  inherited;
  self.SetFocus;
  if Assigned(FOnMouseDown) then
    FOnMouseDown(Self);
end;

procedure TStatusPanel.WMRButtonUp(var Message: TWMRButtonUp);
begin
  inherited;
  self.SetFocus;
  if Assigned(FOnMouseDown) then
    FOnMouseDown(Self);
end;

end.


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