How can I change the BACKGROUND color of the MDI FORM in C#?
I changed it using the background color property but the color is not changed.
What should I do to perform this task?
The actual BackGround colour of the MDI control is based on the colour in the Windows current Theme. You have to physically set the MdiClient control's background inside the WinForm.
// #1
foreach (Control control in this.Controls)
{
// #2
MdiClient client = control as MdiClient;
if (!(client == null))
{
// #3
client.BackColor = GetYourColour();
// 4#
break;
}
}
Edit - Added comments:
We need to loop through the controls in the MdiParent form to find the MdiClient control that gets added when you set the Form to be an MdiParent. Foreach is just a simple iteration of a type through a collection.
We need to find the MdiClient control within the form, so to do this we cast the current control within the loop using the 'as' keyword. Using the 'as' keyword means that if the cast is invalid then the variable being set will be null. Therefore we check to see if 'client' is null. If it is, the current control in the loop is not the MdiClient control. As soon as the variable 'client' is not null, then the control we've got hold of is the MdiClient and we can set its background colour.
Set the backcolour to anything you want. Just replace "GetYourColour()" with whatever colour you want, i.e. Color.White, Color.Blue, Colour.FromArgb(etc)...
As there is only ever 1 MdiClient, there's no point continuing the loop as it's just a waste of processing time. Therefore we call 'break' to exit the loop.
Let me know if you want anything else explaining.
Write this in your load method of your MDI form.
Controls.OfType<MdiClient>().FirstOrDefault().BackColor = Color.Purple;
Related
I am designing a multipage windows form using panels.
I'm displaying a login form and validating the button click, and want to hide the login panel and show the main panel.
However, when I click the button, the login panel disappears alright, but the main panel does not appear. since there is nothing to display, the form window shrinks to just the minimize/maximize/close buttons.
Here's the code for the button:
private void btn_login_Click(object sender, EventArgs e)
{
if (pwdBox.Text == optopwd)
{
MessageBox.Show("Good Morning!!");
loginpanel.Visible = false;
mainpanel.Visible = true;
}
else MessageBox.Show("Incorrect password!");
pwdBox.Text = "";
}
Please let me know what I have missed/misunderstood. Thanks!
Edit:
Screenshots:
Login Screen:
http://img641.imageshack.us/img641/9310/loginscreenj.jpg
Empty window:
http://img163.imageshack.us/img163/1376/emptyx.jpg
The standard mistake is that you accidentally put the mainpanel inside the loginpanel. So when you make loginpanel invisible, the mainpanel can never become visible. This accident is common in the designer, it won't let you put two panels on top of each other. You fix it with View + (Other Windows) + Document Outline. Drag mainpanel and drop it on the form. You'll have to fix the Location property by editing it in the Properties window instead of moving the panel with the mouse.
An entirely different approach is to use a TabControl. Easy in the designer, you just need to hide the tabs at runtime. Code is here.
Or use two UserControls.
Looks like your for is automatically resizing. There are 2 properties on the form responsible for auto size:
AutoSize = True;
AutoSizeMode = GrowAndShrink;
If you have the above settings then your form would shrink just to control panel (buttons) if there's nothing else to display.
Let me know if that helps.
UPDATED
also... does your control "pwdBox" belong to main panel?
Two suggestions:
Try setting the height attribute to 100%
mainpanel.Height = 100%
If that doesn't work, ensure that the page isn't initializing with mainpanel.visible set to false on a postback.
Dim popCus As New PopCustomer()
popCus.StartPosition = FormStartPosition.Manual
popCus.Location = New Point(ctrList.Location)
popCus.Size = New Size(ctrList.Size)
popCus.ShowDialog()
Here ctrList is a UserControl's object and PopCustomer if a Winform.
I want open PopCustomer at same location and same size of ctrList.
The problem there is that the Location of the UserControl is relative to its own parent while for the form it's relative to the screen.
If you change this:
popCus.Location = New Point(ctrList.Location)
to this:
popCus.Location = ctrList.PointToScreen(Point.Empty)
then you'll get the effect you want. You can actually use the same code for a form so that means that you can write a single method with a Control parameter and then use that parameter to set the Location and Size of the new form. You can then call that method and pass either a form or a user control as an argument.
I went and created a tab containing a good amount of controls, most of which are contained within what I'll just call the top-level group box. Now I decide I'd like the text of the top-level group box to be bold, but nothing else. When I set the top-level group box's font to bold, however, all of the controls contained within it become bolded as well, which is what I don't want. I can set each individual control's bold property to false, but it seems like there should be an easier way to do this. Any ideas?
I'm probably missing something obvious, like a group box property that is staring me in the face--and apologize if this turns out to be the case.
Thanks in advance for any help.
You could bypass the problem by placing a label over the caption for the GroupBox, but I wouldn't necessarily recommend this.
A better solution emerges once you understand what is happening and why it is happening. The issue is that a control's font (among other things) is an ambient property, meaning that child controls inherit their parent/container control's properties. So if you set the GroupBox to use a bold font, all of its child controls automatically inherit the bold property by default.
The key there is, of course, by default. Ambient properties only apply if you don't explicitly set the properties of the children to something else. If you don't want the child controls to be bold, select them all and turn off bold. The settings of the parent/container will no longer override the new custom settings.
To make things even easier, you can add a Panel control to your GroupBox, dock/anchor it to fill the entire client area of the GroupBox control, and set it to use a standard, non-bold font. Then, the rules of ambient controls stipulate that the child controls you add to the Panel will not be bold by default. This way, you only have to change the font property of one control as opposed to every child control that you add to the GroupBox.
The reason that this is better than trying to add a Label control over the GroupBox caption is because a GroupBox is designed to contain controls. You can take advantage of the docking and anchoring properties to make sure that everything gets arranged correctly, and you won't have to fight the designer when doing so to make sure that your custom Label correctly covers up the default label drawn by the GroupBox control. Additionally, you won't run into Z order issues or have other redrawing problems rear their ugly heads at runtime when, for example, the Label control gets accidentally hidden behind the GroupBox and no one can see it (and a host of other potential snafus).
I came across this old question when searching for the same, and realised it could be solved in code without adding a separate control just to overcome the ambience issue that Code Gray mentions in his answer.
Add an extensions in a module like so:
<Extension()>
Public Sub UnBold(Of T As Control)(cc As Control.ControlCollection)
For Each c As Control In cc
If Not TypeOf c Is T AndAlso c.GetType.GetProperty("Font") IsNot Nothing Then
Dim RegularFont As New Font(c.Font.FontFamily, c.Font.Size, FontStyle.Regular)
c.Font = RegularFont
ElseIf c.HasChildren Then
UnBold(Of T)(c.Controls)
End If
Next
End Sub
Then unbold all the controls in all the GroupBoxes on a form (including any child GroupBoxes) by using as follows in the form's OnLoad event:
Me.Controls.UnBold(Of GroupBox)()
Or for all controls in a single GroupBox (again, including any child GroupBoxes):
MySpecificGroupBox.UnBold(Of GroupBox)()
With the proviso that if you actually want control within the GroupBox to actually stay emboldened you will have to set that in code after calling the extension.
Consider bypassing the problem by placing a label over the GroupBox's text area and make the label's font bold.
I did it once and even used a CheckBox (for enabling/disabling the whole group). Worked like a charm.
Place all of your controls inside of a ContentControl and reset the font parameters
<GroupBox Header="Group" FontSize="16" FontWeight="Bold">
<ContentControl Margin="0" FontSize="12" FontWeight="Regular">
...
...
...
</ContentControl>
</GroupBox>
Programatically you can do it in order. Assume you want to make font style bold in groupbox but not in child controls. First set the font to a new Font in child controls, in this case you can pass groupbox font property. Then change groupbox font style to bold.
var grpBox = new GroupBox()
{
Text = "",
Width = 780,
Height = 70,
Parent = panel1,
Dock = DockStyle.None,
AutoSize = false,
Visible = true,
Location = new Point(20, grpY)
};
var label = new Label()
{
AutoSize = true,
Parent = grpBox,
Enabled = true,
Name = "label" + btnNum++,
Location = new Point(5, 50),
Text = "",
Font = new Font(grpBox.Font, FontStyle.Regular)
};
var txtBox = new TextBox()
{
Width = 550,
Height = 23,
Location = new Point(65, 20),
Name = "txtBox" + btnNum++,
Parent = grpBox,
Enabled = true,
Tag = label,
Font = new Font(grpBox.Font, FontStyle.Regular)
};
grpBox.Font = new Font(grpBox.Font, FontStyle.Bold);
I have a simple vb.net form a tabpanel strip, and then a seperate form which is loaded for the tabpage.
Here is the code for the button that dynamically creates new tabs:
Dim tempTab As New TabPage
initTab(tempTab)
xt.TabPages.Add(tempTab)
xt.SelectedIndex = xt.TabCount - 1
Here is the code for the "initTab":
Dim tmpTab As New MainTab
tmpTab.Dock = DockStyle.Fill
tmpTab.Panel1.Dock = DockStyle.Fill
tab.Controls.Add(tmpTab)
tab.Text = "Untitled"
tab.Name = " "
I can easily set the focus of any tab by entering following which sets the focus for example to the last tab:
xt.SelectedIndex = xt.TabCount - 1
Now the issue is, how can I set the focus to a textbox on the custom form (in my example labeled "MainTab")? I've tried virtually everything I can google and I can't seem to find any example of how to setfocus or even set/get anything from the MainTab form.
Anyone can help me?
Erm, turning a form into a child control takes some surgery. You have to set its TopLevel property to false, hide the border, make it visible. I don't see it in the code snippet, is MainTab actually a form?
Anyhoo, you cannot use the Focus() method on a control until it is visible. Odds are good that it isn't visible yet in your code snippet. Use the Select() method instead. Say:
tmpTab.TextBox1.Select()
Or just set the TabIndex property of the first control that should get the focus to 0 in the designer.
xt.Controls(xt.SelectedIndex).Controls("TEXTBOXNAME").Focus()
Just make sure that you set the Name property of the textbox you want to have focus (in this case the name would be TEXTBOXNAME) if you do it like this.
Like the title says, I've got a Child form being shown with it's TopLevel property set to False and I am unable to click a MaskedTextBox control that it contains (in order to bring focus to it). I can bring focus to it by using TAB on the keyboard though.
The child form contains other regular TextBox controls and these I can click to focus with no problems, although they also exhibit some odd behavior: for example if I've got a value in the Textbox and I try to drag-click from the end of the string to the beginning, nothing happens. In fact I can't use my mouse to move the cursor inside the TextBox's text at all (although they keyboard arrow keys work).
I'm not too worried about the odd TextBox behavior, but why can't I activate my MaskedTextBox by clicking on it?
Below is the code that shows the form:
Dim newReportForm As New Form
Dim formName As String
Dim FullTypeName As String
Dim FormInstanceType As Type
formName = TreeView1.SelectedNode.Name
FullTypeName = Application.ProductName & "." & formName
FormInstanceType = Type.GetType(FullTypeName, True, True)
newReportForm = CType(Activator.CreateInstance(FormInstanceType), Form)
Try
newReportForm.Top = CType(SplitContainer1.Panel2.Controls(0), Form).Top + 25
newReportForm.Left = CType(SplitContainer1.Panel2.Controls(0), Form).Left + 25
Catch
End Try
newReportForm.TopLevel = False
newReportForm.Parent = SplitContainer1.Panel2
newReportForm.BringToFront()
newReportForm.Show()
I tried your code and got a good repro this time. As I mentioned in my original post, this is indeed a window activation problem. You can see this in Spy++, note the WM_MOUSEACTIVATE messages.
This happens because you display the form with a caption bar. That convinces the Windows window manager that the window can be activated. That doesn't actually work, it is no longer a top-level window. Visible from the caption bar, it never gets drawn with the "window activated" colors.
You will have to remove the caption bar from the form. That's best done by adding this line to your code:
newReportForm.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Which will turn the form into a control that's otherwise indistinguishable from a UserControl. You can still make it distinctive by using this code instead:
newReportForm.ControlBox = False
newReportForm.Text = ""
Either fix solves the mouse click problem.
This is a miserable bug and it took me a long time to find this question. We're doing exactly the same thing as the OP, displaying a Form inside a split container. My workaround was to add an event handler to the MaskedTextBox's Click event:
private void MaskedTextBoxSetFocus(object sender, EventArgs e)
{
var mtb = (MaskedTextBox)sender;
mtb.Focus();
}
This works for the MaskedTextBox but I'm concerned about other odd behavior due to this bug so I will probably set the border style as in the accepted answer.
The text box behavior is a symptom of the same problem. Something is swallowing mouse down notifications. It isn't explained by your code snippet. Forms indeed swallow the mouse click that activates them, but that is a one-time behavior and is turned off by setting its TopLevel property to False.
Not much left. One candidate is the Control.Capture property, turned on at the MouseDown event for a button so that the button can see the MouseUp event, no matter where the mouse moved. That's a one-time effect as well. Watch out for controls that set the Focus in a MouseDown event.
The other is some kind of IMessageFilter code in your form(s) that's eating WM_LBUTTONDOWN messages.