C# winform change selected tabcontrol image - c#

I have a winform application written in C#. I had an imageList in my winform and I have a tabcontrol and each of the tab I assign a image as icon for the tab by changing ImageIndex.
However they have only 1 image for each tab and I want them to change to another image for the selected tab (like another highlighted image for active one). I have an idea to add all images to the imageList (both active and inactive images) and change the imageIndex of the selected tab. But I am not sure how to do it in practical.
Here are my current codes that I can come up with:
Inside SelectedIndexChange event, I have a function:
foreach (TabPage tab in tabControl1)
{
if (tab.index == tabControl1.SelectedIndex) { <---how to get the index?
tab.imageIndex = tab.index + tabControl1.TabCount;
} else {
tab.imageIndex = tab.index;
}
}

I came up with a solution
for (int i=0; i<tabControl1.TabPages.Count; i++)
{
if (tabControl1.TabPages[i] == tabControl1.SelectedTab)
{
tabControl1.TabPages[i].ImageIndex = i + tabControl1.TabPages.Count;
}
else
{
tabControl1.TabPages[i].ImageIndex = i;
}
}

Related

Add image programmatically to nested ToolStripMenuItem via ImageIndex

I have a menu structure as seen in picture below:
I want to add images to all submenu-items under the controllerToolStripMenuItem, ie openToolStripMenuItem, openInNewWindowToolStripMenuItem... ImageList contains my images to use and menuStrip1 gets a reference to the list of images :
menuStrip1.ImageList = ImageList;
Test code:
private void LoadSubMenuIcons()
{
menuStrip1.ImageList = ImageList;
//Just for test:
controllerToolStripMenuItem.ImageIndex = 2;
ToolStrip firstLevelParent = controllerToolStripMenuItem.GetCurrentParent();
//firstLevelParent.ImageList is of type MenuStrip
//firstLevelParent.ImageList equals ImageList set above
foreach (ToolStripItem subMenuItem in controllerToolStripMenuItem.DropDownItems)
{
if (subMenuItem is ToolStripMenuItem)
{
subMenuItem.ImageIndex = 2;
ToolStrip secondLevelParent = subMenuItem.GetCurrentParent();
//secondLevelParent is of type ToolStripDropDownMenu
//secondLevelParent.ImageList is null
}
}
}
In the example code above I try to add the image with index 2 to all submenu-items. This doesn't work! It might have to do with the fact that their parent is of type ToolStripDropDownMenu and its ImageList-property is null? The middle level item, controllerToolStripMenuItem, on the other hand shows the image correctly. Its parent is menuStrip1 which has a valid refrence to my imagelist. How do I solve the problem with the submenu-items?

Adding panels programatically based on .top is being based on the scroll of its parent

I am looking for some assistance in fixing an issue. At the moment I have developed some code that adds a user control to a panel. It adds multiple user controls to the panel and does this based on the .top feature. However, once the panel that I am adding the user controls to is scrolled down the user controls seem to be placed strangely.
I have already tried to adjust the .top value but I am not sure how to do it in relation to the scroll of the panel.
int i = 0;
foreach(memberInformation mi in pnlMembers.Controls.OfType<memberInformation>())
{
try
{
if (UserInformation.isPartyLeader)
{
mi.canUserEdit = "true";
}
else
{
mi.canUserEdit = "false";
}
mi.playerName = downloadInfo.Split(':')[i].Split(',')[0];
mi.playerRole = downloadInfo.Split(':')[i].Split(',')[1];
}
catch
{
pnlMembers.Controls.Remove(mi);
}
i++;
}
VIDEO to show what is happening: https://gyazo.com/985566afb7e4bab464dd06da191a0710
https://gyazo.com/4b0514cbdb310ea8abc46a397458130c
The correct way in order to position panels inside another panel is to use flowlayoutpanel.
Thanks

Allow a ListBox to overlap a TableLayoutPanel (C# .NET)

I have a form that contains a TableLayoutPanel with various controls and labels in it. One of them is a custom control that inherits from ComboBox that has extra auto-complete behavior (auto-completes on any text rather than just left to right). I didn't write the code for this control, so I'm not super familiar with how it works, but essentially upon clicking on the Combobox, it adds a ListBox below the ComboBox, within the same Panel of the TableLayoutPanel, that covers the normal drop down.
Unfortunately, the TableLayoutPanel prevents the ListBox from being fully visible when added, and only one item is shown. The goal is to get it to look like a normal ComboBox which would drop down to cover any controls below it.
Is there any way to allow a control that is in a TableLayoutPanel to overlap the TableLayoutPanel to get this to work as I want? I want to avoid any controls moving around due to the TableLayoutPanel growing to accommodate the ListBox.
Relevant code from the control:
void InitListControl()
{
if (listBoxChild == null)
{
// Find parent - or keep going up until you find the parent form
ComboParentForm = this.Parent;
if (ComboParentForm != null)
{
// Setup a messaage filter so we can listen to the keyboard
if (!MsgFilterActive)
{
Application.AddMessageFilter(this);
MsgFilterActive = true;
}
listBoxChild = listBoxChild = new ListBox();
listBoxChild.Visible = false;
listBoxChild.Click += listBox1_Click;
ComboParentForm.Controls.Add(listBoxChild);
ComboParentForm.Controls.SetChildIndex(listBoxChild, 0); // Put it at the front
}
}
}
void ComboListMatcher_TextChanged(object sender, EventArgs e)
{
if (IgnoreTextChange > 0)
{
IgnoreTextChange = 0;
return;
}
InitListControl();
if (listBoxChild == null)
return;
string SearchText = this.Text;
listBoxChild.Items.Clear();
// Don't show the list when nothing has been typed
if (!string.IsNullOrEmpty(SearchText))
{
foreach (string Item in this.Items)
{
if (Item != null && Item.ToLower().Contains(SearchText.ToLower()))
{
listBoxChild.Items.Add(Item);
listBoxChild.SelectedIndex = 0;
}
}
}
if (listBoxChild.Items.Count > 0)
{
Point PutItHere = new Point(this.Left, this.Bottom);
Control TheControlToMove = this;
PutItHere = this.Parent.PointToScreen(PutItHere);
TheControlToMove = listBoxChild;
PutItHere = ComboParentForm.PointToClient(PutItHere);
TheControlToMove.Anchor = ((System.Windows.Forms.AnchorStyles)
((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
TheControlToMove.BringToFront();
TheControlToMove.Show();
TheControlToMove.Left = PutItHere.X;
TheControlToMove.Top = PutItHere.Y;
TheControlToMove.Width = this.Width;
int TotalItemHeight = listBoxChild.ItemHeight * (listBoxChild.Items.Count + 1);
TheControlToMove.Height = Math.Min(ComboParentForm.ClientSize.Height - TheControlToMove.Top, TotalItemHeight);
}
else
HideTheList();
}
Images:
Desired behavior
Current behavior
Going on the suggestion from TaW, I came up with a tentative solution. This form isn't re-sizable but does auto-size so that it looks ok if the user changes their DPI in Windows.
To resolve this, I moved the control out of the TableLayoutPanel to an arbitrary position in the Parent of the TableLayoutPanel. On form loading, I summed the coordinates of the TableLayoutPanel and an empty panel in the cell that I wanted the control to be located on top of. This worked for my needs but it feels like a kludge.
The better solution is probably to use Control.PointToScreen and Control.PointToClient methods, however I wasn't able to get these methods to give me the correct coordinates.

listview in c# with images [duplicate]

This question already has answers here:
Images in ListView subitem
(2 answers)
Closed 9 years ago.
I wish to make a list of items with pictures, the amount of items can vary from 1-60 and for each item I wish to also show data.
I believe the best way of going about this is using the ListView in c#.
is this true and if so how would I go about doing this?
i have also thought about using interactive images within a scrolling window
If you want to do this in the designer, you can take the following steps to add the
images to the ListView control:
Switch to the designer, click on the ImageList component on the Component Tray,
there will be a smart tag appear on the top-right corner of the ImageList.
Click the smart tag, and click "Choose Images" on the pane.
On the pop-up Image Collection Editor dialog, choose the images from the folder
your want.
Click OK to finish adding images to the ImageList.
Click the ListView on the form, there will be a smart tag appear on the top-right
corner.
Click the smart tag, you will find there're three ComboBoxes there, choose a
ImageList from the list as you want.
Click the "Add items" option on the smart tag, a ListViewItem Collection Editor
will appear, you can add items to the ListView, it's important here to set the
ImageIndex or ImageKey property, or the image won't appear.
Click OK to finish item editing, now you'll find the images are displayed on the
ListView.
If you want to add the images to the ListView by code, you can do something like this`
Code Snippet
private void Form10_Load(object sender, EventArgs e)
{
DirectoryInfo dir = new DirectoryInfo(#"c:\pic");
foreach (FileInfo file in dir.GetFiles())
{
try
{
this.imageList1.Images.Add(Image.FromFile(file.FullName));
}
catch{
Console.WriteLine("This is not an image file");
}
}
this.listView1.View = View.LargeIcon;
this.imageList1.ImageSize = new Size(32, 32);
this.listView1.LargeImageList = this.imageList1;
//or
//this.listView1.View = View.SmallIcon;
//this.listView1.SmallImageList = this.imageList1;
for (int j = 0; j < this.imageList1.Images.Count; j++)
{
ListViewItem item = new ListViewItem();
item.ImageIndex = j;
this.listView1.Items.Add(item);
}
}
Source

How can i give a focus to a listBox in the constructor and when a new item was added?

In the constructor i did:
if (listBox1.Items != null)
{
listBox1.Focus();
}
But when im running the program i cant move with the keyboards up down in listBox since the focus is on a button somewhere else in the Form. I need to click with the mouse on the listBox to get the focus.
Another problem i want that when the user add a new item to the listBox the focus will be automatic on the last added item. For this problem this is the code where im adding a new item to the listBox:
private void KeysValuesUpdate()
{
using (var w = new StreamWriter(keywords_path_file))
{
crawlLocaly1 = new CrawlLocaly();
crawlLocaly1.StartPosition = FormStartPosition.CenterParent;
DialogResult dr = crawlLocaly1.ShowDialog(this);
if (dr == DialogResult.OK)
{
if (LocalyKeyWords.ContainsKey(mainUrl))
{
LocalyKeyWords[mainUrl].Clear();
LocalyKeyWords[mainUrl].Add(crawlLocaly1.getText());
}
else
{
LocalyKeyWords[mainUrl] = new List<string>();
LocalyKeyWords[mainUrl].Add(crawlLocaly1.getText());
}
Write(w);
ClearListBox();
}
if (dr == DialogResult.Cancel)
{
Write(w);
}
}
}
private void ClearListBox()
{
data.Clear();
listBox1.DataSource = null;
string sb;
foreach (KeyValuePair<string, List<string>> kvp in LocalyKeyWords)
{
for (int i = 0; i < kvp.Value.Count(); i++)
{
sb = "Url: " + kvp.Key + " --- " + "Local KeyWord: " + kvp.Value[i] + Environment.NewLine;
data.Add(sb.ToString());
}
}
listBox1.DataSource = data;
}
The question is why i cant set the focus in any of the cases on the listBox items ?
In the first case in the constructor the focus i want it to be on the last item in the list and also each time im adding a new item so the focus will be on the last added item.
Most likely, the item is being selected, you just can't tell because a different control has the focus. There are a couple of different ways that you can solve this, depending on the design of your application.
For the first part of the question, you should set the Focus in the Page/Form Load event, since at the constructor level controls are under initialization process.
Set the focus to the ListView first whenever your form is displayed. The user typically sets focus to controls by clicking on them. However, you can also specify which controls gets the focus programmatically. One way of doing this is by setting the tab index of the control to 0 (the lowest value indicates the control that will have the initial focus). A second possibility is to use the following line of code in your form's Load event, or immediately after you set the Selected property:
listBox1.Select();
The problem with this solution is that the selected item will no longer appear highlighted when the user sets focus to a different control on your form (such as a textbox or a button).
For the second part of the question, selecting last added item in the ListBox, use the following code:
listBox1.SelectedIndex = listBox1.Items.Count - 1;
listBox1.SetFocus();
Looks like your ClearListBox method is actually a UpdateListBox method.
listBox1.DataSource = data;
listBox1.SelectedIndex = <index of newitem>;
// or
listBox1.SelectedItem = "text of new item";
listBox1.SetFocus();
If the new item is the last item, its index is listBox1.Items.Count - 1.

Categories

Resources