I am trying to create a Bitmap from a RichTextBox and set it as the background image for a panel, but unfortunately the text is not shown.
Bitmap l_bitmap = new Bitmap(m_control.Width, m_control.Height);
m_control.DrawToBitmap(l_bitmap, new Rectangle(0, 0, l_bitmap.Width, l_bitmap.Height));
m_panel.BackgroundImage = l_bitmap;
m_panel.Refresh();
m_control is my RichTextBox. When I debug, I can see that the control contains the text I wrote, but the bitmap just shows an empty RichTextBox.
I use the same code for other types of controls (Button, CheckBox, TextBox...). The text is shown with no problems.
Well you are trying to create a bitmap from the control. The text you put in there isn't the control, so it won't bother to chow it as bitmap. Try to create a picture from screen (like a screenshot).
Example:
Graphics gr = Graphics.FromImage(l_bitmap);
gr.CopyFromScreen(m_control.PointToScreen(Point.Empty), point.Empty, m_control.Size);
This will make a bitmap from your given points. This will additional show you the text.
EDIT
Maybe you can use this instead. In addition to your idea, I simply put a label onto my panel. (L for Label and P for Panel)
As you can see, the label is empty because I cleared the Text property. Now, when you click one of the buttons below the panel, it will update the label.Text propertie and there will be the text you gave the control.
Here is some example:
As you can see, the label shows the Name of the control. Completly custom as you can see on my source code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public RichTextBox tmpRtf = new RichTextBox();
//Poor button name incoming...
private void button1_Click(object sender, EventArgs e)
{
if (tmpRtf == null)
tmpRtf = new RichTextBox();
//You can add any text here and it will be shown on the label.
this.tmpRtf.Text = "Richtextbox";
this.UpdatePanel(this.tmpRtf);
}
//Custom method to update the panel for any control. Can pobably be done way better than this, but hey.
private void UpdatePanel(object pControl)
{
//Checks if control is a rtf
if(pControl is RichTextBox)
{
//This is your code! Ay.
Bitmap l_bitmap = new Bitmap(this.panel1.Width / 2, this.panel1.Height / 2);
(pControl as RichTextBox).DrawToBitmap(l_bitmap, new Rectangle(0, 0, l_bitmap.Width, l_bitmap.Height));
this.tmpRtf.BackColor = Color.LightGray;
this.panel1.BackgroundImage = l_bitmap;
this.panel1.BackgroundImageLayout = ImageLayout.Center;
this.labelControlName.Text = this.tmpRtf.Text;
this.panel1.Refresh();
}
}
}
Its not possible to show text on a control thats not visualized. But you can build a workaround! Or, instead of taking a picture you can simply create the control on top of it, that will also show the Text and maybe the user can test it (e.g. click on buttons, look at the control behaviour).
Hopefully this is something to get you inspired that there are always more ways to accomplish.
Related
If this is a dumb question, forgive me. I have a small amount of experience with C#, but not to this degree yet.
I have a series of images that I want to put into a grid with space around each image, also text beneath them and I want them to be clickable, so when they're clicked they hilite, and double click runs an event. The best example I have for this is the user interface of the program ACDSee. I've googled this for hours, and haven't come up with anything applicable. Is this difficult or simple? Can anyone give me an example, or point me in the right direction?
Cheers.
It doesn't seem to be very difficult. I would suggest the following steps:
Add a new "User Control" to your project for image thumbnails. It can contain a docked PictureBox and a Label or LinkLabel at its bottom.
For the space around each thumbnail simply play with the Padding property of the user control.
For the so called grid that is going to hold the thumbnails, use a FlowLayoutPanel, and simply add instances of the above mentioned user-control to this panel.
For visual representation of being selected, change the background color of the user-control instance to blue (for example), and back to control-face when deselected. It is recommended to implement an IsSelected property for the user-control as well.
To emulate thumbnail selection, handle the Click event of the user-control and assign the events for all thumbnail instances to a single event-handler method. Store a global reference to the already selected thumbnail, name it e.g., SelectedThumbnail initialized with null. In the event-handler body compare the sender with the global SelectedThumbnail, and update it if required. If the user-control associated with the sender is not selected (i.e., its background is not blue, or IsSelected is false) make it selected, or change its background. Otherwise change the background to its default color (e.g., control-face).
The Click event handler body looks something like this:
MyThumbnailControl ctrl = sender as MyThumbnailControl;
if(ctrl == null) return;
if(ctrl == SelectedThumbnail) return; // selected again
if(ctrl != SelectedThumbnail)
{
ctrl.IsSelected = true;
ctrl.BackColor = Color.Blue;
// it's better to set the back-color in the IsSelected property setter, not here
SelectedThumbnail.IsSelected = false;
SelectedThumbnail.BackColor = Color.Control;
SelectedThumbnail = ctrl; // important part
}
It's also recommended that all thumbnail instances that are going to be added to the so-called grid, be referenced in a separate array too. Therefore changing selection with arrow-keys would be possible with simple index calculations.
Further Notes: I assumed that the user-control that is to be created is named MyThumbnailControl, just a random name to refer to that control. When you create a new user-control, the wizard generates a class for you with your desired name (e.g., MyThumbnailControl), you can define a property inside it named IsSelected and implement its getter and setter. See this for a tutorial. After defining the user-control you can instantiate instances from its corresponding class. Also by global reference, I meant a variable at the form (or any parent control) level. To keep it simple we can add a reference of the selected thumbnail in the form that is going to hold the grid and thumbnails: MyThumbnailControl selectedThumb = null; or something like this in the body of the form.
Here is something, I just fixed you.
Create a C# project name CreateImageList and in the Form1 add the following 5 controls with their default name i.e. Panel1, PictureBox1, Label1, Button1, Button2:
How it works:
When the page load it create an imageList objects and load all .jpg images from a folder you provide
ImageList Images are set into the PictureBox control and when user clicks "Button1" the picturebox shows next image in ImageList and when user clicks "Button2" the PictureBox shows previous image from ImageList.
The Label1 shows the currentImage counter from the ImageList Arrage. If you want to write something specific, you can create an array of text and sync with your image counter.
When user click on PictureBox the a border is create to show Picture highlighted
When user Double Click on PictureBox a MessageBox appears shows DoubleClick event.
Now, you can use the following code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace CreateImageList
{
public partial class Form1 : Form
{
private int currentImage = 0;
protected Graphics myGraphics;
ImageList iPicList = new ImageList();
public Form1()
{
InitializeComponent();
DirectoryInfo dirImages = new DirectoryInfo("C:\\2012");
iPicList.ImageSize = new Size(255, 255);
iPicList.TransparentColor = Color.White;
myGraphics = Graphics.FromHwnd(panel1.Handle);
foreach (FileInfo file in dirImages.GetFiles())
{
if (file.Extension == ".jpg")
{
Image myImage = Image.FromFile(file.FullName);
iPicList.Images.Add(myImage);
}
}
if (iPicList.Images.Empty != true)
{
panel1.Refresh();
currentImage = 0;
// Draw the image in the panel.
iPicList.Draw(myGraphics, 1, 1, currentImage);
// Show the image in the PictureBox.
pictureBox1.Image = iPicList.Images[currentImage];
label1.Text = "Image #" + currentImage;
}
}
private void showImage(int imgIndex)
{
// Draw the image in the panel.
iPicList.Draw(myGraphics, 1, 1, currentImage);
// Show the image in the PictureBox.
pictureBox1.Image = iPicList.Images[currentImage];
label1.Text = "image #" + currentImage;
panel1.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
if (iPicList.Images.Count - 1 > currentImage)
{
currentImage++;
}
else
{
currentImage = 0;
}
showImage(currentImage);
}
private void button2_Click(object sender, EventArgs e)
{
if (iPicList.Images.Count - 1 >= currentImage)
{
if (currentImage == 0)
currentImage = iPicList.Images.Count-1;
else
currentImage--;
}
else
{
currentImage = iPicList.Images.Count;
}
showImage(currentImage);
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
MessageBox.Show("Picture Box Double clicked");
}
private void pictureBox1_Click(object sender, EventArgs e)
{
panel1.Refresh();
myGraphics.DrawRectangle(Pens.Black, 0, 0, iPicList.Images[currentImage].Width + 1, iPicList.Images[currentImage].Height + 1);
pictureBox1.Image = iPicList.Images[currentImage];
}
}
}
The changes you need are:
Change the Following folder to a place where you have lots of jpg:
DirectoryInfo dirImages = new DirectoryInfo("C:\\2012");
Also if you are dealing with other kind of images, make change here:
if (file.Extension == ".jpg") // Change it to your image type.
If you don't want to use the the buttons to go up and down, you have several other options to host PictureBox control in scrollable Panel or list or something else.
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 am working on a project in c# using windows forms.
me and the group I am in want to make it so that when the user hovers their mouse over an image, in our case a card, that a larger image of that card appears next to the mouse arrow, much in the same way a tool tip would work.
I don't think you can use a tool tip to do this i have tried looking everywhere,
any advice or examples would be great thank you very much
You may want to look at this Code Project Article
It shows you how to create an OwnerDrawn ToolTip with an Image.
Thanks for the responses I got everything figured out.
What I wanted to do was that when I moused over a certain area a different image for that area would popup in the same way that a tool tip did. So after some research I figured out how to create my own tool tip class.
here's an example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CustomToolTip tip = new CustomToolTip();
tip.SetToolTip(button1, "text");
tip.SetToolTip(button2, "writing");
button1.Tag = Properties.Resources.pelican; // pull image from the resources file
button2.Tag = Properties.Resources.pelican2;
}
}
class CustomToolTip : ToolTip
{
public CustomToolTip()
{
this.OwnerDraw = true;
this.Popup += new PopupEventHandler(this.OnPopup);
this.Draw +=new DrawToolTipEventHandler(this.OnDraw);
}
private void OnPopup(object sender, PopupEventArgs e) // use this event to set the size of the tool tip
{
e.ToolTipSize = new Size(600, 1000);
}
private void OnDraw(object sender, DrawToolTipEventArgs e) // use this to customzie the tool tip
{
Graphics g = e.Graphics;
// to set the tag for each button or object
Control parent = e.AssociatedControl;
Image pelican = parent.Tag as Image;
//create your own custom brush to fill the background with the image
TextureBrush b = new TextureBrush(new Bitmap(pelican));// get the image from Tag
g.FillRectangle(b, e.Bounds);
b.Dispose();
}
}
}
A simple way to do is to hide/show a picture box at specified location. Another method is to load & draw (paint) an image using GDI API.
I know that similar questions have already been asked here before, but they all lead to the same codeproject article that doesn't work. Does anybody know of a working ListBox with icons?
Will a ListView work for you? That is what I use. Much easier and you can make it look just like a ListBox. Also, plenty of documentation on MSDN to get started with.
How to: Display Icons for the Windows Forms ListView Control
The Windows Forms ListView control can display icons from three image
lists. The List, Details, and SmallIcon views display images from the
image list specified in the SmallImageList property. The LargeIcon
view displays images from the image list specified in the
LargeImageList property. A list view can also display an additional
set of icons, set in the StateImageList property, next to the large or
small icons. For more information about image lists, see ImageList
Component (Windows Forms) and How to: Add or Remove Images with the
Windows Forms ImageList Component.
Inserted from How to: Display Icons for the Windows Forms ListView Control
If you don't want to change ListBox to a ListView you can write a handler for DrawItemEvent. for example:
private void InitializeComponent()
{
...
this.listBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox_DrawItem);
...
}
private void listBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index == -1)
return;
// Draw the background of the ListBox control for each item.
e.DrawBackground();
var rect = new Rectangle(e.Bounds.X+10, e.Bounds.Y+8, 12, 14);
//assuming the icon is already added to project resources
e.Graphics.DrawIconUnstretched(YourProject.Properties.Resources.YouIcon, rect);
e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(),
e.Font, Brushes.Black, new Rectangle(e.Bounds.X + 25, e.Bounds.Y + 10, e.Bounds.Width, e.Bounds.Height), StringFormat.GenericDefault);
// If the ListBox has focus, draw a focus rectangle around the selected item.
e.DrawFocusRectangle();
}
you can play around with the rectangle to set the location of the icon right
If you're stuck working in WinForms, then you'll have to owner-draw your items.
See the example for the DrawItem event.
A little different approach - don't use a list box.
Instead of using that control that bounds me to its limited set of properties and methods I am making a listbox of my own.
It's not as hard as it sounds:
int yPos = 0;
Panel myListBox = new Panel();
foreach (Object object in YourObjectList)
{
Panel line = new Panel();
line.Location = new Point(0, Ypos);
line.Size = new Size(myListBox.Width, 20);
line.MouseClick += new MouseEventHandler(line_MouseClick);
myListBox.Controls.Add(line);
// Add and arrange the controls you want in the line
yPos += line.Height;
}
Example for myListBox event handlers - selecting a line:
private void line_MouseClick(object sender, MouseEventArgs)
{
foreach (Control control in myListBox.Controls)
if (control is Panel)
if (control == sender)
control.BackColor = Color.DarkBlue;
else
control.BackColor = Color.Transparent;
}
The code samples above were not tested but the described method was used and found very convenient and simple.
A form with a label and a button 'Options'. By clicking the button a new form opens with 2 radio buttons 'Font1' and 'Font2', and two buttons 'Apply' and 'Cancel'. Upon selecting one of the radio buttons and clicking 'Apply' will make the label on the first form change the font face. The problem is how to change the font as in from say Tahoma to Arial or to any other font face of the label.
Options form code for apply button, which if was clicked will return dialogresult.ok == true and change the font of the label on the first form:
private void btnApply_Click(object sender, EventArgs e)
{
if (radioFont1.Checked)
{
mainForm.lblName.Font.Name = "Arial"; 'wrong attempt
}
this.DialogResult = DialogResult.OK;
}
Declaration of the label on first form so that it is visible to second form:
public static Label lblName = new Label();
...
private void mainForm_Load(object sender, EventArgs e)
{
lblName = lblBarName;
}
Font.Name, Font.XYZProperty, etc are readonly as Font is an immutable object, so you need to specify a new Font object to replace it:
mainForm.lblName.Font = new Font("Arial", mainForm.lblName.Font.Size);
Check the constructor of the Font class for further options.
You can't change a Font once it's created - so you need to create a new one:
mainForm.lblName.Font = new Font("Arial", mainForm.lblName.Font.Size);
You need to create a new Font
mainForm.lblName.Font = new Font("Arial", mainForm.lblName.Font.Size);
I noticed there was not an actual full code answer, so as i come across this, i have created a function, that does change the font, which can be easily modified. I have tested this in
- XP SP3 and Win 10 Pro 64
private void SetFont(Form f, string name, int size, FontStyle style)
{
Font replacementFont = new Font(name, size, style);
f.Font = replacementFont;
}
Hint: replace Form to either Label, RichTextBox, TextBox, or any other relative control that uses fonts to change the font on them. By using the above function thus making it completely dynamic.
/// To call the function do this.
/// e.g in the form load event etc.
public Form1()
{
InitializeComponent();
SetFont(this, "Arial", 8, FontStyle.Bold);
// This sets the whole form and
// everything below it.
// Shaun Cassidy.
}
You can also, if you want a full libary so you dont have to code all the back end bits, you can download my dll from Github.
Github DLL
/// and then import the namespace
using Droitech.TextFont;
/// Then call it using:
TextFontClass fClass = new TextFontClass();
fClass.SetFont(this, "Arial", 8, FontStyle.Bold);
Simple.
this.lblMessage.Font = new Font("arial", this.lblName.Font.Size);