Windows application very slow when using transparency - c#

I am writing a windows application with C# in visual studio .net 2005.
In the form , there are some control with transparent Background; the form opens maximised and with full screen background.
The application runs very slow with high CPU usage.
Why is this?

1. Solution using property DoubleBuffered
Sidenote: Only works if you have access to the control as DoubleBuffered is a protected property of Control. Similar as solution 2 (see code behind).
// from within the control class
this.DoubleBuffered = true;
// from the designer, in case you are utilizing images
control.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
System.Windows.Forms.Control.DoubleBuffered
System.Windows.Forms.Control.BackgroundImageLayout
2. Alternative solution using SetStyle + OptimizedDoubleBuffer:
Sidenote: The control paints itself, window message WM_ERASEBKGND is ignored to reduce flicker, and the control is first drawn to a buffer rather than directly to the screen.
control.SetStyle(UserPaint | AllPaintingInWmPaint | OptimizedDoubleBuffer, true);
System.Windows.Forms.Control.SetStyle(ControlStyles, Boolean)
System.Windows.Forms.Control.ControlStyles
3. Alternative solution using SetStyle + DoubleBuffer:
Sidenote: Similar as OptimizedDoubleBuffer, due to legacy reasons it remained in the codebase.
control.SetStyle(UserPaint | AllPaintingInWmPaint | OptimizedDoubleBuffer, true);
System.Windows.Forms.Control.SetStyle(ControlStyles, Boolean)
System.Windows.Forms.Control.ControlStyles

Thats because the GDI+ transparency implemented in .NET 2 is not ideally implemented, as Bob Powell explains.

Related

Remove Title Bar from Windows Form (Windows 10 style)

I have a very simple class which inherits from System.Windows.Forms.Form and removes the WS_CAPTION window style. It works in Windows XP & 7 perfectly. In windows 10 a piece of the titlebar is still drawn and it ends up looking ugly when using a custom titlebar control.
I know there are likely several ways to accomplish this kind of look, but I've chosen this for multiple reasons. I'm not interested in the alternative methods--that's not the intention of my question here.
My question is what is causing such a difference between the way this is rendered in windows 10 vs windows 7? The difference is not merely stylistic. It appears that the titlebar is still being rendered in some capacity even though the WS_CAPTION flag has been removed.
class BorderlessForm : System.Windows.Forms.Form
{
protected override System.Windows.Forms.CreateParams CreateParams
{
get
{
var _CreateParams = base.CreateParams;
_CreateParams.Style &= ~0x00C00000; // remove WS_CAPTION
return _CreateParams;
}
}
}
Windows 7 screenshot (desired appearance consistent with MSDN description):
Windows 10 screenshot (undesirable appearance inconsistent with MSDN description):
What you are observing is not a title bar but sizing border.
My question is what is causing such a difference between the way this is rendered in windows 10 vs windows 7?
The cause is different look and feel implementation on different versions of Windows.
In case you are interested how to get rid of the sizing border even on Windows 10: Remove the WS_THICKFRAME flag.
Alternatively (and perhaps more preferable) you can change your form's FormBorderStyle to some other value. Test whatever works best for you.
However there is nothing what defines the overall form border precisely. It's up to the look and feel (theme). Technically you cannot expect that form's border won't differ under different implementation. You can only ensure by testing.

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

Double buffering control causes grey to appear

I have a class that accepts a Control and draws generated images to it. In my application code I'm using a Panel control for this - which seems to work well, except that I get a lot of flickering on the control as the image is redrawn. I think the solution is to enable double buffering on the control. I'm doing this with the following code:
System.Reflection.PropertyInfo aProp =
typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(drawControl, true, null);
After adding this code, the image is drawn, and then immeadiately replaced with the default grey button background colour - it's as if the system is drawing over my own content.
I remember seeing somewhere a property that tells the system to never draw the control (which would be perfect for me since I'm filling the entire control with content), but now I cannot find it. Is there such a property, and if so, how can I enable it?
I'm using C# with the .NET framework ver 4.0.
Try setting FlatStyle on the control to FlatStyle.Standard, if it's currently set to FlatStyle.System.
(Setting DoubleBuffered by reflection looks horrible too, but perhaps you need to do that for some reason)

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.

Resizing window causes black strips

I have a form, which sets these styles in constructor:
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
And I draw some rectangles in Paint event. There are no controls on the form. Hovewer, when I resize the form, there are black strips at right and bottom of the form. Is there any way to get rid of them? I've tried everything, listening for WM_ERASEBKGND in WndProc, manually drawing the form on WM_PAINT, implementing custom double buffer, etc. Is there anything else I could try?
I've found this:
https://connect.microsoft.com/VisualStudio/feedback/details/522441/custom-resizing-of-system-windows-window-flickers
and it looks like it is a bug in DWM, but I just hope I can do some workaround.
Please note that I must use double buffering, since I want to draw pretty intense graphic presentation in the Paint event. I develop in C# .NET 2.0, Win7.
Status Update 1
I've managed to get rid of most of the black stripes by implementing the resize functionality by myself. Hovewer there are still some minor glitches. Is there any way to do resize and paint operation at once? Here is a pseudo-code of what I need to do:
IntPtr hDC;
var size = new Size(250, 200);
IntPtr handle = API.PaintAndResizeBegin(this.Handle /* Form.Handle */,
size.Width, size.Height, out hDC);
using (var g = Graphics.FromHdc(hDC)) {
this.backBuffer.Render(g, size);
}
API.PaintAndResizeCommit(handle);
Is there any way to implement the above code?
The second solution could be to back-buffer whole form, including non-client area. But how to do that? I don't want to paint the non-client area by myself, as I want to keep the nice aero effect on Vista/7. Any help will be deeply appreciated.
Status Update 2
It looks like this problem is unsolvable, since it is omnipresent on Windows, in every application. We can just hope that MS will take some inspiration in Mac OS X and will provide appropriate APIs in new Windows.
I've found the function which can paint and resize window at the same time - UpdateLayeredWindow.
So now it should be possible to create resizable windows, which do not have any strips while being resized. However, you need to paint the window content yourself, so it is a little inconvenient. But I think that using WPF and UpdateLayeredWindow, there shouldn't be any problem.
Update
Found problems. :-) When using UpdateLayeredWindow, you must paint the window's border yourself. So, if you want standard window painted using UpdateLayeredWindow with nice glass effect in win7, you are screwed.
On Microsft Connect is even a thread about this problem, where Microsoft says it is a bug by design, and if it ever gets fixed, then probably in Win8 or some newer system. So there isn't much we could do about this.
I found that it is best not to do any custom rendering directly on the Form surface. Instead, put a docked PictureBox on the form, create Bitmap object that will be displayed in the PictureBox, draw everything onto that using the System.Drawing.Graphics.FromImage(Image) method.
I used that method with a game loop to make a simple shooter game (Crimsonland-style) and got pretty good performance (with anti-aliased lines), above 100 FPS.

Categories