Cascade windows in a non MDI C++/CLI application - c#

I would like to implement a cascade layout in my application.
I cannot use FormStartPosition.WindowsDefaultLocation as per the below answer
C# Cascading forms without mdi parent?
Even though cascading is achieved using this approach, each time windows are coming at different different locations.
I want to display windows at fixed positions preferably starting from CentreScreen and going towards the bottomroght direction
Extra Info: This is a tray icon application and each form is displayed Modally by calling ShowDialog().
please help!!
Thanks & Regards,
Rohini

If you are going to show the windows modally Form.ShowDialog() I'm not really sure a cascade layout is really necessary. Just set StartPosition = FormStartPosition.CenterParent and you should be good to go.
If you really insist on doing a manual cascade then set Form.StartPosition to FormStartPosition.Manual. This enables you to define the starting point of the Form through the Form.Location property.
Typically, you should do this overriding Form.OnLoad(EventArgs e) and working your starting position based on the position of Form.Owner
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (this.Owner != null)
{
this.Location = .... // offset this.Owner.Location
}
}
Note that Form.Location is in global screen coordinates though it doesn't make a difference as you are working with offsets.

Related

Showing Winforms on dual-screen setup

I have a winforms application in C#, with about 10 forms to navigate through.
On all of them, I have set StartPosition as CenterScreen but I use a laptop with a second screen plugged in.
Now the application starts randomly on one of my screens. Also even if the app is on one screen, MessageBoxes pop up on the second one. How can I set the application to always start at the main screen, the one set as "1" in Windows.
I also want to bind the application to the screen it is showing at so that MessageBoxes would appear on the same screen as the app. Another thing I would like to have is so that new forms would show on the same position as previous forms, not going back to the screen where the application started.
What should I use to control the positions of the forms?
I tried changing StartPosition to CenterParent, but that doesn't seem to change anything.
Try this out on starting page ( first form):
private void MyForm_Load(object sender, EventArgs e)
{
this.Location = Screen.AllScreens[0].WorkingArea.Location;
this.StartPosition = FormStartPosition.CenterScreen;
}
More information here : Showing a Windows form on a secondary monitor?
This question is about showing program on secondary screen. just change 1 index to 0 on arrays if you used answers of that.
Edit:
Just for emphasize Bryce Wagner comment for other people read this question :
If you're calling it from a form or user control, you'll want to call MessageBox.Show(this, "Message") instead.
Combining all answers here and in similar questions, the working solution for showing app on primary screen is this:
private void FormLogin_Load(object sender, EventArgs e)
{
this.Location = Screen.AllScreens[0].WorkingArea.Location;
ReallyCenterToScreen();
}
protected void ReallyCenterToScreen()
{
Screen screen = Screen.FromControl(this);
Rectangle workingArea = screen.WorkingArea;
this.Location = new Point()
{
X = Math.Max(workingArea.X, workingArea.X + (workingArea.Width - this.Width) / 2),
Y = Math.Max(workingArea.Y, workingArea.Y + (workingArea.Height - this.Height) / 2)
};
}
And to keep the MessageBoxes on the center screen is this:
MessageBox.Show(this, "Message")
Sources are the comment of #Bryce Wagner to my question, the answer from #Mohamad Shahrestani and from this question answer by #Sarsur.A
I have a laptop with a second screen. Windows 10 is in "Extend" mode. None of the code examples helped with my dialog ignoring the manual location.
It turns out that NVidia has some helpful options in their driver. One will decide for you where you want your form or your dialog. If your code just doesn't seem to behave, try the "nView Desktop Manager" -> "Windows Manager" -> "Dialog box repositioning" and Open windows on settings.

How to properly resize app to visible bounds on UWP? (VisibleBoundsMode doesn't seem to work)

I have two UWP apps and after testing them out with Continuum I noticed the app bar of the OS (the bar with the Start button) at the bottom of the screen (it can be at each of the 4 edges of the screen, of course) was covering part of my app.
Now, I'm already using ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseVisible) before calling Window.Current.Activate(), but that doesn't seem to solve the issue.
1) Why is it that setting the DesiredBoundsMode property doesn't seem to work here? Shouldn't that automatically resize the window
content to the visible bounds (ie. excluding system overlays like the
navigation bar or the app bar)?
The workaround I'm using for now on Windows 10 Mobile devices is to subscribe to the VisibleBoundsChanged event and then manually adjust the margins of my Window.Current.Content item to make sure it doesn't show anything behind covered areas of the screen.
Basically, I use the Window.Current.Bounds property and the ApplicationView.VisibleBounds property to calculate the occluded areas on the different edges of the app window, and increase the margins from there.
2) Is there a proper/better way to do this?
I mean, I'm quite sure there's another method that should be used to avoid this issue (considering there are tons of different situations like Continuum, navigation bar etc... that I don't think are supposed to be manually handled one by one).
Thank you for your help!
Use the subscription to the event VisibleBoundsChanged. This is the best solution that I found.
var curr = ApplicationView.GetForCurrentView();
if (curr.IsFullScreenMode == true)
{
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.FullScreen;
curr.FullScreenSystemOverlayMode = FullScreenSystemOverlayMode.Minimal;
}
else
{
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.Auto;
curr.FullScreenSystemOverlayMode = FullScreenSystemOverlayMode.Standard;
}

fullscreen is not always functioning

Good day, I have a winform that can set full screen. But sometimes it's not. It is sometimes 3/4 of the screen but sometimes it is full screen. Below is my Code. Anybody knows why it's not always fullscreen....?
private void Form1_Load(object sender, EventArgs e)
{
FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
Width = Screen.PrimaryScreen.WorkingArea.Width;
Height = Screen.PrimaryScreen.WorkingArea.Height;
}
When I run it in my pc. Its fine. But when it is in the production. I saw it did not go well. But sometimes it is ok.
By the way, I want my taskbar to be seen. If I set FormWindowState.Maximized, my taskbar would not be seen.
Thank you.
The issue is that the WorkingArea is not the same with Full Screen. WorkingArea is relative, not the common way of forcing full screen.
There are a couple of ways to attempt to force the full screen.
One of the most popular way to force fill is by setting WindowsState to Maximized (also here and here - quite popular) combined with setting TopMost property to true.
private void Form1_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
Alternatively, less popularly, you could also use Screen.Bounds (but may not be absolute too, try to put additional TopMost = true)
And finally, you could also using WorkingArea with conditional statement. To debug and see what is the WorkingArea size in you production PC, you could use GetWorkingArea method. This way, you can debug what is the working area in the production PC and if it is not full screen comparing to the size of the PC, you could force is to full screen. Not so efficient though...
Here is more explanation on working area vs screen area to help you making decisions.
Edit: with bar to be seen, what I could think of as another way to do this is by Get Screen Size. See:
How can I get the active screen dimensions?
Then you should limit the maximum dimension of your form (y/x-axis) such that you have room for your bar - that is, to be little less than the screen size in one of the axis. Then, on form load or other related events, you could control the position of your WinForm such that you won't block your bar.
See StartupPosition property:
C# window positioning
Screen.PrimaryScreen.WorkingArea only gets the screen's working area.
I think you need to change it to
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
You just need to set the WindowState to Maximized at run-time:
WindowState = FormWindowState.Maximized;
Or at design-time, using the WindowState property of the form.

Overlaying a top-level window on top of another

In the software products I'm currently working on, we have several 3D View controls. Appeared the need to have overlay information on top of these 3D Views. I won't go into too much background details, because it is not the point, but here are the constraints we face :
we must use two different 3D View controls
we don't have the source code for them
they are embedded in Windows Forms controls, and all our own GUIs around these controls are in Windows Forms
we use .NET Framework 3.5SP1 and Windows 7
We want to be able to display various overlay informations and controls on top of these 3D views, because we usually demo our products by showing full screen 3D views on big screens, and not show our GUIs, which have the necessary information and controls.
Back in the days we used only one type of 3D view, I managed, via various hacks involving reflection, to hook my own overlay window system written in DirectX (based on WorldWind .NET overlay widgets, the 3D view was indeed based on WorldWind at the time). The next version of the 3D View product made huge changes to the rendering core code and of course made these hacks incompatible (yeah, I had it coming, I know :-)). Moreover, we are now using, because of different needs in other products, another type of 3D View, closed source as well.
I emphasize the fact that we don't have the source code for them because we can't have access to the rendering loop and therefore cannot hook a windowing system made for 3D Engines, such as CEGUI (search for it yourself, I'm not allowed to post much hyperlinks yet, sorry).
Consequently, I had the following idea : since our 3D Views are embedded in winforms controls, why don't we code our overlay controls in plain winforms, and overlay it on top of the 3D views? The advantages of this solution are huge :
this would be compatible with both 3D Views, enabling us to reuse overlays across engines, if needed
we would be able to reuse custom controls or forms we already developed for the rest of the GUI. Indeed, it is a pretty big project, and we are beginning to have quite a library of such controls.
The only slight (!) problem is that we want to be able to manage overlay transluency, like I did with my former system in DirectX. We can't afford fully opaque overlays, because it would clutter the view too much. Imagine something like a barely visible overlay, becoming more opaque when the mouse is hovering over it for example.
Windows offer the possibility to have child windows inside other windows or controls (Win32 API doesn't really make a difference between windows and controls, this is pretty much a MFC/WinForms abstraction as I understood it), but since it is not top-level windows, we cannot adjust the transluency of these, so this is not something we can use. I saw here, that this is however possible on Windows 8, but switching to windows 8 is not possible anytime soon, because our software is deployed on quite a few machines, running 7.
So I started an intense googling session on how could I work around such a problem. It appears I must "enslave" top level windows to my 3D View controls. I already tried out something like that directly in winforms, having a form owned (not parented, there is a clear distinction, read about it in the previously linked MS page) by a control, and "following" its movements on screen. As expected, it kind of worked, but the issues are difficult to overcome. The most important is a clipping issue. If the parent form of the owner control changes its size, the overlay form is still shown in full. In my sample, I have a simple form with a menu, and a black panel containing a calendar (to show clipping differences between child controls and owned ones). I "enslaved" a borderless form containing a property grid to the black panel. It successfully follows the forms movements, but if I shrink the main form, I get this :
Clipping issue screenshot
Note how the calendar is clipped correctly (child window), and the overlay is not (owned window). I also get weird effects when minimizing/restoring the main form. Indeed, my overlay disappears when minimizing, but when restoring, it just "spawns" while the restoring animation of the main form is occuring. But this is less of an issue, and I guess can be worked around by handling proper events (but which ones?).
From what I understood, I must handle at least some of the clipping myself, using win32 API calls and hooks. I already begun to document myself, but it is quite complicated stuff. The Win32 API being a real mess, and myself being a former Unix developer introduced to Windows programming via the great .NET framework, I don't have any real experience in Win32, and therefore don't really know where to begin, and how to make myself a path in this jungle...
So if a winapi guru is passing by, or if someone has some other idea to achieve my goals given the constraints above, I'll be glad to read about it :-)
Thanks in advance, and apologies for being such a stackoverflow "leecher" by subscribing only to ask a question, but I don't have no direct internet access on my workstation (yeah, for real, I have to go to a specific computer for this), so participating in this great community is not that easy for me.
Finally, here is my sample code (designer code available if you ask) :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Point _myLoc;
private void formToolStripMenuItem_Click(object sender, EventArgs e)
{
var ctrl = new PropertyGrid();
var obj = this.panel1;
ctrl.SelectedObject = obj;
var form = new Form();
ctrl.Dock = DockStyle.Fill;
form.Controls.Add(ctrl);
form.Opacity = 0.7;
var rect = obj.RectangleToScreen(obj.DisplayRectangle);
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(rect.Left + 10, rect.Top + 10);
var parentForm = this;
_myLoc = parentForm.Location;
form.FormBorderStyle = FormBorderStyle.None;
parentForm.LocationChanged += (s, ee) => {
int deltaX = parentForm.Location.X - _myLoc.X;
int deltaY = parentForm.Location.Y - _myLoc.Y;
var loc = form.Location;
form.Location = new Point(loc.X + deltaX, loc.Y + deltaY);
_myLoc = parentForm.Location;
};
form.Show(this.panel1);
}
}
Clipping can be easily implemented using Region property. Each window can have an associated Region object, which defines window rendering constraints:
static void ManualClipping(Control clipRegionSource, Form formToClip)
{
var rect = clipRegionSource.DisplayRectangle;
rect = clipRegionSource.RectangleToScreen(rect);
rect = formToClip.RectangleToClient(rect);
rect = Rectangle.Intersect(rect, formToClip.ClientRectangle);
if(rect == formToClip.ClientRectangle)
{
formToClip.Region = null;
}
else
{
formToClip.Region = new Region(rect);
}
}
usage:
/* ... */
parentForm.SizeChanged += (s, ee) => ManualClipping(panel1, form);
form.Show(this.panel1);

How to dock a windows form in C#?

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

Categories