Adding Control to MDI Client
please help me i have a problem i wanna know how add a control like button or panel to MDI Client please help 开发者_如何学Gome thanks
If i understand you correctly, you can create the forms in design view as per usual and then load these forms in the MDI Parent as children.
// Create a new instance of the child form.
Form childForm = new Form1(); //where form1 is the form you designed
// Make it a child of this MDI form before showing it.
childForm.MdiParent = this;
childForm.Text = "Window " + childFormNumber++;
childForm.Show();
Have a look at Using MDI.
I'm assuming that you're trying to do the same as me. I've found out how to put the toolbar and statusbar in the mdi client area but I can't find anything about other controls.
Here's how I've done the statusbar;
In the WM_CREATE message of the main window callback, create the statusbar using CreateWindowEx. The array statwidths[] holds the position of each statusbar window which for some reason is measured from the right-hand side, or end, of each window:
HWND hStatus;
int statwidths[] = { 50, 100, -1 };
hStatus = CreateWindowEx(
0, STATUSCLASSNAME,
NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
0,0,0,0,
hWnd,
(HMENU)IDC_MAIN_STATUS,
GetModuleHandle(NULL),
NULL);
if (hStatus == NULL)
MessageBox(hWnd, L"Could not create statusbar.", L"Error", MB_OK | MB_ICONERROR);
SendMessage(hStatus, SB_SETPARTS, sizeof(statwidths) / sizeof(int), (LPARAM)statwidths);
SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)L"Win32");
SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)L"MDI");
Then in WM_SIZE:
HWND hStatusbar;
RECT rcStatusbar;
int iStatusbarHeight;
hStatusbar = GetDlgItem(hWnd, IDC_MAIN_STATUS);
SendMessage(hStatusbar, WM_SIZE, 0, 0);
GetWindowRect(hStatusbar, &rcStatusbar);
iStatusbarHeight = rcStatusbar.bottom - rcStatusbar.top;
For the toolbar do exactly the same with a bit of code to populate the toolbar with buttons. In WM_CREATE:
HWND hToolbar;
TBBUTTON tbb[3];
TBADDBITMAP tbab;
hToolbar = CreateWindowEx(
0,TOOLBARCLASSNAME,
NULL,
WS_CHILD | WS_VISIBLE,
0,0,0,0,
hWnd,
(HMENU)IDC_MAIN_TOOL,
GetModuleHandle(NULL),
NULL);
if (hToolbar == NULL)
MessageBox(hWnd, L"Could not create tool bar.", L"Error", MB_OK | MB_ICONERROR);
// Send the TB_BUTTONSTRUCTSIZE message, which is required for
// backward compatibility.
SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
tbab.hInst = HINST_COMMCTRL;
tbab.nID = IDB_STD_SMALL_COLOR;
SendMessage(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
ZeroMemory(tbb, sizeof(tbb));
tbb[0].iBitmap = STD_FILENEW;
tbb[0].fsState = TBSTATE_ENABLED;
tbb[0].fsStyle = TBSTYLE_BUTTON;
tbb[0].idCommand = ID_FILE_NEW;
tbb[1].iBitmap = STD_FILEOPEN;
tbb[1].fsState = TBSTATE_ENABLED;
tbb[1].fsStyle = TBSTYLE_BUTTON;
tbb[1].idCommand = ID_FILE_OPEN;
tbb[2].iBitmap = STD_FILESAVE;
tbb[2].fsState = TBSTATE_ENABLED;
tbb[2].fsStyle = TBSTYLE_BUTTON;
tbb[2].idCommand = ID_FILE_SAVEAS;
SendMessage(hToolbar, TB_ADDBUTTONS, sizeof(tbb) / sizeof(TBBUTTON), (LPARAM)&tbb);
and then in WM_SIZE do exactly the same as for the statusbar;
HWND hToolbar;
RECT rcToolbar;
int iToolbarHeight;
hToolbar = GetDlgItem(hWnd, IDC_MAIN_TOOL);
SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
GetWindowRect(hToolbar, &rcToolbar);
iToolbarHeight = rcToolbar.bottom - rcToolbar.top;
Finally to resize the client area of the main window;
HWND hMDI;
int iMDIHeight;
RECT rcClient;
GetClientRect(hWnd, &rcClient);
iMDIHeight = rcClient.bottom - iToolbarHeight - iStatusbarHeight;
hMDI = GetDlgItem(hWnd, IDC_MAIN_MDI);
SetWindowPos(hMDI, NULL, 0, iToolbarHeight, rcClient.right, iMDIHeight, SWP_NOZORDER);
I hope this is what you're after. If you find out how to put an edit control on top of the statusbar, like the output window in Visual Studio, let me know how you did it.
As far as I know, you can only add windows (read: forms) to an MDI window. A control must always have a parent window in which it exists. astander's example is technically correct: if you want to "add a button or panel to an MDI client" then you will need to host that button or panel inside a form, before adding that form to the MDI client.
This is not the usual recommendation, but for you you write your simple MDI Kind of application. I have one sample. Add a panel (docStyle=fill)[name it 'panel_Container'] to your main form. Create Child Forms and call this method.
void MakeMDIChild_Simplest(Type thisForm)
{
FlowLayoutPanel panel_Bottom_flowLayout = null;
if (null == Controls["panel_Bottom_flowLayout"])
{
panel_Bottom_flowLayout = new FlowLayoutPanel()
{
AutoSize = true,
BackColor = System.Drawing.Color.Transparent,
Dock = System.Windows.Forms.DockStyle.Bottom,
Location = new System.Drawing.Point(0, 332),
Name = "panel_Bottom_flowLayout",
Size = new System.Drawing.Size(479, 0),
TabIndex = 1
};
Controls.Add(panel_Bottom_flowLayout);
}
else
{
panel_Bottom_flowLayout = (FlowLayoutPanel)Controls["panel_Bottom_flowLayout"];
}
Form frm = (Form)Activator.CreateInstance(thisForm);
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_CHILD = 0x40000000;
uint style = GetWindowLong(frm.Handle, GWL_STYLE);
style = (style & ~(WS_POPUP)) | WS_CHILD;
SetWindowLong(frm.Handle, GWL_STYLE, style);
SetParent(frm.Handle, panel_Container.Handle);
int captionHeight = frm.Height - frm.ClientSize.Height;
frm.Location = new Point(panel_Container.Width / 2 - frm.Width / 2, panel_Container.Height / 2 - frm.Height / 2 + captionHeight);
frm.Show();
frm.MouseDown += (sender, mea) =>
{
const int WM_NCLBUTTONDOWN = 0xA1;
ReleaseCapture();
PostMessage(frm.Handle, WM_NCLBUTTONDOWN, new IntPtr(2), IntPtr.Zero);
};
frm.Resize += (Sendder, rea) =>
{
if (frm.WindowState == FormWindowState.Minimized)
{
frm.SendToBack();
Label lbl =
new Label()
{
AutoSize = true,
Text = frm.Text,
BackColor = Color.LightCoral,
BorderStyle = BorderStyle.FixedSingle,
Padding = new System.Windows.Forms.Padding(5),
Margin = new System.Windows.Forms.Padding(2)
};
lbl.Click += (sender, cea) =>
{
frm.WindowState = FormWindowState.Normal;
frm.Location = lbl.Location;
frm.BringToFront();
panel_Bottom_flowLayout.Controls.Remove(lbl);
};
panel_Bottom_flowLayout.Controls.Add(lbl);
}
};
}
Usage:
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
MakeMDIChild_Simplest(typeof(ChildForm));
}
You will also have to add the following to your MainForm Class
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
And thats it
精彩评论