How to Drag&Drop Outlook-Mail into richTextBox - c#

I got a problem with my WinForms-Application; I want to Drag&Drop a Outlook Mail into a RichTextBox. I found many articles about the Drag&Drop function but they all insert the Mailtext into the rTB (see: Link).Actually I can insert document like .txt, .jpg, Outlook-mails from desktop... to my program. My richTextBox automatic generate an image for the file and insert this image on a position. Like:
.
After the user Drag and Drop the file a image will be created on the Drop position and if the user double click the image the file will be opened.
PROBLEM:
The program work fine, but if I try to drag a mail out of Outlook, the program insert the mailbody to the richTextBox and no as an image.
I have saved one Mail on the desktop and try to insert this mail to my program. The following output is given in my richTextBox (would be perfect):
Mailicon from desktop per Drag&Drop:
Otherwise I tried to Drag&Drop a mai from Outlook to my program and the following output is given (Just look at the text and not the images:
Mail from Outlook per Drag&Drop (THE PROBLEM!!!):
The Programm insert the cc/mailadress and Mailbody to the rTB.
Here is the code behind: (My richTextBox is a own created richTextBox called "MyRichTextBox" Download the project under: link_RICHTEXTBOX. )
CODE
private void Form1DragDrop(object sender, DragEventArgs e)
{
Startup();
//Microsoft.Office.Interop.Outlook.ApplicationClass oApp =
// new Microsoft.Office.Interop.Outlook.ApplicationClass();
Microsoft.Office.Interop.Outlook.Explorer oExplorer = _Outlook.ActiveExplorer();
Microsoft.Office.Interop.Outlook.Selection oSelection = oExplorer.Selection;
foreach (object item in oSelection)
{
Microsoft.Office.Interop.Outlook.MailItem mi = (Microsoft.Office.Interop.Outlook.MailItem)item;
rTB_test.Text = mi.Body.ToString();
string mailName = "Mail\n" + (mailList.Count + 1);
// load an image with enough room at the bottom to add some text:
Image img = Image.FromFile(Imagepath);
// now we add the text:
int width = img.Width;
using (Graphics G = Graphics.FromImage(img))
using (Font font = new Font("Arial", 7f))
{
SizeF s = G.MeasureString(mailName, font, width);
G.DrawString(mailName, font, Brushes.Black,
(width - s.Width) / 2, img.Height - s.Height - 1);
}
// adding the image is easy only if we use the clipboard..
Clipboard.SetImage(img);
// now insert image
rTB_test.Paste();
// now we can get a hashcode as a unique key..
// ..we select the image we have just inserted:
rTB_test.SelectionStart = rTB_test.TextLength - 1;
rTB_test.SelectionLength = 1;
// finally we need to store the mail itself with its key:
mailList.Add(rTB_test.SelectedRtf.GetHashCode(), mi);
// cleanup: unselect and set cursor to the end:
rTB_test.SelectionStart = rTB_test.TextLength;
rTB_test.SelectionLength = 0;
}
Microsoft.Office.Interop.Outlook.Application _Outlook = null;
Dictionary<int, Microsoft.Office.Interop.Outlook.MailItem> mailList =
new Dictionary<int, Microsoft.Office.Interop.Outlook.MailItem>();
private void rTB_test_DoubleClick(object sender, EventArgs e)
{
var ss = rTB_test.SelectionStart;
var sl = rTB_test.SelectionLength;
int hash = rTB_test.SelectedRtf.GetHashCode();
// a few checks:
if (sl == 1 && mailList.Keys.Contains(hash))
{
Microsoft.Office.Interop.Outlook.MailItem mi = mailList[hash];
// do stuff with the msgItem..
// ..
}
}
void lbl_MouseDoubleClick(object sender, MouseEventArgs e)
{
Microsoft.Office.Interop.Outlook.MailItem mi =
(Microsoft.Office.Interop.Outlook.MailItem)((Label)sender).Tag;
// code to process the doubleclicked mail item..
}
void Startup()
{
_Outlook = new Microsoft.Office.Interop.Outlook.Application();
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
After the user double click on the picture the mail should be opened in Outlookexplorer.
UPDATE
If I use the code from TaW´s answer the following output is given:
After I double click the icon the mail won´t be open... So the code from the answer is just a "iconcreation".
Thank you in advanced!

Here is what I meant in my comments:
private void Form1DragDrop(object sender, DragEventArgs e)
{
Startup();
Microsoft.Office.Interop.Outlook.ApplicationClass oApp =
new Microsoft.Office.Interop.Outlook.ApplicationClass();
Microsoft.Office.Interop.Outlook.Explorer oExplorer = _Outlook.ActiveExplorer();
Microsoft.Office.Interop.Outlook.Selection oSelection = Explorer.Selection;
foreach (object item in oSelection)
{
Microsoft.Office.Interop.Outlook.MailItem mi =
(Microsoft.Office.Interop.Outlook.MailItem)item;
// rTB_test.Text = mi.Body.ToString();
Label lbl = new Label();
lbl.AutoSize = false;
lbl.Size = new Size( 80, 50); // <-- your choice!
lbl.Text = someText; // <-- your choice!
lbl.TextAlign = ContentAlignment.BottomCenter;
lbl.Image = someImage; // <-- your choice!
lbl.ImageAlign = ContentAlignment.TopCenter;
int count = rTB_test.Controls.Count;
int itemsPerRow = rTB_test.Width / 80;
lbl.Location = new Point( (count % itemsPerRow) * 80,
count / itemsPerRow * 50);
lbl.Tag = mi; // store the data object
lbl.MouseDoubleClick += lbl_MouseDoubleClick;
lbl.Parent = rTB_test; // add to the RTF's Controls
}
}
void lbl_MouseDoubleClick(object sender, MouseEventArgs e)
{
Microsoft.Office.Interop.Outlook.MailItem mi =
(Microsoft.Office.Interop.Outlook.MailItem) ( (Label)sender).Tag;
// code to process the doubleclicked mail item..
}
These Labels will sit on top of any Text in the RTB without interfering with it. If you want to, you can modify the code for the Location to move them out of the way or style the Labels in many other ways..
Update
After the last remarks the problem get a lot clearer: other parts of the application are already adding mail icons to the RTB and we shall add more 'of the same'..
Adding an Image is best done via the clipboard; here is code that will do that:
// create some test text, maybe extract it from the mailheader?..
string mailName = "Mail\n" + (mailList.Count + 1);
// load an image with enough room at the bottom to add some text:
Image img = Image.FromFile(yourMailImageFile);
// make the images unique by embedding a counter in a bright pixel:
img = (Image)fingerPrintID((Bitmap)img, 250 - mailList.Count); //*1*
// now we add the text:
int width = img.Width;
using (Graphics G = Graphics.FromImage(img))
using (Font font = new Font("Arial", 7f))
{
SizeF s = G.MeasureString(mailName, font, width);
G.DrawString(mailName, font, Brushes.Black,
(width - s.Width) / 2, img.Height - s.Height - 1);
}
// adding the image is easy only if we use the clipboard..
Clipboard.SetImage(img);
// insert only at the end!
rTB_test.SelectionStart = rTB_test.TextLength;
rTB_test.SelectionLength = 0;
// now insert image
rTB_test.Paste();
// now we can get a hashcode as a unique key..
// ..we select the image we have just inserted:
rTB_test.SelectionStart = rTB_test.TextLength - 1;
rTB_test.SelectionLength = 1;
// retrieve the counter id:
string id = GetID(rTB_test.SelectedRtf); //*2*
// finally we need to store the mail itself with its key:
mailList.Add(id, mi);
// cleanup: unselect and set cursor to the end:
rTB_test.SelectionStart = rTB_test.TextLength;
rTB_test.SelectionLength = 0
We need to create a Dictionary to store our mails:
Dictionary<string, Microsoft.Office.Interop.Outlook.MailItem> mailList =
new Dictionary<string, Microsoft.Office.Interop.Outlook.MailItem>(); // *3*
Here is how we can access the mails in the DoubleClick event:
private void rTB_test_DoubleClick(object sender, EventArgs e)
{
var ss = rTB_test.SelectionStart;
var sl = rTB_test.SelectionLength;
string id = GetID(sr); //*4*
// a few checks:
if (sl == 1 && mailList.Keys.Contains(id) && sr.Contains(#"{\pict\") )
{
Microsoft.Office.Interop.Outlook.MailItem mi = mailList[id];
// do stuff with the msgItem, e.g..
mi.Display();
}
}
Here is the result along with the image I use:
Note that in addition to adding the image we also store the both the mail data and the position of the image in the RTB in a Dictionary.
Update 2: I have replaced the position of the image as key with a HashCode of its RtfText; this is robust to any changes in the rest of the RTF's content. However, it relies on the images being unique, so adding an index to their text as in the code is recommended. (Or setting a few random pixels, maybe based on a GUID..)
Update 3 & 4: (*1* - *6*)
We found that we need to make the key resilient to several changes, like fonts surrounding the icon, which will influence the Rtf code, or the user enlarging the image.
Here is a FingerPrint function, which will make the images we add in unobtrusivly unique by setting a few pixels at the top of the image. Three to set a marker and one to set an ID:
Bitmap fingerPrintID(Bitmap bmp, int key) //*5*
{
for (int i = 0; i < 3; i++)
{
bmp.SetPixel(i, 0, Color.FromArgb(255, 238,238,238)); // EE EE EE
}
bmp.SetPixel(3, 0, Color.FromArgb(255, key, key, key));
return bmp;
}
And to retrieve this function will pull the 3 hex digits as string from the RTF code:
string GetID(string Rtf) //*6*
{
int x = Rtf.IndexOf("eeeeeeeeeeeeeeeeee"); // 238 238 238
if (x < 0) return "";
string hex = Rtf.Substring(x +18, 6);
return hex;
}
I chose the pixels to be rather bright; if you know which image you use, you can optimze the color choice even more.. With the new string id, we don't need the GetHashcode calls..

Related

how can I select the pictures loaded in windows Form in c#?

I have some pictures in a database which I retrieve them . To load these pictures, I made a "Tab Control" in Windows Form, which has a "Tab page1". when the program runs, a group box, containing a PictureBox (and some other text boxes), will be created for each picture. my pictures can be load in these picture boxes, and I will have a list of group boxes(gbList). However, I can not select these pictures during the run. Can anybody suggest a solution?
private void Form2_Load(object sender, EventArgs e)
{
tabPage1.Controls.Clear();
int x = 0, y = 0;
int j = 0;
for (int i = 0; i < output.Count - 1; i++)
{
PictureBox pic = new PictureBox();
pic.SizeMode = PictureBoxSizeMode.StretchImage;
SelectablegroupBox gb = new SelectablegroupBox();
gb.Controls.Add(pic);
gbList.Add(gb);
//to retrieve the images from the database in ProductImages class: (output is the result of a query of database)
ProductImages pI = output[i];
imgbyte = pI.Pic;
using (MemoryStream ms = new MemoryStream(imgbyte))
{
Image img = Image.FromStream(ms);
pic.Image = img;
}
//to add the group box list o the tabpage:
tabPage1.Controls.Add(gbList[j]);
gbList[j].Location = new Point(x, y);
y += gbList[i].Height;
j++;
}
here is my problem. I want the user to be able to select the images (Then I want to save these selected Items). But the "result" is always empty:
var result = from s in gbList
where s.Focused ==true
select s;
foreach (var s in result)
{ //save the selected images}
As I learned from another post, I defined SelectablegroupBox" as:
class SelectablegroupBox : GroupBox
{
public SelectablegroupBox()
{
this.SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
}
protected override void OnEnter(EventArgs e)
{
this.Focus();
this.Invalidate();
base.OnEnter(e);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if (this.Focused)
{
var rc = this.ClientRectangle;
rc.Inflate(-2, -2);
ControlPaint.DrawFocusRectangle(pe.Graphics, rc);
}
}
}
thanks in advance
Your class SelectableGroupBox is not suitable to let the user select one or more images. There can be at most one focused control in your app - this will be probably a button on your form which the user clicks to save the selected images.
One simple solution would be to use CheckBox controls with the Appearance property set to Button. Also, you don't have to layout the images manually, let a FlowLayoutPanel do the job.
First, add a FlowLayoutPanel named flowLayoutPanel to your tabPage2 and set the following Properties:
flowLayoutPanel.AutoScroll = true;
flowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
Then change the appropriate code in Form2 to:
private const int imageWidth = 128;
private const int imageHeight = 128;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
for (int i = 0; i < output.Count; i++)
{
CheckBox cb = new CheckBox();
cb.Appearance = Appearance.Button;
cb.Size = new Size(imageWidth, imageHeight);
cb.BackgroundImageLayout = ImageLayout.Zoom;
ProductImages pI = output[i];
//Don't dispose the MemoryStream, the Image class will need it!
var ms = new MemoryStream(pI.Pic);
cb.BackgroundImage = Image.FromStream(ms);
flowLayoutPanel.Controls.Add(cb);
}
}
This is how you get your selected pictures:
private void SaveButton_Click(object sender, EventArgs e)
{
var selected = flowLayoutPanel.Controls.OfType<CheckBox>().Where(x => x.Checked);
Debug.Print("Selected images: {0}", selected.Count());
foreach (var item in selected)
{
//Save the picture from item.BackgroundImage.
}
}

How to get Images from database to Listview c#

I want to get database images show in listview but it does not work . I tried but can't any one can help .
ListViewItem liv = new ListViewItem(read[0].ToString());
liv.SubItems.Add(read[1].ToString());
liv.SubItems.Add(read[2].ToString());
liv.SubItems.Add(read[3].ToString());
listView1.Items.Add(liv);
Here on index[3] in database the images stored .
The error show in image
For what I can see, your image is stored in a Database and retrieved in ByteArray format. You need to convert the ByteArray stream to a Bitmap Image:
Image _image = new Bitmap(new MemoryStream((Byte[])read[3]));
Since this image has to be referenced in more than one method, define it at Class level.
using System.Drawing;
using System.Drawing.Text;
Image _image;
To let a SubItem display the image, you need to Paint the items yourselft, so set the OwnerDraw property of your ListView:
listView1.OwnerDraw = true;
Get the items from your Data source:
(... LOOP ...)
//Define a new ListView Item...
ListViewItem _LVItem = new ListViewItem(read[0].ToString());
ListViewItem.ListViewSubItemCollection _ItemsCollection =
new ListViewItem.ListViewSubItemCollection(_LVItem);
//... and SubItems
_ItemsCollection.Add(new ListViewItem.ListViewSubItem(_LVItem, read[1].ToString()));
_ItemsCollection.Add(new ListViewItem.ListViewSubItem(_LVItem, read[2].ToString()));
//No text here, this is where the image will be drawn
_ItemsCollection.Add(new ListViewItem.ListViewSubItem(_LVItem, ""));
//Create a new Bitmap using a MemoryStream
_image = new Bitmap(new MemoryStream((Byte[])read[3]));
listView1.Items.Add(_LVItem);
(... LOOP ...)
Create EventHandlers for listView1.DrawColumnHeader and listView1.DrawSubItem
//You need to draw both Headers...
private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
//Let the system draw these headers, nothing to do here
e.DrawDefault = true;
}
//... and SubItems
private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
//If this is the column where the image is shown, draw it
if (e.ColumnIndex == 3)
{
//Position the image in the middle of its Column
//This will be re-calculated when the Column is resized
int _XLocation = (e.SubItem.Bounds.X +
(e.SubItem.Bounds.Width / 2) -
(e.SubItem.Bounds.Height / 2));
//Draw the Image resized to the Height of the row
e.Graphics.DrawImage(_image, new Rectangle(_XLocation, e.SubItem.Bounds.Y, e.SubItem.Bounds.Height, e.SubItem.Bounds.Height));
}
//Draw the other columns using their pre-defined values
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
e.Graphics.DrawString(e.SubItem.Text,
e.SubItem.Font,
new SolidBrush(e.SubItem.ForeColor),
e.SubItem.Bounds.Location.X,
e.SubItem.Bounds.Location.Y);
}
And this is the result:
// To Convert you byte array to Images you need to convert it to a memory stream first
// You will need to add:
// using System.IO;
// And you need to add an ImageList named "imageList1" to your form.
// Then Initialize the ImageList object with images.
for (int i = 0; i < read.Length; i++)
{
try
{
MemoryStream memStream = new MemoryStream(read[i]);
this.imageList1.Images.Add(Image.FromStream(memStream));
}
catch
{ MessageBox.Show( "Image at index ( " + i.ToString() + " ) is not an image file"); }
}
//Now You can assign the ImageList objects to your ListView.
this.listView1.View = View.SmallIcon;
this.listView1.SmallImageList = this.imageList1;
for (int j = 0; j < this.imageList1.Images.Count; j++)
{
ListViewItem liv = new ListViewItem();
liv.ImageIndex = j;
this.listView1.Items.Add(liv);
}

Display text from file in a picture box

I would like to ask, how would you print text from a file directly into a pictureBox. Currently, my program is supposed to do that, but it fails, and I think the reason is, that I force the containerBox to the front of the program. The pictureboxes itself are black as of right now, but that is for testing purposes.
Code:
for (int i = 0; i < fileitems.Length; i++)
{
containerBox.Add(new PictureBox());
//PictureBox pBox = new PictureBox();
containerBox[i].Name = "cb" + i;
containerBox[i].Location = new Point(Convert.ToInt32(b*0.05), curB);
containerBox[i].Size = new Size(Convert.ToInt32(b*0.9),Convert.ToInt32(a/5));
containerBox[i].BackColor = Color.Black;
containerBox[i].Dock = DockStyle.Left;
containerBox[i].Anchor = AnchorStyles.None;
//containerBox[i].Paint += PBox_Paint;
j = containerBox[i].CreateGraphics();
using (Font test1 = new Font("Arial", 14))
{
j.DrawString(fileitems[i],test1,Brushes.Blue,new Point(2,2));
}
//this.Controls.Add(containerBox[i]);
//containerBox.Add(pBox);
this.Controls.Add(containerBox[i]);
containerBox[i].BringToFront();
curB = Convert.ToInt32(containerBox[i].Location.Y+(a/5)+25);
}
As you can see, I tried making it so, that I can paint, but then I can't access the file or read the data. Below you see the code in the paint event
Code:
private void PBox_Paint(object sender, PaintEventArgs e)
{
/*
using (Font test1 = new Font("Arial", 14))
{
e.Graphics.DrawString("test", test1, Brushes.Blue, new Point(3, 3));
}*/
}
How can I read the text from the file, then print it to the left side in the picturebox?

Format issue in Listbox

I want to show on my listbox this type of format:
"File name Size";
foreach (string filePath in filePaths)
{
BarraDeProgresso.Visible = true;
PegarMeuFicheiro = filePath;
// here is where im tryng to do it. but isn´tworking as i expected.
lbMostrarItems.Items.Add(String.Format("{0, 5} {1, 30}",PegarMeuFicheiro.Substring(9 + nome.Length + 20, PegarMeuFicheiro.Length - (9 + nome.Length + 20)),"Size"));
//lbMostrarItems.SelectedIndex = lbMostrarItems.Items.Count - 1;
}
What can I do to make it all align on the right?
Make use of the ListView control instead which allows for columns and many other features.
First add the control, then select it and go to the control's property and change the View to Details. This will allow you to see a list with resizable column names.
Next, create two columns (One for the file name and the other for the file size) or whatever it may be in your case. To do this, on the properties window go to Columns and click it to get the dialog window which will allow you to add columns.
Finally, here is some sample code on how to use ListView.
private void Form1_Load(object sender, EventArgs e)
{
var fileListForExample = Directory.GetFiles(#"C:\");
foreach (var item in fileListForExample)
{
FileInfo fileInfo = new FileInfo(item);
var lstItem = new ListViewItem(Path.GetFileName(item));
lstItem.SubItems.Add(fileInfo.Length.ToString());
var itemAdded = listView1.Items.Add(lstItem);
}
}
You can manually draw item in the ListBox.
Example:
public Form1()
{
//InitializeComponent();
this.Width = 500;
var listBox = new ListBox { Parent = this, Width = 400, Height = 250 };
listBox.DrawMode = DrawMode.OwnerDrawFixed;
var files = new DirectoryInfo(".").GetFiles();
listBox.DataSource = files;
listBox.DrawItem += (o, e) =>
{
e.Graphics.DrawString(files[e.Index].Name, listBox.Font, Brushes.Black, e.Bounds);
var length = files[e.Index].Length.ToString();
var size = e.Graphics.MeasureString(length, listBox.Font);
e.Graphics.DrawString(length, listBox.Font,
Brushes.Black, e.Bounds.Width - size.Width, e.Bounds.Y);
};
}

Using Graphics.DrawImage to create custom tabs in C#

I have a project in which you can add and remove tabs (like a web browser). So far I have this:
//Button to add a new tab page
private void cb_addPage_Click(object sender, EventArgs e)
{
string title = "TabPage " + (tabControl1.TabCount + 1).ToString() + " ";
TabPage myTabPage = new TabPage(title);
tabControl1.TabPages.Add(myTabPage);
tabControl1.SelectedTab = myTabPage;
}
//Form1_Load
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
cb_addPage.Top = tabControl1.Top;
cb_addPage.Left = tabControl1.Right - cb_addPage.Width;
foreach (TabPage tp in tabControl1.TabPages) tp.Text += " ";
}
Rectangle closeX = Rectangle.Empty;
//Sets background and places the X button on each tab
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Size xSize = new Size(15, 15);
TabPage tp = tabControl1.TabPages[e.Index];
e.DrawBackground();
using (SolidBrush brush = new SolidBrush(e.ForeColor))
e.Graphics.DrawString(tp.Text + " ", e.Font, brush,
e.Bounds.X + 3, e.Bounds.Y + 4);
if (e.State == DrawItemState.Selected)
{
closeX = new Rectangle(e.Bounds.Right - xSize.Width - 3,
e.Bounds.Top + 5, xSize.Width, xSize.Height);
e.Graphics.DrawImage(imageList1.Images[0], closeX,
new Rectangle(0,0,16,16), GraphicsUnit.Pixel );
}
}
//Removes current tab (from X button)
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
if (closeX.Contains(e.Location))
tabControl1.TabPages.Remove(tabControl1.SelectedTab);
}
So all this does is let you add tabs with a button and on each individual tab there is an X button to delete the tab.
I have used Graphics.DrawImage to display the custom X button (that are in an imageList). However how will I go about making custom tabs using Graphics.DrawImage.
To sum up I want tabs, but I want them to be custom images that I have made so it looks better. - Thanks
Your question is not very clear. Probably you want to display a different text on each tab. You can use the TextRenderer to do so:
const TextFormatFlags flags = TextFormatFlags.PreserveGraphicsClipping |
TextFormatFlags.VerticalCenter;
TextRenderer.DrawText(e.Graphics, tp.Text, tp.Font, e.Bounds, tp.ForeColor, flags);
Either prepend some spaces to the text in order to leave space for the X or define new coordiantes for the text
const int XCrossWidth = 20;
Rectangle textRect = new Rectangle(e.Bounds.Left + XCrossWidth, e.Bounds.Top,
e.Width - XCrossWidth, e.Height);
and substitue this for e.Bounds in TextRenderer.DrawText(...).
UPDATE
So you want to display custom images on your tabs. I assume that you have placed these images in the imageList1. How do you know which of them to display on which TabPage?
You could create your own tab page class and use this one instead of TabPage.
public TabPageEx : TabPage
{
public int ImageIndex { get; set }
}
Now set the property to the appropriate image index.
TabPageEx myTabPage = new TabPageEx(title);
myTabPage.ImageIndex = 3; // As an example.
tabControl1.TabPages.Add(myTabPage);
Then you can draw the image with
TabPageEx tp = (TabPageEx)tabControl1.TabPages[e.Index];
...
Rectangle imageRect = new Rectangle(e.Bounds.Left + 20, 0, 16, 16);
e.Graphics.DrawImage(imageList1.Images[tp.ImageIndex], imageRect);
If you want to display Images in addition to the text like a webbrowsers favicon you can use this modified code:
private void tabControl3_DrawItem(object sender, DrawItemEventArgs e)
{
Size xSize = new Size(16,16);
Point imgLoc = new Point(e.Bounds.X + 4, e.Bounds.Y + 4);
TabPage tp = tabControl3.TabPages[e.Index];
e.DrawBackground();
e.Graphics.DrawImage(imageList1.Images[tp.ImageIndex], new Rectangle(imgLoc, xSize),
new Rectangle(Point.Empty, xSize), GraphicsUnit.Pixel);
using (SolidBrush brush = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(tp.Text + " ", e.Font, brush,
e.Bounds.X + 23, e.Bounds.Y + 4);
if (e.State == DrawItemState.Selected)
{
closeX = new Rectangle(e.Bounds.Right - xSize.Width - 3,
e.Bounds.Top + 5, xSize.Width, xSize.Height);
e.Graphics.DrawImage(imageList1.Images[0], closeX,
new Rectangle(Point.Empty, xSize), GraphicsUnit.Pixel);
}
}
}
You need to make sure that:
You have those images you want to show in each tab in your imagelist.
and you know the index of ech one.
Youi must set it when you create the page but you can always change it later.
It is a good idea to have a default icon at index 0 and to set the imageindex to 0 for those you don't know the right index.
Usually you would also have to make your Tab control point to the Imagelist. But since we are drawing it all by ourselves, this is not important.
You can use the more complex format of DrawString, that is used for drawing the close button. Here you don't just use a point to determine the location where to draw; instead this format uses two rectangles to determine the source and the target. This effectively leads to th option of scaling the image to a new size.
But you'll get the best quality if your Images have the right size to begin with. Please note that the text of each TabPage determines the width of the tab; to make it higher you need to chose a larger Fontsize.

Categories