@@ -37,6 +37,8 @@ TVTBaseAncestorVcl = class abstract(TCustomControl)
37
37
function RenderOLEData (const FormatEtcIn: TFormatEtc; out Medium: TStgMedium; ForClipboard: Boolean): HResult; virtual ;
38
38
procedure NotifyAccessibleEvent (pEvent: DWord = EVENT_OBJECT_STATECHANGE);
39
39
function PrepareDottedBrush (CurrentDottedBrush: TBrush; Bits: Pointer; const BitsLinesCount: Word): TBrush; virtual ;
40
+ function CreateSystemImageSet (): TImageList;
41
+ procedure SetWindowTheme (const Theme: string); virtual ;
40
42
// // Abtract method that are implemented in TBaseVirtualTree, keep in sync with TVTBaseAncestorFMX
41
43
function GetSelectedCount (): Integer; virtual ; abstract ;
42
44
procedure MarkCutCopyNodes ; virtual ; abstract ;
@@ -104,10 +106,17 @@ implementation
104
106
105
107
uses
106
108
System.SyncObjs,
109
+ System.SysUtils,
107
110
Vcl.AxCtrls,
111
+ Vcl.Forms,
112
+ Vcl.Themes,
113
+ Winapi.CommCtrl,
114
+ Winapi.ShlObj,
115
+ Winapi.UxTheme,
108
116
VirtualTrees.DataObject,
109
117
VirtualTrees.Clipboard,
110
- VirtualTrees.AccessibilityFactory;
118
+ VirtualTrees.AccessibilityFactory,
119
+ VirtualTrees.StyleHooks;
111
120
112
121
// ----------------------------------------------------------------------------------------------------------------------
113
122
@@ -283,6 +292,137 @@ procedure TVTBaseAncestorVcl.CopyToClipboard;
283
292
end ;
284
293
end ;
285
294
295
+ function TVTBaseAncestorVcl.CreateSystemImageSet : TImageList;
296
+
297
+ // Creates a system check image set.
298
+ // Note: the DarkCheckImages and FlatImages image lists must already be filled, as some images from them are copied here.
299
+
300
+ const
301
+ MaskColor: TColor = clRed;
302
+ cFlags = ILC_COLOR32 or ILC_MASK;
303
+
304
+ var
305
+ BM: TBitmap;
306
+ Theme: HTHEME;
307
+ Details: TThemedElementDetails;
308
+
309
+ // ---------------------------------------------------------------------------
310
+
311
+ // Mitigator function to use the correct style service for this context (either the style assigned to the control for Delphi > 10.4 or the application style)
312
+ function StyleServices : TCustomStyleServices;
313
+ begin
314
+ Result := VTStyleServices(Self);
315
+ end ;
316
+
317
+ procedure AddSystemImage (IL: TImageList; Index: Integer);
318
+ const
319
+ States: array [0 ..19 ] of Integer = (
320
+ RBS_UNCHECKEDNORMAL, RBS_UNCHECKEDHOT, RBS_UNCHECKEDPRESSED, RBS_UNCHECKEDDISABLED,
321
+ RBS_CHECKEDNORMAL, RBS_CHECKEDHOT, RBS_CHECKEDPRESSED, RBS_CHECKEDDISABLED,
322
+ CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDDISABLED,
323
+ CBS_CHECKEDNORMAL, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDDISABLED,
324
+ CBS_MIXEDNORMAL, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDDISABLED);
325
+ var
326
+ ButtonState: Cardinal;
327
+ ButtonType: Cardinal;
328
+
329
+ begin
330
+ BM.Canvas.FillRect(Rect(0 , 0 , BM.Width, BM.Height));
331
+ if StyleServices.Enabled and StyleServices.IsSystemStyle then
332
+ begin
333
+ if Index < 8 then
334
+ Details.Part := BP_RADIOBUTTON
335
+ else
336
+ Details.Part := BP_CHECKBOX;
337
+ Details.State := States[Index];
338
+ DrawThemeBackground(Theme, BM.Canvas.Handle, Details.Part, Details.State, Rect(0 , 0 , BM.Width, BM.Height), nil );
339
+ end
340
+ else
341
+ begin
342
+ if Index < 8 then
343
+ ButtonType := DFCS_BUTTONRADIO
344
+ else
345
+ ButtonType := DFCS_BUTTONCHECK;
346
+ if Index >= 16 then
347
+ ButtonType := ButtonType or DFCS_BUTTON3STATE;
348
+
349
+ case Index mod 4 of
350
+ 0 :
351
+ ButtonState := 0 ;
352
+ 1 :
353
+ ButtonState := DFCS_HOT;
354
+ 2 :
355
+ ButtonState := DFCS_PUSHED;
356
+ else
357
+ ButtonState := DFCS_INACTIVE;
358
+ end ;
359
+ if Index in [4 ..7 , 12 ..19 ] then
360
+ ButtonState := ButtonState or DFCS_CHECKED;
361
+ // if Flat then
362
+ // ButtonState := ButtonState or DFCS_FLAT;
363
+ DrawFrameControl(BM.Canvas.Handle, Rect(0 , 0 , BM.Width, BM.Height), DFC_BUTTON, ButtonType or ButtonState);
364
+ end ;
365
+ IL.AddMasked(BM, MaskColor);
366
+ end ;
367
+
368
+ // --------------- end local functions ---------------------------------------
369
+
370
+ const
371
+ cDefaultCheckboxSize = 13 ;// Used when no other value is available
372
+ var
373
+ I: Integer;
374
+ lSize: TSize;
375
+ Res: Boolean;
376
+ begin
377
+ BM := TBitmap.Create; // Create a temporary bitmap, which holds the intermediate images.
378
+ try
379
+ Res := False;
380
+ // Retrieve the checkbox image size, prefer theme if available, fall back to GetSystemMetrics() otherwise, but this returns odd results on Windows 8 and higher in high-dpi scenarios.
381
+ if StyleServices.Enabled then
382
+ if StyleServices.IsSystemStyle then
383
+ begin
384
+ { $if CompilerVersion >= 33}
385
+ if TOSVersion.Check(10 ) and (TOSVersion.Build >= 15063 ) then
386
+ Theme := OpenThemeDataForDPI(Handle, ' BUTTON' , CurrentPPI)
387
+ else
388
+ { $ifend}
389
+ Theme := OpenThemeData(Self.Handle, ' BUTTON' );
390
+ Details := StyleServices.GetElementDetails(tbCheckBoxUncheckedNormal);
391
+ Res := GetThemePartSize(Theme, BM.Canvas.Handle, Details.Part, Details.State, nil , TS_TRUE, lSize) = S_OK;
392
+ end
393
+ else
394
+ Res := StyleServices.GetElementSize(BM.Canvas.Handle, StyleServices.GetElementDetails(tbCheckBoxUncheckedNormal), TElementSize.esActual, lSize { $IF CompilerVersion >= 34} , Self.CurrentPPI{ $IFEND} );
395
+ if not Res then begin
396
+ lSize := TSize.Create(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK));
397
+ if lSize.cx = 0 then begin // error? (Should happen rarely only)
398
+ lSize.cx := MulDiv(cDefaultCheckboxSize, Screen.PixelsPerInch, USER_DEFAULT_SCREEN_DPI);
399
+ lSize.cy := lSize.cx;
400
+ end ;// if
401
+ end ;// if
402
+
403
+ Result := TImageList.CreateSize(lSize.cx, lSize.cy);
404
+ Result.Handle := ImageList_Create(Result.Width, Result.Height, cFlags, 0 , Result.AllocBy);
405
+ Result.Masked := True;
406
+ Result.BkColor := clWhite;
407
+
408
+ // Make the bitmap the same size as the image list is to avoid problems when adding.
409
+ BM.SetSize(Result.Width, Result.Height);
410
+ BM.Canvas.Brush.Color := MaskColor;
411
+ BM.Canvas.Brush.Style := bsSolid;
412
+ BM.Canvas.FillRect(Rect(0 , 0 , BM.Width, BM.Height));
413
+ Result.AddMasked(BM, MaskColor);
414
+
415
+ // Add the 20 system checkbox and radiobutton images.
416
+ for I := 0 to 19 do
417
+ AddSystemImage(Result, I);
418
+ if StyleServices.Enabled and StyleServices.IsSystemStyle then
419
+ CloseThemeData(Theme);
420
+
421
+ finally
422
+ BM.Free;
423
+ end ;
424
+ end ;
425
+
286
426
procedure TVTBaseAncestorVcl.CutToClipboard ;
287
427
var
288
428
lDataObject: IDataObject;
@@ -409,6 +549,13 @@ function TVTBaseAncestorVcl.SetScrollInfo(Bar: Integer; const ScrollInfo: TScrol
409
549
410
550
// ----------------------------------------------------------------------------------------------------------------------
411
551
552
+ procedure TVTBaseAncestorVcl.SetWindowTheme (const Theme: string);
553
+ begin
554
+ Winapi.UxTheme.SetWindowTheme(Handle, PWideChar(Theme), nil );
555
+ end ;
556
+
557
+ // ----------------------------------------------------------------------------------------------------------------------
558
+
412
559
function TVTBaseAncestorVcl.GetScrollInfo (Bar: Integer; var ScrollInfo: TScrollInfo): Boolean;
413
560
begin
414
561
Result:= WinApi.Windows.GetScrollInfo(Handle, Bar, ScrollInfo);
0 commit comments