C# Best Method to Dim Screen, Multiple Windows Forms? - c#

So I've written code to create a new Windows form from the parent that is fullscreen, black and opacity of 80% to create a dimming effect.
Then another form is shown above this to show progress.
The code is currently looking like this:
this.Enabled = false;
frmDimScreen.BackColor = Color.Black;
frmDimScreen.Opacity = .8;
frmDimScreen.FormBorderStyle = FormBorderStyle.None;
frmDimScreen.Size = new Size(splitContainerMain.Width - 4, splitContainerMain.Height - 2);
frmDimScreen.StartPosition = FormStartPosition.Manual;
frmDimScreen.ShowIcon = false;
frmDimScreen.ShowInTaskbar = false;
frmDimScreen.Show();
frmDimScreen.Location = new Point(splitContainerMain.Location.X + 2, ((splitContainerMain.Location.Y + tsMainTools.Height) - 4));
addImgIL.ShowIcon = false;
addImgIL.ShowInTaskbar = false;
addImgIL.TopMost = true;
addImgIL.Show();
addImgIL.Location = new Point((this.Width - addImgIL.Width) / 2, (this.Height - addImgIL.Height) / 2);
addImgIL.BringToFront();
Obvioulsy the main reason I'm questioning this is if the parent window loses focus, then the child forms get out of order and are not layered correctly. I know I can handle this via OnPaint, but looking for the best solution.
The question/problem, is this the best method to achieve what I am attempting? Should I be using forms or graphics to create the dimming? What's everyones experience with this?
Thanks in advance!

Another approach using only a single window would be to use an alpha blended image to draw the transparent dark background (you could even have a gradient) with a non-transparent custom drawn progress bar. See http://www.codeproject.com/KB/GDI-plus/perpxalpha_sharp.aspx .
In that project you can find a class that you can use to easily assign an alpha blended Bitmap to a form's background. The problem with this method is that you must custom draw everything on the form, including the progress bar or whatever other controls you need on it.
The effect that you are trying to achieve is kind of unusual for a windows application, that is why the best method is not very straightforward.

Related

Keep my form above the taskbar?

My overall goal is to render a second (or third, fourth...) mouse cursor. To this end, I have created a frameless, topmost, transparent window. I can draw on this window (I have 4 buttons on it to show that it's properly covering the whole desktop) - but when I click on the taskbar, it is brought to the top and overlays my buttons and drawn line.
How can I keep my window above the taskbar?
Alternatively, is there a way that I can draw on the "final" version of the screen?
Here's the code from my .Designer.cs file:
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.White;
this.CausesValidation = false;
this.ClientSize = new System.Drawing.Size(332, 332);
this.ControlBox = false;
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Screen";
this.ShowIcon = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultBounds;
this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.White;
Without analysing the exact motivation of doing this and whether this approach is the best way through, you should note that the taskbar's behaviour is equivalent to the one of any other window: TopMost can be used without any restriction. On the other hand, it is considered outside the "WorkingArea" and thus, depending upon the properties you are using, it might be ignored. Take a look at the sample codes below to understand this better.
Main Form covering all the available space above the taskbar:
this.ClientSize = new System.Drawing.Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);
Main Form covering the whole available space of the screen:
this.ClientSize = new System.Drawing.Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);
Thus, you can locate your form on top of the taskbar without any problem by bearing the mind that it represents the difference between WorkingArea and Bounds of the screen.
CLARIFICATION: this answer highlights what might be the reason for the taskbar to be treated differently than any other part of the screen. It does not imply that you have to make your form as big as the whole screen to put it over the taskbar; you can put it over the taskbar whenever you want with an as small size as you wish. What you have to bear in mind is that WorkingArea does not provide the whole dimensions of the screen, but just the area ABOVE the taskbar; if you want to bring the taskbar into consideration, consider Bounds.
I'll go with varocarbas answer,but there is something that i want to add which i think might be useful.
A few things are there that i guess may be helpful,when i read your question the first idea that struck my mind was to create a GlobalHook to monitor message WM_CBT,this message is send to GlobalHook procedure when the system is about to Maximize,Minimize,Restore or Focus a Window.When any hook is trapped you can override any required events to block that window from becoming the topmost window,thus giving your Form a chance to remain the topmost Window.This method will be highly helpful if it worked as i am expecting.
If you are interested in this, here are the methods that are required to make a GlobalHook work.
SetWindowsHookEx(),used to tell the system to create a GlobalHook.
HookProc,Represents the method called when a hook catches a monitored event.
HookType,Enumerates the valid hook types passed into a call to SetWindowsHookEx.
CallNextHook.If using interoperability is messy,try this open source library that contains WindowsAPI functions in a managed wrapper.Hope this helps you,meanwhile i'm also trying to get the stuff working for you.
I've been struggling for a few hours with this same problem. I thought of a nice solution: just change the bottom padding of the form dynamically whenever the form is maximized.
If Me.WindowState = FormWindowState.Maximized then
Dim pd As New Padding
pd.Left = Me.Padding.Left
pd.Right = Me.Padding.Right
pd.Top = Me.Padding.Top
pd.Bottom = Me.Height - Screen.PrimaryScreen.WorkingArea.Height
Me.Padding = pd
end if
This way the form is not above the taskbar, but at least your controls are!
Note: in designing your forms you can leave the bottom-padding 0.
If you want your form to be able to minimize/normal resize, then you may want to reset the bottom padding to 0 in another form event.
I actually found the solution about 15 minutes after I posted. (Isn't that always the way? Research for hours, but as soon as you ask for help, you figure it out on your own. :)
I have an event that is calling my code with position updates. If I simply call "BringToFront" in this event, it works just fine. The event is called many times per second, but if I throttle my behavior back to 1/4 second, it still works great.

when i press tab the panel clears

Using DrawImageUnscaled my program draws a parobola or a line ...
If I press tab after the program draws, the panel in whith the image clears..
For my ox and oy axes i use ? and they disappear too...
System.Drawing.Pen linepen;
linepen = new System.Drawing.Pen(System.Drawing.Color.Green);
System.Drawing.Graphics g = drawingboard.CreateGraphics();
g.DrawLine(linepen, 0, drawingboard.Height / 2, drawingboard.Width, drawingboard.Height / 2);
g.DrawLine(linepen, drawingboard.Width / 2, 0, drawingboard.Width / 2, drawingboard.Height);
timer1.Enabled = false;
How can I fix this ?
Typically in DOT.NET you don't just paint what you want the user to see in a random place. Instead each panel (and control) has an OnPaint function which is called when the control displays itself. You want to modify this function to draw your new lines.
You will notice as you work with .NET that this function will get called multiple times when certain events happen in the application -- for example re-size. This allows the programmer to change what is displayed when the window changes size.
Add your code above to the OnPaint function of the control and it should work much better.
I'm not sure what you mean by ox and oy -- you don't seem to have any code with them

Panel with fixed size

I have a homework, where I need to create a winforms game using C#. I have the following components:
Panel subclass with custom paint event
Panel with default windows UI elements.
I want them to arrange like this:
Because I draw on the center panel manually, I want to set it's Width, and Height fixed, so the Form subclass, what will contain it, would show the whole panel.
I tried setting the size manually in the panel subclass:
Width = someFixedWidth;
Height = someFixedHeight;
Then adding it to the containing Form:
GamePanel panel = new GamePanel(...);
panel.Dock = DockStyle.Center;
this.AutoSize = true;
this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
this.Controlls.Add(panel);
Using this, I thought, that the form will respect the size of the Panel, but it just shrinks the window to so small, that nothing is visible, only the title.
So my question is, how would I be able to set the size of the GamePanel manually, and then dock it in the center of the form, so that the Form will respect the size I set, and doesn't makes it smaller/bigger?
The Dock property is used to define the behavior of the component during resizing Container (Form) The way you did the screen is not centralized but is resized according to the screen changes, the ideal is to use a method to reposition the control and set its size. See this:
SuspendLayout();
Width = someFixedWidth;
Height = someFixedHeight;
panel.Size = new Size(panelWidth, panelHeight);
panel.Location = new Point( ClientSize.Width / 2 - panelWidth / 2, ClientSize.Height / 2 - panelHeight / 2);
panel.Anchor = AnchorStyles.None;
panel.Dock = DockStyle.None;
ResumeLayout();
In my case, I edited minimum height/width of the panel and it worked.
I tried to edit the code which related to design but it was not recommended to rewrite auto-generated code.
Thank you.

How can I make a background panel from a form transpart/invisible in an XNA window?

I have an XNA project that utilizes the Windows.Forms to create the GUI. Our GUI consists of a left panel and right panel. They both have a image laid over them(let's call them the panel images). Those images have buttons with images over them. Now the panel images don't completely cover the panel. Now what we want to do is make the panel invisible or transparent so you only see the panel images. In the picture below I circled what I want to be transparent/invisible. As you can see on the upper part of the project it already looks transparent but that is only because it blends in with the background on the XNA scene. On the bottom where the panel is over the ground you can see how the panel extends further than the panel images. So, does anyone know how I can make those parts invisible/transparent.
Alright, we've messed around with making the panel color Color.Transparent, magenta(XNA transparent color) and those attempts haven't worked. Any input/advice is welcome and much appreciated.
Here is the code that sets up the panel:
this.pnlLeftSide.BackgroundImage = global::Referenceator_UI.Resources.LeftBar;
this.pnlLeftSide.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.pnlLeftSide.Controls.Add(this.btnScreenShot);
this.pnlLeftSide.Controls.Add(this.btnScale);
this.pnlLeftSide.Controls.Add(this.btnMove);
this.pnlLeftSide.Controls.Add(this.btnRotate);
this.pnlLeftSide.Controls.Add(this.btnSelect);
this.pnlLeftSide.Location = new System.Drawing.Point(0, 0);
this.pnlLeftSide.Name = "pnlLeftSide";
this.pnlLeftSide.Size = new System.Drawing.Size(197, Screen.PrimaryScreen.WorkingArea.Height);
this.pnlLeftSide.Dock = DockStyle.Left;
this.pnlLeftSide.BackColor = controlColor; //this what we want invisible/transparent
-Thank you stackoverflow community
Try setting Region property of your panels. You can create necessary Region objects manually (by enumerating lines describing visible polygon) or use some method which converts image with transparency color key to Region (easily googled - https://stackoverflow.com/questions/886968/how-do-i-convert-an-images-transparency-into-a-region for example).
Since geometry of your panels does not seem to be too complex, you can create Region manually following way:
using(var gp = new System.Drawing.Drawing2D.GraphicsPath())
{
// Here goes series of AddLine() calls.
// You must
// gp.AddLine(0, 0, leftPanel.Width, 0);
// ...
gp.CloseFigure();
return new Region(gp);
}
Note that you'll get sharp edges with this method (even if it works). Consider rendering all that GUI using XNA.

C# creating a form for given size

I want to draw a rectangle on the screen. I guess the most appropriate way is use a form without boarder.
Form frm = new Form();
frm.StartPosition = FormStartPosition.Manual;
frm.Location = new Point(GlobalPosX, GlobalPosY);
frm.Size = new Size(101, 30);
frm.BackColor = System.Drawing.Color.Yellow;
frm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frm.Show();
The created from is not as the given size. It's size is similar to the window having boarder. The displayed window is bit larger as I given and the position is also moved little bit upper and left.
Is there another way to achieve my goal?
Use the ClientSize property instead of Size:
frm.ClientSize = new Size(101,30);
If you want to draw rectangle on the screen, you can draw it directly: http://bytes.com/topic/c-sharp/answers/263740-draw-directly-screen
Drawing C# graphics without using Windows Forms
That like talks about making a border-less window. From there, just use the Graphics object to draw whatever you'd like

Categories

Resources