I have created an MDI application that I want to add a ToolStripContainer to. My first try was to just add one and dock it on Top. Problem I got here was moving ToolStrips inside the container's ToolStripPanels would create an extra Row which was invisible.
Then I saw this question and tried to implement my do-it-yourself MDI interface, using the ToolStripContainer's ContentPanel as where the windows go. This way, I can have my ToolStrips anywhere around the MDI.
The code I have is as follows:
Form f = new Form();
f.TopLevel = false;
tsContainer.ContentPanel.Controls.Add(f);
It all works remarkably well, but I am wondering if this is smart, would I not run into problems later on? Also, if this is possible, why have the entire MDI functionality in Windows?
By setting the TopLevel property to false, the form essentially turns into a UserControl. Do note that you have to explicitly set the Visible property to true, it isn't automatic.
But yes, there certainly are problems and it doesn't behave like an MDI child window at all. The biggest issue should be readily visible, the form can no longer be activated. Very noticeable from its caption bar, it will always be rendered with the colors for a non-active window. It however still works like a caption bar, the user can drag the window and move it around. Which has the clear failure mode that the window is going to get clipped without scrollbars. Not only that, the window can still be maximized and minimized by double-clicking the caption. An MDI child does this very differently. And the visual style for the frame will be wrong in Windows 8.x, looking like a Win7 frame instead, a quirk that has no known workaround.
Realistically, you have to set the FormBorderStyle property to None so it behaves more like a true child window. Or write a bunch of fairly nasty code in the WndProc() override to tame the window, you'll be doomed to re-invent an MDI child, imperfectly.
Which is otherwise a fine way to embed a form. The only remaining quirk after fixing the border is that the form still gets added to the Application.OpenForms collection.
Related
I needed a modal dialog for my app but it appeared there is nothing like that in XAML Metro app. Someone suggested a popup.
I tried and it appeared that underlying UI still responsive.. so a Popup is not modal.
I thought OK may be its purpose is to be a popup in the center of the screen regardless the other layout and it appeared - not. Popup is bound to a layout as everything else. if it is in a grid it will be placed in row 0 and column 0 not in the center..
So may be I missing something. please help to understand. I cant find any use for it different from what can be achieved by using Grid.
what is the purpose of Popup? how it different from any other content controls?
Differences:
You don't have to put it as a child of another control. Though in such scenarios you might get problems traversing the visual tree and focusing on a TextBox won't shift its contents so the virtual keyboard might cover its contents or its adorner contents might lose alignment to adorned controls not on the Popup.
Its content tree is rendered on top of any other content and (I believe) doesn't get clipped by parent control's Clip regions.
You usually need to set its Width and Height manually when first showing or when parent layout (or size) changes, especially in one of the most common scenarios when you set its Width and Height to the Width and Height of the parent (or the window).
That said - modal dialogs are bad UI and should be avoided. You can simply navigate to another page if you would otherwise want to display a dialog or use other approaches. There's (almost) nothing more annoying than displaying a modal dialog over UI that looks otherwise enabled but doesn't respond to input.
I needed a modal dialog for my app but it appeared there is nothing like that in XAML Metro app. Someone suggested a popup.
Since Windows 8.1, there is actually something similar to a modal dialog that you may want to look into:
It's called Flyouts.
Apparently a modal popup with custom content is missing in Windows 8.1. One possible workaround:
use a Popup control (per se not modal)
make the background semi-transparent
stretch it across the entire screen
place the actual popup content inside that container and leave some space around it
Now, the parent page is visible but dimmed, and it cannot be accessed as the Popup is covering it.
I've tried looking many places for an answer to an issue I'm having and so far I've found nothing.
What I currently have is a c# windows form with user controls inside it. Some user controls have other controls inside them. What happens when I change the text in a textbox, is its parent windows will no longer resize like they should when changing the window size. i.e. A horizontal scrollbar will appear even though horizontal scrollbars are disabled in that specific window. Its almost as if changing the text changes the parent window's styling.
In case this is too vague, I have a textbox inside a panel with a docking property set to fill. The panel has a padding of 10 in order to allow the textbox to have some white space for aesthetic purposes. This control resides within a parent control (we'll call it parent 1), which in turn resides within another control as well (we'll call it parent 2). So when I change the textbox's text (at all, even adding a space), will then make parent 2 have a horizontal scrollbar flicker and sometimes even remain when resizing the form window manually.
You should make sure that not only the TextBox in the UserControl is docked to fill but also that the user control itself and its parent (and its parent) are Docked correctly or have anchor set so that they resize with the Form.
Do you execute any special code when the user enters a character? (KeyPressed event etc.). If yes you should try disabling the events temporarily to see if they cause the problem.
If you post a sample of your code it would be easier to help. Without this we can only guess, like I tried...
I found out my issue! When using autoScrollBars and double buffering, it caused the horizontal scrollbar to show when it shouldn't have (at least in my case) when resizing the window. The answer was simple, forget the autoScrollBars, and implement my own vertical scroll bar!
I was actually getting some code to post up on here for you guys to look at, but when looking at it, I decided to forget the autoscroll, and lo and behold it worked!
I'm actually curious as to why that is though. My friend heard that .net has some issues with autoScroll but I didn't think it would be to this degree.
Windows Forms project, working only in designer (i.e. with mouse, before the compilation). I have a Form and 2 Panels in it. panel1 is docked (option - fill) in form1. panel2 is docked (fill) in form1, too. Also, panel2 is in front of panel1 (the latter is hidden behind the former). My problem is - when I undock panel2 and dock it again - it docks in panel1 (panel1 becomes it's parent) and not in form1. How can I change the parent of the panel2?
The only solution I figured out so far is cutting (ctrl+x) panel2, selecting form1 and then pasting (ctrl+v) panel2, but this, for some reason, removes all connections between panel2 controls and the code (for example clicking the button on panel2 doesn't work anymore although the function handling the event is still there).
Any better ideas?
Cutting controls to the clipboard will sever the event handlers, so best to stay away from cut and paste in the designer.
Since you are using the designer, open the Document Outline panel from the View - Other Windows menu in Visual Studio. Use the Arrow buttons to properly set the parent or the docking order of the controls.
The Document Outline window looks something like this:
Seems people liked my commented answer so I am putting it here as an answer
You can undock panel1, then move panel two out of panel1 onto the Form1 background. I have struggled with this as well. that was always my work around, I too found that cutting and pasting it cause a lot of haedaches. It can also be fixed in code, using the designer file
The panel can't change Parent when you change is dock !!!
Or I not really anderstand your problem.
But... if you want change the parent. Just remove the panel of the list of Control of the Panel and add it on the list of Control of the form.
yourPanel.Controls.Remove(yourOtherPanel);
yourForm.Controls.Add(yourOtherPanel);
yourOtherPanel.Dock = .....;
I'm looking for a nice way to render overlays over a native Windows form not owned by myself preferably using a library available for .NET (WinForms, GTK#, ...). Precisely, I'd like to display a few labels or text boxes at a given location on the window.
Device Context & System.Drawing: What I'm currently doing is drawing directly onto the other windows' device context, which causes flickering, as parts of the other application are redrawn in unpredictable intervals. I therefore would have to catch its WM_PAINT event using hook magic, but that's actually not as far down as I'd like to go unless there's no simpler way.
Transparent window overlay with visible child labels: another technique I tried was creating a Windows.Forms.Form with the other windows' size, using TransparencyKey to make only the children visible. This seems pretty hard to get correct, as I don't want the window to be the upper-most one but only exactly one Z-level above the foreign window. The upside would be, that I could add more behaviour to it, as I could actually handle click events, etc.
How would you implement it / deal with the problems in the two techniques described above?
Definitely go with the transparent window approach as that should be simpler to implement. Creating a transparent form is very easy. You already know how to use the TransparenyKey to get the background to not drawn. Also remove the border from the window and remove the min/max/close buttons so you do not have any chrome showing.
Create your window as owned by the window of interest and it will always be on top of the target and act like a modeless dialog. I.e. it is visible only when the owning window is visible.
Thanks for your answer, but I'm still a little confused. How exactly would you set the owner of a window to anything not owned by your own application? I guess that's not even possible when the other application is unmanaged, is it?
Edit:
I now got a little step closer. The example code is in Boo.
[DllImport("user32.dll", SetLastError: true, CharSet: CharSet.Auto)]
public def SetParent(child as IntPtr, parent as IntPtr):
pass
def createAttachedForm(parentHandle as IntPtr):
f = Form()
f.Text = "My overlay"
f.Show()
SetParent(f.Handle, parentHandle)
Application.Run(f)
Now only the TransparencyKey thing doesn't seem to work. Instead the form is completely invisible when the value is set.
Setting the owner of a form can be done with
Form.Show(IWin32Window w)
where w exposes the Handle to the parent window.
I have a form which is a mdicontainer and has a menu strip at the top. I add a child form to my mdi container and when I maximize the child it maximizes over the menustrip. I want to know how to limit the child to maximize below the menustrip. Any help would be appreciated.
Your child form is being maximized in the way that child forms are supposed to be maximized in MDI. It's not really covering the menu strip of the parent form - it's actually merging its own menu strip with that of the parent form.
To make the child form take up only the available child area in the MDI parent (and not merge its menu with the parent's menu), put something like this code in the child form's Resize event:
if (this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
this.Size = this.MdiParent.ClientSize;
this.Location = new Point(0, 0);
}
which will prevent the child window from being actually maximized.
I say "something like this code" because this snippet doesn't work exactly right. The ClientSize property of the parent form gives the overall size of the form, whereas you want to use the size of just the MDI client area. I don't know how to get that, and apparently it's not super-easy. See this question:
Size/Location of Winforms MDI Client Area
You could set the MaximumSize property so that it doesn't fill up the entire container.
I know this an old question, but I just ran into this on an old project I'm working on, so here's an answer for anyone seeing this. Setting the Dock to DockStyle.Fill will give you the behaviour you want.
Just be aware that the window will act/look strange if you try to reposition or resize the window while it has that DockStyle.
To accomplish this, I subscribed to the MDI client window's resize event and if the window had just been maximized, I set its DockStyle to Fill, set the FormBorderStlye to FixedDialog(to prevent resizing), and set the window state to normal to prevent the maximization from occurring.
To prevent the user from moving the window while it is in this "maximized state" I simply overrode the WndProc method and handled when the window was being moved(SC_MOVE) and placed a return to prevent the action from taking effect.