From: Bee on 10 Jan 2010 13:31 On Jan 9, 7:45 pm, Just_a_...(a)home.net wrote: > I have a little clock with a color-key type of invisibility. > > In Windows XP, it works just fine. In Vista, I can move the form by > clicking and dragging in the invisible area. It is invisible but still > "there" to Vista. > > Here's the code I have used for years to prepare the form: > > Public Const InvisibleColor = 16744705 > > 'Prepare for Invisibility > Ret = GetWindowLong(Me.hwnd, GWL_EXSTYLE) > Ret = Ret Or WS_EX_LAYERED > SetWindowLong Me.hwnd, GWL_EXSTYLE, Ret > 'Set the opacity of the layered window to 128 > SetLayeredWindowAttributes Me.hwnd, InvisibleColor, 0, LWA_COLORKEY > > Then the usual to invoke it: > > gbInvisible = GetSetting(App.EXEName, "Options", "Invisible", False) > If gbInvisible Then Me.BackColor = InvisibleColor > > Is there an update to make it work properly on Vista? > > Mike What happens when you turn off Aero?
From: Oxana on 12 Jan 2010 02:01 ...Same problem. After switching to Aero Theme from any other my LayeredWindow becomes invisible.. but still exists for Vista. UpdateLayeredWindow function doesn't return any mistakes. Window is invisible even if i use ULW_OPAQUE.. Playing with BLENDFUNCTION structure doesnt give any result too. Need help! "Bee" wrote: > On Jan 9, 7:45 pm, Just_a_...(a)home.net wrote: > > I have a little clock with a color-key type of invisibility. > > > > In Windows XP, it works just fine. In Vista, I can move the form by > > clicking and dragging in the invisible area. It is invisible but still > > "there" to Vista. > > > > Here's the code I have used for years to prepare the form: > > > > Public Const InvisibleColor = 16744705 > > > > 'Prepare for Invisibility > > Ret = GetWindowLong(Me.hwnd, GWL_EXSTYLE) > > Ret = Ret Or WS_EX_LAYERED > > SetWindowLong Me.hwnd, GWL_EXSTYLE, Ret > > 'Set the opacity of the layered window to 128 > > SetLayeredWindowAttributes Me.hwnd, InvisibleColor, 0, LWA_COLORKEY > > > > Then the usual to invoke it: > > > > gbInvisible = GetSetting(App.EXEName, "Options", "Invisible", False) > > If gbInvisible Then Me.BackColor = InvisibleColor > > > > Is there an update to make it work properly on Vista? > > > > Mike > > What happens when you turn off Aero? > . >
From: Mike Williams on 12 Jan 2010 05:40 <Just_a_fan(a)home.net> wrote in message news:g1jik5hrpetmp6ra24pevtijn0koin6na1(a)4ax.com... > I have a little clock with a color-key type of invisibility. > In Windows XP, it works just fine. In Vista, I can move the > form by clicking and dragging in the invisible area. It is invisible > but still "there" to Vista. I know this solves only part of the problem but on the presumption that you are allowing the user to drag the Form by releasing capture and sending a button down message then why don't you do that only if the user clicks a part of the Form that is not set to the transparent colour, something like: Private Sub Form_MouseDown(Button As Integer, Shift As Integer, _ X As Single, Y As Single) If Button = vbLeftButton And Point(X, Y) <> InvisibleColor Then ReleaseCapture SendMessageLong Me.hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0& End If End Sub You'll still need to look for a means of preventing the Form from picking up the focus when the user clicks a transparent area of it, but at least it will prevent the Form from moving under such conditions and it might be sufficient to get you by until you find a better solution. Mike
From: Mike Williams on 12 Jan 2010 07:18 <Just_a_fan(a)home.net> wrote in message news:g1jik5hrpetmp6ra24pevtijn0koin6na1(a)4ax.com... > In Windows XP, it works just fine . . . but In Vista > [whilst running Aero] I can move the form by clicking > and dragging in the invisible area. It is invisible but still > "there" to Vista. Further to my previous response, you can solve the problem in a better way (solving both parts of the problem) by setting the translucency and the transparent colour exactly as you are doing now, presumably something like: SetLayeredWindowAttributes Me.hwnd, transColor, 128, _ LWA_COLORKEY Or LWA_ALPHA .. . . and then following that line with a line with another line to set the window region, such as: SetWindowRgn Me.hwnd, Rgn1, True .. . . where Rgn1 is a region created using one of the regular shaped region function (CreateEllipticRgn for example if your clock is a nice round shape) or alternatively a region created in code from a bitmap (either drawn or loaded) by combining smaller rectangular regions into one whole if your clock (or whatever) is irregularly shaped. I've just tried that now on both regular and irregularly shaped images and the translucency and the region transparency work fine together (although the LWA_COLORKEY flag in the call to SetLayeredWindowAttributes is of course no longer actually required when using a region to set the shape). It works fine both in XP and in Vista, regardless of whether Vista is running Aero or not. Mike
From: Mike Williams on 25 Jan 2010 06:36
<Just_a_fan(a)home.net> wrote in message news:bf9ql5p168nkt791dcli7ajj33tmvfa8sr(a)4ax.com... > Again a miss but thanks for answering. I think you're dismissing my suggestion without even giving it a try. Personally I reckon it will work fine and will solve your problem. It is at the very least worth giving it a try. > This is a VERY irregular form and the parts which are visible > and invisible change every second. It is an odd clock. Go to > Planet-Source-Code, search for Mike Morrow and get the > Triangular Clock under that name. Compile it, take it to Vista > and you should see what I mean. Dots go on and off every > second & minute and become either Red/Green or invisible. > Yes, much of the form stays invisible all of the time but this, > too, is very irregular, being the area outside the dots. I've just downloaded and ran your code and I can see that your triangular clock, although quite small, has a fairly complex shape, with all those little separate circles and pieces of text and other stuff, at least as far as creating a region "on the fly" is concerned, but I still think it is very "doable" using the suggestion I made in my previous response. I know that it would be necessary to examine the image pixel by pixel in order to create such a complex shaped region, but examining pixels is very quick if you use code to load the pixel data into a VB array so as to get rid of the need to repeatedly call GetPixel. Using that code to examine the image data and determine all the required little rectangular regions and then combining all those subregions into one main region is obviously going to take much more time than simply examining the pixel data would take of course, but it is nevertheless still reasonably quick if you do it correctly > Dots go on and off every second & minute > and become either Red/Green or invisible. Yes, I can see that you are using Shape Controls for those things and are effectively using them to create a slightly different composite "image" which changes in certain parts every second. That part of your code could easily be replaced by some simple drawing instructions though. Even using the native VB Circle method you should be able to draw all of those 25 little filled (or unfilled) circles and print the small amount of text which displays the time all in a very short space of time, probably something less than half a millisecond for the full drawing even on fairly modest machines. That then leaves just the region to create from the complex finished drawing, so that you can set the region in order to overcome your current display problems on Vista when running Aero. Admittedly analyzing the drawing and creating and setting the complex region is going to be by far the most time consuming part of the job, taking much longer than the half millisecond needed to create the drawing in the first place, but you should nevertheless be able to do it in the time available. In fact since first responding to your earlier messages in this thread I cobbled together some test code to show you how to create a small reasonably complex shaped drawing and get it into a region. At the time I was mainly concerned in providing you with something which actually works and which overcomes your Vista Aero problem, rather than worrying about the speed issue or about writing neat code, so it is a bit of a jumble at the moment, but it seems okay. I've just added some timer code to it in response to this latest post of yours and I think it will do the job for you. Using my own test image, which is created in the Form load event just for testing purposes and which consists of 5 fairly large coloured filled circles and a large point size piece of text, I have timed how long it takes the code to create and set the region and the translucency etc from that image. Code of such nature (which consists in a large part of examining data in a VB array) runs faster as a compiled exe than it does in the IDE of course, although of course the creation and cobbling together of the individual little regions into one composite region does slow it down a lot whether compiled or not, but I think it will be fast enough for you. In this test the main part of the drawing (the five relatively large coloured filled circles) and the "outline" part of what is effectively some "outline text with a transparent fill" are all treated as being part of the region and therefore semi translucent, and any point that is not within the irregular shaped drawing or is within the transparent fill of the outline text is treated as not being part of the region and therefore being totally transparent. If the mouse is anywhere on any of these transparent areas then you can "clcik through" onto the desktop (or whatever), and it works just as well in Vista when running Aero (because of the region) as it does otherwise. The shape of the drawing in my example (as far as creating a region is concerned) is reasonably complex, mainly because it includes some large point size outline text with an effectively transparent fill, and when testing as a standard native code compiled exe it does the entire job in an average of about 9 milliseconds on my own machine. I've just tried it again, this time using a copy of your own image of the triangular clock consisting of the 25 little circles and the text showing the time. Your own drawing is smaller, but is more complex because it contains 25 little circles and because the text, although not transparently filled, contains more and smaller characters. In fact it takes the same time on your drawing as it does on my own, an average of about 9 milliseconds. Since it will take certainly less than 1 millisecond to actually create a new drawing each time, or to modify the existing one, then that is a total of less than 10 milliseconds (say 10 milliseconds on average) both to create the drawing and to analyze it and create and set the complex region from it. So, on my machine at least, your clock would be updating itself once every second (once every 1000 milliseconds) and it will take just 10 milliseconds to perform the entire "next second" modification and to create and assign any new region that might be required. Your code will therefore be working for a maximum of only 1 per cent of the available time, and it will be spending the remaining 99 per cent of the time waiting for the next second to arrive. Sounds okay to me. Anyway, here's my example so you can try it out yourself on your own machine. Start a new VB project and place one PictureBox, one Label Control and two Command Buttons on the Form. Set the Form's BorderStyle property to None in the IDE. Then paste in the following code. Run it as a native code compiled exe. Clicking one button will cause the filled circles and the outline of the text to become semi translucent, with the remainder of the Form and the area within the outline of the characters becoming totally transparent. Even when running Vista in Aero mode you should find that the transparent areas (anywhere outside the filled circles and anywhere within the "transparent fill" of the outline characters) is properly "click through". The time taken to analyze the image and to create and assign the complex region will be displayed in the Label (in milliseconds). Click the other button to make the Form solid again. With Windoze being what it is you should of course click the buttons to set and reset the transparency / translucency a number of times and take the average of them. This is just a sample to test the speed of operation of course, and you will need to include the code to create your triangular clock image and to repeatedly pefform the necessary stuff every second but, as I have already mentioned, the drawing part of the code will take virtually no time at all by comparison (certainly less than an additional one millisecond). Let me know if it is any good for you. Anyway, here's the example code: Mike Option Explicit Private s1 As String, s2 As String Private Declare Function CreateRectRgn Lib "gdi32" _ (ByVal x1 As Long, ByVal y1 As Long, ByVal X2 As Long, _ ByVal Y2 As Long) As Long Private Declare Function CombineRgn Lib "gdi32" _ (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, _ ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long Private Declare Function DeleteObject Lib "gdi32" _ (ByVal hObject As Long) As Long Private Declare Function GetWindowRgn Lib "user32" _ (ByVal hWnd As Long, ByVal hRgn As Long) As Long Private Declare Function SetWindowRgn Lib "user32" _ (ByVal hWnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As Long Private Declare Function GetWindowLong Lib "user32" _ Alias "GetWindowLongA" (ByVal hWnd As Long, _ ByVal nIndex As Long) As Long Private Declare Function SetWindowLong Lib "user32" _ Alias "SetWindowLongA" (ByVal hWnd As Long, _ ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare Function SetLayeredWindowAttributes _ Lib "user32" (ByVal hWnd As Long, ByVal crKey As Long, _ ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long Private Declare Function SendMessageLong Lib "user32" _ Alias "SendMessageA" (ByVal hWnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long Private Declare Function ReleaseCapture _ Lib "user32" () As Long Private Declare Function GetDIBits Lib "gdi32" _ (ByVal hdc As Long, ByVal hBitmap As Long, _ ByVal nStartScan As Long, ByVal nNumScans As Long, _ lpBits As Any, lpBI As BITMAPINFO, _ ByVal wUsage As Long) As Long Private Declare Function timeBeginPeriod Lib "winmm.dll" _ (ByVal uPeriod As Long) As Long Private Declare Function timeEndPeriod Lib "winmm.dll" _ (ByVal uPeriod As Long) As Long Private Declare Function timeGetTime _ Lib "winmm.dll" () As Long Private Type BITMAPINFOHEADER biSize As Long biWidth As Long biHeight As Long biPlanes As Integer biBitCount As Integer biCompression As Long biSizeImage As Long biXPelsPerMeter As Long biYPelsPerMeter As Long biClrUsed As Long biClrImportant As Long End Type Private Type BITMAPINFO bmiHeader As BITMAPINFOHEADER End Type Private Const DIB_RGB_COLORS = 0 Private Const BI_RGB = 0 Private Const RGN_COPY = 5 Private Const RGN_OR = 2 Private Const WM_NCLBUTTONDOWN = &HA1 Private Const HTCAPTION = 2 Private Const GWL_EXSTYLE = (-20) Private Const WS_EX_LAYERED = &H80000 Private Const LWA_COLORKEY = &H1 Private Const LWA_ALPHA = &H2 Private transColour As Long, Opacity As Long Private oldRgn As Long, oldStyle As Long Private Sub Command1_MouseDown(Button As Integer, _ Shift As Integer, X As Single, Y As Single) Dim t1 As Long, t2 As Long Dim lStyle As Long, rgn1 As Long t1 = timeGetTime lStyle = oldStyle Or WS_EX_LAYERED SetWindowLong Me.hWnd, GWL_EXSTYLE, lStyle SetLayeredWindowAttributes Me.hWnd, transColour, _ Opacity, LWA_COLORKEY Or LWA_ALPHA rgn1 = RegionFromImage(Picture1, transColour) SetWindowRgn Me.hWnd, rgn1, True DeleteObject rgn1 t2 = timeGetTime Label1.Caption = Format(t2 - t1) & " msecs" End Sub Private Sub Command2_MouseDown(Button As Integer, _ Shift As Integer, X As Single, Y As Single) SetWindowLong Me.hWnd, GWL_EXSTYLE, oldStyle SetWindowRgn Me.hWnd, oldRgn, True Label1.Caption = "" End Sub Private Sub Form_Load() Dim X As Long, Y As Long timeBeginPeriod 1 ' set timing resolution ' (in the following line make sure you use a colour that ' is actually available as a solid colour in the typical ' "5-6-5 bit" RGB arrangement of a system that might be ' running its display at the old low 16 bit colour depth, ' or alternatively you can check the colour depth of the ' system in code and omit the region stuff altogether on ' 16 bit systems since they cannot be running Vista in ' Aero mode and the Aero problem will not therefore arise) transColour = RGB(0, 0, 8) ' or any suitable unused colour ' set opacity (anything between 0 and 255) Opacity = 150 Me.ScaleMode = vbPixels Command1.Caption = "Make Translucent" Command1.Move 75, 150, 100, 40 Command2.Caption = "Make Solid" Command2.Move 10, 40 Label1.FontBold = True Label1.Move 20, 14, 60, 20 Me.BackColor = transColour ' The following is just some temporary code to draw ' an irregularly shaped bitmp for test purposes With Picture1 .Visible = False .ScaleMode = vbPixels .AutoRedraw = True .BorderStyle = vbBSNone .Move 0, 0, 250, 250 ' 250 x 250 pixels .BackColor = transColour .FillStyle = vbFSSolid .FillColor = vbRed Picture1.Circle (125, 125), 80, .FillColor .FillColor = vbBlue Picture1.Circle (200, 50), 49, .FillColor .FillColor = vbGreen Picture1.Circle (50, 50), 49, .FillColor .FillColor = vbMagenta Picture1.Circle (50, 200), 49, .FillColor .FillColor = vbCyan Picture1.Circle (200, 200), 49, .FillColor Picture1.Font.Name = "Times New Roman" Picture1.Font.Size = 38 Picture1.Font.Bold = True Picture1.ForeColor = vbBlue For Y = 89 To 91 For X = 59 To 61 Picture1.CurrentX = X Picture1.CurrentY = Y Picture1.Print "TEST"; Next X Next Y Picture1.ForeColor = transColour Picture1.CurrentX = 60 Picture1.CurrentY = 90 Picture1.Print "TEST"; Me.Width = ScaleX(.Width, vbPixels, vbTwips) Me.Height = ScaleY(.Height, vbPixels, vbTwips) End With Set Me.Picture = Picture1.Image oldStyle = GetWindowLong(hWnd, GWL_EXSTYLE) GetWindowRgn Me.hWnd, oldRgn End Sub Private Sub Form_Unload(Cancel As Integer) timeEndPeriod 1 ' release timing resolution End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, _ X As Single, Y As Single) If Button = vbLeftButton Then ' allow the user to move the Form ... ReleaseCapture SendMessageLong Me.hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0& End If End Sub Private Sub Form_DblClick() Unload Me End Sub Private Function RegionFromImage(p1 As PictureBox, _ transClr As Long) As Long Dim FullRgn As Long, LineRgn As Long, TempRgn As Long Dim X As Long, Y As Long, p1Pixel As Boolean Dim xBegin As Long, xEnd As Long, PicOld As Boolean Dim wide As Long, high As Long Dim transColourBGR As Long FullRgn = CreateRectRgn(0, 0, 0, 0) ' swap r and b of rgb to account for the fact that ' they are in that order in a DIBSection transColourBGR = transClr And &HFF00FF00 _ Or (transClr And &HFF&) * &H10000 _ Or (transClr And &HFF0000) \ &H10000 wide = Picture1.ScaleWidth high = Picture1.ScaleHeight ReDim myArray(0 To wide - 1, 0 To high - 1) As Long ' Get Picture1 pixels into array 1 Dim bmapinfo As BITMAPINFO With bmapinfo.bmiHeader .biSize = 40 .biWidth = wide ' make the following negative to cause the GetDIBits ' to return the scanlines in "top down" order instead ' of its normal "bottom up" order .biHeight = -high .biPlanes = 1 .biBitCount = 32 .biCompression = BI_RGB End With GetDIBits p1.hdc, p1.Image, 0, high, _ myArray(0, 0), bmapinfo, DIB_RGB_COLORS For Y = 0 To high - 1 For X = 0 To wide - 1 p1Pixel = (myArray(X, Y) <> transColourBGR) If p1Pixel = True Then If PicOld = False Then xBegin = X End If PicOld = True Else If PicOld = True Then xEnd = X LineRgn = CreateRectRgn(xBegin, Y, xEnd, Y + 1) CombineRgn FullRgn, FullRgn, LineRgn, RGN_OR DeleteObject LineRgn End If PicOld = False End If Next X If PicOld = True Then xEnd = X LineRgn = CreateRectRgn(xBegin, Y, xEnd, Y + 1) CombineRgn FullRgn, FullRgn, LineRgn, RGN_OR DeleteObject LineRgn End If PicOld = False Next Y RegionFromImage = FullRgn End Function |