everyone who has used xp would have seen the effect produced when a user opts to shutdown windows xp. to see it you click the "start" button and then select shutdown, which brings up the windows shutdown dialog similar to the one below.

the question is why would anyone click "start" when they want to "stop"? but that is another story...


you may have also noticed that windows slowly fades the coloured background down to grey, leaving the coloured dialogbox to appear more prominent. the colour of the desktop is restored if the user cancels this operation.

this same effect is possible in vfp forms and applications by using the gdi+x classes found on codeplex.

the class i created will do this for you for any form you drop it on, and call its methods. this class (download link below) uses the imgcanvas object so to use it you will need to download the gdi+x classes.

usage is extremely simple. you just drop it on the main form of a sdi or add it to _screen. when you need to produce the effect, you just call its showlightbox() method and to remove the effect call the hidelightbox() method. as calling sample is shown below which could be added to an exit or quit button:

bb = thisform.bbgdilightbox1.showlightbox()
if messagebox("are you sure you want to quit?",308,"gdi+x lightbox",0) = 7
    bb = thisform.bbgdilightbox1.hidelightbox()
    return
else
    thisform.release
endif

basically what happens when the showlightbox method is called is that using gdi+ an image of the mainform is captured,  the lightbox class expands to overlay the whole form and the image is painted on the imgcanvas. a timer is kicked off in the background and the class returns control to the code.

the timer in the background increments a variable and calls the imgcanvas.draw. the variable affects the way the colormatrix is created and this changes the colours of the screen image. with repeated calls the colour is "faded" till the image is grey. the timer then stops.

to restore, the class is just made invisible again.

the code to produce this effect comes from an article by cesar in the ut mag. without which this class would not have been possible.

a sample form where you can test this as well as a pseudo messagebox form is also included in the download for this article. just make sure you have the gdi+x classes, run system.app and then run the form:


sample form with coloured background and vfp controls.

click the "exit" button to see the effect as the messagebox appears and the background slowly fades to grey.


sample form with the form and controls faded to grey.

complete source code is provided for anyone to modify as they please. enjoy.

update: since i do not include the gdiplusx.vcx (as this must be downloaded from the vfpx site) and since i have subclassed the imgcanvas class found in the gdiplusx.vcx classlibrary, you need to resolve the link to the class yourself.

just open the form in vfp and when it asks you for the imgcanvas navigate to the gdiplusx.vcx on your computer where you will find the imgcanvas class. the form will then resolve the location correctly. save the form, set the default path to the directory where the form is (to find the images) and then run the form.

unfortunately this would happen since i don't supply the gdiplusx.vcx and i don't know where a user might have stored it. thanks to mike s for pointing that out.

unfortunately because of the amount of junk mail being generated from the weblog i have switched off comments. please post your comments, if any, at www.foxite.com

7 Responses to Emulating the XP Shutdown Effect in VFP9 forms with GDI+

  • Horacio Giménez says:

    ¡Excelente, Bernard!
    Muchas gracias por compartirlo

    No hay de qué Horacio

  • MikeS says:

    I was wondering how long it would take you to get this one up an running 🙂

    When I try to run your form, I receive an “Error instantiating class” message. It is looking for a path “..\aavfpx\gdiplusxfull20080109\source\gdiplusx” which I don’t have. If I try to Locate it (in gdilightbox.vcx) I get another error “Cannot find imgcanvas in gdilightbox.vcx”.

    FYI, I’ve downloaded the latest GDIPLUSX.

    What am I doing wrong?

    I dont include the gdiplusc.vcx since you need that from VFPx.

    Just open the form in VFP and when it asks you for the Imgcanvas navigate it to the gdiplusx.vcx on your computer. The form will then resolve the location correctly. Save the form, set the default path to the directory where the form is (to find the images) and then run the form. I have subclassed the imgcanvas class from the gdiplusx.vcx class library. Unfortunately this would happen since I don’t supply the gdiplusx.vcx and I don’t know where a user might have stored it. Thanks for that anyway. Will make a note in the blog.

  • Dale says:

    Hmmm… Bernard, I can read you mind. I can see what are you thinking next. Based on the aquarium background of the form, you’re thinking of putting an animated fish swimming in there, eh? Nice job by the way.

    Good guess Dale. But already done in another soon to be released post. Not in this class though.

  • Vivek Deodhar says:

    Bernard,

    If I turn off the title bar of the form, error crops up “LOBITMAP is not an object”.
    Why is that?
    (I turn off title bar for my main form and use my own skin)
    Vivek

    The code in the BeforeDraw of the imgcanvas class in the lightboxclass:

    Local

    lnTitleHeight, lnLeftBorder, lnTopBorder

    lnTitleHeight

    = Sysmetric(9)

    lnLeftBorder = Sysmetric(3)

    lnTopBorder = Sysmetric(4)

    With _Screen.System.Drawing

    * get it once

    IF VARTYPE(NVL(This.Parent.oBitmap,“”)) # “O”

    This.Parent.oBitmap = .Bitmap.FromScreen(Thisform.HWnd,;

    lnLeftBorder,;

    lnTopBorder+lnTitleHeight,;

    ThisForm.Width,;

    ThisForm.Height)

    This.oGfx.clear(.Color.transparent)

    ENDIF

    Vivek

    This code sets the top boubdary of the image as

    lnTopBorder+lnTitleHeight,;

    If no title then just change the code to :

    lnTopBorder,;  (remove the height of the title bar)

    If using a borderless form change 

    lnLeftBorder,;

    lnTopBorder+lnTitleHeight,;

    to

    0,;

    0+lnTitleHeight

    If using your own skin, then you will need to get the height of your skin titlebar and use that. The code segment describes the area to be captured as Left,Top,width,Height so change as needed. It must be within the boundaries of your form or you get the error! You have the source so make the changes.

    HTH

    Bernard

  • Vivek Deodhar says:

    Bernard,

    Thanks, it is working now. However, activex controls are still on top, but I think that can’t be helped. or am I wrong?

    Vivek

    Of course it is.Smile <img src=” src=”/emoticons/emotion-1.gif”> Re Activex, you are wrong. It can be helped and I have done it.

    Check my previous blog post:

    http://weblogs.foxite.com/bernardbout/archive/2008/09/13/6768.aspx

    Now you have the source code for both techniques, you combine them and send it to me.

  • Zahid says:

    If I put it in the _screen.addobject(‘LightBox’,’Bbgdilightbox’) it shows error “LOBITMAP is not an object”.
    I even changed the code to:

    IF VARTYPE(NVL(This.Parent.oBitmap,””)) # “O”
      This.Parent.oBitmap = .Bitmap.FromScreen(Thisform.HWnd,;
    IIF(ThisForm.BorderStyle = 0,0,lnLeftBorder),;
    IIF(ThisForm.BorderStyle = 0,0,lnTopBorder)+IIF(ThisForm.Titlebar =0,0, lnTitleHeight),ThisForm.Width,ThisForm.Height)
      This.oGfx.clear(.Color.transparent)
    ENDIF

    But it doesn’t work.

    And when i try to quit vfp it show error “UnKnown member controls”
    from ImgCanvas.Destroy()

    Zahid

    First off this class is not a blackbox. I have provided the source so that anyone can adapt it to their needs. The class is only a guide to assist you to enhance it by examining and understanding the source and modifying it to your needs.

    _Screen

    .System.Drawing.Bitmap.FromScreen()

    is used to get a screen capture just before displaying the messagebox. If you want to capture a form you send the form hWnd as well as other parameters. If you want _screen you just call the method with no parameters.

    So all you need to do is change this bit of code:

    IF VARTYPE

    (NVL(This.Parent.oBitmap,“”)) # “O”

        This.Parent.oBitmap = .Bitmap.FromScreen(Thisform.HWnd,;

            lnLeftBorder,;

            lnTopBorder+lnTitleHeight,;

            ThisForm.Width,;

            ThisForm.Height)

        This

    .oGfx.clear(.Color.transparent)

    ENDIF

    to this to check if the object is in the _screen:

    IF VARTYPE

    (NVL(This.Parent.oBitmap,“”)) # “O”

        * are we running from _screen?

        IF This.Parent.Parent.Name = “Screen”

            This.Parent.oBitmap = .Bitmap.FromScreen()

        ELSE

            This

    .Parent.oBitmap = .Bitmap.FromScreen(Thisform.HWnd,;

            lnLeftBorder,;

            lnTopBorder+lnTitleHeight,;

            ThisForm.Width,;

            ThisForm.Height)

        ENDIF

        This

    .oGfx.clear(.Color.transparent)

    ENDIF

    And everything else will work as it should. How do I know? I took the time to learn how to use the GDIPlusx classes.

    See also this link http://weblogs.foxite.com/vfpimaging/archive/2007/01/17/3145.aspx

  • Subrata Paul says:

    Hi Bernard

    We are using this bbGdiLightbox effect feature in our application. In XP, 2000 and Vista – it is working fine. But in Windows 7 the same application is not working (it gives a cross window backside of the current form).

    Do you have any idea why it is not working in Windows 7?

    Best Regards
    Subrata
    spal@factsoftware.com

    Don’t know. This happens when the Bitmap cannot be generated. Do you have the GDI DLL installed in WINDOWS 7? I have no way of testing this since I don’t have win 7. Try Tracing in VFP to see where in the class this is occurring.

Leave a Reply

Your email address will not be published. Required fields are marked *