I'd like to bold the text for a tab page under certain conditions (not, necessarily, GotFocus). Is it true the only 'er easiest way to do this is by overriding the DrawItem event for the tab control?
http://www.vbforums.com/showthread.php?t=355093
It seems like there should be an easier way.
Like ...
tabControl.TabPages(index).Font = New Font(Me.Font, FontStyle.Bold)
That doesn't work, obviously.
When you set the Font property on a TabPage, you are setting the default font for all controls on that tab page. You are not setting it for the header, however.
When you execute the following code:
tabControl.TabPages(index).Font = New Font(Me.Font, FontStyle.Bold)
Any controls on that page will now be bold by default, which is not (I'm assuming) what you want.
The header's font (that is, the tab itself) is controlled by the TabControl's Font property. If you were to change your code to:
tabControl.Font = New Font(Me.Font, FontStyle.Bold)
You will see that in action. However, it changes the font for all the tabs on display, which is also not, I'm assuming, what you want.
So, using the default WinForms tab control, you are (I believe) limited to the technique in the link you've posted. Alternatively, you can begin looking at 3rd-party controls, such as those discussed in these questions on StackOverflow.
An easy way to give tab controls different labels depending on a field value is to change the caption itself:
For example:
Private Sub Form_Current()
If IsNull(Me.Subform.Form.Field_Name) Then
Me.Tab_Name.Caption = "Tab One"
Else
Me.Tab_Name.Caption = "Tab One +++"
End If
End Sub
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Font BoldFont = new Font(tabControl1.Font, FontStyle.Bold);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, BoldFont, Brushes.Black, e.Bounds);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
}
Related
I have a form that i set it's Opacity as 50% like this:
this.Opacity = 0.5D; <--this==Form
My problem is that everything that on the form is with an Opacity of 50%
I have two buttons on the form and I want them without Opacity.
I know that this.Opacity included all Controls and for some reason the graphics too
My question is, How to Exclude the Opacity of the controls?
Example Image:
Thanks!
Since Control doesn't have Opacity property and plus that, most of the controls doesn't support transparent colors, then a working solution can be this:
Create a Form called MainForm and place all the controls you're going to be excluded.
1.1 Set both of BackColor and TransparencyKey properties of MainForm to the same color, e.g Color.Red
Create another form named TransparentForm and place all controls that must become transparent. Set ShowInTaskbar property to False.
In the MainForm Load event show the TransparentForm and send it to back.
private void MainForm_Load(object sender, EventArgs e)
{
TransparentForm form = new TransparentForm();
form.Opacity = 0.5D;
form.Show();
form.SendToBack();
}
The position of controls in both form must be such that, when combined, it shows the proper user interface.
Crate a C# project and add 3 forms named
MAIN
BACKGOUND
Child
and add the following code for "MAIN" form load event;
private void MAIN_Load(object sender, EventArgs e)
{
Child frm1 = new Child();
BACKGOUND frm2 = new BACKGOUND();
frm2 .WindowState = System.Windows.Forms.FormWindowState.Maximized;
frm2.Opacity = 0.5;
frm2.Show();
frm1.ShowDialog();
frm2.Close();
}
How can I toggle the checkbox of an item in a CheckedListbox if CheckOnClick is True, but SelectionMode is None..?
If I set SelectionMode to One it works as expected, but I would like to prevent items in the list from being selected. The only purpose of the CheckedListbox is to use the checkboxes; having items selected is not desired.
I tried a bit of code with the various Click and Mouse events, but none of them seem to report the item in the list that was clicked. If I could determine that, it would be a simple matter to toggle the checkbox of the clicked item.
The MouseClick event will tell you when the control was clicked and where. Determine whether the click was on an item and which one, then toggle it:
Private Sub CheckedListBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles CheckedListBox1.MouseClick
Dim clickedIndex = CheckedListBox1.IndexFromPoint(e.X, e.Y)
If clickedIndex <> ListBox.NoMatches Then
CheckedListBox1.SetItemChecked(clickedIndex, Not CheckedListBox1.GetItemChecked(clickedIndex))
End If
End Sub
After a little testing, I would say that you need to consider “how” you want to achieve the non-selection mode you describe. As you have noted, if you set the CheckedListBoxes SelectionMode to None… then basically the check boxes become unusable.
The user cannot check or un-check any check box, as you already know… and this is why you want “your” code to change the check boxes checked state. So, you have now inherited the job of changing the check boxes check state because you set its “SelectionMode” to “None" … ? …
In addition, when the selection mode is set to “None” … then many “typical” properties of the CheckedListBox will lose functionality and become useless. Example, the checked list boxes SelectedItem property will always be null and its SelectedIndex property will most likely always be -1. Meaning, most “selection” type events will need to find what item was clicked by using the mouse location as shown in another answer.
The main point here is that when you decided to set the checked list boxes selection mode to “None”, then you basically open the door for more coding/responsibility on your part as far as “managing” the checked list box. I am just saying that the out-of-the-box .Net CheckedListBox is not feature rich and is a basic control. I am guessing there “may” be a third-party CheckedListBox Control that may have this “non-selected” functionality built-in.
So… I suggest another approach… however… it also has some drawbacks… basically you have to create a new Class MyCheckedListBox type “Control” that inherits from the CheckedListBox and then override its draw method to paint the cell the way we want.
I tend to avoid creating new controls. However, this will allow us to “keep” the CheckedListBoxes “selection functionality” by keeping its SelectionMode set to One. In addition to removing the job of “your” code having to manage each check box’s check state… we can also use all the checked list boxes “selection” events and use them as we typically would using the list boxes “selection” properties.
Below is a crude example of how to override the CheckedListBox’s Draw method to keep the “selected” items back color to the same color of the non-selected items.
class CheckedListBox_NoSelect : CheckedListBox {
protected override void OnDrawItem(DrawItemEventArgs e) {
DrawItemEventArgs new_e_Args = new DrawItemEventArgs
(e.Graphics,
e.Font,
new Rectangle(e.Bounds.Location, e.Bounds.Size),
e.Index,
(e.State & DrawItemState.Focus) == DrawItemState.Focus ? DrawItemState.Focus : DrawItemState.None,
this.ForeColor,
this.BackColor);
base.OnDrawItem(new_e_Args);
}
}
The code above is a simplified version of this SO question… How change the color of SelectedItem in CheckedListBox in WindowsForms? …
As I started, you will have to decide which approach you need. I may tend to go the route of #user18387401‘s answer … simply to avoid creating a new User Control. However, if you want this functionality for all the CheckedListBoxes, then creating the control may be a better approach.
Below is a full example of what is described above.
The CheckedListBox on the left is a regular CheckedListBox and uses the approach from user18387401‘s answer. The CheckedListBox on the right is our new control class CheckedListBox_NoSelect above.
For each control, the SelectedIndexChanged event is wired up to demonstrate that the checked list box on the left with its SelectionMode set to None will always have its SelectedItem set to null and its SelectedIndex will always be set to -1. However, it is not difficult to figure out “which” item was selected using user18387401‘s approach. This index is also displayed in its SelectedIndexChanged event.
private void Form1_Load(object sender, EventArgs e) {
checkedListBox1.SelectionMode = SelectionMode.None;
checkedListBox1.Items.Add("Item 1");
checkedListBox1.Items.Add("Item 2");
checkedListBox1.Items.Add("Item 3");
checkedListBox1.Items.Add("Item 4");
checkedListBox1.Items.Add("Item 5");
checkedListBox1.CheckOnClick = true;
// Leave default selection mode to "One"
checkedListBox_NoSelect1.Items.Add("Item 1");
checkedListBox_NoSelect1.Items.Add("Item 2");
checkedListBox_NoSelect1.Items.Add("Item 3");
checkedListBox_NoSelect1.Items.Add("Item 4");
checkedListBox_NoSelect1.Items.Add("Item 5");
checkedListBox_NoSelect1.CheckOnClick = true;
}
private void checkedListBox1_MouseClick(object sender, MouseEventArgs e) {
int clickedIndex = checkedListBox1.IndexFromPoint(e.X, e.Y);
if (clickedIndex != -1) {
checkedListBox1.SetItemChecked(clickedIndex, !checkedListBox1.GetItemChecked(clickedIndex));
Debug.WriteLine("LEFT: MouseClick Selected Index: " + clickedIndex);
}
}
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e) {
Debug.WriteLine(" LEFT -> Item: " + (checkedListBox1.SelectedItem == null ? "Null" : checkedListBox1.SelectedItem));
Debug.WriteLine(" LEFT -> Index: " + checkedListBox1.SelectedIndex);
}
private void checkedListBox_NoSelect1_SelectedIndexChanged(object sender, EventArgs e) {
Debug.WriteLine("RIGHT -> Item: " + (checkedListBox_NoSelect1.SelectedItem == null ? "Null" : checkedListBox_NoSelect1.SelectedItem));
Debug.WriteLine("RIGHT -> Index: " + checkedListBox_NoSelect1.SelectedIndex);
}
I hope this makes sense and helps. Sorry that I did this in C#. If you can not convert the code to a VB version, then let me know and I will add a VB version.
In my C# Form I have a Label that displays a download percentage in the download event:
this.lblprg.Text = overallpercent.ToString("#0") + "%";
The Label control's BackColor property is set to be transparent and I want it to be displayed over a PictureBox. But that doesn't appear to work correctly, I see a gray background, it doesn't look transparent on top of the picture box. How can I fix this?
The Label control supports transparency well. It is just that the designer won't let you place the label correctly. The PictureBox control is not a container control so the Form becomes the parent of the label. So you see the form's background.
It is easy to fix by adding a bit of code to the form constructor. You'll need to change the label's Parent property and recalculate it's Location since it is now relative to the picture box instead of the form. Like this:
public Form1() {
InitializeComponent();
var pos = label1.Parent.PointToScreen(label1.Location);
pos = pictureBox1.PointToClient(pos);
label1.Parent = pictureBox1;
label1.Location = pos;
label1.BackColor = Color.Transparent;
}
Looks like this at runtime:
Another approach is to solve the design-time problem. That just takes an attribute. Add a reference to System.Design and add a class to your project, paste this code:
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design; // Add reference to System.Design
[Designer(typeof(ParentControlDesigner))]
class PictureContainer : PictureBox {}
You can just use
label1.Parent = pictureBox1;
label1.BackColor = Color.Transparent; // You can also set this in the designer, as stated by ElDoRado1239
You can draw text using TextRenderer which will draw it without background:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
TextRenderer.DrawText(e.Graphics,
overallpercent.ToString("#0") + "%",
this.Font,
new Point(10, 10),
Color.Red);
}
When overallpercent value changes, refresh pictureBox:
pictureBox1.Refresh();
You can also use Graphics.DrawString but TextRenderer.DrawText (using GDI) is faster than DrawString (GDI+)
Also look at another answer here and DrawText reference here
For easy for your design.
You can place your label inside a panel. and set background image of panel is what every image you want. set label background is transparent
After trying most of the provided solutions without success, the following worked for me:
label1.FlatStyle = FlatStyle.Standard
label1.Parent = pictureBox1
label1.BackColor = Color.Transparent
You most likely not putting the code in the load function. the objects aren't drawn yet if you put in the form initialize section hence nothing happens.
Once the objects are drawn then the load function runs and that will make the form transparents.
private void ScreenSaverForm_Load(object sender, EventArgs e)
{
label2.FlatStyle = FlatStyle.Standard;
label2.Parent = pictureBox1;
label2.BackColor = Color.Transparent;
}
One way which works for everything, but you need to handle the position, on resize, on move etc.. is using a transparent form:
Form form = new Form();
form.FormBorderStyle = FormBorderStyle.None;
form.BackColor = Color.Black;
form.TransparencyKey = Color.Black;
form.Owner = this;
form.Controls.Add(new Label() { Text = "Hello", Left = 0, Top = 0, Font = new Font(FontFamily.GenericSerif, 20), ForeColor = Color.White });
form.Show();
Using Visual Studio with Windows Form you may apply transparency to labels or other elements by adding using System.Drawing; into Form1.Designer.cs This way you will have Transparency available from the Properties panel ( in Appearance at BackColor ). Or just edit code in Designer.cs this.label1.BackColor = System.Drawing.Color.Transparent;
I have a Windows Form VS2010 .NET 4 project with a standard DataGridView bound to a datasource on a form.
The grid has a text column that I want to be a point and edit at the character clicked to.
Like normal textbox/editors when you click on the character you want to adjust. If possible I would also like to use the UP/DOWN keys to move between rows but would like the cursor to move to the same character position obviously in the same column without selecting the entire text.
I have tried a few things:
DataGridView1.ClearSelection()
DataGridView1.BeginEdit(False)
The BeginEdit just puts the cursor at the end of the text, which means another click to point to the character position for editing.
I know a Commercial grid like DevExpress defaults to editing in which you can click to the correct character position with one click but obviously costs money.
I have tried in the DataGridView1_EditingControlShowing event
If TypeOf e.Control Is System.Windows.Forms.DataGridViewTextBoxEditingControl Then
Dim tb As TextBox = e.Control
tb.SelectionStart = 5
tb.SelectionLength = 5
End If
But this does nothing.
I am just trying to remove the two or three clicks to get to the character position that needs adjustment.
I haven't looked at a Custom DataColumn as yet.
Any suggestions would be greatly appreciated.
There is no good out of the box way of doing this. The closest there is is to set the EditMode of the grid to EditOnEnter but that means you only need two clicks, not three.
You will need to write your own column type.
Someone has done just that here.
I haven't checked if that example handles up and down - if it doesn't then you were on the right track with the SelectionStart and SelectionLength properties, just grab the caret position of the cell you are leaving and apply it to the new cell.
It turns out that setting these properties is a little bit more involved that I remembered (possibly because I was already using a MaskedTextBox custom column type last time I did this).
The code below (in c# but the principle holds for vb.Net and I can give the vb code if you can't convert it yourself) works happily - could be tidied up by putting it into a custom control but I'll leave that as an exercise :)
First I add a handler for the EditingControlShowing event:
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewTextBoxEditingControl t = e.Control as DataGridViewTextBoxEditingControl;
current_control = t;
t.Leave += new EventHandler(t_Leave);
}
In the method above current_control is a form level private variable. The event handler for t looks like this:
void t_Leave(object sender, EventArgs e)
{
cell_caret_pos = current_control.SelectionStart;
}
There again we have a class level private field - cell_caret_pos.
Then what I found was that to set SelectionStart and SelectionLength you need to work within the CellEnter event handler:
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
dataGridView1.BeginEdit(false);
DataGridViewTextBoxEditingControl editControl =
(DataGridViewTextBoxEditingControl)dataGridView1.EditingControl;
if (cell_caret_pos != 0)
{
editControl.SelectionStart = cell_caret_pos;
editControl.SelectionLength = 0;
}
}
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);