Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Transparency: Make the Window Background of Your VFP Forms transparent (Windows XP ... 10 / 11)

Status
Not open for further replies.

StefanFoerner

Programmer
Mar 23, 2015
93
DE
Hi everyone,

how it works:

1) set the Backcolor of Your Form to colorKey
2) make Your Form a Layered Window
3) set the colorKey of this Layered Window: this makes the Background transparent :)

Code:
#DEFINE GWL_EXSTYLE -20

#DEFINE WS_EX_LAYERED 0x00080000

#DEFINE LWA_COLORKEY 0x1


FUNCTION _GetWindowLong( hWnd, indexVal )
	LOCAL ret
	
	DECLARE INTEGER GetWindowLong IN WIN32API;
			INTEGER hWnd,;
			INTEGER nIndex
			
	ret = GetWindowLong( hWnd, indexVal )
	
	RETURN ret
ENDFUNC


FUNCTION _SetWindowLong( hWnd, indexVal, newValue )
	LOCAL ret
	
	DECLARE INTEGER SetWindowLong IN WIN32API;
			INTEGER hWnd,;
			INTEGER nIndex,;
			INTEGER dwNewLong
			
	ret = SetWindowLong( hWnd, indexVal, newValue )
	
	RETURN ret
ENDFUNC


FUNCTION layeredWindowActivate( hWnd )		&& Activate Layered Window
	LOCAL winStyle
	
	winStyle = _GetWindowLong( hWnd, GWL_EXSTYLE )		&& get Extended Window Style
	
	winStyle = BITOR( winStyle, WS_EX_LAYERED )		&& add Layered Window Style
	
	_SetWindowLong( hWnd, GWL_EXSTYLE, winStyle )		&& set Extended Window Style
ENDFUNC


FUNCTION _SetLayeredWindowAttributes( hWnd, crKey, alphaVal, flagsVal )
	LOCAL ret
	
	DECLARE INTEGER SetLayeredWindowAttributes IN WIN32API;
			INTEGER hWnd,;
			INTEGER crKey,;
			INTEGER bAlpha,;
			INTEGER dwFlags
			
	ret = SetLayeredWindowAttributes( hWnd, crKey, alphaVal, flagsVal )
	
	RETURN ret
ENDFUNC


FUNCTION windowColorKeySet( hWnd, colorKey )		&& set colorKey of Layered Window, must be equal to Form Backcolor
	layeredWindowActivate( hWnd )
	
	_SetLayeredWindowAttributes( hWnd, colorKey, 0, LWA_COLORKEY )
ENDFUNC



* now we start the Transparency Effect
* ------------------------------------

* at Design Time set the Form Property Desktop = .T. !!!

THISFORM.LockScreen = .T.		&& don't make any changes to the window immediatly

colorKey = RGB( 191, 192, 193 )		&& see description below

THISFORM.BackColor = colorKey		&& set Form Backcolor to colorKey

windowColorKeySet( hWnd, colorKey )	&& this makes the Background transparent

THISFORM.LockScreen = .F.		&& make all changes to the window at once


hwnd: use the hWnd of Your VFP Form (or _VFP.hWnd or _SCREEN.hWnd ??? or etc.)

colorKey: RGB( x, y, z ) three slightly different values and the window background remains clickable
colorKey: RGB( x, x, x ) three equal values and the window background becomes clickable through
colorKey: Controls on the Form are rendered to this Color in transition to the background !!!
              (Visual FoxPro doesn't know the Transparency Effect of the background)


Screenshot: 3 VFP Forms with Transparency, BorderStyle = 0 (No Border), TitleBar = 0 (Titlebar Off): www.memotech.de/WindowTransparency/WindowTransparency.jpg

=> Windows Fluent Design: next week we want to blur the window background of VFP Forms as an extension based on the code above :)


Regards, Stefan
 
Before you go on about something like this, perhaps look into the VFPX Win32API project, if there is a sample

I find this:
and also this:
and also linked in on of these

Just by the way, the VFPX Win32API samples make a comment on ShowWindow=2 && important!!
While that's not very verbose, you learn this does only work for top level forms. (And ShowWindow = 2 defines a forma s top level form.
Whereas the latest documentation of SetLayeredWindowAttributes states that this limitation to top level forms was only until Windows 7 and Windows versions since 8 allow to use it on child windows, too. But within the VFP IDE at least, I only get this to work for top level forms, even on Windows 10. No idea what's right or wrong - documentation, VFP or reality.

Chriss
 
This looks good, Stefan. Thanks for posting it.

I used a similar technique some years ago to create a "fading" form class. When you launch a form based on the class, instead of appearing instantly, the form gradually fades in, taking a second or two to do so. Similarly, when you close the form, it gradually fades out. I think this can add quite a pleasing effect - provided you don't overdo it.

If anyone is interested, you can download a copy of my class from this page: Add a fading effect to your forms. The accompanying article explains how it works.

A limitation of the class is that it only works with top-level forms (I don't exactly remember why). I often use it to create small message windows that fade in near the bottom of the screen to alert the user to some situation, and then gently fade out again.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Chriss,

thankx for hints and the links!

My post still has some new information:
- how to make the transparent background clickable
- how to make the transparent background clickable through
- how Visual FoxPro renders controls to the background

Just tested my Form with transparent background:
- it works for all values: ShowWindow = 0 or ShowWindow = 1 or ShowWindow = 2 :)

Regards, Stefan
 
Hi Chriss, hi Mike,

- Addendum: when ShowWindow = 0 or ShowWindow = 1, You must set Desktop = .T.

Regards, Stefan
 
Thanks Stefan,

that works, but also makes it effectively a top level form.

Code:
Declare INTEGER IsTopLevelWindow in user32;
   INTEGER nHwnd

loDesktopForm = CreateObject("DesktopForm")
loStandardForm = CreateObject("Form")
Activate Screen 
? 'Desktop form is top level:',IsTopLevelWindow(loDeskTopForm.Hwnd)
? 'Standard form is not top level:',IsTopLevelWindow(loStandardForm.Hwnd)

Define Class DesktopForm as Form
   DeskTop = .T.
EndDefine

Chriss
 
Hi Mike,

please remember to check the setting Desktop = .T.

Regards, Stefan
 
I'm not sure I agree with Chris that setting ShowWindow = 0 and Desktop = .T. effectively makes it a top-level form. Setting Desktop to .T. allows the form to float outside the main window. But, unlike a top-level form, it doesn't remain visible if you minimise or hide the main window, and it doesn't have its own taskbar button.

Not that any of that really matters. It's still worth making those settings - an improvement on what I had before.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Stefan,

You said:


Windows 8:
The WS_EX_LAYERED style is supported for top-level windows and child windows. Previous Windows versions support WS_EX_LAYERED only for top-level windows.

The article you cited says the same.

Interestingly, I just tested the code on my ancient Windows 7 system, and it seems to work correctly (that is, with ShowWindow = 0 and Desktop = .T.)

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Chriss,

for me IsTopLevelWindow( hWnd ) always returns 1 = .T.

any combinations of ShowWindow = 0, 1, 2 and Destop = .F., .T. => always 1 = .T. ?????????

Regards, Stefan
 
Stefan,

For me, testing on Windows 10, a normal form, just the CreateObject("Form"), which has Desktop=.F. and ShowWindow = 0 (in Screen) does not work. IsTopLevelWindow returns 0,.

I know you pointed out DeskTop =.T. solves that, and it does. But then IsTopLevelWindow returns 1, so effectively it is not a child form of the screen anymore. It only becomes movable outside of the screen top level form, because it becomes a top level form itself. In the terms that regard Windows, not VFP, and that matters more.

So, if you set Desktop=.T. IsTopLevelForm becomes 1, even though ShowWindow is still 0.

Notice, some VFP properties only determine what happens at form instanciation. They are also readonly, not only because changing them while the form already is created is pointless, then.

VFP form properties are sometimes strange in comparison to what the actual form properties and also behaviors are. You can set a VFP form to Modal and Top Level, it will at runtime not behave modal, even though WindowType is still 1. So that VFP setting loses its meaning and the VFP property WindowType therefoe also doesn't reflect what's the real state of the form. I'd say this is the same about ShowWindow. You can't have a screen child form that also can be moved outside of the screen, it can only work when the form is made top level, and that's exactly what happens.

Chriss
 
I've now updated my article to say that you can now have ShowWindow set to 0 or 1, but, if you do, you must set Desktop to .T. This applies from Windows 8. (I didn't mention the unexpected fact that it also seems to work with Windows 7, so as not to confuse the issue. In any case, that's hardly likely to affect more than a handful of developers.)

Thanks to Stefan and Chris for helping to clarify this.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Mike,

I assume Chriss is right in everything he wrote
if you set Desktop = .T., VFP makes the window internally a top level window - not shown in the Taskbar
that's why your code now also works with Windows 7

I believe it even works with Windows 2000, XP and Vista ...

Regards, Stefan
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top