2
Tags:
delphi
Skrevet af
Bruger #58
@ 17.06.2001
Få TCustomControl over udseendet
I denne artikel vil jeg beskrive forskellige måder at tegne sine egne kontroller på, og hvordan du ved hjælp af Windows API'et kan komme til at tegne overalt på kontrollen.
En af de ting der er vigtige for at en kontrol ser "Windows-agtig" ud er, at den bruger de rigtige farver til 3D, og bruger dem de rigtige steder. Først:
Eksempel: Sådan kan du finde 3D farverne
{ Dette eksempel kræver en form med fire TShape på.
Disse shapes skal alle være 1 pixel tynde, og være
placeret så de danner en boks. Kald dem shTop,
shBottom, shLeft og shRight efter hvor de er
placeret. }
procedure TForm1.FormCreate(Sender: TObject);
begin
shTop.Pen.Color := clBtnHighlight;
shBottom.Pen.Color := clBtnShadow;
shLeft.Pen.Color := clBtnHighlight;
shRight.Pen.Color := clBtnShadow;
end;
Resultat: En hævet boks. Det samme kunne være lavet meget nemmere med en TBevel. Det vigtigste er dog at lære hvordan du kan finde de rigtige farver, og bruge dem rigtigt. Men videre til noget andet: En mere avanceret API funktion.
Eksempel: DrawEdge API'et
{ Sæt både OnPaint og OnResize for formen til denne event }
procedure TForm1.MakeBorder(Sender: TObject);
var
BRect: TRect;
begin
BRect := ClientRect;
Canvas.Brush.Color := clWindow;
Canvas.FillRect(BRect);
DrawEdge(Canvas.Handle, BRect, EDGE_SUNKEN, BF_RECT);
end;
Resultat: Et vindue med ramme inderst. Uden brug af komponenter, og med kun 4 liniers kode. Og så videre til noget mere avanceret igen: Tegn din egen vinduesramme på formen. Her er en komplet unit fyldt med kommentarer:
Eksempel: En ny type ramme til vinduet
unit CustomBorderFormUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TCustomBorderForm = class(TForm)
// Husk at sætte OnPaint til FormPaint.
// Det er også en god ide at sætte OnResize til OnPaint.
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
// En "handler" til Windows messagen WM_NCPAINT, eller
// "Window Message Non-Client Paint"
procedure WMNCPaint(var Msg: TMessage); message WM_NCPAINT;
public
{ Public declarations }
end;
var
CustomBorderForm: TCustomBorderForm;
implementation
{$R *.DFM}
procedure TCustomBorderForm.WMNCPaint(var Msg: TMessage);
var
// NCCanvas = Non-CLient canvas
NCCanvas: TCanvas;
// DrawEdge kræver at det er en variabel du giver den.
// Den vil ikke nøjes med at property.
BR: TRect;
begin
// Lav et nyt canvas
NCCanvas := TCanvas.Create;
// Tildel det hele vinduets HDC (Handle Drawing Canvas)
NCCanvas.Handle := GetWindowDC(Handle);
// BoundsRect kan ikke bruges, den giver koordinter i forhold
// til skærmen
BR := Rect(0, 0, Width, Height);
// Tegn en kant rundt om formen, en lidt speciel kant
DrawEdge(NCCanvas.Handle, BR, EDGE_ETCHED, BF_RECT);
// Gør rektangler 2 pixels mindre i alle retninger
InflateRect(BR, -2, -2);
// Tegn to Button Face farvede raktangler inden i rammen
NCCanvas.Brush.Color := clBtnFace;
NCCanvas.FrameRect(BR);
InflateRect(BR, -1, -1);
NCCanvas.FrameRect(BR);
// Tegn en linie under titellinien
NCCanvas.Pen.Color := clBtnFace;
NCCanvas.PenPos := Point(2, GetSystemMetrics(SM_CYSIZE)+4);
NCCanvas.LineTo(Width - 2, NCCanvas.PenPos.y);
// Lav et rektangel der er lidt højere end den normale
// titellinie
BR := Rect(2, 2, Width-2, GetSystemMetrics(SM_CYSIZE)+4);
// Tegn rektanglet med InfoTip baggrunds farven. Specielt udseende.
NCCanvas.Brush.Color := clInfoBk;
NCCanvas.FillRect(BR);
// Også en anderledes font. Verdana med InfoText farve.
NCCanvas.Font.Color := clInfoText;
NCCanvas.Font.Style := [fsBold];
NCCanvas.Font.Name := 'Verdana';
// Dette er i stedet for at sætte Font.Size. Giver et bedre resultat.
NCCanvas.Font.Height := GetSystemMetrics(SM_CYSIZE);
// Endnu mere API. Denne gang til at tegne tekst på en speciel måde.
DrawText(NCCanvas.Handle, PChar(Caption), Length(Caption), BR,
DT_CENTER or DT_END_ELLIPSIS);
// Frigiv tegneoverfladen og kanvasset
ReleaseDC(Handle, NCCanvas.Handle);
NCCanvas.Free;
// Fortæl Windows at vi har behandlet beskeden
Msg.Result := 0;
end;
procedure TCustomBorderForm.FormPaint(Sender: TObject);
begin
// Ekstra forsikring for at vores egen ramme bliver tegnet rigtigt
Perform(WM_NCPAINT, 0, 0);
end;
end.
Resultat: Et helt anderledes vindue. Denne metode kan bruges til alle kontroller der har et vindue. For at vise det, har jeg lavet et TPanel med en ny slags ramme. Det hedder TStrangePanel og ligger i Download sektionen her på Udvikleren. Det bruger denne metode til at få en lignende ramme når det er sat til Ctl3D=True og BorderStyle=bsSingle.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (1)
God artikel - men , men , men ...
Der måtte gerne være lidt mere forklaring -
Ellers flot og god til at 'gejle' ens forme med.
Du skal være
logget ind for at skrive en kommentar.