With jpeg I can set a transparent background ? and that the vb recognise it ?
Printable View
Just FYI. Never use JPGs with that window shaper class. In most cases, JPGs will not preserve your "transparency" color througout the image. The reason is that JPG does not use a lossless compression algorithm. Bitmaps & GIFs are ok, bitmaps preferred. Also, regarding size. JPGs in most cases only save size when added to your project's picture properties or resource file or saved to file. When all is said and done, the JPG is converted to bitmap for window's use when it is displayed.
I am continuing read all you provided and making some tests, here is what i noted till now :
The class of LaVolpe in post #36 work well, thanks a lot it was very helpfull and does what i need.
The suggestions of using a picture box provided by MarMan, LaVolpe and baja_yu
at posts #13 #19 #20 #33 #37
Seems to work well with less code, but i noticed some weird things , I don't know if any of you has an explication :
Using the same Photo.gif picture :
1st, I tried the, it gave white background arround the arrow which not nice at all !vb Code:
Picture1.PaintPicture Image1.Picture, 1, 1
2nd, I tried with an image controls all to do the following and worked well
vb Code:
Image2.Move Image2.Left + Screen.TwipsPerPixelX, Image2.Top + Screen.TwipsPerPixelY
3rd, I tried it with picturebox, with same Photo.gif, it showed me a white background arround the arrow !!
4th, I set FontTransparent property to False, suddenly the white background went and become transparent and got same effect as ImageBox, so I said it's coming from this property ! I put it again to true, then i noticed that the background didn't go back to white and stayed transparent !Thus it's not this property that caused the white background
5th, I tried to add more picture boxes to make tests and the white background never appeared again !
6th, I tried again the, and it always give white background !vb Code:
Picture1.PaintPicture Image1.Picture, 1, 1
LaVolpe, Please Can you explain me this note ? Should i put on autoredraw or not ? am confused !
Quote:
Edited: Odds are that your picturebox will have AutoRedraw=True. If so, you will want to refresh the picturebox after all of your drawing is done.
by the way, if the class LaVolpe works well is it better to use it than the effect used by dealing with mouse move ?
Now i am reading the thread http://www.vbforums.com/showthread.php?t=553612 to see at the end what to use exactly.
I will keep you informed if I noticed more things
Didn't know that. I mostly add them to the picture property when building GUI elements, and I'm aware of the lossless compression but I can set the quality to that is still acceptable without any noticeable degradation. As it packs it in the frx and compiles them to the exe I use them to save on final file size.
@baja_yu. Higher JPG quality is definitely a player, but higher quality results in larger file size; a trade-off. As a rule, I always recommend against converting to JPG if color values are very important.
@justgreat. Yes you can have transparency with a bitmap, however, VB on its own will never display the bitmap with transparency. Besides png & gif, other common formats use transparency too: ico, cur, tga, tif
Edited: Just so there is no confusion. When I used "transparency color" in my previous reply, I was refering to whatever color should be made transparent throughout the image.
LaVolpe, thanks, but if in vb he can see transparency of bmp i think it's better for my case to use .gif
Right ?
Anyone has an idea about the weird thing i noted above #43 when making my tests ?
Don't know what Photo.Gif is. I don't see it anywhere.
Regarding your question. Gif is far easier if you are using a image control. I mentioned some of the drawbacks of using a image control in post #29. I don't know what method(s) you are currently decided upon.
Photo.Gif i mean with it the photo of the red button ! But also got the same with the arrow pic
As for the method, yesterday i slept, so today i will read the second thread http://www.vbforums.com/showthread.php?t=553612 to see what you said in it and decide what to use, but for what was said in this current thread I tried all yesterday :)
I will make some tries, and If using the mouse move events will give same result i will use it and if not i will use ur class, but in both cases i will try to study your class to learn because it's really perfect, very good job
Ok, I see what you are talking about. PaintPicture is not ideal for transparent GIFs. If you want to learn more, see "stdPicture Render Usage" linked in my signature below.
To summarize. PaintPicture is taking the bitmap representation of the GIF. The GIF is a bitmap as far as windows is concerned. You'd get the same result if you tried to use BitBlt/SetDIBits. When VB displays the GIF in a picturebox/image control, it is performing a masking operation on the DC to create transparency; PaintPicture does not do that. The .Picture.Render method will do that. In post #43 you mentioned you got the GIF to render with transparency by using PaintPicture; a fluke maybe, does the picturebox backcolor/forecolor have anything to do with it? I don't know, but rendering it properly with PaintPicture would be unexpected IMO.
Thanks LaVolpe for explication.
I read the other thread, the problem is that there are lots of notions that i don't know so it's gonna take me time to understand , do you have any link for a tutorial about all these notions ?
I am not new to VB, i work on vb since 99, but I never focused on the graphical issue that's why I have no clue about graphics. By the way, your article about render is very usefull.
I will either use your class (without understanding it for the moment), or I will use the other suggestion of making effects with mouse move.
but i have a question please ! TO add a caption to the button what is best to do ? adding a label inside the picture box ? if yes, should I repeat also in the label mouse move event, the same code as the one i put for the button to make sure that even if the mouse is over the caption the button is pressed ?
A label is the easiest. Just forward the mouse events for the label to the picturebox
Note that the X,Y coords will be off because they are in relation to the label, not the picturebox. If they are important, you'll have to offset them...Code:Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
' move the picbox down 1 by 1
End Sub
Private Sub Label1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call Picture1_MouseDown(Button, Shift, X, Y)
End Sub
Edited: Another easy option is to simply print the text. If done, ensure AutoRedraw=True for the pictureboxCode:Call Picture1_MouseDown(Button, Shift, X + Label1.Left, Y + Label1.Top)
Code:Picture1.CurrentX = 10 * Screen.TwipsPerPixelX ' if picbox scalemode is twips
Picture1.CurrentY = 70 * Screen.TwipsPerPixelY
Picture1.ForeColor = vbBlue
Picture1.Print "My Caption"
Thanks a lot LaVolpe, Once again you give clear and nice answers, I will try all you told me.
If i want to understand your class, what should i start looking for ? any tutorial or basic things that i should learn to be able to understand the nice class you provided, because I hope to understand it and not only to use it
A pixel in general terms is a rectangle on the screen, a small rectangle but still a rectangle (generally speaking). If you were to magnify an image 100x that uses a different color for each pixel, you should be able to clearly see the pixels as individual squares. This is the basis of the class.
The class builds rectangles that exclude "transparent" areas and only include the desired pixels. That's it in simple terms. Window's (O/S) requires its rectangles/squares to be the same size vertically for each row of rectangles. This means all rectangles on any single row must be the same height; can be different widths, but must be same height. The height of rectangles between different rows can be different sizes. Visualize the letter H. From top to bottom, each row of pixels have 2 pixels except the middle row which has pixels all the way across. Now imagine each pixel as a rectangle and the middle row as 1 long rectangle and you've got the general idea. The class simply creates rectangles only from the pixels in the picture that do not equal the pixel color that should be treated as transparent. The class picks the top left corner as the transparent color unless a color is passed explicitly.
When you apply a region to a window, the O/S cuts out the area not included in the region; thereby shaping the window. This is a nice way to shape windows but has limitations, mostly jaggies. You cannot create a smooth curve, circle, or diagonal with regions. Actually some diagonals can be rather smooth, but most will not be. By the way, regions apply to other things to, namely clip regions applied to an hDC to restrict drawing to a specific region of the DC.
You can see how this applies to your GIFs. The arrows will look nearly perfect, the pill button, not so much. Until Win2K came around, this was the best we could get. Now we have layered windows with alphablended edges, but they don't apply to controls, just to main-level windows.
Here's some reading/playing for you when you find the time. A project I designed that uses regions to locate a path between two points. Kind of similar to A* path finding algorithm
http://www.planet-source-code.com/vb...61062&lngWId=1
Thanks a lot LaVolpe, I will read all you said, but want to inform you that the code you provided didn't give any effect, am i missing something ? I put a picture box with autoredraw = true and picture (my .gif arrow pic)
vb Code:
Picture1.CurrentX = 10 * Screen.TwipsPerPixelX ' if picbox scalemode is twips Picture1.CurrentY = 70 * Screen.TwipsPerPixelY Picture1.ForeColor = vbBlue Picture1.Print "My Caption"
It worked, just printed where you couldn't see it :)
If your image size is less than 70 pixels tall, adjust the CurrentY value. Also adjust the CurrentX as needed. And last but not least, if your picturebox scalemode is pixels remove the multiplication by TwipsPerPixelX/Y
Here's a tip.
1) In the picturebox, add a label with the captioin you want to use
2) Make the label's font the same as the picturebox's font: same size, name, boldness, etc
3) Position the label on the picturebox where you want the text to be displayed
4) Jot down the Left & Top coordinates of the label
5) Use those values as the CurrentX & CurrentY coordinates
6) Hide/delete your label and try running project again. Delete label when no longer needed
LaVolpe,
-Yes you were right, after following your recommandation your code works, but I shouldn't put current X and Current Y in twip values even if my Scale mode is Twip, i had to put the values of X, Y in Pixel, so for the 10, 70, i put 0, 38 , it worked.
VB Code:
Picture1.CurrentX = 0 * Screen.TwipsPerPixelX ' if picbox scalemode is twips Picture1.CurrentY = 38 * Screen.TwipsPerPixelY Picture1.ForeColor = vbBlue Picture1.Print "My Caption
- Thanks a lot for your post #54 it was very usefull to understand theorically what is going on, but you said that :
.Quote:
You cannot create a smooth curve, circle, or diagonal with regions
If So than how to do curves when I see some skinned forms that are not rectangles ?
- You said also above the limitation of the Picturebox, one of them is that we can't use Tab with them, I am curious to know/learn in case I need the Tab, what should I do in this case ?
To get the smooth curves of skinned forms, I mentioned earlier that layered windows are used & that became available with Win2K. Those apply to forms only, not controls.
The Tab limitation was with image controls, not pictureboxes.
Following your Recommandation MarMan, LaVolpe and baja_yu : I tried 3 differents style : very basic ones
Test 1 : move picture box down 1px : It worked fine
Test 2 : USING 2 different picture state 'normal and 'pressed
Test 3 : Combination of Both moving down the button and change the picture
The Test 2 and 3 are not working properly,
Test 2 : I see a kind of flashing color if I do fast clicks on the button
Test 3 : Wrong behavior
First all goes well,if i click one click and not so fast on the boutton... Then if I start clicking double clicks or fast clicks, the behaviors are weird, there is a kind of flashing color like test 2, but what is weird is that at the beginning the button moves down (normal behavior), but after making fast clicks and doubbles clicks on it, it starts moving up !
I showed in two textboxes the x and Y of the picture box and found that when i make simple clicks they are constants, but when i do fast clicks or double clicks they start changing that's why button moves weird way !
Please, Anyone can check the code and tell me what is wrong ?
You'll have to handle double clicks manually, using flags as needed to let you know a double click occurred.
Here's how VB's picutrebox records double clicks:
-- mouseDown, mouseUp, Click, DblClick, mouseUp
Notice that you get 1 mouse down and 2 mouse up events. This means for every double click, you are moving the control up twice, but down just once; hence why it slowly sneaks up. You may want to treat a DblClick event as a mouseDown event. But play with it.
Ah now i Understand, thanks Lavolpe for explication, Once back home, I will try to edit the code to solve this problem and will let you know what it gave.
I got some questions please
1- In case I want to give the same shape to many buttons is it better to load my template photos of the button (pressed and unpressed),into two different image boxes, and on form load event of the form, i use the PaintPicture to copy it to each button ? and I use the Picture1.Print "My Caption" to give them caption
Or its better to create for each button 2 images like i did in the zip i attached ?
What is more performant and better to do ?
2- Is it possible with your class Lavolpe to load two different pictures for each button or your class just move the image inside the picture box ?
3- If i want to make an effect that the picture is pressed without moving it, is it doable ? to make it act like pressed and unpressed without moving it the 1px ?
4- can i add a 3rd state which is the mouse hover with red border of the picture ? if yes at which event i should do this ?
5- Any explication for why i see black color flash from time to other ? is it due to speed of vb to refresh pictures ?
For your questions:
1) It is best to use just 1 image control (hidden or not) for each image, no matter how many controls may be using that image. Simply uses less resources
2) You can call the RegionFromBitmap routine each time the shape changes, simply include the picture handle of the new shape. If the shape doesn't change, but the picture does, then just use Set Picture or PaintPicture to get the image into the picturebox
Example: The following just references your image control. Set Picture1.Picture = Image1.Picture. Any number of controls can reference the same picture.
3) If you are not changing the image nor moving the control, nor offsetting the drawn image, how will it imitate some pressed state? With a typical button, the image & caption are drawn 1 pixel down/right and the 3D borders (if any) are drawn to the opposite edges of the button.
4) To add any border to your picturebox, you will have to either a) shift the image 1 pixel & have your picturebox 2 pixels larger than needed to display the border without it drawing over the image; or b) simply draw the border and don't care if it covers a bit of the image. Regarding mouse hover, you get a mouse move event, correct? If you use a flag, if the flag is false when mouse move happens, it is the first time mouse enters the control & set flag=true. However, tracking when mouse leaves the control is problematic. But there are ways, some easier with windowed controls. Search for examples: "mouse enter exit SetCapture"
5) Probably, toggling visibility between your buttons is most likely the reason.
Thanks again LaVolpe for your support and answers.
Here are my notes about these points
1) I am trying to doing this,Putting 2 images control (1 with the pic of pressed and one with unpressed)
using theto copy these pictures as needed to all buttons in my application, but when I do this, I get an ugly background arround the image which is not what i want.vb Code:
Picture1.PaintPicture Image1.Picture, 1, 1
The background that appears is black if I set the transparency of my .gif a value between 1 and 255, and White if i set transparency to 0 (i am setting the transparency using Paint.net) ! By the way, in the image control,I don't see the background,it's just after appliying the PaintPicture
Is there anyway to avoid this ? If not, then I think my only choice will be to create as much pics as I have buttons and use them directly in picture box but it will require much more ressources (2 pics / boutton)
2)Thanks a lot for explication,i got you
3) I didn't say I don't want to offset etc...I wanted to know what are the steps I can do to imitate a real button behaviors , maybe reduce size of image from all sides once clicked ?
4) didn't understand it well how to make a red border,I should draw the border in the picture itself or the picture box border ?
I found this about
mouse enter exit SetCapture, I will try to apply it, thanks for the hint
5) I think the same
For your questions.
1) You are not going to avoid the background. Even if you use .Picture.Render vs. PaintPicture, you will avoid that black/white background, but then the picturebox backcolor will show.
3) Reducing the image is one option. Personally, I like the control moving myself, but that's my preference.
4) Drawing the border around the shape of the image will be challenging. The RegionFromBitmap can help there since it can return a region handle vs. shaping a window. With the returned region handle the API FrameRgn can be used to outline the region, then destroying the region & brush handles when done.
Good night, good luck. Heading to bed a bit early tonight; guess I'm getting old ;)
LaVolpe, thanks again
1) What are the remaining options ? to load for each button it's own picture right ? do I have other choice ?
From what you say, I may also try to use .Picture.Render and set the background of the image box to the same color as the form so that it won't appear right ? I will search about how to use the .Render and test
3) What functions do I need to reduce the size ? Just to learn how to do and see what it give as effect
4) I think the week-end I will work on that part but before let me end from previous problems :)
1) .Picture.Render will draw the GIF with transparency. You can look at the link in my signature below: "stdPicture Render Usage". Making your picbox backcolor same as form should fake picbox transaprency well, but won't help if your picbox is placed over graphics or gradient background. In that case, more complex code required to transfer form background contents to the picbox to fake transparency.
3) None. .Picture.Render can draw an image stretched/scaled as can PaintPicture
LaVolpe, thanks a lot, I am reading now about the render at least to learn, but guess what :
1)If i use what you said in post #63I won't get a background like with paintpicture, so I think this will be better than looking for complicated things right ?vb Code:
Set Picture1.Picture = Image1.Picture
Please can you explain to me the advantage of using the class you provided me, if I compare it to : create a gif with transparent background (alpha 0), then loading it into picture box ? I am asking because it's time for me now to decide what methode to use.
The only advantage of using that class is to shape the window to an image. That's all, in this case.
You mean by "window" the picture box ? so that it's changing the rectangle of picture box to give it the shape of the image inside it instead of beeing rectangle ?
Yes, of course. I thought you played with the example I posted awhile back?
I have tried it before, but yesterday i wanted to take a decision so i started messing with it again and realized that if the picturebox has a border the class doesn't change anything, that's why
Not true exactly. If the picturebox has a border, the left/top edges of the border may be left over. Same applies to shaping whole forms. Use borderless windows.
Can you explain me why?
Can we use your class also to shape a whole form or only stdpicture ?
I am asking because even if i didnt use it to make my buttons now, surely i will use it for later projects, because simply its very fast and nice
A form is a window, a picturebox is a window. A window is a window. Applying a region via the API SetWindowRgn doesn't care what kind of window it is as long as it has a window handle. The class works for all windows that have a window handle. How the region is created/shaped is important to the overall effect. Borderless windows should be used and if not, the region should be offset to account for borders. A region can be created from a bitmap as is done in that RegionFromBitmap routine, it can be circular, rectangular, oval, etc, etc using Windows region-based APIs too.
But regions can be used for far more than shaping windows as briefly described in previous posts. If you want to play with regions more, got to PSC and search for: LaVolpe Regions. You'll find several projects of mine that use regions in unusual ways.
I am trying to create a border to my button based on what you said but I am not succeeding !
I tried to use the region class, that way :
I read that if i pass second parameter 0 to your class that it returns the hwd of the shaped region, based on this I did the follwing :
vb Code:
Dim hBrush As Long Dim RegionHandle as Long Dim cRgn As New clsRegions hBrush = CreateSolidBrush(vbRed) Me.BackColor = vbYellow ' just to show the picturebox is indeed shaped RegionHandle = cRgn.RegionFromBitmap(Picture1.Picture.Handle, Picture1.hWnd) 'to shape RegionHandle = cRgn.RegionFromBitmap(Picture1.Picture.Handle, 0) 'to get the 'handle FrameRgn Picture1.Picture.Handle, RegionHandle, hBrush, 1, 1
by the way, when I pass 0, the background of the image appears so it seems it's not 'shaped , but didn't understand how to get the handle if i don't pass 0 ! SO i did these 2 lines
vb Code:
RegionHandle = cRgn.RegionFromBitmap(Picture1.Picture.Handle, Picture1.hWnd) 'to shape RegionHandle = cRgn.RegionFromBitmap(Picture1.Picture.Handle, 0)
In your 1st example. Caching RegionHandle in line 7 is unnecessary as it will be the result of SetWindowRgn when called to shape a window (see section of RegionFromBitmap where that API is called). Line 8 is correct. Line 9 is incorrect. The first parameter of FrameRgn is a DC
Do not forget to destroy the region handle and brush handleCode:FrameRgn Picture1.hDC, RegionHandle, hBrush, 1, 1
Thanks, but it still not working(check attached pic) , it seems that I am still missing something , here is what i did :
vb Code:
Private Sub Command1_Click() Dim hBrush As Long Dim RegionHandle As Long Dim cRgn As New clsRegions hBrush = CreateSolidBrush(vbRed) Me.BackColor = vbYellow ' just to show the picturebox is indeed shaped RegionHandle = cRgn.RegionFromBitmap(Picture1.Picture.Handle, 0) 'to get the 'handle FrameRgn Picture1.hDC, RegionHandle, hBrush, 1, 1 DeleteObject hBrush DeleteObject RegionHandle End Sub
is this the good way to delete the region and brush ? i saw this in your code at pscode, but want to make sure and if they are other ways to delete or not !
vb Code:
DeleteObject hBrush DeleteObject RegionHandle
I don't see anything wrong, I'd expect to see a red border hugging the image shape. Ensure Regionhandle is non-zero. If AutoRedraw=True, try refereshing your picbox. Ensure you are not drawing over the border with any later lines of code. You are deleteing the handles correctly.
Thanks LaVolpe , I could make it works but there are things am not understanding :
I added the to previous codeand this made the red border appears. I tried to change autoredraw from true to false, nothing changed same effet, it's only the .Refresh that gives effect.vb Code:
Picture1.Refresh
The problem is that there is a background arround the picture (the grey background you see), to avoid this, i had to make after the Picture1.Refresh, the following :otherwise i get always the background !vb Code:
cRgn.RegionFromBitmap Picture1.Picture.Handle, Picture1.hWnd
Any explication what autredraw is not changing anything and why i had to call again the RegionFromBitmap to avoid the background ?
Here is thefinal code that worked to give the border arround
vb Code:
Private Sub Command1_Click() Dim hBrush As Long Dim RegionHandle As Long Dim cRgn As New clsRegions hBrush = CreateSolidBrush(vbRed) Me.BackColor = vbYellow ' just to show the picturebox is indeed shaped RegionHandle = cRgn.RegionFromBitmap(Picture1.Picture.Handle, 0) 'to get the 'handle Debug.Print RegionHandle FrameRgn Picture1.hDC, RegionHandle, hBrush, 1, 1 Picture1.Refresh cRgn.RegionFromBitmap Picture1.Picture.Handle, Picture1.hWnd DeleteObject hBrush DeleteObject RegionHandle End Sub