C#, WinForms - Change FormBorderStyle without the client area moving - c#

I have a small tool window that normally has the FormBorderStyle to FixedDialog with no caption text and no control box so it looks like a border-less form with a raised 3d effect.
When the user moves the mouse over the tool window it changes from this border-less FixedDialog mode to a SizableToolWindow w/ caption text and a control box.
The result is the client area moving.
The following code works but i do not want to hard code the top/left delta and I assume it is different depending on what theme/os the user has
void Reposition()
{
var topDelta = 12; // this number is wrong, i have not found the right number for aero yet
var leftDelta = 3;
if (this.Bounds.Contains(MousePosition))
{
if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
{
this.Location = new Point(this.Location.X - leftDelta, this.Location.Y - topDelta);
this.ControlBox = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
}
}
else
{
if (this.FormBorderStyle == System.Windows.Forms.FormBorderStyle.SizableToolWindow)
{
this.Location = new Point(this.Location.X + leftDelta, this.Location.Y + topDelta);
this.ControlBox = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
}
}
}

Look into SystemParameters class. You will find the values you are hard-coding in your code there.

Related

C# Screen Class member methods cannot open form on secondary display

There are some methods from the Screen class to retrieve the respective screen, which contains the most area of a control.
They are the:
Screen.FromRectangle(Rectangle rect)
Screen.FromControl(Control control)
Screen.FromHandle(IntPtr hwnd)
Screen.FromPoint(Point point)
The issue here is that I have a problem getting my second Form to be opened in the second monitor. It kept on displaying only on the primary screen. According to the answer from here, the suspect is that the DpiAware was not enabled. However, the problem was still not fixed even after I have enabled the DpiAware.
To help me to check what was going on, I've added code for debugging. Then, I called/ opened the popup menu on \\\\.\\DISPLAY2. Inside of the debug console, the chosen Screen for FromPoint() was written \\\\.\\DISPLAY2. However, the popup menu was still opened on \\\\.\\DISPLAY1. Can anyone help me with this issue, please?
Below are the codes example:
Under main form class:
//mouseup event handler
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
//if RMB clicked
if(e.Button == MouseButtons.Right)
{
//----set PopupMenu form location----
popupMenuObj.Location = popupMenuObj.popupMenuLocation((sender as Control).PointToScreen(e.Location));
//----set PopupMenu form location----
//process the form location
popupMenuObj.Location = popupMenuObj.processFormLocation(popupMenuObj.Location);
//----set PopupMenu cursor location----
Cursor.Position = popupMenuObj.middleOfPopupMenu(popupMenuObj.Location);
//----set PopupMenu cursor location----
//----display the popup menu----
popupMenuObj.displayPopupMenu(1);
//----display the popup menu----
}
}
Under popup menu class:
//to set cursor to middle of popup menu
public Point middleOfPopupMenu(Point mousePoint)
{
int theCenterWidth = this.Width / 2;
int theCenterHeight = this.Height / 2;
//set the mouse pointer location at middle of PopupMenu
mousePoint.X += theCenterWidth;
mousePoint.Y += theCenterHeight;
return Cursor.Position = mousePoint;
}
//to set popupmenu location
public Point popupMenuLocation(Point thePoint)
{
return this.Location = thePoint;
}
//set popup menu display status
public bool displayPopupMenu(int displayFlag)
{
switch(displayFlag)
{
case 1: //if argument 1 -> display the PopupMenu
this.Visible = true;
return true;
case 0: //if argument 0 -> close the PopupMenu
this.Visible = false;
return false;
default: //by default, no need to display
return false;
}
}
//to process if popupmenu opens exceeding the screen working area
public Point processFormLocation(Point currentPoint)
{
Point newPoint = new Point();
int selectedScrWidth, selectedScrHeight; //screen dimension of the selected screen
Screen selectedScreen;
int totalXPos, totalYPos; //where the form is located before exceed screen is handled
//---get screen where point is at---
selectedScreen = Screen.FromPoint(currentPoint);
Console.WriteLine("\nSelected screen info: {0}\n", selectedScreen); //for debugging purposes
//---get screen where point is at---
//---get selected screen dimension---
selectedScrWidth = selectedScreen.WorkingArea.Width;
selectedScrHeight = selectedScreen.WorkingArea.Height;
//---get selected screen dimension---
totalXPos = currentPoint.X + this.Width; //mouseXCoor + popupMenu width
totalYPos = currentPoint.Y + this.Height; //mouseXCoor + popupMenu height
//if exceed selected screen width and height
if ((totalXPos >= selectedScrWidth) && (totalYPos >= selectedScrHeight))
{
newPoint.X = selectedScrWidth - this.Width;
newPoint.Y = selectedScrHeight - this.Height;
}
//if exceed selected screen width
else if ((totalXPos >= selectedScrWidth))
{
newPoint.X = selectedScrWidth - this.Width;
newPoint.Y = currentPoint.Y;
}
//if exceed selected screen height
else if ((totalYPos >= selectedScrHeight))
{
newPoint.X = newPoint.X;
newPoint.Y = selectedScrHeight - this.Height;
}
else //if x exceed screen, just set the location as is
{
return this.Location = Cursor.Position;
}
return this.Location = newPoint;
}
Update 1:
As per Jimi's request under the comment section, after creating a simple test project based on given answer here, here's what I got:
Please note the reason why the code in the question from the previous thread has no Width, Height, and StartPosition = FormStartPosition.Manual defined was because the popup menu is from a class on another .cs file where, those specific properties have already been declared in the PopupMenu.Designer.cs file. Therefore, I don't feel like redefining was necessary.
Update 2:
Now that it works, a newer problem arises is that, only when popup menu exceeds right boundary of secondary display, the popup menu was displayed on primary screen. However this didn't occur when I try to open the popup menu when exceeding the height of secondary screen. Example is shown below:
Above is the case when I try to open the popup menu when exceeding the width of secondary screen. The popup menu opens at the right boundary of primary screen.
It however worked just fine when I tried the case for exceeding the height of secondary display.

Taskbar not hiding when single screen but hiding when multiple C#

I have the below code which I use which includes hiding the taskbar by my form. It works well if there are two screens connected to my computer but if there is only one screen the taskbar shows, I am not sure why?
FormBorderStyle = FormBorderStyle.None;
await Task.Delay(500);
this.WindowState = FormWindowState.Normal;
this.ActiveControl = textBox1;
StartPosition = FormStartPosition.Manual;
Location = new Point(0, 0);
var height = Screen.AllScreens.Max(x => x.WorkingArea.Height + x.WorkingArea.Y);
var width = Screen.AllScreens.Max(x => x.WorkingArea.Width + x.WorkingArea.X);
Size = new Size(width, height);
this.BringToFront();
this.AcceptButton = button1;
this.ControlBox = false;
this.TopMost = true;
this.Size = Size;
Rectangle ru = Rectangle.Union(Screen.AllScreens[0].Bounds , Screen.AllScreens[1].Bounds);
Bounds = ru;
You're getting an "System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'" error because of AllScreens[1] when you only have one screen connected there is only one value in the AllScreen array so index[1] is out of bound.
Change;
Rectangle ru = Rectangle.Union(Screen.AllScreens[0].Bounds , Screen.AllScreens[1].Bounds);
To;
var ru = Screen.AllScreens.Select(a => a.Bounds).Aggregate(Rectangle.Union);
Now because you're using a Select you wil only getting AllScreens[0] instead of guessing what indexes well be there this code now also works is you have three monitors or any other configuration of monitors.
Edit
Also, as a small side note if you're trying to block a user from doing anything outside of your program. This will not block them fully actions like pressing the windows key will still bring up the taskbar or give control back to the user.

Maximizing borderless form with multiple monitors c#

I'm currently making a borderless form with a Doubleclick event to maximize form. But I realized that the form wouldn't maximize on the two other screens, only my main middle.
So my code is currently:
private void Form1_DoubleClick(object sender, EventArgs e)
{
if ((this.Height == Screen.PrimaryScreen.WorkingArea.Height) && (this.Width == Screen.PrimaryScreen.WorkingArea.Width))
{
this.Width = 534;
this.Height = 600;
CenterToScreen();
}
else
{
this.Height = Screen.PrimaryScreen.WorkingArea.Height;
this.Width = Screen.PrimaryScreen.WorkingArea.Width;
this.Location = Screen.PrimaryScreen.WorkingArea.Location;
}
}
It might look weird, but I use it to not cover the taskbar.
I need a code like this to dock it to the side, and use it to calculate where the form should be. Looking like this: half right screen dock
when I click one of those 9 buttons, it will dock the screen in different places of the screen. In corner, half of the screen or in the middle.
I tried using a code where the form would detect which screen it was on, and using that again to maximize the form on that screen, but I got a bunch of red lines, and it didn't work in the end.
I have 3 monitors.
Please help.
You hardcoded it to primary screen, which is the screen with the task bar. To allow other screens get the screen the form is currently on an adjust to that.
private void Form1_DoubleClick(object sender, EventArgs e)
{
if ((this.Height == Screen.FromControl(this).WorkingArea.Height) && (this.Width == Screen.FromControl(this).WorkingArea.Width))
{
this.Width = 534;
this.Height = 600;
CenterToScreen();
}
else
{
this.Height = Screen.FromControl(this).WorkingArea.Height;
this.Width = Screen.FromControl(this).WorkingArea.Width;
this.Location = Screen.FromControl(this).WorkingArea.Location;
}
}

Windows Vista Sidebar Equivalent

I'm trying to create an application that looks similar to the Windows Vista sidebar. There's an API that allows docking toolbars on the screen (AppBar), but it's not exactly what I'm looking for.
How can I attach a Form to the desktop and dock it to the side of the screen, but without preventing other windows from overlapping it?
With all the following options you get a Sidebar look-a-like (the code below is for a WPF Window):
//width of the sidebar
Width = 300;
//height (remember to add a reference to the System.Windows.Forms dll)
Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
//no window style means no border
WindowStyle = WindowStyle.None;
//not resizable
ResizeMode = ResizeMode.NoResize;
//allow a transparent sidebar
AllowsTransparency = true;
//change the color
Background = new SolidColorBrush(Colors.CadetBlue);
//set the opacity (how much transparent)
Opacity = 0.5d;
//offset from the top
Top = 0;
//offset from the left (calculated so it shows on the right side)
Left = SystemParameters.PrimaryScreenWidth - (double)GetValue(WidthProperty);
//set it the topmost window
Topmost = true;
//hide the icon from the taskbar
ShowInTaskbar = false;
Hope this helps!
Update:
Here's a similar solution for when you're using WindowsForms, altough with WPF you have much more possibilities! The differences are minor, everything explains itself. The last line I added hides the window taskbar-icon. Do not place the code in the constructor of the Form but in the Load-event, otherwise the Location will be wrong. In WPF this doesn't matter.
Width = 300;
Height = Screen.PrimaryScreen.Bounds.Height;
FormBorderStyle = FormBorderStyle.None;
BackColor = Color.CadetBlue;
Opacity = 0.5d;
Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width, 0);
TopMost = true;
ShowInTaskbar = false;

How to display a Windows Form in full screen on top of the taskbar? [duplicate]

This question already has answers here:
How do I make a WinForms app go Full Screen
(10 answers)
Closed 8 years ago.
I have a .net windows application that needs to run in full screen. When the application starts however the taskbar is shown on top of the main form and it only disappears when activating the form by clicking on it or using ALT-TAB. The form's current properties are as follow:
WindowState=FormWindowState.Normal
TopMost=Normal
Size=1024,768 (this is the screen resolution of the machines it's going to be running on)
FormBorderStyle = None
I've tried adding the followings on form load but none worked for me:
this.Focus(); (after giving the focus this.Focus property is always false)
this.BringToFront();
this.TopMost = true; (this however would not be ideal in my scenario)
this.Bounds = Screen.PrimaryScreen.Bounds;
this.Bounds = Screen.PrimaryScreen.Bounds;
Is there a way to do it within .NET or would I have to invoke native windows methods and if so a code snippet would very much be appreciated.
many thanks
Use:
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
And then your form is placed over the taskbar.
I've tried so many solutions, some of them works on Windows XP and all of them did NOT work on Windows 7. After all I write a simple method to do so.
private void GoFullscreen(bool fullscreen)
{
if (fullscreen)
{
this.WindowState = FormWindowState.Normal;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Bounds = Screen.PrimaryScreen.Bounds;
}
else
{
this.WindowState = FormWindowState.Maximized;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
}
}
the order of code is important and will not work if you change the place of WindwosState and FormBorderStyle.
One of the advantages of this method is leaving the TOPMOST on false that allow other forms to come over the main form.
It absolutely solved my problem.
This is how I make forms full screen.
private void button1_Click(object sender, EventArgs e)
{
int minx, miny, maxx, maxy;
inx = miny = int.MaxValue;
maxx = maxy = int.MinValue;
foreach (Screen screen in Screen.AllScreens)
{
var bounds = screen.Bounds;
minx = Math.Min(minx, bounds.X);
miny = Math.Min(miny, bounds.Y);
maxx = Math.Max(maxx, bounds.Right);
maxy = Math.Max(maxy, bounds.Bottom);
}
Form3 fs = new Form3();
fs.Activate();
Rectangle tempRect = new Rectangle(1, 0, maxx, maxy);
this.DesktopBounds = tempRect;
}
My simple fix it turned out to be calling the form's Activate() method, so there's no need to use TopMost (which is what I was aiming at).
A tested and simple solution
I've been looking for an answer for this question in SO and some other sites, but one gave an answer was very complex to me and some others answers simply doesn't work correctly, so after a lot code testing I solved this puzzle.
Note: I'm using Windows 8 and my taskbar isn't on auto-hide mode.
I discovered that setting the WindowState to Normal before performing any modifications will stop the error with the not covered taskbar.
The code
I created this class that have two methods, the first enters in the "full screen mode" and the second leaves the "full screen mode". So you just need to create an object of this class and pass the Form you want to set full screen as an argument to the EnterFullScreenMode method or to the LeaveFullScreenMode method:
class FullScreen
{
public void EnterFullScreenMode(Form targetForm)
{
targetForm.WindowState = FormWindowState.Normal;
targetForm.FormBorderStyle = FormBorderStyle.None;
targetForm.WindowState = FormWindowState.Maximized;
}
public void LeaveFullScreenMode(Form targetForm)
{
targetForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
targetForm.WindowState = FormWindowState.Normal;
}
}
Usage example
private void fullScreenToolStripMenuItem_Click(object sender, EventArgs e)
{
FullScreen fullScreen = new FullScreen();
if (fullScreenMode == FullScreenMode.No) // FullScreenMode is an enum
{
fullScreen.EnterFullScreenMode(this);
fullScreenMode = FullScreenMode.Yes;
}
else
{
fullScreen.LeaveFullScreenMode(this);
fullScreenMode = FullScreenMode.No;
}
}
I have placed this same answer on another question that I'm not sure if is a duplicate or not of this one. (Link to the other question: How do I make a WinForms app go Full Screen)
FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
I believe that it can be done by simply setting your FormBorderStyle Property to None and the WindowState to Maximized. If you are using Visual Studio both of those can be found in the IDE so there is no need to do so programmatically. Make sure to include some way of closing/exiting the program before doing this cause this will remove that oh so helpful X in the upper right corner.
EDIT:
Try this instead. It is a snippet that I have kept for a long time. I can't even remember who to credit for it, but it works.
/*
* A function to put a System.Windows.Forms.Form in fullscreen mode
* Author: Danny Battison
* Contact: gabehabe#googlemail.com
*/
// a struct containing important information about the state to restore to
struct clientRect
{
public Point location;
public int width;
public int height;
};
// this should be in the scope your class
clientRect restore;
bool fullscreen = false;
/// <summary>
/// Makes the form either fullscreen, or restores it to it's original size/location
/// </summary>
void Fullscreen()
{
if (fullscreen == false)
{
this.restore.location = this.Location;
this.restore.width = this.Width;
this.restore.height = this.Height;
this.TopMost = true;
this.Location = new Point(0,0);
this.FormBorderStyle = FormBorderStyle.None;
this.Width = Screen.PrimaryScreen.Bounds.Width;
this.Height = Screen.PrimaryScreen.Bounds.Height;
}
else
{
this.TopMost = false;
this.Location = this.restore.location;
this.Width = this.restore.width;
this.Height = this.restore.height;
// these are the two variables you may wish to change, depending
// on the design of your form (WindowState and FormBorderStyle)
this.WindowState = FormWindowState.Normal;
this.FormBorderStyle = FormBorderStyle.Sizable;
}
}
I'm not have an explain on how it works, but works, and being cowboy coder is that all I need.
System.Drawing.Rectangle rect = Screen.GetWorkingArea(this);
this.MaximizedBounds = Screen.GetWorkingArea(this);
this.WindowState = FormWindowState.Maximized;
FormBorderStyle = FormBorderStyle.Sizable;
TopMost = false;
WindowState = FormWindowState.Normal;
THIS CODE MAKE YOUR WINDOWS FULL SCREEN THIS WILL ALSO COVER WHOLE SCREEN

Categories