I'm trying to create an effect so when the user hovers the mouse over a picturebox, the button fades to a hoverimage, and when they leave, it fades back to the original. I'm using pictureboxes as buttons in a program. I'm doing this because all the buttons will be pictures with no button textures, so I didn't see the point in using a button. Just so you can visualize it, here is the original image:
And the image to fade to:
I could still change these images a bit, but thats the general idea.
How would I go about creating this fading effect? I'm picturing something using timers and opacity settings, but I don't know how any of that stuff could help me solve this.
E: Heres a bit of code I have. It changes from image to image when I hover, but its not a fade, and it looks very choppy.
private void pictureBox3_MouseEnter(object sender, EventArgs e)
{
pictureBox3.Image = pictureBox37.Image;
}
private void pictureBox3_MouseLeave(object sender, EventArgs e)
{
pictureBox3.Image = pictureBox38.Image;
}
pictureBox37 and pictureBox38 are invisible reference pictureboxes with the images I need.
I don't think there's any WinForms support for this kind of animation, so you'd have to do this manually. If you have more than one of these buttons, I recommend creating your own UserControl with this functionality. I can give you some pointers how to do this:
Your UserControl will have two Image properties, one for the normal and one for the hover image
You'll have to override the OnPaint method to do your own custom painting, blending these two images onto your Graphics according to a position property. This is a float where 0 indicates showing the normal image and 1 the hover image. Any value in between means a blend of these two images. I found some good blending code here.
Then you'll need a Timer to update this position dynamically and redraw the button (by calling Invalidate). I recommend using a Windows.Forms.Timer, which has the advantage that its Tick event is always executed on the main Thread, so you don't have to use Invoke to modify your control.
And last but not least you override the OnMouseEnter and OnMouseLeave methods, to set this all into motion. These methods could set a positionChange property that indicates in which direction position is changing.
Hope this helps ...
Related
Is it possible to detect a click on a picturebox that is not visible
I have tried this :
private void PictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("teste");
}
But even if the picture box has no image and that background color is transparent, it hides the elements behind it.
I explain myself a little better;
I do a tic-tac-toe and I have the image of the cross that is not visible when the game is started; as soon as I press on a delimited area (where I want to place the cross), I want it to become visible
How can I do that?
Thank you.
I would use the PictureBox with an ImageList containing 2 images: the first is the background of your game field and the second is the cross.
In your Click Event I would toggle the pictures on click then.
I make Tic Tac Toe game, i have 9 cells that the player can click. Initially cell don't have any picture, but when cell was clicked it's picture must changes. How can i create this event for every cell without code duplicate?
The signature for a click event has a "sender" object. You can use that for reference. Cast it to the appropriate type, and you can access all its public properties directly.
You should be able to do something like:
protected void pictureClick(Object sender, EventArgs e) {
PictureBox pic = sender as PictureBox;
if (pic != null) {
// set the image based on which players turn it is.
}
}
and now each picture box would have its onClick event set to this one pictureClick function.
--- Edit ---
I'd also add that using independent UI controls in this manner is extremely inefficient for large tile games. For a 3x3 tic-tac-toe grid, it's probably fine, but for something like a 8x8 chessboard, the refresh times for all 64 squares is going to be noticeable, because every UI component on the page has its Paint() method called when the window refreshes. I'm speaking from experience here. I once tried to use this approach of having a grid of 10x10 Panel components with custom draw methods based on the game state data, and anytime the window was resized, the game would hang for several seconds while everything would refresh.
I am working on WindowsForm C#.
The border i create becomes problem when maximized!
private void App_Paint(object sender, PaintEventArgs e)
{
ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.Crimson, ButtonBorderStyle.Solid);
}
Normal:
Maximized:
Am i doing something wrong?
Is there a better way of doing this?
DrawBorder() has a parameter that can be used to remove a previously drawn border, just set ButtonBorderStyle to None
Example:
ControlPaint.DrawBorder(e.Graphics, (sender as Control).ClientRectangle, Color.Red, ButtonBorderStyle.None);
The only thing I don't like as much of my approach, is that it requires calls to the Paint event, which can get slow.
See this to refresh the form at runtime
Based on the information provided, I see it twice, meaning the painted information is being retained (relative to the position of the form) from the previous instance.
I'd strongly recommend staying away from trying to paint the non-client area.
If you have a custom request such as this, create a form with FormBorderStyle.None. Then, have a custom event to paint the Split Container's border. The top panel will have the custom min/max buttons. The rest of the content should be in the lower panel that fills below the min/max button.
Stay away from non-client painting. It's more trouble than it's worth.
I did it my self :D
1) Create a button, turn its FlatStyle to flat.
2) Turn Enable property to false, also remove all text
3) Dock the button to fill.
4) If previous button,labels(control) got hidden because of button, right click the button , send it to back!
I have a transparent form that overlays the desktop in a c# .NET winforms application. The transparency is done by setting the BackColor to bright orange and then setting the TransparencyKey to the same bright orange.
So far this works great and it creates a transparent form. I then want to create a control on the transparent form that draws a rectangle around items on the desktop. So essentially you can think of a transparent button with a rectangular border. To make this happen I currently extend Control and setup the control like this inside of the parent form which is also transparent:
public class CustomControl : Control
{
public CustomControl(Size size, Point point)
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
this.Size = size;
this.Location = point;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen pen = new Pen(Color.Red, 2f);
e.Graphics.DrawRectangle(pen, this.ClientRectangle);
}
}
This creates the exact effect I'm looking for in that there is a control with a solid opaque rectangle border inside a transparent form and you can see the desktop through the control and form (see image below on left side).
The problem is that the transparent area of the control does not receive any mouse events. In fact, it basically doesn't exist. For example, when your mouse goes over the red rectangular border of the control that triggers the Mouse Hover, Mouse Enter, and Mouse Leave events and changes the cursor to whatever you set as this.Cursor for the control. Once, the mouse is in the transparent portion of the control none of these things trigger.
How can I keep things the way they are now in regards to the look of the control but still receive mouse events in the transparent area. In particular I want to receive Mouse Hover and have the controls Cursor value be honored. Note that if I make the BackColor of the control anything other than Color.Transparent then mouse events work fine.
Thank you!
Update
Based on Hans comment I would like to add that we have implemented the above and that it has usually worked (i.e., the transparent area does respond to mouse events). The reason this issue came up is because I recently rebuilt my machine with all the Windows 8.1 updates and latest ATI graphic drivers and after that the above setup no longer works ever (transparent areas on the control no longer receive any mouse events and for all intents and purposes are not part of the control) On my colleague's machine it almost always works although we've occasionally noticed that it won't work but we could never consistently reproduce the issue.
My assumption was that we did something wrong to cause the transparent areas to not respond to mouse events. However, based on Hans' comment, it seems as though the above code should never work and that the only reason it worked was because of a bug in Aero.
The exact color of our transparency key is rgb(255, 128, 0). In addition we did notice that any label controls placed on the transparent form look terrible (per Han's comment).
Update 2
Based on Han's additional comment regarding the Aero transparency bug I have the following updated questions.
Is there any information on this bug somewhere that explains what the bug is?
What is the intended behavior (assume there are no bugs) for transparent areas of a control? Should mouse events (e.g., Mouse Hover) work on the transparent area?
The Final Answer (that usually works)
The answered provided by Reza below did work for me on some of my computers. However, my primary desktop continued to stubbornly refuse to cooperate. Even when copying the exact project between computers using the same version of windows and .NET the problem existed. The issue when it arose was that transparent areas would not trigger mouse events and were not treated as part of the control.
In addition, I noticed the same thing Reza noticed which was that certain TransparencyKey colors flat out did not work. Although I don't know any details of the bug I would have to agree with Hans that there are bugs involved with transparency on WinForms and if anyone is starting from scratch I would go the WPF route and save yourself any possible future headaches.
In the end we ended up implementing a work around based on some of Hans' answers that required using a timer to check the mouse location and nesting two forms (one with opacity set) to be able to manage the mouse cursor. This solution has worked on all our systems and will hopefully hold up until we move over to WPF. I accepted Reza's answer because it seems to work in most places but be aware that it might not work you and there is no rhyme or reason as to why.
For detailed information on the two workaround we implemented please see the following questions and answers by Hans.
MouseHover and MouseLeave Events controlling
How can I add transparency to a c# form while keeping controls visible?
Important
Consider set BackgroundColor of form to Red and TransparencyKey to Red and BackGroundColor of transparent control to Transparent and it will work!
the strange thing that I see is, the approach doesn't work with for example Magenta but works with Red and Blue.
I think you should create your transparent control this way:
Transparent Control Code
public class TransparentControl : Control
{
public TransparentControl()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
private const int WS_EX_TRANSPARENT = 0x20;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
}
And for the mouse events and rendering border when the mouse enters, here is the sample I did Using .Net 4.5 On Windows 8.1:
Create a Form and put a TransparentControl that we created using above code, on it, then handle MouseEnter and MouseLeave and Paint events and paint the border when mouse is in control bouds and handle Click event and show a message.
Form Code
private bool drawBorder;
private void transparentControl1_MouseLeave(object sender, EventArgs e)
{
drawBorder = false;
transparentControl1.Invalidate();
}
private void transparentControl1_MouseEnter(object sender, EventArgs e)
{
drawBorder = true;
transparentControl1.Invalidate();
}
private void transparentControl1_Paint(object sender, PaintEventArgs e)
{
if(drawBorder)
{
using (var pen = new Pen(this.ForeColor, 5))
{
e.Graphics.DrawRectangle(pen, 0, 0, this.transparentControl1.Width - 1, this.transparentControl1.Height - 1);
}
}
}
private void transparentControl1_Click(object sender, EventArgs e)
{
MessageBox.Show("Clicked");
}
Screenshot
The mouse cursor is in the control's area so the black border has been painted.
Important Note
If you draw border the same color as form's transparency key, the border will not be shown.
I think it's okay for the mouse cursor to go in the middle of that overlay box and move with the mouse cursor and the overlay box to make it look like it's a mouse cursor.
Like this picture
I have had similar problem when I use a picturebox control on a transparent form and use the mouseclick event over the control to trigger code. Sometimes the mouseclick is captured and sometimes it isn't. No pattern to it other than the color used as the form background. Red works fine but many other colors do not. Even black does not work consistently. I have found an almost black color that works fine when form.backcolor and form.transparencykey are set to this color. Based on this and others experiences it appears a bug in VB Studio and the way transparency is handled.
Form1.BackColor = Color.FromArgb(64, 0, 0) ' a color that works with transparency and allows picturebox to be clicked
i tried to search for this on google, but didnt seem to find anything related that could help me.
My problem is this, i have a panel in which i draw a cube, and i added a group box with 3 radio buttons and 4 normal buttons(these do the rotation of the cube)
For testing i have another button added on the panel but not in the group box.
The problem is this, when i push on any button it doesn't update the cube's rotation, only when i move the mouse on the test button(over it)
If i try to move the buttons outside the group box then all works well, but they don't work if they stay inside the group box.
Does anyone know how i can fix this?
May I suggest that instead of redrawing the panel you create a Bitmap for drawing your (rotated) cube and use a PictureBox to display it? The PictureBox could be inside the Panel together with the GroupBox.
The flickering comes because the panel redraws his background first and then raises the Paint event. To avoid this you must to create a custom control and do the drawing in OnPaintBackground protected method. This seems a overkill. Or you can write to a Bitmap and put it in the BackgroundImage property.