AArnie
asked on
Transparent frame control not refreshing before being displayed.
Hi,
I am attempting to inplement some code that sets the background colour of a VB6 Frame control to transparent. I am doing this because I am using XP themes on the application and the colours of the frame and tab control that it sits on are different.
Thia is the code I am using.
************************** ********** ********** **
Main form
************************** ********** ********** **
Public Sub Main()
frmMain.fraMediaplayer.Bac kColor = &HFF&
frmMain.Show
frmMain.Refresh
MakeFrameTransparent frmMain.fraMediaplayer
End Sub
************************** ********** ********** **
Module 1
************************** ********** ********** **
Option Explicit
Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) _
As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject _
As Long) As Long
Public Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 _
As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 _
As Long) As Long
Public Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn _
As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, _
ByVal nCombineMode As Long) As Long
Public Declare Function GetPixel Lib "gdi32" (ByVal hDC As Long, _
ByVal x As Long, ByVal y As Long) As Long
Public Declare Function SetWindowRgn Lib "user32" (ByVal hwnd _
As Long, ByVal hRgn As Long, ByVal bRedraw As Long) As Long
Public CtrlDc As Long
Public Function GetTransparentFrame(Ctrl As Frame) As Long
Dim lHeight As Long
Dim lWidth As Long
Dim lTemp As Long
Dim lSkin As Long
Dim lStart As Long
Dim lLine As Long
Dim lColumn As Long
Dim lBackColor As Long
lSkin = CreateRectRgn(0, 0, 0, 0)
With Ctrl
'Form.ScaleMode = vbTwips
lHeight = .Height / Screen.TwipsPerPixelY
lWidth = .Width / Screen.TwipsPerPixelX
'Form.ScaleMode = vbPixels
'lHeight = .Height
'lWidth = .Width
CtrlDc = GetDC(.hwnd)
lBackColor = Ctrl.BackColor
For lLine = 0 To lHeight - 1
lColumn = 0
Do While lColumn < lWidth
Do While lColumn < lWidth And GetPixel(CtrlDc, lColumn, lLine) = lBackColor
lColumn = lColumn + 1
Loop
If lColumn < lWidth Then
lStart = lColumn
Do While lColumn < lWidth And GetPixel(CtrlDc, lColumn, lLine) <> lBackColor
lColumn = lColumn + 1
Loop
If lColumn > lWidth Then lColumn = lWidth
lTemp = CreateRectRgn(lStart, lLine, lColumn, lLine + 1)
Call CombineRgn(lSkin, lSkin, lTemp, 2)
Call DeleteObject(lTemp)
End If
Loop
Next lLine
End With
GetTransparentFrame = lSkin
End Function
Public Sub MakeFrameTransparent(Ctrl As Frame)
Dim lSkin As Long
Ctrl.Visible = True
'Set the background colour.
lSkin = GetTransparentFrame(Ctrl)
Call SetWindowRgn(Ctrl.hwnd, lSkin, True)
End Sub
************************** ********** ********** **
When the form is loaded/displayed I can see the red background of the frame for a short period before it changes to transparent. If I put a break point in on >frmMain.show<, and step through the code, then it works, but take out the breakpoint - or compile into an exe and run - and I see the colour change.
Can the form be updated/painted before being shown on the screen, so that the red backgound is never seen?
Thanks,
AArnie.
I am attempting to inplement some code that sets the background colour of a VB6 Frame control to transparent. I am doing this because I am using XP themes on the application and the colours of the frame and tab control that it sits on are different.
Thia is the code I am using.
**************************
Main form
**************************
Public Sub Main()
frmMain.fraMediaplayer.Bac
frmMain.Show
frmMain.Refresh
MakeFrameTransparent frmMain.fraMediaplayer
End Sub
**************************
Module 1
**************************
Option Explicit
Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) _
As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject _
As Long) As Long
Public Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 _
As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 _
As Long) As Long
Public Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn _
As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, _
ByVal nCombineMode As Long) As Long
Public Declare Function GetPixel Lib "gdi32" (ByVal hDC As Long, _
ByVal x As Long, ByVal y As Long) As Long
Public Declare Function SetWindowRgn Lib "user32" (ByVal hwnd _
As Long, ByVal hRgn As Long, ByVal bRedraw As Long) As Long
Public CtrlDc As Long
Public Function GetTransparentFrame(Ctrl As Frame) As Long
Dim lHeight As Long
Dim lWidth As Long
Dim lTemp As Long
Dim lSkin As Long
Dim lStart As Long
Dim lLine As Long
Dim lColumn As Long
Dim lBackColor As Long
lSkin = CreateRectRgn(0, 0, 0, 0)
With Ctrl
'Form.ScaleMode = vbTwips
lHeight = .Height / Screen.TwipsPerPixelY
lWidth = .Width / Screen.TwipsPerPixelX
'Form.ScaleMode = vbPixels
'lHeight = .Height
'lWidth = .Width
CtrlDc = GetDC(.hwnd)
lBackColor = Ctrl.BackColor
For lLine = 0 To lHeight - 1
lColumn = 0
Do While lColumn < lWidth
Do While lColumn < lWidth And GetPixel(CtrlDc, lColumn, lLine) = lBackColor
lColumn = lColumn + 1
Loop
If lColumn < lWidth Then
lStart = lColumn
Do While lColumn < lWidth And GetPixel(CtrlDc, lColumn, lLine) <> lBackColor
lColumn = lColumn + 1
Loop
If lColumn > lWidth Then lColumn = lWidth
lTemp = CreateRectRgn(lStart, lLine, lColumn, lLine + 1)
Call CombineRgn(lSkin, lSkin, lTemp, 2)
Call DeleteObject(lTemp)
End If
Loop
Next lLine
End With
GetTransparentFrame = lSkin
End Function
Public Sub MakeFrameTransparent(Ctrl As Frame)
Dim lSkin As Long
Ctrl.Visible = True
'Set the background colour.
lSkin = GetTransparentFrame(Ctrl)
Call SetWindowRgn(Ctrl.hwnd, lSkin, True)
End Sub
**************************
When the form is loaded/displayed I can see the red background of the frame for a short period before it changes to transparent. If I put a break point in on >frmMain.show<, and step through the code, then it works, but take out the breakpoint - or compile into an exe and run - and I see the colour change.
Can the form be updated/painted before being shown on the screen, so that the red backgound is never seen?
Thanks,
AArnie.
ASKER
Hi Burbble
If I move the line: -> "MakeFrameTransparent frmMain.fraMediaplayer" then the backcolor is always red, and if I move the form off of he screen then reposition, it is still red.
If I move the form 50% on the screen and then move it, the half that was on the screen goes transparent, but the half that was off of the screen stays red.
It seems that the form has to be visible on screen before it can be made transparent. If it is not visible on the screen then no matter what I do before it is visible is reverted back before being displayed. Perhaps the backcolor is being buffered in memory somewhere and never updated until it has been displayed.
I'm not sure.
AArnie.
If I move the line: -> "MakeFrameTransparent frmMain.fraMediaplayer" then the backcolor is always red, and if I move the form off of he screen then reposition, it is still red.
If I move the form 50% on the screen and then move it, the half that was on the screen goes transparent, but the half that was off of the screen stays red.
It seems that the form has to be visible on screen before it can be made transparent. If it is not visible on the screen then no matter what I do before it is visible is reverted back before being displayed. Perhaps the backcolor is being buffered in memory somewhere and never updated until it has been displayed.
I'm not sure.
AArnie.
Well, after many hours of contemplation and experimentation, I still have no solution. The problem is that the GetPixel function returns -1 for any part of the Frame that is offscreen (since Frames don't have an AutoRedraw property, they aren't drawn when not onscreen). I don't think there is a solution for this, aside from using a different control (like a PictureBox).
This probably isn't of any use, but I also tried this:
CtrlDc = GetDC(Ctrl.hwnd)
For y = 0 To Ctrl.Height - 1
For x = 0 To Ctrl.Width - 1
If GetPixel(CtrlDc, x, y) = Ctrl.BackColor Then
SetPixel CtrlDc, x, y, GetPixel(frmMain.hdc, x + Ctrl.Left, y + Ctrl.Top)
End If
Next x
Next y
Which also didn't work, because of the GetPixel thing. Plus, since Frames don't AutoRedraw, with this code you can move the Form offscreen and then back on to make the Frame red again.
Hmm...
-Burbble
This probably isn't of any use, but I also tried this:
CtrlDc = GetDC(Ctrl.hwnd)
For y = 0 To Ctrl.Height - 1
For x = 0 To Ctrl.Width - 1
If GetPixel(CtrlDc, x, y) = Ctrl.BackColor Then
SetPixel CtrlDc, x, y, GetPixel(frmMain.hdc, x + Ctrl.Left, y + Ctrl.Top)
End If
Next x
Next y
Which also didn't work, because of the GetPixel thing. Plus, since Frames don't AutoRedraw, with this code you can move the Form offscreen and then back on to make the Frame red again.
Hmm...
-Burbble
ASKER
Well, thanks for trying.
Perhaps I'll have to look at a different approach. Maybe I can subclass another control, or find a 3rd party one.
If I get a solution I'll post it here.
Thanks anyway,
AArnie.
Perhaps I'll have to look at a different approach. Maybe I can subclass another control, or find a 3rd party one.
If I get a solution I'll post it here.
Thanks anyway,
AArnie.
Ok, sorry I couldn't help more :/
-Burbble
-Burbble
This may be helpful, it explains a workaround (however unsupported):
INFO: Visual Basic 6.0 Does Not Support Windows XP Themes or Visual Styles
http://support.microsoft.com/?id=309366
INFO: Visual Basic 6.0 Does Not Support Windows XP Themes or Visual Styles
http://support.microsoft.com/?id=309366
ASKER
I already use the workaround mentioned here. This is part of the problem, as I have a tab control on a form, and my frame sits within this. In VB6 the background is a constant colour, but with the XP styles there is a gradient - hence this is why I am after the transparency.
Thanks for the input though. I'll keep trying.
Cheers,
AArnie.
Thanks for the input though. I'll keep trying.
Cheers,
AArnie.
Good reading:
Use Manifests for the Look and Feel of Windows XP
http://www.thescarms.com/vbasic/XPStyle.asp
Their sample writes the manifest file on-the-fly. I tried the sample and the frame control paints normally using the standard themes that come w/XP.
Do you have a third party skinner or theme program installed?
Use Manifests for the Look and Feel of Windows XP
http://www.thescarms.com/vbasic/XPStyle.asp
Their sample writes the manifest file on-the-fly. I tried the sample and the frame control paints normally using the standard themes that come w/XP.
Do you have a third party skinner or theme program installed?
ASKER
Hi people,
Apologies for not repling.
Thanks for your responses. I don't think I found the answer I was looking for however. Finally I found the following 3rd party control, which is currently free, and for the moment suits my requirements.
http://www.innovasys.com/ -> Freecontrols.
If nobody has any objections I'll put a request in to have points refunded in the next day or so.
AArnie.
Apologies for not repling.
Thanks for your responses. I don't think I found the answer I was looking for however. Finally I found the following 3rd party control, which is currently free, and for the moment suits my requirements.
http://www.innovasys.com/ -> Freecontrols.
If nobody has any objections I'll put a request in to have points refunded in the next day or so.
AArnie.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
MakeFrameTransparent frmMain.fraMediaplayer
in the Form_Load event of frmMain.
Alternatively, you could have the default window position of the form somewhere off screen, and then move it after you execute MakeFrameTransparent, like this:
frmMain.Move (Screen.Width - frmMain.Width) * 0.5, (Screen.Height - frmMain.Height) * 0.5
-Burbble