Recent

Author Topic: BGRA Opaque Panel example, teach me please  (Read 1495 times)

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
BGRA Opaque Panel example, teach me please
« on: February 10, 2024, 10:28:30 am »
Good day!

After a message from Lainz about that there is a darkmode for BGRA controls I did update my Lazarus installation with the dev variants of both packages (BGRA Bitmap and Controls)
All works wonderful, while I tested out the different panels I found a gradient drawing TBCPanel. That looks pretty interesting!
Now I did try, without luck, to put another panel over it that has no colors (clNone) to achieve the effect of a full opaque window control where I could align labels or other controls in it but the grandient of the background panel is full visible.

I did try this with several different panels but I can't make it work.

Can you teach me how to achieve it please?

Attached is a demo project (no code, just visual properties) where I would learn from about how to use the properties correct to have a full opaque window control.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #1 on: February 10, 2024, 02:07:04 pm »
I can imagine you can use TBGRAVirtualScreen and OnRedraw event draw the gradient background of the TBCPanel.
Like drawing the background rect in the virtual screen. A virtual screen is a panel.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
Re: BGRA Opaque Panel example, teach me please
« Reply #2 on: February 10, 2024, 02:58:24 pm »
I can imagine you can use TBGRAVirtualScreen and OnRedraw event draw the gradient background of the TBCPanel.
Like drawing the background rect in the virtual screen. A virtual screen is a panel.
I will look into that Virtual Screen, thank you for the hint!

Meanwhile I am stuck on a different problem, actually its 2 problems.
I do show what I've done to get what I needed and by accident found something interesting for your demo that uses desktop wallpaper and blur it to have a fake glass effect.
That way the blur should be faster since the images are small.
The problem is that is uses wrong coordinate and it sadly does not autoupdate itself with my current way of doing :-/
Code: Pascal  [Select][+][-]
  1. unit uMain;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
  9.   BCPanel, BGRACustomDrawn, BCLabel, LCLIntf, LCLType, LMessages;
  10.  
  11. type
  12.  
  13.   { TBCDPanel }
  14.  
  15.   TBCDPanel = class(BGRACustomDrawn.TBCDPanel)
  16.     strict private
  17.       FBackgroundBitmap: TBitmap;
  18.       FCustomPaint: Boolean;
  19.       FUseDesktop: Boolean;
  20.       FOnMove: TNotifyEvent;
  21.       procedure SetCustomPaint(AValue: Boolean);
  22.     protected
  23.       procedure Resize; override;
  24.       procedure Loaded; override;
  25.       procedure Paint; override;
  26.       procedure WndProc(var Message: TLMessage); override;
  27.     private
  28.       procedure MoveHandler(Sender: TObject);
  29.     public
  30.       procedure UpdateBackgroundBitmap;
  31.     public
  32.       constructor Create(AOwner: TComponent); override;
  33.       destructor Destroy; override;
  34.     published
  35.       property OnMove: TNotifyEvent read FOnMove write FOnMove;
  36.       property UseDesktop: Boolean read FUseDesktop write FUseDesktop default True;
  37.       property CustomPaint: Boolean read FCustomPaint write SetCustomPaint default False;
  38.   end;
  39.  
  40. type
  41.  
  42.   { TForm1 }
  43.  
  44.   TForm1 = class(TForm)
  45.     BCDPanel1: TBCDPanel;
  46.     BCDPanel2: TBCDPanel;
  47.     BCDPanel3: TBCDPanel;
  48.     Label1: TLabel;
  49.     Label2: TLabel;
  50.     Label3: TLabel;
  51.     Label4: TLabel;
  52.     Label5: TLabel;
  53.     Label6: TLabel;
  54.     Panel1: TPanel;
  55.     pnlMain: TBCPanel;
  56.   protected
  57.     procedure WndProc(var Message: TLMessage); override;
  58.   private
  59.     procedure UpdatePanelBackground;
  60.   private
  61.  
  62.   public
  63.  
  64.   end;
  65.  
  66. var
  67.   Form1: TForm1;
  68.  
  69. implementation
  70.  
  71. {$R *.lfm}
  72.  
  73. { TBCDPanel }
  74.  
  75. procedure TBCDPanel.SetCustomPaint(AValue: Boolean);
  76. begin
  77.   if FCustomPaint = AValue then
  78.     Exit;
  79.   FCustomPaint := AValue;
  80.   if FCustomPaint then
  81.     UpdateBackgroundBitmap; // Update the background bitmap when the control is loaded
  82. end;
  83.  
  84. procedure TBCDPanel.Resize;
  85. begin
  86.   inherited Resize;
  87.   if FCustomPaint then
  88.     UpdateBackgroundBitmap; // Update the background bitmap when the control is loaded
  89. end;
  90.  
  91. procedure TBCDPanel.Loaded;
  92. begin
  93.   inherited Loaded;
  94.   if FCustomPaint then
  95.     UpdateBackgroundBitmap; // Update the background bitmap when the control is resized
  96. end;
  97.  
  98. procedure TBCDPanel.Paint;
  99. begin
  100. //  inherited Paint;
  101. //  Self.Canvas.Brush.Color := clOlive;
  102. //  Self.Canvas.Brush.Style := bsSolid;
  103. //  Self.Canvas.FillRect(Self.ClientRect);
  104.   if FCustomPaint then
  105.     Self.Canvas.Draw(0,  0, FBackgroundBitmap)
  106.   else
  107.     inherited Paint;
  108. end;
  109.  
  110. procedure TBCDPanel.WndProc(var Message: TLMessage);
  111. begin
  112.   case Message.Msg of
  113.     LM_SIZE:
  114.       begin
  115.         UpdateBackgroundBitmap;
  116.       end;
  117.     LM_MOVE:
  118.       begin
  119.         UpdateBackgroundBitmap;
  120.       end;
  121.     else
  122.       inherited WndProc(Message);
  123.   end;
  124. end;
  125.  
  126. procedure TBCDPanel.UpdateBackgroundBitmap;
  127. var
  128.   ScreenDC, MemDC: HDC;
  129.   OldBitmap: HBITMAP;
  130.   PointOnScreen: TPoint;
  131. begin
  132.   if FUseDesktop then
  133.     ScreenDC := GetDC(0)
  134.   else
  135.     ScreenDC := GetDC(Parent.Handle);
  136.   if ScreenDC <>  0 then
  137.   begin
  138.     try
  139.       PointOnScreen := Self.ClientToScreen(Point(Self.Left + Parent.Left,  Self.Top + Parent.Top));
  140. //      PointOnScreen := Self.ScreenToClient(Point(Self.Left + Parent.Left,  Self.Top + Parent.Top));
  141. //      PointOnScreen := Self.ClientToScreen(Point(Self.Left,  Self.Top));
  142. //      PointOnScreen := Self.ScreenToClient(Point(Self.Left,  Self.Top));
  143.       FBackgroundBitmap.SetSize(Self.Width, Self.Height);
  144.       MemDC := CreateCompatibleDC(ScreenDC);
  145.       if MemDC <>  0 then
  146.       begin
  147.         try
  148.           OldBitmap := SelectObject(MemDC, FBackgroundBitmap.Handle);
  149.           BitBlt(MemDC,  0,  0, Self.Width, Self.Height, ScreenDC, PointOnScreen.X, PointOnScreen.Y, SRCCOPY);
  150.           SelectObject(MemDC, OldBitmap);
  151.         finally
  152.           DeleteDC(MemDC);
  153.         end;
  154.       end;
  155.     finally
  156.       if FUseDesktop then
  157.         ReleaseDC(0, ScreenDC)
  158.       else
  159.         ReleaseDC(Parent.Handle, ScreenDC);
  160.     end;
  161.   end;
  162.   Self.Invalidate;
  163. end;
  164.  
  165. procedure TBCDPanel.MoveHandler(Sender: TObject);
  166. begin
  167.   if FCustomPaint then
  168.     UpdateBackgroundBitmap;
  169. end;
  170.  
  171. constructor TBCDPanel.Create(AOwner: TComponent);
  172. begin
  173.   inherited Create(AOwner);
  174.   FUseDesktop := True;
  175.   FCustomPaint := True;
  176.   FBackgroundBitmap := TBitmap.Create;
  177.   Self.DoubleBuffered := False;
  178.   Self.ParentBackground := False;
  179.   Self.Color := clNone;
  180.   Self.Visible := True;
  181.   Self.OnMove := @MoveHandler;
  182. end;
  183.  
  184. destructor TBCDPanel.Destroy;
  185. begin
  186.   FBackgroundBitmap.Free;
  187.   inherited Destroy;
  188. end;
  189.  
  190. { TForm1 }
  191.  
  192. procedure TForm1.WndProc(var Message: TLMessage);
  193. begin
  194.   case Message.Msg of
  195.     LM_SIZE:
  196.       begin
  197.         UpdatePanelBackground;
  198.       end;
  199.     LM_MOVE:
  200.       begin
  201.         UpdatePanelBackground;
  202.       end;
  203.     else
  204.       inherited WndProc(Message);
  205.   end;
  206. end;
  207.  
  208. procedure TForm1.UpdatePanelBackground;
  209. var
  210.   i: Integer;
  211. begin
  212.   for i := 0 to Pred(Self.ControlCount) do
  213.     begin
  214.       if Self.Controls[i] is TBCDPanel then
  215.         (Self.Controls[i] as TBCDPanel).UpdateBackgroundBitmap;
  216.     end;
  217. end;
  218.  
  219. end.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
Re: BGRA Opaque Panel example, teach me please
« Reply #3 on: February 10, 2024, 05:59:42 pm »
I have made a big progress in belonging if i want to have the content of whats behind our form window to use in inside panel as background is working very reliable now.
Now I wanted to make the same than Lainz did to blurr an Image but the result is wrong so I use it wrong I assume :D
Can you please look over and help me fixing this issue?
Code: Pascal  [Select][+][-]
  1. procedure TBCDPanel.UpdateBackgroundBitmap;
  2.   function FindTopLevelParent(Control: TControl): TControl;
  3.   begin
  4.     if Assigned(Control.Parent) then
  5.       Result := FindTopLevelParent(Control.Parent)
  6.     else
  7.       Result := Control;
  8.   end;
  9. const
  10.   BLURSIZE = 5;
  11.   ALPHAVALUE = 10;
  12. var
  13.   ScreenDC, MemDC: HDC;
  14.   OldBitmap: HBITMAP;
  15.   PointOnScreen: TPoint;
  16.   CurrentControl: TControl;
  17.   blurred: TBGRABitmap;
  18. begin
  19.   if not FCustomPaint then
  20.     Exit;
  21.   ScreenDC := GetDC(0);
  22.   try
  23.     FBackgroundBitmap.SetSize(Self.Width, Self.Height);
  24.     MemDC := CreateCompatibleDC(ScreenDC);
  25.     try
  26.       OldBitmap := SelectObject(MemDC, FBackgroundBitmap.Handle);
  27.  
  28.       if FUseDesktop then
  29.         CurrentControl := FindTopLevelParent(Self)
  30.       else
  31.         CurrentControl := Self;
  32.       PointOnScreen := CurrentControl.ClientOrigin;
  33.       if FUseDesktop then
  34.         begin
  35.           PointOnScreen.X := PointOnScreen.X - (CurrentControl.Left - Self.Left);
  36.           PointOnScreen.Y := PointOnScreen.Y - (CurrentControl.Top - Self.Top);
  37.         end
  38.       else
  39.         begin
  40.           PointOnScreen.X := PointOnScreen.X - (CurrentControl.Left);
  41.           PointOnScreen.Y := PointOnScreen.Y - (CurrentControl.Top);
  42.         end;
  43.       BitBlt(MemDC,   0,   0, Self.Width, Self.Height, ScreenDC, PointOnScreen.X, PointOnScreen.Y, SRCCOPY);
  44.  
  45.       SelectObject(MemDC, OldBitmap);
  46.     finally
  47.       DeleteDC(MemDC);
  48.     end;
  49.   finally
  50.     ReleaseDC(0, ScreenDC);
  51.   end;
  52.   if FUseDesktop then
  53.   begin
  54.     blurred := TBGRABitmap.Create;
  55.     try
  56.       blurred.Assign(FBackgroundBitmap);
  57.       BGRAReplace(blurred, blurred.FilterBlurRadial(BLURSIZE, BLURSIZE, rbBox));
  58.       blurred.Rectangle(0, 0, blurred.Width, blurred.Height,
  59.         BGRA(255, 255, 255, ALPHAVALUE), BGRA(255, 255, 255, ALPHAVALUE), dmDrawWithTransparency);
  60.       blurred.PutImage(-Left, -Top, blurred, dmSet);
  61.       blurred.Rectangle(0, 0, blurred.Width + 1, blurred.Height, BGRABlack, dmSet);
  62. //      blurred.AssignToBitmap(FBackgroundBitmap);
  63.     finally
  64.       blurred.Free;
  65.     end;
  66.   end;
  67.  
  68.   Self.Invalidate;
  69. end;

/edit
To show current results I've added an image to show that the background is used now at correct location
What is badly needed is a fix that it redo this method when the form moves and a fix to the blurr
« Last Edit: February 10, 2024, 06:14:32 pm by KodeZwerg »
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #4 on: February 11, 2024, 12:33:05 am »
Can you attach a compilable program, I don't want to make all the UI despite is just panels and labels.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
Re: BGRA Opaque Panel example, teach me please
« Reply #5 on: February 11, 2024, 10:30:53 am »
Can you attach a compilable program, I don't want to make all the UI despite is just panels and labels.
Of course I can and did :-D

This is the latest full of bugs of all kind version that at least show, even when broken, that a background image is created and shown.
My 3 options that I included with checkboxes are doing no difference for still unknown reason but present to let you know that this is how I am needing it to tweak the original TBCDPanel component.
Maybe adding option to tweak interval for update process, I was thinking if its blurr choosen than once per second do update is enough.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
Re: BGRA Opaque Panel example, teach me please
« Reply #6 on: February 11, 2024, 01:28:33 pm »
I would really appreciate if BGRA Controls would add an BGRA optimized Opaque Panel visual control into its palette  :-*

My needings and current way of doing, in a work in progress manner:
- choose between 2 opaque modes, from point of whats behind form = UseDesktop, from point of whats behind the control = not UseDesktop :-D
- an generic option to turn opaque mode on/off = CustomPaint (should rename this to OpaqueEnabled...)
- depending on UseDesktop, either cut out of form the region of the panel to make a screenshot of whats begin control
    or cutout the full form of view to know whats behind the form, very alpha state :-/
- give back screenshot as backgroundimage to panel, optional blurr it
- make it update itself, works but very alpha, should probably check if there is a difference between new image and current displayed to reduce flickering
- convert all to a BGRA Bitmap version without need of other units so its multicrossplatform and hopeful faster

//edit
future plans, let me dream:
- make it a custom control instead of intercepting
- extend current blurr effect by switching to a simplified glass effect
  - make glass effect by "draw alphablended color over screenshot" without adding fancy glass highlights (could become possible in many many future versions :D)
  - take screen shot, add overlay of glasscolor if <> clNone
  - add blurr effect setting for "how strong you can see thru glass" 0..100
  - add opacity property to choose between 0 and 100 how much alphablended (transparency to background of control) the background should become
  - optimize it for better handling
« Last Edit: February 11, 2024, 02:50:07 pm by KodeZwerg »
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #7 on: February 11, 2024, 03:39:27 pm »
Attached a screenshot of my latest demo in bgracontrols, please test.

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #8 on: February 11, 2024, 06:26:48 pm »
- Added Shadow
- Added noise for the blur
- Working on High DPI

ToDo:
- fix bgravirtualscreen bug that doesn't redraw if size don't change

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
Re: BGRA Opaque Panel example, teach me please
« Reply #9 on: February 11, 2024, 08:13:22 pm »
Attached a screenshot of my latest demo in bgracontrols, please test.
I am unsure how to test, cant find your attachment, but its looking cool! Especial the last one with fluent ui optics <3
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #10 on: February 11, 2024, 08:29:36 pm »
Attached a screenshot of my latest demo in bgracontrols, please test.
I am unsure how to test, cant find your attachment, but its looking cool! Especial the last one with fluent ui optics <3

Hi, thanks.

It's here:
https://github.com/bgrabitmap/bgracontrols/tree/dev-bgracontrols/test/test_bgravirtualscreen_blur

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1999
  • Fifty shades of code.
    • Delphi & FreePascal
Re: BGRA Opaque Panel example, teach me please
« Reply #11 on: February 12, 2024, 12:09:21 am »
Wow, I've downloaded and run demo, it enlightened me so much!
That TBGRAVirtualScreen is really amazing and as you suggested first, it fit my needs to 100% !

So it is like a full empty void with the advantage of having custom paint and keep acting as container for more, awesome!
I like to play with it a little since I found some behave I'd like to upgrade.
I will look into it if I can tweak its usage to generate small screenshots of the region on screen without the control and integrate a "see-thru form" opaque modifier.
Plus that it autoupdate interval based, as i see it uses a redraw method to bring it on screen so that can be called and a current background image just for the region of the panel (virtualscreen) can be computed in there

Thank you Lainz for your example, it really help me much on this voyage!
I will try if I can make a Blurr(inBitmap, outBitmap, Glasscolor, Glassdensity, Blurrdistortion) or something like that method to combine each and all of your example and call it on redraw
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #12 on: February 12, 2024, 02:00:08 am »
Great. Keep going.  :)

lainz

  • Hero Member
  • *****
  • Posts: 4424
    • https://lainz.github.io/
Re: BGRA Opaque Panel example, teach me please
« Reply #13 on: February 18, 2024, 12:55:39 am »
Hi. I've fixed the demo with full image. It works fine in Lazarus 3. The bug was in Lazarus 2 that do not refresh the virtual screen properly...

 

TinyPortal © 2005-2018