I'm working on a project where I have to add a small preview pane and a about box whenever a user is hovering the buttons on the main window.
For the examlpe: I have a window - preview.xaml, and my main window called MainWindow.xaml.
How do I set the preview windows bottom to appear on the top of button1 on the MainWindow?
I tried something like this without any luck:
public preview()
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.Manual;
Top = mainWindow.button1.Margin.Top;
}
I hope my ramblings makes any sense...
Any help is greatly appreciated!
You need to set Left and Top window properties to screen coordinates, button margins won't help here. Use PointToScreen function to obtain screen coordinates of your buttons:
private void button1_MouseEnter(object sender, MouseEventArgs e)
{
var control = ((FrameworkElement)sender);
// get screen coordinates of (0,0) point of button
var location = control.PointToScreen(new Point(0, 0));
var w = new preview()
{
WindowStartupLocation = System.Windows.WindowStartupLocation.Manual,
ShowActivated = false,
};
w.Top = location.Y - w.Height;
w.Left = location.X + (control.ActualWidth - w.Width) / 2;
w.Show();
}
You have to do it the other way round. In your MainWindow where you open the preview-window do something like this:
PreviewWindow preview = new PreviewWindow
{
Owner = this,
WindowStartupLocation = WindowStartupLocation.Manual,
Top = button1.Margin.Top
};
preview.Show();
If you want to reuse that window, you have to do a little logic around.
Related
Lately I am working on this personal app, it's form is without border so the Exit Button, Minimize Button and Maximize button, as well as the option to resize and move the form have been custom added. The app contains several User Controls which perform different functions such as Login, a Control Panel for the app and so on. The issue here is that the User Controls, which are placed within a panel (Anchored properly, of course) in the main form are not resizing properly when the window is in a Maximized state.
To detail... the app starts at
this size and while it's manually resized in minimized state the controls have no issue inheriting it's parent's (the panel) size,
like this and this also works if the window is maximized while the control is visible, like this however if the window is already in a maximized state and I call the control with the designated button the control does not resize, it stays to it's minimum dimensions, like so.
At first I thought it may have something to do with the code that resizes the form so I removed everything and made the app with the default windows border and controls, basically set the border Property from none to sizable but that did nothing. Also I have tried accessing the User Control's parent (the panel) using this.Parent and then setting the width and height of the control with Width = this.Parent.Width and Height = this.Parent.Height but the parent returns null for some reason which I am yet to understand. Now, worth mentioning that those user controls are dynamically added (i.e Login loginForm = new Login();) to the panel every time the button is clicked and then Disposed once the control is left.
I looked all over Google for this but found nothing related and at this point I am out of options. I really want the app to be resizable and must resize properly so if anyone has any solutions I am open to anything.
Thanks anticipated.
Meanwhile, for Winforms, I may have an answer.. the key is to use the Resize event of your user control(s), see below. I tested this in Core 3.1 and Net 4.7, you can use an default designer.cs unit with an empty form. It has no issues with resize from maximized state.
My user control for the center app is named CenteredPanel and derived from Panel. Make sure you derive your user controls from Panel and call base() on the constructor, else the docking will not work properly.
Also, your question about parenting: it was not needed to use Parent below, but if you really need it, make sure you assign it !
public partial class Form1 : Form
{
private Panel panel1, panel2, panel3, panel4;
private CenteredPanel panelApp;
public Form1()
{
InitializeComponent();
this.panel1 = new System.Windows.Forms.Panel()
{ Parent = this, Dock = DockStyle.Fill };
this.panel2 = new System.Windows.Forms.Panel()
{ Parent = panel1, Dock = DockStyle.Left, Width = 120, BackColor = Color.FromArgb(60, 60, 60) };
this.panel3 = new System.Windows.Forms.Panel()
{ Parent = panel1, Dock = DockStyle.Fill };
this.panel4 = new System.Windows.Forms.Panel()
{ Parent = panel3, Dock = DockStyle.Top, Height = 60, BackColor = Color.FromArgb(60, 60, 60) };
this.panelApp = new WindowsFormsAppCore.CenteredPanel()
{ Parent = panel3, Dock = DockStyle.Fill, BackColor = Color.FromArgb(90, 90, 90) };
this.panel1.Controls.Add(this.panel3);
this.panel1.Controls.Add(this.panel2);
this.panel3.Controls.Add(this.panelApp);
this.panel3.Controls.Add(this.panel4);
this.Controls.Add(this.panel1);
}
}
public class CenteredPanel : Panel
{
Label label1, label2;
TextBox textbox1;
public CenteredPanel() : base()
{
this.Resize += new System.EventHandler(this.Resizer);
this.label1 = new System.Windows.Forms.Label()
{ Parent = this, AutoSize = true, Name = "label1", ForeColor =Color.White, Text = "Connectare Administrator" };
this.label2 = new System.Windows.Forms.Label()
{ Parent = this, AutoSize = true, Name = "label2", ForeColor = Color.White, Text = "Nume de utilizator" };
this.textbox1 = new System.Windows.Forms.TextBox()
{ Parent = this, AutoSize = true, Name = "textbox1", PasswordChar = '*', Text = "****" };
this.Controls.Add(this.label1);
this.Controls.Add(this.label2);
this.Controls.Add(this.textbox1);
}
public void Resizer(object sender, EventArgs e)
{
Point CenteringAnchor = new Point(Width / 2, Height / 2);
for (int i=0; i<Controls.Count; i++)
{
Control c = Controls[i];
// put your resizing rules here.. this is a very simple one
c.Location = new Point(CenteringAnchor.X - c.Width / 2, -40 + i * ((i == 1) ? 40 : 30) + CenteringAnchor.Y - c.Height / 2);
}
}
}
I'm working on a Excel add-in project that will require me to procedurally generate some controls in a windows task pane. While experimenting, I ran into an issue where this button keeps having its width set to 0, and I don't understand why.
If I don't use any anchoring or docking then the button shows up, but at its default width and height. I am trying to get it to span the width of the layout panel, and it was my understanding you could accomplish this by using AnchorStyles Left and Right, or with DockStyle Fill. However, as soon as I add these properties the width gets set to 0 (as seen from the debugger). I checked the width of the root control (this) and the button's parent control FlowLayoutPanel, and they are both the default non-zero size.
What am I doing wrong?
public MyUserControl()
{
FlowPanel = new FlowLayoutPanel
{
Name = "My Flow Panel",
TabIndex = 0,
FlowDirection = FlowDirection.TopDown,
};
Button button1 = new Button
{
Name = "button1",
Text = this.Width.ToString(),
FlatStyle = FlatStyle.Flat,
Padding = new Padding
{
Left = 10
},
Parent = FlowPanel,
Anchor = (AnchorStyles.Left | AnchorStyles.Right)
};
FlowPanel.Controls.Add(button1);
this.Controls.Add(FlowPanel);
}
You can't anchor like that in FlowLayoutPanels. Instead, subscribe to the SizeChanged event and modify the button width there. You'll probably also need to set the width when you create the button, so below I've just created a method you can call from both places.
FlowPanel.SizeChanged += new System.EventHandler(this.FlowPanel_SizeChanged);
private void FlowPanel_SizeChanged(object sender, EventArgs e)
{
SetButtonWidth();
}
void SetButtonWidth()
{
button1.Width = FlowPanel.Width - FlowPanel.Padding.Horizontal - button1.Margin.Horizontal;
}
So I'm trying to open a maximized Window on my secondary monitor. It all works fine, except it's height is 2 pixels lower than it should be.
My secondary monitor has a resolution of 1280x1024. However once I inspect the window, it's 1280x1022. Does anyone know the problem?
OS: Windows 10
Actual height/width image (Puush)
Here is some code:
SecondaryMonitorWindow smw = new SecondaryMonitorWindow();
smw.Show();
XAML
Loaded="OnWindowLoaded"
WindowStartupLocation="Manual"
WindowStyle="None"
SnapsToDevicePixels="True"
Height="1280"
Width="1024"
Constructor
public SecondaryMonitorWindow()
{
InitializeComponent();
Instance = this;
}
Event
private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
this.MaximizeToSecondaryMonitor();
}
ExtensionMethod
public static void MaximizeToSecondaryMonitor(this Window window)
{
var secondaryScreen = Windows.Forms.Screen.AllScreens.Where(s => !s.Primary).FirstOrDefault();
if (secondaryScreen != null)
{
if (!window.IsLoaded)
window.WindowStartupLocation = WindowStartupLocation.Manual;
window.Left = secondaryScreen.WorkingArea.Left;
window.Top = secondaryScreen.WorkingArea.Top;
window.Width = secondaryScreen.WorkingArea.Width;
window.Height = secondaryScreen.WorkingArea.Height;
if (window.IsLoaded)
window.WindowState = WindowState.Maximized;
}
}
Try setting the parameter grammatically, this way only you'll be able to achieve the perfect size :
public MainWindow()
{
InitializeComponent();
this.Height = SystemParameters.WorkArea.Height;
this.Width = SystemParameters.WorkArea.Width;
}
however there are bugs around Window 10. if you are using please let me know I'll update the answer.
For Window 10 this post will help. there are no design Border in window 10 so there is some pixel problem. I'm not sure what is Window decoration settings on your OS, but try this.
this.Height = SystemParameters.WorkArea.Height + SystemParameters.FixedFrameHorizontalBorderHeight;
this.Width = SystemParameters.WorkArea.Width + SystemParameters.FixedFrameVerticalBorderWidth;
If there were some other borders are removed try ResizeFrame border size addition too.
I have created 4 buttons dynamically and placed them horizontally using c# win forms.Now i want show a custom tooltip(actually its a borderless form) under each of the 4 buttons on mouse hover event.But how do i position my tooltip form under the buttons??
I have tried the code below but it does not work the desired way.
tooltip.Location = new System.Drawing.Point(b.Left, b.Top);
Where 'tooltip' is tooltip form object & 'b' is the dynamic button.Please advise with some code snippet.
private void B_MouseHover(object sender, EventArgs e)
{
var b = sender as Button;
//MessageBox.Show(Cursor.Position.ToString());
if(b!= null)
{
if (tooltip == null)
{
tooltip = new frmSecQStatToolTipDlg();
}
tooltip.Location = new System.Drawing.Point(b.Left, b.Bottom);
tooltip.data(b.Tag.ToString());
tooltip.Show();
}
}
The way you named it is a bit misleading. As I understand, what you call a tooltip is just a Form. You need to consider 2 things
(1) Form.StartPosition must be set to FormStartPosition.Manual
(2) Form.Location must be in screen coordinates. Note that the Button.Location you are trying to use is in button's parent client coordinates. Control.PointToScreen has to be used for conversion.
In your case, it should be something like this
tooltip.StartPosition = FormStartPosition.Manual;
var topLeft = b.PointToScreen(new Point(0, 0));
tooltip.Location = new Point(topLeft.X, topLeft.Y + b.Height);
When you show the tooltip you can control its location, check show method overloads: https://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.show.aspx
There is a DataGridView in my form. When I click a cell in this DataGridView, it would show a dialog.
Form_Para formPara = new Form_Para();
formPara.ShowDialog();
In general, I hope this dialog just within screen and below this cell.
If showing below this cell will out of screen, then change its position to above the cell.
I know I can get the size and position of dialog and range of screen to calculate new dialog position. However, is there a simpler method?
For example, when I set 'StartPosition' of dialogs as 'CenterParent'.
It will show in the center of parent form and within screen automatically. I don't need to calculate the new position for avoiding out of screen.
Thanks a lot.
Finally, I think setting 'StartPosition' of dialogs as 'CenterParent' is simpler.
And then change only the Location.Y for avoiding to cover current cell.
Point currCellPosTop, currCellBottom;
currCellPosTop = dataGridView1.GetCellDisplayRectangle(dataGridView1.CurrentCell.ColumnIndex, dataGridView1.CurrentCell.RowIndex, true).Location;
currCellPosTop = dataGridView1.PointToScreen(currCellPosTop);
currCellBottom = new Point(currCellPosTop.X, currCellPosTop.Y );
currCellBottom.Y += dataGridView1.CurrentCell.Size.Height;
Form_Para formPara = new Form_Para(currCellPosTop, currCellBottom);
formPara.StartPosition = FormStartPosition.CenterParent;
formPara.ShowDialog();
Dialog Form:
private Point _TriggerControlPosTop;
private Point _TriggerControlPosBottom;
public Form_Para(Point triggerControlPosTop, Point triggerControlPosBottom)
{
_TriggerControlPosTop = triggerControlPosTop;
_TriggerControlPosBottom = triggerControlPosBottom;
InitializeComponent();
}
And visible change event of dialog:
private void Form_Para_VisibleChanged(object sender, EventArgs e)
{
this.Location = new Point(this.Location.X, _TriggerControlPosBottom.Y);
if (_TriggerControlPosBottom.Y + this.Height > Screen.PrimaryScreen.Bounds.Height)
{
this.Location = new Point(this.Location.X, _TriggerControlPosTop.Y - this.Height);
}
}