CustomControl "disappears" when dragged in panel/form with backgroundimage - c#

I am writting a pin-up board in C# where I need to be able to drag around pieces of paper (notes) on the board. I have made the notes as customcontrols since I needed to be able to write on them as well. The background of the customcontrol (a note) is an image of a piece of paper. When I don't use a backgroundimage, for the board itself, everything works as intended. I am able to drag around the notes (customcontrols with a backgroundimage) just fine - no flickering. When I use a backgroundimage on the board (which I want to do, since a plain color background doesn't cut it for me), I am not able to drag the notes around smoothly anymore. When I start dragging the note disappears and is first redrawn when I stop moving the mouse.
I am using the following code on the panel (in its constructor) where I drag around notes, but it has only sorted out my initial screen flickering issue.
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
The image file used for the background is imported into the projects resources. I have tried to load the image file into a bitmap object and used this object as the backgroundimage of the panel, but that didn't change anything.
Below a link to an image of how a note should look when being dragged:
http://i.stack.imgur.com/9LnKj.jpg
Below an image of how the note actually looks when I start dragging it around:
http://i.stack.imgur.com/x0Lf1.png
Please ask if you need more details to be able to help me solve my issue. Any help and suggestions on what the problem might be is very appreciated! Thanks in advance.
Edit: The size of the note on the second image is dependent on how far I drag it from its initial point. I am able to get the note to disappear completely when I drag it further than the size of it. It gets redrawn when I stop moving the mouse.
Edit: I use the following code for moving around the notes:
private void NoteControl_MouseMove(object sender, MouseEventArgs e)
{
if (_dragme)
{
System.Drawing.Point newLocation = e.Location - mouseOffset;
this.Left += newLocation.X;
this.Top += newLocation.Y;
}
}

Since I have not been able to solve my issue with the custom control disappearing when getting dragged on an imaged background I have decided to create an asp.net version of my project rather than a windows form application. This also prevent the issue with cross platform compatibility. The dragging is now accomplished using jQuery

Related

Panel is flickering when switching from one winform to another

I render my image on the panel.
using Microsoft.DirectX.Direct3D;
Device device;
this.device = new Device(0, DeviceType.Hardware, this.panel2,
CreateFlags.HardwareVertexProcessing, presentationParameters);
As a result, the panel is flickering when I try to switch the winform from one to another.
I know it is hard to describe the scenario. Hence I hereby upload a video clip (.swf) to my google drive, you guys may download it and open it with window media player to watch the video.
Below is the shared link:
https://drive.google.com/file/d/0B6wTfkJvzke_aVJwanVkaU1iSVU/edit?usp=sharing
Inside the video, I am running my application at debug mode, then I click on the 'chrome browser' tab in task bar to access the 'chrome browser', when the minimized 'chrome browser' pop out, the panel will be flickered. Then when I minimize the 'chrome browser' again, the panel flickered again.
The problem occur when there is some other winform being placed above the panel on screen.
Any comment on the above matter? Help is needed.
I ran into the same flicker issues when using DirectX with Panel. It turned out that the OS draw events were colliding my own. To fix this, you need to disable OS drawing on your Panel by creating a custom panel. Something as simple as this should suffice.
class Direct3DPanel : Panel
{
public Direct3DPanel()
{
this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
}
}
The SetStyle method call tells the OS that only you should draw in Direct3DPanel. Note that once you do this, you will be responsible for all drawing. You may need to handle the Paint event and call your draw logic depending on your current architecture.
You can get more information about the different ControlStyles here
http://msdn.microsoft.com/en-us/library/system.windows.forms.controlstyles(v=vs.110).aspx

How can I add transparency to a c# form while keeping controls visible?

UPDATE: I took a break from messing with the transparency stuff for a few days. I started messing with it again tonight. I got a new result using Hans Passant's solution:
http://img3.imageshack.us/img3/4265/icontransp.jpg
Passant's solution does solve the issue of the transparent background gradient. However, I'm still running into the problem with the transparent colors in my icon blending with the form's BackColor. You can see the fuchsia around various parts of the icon in the above image.
ORIGINAL CONTENT:
I've been going at this for several hours now, and I haven't had much luck. I've messed with Control.Region, Form.TransparencyKey, Form.Opacity, and a couple other random things with some funky effects.
Lately I've been trying to customize my desktop and decided to mess with Application Docks. After seeing what the Mac dock and a few third-party Windows implementations had to offer, I decided I wanted to build my own.
Eventually I want to move on to using the Win32 API. For now I just want to get something working using as much C# and .Net framework capabilities as possible.
There are a few things I want to be able to do in this application:
Display a form/menu with a gradient background.
Allow the form/menu to have transparency while keeping icons opaque.
Display icons that contain transparent backgrounds.
The Menu and Icons should be able to receive mouse-related events (hover, leave, click, dragover, dragdrop, and a few others).
This is the effect I'm shooting for:
http://img207.imageshack.us/img207/5716/desired.jpg
This image shows the visual effects I'm trying to achieve. This was a skin I made for a program called Rainmeter. The image shows Notepad++ behind the skin with a few of the skin's files open in the editor. The menu is transparent, but the icons remain opaque.
My Approach:
Using a Form to act as the menu seemed like a logical first choice to me. I have a basic understanding of events. I'm not quite sure how to create my own click events, so a form would make working with events a tad easier. I considered a few options for the icons. I decided I'd use PictureBoxes for the icons, since they can hold images and receive events.
Once I finished the code for all the structural logic of my menu, I started playing around with it to try to get the visual effect I wanted. Form.Opacity affected the transparency of everything on the form. Since I want the icons to be fully opaque, I left this property alone. I tried setting the BackColor to Color.Transparent, but that gives an error. I played around with a few combinations...
http://img204.imageshack.us/img204/757/effectsi.jpg
I drew the gradient with a Drawing2D.LinearGradientBrush into a Bitmap. This Bitmap was then placed as the Form.BackgroundImage or as a PictureBox.Image. If used, the PictureBox was sized to cover the entire Form and sent to the back.
I noticed that some of the Form.BackgroundColor would be mixed in with the outlines of my icons. The icons have transparency along the edges for a smoother appearance. Since the icons are picking up the Form's BackgroundColor, this makes me think that the PictureBoxes are creating new images when the icons are loaded into the form. The semi-transparent portions of the image are then merged with the Form's BackgroundColor when they should merge with whatever colors are behind the form.
http://img838.imageshack.us/img838/8299/whitedesktop.jpg
In this image you can see the Fuchsia existing in the icons even though the Form's Fuchsia color is now completely transparent. I forgot to point out that the same green to yellow gradient with an Alpha value of 150 was used in every case. In the images where the gradient doesn't look green, it's because the transparent colors are blending with the Fuchsia background.
I'm not really sure what to do from here. I feel like I could get what I want if I could somehow make the Form alone completely transparent. I was also thinking I may have better luck just drawing the icons instead of using PictureBoxes. The problem then would be setting up the icons to receive mouse events. (I've never made my own events, and I think it would involved some Win32 API calls.)
Is there something else I can do with the PictureBoxes to get the effect I want? Whichever the case, I'm open to any ideas or suggestions for the overall effect I'm trying to achieve.
This is pretty easy to do in Winforms. What you need is a sandwich of two forms. The bottom one should provide the transparent gradient background, the top one should draw the icons and handle mouse clicks. Some sample code:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.TransparencyKey = this.BackColor = Color.Fuchsia;
this.Opacity = 0.3;
var overlay = new Form();
overlay.FormBorderStyle = FormBorderStyle.None;
overlay.TransparencyKey = overlay.BackColor = Color.Fuchsia;
overlay.StartPosition = FormStartPosition.Manual;
overlay.Location = this.Location;
overlay.MouseDown += HandleIconClick;
this.Resize += delegate { overlay.Size = this.Size; };
this.LocationChanged += delegate { overlay.Location = this.Location; };
overlay.Paint += PaintIcons;
this.Paint += PaintBackground;
this.Load += delegate { overlay.Show(this); };
}
private void PaintBackground(object sender, PaintEventArgs e) {
var rc = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height);
using (var br = new LinearGradientBrush(rc, Color.Gainsboro, Color.Yellow, 0f)) {
e.Graphics.FillRectangle(br, rc);
}
}
private void PaintIcons(object sender, PaintEventArgs e) {
e.Graphics.DrawIcon(Properties.Resources.ExampleIcon1, 50, 30);
// etc...
}
void HandleIconClick(object sender, MouseEventArgs e) {
// TODO
}
}
Which looks like this with the somewhat random colors and icon I selected:
OK, I got a bit lost in all that, but from the description in the original paragraph, I would make sure the background rectangle is NOT the visual parent of the pictureboxes. Make them overlapping siblings, with the pictureboxes in front using Panel.Zindex.
Then you can just change the opacity of the rectangle, without affecting the icons. Also make sure the icon source image files have a transparent background.
Should work I think.

How to make label & other controls transparent with background image on windows mobile?

I am developing the smart device application in C#. I am new to the windows mobile. I have added the background image to the form in my application by using the following code. I want to make label & other controls on this form transparent so that my windows form will be displayed properly.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Bitmap CreateCustomerImage = new Bitmap(#"/Storage Card/background.png");
e.Graphics.DrawImage(CreateCustomerImage, 0, 0);
}
how to do this ? How to solve this problem? Can you provide me any code or link through which I can solve the above issue?
Windows CE doesn't inherently support transparent controls, which tends to be a huge pain. You have to use something like ColorKey transparency, so in your OnPaint, you need to fill the background with a color (magenta is a popular one) and use SetColorKey to make that color transparent.
There are several tutorials online for colorkey transparency. Here is one that I just found with a search engine that looks reasonable but feel free to search for others as well.
The place this falls down is when you have controls in a container control, which is then on the Form. To get that to work right you have to cascade calls to clipping regions from the Form all the way down. I don't have a ready sample of this that isn't inside a shipping project, so I can't easily post it. If you run into this, though, update the question and I'll see if I can extract something.

Showing image / text on screen without forms in c#

How can I show something on screen wihtout using forms?
Actually, I want to show some text and images popping on screen.
EDIT: just like i said HERE
What you can do is to create a alphatransparent form that draws the PNG and position it at the correct location and bind move etc.
http://www.codeproject.com/KB/GDI-plus/perpxalpha_sharp.aspx
PerPixelAlphaForm transparentImageForm = new PerPixelAlphaForm();
transparentImageForm.SetBitmap(<IMAGE GOES HERE>,<OPACITY GOES HERE>);
//opacity is the opacity that the image will be drawn with, a value of 255 = all transparent parts will be alpha/transparent just as much as the original PNG etc..
and you can put a timer that calls SetBitmap and changes the Opacity to fade in/out the image on the screen
And you can generate the text (on the fly) in a nice way with code from THIS article
and pass that image to the SetBitmap of the AlphaTransparent form.
EDIT: OR GO TO WPF.
I don't think you can: a form is equivalent to a window, and Windows applications draw into a window and not directly onto the screen (unless perhaps it's the backgroun/wallpaper, which I don't know about).
I think that's overdoing it but XNA will allow you to draw to the screen, but it is meant to be used for games so you will have trouble fitting it to a normal application.

Gradient Drawing Bug

I'm having trouble with a gradient drawing call. I have a Form that looks like this.
Screenshot http://img413.imageshack.us/img413/3570/30364682.png
The problem is every now and again the above gradient drawing bug will start happening. It should go right across of course. Sometimes it only takes some build-rebuild-mashing to fix and it'll simply just "start" after a build every now and again.
That control (the top white part) is a TableLayoutPanel. The BackColor is set to white and on the panel's Paint event I do this:
/// <summary>
/// Draws the background gradient.
/// </summary>
private void titleBarLayoutPanel_Paint(object sender, PaintEventArgs e)
{
Brush brush = new LinearGradientBrush(titleBarLayoutPanel.Bounds, TaskHeaderLeftColor, TaskHeaderRightColor, LinearGradientMode.Horizontal);
e.Graphics.FillRectangle(brush, titleBarLayoutPanel.Bounds);
}
Should I be doing something else? The problem is that it works, and then without so much as a rebuild or build this will start happening!
EDIT I have since rebuilt the class library it is contained in (it's a generic Form) then rebuilt the app it's used in and the gradient is now filling across completely. This is bizarre.
Building and re-building your application, with no changes, normally doesn't solve this (or most any other bug for that matter) save the ones in which you run your application without doing a clean/rebuild first and then notice that the code you just wrote doesn't run (not sure that's possible these days with the IDEs). I see this a lot with newer devs when they keep rebuilding hoping that somehow the compiler will make the code "correct" or that maybe the compiler is simply not generating the correct code to begin with. (Please note that I do not mean the aforementioned statements to be taken disparagingly.)
To solve the issue at hand, you might try deriving your own TableLayoutPanel class in which you override the OnBackgroundPaint event, painting your own background, or simply returning if you don't want to paint your own background. (You seem to be painting the background in the Paint event). What you are doing in the code above is simply painting over the background already painted by the control, hence the "bug" you see, (double paint). It appears that the form is not resizable. Try making it resizable. Then resize it and watch it paint, or simply move other windows over it.
class CustomTableLayoutPanel : TableLayoutPanel
{
protected override void OnPaintBackground(PaintEventArgs e)
{
Brush brush = new LinearGradientBrush(this.ClientRectangle, TaskHeaderLeftColor, TaskHeaderRightColor, LinearGradientMode.Horizontal);
e.Graphics.FillRectangle(brush, this.ClientRectangle);
//base.OnPaintBackground(e);
}
}
By the way, you should replace Bounds with ClientRectangle.
Bounds is the control's rectangle relative to its parent; ClientRectangle is relative to the control itself.
In this particular case, it won't make a difference, since the control is at 0, 0.

Categories