I just would like to know if it is possible to dock a windows form on top of the user screen? I have been trying to do this by manually setting the position of my form to the coordinates I want. But using this method, however, allows the user to change the position of the form just by dragging it. I want to make the form docked to the upper portion of the screen since this window form will server as a menu for the project I am making.
Thanks a lot. :)
I would consider using the Control.Dock property along with one of the DockStyle enumeration values.
You might need to play with the Layout too, so that you may layout your form's controls differently depending on the DockStyle selected.
You will need, in my point of view, to consider the Control.Location property so that you get to know which DockStyle value to dock your form with.
EDIT #1
Your Windows Form has a Dock property as it inherits from Control.
Let's consider the following :
Each time your form comes closer to your right-side of the screen, for example, or of the MDI container, you want to dock right, right ? (Little word play here... =P) So, you have to subscribe to the Control.LocationChanged event.
private void myForm_LocationChanged(object sender, EventArgs e) {
if (this.Location.X > 900) then
this.Dock = DockStyle.Right;
else if (this.Location.X < 150) then
this.Dock = DockStyle.Left;
else if (this.Location.Y > 600) then
this.Dock = DockStyle.Bottom;
else if (this.Location.Y < 150) then
this.Dock = DockStyle.Top;
else
this.Dock = DockStyle.None;
}
Indeed, instead of constant values, you should use the current desktop resolution and calculate a ratio from it where you want your docking to occur.
***Disclaimer:****This code is provided as-is and has not been tested. This algorithm is hopefully enough to guide you through the docking process as you need it. Further assistance may be brought upon request.* =)
It seems the Form.DesktopLocation property is the righter tool for the job as for your main window, meaning your MDI container, for instance. As for the other windows, I would go along with something that looks like the code sample provided.
Does this help?
EDIT #2
If you want to prevent Form's overlapping, perhaps the Control.BringToFront() method could do it before or after your call to the Control.Show() method, depending on what works best for you.
So after some tweaks I finally was able to get this code working.
this.DesktopLocation = new Point((Screen.PrimaryScreen.Bounds.Width / 2 - 420), 0);
I placed that line below the InitializeComponent() and it docks my form to the center of the screen with whatever resolution values.
By setting the FormBorderStyle of your form to None, you take the drag handle away from the user so they cannot move it via the mouse.
Then you just need to place it where you want.
If you really want to take away the users options you can also set the ShowInTaskbar property to false
Related
Before you jump to conclusions and ask "Why don't you just Hide() the form?" let me explain.
I have the following:
A PDF Viewer control PDFViewer.
A form containing a TextBox TextBoxForm.
A parent form containing PDFViewer and TextBoxForm (with Owner property set to this parent).
TextBoxForm is an overlay to PDFViewer and should be hidden when outside the bounds of PDFViewer, which can happen if the user scrolls. Here's how I achieve that:
PDFViewer_OnScroll(object sender, HandledMouseEventArgs e){
TextBoxForm.SetBounds(GetBounds(PDFViewer));
TextBoxForm.Top = [some value];
}
Ìnside TextBoxForm I do the following:
protected override void OnMove(EventArgs e)
{
base.OnMove(e);
UpdateFormRegion(); // Offset bounds so it's relative to the form itself instead of the screen
Invalidate();
}
This works fine when TextBoxForm is completely or partially inside the bounds of PDFViewer, but as soon as it's moved completely outside, whichever part of TextBoxForm was rendered before will still be rendered (I assumed it's because Windows decides there is no need to re-paint the form, when it's not inside it's own bounds).
It's easy enough to make a check for when this happens, but the reason I don't want to call TextBoxForm.Hide() is because that causes the TextBox to lose focus.
Any way I can get the form hidden without losing focus?
I just thought of a possible solution (not a very elegant one, however):
if (Right < _bounds.Left || Left > _bounds.Right || Bottom < _bounds.Top || Top > _bounds.Bottom)
{
Top = -20000;
Left = -20000;
}
Basically, whenever the form is moved/resized I check if it is now completely outside the supplied bounds and move it way off screen if true.
A less "hacky" solution is still welcome.
I am trying to get an accurate Form.Width on FormClosing().
I have a zoom() method I use to scale a picture in the Form. The form's width is then manually re-sized by me to fit. I then, set the MaximumSize's Width limit to the new width of the form. For our purpose, let's say the width and maxwidth are now 1386.
If I re-size the form in the Windows interface by dragging its edge to the left, the width is being reduced just fine. FormClosing reports the re-sized width accurately. Let's say 1107.
However, if go through the zoom() method I wrote, even though I drag to the left to the same position, FormClosing is reporting the ORIGINAL 1386 width. The only things I do to form size in the zoom() method are set width and maxwidth.
I am at a loss to handle this behavior. I need FormClosing to report the correct size. I think FormClosing is setting the Width to MaximumWidth when it fires. I think I read something about how the Form is set to Hidden by the time the FormClosing event is fired. Maybe being Hidden reverts its size to MaxWidth.
Any help would be much appreciated. I have been struggling with this for a few hours and can't find anything.
Thanks.
Here is the relevant code:
private void zoom()
{
// Re-size form width to slightly more than page width.
// This is percentage-based, meaning 100 = default size.
Size picSize = new Size
{
Width = (int)(originalRenderingSize.Width * integerUpDownZoom.Value / 100),
Height = (int)(originalRenderingSize.Height * integerUpDownZoom.Value / 100),
};
// some code here which I commented-out, and still, the problem exists.
// Set maximum to prevent ugly sizing.
this.MaximumSize = new Size(picSize.Width + 40, Screen.FromControl(this).WorkingArea.Height);
// The problem is this: When this method processes, as shown, a page is rendered and sized according to
// a user-provided zoom level represented by an integerUpDown control. Once rendered, the form should
// re-size its width to match the newly-scaled page's width. This works, too. So far, so good.
//
// But!!! If the user grabs the right side of the form and drags it to the left to reduce the width
// of the form (mind you, this is Windows OS doing this), upon Form.Form_Closing(), you can see a
// quick flash of the form fully-open and unscrolled. Then, in the FIRST line of Form_Closing(),
// the debugger reports the form's width as the fully-open and UNSCROLLED width.
//
// The goal is to set the width upon the conclusion of this zoom, but then, on closing
// get the width of the Form in order to persist it for use the next time the app is run.
//
// 2 options have been tried. Both cause Form_Closing to erroneously report the fully-open width.
// But if BOTH are commented-out, the re-sizing occurs and Form_Closing() reports properly the
// form's scrolled width.
// Bear in mind that Form_Closing is one of those things that can happen anytime or never. This means
// the bug is triggered by EITHER and ONLY the two options below.
// Option 1: Tried first. It sets the width fine.
//
// this.Width = picSize.Width + 40;
// Option 2: It also sets the width fine.
// I think this option causes width to change (it invokes width change, and somewhere in the
// OS's width change, the error occurs.
//this.MinimumSize = new Size(MaximumSize.Width - 1, this.Height);
//this.MinimumSize = new Size(0, 0);
}
Edit: I have new information which should help. The culprit is FormClosing(). Here's what I did: I re-sized the form in Windows until it occupied maybe 500 pixels in width. The horizontal scrollbar on my panel was showing. Then, in the FormClosing event, I added the line: Form.Show(). After that, I put a MessageBox.Show("Hi."). Sure enough, the Show() caused the form to repaint in its full, unscrolled width. It did not maintain its scroll state.
I think I have the solution and will post back after trying. Namely, I need to check Scroll values and operate on those values as well.
Edit 2: FormClosing() also re-sets HorizontalScroll.Value and VerticalScroll.Value to 0. This is a bummer! I wonder how to work around this. I also looked at e.Cancel, but there seems to be no way to take advantage of it, either. It seems e.Cancel just re-shows() the form in its unhidden state.
Sorry I cannot post the code. It would be pointless anyway. Think about it. The Windows OS handles the resizing. Not me. When the user re-sizes the form, it's all on Windows. If user re-sizes the form to 500 pixels wide, but FormClosing() reports it is 1386 pixels wide, no amount of my coding will show us anything new. This is a behavior issue. There is no code to show you how the Windows OS handles form re-sizing.
On FormClosing Event Use:
MessageBox.Show(this.Width.ToString());
You're using another Instance of your form's class, Form.Show() should not work in this event cause Dispose function is called and if you have referenced the same instance it will be disposed as well.
I would like to have a form in which the controls on the form are fully visible but the form itself is invisible. If I change the form's Opacity, this makes both the form and the controls on it semi-transparent, so this doesn't work.
I can't do this by setting the form's TransparencyKey, since I have a PictureBox on the form. If the image in the PictureBox happens to contain pixels that match the TransparencyKey, they appear as openings in the form, which I don't want.
TransparencyKey is the only way to get this. Pick the right color. Color.Fuchsia has a long tradition of being the color of choice, going back to the early days of Win32 development. Assault your eye with it to see its merits.
With the caveat that I've never used it, just ran across it once, thought "neat!" and moved on...
Look into System.Drawing.Drawing2D.GraphicsPath and setting the form's Region property. I added two buttons to the basic Windows forms application:
public Form1()
{
InitializeComponent();
Rectangle r1 = new Rectangle(button1.Location, button1.Size);
Rectangle r2 = new Rectangle(button2.Location, button2.Size);
GraphicsPath gp = new GraphicsPath();
gp.AddRectangle(r1);
gp.AddRectangle(r2);
this.Region = new Region(gp);
}
I've approximated the shape of the button with a rectangle; with this code, you can see the form background color at the buttons' corners. You'll need to work out the enclosing path for each of your controls and add them to the path individually. You'll need to take into account any offset introduced by the form title bar or border style.
Update: I did some investigation and have a couple of possible approaches for the problem:
Using the GraphicsPath method, set pictureBox.Visible to False if there is no image loaded.
When you load an image into the picture box, analyze the image to get a list of all the colors in it, then randomly generate one that isn't. Set the form's BackColor and TransparencyKey properties to match this new color, Hans Passant's answer.
I am developing a quick app in C#. One thing that I want to do is the equivalent of Swing's (java) pack(). This is a call that allows me to say to a form (Frame in Java), resize yourself to the size of the sum of the components within yourself.
I have searched and searched (the components change dynamically so I cannot simply hardcode the form to the right size) but I cannot find the equivalent method in C#.
Does anyone know what it is called?
You don't even need write code in order to 'pack' the form. In the forms designer, set the form's AutoSize property to true, and set the AutoSizeMode property to GrowAndShrink, repeat this for any controls on the form which may also change size.
And voila!
At runtime (only), the form will dynamically resize itself to accommodate all the controls. If you want it to keep a little distance from the controls so that the controls won't 'stick' to the edges, you can set the Padding property (I'd recommend at least a value of 12,12,12,12).
Also in xaml:
<Window SizeToContent="WidthAndHeight" />
Another solution, available only if the image is smaller than the screen:
Form frm = new Form();
PictureBox pbx = new PictureBox();
pbx.Image = Image.FromFile( _imagePath.Text );
pbx.Dock = DockStyle.Fill;
frm.Controls.Add( pbx );
frm.Size = pbx.Image.Size;
frm.Show();
I'm trying to center a fixed size control within a form.
Out of interest, is there a non-idiotic way of doing this? What I really want is something analogous to the text-align css property.
At the moment, I'm setting the padding property of the surrounding form to a suitable size and setting the Dock property of the control to fill.
You could achieve this with the use of anchors. Or more precisely the non use of them.
Controls are anchored by default to the top left of the form which means when the form size will be changed, their distance from the top left side of the form will remain constant. If you change the control anchor to bottom left, then the control will keep the same distance from the bottom and left sides of the form when the form if resized.
Turning off the anchor in a direction will keep a control centered when resizing, if it is already centered. In general, a control not anchored maintains its proportional position to the dialog. E.g. If you put a control at X=75% of the dialog width and turn off left/right anchors, the control will maintain its center at X=75% of the dialog width.
NOTE: Turning off anchoring via the properties window in VS2015 may require entering None (instead of default Top,Left)
myControl.Left = (this.ClientSize.Width - myControl.Width) / 2 ;
myControl.Top = (this.ClientSize.Height - myControl.Height) / 2;
Since you don't state if the form can resize or not there is an easy way if you don't care about resizing (if you do care, go with Mitch Wheats solution):
Select the control -> Format (menu option) -> Center in Window -> Horizontally or Vertically
I found a great way to do this and it will work with multiple controls. Add a TableLayout with 3 columns. Make the center column an absolute size (however much room you need). Set the two outside columns to 100%. Add a Panel to the center column and add any controls you need and place them where you want. That center panel will now remain centered in your form.
To center Button in panel o in other container follow this step:
At design time set the position
Go to properties Anchor of the button and set this value as the follow image
In addition, if you want to align it to the center of another control:
//The "ctrlParent" is the one on which you want to align "ctrlToCenter".
//"ctrlParent" can be your "form name" or any other control such as "grid name" and etc.
ctrlToCenter.Parent = ctrlParent;
ctrlToCenter.Left = (ctrlToCenter.Parent.Width - ctrlToCenter.Width) / 2;
ctrlToCenter.Top = (ctrlToCenter.Parent.Height - ctrlToCenter.Height) / 2;
You can put the control you want to center inside a Panel and set the left and right padding values to something larger than the default. As long as they are equal and your control is anchored to the sides of the Panel, then it will appear centered in that Panel. Then you can anchor the container Panel to its parent as needed.
It involves eyeballing it (well I suppose you could get out a calculator and calculate) but just insert said control on the form and then remove any anchoring (anchor = None).
you can put all your controls to panel and then write a code to move your panel to center of your form.
panelMain.Location =
new Point(ClientSize.Width / 2 - panelMain.Size.Width / 2,
ClientSize.Height / 2 - panelMain.Size.Height / 2);
panelMain.Anchor = AnchorStyles.None;
To keep the control centered even the form or parent control were resize.
Set the following properties of the parent element (you can set it through the property window):
parentControl.AutoSize = true;
parentControl.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
Put this code in the Resize event of the form or the parent control (if the control is inside of another control).
controlToCenter.Left = (parentControl.Width- controlToCenter.Width) / 2;
controlToCenter.Top = (parentControl.Height - controlToCenter.Height) / 2;
If the parent control is docked to the form, add this line of code.
//adjust this based on the layout of your form
parentControl.Height = this.ClientSize.Height;
So, I am currently working on a pagination control and I came up with the following to achieve the below result.
Add a PanelLayout to your container (e.g. form or usercontrol)
Set the PanelLayout properties:
Dock: Bottom (or Top)
AutoSize: False
This will center the PanelLayout horizontally.
Now, in your codebehind, do something like this:
public MyConstructor()
{
InitializeComponent();
for (var i = 0; i<10; i++)
{
AddButton(i);
}
}
void AddButton(int i)
{
var btn = new Button();
btn.Width = 30;
btn.Height = 26;
btn.Text = i.ToString();
this.flowLayoutPanel1.Controls.Add(btn);
btn.Anchor = AnchorStyles.None;
}
There is a ceveat, however. If I make my form too small (horizontally) buttons will "disappear" outside of the viewport. In my case, that's not a problem, but you could take care of this by writing code that listens to the Resize event, and remove elements (buttons) based on the viewport Width.