Board index » delphi » Double buffering a "transparent" form

Double buffering a "transparent" form

  I would like to create a rectangular form which appears transparent,
so its Canvas should be filled with the screen background. Besides
the background the form contains additional graphics. To reduce
flicker I tried to use double buffering by copying the screen
background into a Bitmap using
    PrintDesktop(Bitmap.Canvas.Handle);
then draw the graphics onto the Bitmap and finally copy the Bitmap
onto the Form.Canvas. As it is, the PrintDesktop operation copies
the screen background always beginning with the screen point (0,0)
at the left upper corner, no matter where is the form positioned on the
screen. How can I enforce grabbing, for instance, the screen
background beginning with (100,200) without creating a screen size
Bitmap?
  Thank you for your suggestions,
  Anton
--

------------------
Anton Rozsypal
ant...@ualberta.ca
------------------

 

Re:Double buffering a "transparent" form


I used a quite different approach. I captured and supressed the
WM_ERASEBKGND message. I also captured the WM_WINDOWPOSChanging message to
force redrawing when the form is moved.
To see the full application that use transparent background see:
http://www.propix.hu/share/WStar/WStar.html or download it
http://www.propix.hu/share/WStar/WStar_503.zip (83K including source and
executable)

Pintr Gbor, PROPIX Ltd.
Szkesfehrvr, Krivnyi u. 15.
H-8000, Hungary
Tel: +36 30 9972445, +36 22 300915, Fax: +36 22 304326
Email: pro...@mail.datatrans.hu Pinter.Ga...@freemail.hu
Web: http://www.propix.hu http://www.datatrans.hu/propix

Here is the source extract that is responsible for doing it:

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

type
  TMainForm = class(TForm)
   ....
  private
    procedure WMEraseBkgnd(var msg: TWMEraseBkgnd); message WM_ERASEBKGND;
// Supress background paint
    procedure WMWindowPosChanging(var msg: TWMWindowPosMsg); message
WM_WINDOWPOSChanging; // Force redraw
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

//--------------------------------------------------------------------------
--------------------------------------------
// Create, resize and paint

// Supress background paint
procedure TMainForm.WMEraseBkgnd(var msg: TWMEraseBkgnd);
begin
  msg.Result:= LRESULT(False);
end;

// About to move
procedure TMainForm.WMWindowPosChanging(var msg: TWMWindowPosMsg);
begin
  msg.WindowPos.flags:= msg.WindowPos.flags or SWP_NOCOPYBITS;
// Force redraw
  inherited;
end;

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

Quote
Anton Rozsypal <ant...@ualberta.ca> wrote in message

news:3A3AEDE2.E849EA3D@ualberta.ca...
Quote
>   I would like to create a rectangular form which appears transparent,
> so its Canvas should be filled with the screen background. Besides
> the background the form contains additional graphics. To reduce
> flicker I tried to use double buffering by copying the screen
> background into a Bitmap using
>     PrintDesktop(Bitmap.Canvas.Handle);
> then draw the graphics onto the Bitmap and finally copy the Bitmap
> onto the Form.Canvas. As it is, the PrintDesktop operation copies
> the screen background always beginning with the screen point (0,0)
> at the left upper corner, no matter where is the form positioned on the
> screen. How can I enforce grabbing, for instance, the screen
> background beginning with (100,200) without creating a screen size
> Bitmap?
>   Thank you for your suggestions,
>   Anton
> --

> ------------------
> Anton Rozsypal
> ant...@ualberta.ca
> ------------------

Re:Double buffering a "transparent" form


Hello Gabor:

Thank you for your WStar demo of a neat graphics trick. Your program
shows transparent graphics, so to speak, bur you still see the form
background through the static foreground graphics.
What I need is double buffering, where the user sees flickerless moving
graphics on the screen background. The form is there, but appears to be
invisible. Somehow I have to copy the screen background into the Bitmap.

Many thanks,

Anton

Quote
"Pintr Gbor" wrote:
> I used a quite different approach. I captured and supressed the
> WM_ERASEBKGND message. I also captured the WM_WINDOWPOSChanging message to
> force redrawing when the form is moved.
> To see the full application that use transparent background see:
> http://www.propix.hu/share/WStar/WStar.html or download it
> http://www.propix.hu/share/WStar/WStar_503.zip (83K including source and
> executable)

> Pintr Gbor, PROPIX Ltd.
> Szkesfehrvr, Krivnyi u. 15.
> H-8000, Hungary
> Tel: +36 30 9972445, +36 22 300915, Fax: +36 22 304326
> Email: pro...@mail.datatrans.hu Pinter.Ga...@freemail.hu
> Web: http://www.propix.hu http://www.datatrans.hu/propix

> Here is the source extract that is responsible for doing it:

> //--------------------------------------------------------------------------
> --------------------------------------------

> type
>   TMainForm = class(TForm)
>    ....
>   private
>     procedure WMEraseBkgnd(var msg: TWMEraseBkgnd); message WM_ERASEBKGND;
> // Supress background paint
>     procedure WMWindowPosChanging(var msg: TWMWindowPosMsg); message
> WM_WINDOWPOSChanging; // Force redraw
>   end;

> var
>   MainForm: TMainForm;

> implementation

> {$R *.DFM}

> //--------------------------------------------------------------------------
> --------------------------------------------
> // Create, resize and paint

> // Supress background paint
> procedure TMainForm.WMEraseBkgnd(var msg: TWMEraseBkgnd);
> begin
>   msg.Result:= LRESULT(False);
> end;

> // About to move
> procedure TMainForm.WMWindowPosChanging(var msg: TWMWindowPosMsg);
> begin
>   msg.WindowPos.flags:= msg.WindowPos.flags or SWP_NOCOPYBITS;
> // Force redraw
>   inherited;
> end;

> //--------------------------------------------------------------------------
> --------------------------------------------

> Anton Rozsypal <ant...@ualberta.ca> wrote in message
> news:3A3AEDE2.E849EA3D@ualberta.ca...
> >   I would like to create a rectangular form which appears transparent,
> > so its Canvas should be filled with the screen background. Besides
> > the background the form contains additional graphics. To reduce
> > flicker I tried to use double buffering by copying the screen
> > background into a Bitmap using
> >     PrintDesktop(Bitmap.Canvas.Handle);
> > then draw the graphics onto the Bitmap and finally copy the Bitmap
> > onto the Form.Canvas. As it is, the PrintDesktop operation copies
> > the screen background always beginning with the screen point (0,0)
> > at the left upper corner, no matter where is the form positioned on the
> > screen. How can I enforce grabbing, for instance, the screen
> > background beginning with (100,200) without creating a screen size
> > Bitmap?
> >   Thank you for your suggestions,
> >   Anton
> > --

> > ------------------
> > Anton Rozsypal
> > ant...@ualberta.ca
> > ------------------

--

------------------
Anton Rozsypal
ant...@ualberta.ca
------------------

Re:Double buffering a "transparent" form


Please try my other component. It is brand new, there is no html page, nor
other links to it just this:
http://www.propix.hu/share/GraphicScreen/GraphicScreen_100.zip

GraphicScreen is a global object that provides read and write access to the
Canvas of the desktop.
You can use GraphicScreen.Canvas.CopyRect to capture anything on screen and
copy it to another Canvas.

Pintr Gbor, PROPIX Ltd.
Szkesfehrvr, Krivnyi u. 15.
H-8000, Hungary
Tel: +36 30 9972445, +36 22 300915, Fax: +36 22 304326
Email: pro...@mail.datatrans.hu Pinter.Ga...@freemail.hu
Web: http://www.propix.hu http://www.datatrans.hu/propix

Re:Double buffering a "transparent" form


I think what you need is TTtitleBar.

The component uses windows regions rather than constantly repainting, which
are more efficient and flexible I believe.

Have a look for it in google.com.

HTH

Quote
Anton Rozsypal wrote:
>   I would like to create a rectangular form which appears transparent,
> so its Canvas should be filled with the screen background. Besides
> the background the form contains additional graphics. To reduce
> flicker I tried to use double buffering by copying the screen
> background into a Bitmap using
>     PrintDesktop(Bitmap.Canvas.Handle);
> then draw the graphics onto the Bitmap and finally copy the Bitmap
> onto the Form.Canvas. As it is, the PrintDesktop operation copies
> the screen background always beginning with the screen point (0,0)
> at the left upper corner, no matter where is the form positioned on the
> screen. How can I enforce grabbing, for instance, the screen
> background beginning with (100,200) without creating a screen size
> Bitmap?
>   Thank you for your suggestions,
>   Anton
> --

> ------------------
> Anton Rozsypal
> ant...@ualberta.ca
> ------------------

  patrickmmartin.vcf
< 1K Download

Re:Double buffering a "transparent" form


Create a region and attach it to your form.  Regions can be any shape you
want.  This will make your form truely transparent and you can even click on
windows in the holes of your form.  This alleviates the need to copy the
desktop image into your form to simulate transparency.  This is how Sonique,
WinAmp and many other applications with odd-shaped windows do it.

--
Steve 'Sly' Williams
Tools Developer
http://www.kromestudios.com

Quote
>   I would like to create a rectangular form which appears transparent,
> so its Canvas should be filled with the screen background. Besides
> the background the form contains additional graphics. To reduce
> flicker I tried to use double buffering by copying the screen
> background into a Bitmap using
>     PrintDesktop(Bitmap.Canvas.Handle);
> then draw the graphics onto the Bitmap and finally copy the Bitmap
> onto the Form.Canvas. As it is, the PrintDesktop operation copies
> the screen background always beginning with the screen point (0,0)
> at the left upper corner, no matter where is the form positioned on the
> screen. How can I enforce grabbing, for instance, the screen
> background beginning with (100,200) without creating a screen size
> Bitmap?
>   Thank you for your suggestions,
>   Anton
> --

> ------------------
> Anton Rozsypal
> ant...@ualberta.ca
> ------------------

Re:Double buffering a "transparent" form


Hello Gabor:

Thank you for the demo program. I could easily expand it to do all I needed,
except in the transparent background were also visible the desktop icons and
other possible applications. I would prefer just the background as the API
function PaintDesktop provides. Studying your code shifted my attention to
the TScreen class and eventually I found the answer to my problem in the
book by Tom Swan & Jeff Cogswell: Delphi 32-Bit Programming Secrets,
IDG Books, 1994, written for Delphi 2, in chapter 11, Graphics Secrets.
My painting sequence in the end looks like this:

    Create a form-size Bitmap (my form is Borderless)
    API function SetWindowOrgEx shifts the Screen coordinates origin
        to the Form position
    API function PaintDesktop copies the desktop background to the Bitmap
    API function SetWindowOrgEx restores the Screen coordinates origin back
        to the original position
    Drawing a Sprite on the Bitmap
    Copy Bitmap to Form Canvas
    Free Bitmap

The result is a flicker-less (double buffered) animation on a clickable
transparent-like Form. The icons and windows underneath the Form
don't interfere visually with the animation. I hope the short-term shift
in the Screen coordinates would not interfere with other applications.

Once again, thank you for all your help and inspiration,

Anton

Quote
"Pintr Gbor" wrote:
> Please try my other component. It is brand new, there is no html page, nor
> other links to it just this:
> http://www.propix.hu/share/GraphicScreen/GraphicScreen_100.zip

> GraphicScreen is a global object that provides read and write access to the
> Canvas of the desktop.
> You can use GraphicScreen.Canvas.CopyRect to capture anything on screen and
> copy it to another Canvas.

> Pintr Gbor, PROPIX Ltd.
> Szkesfehrvr, Krivnyi u. 15.
> H-8000, Hungary
> Tel: +36 30 9972445, +36 22 300915, Fax: +36 22 304326
> Email: pro...@mail.datatrans.hu Pinter.Ga...@freemail.hu
> Web: http://www.propix.hu http://www.datatrans.hu/propix

------------------
Anton Rozsypal
ant...@ualberta.ca
------------------

Re:Double buffering a "transparent" form


Hello Steve:

Thank you for your suggestion. In my original message I did not make myself
clear: I need a form that only looks like transparent, it should be clickable
and
serve as a background for animation on most of its surface. I believe that I
have
found a solution described in my discussion with Gabor Pinter in the thread
above.

Many thanks,

Anton

Quote
Steve Williams wrote:
> Create a region and attach it to your form.  Regions can be any shape you
> want.  This will make your form truely transparent and you can even click on
> windows in the holes of your form.  This alleviates the need to copy the
> desktop image into your form to simulate transparency.  This is how Sonique,
> WinAmp and many other applications with odd-shaped windows do it.

> --
> Steve 'Sly' Williams
> Tools Developer
> http://www.kromestudios.com

> >   I would like to create a rectangular form which appears transparent,
> > so its Canvas should be filled with the screen background. Besides
> > the background the form contains additional graphics. To reduce
> > flicker I tried to use double buffering by copying the screen
> > background into a Bitmap using
> >     PrintDesktop(Bitmap.Canvas.Handle);
> > then draw the graphics onto the Bitmap and finally copy the Bitmap
> > onto the Form.Canvas. As it is, the PrintDesktop operation copies
> > the screen background always beginning with the screen point (0,0)
> > at the left upper corner, no matter where is the form positioned on the
> > screen. How can I enforce grabbing, for instance, the screen
> > background beginning with (100,200) without creating a screen size
> > Bitmap?
> >   Thank you for your suggestions,
> >   Anton
> > --

------------------
Anton Rozsypal
ant...@ualberta.ca
------------------

Re:Double buffering a "transparent" form


Hello Patrick:

Thank you for your suggestion. I need the constant repainting because my
transparent-like form displays animation. I think I have arrived at a solution,

described in my discussion with Gabor Pinter in the thread above.

Best Regards,

Anton

Quote
Patrick Martin wrote:
> I think what you need is TTtitleBar.

> The component uses windows regions rather than constantly repainting, which
> are more efficient and flexible I believe.

> Have a look for it in google.com.

> HTH
> Anton Rozsypal wrote:

> >   I would like to create a rectangular form which appears transparent,
> > so its Canvas should be filled with the screen background. Besides
> > the background the form contains additional graphics. To reduce
> > flicker I tried to use double buffering by copying the screen
> > background into a Bitmap using
> >     PrintDesktop(Bitmap.Canvas.Handle);
> > then draw the graphics onto the Bitmap and finally copy the Bitmap
> > onto the Form.Canvas. As it is, the PrintDesktop operation copies
> > the screen background always beginning with the screen point (0,0)
> > at the left upper corner, no matter where is the form positioned on the
> > screen. How can I enforce grabbing, for instance, the screen
> > background beginning with (100,200) without creating a screen size
> > Bitmap?
> >   Thank you for your suggestions,
> >   Anton

------------------
Anton Rozsypal
ant...@ualberta.ca
------------------

Other Threads