File: HeaderCustomDrawDemo.pas

package info (click to toggle)
lazarus 4.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 275,760 kB
  • sloc: pascal: 2,341,904; xml: 509,420; makefile: 348,726; cpp: 93,608; sh: 3,387; java: 609; perl: 297; sql: 222; ansic: 137
file content (311 lines) | stat: -rw-r--r-- 10,619 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
unit HeaderCustomDrawDemo;

{$MODE Delphi}
{$H+}

// Virtual Treeview sample form demonstrating following features:
//   - Advanced header custom draw.
// Written by Mike Lischke.

interface

uses
  LCLIntf, Laz.VTGraphics, Types, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, Laz.VirtualTrees, StdCtrls, ExtCtrls, LCLType, LCLProc;

type
  THeaderOwnerDrawForm = class(TForm)
    Label8: TLabel;
    HeaderCustomDrawTree: TLazVirtualStringTree;
    HeaderImages: TImageList;
    AnimationTimer: TTimer;
    procedure HeaderCustomDrawTreeHeaderDrawQueryElements(Sender: TVTHeader; var PaintInfo: THeaderPaintInfo;
      var Elements: THeaderPaintElements);
    procedure HeaderCustomDrawTreeAdvancedHeaderDraw(Sender: TVTHeader; var PaintInfo: THeaderPaintInfo;
      const Elements: THeaderPaintElements);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure AnimationTimerTimer(Sender: TObject);
    procedure HeaderCustomDrawTreeHeaderMouseUp(Sender: TVTHeader; Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer);
    procedure HeaderCustomDrawTreeHeaderMouseDown(Sender: TVTHeader; Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer);
    procedure HeaderCustomDrawTreeStateChange(Sender: TBaseVirtualTree; Enter, Leave: TVirtualTreeStates);
    procedure HeaderCustomDrawTreeGetText(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
      var CellText: String);
  private
    FBackBitmap1,
    FBackBitmap2,
    FCheckerBackground: TBitmap;
    FHeaderBitmap: TBitmap;
    FLeftPos: Integer;
    procedure CreateCheckerBackground;
    procedure PaintSelection(Bitmap: TBitmap);
    procedure FillBackground(R: TRect; Target: TCanvas);
  end;

var
  HeaderOwnerDrawForm: THeaderOwnerDrawForm;

//----------------------------------------------------------------------------------------------------------------------

implementation

{$R *.lfm}

uses
  States, LclExt;


//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.HeaderCustomDrawTreeHeaderDrawQueryElements(Sender: TVTHeader;
  var PaintInfo: THeaderPaintInfo; var Elements: THeaderPaintElements);

// This event tells the tree which part we want to draw ourselves. Don't forget to enable custom drawing in the header
// options and switch the Style property of every column, which we handle here to vsOwnerDraw.

begin
  with PaintInfo do
  begin
    // First check the column member. If it is NoColumn then it's about the header background.
    if Column = nil then
      Elements := [hpeBackground] // No other flag is recognized for the header background.
    else
    begin
      // Using the index here ensures a column, regardless of its position, always has the same draw style.
      // By using the Position member, we could make a certain column place stand out, regardless of the column order.
      // Don't forget to change the AdvancedHeaderDraw event body accordingly after you changed the indicator here.
      case Column.Index of
        0: // Default drawing.
          ;
        1: // Background only customization.
          Include(Elements, hpeBackground);
        2: // Full customization (well, quite).
          Elements := [hpeBackground, hpeText{, hpeDropMark, hpeHeaderGlyph, hpeSortGlyph}];
      end;
    end;
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.HeaderCustomDrawTreeAdvancedHeaderDraw(Sender: TVTHeader; var PaintInfo: THeaderPaintInfo;
  const Elements: THeaderPaintElements);

var
  S: string;
  Size: TSize;
  SourceRect,
  TargetRect: TRect;

begin
  with PaintInfo do
  begin
    // First check the column member. If it is NoColumn then it's about the header background.
    if Column = nil then
    begin
      if hpeBackground in Elements then
      begin
        TargetCanvas.Brush.Color := clBtnFace;
        TargetCanvas.FillRect(PaintRectangle);
      end;
    end
    else
    begin
      case Column.Index of
        0: // Will never come here.
          ;
        1: // Background only customization.
          begin
            FBackBitmap1.Width := PaintRectangle.Right - PaintRectangle.Left;
            FBackBitmap1.Height := PaintRectangle.Bottom - PaintRectangle.Top;
            FillBackground(PaintRectangle, FBackbitmap1.Canvas);
            if IsHoverIndex and MMXAvailable then
              PaintSelection(FBackBitmap1);
            TargetCanvas.Draw(PaintRectangle.Left, Paintrectangle.Top, FBackbitmap1);
          end;
        2: // Full customization. Check elements to learn what must be drawn in the various stages.
          begin
            if hpeBackground in Elements then
              with FBackBitmap2 do
              begin
                Width := PaintRectangle.Right - PaintRectangle.Left;
                Height := PaintRectangle.Bottom - PaintRectangle.Top;
                TargetRect := Rect(0, 0, Width, Height);
                Canvas.Brush.Color := $E1FFFF;
                Canvas.FillRect(TargetRect);
                InflateRect(TargetRect, - 10, -10);
                SourceRect := TargetRect;
                OffsetRect(SourceRect, -SourceRect.Left + FLeftPos, -SourceRect.Top);
                Canvas.CopyRect(TargetRect, FHeaderBitmap.Canvas, SourceRect);

                TargetCanvas.Draw(PaintRectangle.Left, Paintrectangle.Top, FBackbitmap2);
              end;
            if hpeText in Elements then
            begin
              TargetCanvas.Font.Name := 'Webdings';
              TargetCanvas.Font.Charset := SYMBOL_CHARSET;
              TargetCanvas.Font.Size := 60;
              if IsHoverIndex then
                TargetCanvas.Font.Color := $80FF;
              S := 'รป';
              Size := TargetCanvas.TextExtent(S);
              SetBkMode(TargetCanvas.Handle, TRANSPARENT);
              TargetCanvas.TextOut(PaintRectangle.Left + 10, Paintrectangle.Bottom - Size.cy, S);
            end;
            // Other elements go here.
          end;
      end;
    end;
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.CreateCheckerBackground;

begin
  FCheckerBackground := TBitmap.Create;
  with FCheckerBackground do
  begin
    Width := 16;
    Height := 16;
    Canvas.Brush.Color := clBtnShadow;
    Canvas.FillRect(Rect(0, 0, Width, Height));
    Canvas.Brush.Color := clBtnHighlight;
    Canvas.FillRect(Rect(0, 0, 8, 8));
    Canvas.FillRect(Rect(8, 8, 16, 16));
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.PaintSelection(Bitmap: TBitmap);

const
  Alpha = 75;

var
  R: TRect;

begin
  R := Rect(0, 0, Bitmap.Width, Bitmap.Height);
  Laz.VTGraphics.AlphaBlend(0, Bitmap.Canvas.Handle, R, Point(0, 0), bmConstantAlphaAndColor, Alpha,
    ColorToRGB(clHighlight));
  with Bitmap do
  begin
    Canvas.Pen.Color := clHighlight;
    Canvas.Brush.Style := bsClear;
    Canvas.Rectangle(0, 0, Width, Height);
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.FillBackground(R: TRect; Target: TCanvas);

// Tiles the background image over the given target bitmap.

var
  X, Y: Integer;
  dX, dY: Integer;

begin
  with Target do
  begin
    dX := FCheckerBackground.Width;
    dY := FCheckerBackground.Height;

    Y := 0;
    while Y < R.Bottom - R.Top do
    begin
      X := 0;
      while X < R.Right - R.Left do
      begin
        Draw(X, Y, FCheckerBackground);
        Inc(X, dX);
      end;
      Inc(Y, dY);
    end;
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.FormCreate(Sender: TObject);

begin
  FBackBitmap1 := TBitmap.Create;
  FBackBitmap1.PixelFormat := OptimalPixelFormat;
  FBackBitmap2 := TBitmap.Create;
  //FBackBitmap2.PixelFormat := OptimalPixelFormat;
  CreateCheckerBackground;
  FHeaderBitmap := TBitmap.Create;
  FHeaderBitmap.LoadFromResourceName(HINSTANCE, 'Transcriptions');
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.FormDestroy(Sender: TObject);

begin
  FCheckerBackground.Free;
  FBackBitmap1.Free;
  FBackBitmap2.Free;
  FHeaderBitmap.Free;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.AnimationTimerTimer(Sender: TObject);

begin
  FLeftPos := (FLeftPos + FHeaderBitmap.Width div 2000) mod FHeaderBitmap.Width;
  with HeaderCustomDrawTree.Header do
    Invalidate(Columns[2]);
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.HeaderCustomDrawTreeHeaderMouseUp(Sender: TVTHeader; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

begin
  // Reenable animation after a drag operation.
  AnimationTimer.Enabled := True;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.HeaderCustomDrawTreeHeaderMouseDown(Sender: TVTHeader; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

begin
  // Stop animation when mouse button is down.
  AnimationTimer.Enabled := False;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.HeaderCustomDrawTreeStateChange(Sender: TBaseVirtualTree; Enter, Leave: TVirtualTreeStates);

begin
  if not (csDestroying in ComponentState) then
    UpdateStateDisplay(Sender.TreeStates, Enter, Leave);
end;

//----------------------------------------------------------------------------------------------------------------------

procedure THeaderOwnerDrawForm.HeaderCustomDrawTreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);

begin
  CellText := 'Some simple text.';
end;

//----------------------------------------------------------------------------------------------------------------------


end.