Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 21.02.09 16:38 
Ich bastle gerade an einem TSkinButton rum. Basis ist der Colorbutton von hier.

Über
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TSkinButton.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do Style := Style or BS_OWNERDRAW;
end;
wird geregelt, dass der Button selbst gezeichnet werden kann. Ich würde das gerne zur Laufzeit ändern können, um dadurch den Skin an bzw. auszuschalten.
Oder, wenn das nicht geht - wie erreiche ich in der Zeichenroutine
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TSkinButton.CNDrawItem(var Message: TWMDrawItem);
var
  SaveIndex: Integer;
begin
    with Message.DrawItemStruct^ do
    begin
      SaveIndex := SaveDC(hDC);
      FCanvas.Lock;
      try
        FCanvas.Handle := hDC;
        FCanvas.Font := Font;
        FCanvas.Brush := Brush;
        DrawButton(rcItem, itemState);
      finally
        FCanvas.Handle := 0;
        FCanvas.Unlock;
        RestoreDC(hDC, SaveIndex);
      end;
    end;
    Message.Result := 1;
end;
, dass die Windows-eigene Zeichenroutine aufgerufen wird? Damit der Button wieder wie ein normaler Button aussieht?

_________________
We are, we were and will not be.


Zuletzt bearbeitet von Gausi am Mo 23.02.09 13:05, insgesamt 1-mal bearbeitet
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 23.02.09 12:18 
Keiner ne Idee? :(

_________________
We are, we were and will not be.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19276
Erhaltene Danke: 1741

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 23.02.09 13:09 
Meiner Meinung nach ist das nicht möglich. Da ich mir da aber nicht 100%ig sicher bin, hatte ich mich erstmal der Stimme enthalten. ;-)

Wenn, dann müsste das ja mit SetWindowLongPtr gehen, eine andere Idee hätte ich da nicht, aber das hatte ich glaube ich ausprobiert.

Ich denke da müsstest du den Button neu erstellen. So habe ich das übrigens auch mal gemacht. Um genau zu sein hatte ich innerhalb der Komponente den eigentlichen Button nochmal darin erstellt. So konnte ich diese Logik etwas verallgemeinern, so dass ich das nicht für jede Komponente neu machen musste.
Eigentlich wollte ich das auch noch auf meine Gradient Components ausdehnen, aber bei denen bin ich ja noch nicht mal zu Farbschemata gekommen bisher.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 23.02.09 13:21 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Meiner Meinung nach ist das nicht möglich.

Sowas hatte ich fast befürchtet.

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ich denke da müsstest du den Button neu erstellen. So habe ich das übrigens auch mal gemacht. Um genau zu sein hatte ich innerhalb der Komponente den eigentlichen Button nochmal darin erstellt.
Ich bin nicht ganz so fit in der Komponenten-Entwicklung - könntest du da mal ein Stück Code posten, auf das ich dann aufbauen kann?
Heisst das, dass der Vorfahrtyp der Komponente einfach TComponent ist, mit einer Property vom Typ TButton, die je nach Property "FullSkin" so oder so gestaltet wird?

_________________
We are, we were and will not be.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19276
Erhaltene Danke: 1741

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 23.02.09 14:44 
Ja, nicht von TComponent, aber so meinte ich das.

Ich hab mal schnell ne kleine Demo zusammengefrickelt, nur Caption und SetBounds wird derzeit weitergeleitet, die restlichen Properties müssten alle noch entsprechend implementiert werden, aber es zeigt, dass das so funktioniert.

Eine CheckBox schaltet zwischen Skinned ColorButton und Standard Themed um, der linke Button ist ein normaler Button. Wobei ich zumindest hier unter Vista den ColorButton als normalen Button sehe, aber ich hatte auch grad keine Lust mir das genauer anzuschauen was da passiert, also im ColorButton. ;-)
Einloggen, um Attachments anzusehen!
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 23.02.09 16:26 
Ah ja, danke. :D

Das mit TWinControl als Vorfahrtyp ist mir auch schon eingefallen - sonst sind ja auch die Basis-Eigenschaften wie Width und Height erstmal unbekannt.
Das funktioniert soweit ganz gut, auch mit TBitBtn anstelle von TButton (denn so brauche ich das eigentlich). Gut, jetzt habe ich etwas stupide Arbeit vor mir, aber das sollte schaffbar sein. Unter Vista sieht das mit meinem Demoprojekt auch so aus, wie ich es erwarten würde.

_________________
We are, we were and will not be.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19276
Erhaltene Danke: 1741

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 23.02.09 17:19 
user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Gut, jetzt habe ich etwas stupide Arbeit vor mir, aber das sollte schaffbar sein.
Das lässt sich ja relativ gut automatisieren. Zuerst Variablennamen bei Read/Write hinschreiben / kopieren, das geht per Makro, dann Strg + Shift + C, jetzt hast du die. Dann statt dem F am Anfang Get/Set für Getter / Setter, Strg + Shift + C, fertig. Dann noch überall eintragen.

Ich glaube das geht so auch ohne Plugins bei D2006 / TD. Ganz automatisch geht das nur, wenn ich irgendwann mal zu meinem Code Assistenten komme...
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 23.02.09 20:34 
Das geht viel einfacher: If-Abfrage o.ä. in TSkinButton.CreateParams einbauen und zum Wechseln TSkinButton.RecreateWnd aufrufen.
Garf
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 54
Erhaltene Danke: 2


D3Prof, D7PE, TDE
BeitragVerfasst: Di 24.02.09 09:49 
Wenn der Button kein Handle haben muss, würde sich ein TSpeedbutton als Grundlage anbieten.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 24.02.09 10:16 
Der Speedbutton bringt mir nichts, da ich den Button auch per Tastatur ansteuern möchte. Deswegen mach ich das ganze ja: Bei meinem Player sind die ganzen Buttons im Skin-Modus einfach nur TImages, im normalen Modus (und im alten Skinmodus) TBitBtns. Das schalte ich recht umständlich im Code um.
Ich würde das jetzt gerne möglichst abwärtskompatibel einfacher lösen. Und da ist der Workaround von jaenicke glaube ich am Besten geeignet. Wenn ich das Umschalten zwischen BitBtn und Skinbutton in der Komponente erledigen lasse, kann ich den Rest des Codes vereinfachen und übersichtlicher gestalten.

@Delfiphan: Das hört sich auch sehr gut, ist aber für meine Zwecke doch ungeeignet, wie sich mittlerweie herausgestellt hat. Als "Standard-Button" brauche ich den BitBtn, und der hat dieselben CreateParams. Da die Zeichenroutine von BitBtn aber als Private deklariert ist, kann ich die nicht überschreiben oder aufrufen, und den Code aus Delphi2007 in das Delphi7-Projekt zu kopieren dürfte erstens nicht ganz legal sein und funktioniert zweitens nicht, da in D7 eine Unit fehlt, die der neue Source braucht. Die Alternative wäre natürlich, endlich mal auf D2007 umzusteigen, aber da will ich jetzt durch. ;-)

_________________
We are, we were and will not be.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Di 24.02.09 11:44 
TBitBtn ist auch nur von TButton abgeleitet. Schreib doch deine eigene private CNDrawItem message-Methode. Dort zeichnest du dann den Button entweder selbst oder rufst inherited auf. Bei message-Methoden geht das.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19276
Erhaltene Danke: 1741

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 24.02.09 11:51 
Inherited bringt doch auch nicht den Standardbutton zur Anzeige, oder? :gruebel:
Schließlich muss für das Auslesen BS_OWNERDRAW gesetzt sein, das verhindert aber gleichzeitig das normale Zeichnen des Buttons.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 24.02.09 11:57 
Da ich den Standard-Button eh nicht gebrauchen kann, sondern halt doch den BitBtn, könnte das funktionieren. Und wenn ich mir das hier so durchlese, bin ich da sehr zuversichtlich. :D

Ich denke, so langsam lichtet sich der Nebel. :lupe:

_________________
We are, we were and will not be.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Di 24.02.09 16:47 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Inherited bringt doch auch nicht den Standardbutton zur Anzeige, oder? :gruebel:
Schließlich muss für das Auslesen BS_OWNERDRAW gesetzt sein, das verhindert aber gleichzeitig das normale Zeichnen des Buttons.

Beim Standardbutton müsste meine erste Lösung funktionieren (Window-Handle wird neu erstellt, mit geänderten Einstellungen). Beim TBitBtn meine zweite (es wird immer Ownerdraw verwendet, aber je nachdem ob inherited aufgerufen wird oder nicht wird per VCL gezeichnet oder über seine eigene Draw-Methode). Die 2 Lösungen sind nicht austauschbar.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 24.02.09 20:03 
Sehr schön. Das klappt, und vereinfacht die ganze Sache ganz erheblich. :D

War zwar ne schwere Geburt, aber jetzt ist der Weg wohl klar, wie ich damit weiter verfahren muss. Z.B. möchte ich die Glyphs mehrzeilig machen, damit man den Play/Pause-Button einfacher handhaben kann - anstelle ein neues Glyph zuzuweisen, ändere ich nur den "Glyphstatus", und der Button macht den Rest von alleine.

Danke euch beiden. :flehan:

_________________
We are, we were and will not be.