Got some C# forms/controls that can be called up either from a C# control on a Winform in a Winforms MDI app OR the same C# control used by a PowerBuilder MDI app via COM.
I've been using the WinAPI call SetParent to attach forms to the MDI.
It works (or seemed to) in both environments.
It lets the child window have its own WindowState (Normal, Maximised) instead of taking on that of the child windows already open (which was a real pain).
Say the control is called T. Code on control T calls up form D.
Control T is on form X.
Control T is also on form Y.
In .Net all is well, and form D stays within the MDI.
in PB:
Control T is on PB control PX.
Control T is also on PB control PY.
For PX all is well.
For PY, however, there is a problem - form D does not seem to become an MDI child - it can go outside the app and has a taskbar icon. I stress that this is using same objects as the ones that do work. The SetParent is literally the same line of code.
Further research has revealed that SetParent doesn't really work for proper MDI childing - but that's OK(ish) cos we don't need to merge menus etc.
Interestingly, have found that though SetParent seems to 'work', you don't get the handle back if you try GetParent...
Form form = new MyForm();
WindowsMessageHelper.SetParent(form.Handle, MDIParentHandle); //passed down
int parentHandle = WindowsMessageHelper.GetParent(form.Handle);
parentHandle will always be 0....
Is there any way of making form D behave under all circumstances? My own researches have not been promising. I don't really want to go back and rewrite my forms as controls and have PowerBuilder manage them - mainly becasue there can be multiple instances of each form and PowerBuilder would have to handle that (instead of the controller class/base class I've got doing it in the .net app).
Can I stress that there is NO problem within .Net, the problem only shows up in the PowerBuilder app
In the end, we found that the difference was that PB was doing the equivalent of setting .MDIParent for the control PX (the one where calling up form D worked) but not for PY.
Once that was sorted then we were then getting the correct MDIParent handle and all is now well.
Your child needs to be a System.Windows.Forms.Form, and set its MdiParent property to the MDI Patent window (not its Parent).
The container needs to also follow a few rules.
A read through the MDI instructions on MSDN may help further.
Option two: you may not be able to do this with a single control. Instad consider composition of the core implementation in two wrappers. The first wrapper acts as a WinForms MDI child, the second as a COM wrapper for use under whatever GUI framework PowerBuilder works.
If the only problem you haven't solved yet is GetParent doesn't work you might be able to live with it.
EDIT: but asker has more problems.
There are a number of API pokes that have to be each done in turn to make this work. You will have an easier time making this a user control and placing it on a native MDI parent when using it VIA a COM interface or on a .NET MDI child when placing it in a .NET MDI parent.
There are different base window procedures (DefWindowProc vs DefMdiChildProc) that have to be used here and to make this work you end up implementing DefMdiChildProc.
If you used .NET reflector, you might be able to find a way to cause System.Windows.Forms.Form to call DefMdiChildProc for you.
Related
I am creating a windows mobile application that has several different screens. At the bottom of each screen is a menu bar which the user can click on to navigate each screen.
My question is should I use a new form for each screen and clone the menu or use one form and have all the other screens as a control and add them to the main form?
Cheers
I'd vote for controls.
Both mechanisms can achieve the flow you want, and from a fundamental perspective neither is going to really be worse (as in load times, memory consumed, or what have you) so it's largely a personal style decision. Me, I use a UI framework that lends itself heavily to UserControls, so that's what I use.
Generally speaking, when I create an app I have a single parent/host form that has Workspaces where I put my Views. Thos Views are UserControls. Whether I use a tabbed workspace or a desk workspace, they still end up as Controls. The only reason I use more than one full-up Form is if I have a dialog (warnings, inputs, etc) where I will be doing a ShowDialog call.
Per this link, there is no MDI functionality in Windows Mobile.
In our application, we use different forms for each screen.
There are two ways to open up new windows:
formName.ShowDialog(): the new screen will be opened as a child of the other screen. In this case, you won't be able to access your parent form until the child is closed.
formName.Show(): the new screen will NOT be opened as a child of the other screen. Hence, you can access your parent even if the child is not closed.
You can use TabControl in single form with each tab having it's own controls. No need to add controls dynamically. And one single form. The way to achieve this is discussed in more detail in this answer.
Creating Wizards for Windows Forms in C#
I am using WinForms for a C# project and my main form has a simple button that uses ShowDialog(this) on a second form to show it.
Like this:
if (myParameterForm.ShowDialog(this) == DialogResult.OK)
{//stuff happens}
As per my requirements, when the child form is visible, you cannot access the parent form.
For the past year this child form has been the bane of my application as it mysteriously manages to hide behind its parent form from time to time. The reason this is such a big problem is because the software is designed to be used from a touchscreen kiosk, so the user only has access to a touch-screen, but the child form has locked input from any form but itself till it is acknowledged (closed with ok or cancel).
On load the child form uses "this.TopMost = true" just in case, I added this as an effort to fix my problem.
I use no other visualizing functions on the child form, the thread calling the form literally waits there till the form is closed.
Since the user has no access to a keyboard, or anything but a touchscreen I'm miffed as to how the child form manages to hide behind the parent form. I actually have been unable to replicate the behavior, and have only seen it as a result of responding to service requests.
I want to avoid using a timer to continually check if the form is TopMost because it just seems wrong. Should I reconsider? What event could possibly be occurring that is banishing my child form backstage?
I've tried using the search, but as far as I can tell I'm doing this correctly... Assuming that there is some sinister 3rd party application causing occasional hijinks, what is the best way to detect and rectify this situation automatically without throwing in a periodic check? I am not sure that the VisibleChanged event is what I'm looking for.
I can reproduce the behavior you are describing by minimizing the child window when it is displayed using ShowDialog. Is it possible that something is minimizing the child window? You could try disabling the control box for the child window to see if that helps. I would probably also set ShowInTaskbar to false for the child window (for usability reasons).
I would probably just implement the child form as a dynamically loaded user control instead. When you need it just load it on top of everything else. This way your main window is always in focus and the content you want to display is on top. this will obviously be a bit of work, but judging by the fact that this has been a problem for a year, you probably don't mind the work if it fixes the problem. There may be more intricacies that you'll have to deal with(i.e. having to make all other controls invisible until the child is done, etc.) but I think this is the easiest and most reliable fix.
In my experience TopMost windows and modal dialogs never behave very well ... as you can lock yourself out if a TopMost window happen to cover the modal dialog control. Are you applying TopMost to the main window anywhere in your code?
I have a c# .net 2.0 winforms application which consists basically of one form A.
I am building another form B with a tabcontrol on it.
From the form B, I would like to be able to create one or more instances of this application.
Each form A I would like to be placed on tabpages on form B's tabcontrol.
Each instance is a different process that is running on a separated folder.
How could I achieve this?
Another way to put this is, how I could dock a form from another running instance into the current application instance's form.
Look at this codeproject article. It is what you are searching for.
I think the best way to do this would be to have to versions of your app. One is the executable and the other is a component that you could add dynamically. I have an app that I do this with tool controls. Each tool represents a separate set of functionality that can be added to a workspace (tab) depending on the user's need for it. For example, I have a tool for logging particular items that's called "logger" and a user can create a new instance of it which essentially adds it as a new tab in the main window. Just a thought. I think docking two running instances of the same application would have to be handled by Windows through the app docking interface.
If you don't control the source code for both of these applications then I don't think you can accomplish your objective.
If you DO control the source code, then I would recommend that you isolate the Form A functionality in a usercontrol in a separate library and reference this from the form in AppA and from the tab control in App B
This is my first question.
I start to computer graphics programming with opengl via Tao Framework.
Everything going well but today I tried to work with MDI forms. My application crashed. It is a bit difficult to describe my problem. So I captured 5 images and I added my questions on them. I could not add this images because of my reputation. This is my homepage link. Thank you.
Please read all details
http://www.emrekiyak.com/tao.html
I believe you are setting the MyParentForm property as the form itself, which creates a circular reference.
You could parametrize the child form Constructor to carry a reference to the parent, which will allow you to properly set it.
public ChildForm(Form parentForm)
{
//Other code
MdiParent = parentForm;
Show();
}
No need to keep it as a property elsewhere.
I'm currently designing an MDI application (a custom CRM) in .net 4.0 and i'm starting to dislike the whole interface simply because there's no real way to track which windows are open or closed and it'll probably lead to a very confusing interface.
What is the best way to avoid this?
- Should i implement a taskbar to track every open mdi child?
- Should i use dialogs instead to prevent multi-tasking?
- Is there any way to change the size of a minimized window on a mdi container (why are they so small, you can't even read the full form title that way...)
Sorry for so many questions, thanks in advance.
MDI has its uses, but as you've found can easily lead to a cluttered, hard-to-use interface. The current in-vogue way of dealing with this is to add a tab control (as in any web browser, or most text editors/IDEs) to allow switching between open views. This is close to a task bar I guess.
Other options are controls like the Outlook bar (the big view chooser down the left-hand side of Outlook) or possibly just a simple list box with the currently open views.
Alternatively, consider how often you really want multiple windows available and whether most of them are "tool windows". If so, perhaps look at using docking windows for these tool windows, and a Single Document interface for the rest of the app. All depends on what you're actually doing!
The MDI windowing management already has the built-in to track open windows by way of the menu. The ToolStripMenu has an MdiWindowListItem that you can set to a reference of the menu item that will contain the list of open windows. If the menu is attached to the MDI parent window, child windows automatically populate the menu item.
One of the objectives of MDI is to allow multitasking. If that's not what you want, use a different design.
As far as changing the size of the minimized windows, apparently it's not possible using the standard Windows interface. See more info here: Is it possible to change size of minimized window in MDI C# Winforms. But you could remove the standard Minimize button, add your own, and do what you want with the windows in a Normal state.