I have a background image, then I want to load several others on top of this. Each image is a png with an alpha channel that has different areas non-transparent.
I placed a PicureBox on a form. Then in the code:
private List<PictureBox> layers = new List<PictureBox>();
for (int l = 0; l < 11; l++)
{
Image i = (Image) Properties.Resources.ResourceManager.GetObject(l.ToString());
PictureBox b = new PictureBox
{
Parent = form_picture,
Image = i,
Dock = DockStyle.Fill,
SizeMode = PictureBoxSizeMode.Zoom,
BackColor = Color.Transparent
};
//b.BringToFront();
layers.Add(b);
}
where "form_picture" is the PictureBox placed on the form, and my resource images are named 0,1,2..10.
It shows only the first image or the last one (removing the comment to the BringToFront method).
It doesn't seem a problem of transparency because I correctly see the background image, but only the first or last opaque area of the upper levels.
I'm afraid I'm not using correctly the properties.
IMO, you shouldn't use pictureboxes at all. They're too expensive for what You're trying to do. Use Graphics.DrawImage instead.
The System.Drawing.Image has a PixelFormat property of type System.Drawing.Imaging.PixelFormat that should help you with the alpha channel.
Related
i am currently trying to put the notes on top of the staff image. However, the notes background are being set to the form background as shown in the image.
image type used is png.
//class music staff
public MusicStaff(int xLoc, int yLoc, int xSize, int ySize)
{
this.SetBounds(xLoc, yLoc, xSize, ySize);
this.Visible = true;
ResourceManager rm = Resources.ResourceManager;
Bitmap bmp = (Bitmap)rm.GetObject("Staff1");
this.BackgroundImage = bmp;
this.BackgroundImageLayout = ImageLayout.Stretch;
this.BackColor = Color.White;
//adding the background pic
panel4 = new MusicStaff(3, 62, 927, 150);
//adding a note
MusicNote p = new MusicNote(pitch, duration, shape, s);
p.SizeMode = PictureBoxSizeMode.StretchImage;
p.BackColor = Color.Transparent;
p.Size = new Size(50, 75);
p.Location = new Point(xCounter + starterX, NoteLocations.c0.mainPoint);
Bitmap myImage = (Bitmap)rm.GetObject(shape);
p.Image = myImage;
You are not really overlaying images. You are overlaying controls with images.
For this to work with transparency, your notes controls need to be nested in the staff control!
As they aren't, the transparency shows the color of their actualy parent, i.e. the form.
Set p.Parent=panel4 and adapt the locations accordingly, i.e. make them relative to the staff..
This is a limitation of winforms transparency, which doesn't support overlapping controls. Nested controls will work fine but only by faking the transparent parts by copying them from the parent..
Note that as a consequence you will not be able to have the notes overlap each other or be overlapped by any other controls.
Often giving up on using controls is the better way; instead one can simply draw all parts that make up the total..
So you could do a series of e.Graphics.DrawImage(noteImg, x, y) in the panel4_Paint event.
I want display an image in my picture box but when I run the code everything else works except the image isn't displayed. Here is the relevant code:
Image[] deadWoman = new Image[5]; //this array will hold the images of bit and pieces of katie
deadWoman[0] = Image.FromFile("F:/Jers Hangman Game/Jers Hangman Game/Resources/katie-hopkins.jpeg");
private void MainPic_Paint(object sender, PaintEventArgs e)
{
Graphics katie = e.Graphics; // creates a graphics object for the picture box
if (numWrongGuesses > 0)
{
e.Graphics.DrawImage(deadWoman[0], 20, 20,60,60);
}
}
I guess the image is never repainted, that's why you don't see it when numWrongGuesses is updated. You should Invalidate() the PictureBox in order to see the update.
I would advise to set the image though, and simply use Visible = true and Visible = false for showing and hiding. You could even set the BackgroundImage if you need to create some overlay effect.
You don't override Paint in order to put an Image object into a PictureBox. Just use the property:
MainPic.Image = deadWoman[0];
You can also do this in the WinForms designer, as long as the Image is a resource.
Also, you can hide and show your image by the .Visible property:
MainPic.Visible = numWrongGuesses > 0;
I draw images (lets say 200x200) on control in C# depending on how many there are (could be over 100) they get drawn offscreen since they are stacked one above the other. What is the best way to make a dynamic scroll so that i can scroll to the ones that are offscreen.
I was thinking of using a Panel and painting them on there and then just place the Panel on the control. But with the panel being transparent and the control on which the panel is sitting is changing its image (its a map that you can move with draging) the panel lags behind when drawing and creates a ugly jitter effect.
So are there any good solutions where i wont need to implement the whole logic of a scroller myself for such a solution?
PictureBox is doublebuffered and will take care of the flicker.
For your case don't draw onto a control, no matter which, but instead draw into a PictureBox's Image.
Put the PictureBox inside an autoscroll panel and make it a large as the Size you need. No jitter, smooth scrolling..
Here is an example. It randomly draws around 200 small images into the Image of a PictureBox. I create the Image with a large size and I put the PB into a Panel:
Random R = new Random();
private void button1_Click(object sender, EventArgs e)
{
panel1.AutoScroll = true;
pictureBox1.Parent = panel1;
pictureBox1.Location = Point.Empty;
pictureBox1.Image = new Bitmap(3000, 500);
pictureBox1.ClientSize = pictureBox1.Image.Size;
var imgFiles = Directory.GetFiles(#"D:\scrape\", "*.png");
foreach(string file in imgFiles)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
using (Bitmap bmp = new Bitmap(file))
{
if (bmp.Size.Width < 300)
{
for (int i = 0; i < 10; i++ )
G.DrawImage(bmp, R.Next(2500), R.Next(400));
}
}
}
}
You can easily adapt it to your own project, I'm sure..
i am trying to move a image in picture box. i added panel to my application and also added picture box in panel. i opened an image.if the image size is big.i want to see the particular portion of image. so how can i move the image up and down (without using scroll bars) to see the particular portion of image?
You can add controls like move left, move right, move up, move down with associated actions to move the image within your picturebox. An example of how to do this for moving the image to the right is shown below. You can implement these action with mouse down and mouse up events so that the user just presses the appropriate buttons to move the picture as he wants. Also note that once you reach the maximum dimensions of the image, you can change the rectangular region to that within image bounds.
int ff = 0; //number of positions to move
Bitmap b2;
private void button1_Click(object sender, EventArgs e)
{
if (ff == 0) { b2 = new Bitmap(pictureBox1.Image);} //original image as bitmap b2
Bitmap b1 = new Bitmap(pictureBox1 .Width ,pictureBox1.Height ); //new bitmap with rectangular region of original image
Rectangle r1 = new Rectangle(ff++, 0, pictureBox1.Width, pictureBox1.Height );
Graphics g = Graphics.FromImage(b1);
g.DrawImage(b2, 0, 0, r1, GraphicsUnit.Pixel);
g.Dispose();
pictureBox1.Image = null;
pictureBox1.Image = (Image)b1;
pictureBox1.Refresh();
}
Not sure if it really answers your question, but this seems like a fun reason to play with Reactive Extensions (Rx). This video demonstrates nicely how well this stuff works with asynchronous events like mouse-input.
I have a picturebox with a png in it. Yet even when I set the BackColor to Transparent, it is not transparent. Any ideas what might be wrong? :)
Thanks!
I have also faced the problem regarding transparent pictures.
you have to Draw it through code.
See my question A PictureBox Problem
EDIT:
In paint event (Control containing Background Image)
write this
//If added your image in project's resources get from there OR your Image location
Image img = yourNamespace.Properties.Resources.yourPicture;
e.Graphics.DrawImage(img,50,50,100,100);
Your PNG file should also have the transparent background. This is can be done while creating the image(png) files.
You really have to draw it through code. Place a pictureBox on your form, set sizeMode and docking as you like. Then you may fire the following function on the pictureBox's PAINT event:
public void LogoDrawTransparent(PaintEventArgs e)
{
// Create a Bitmap object from an image file.
Image myImg;
Bitmap myBitmap;
try
{
myImg = cls_convertImagesByte.GetImageFromByte(newImg);
myBitmap = new Bitmap(myImg); // #"C:\Temp\imgSwacaa.jpg");
// Get the color of a background pixel.
Color backColor = myBitmap.GetPixel(0, 0); // GetPixel(1, 1);
Color backColorGray = Color.Gray;
Color backColorGrayLight = Color.LightGray;
Color backColorWhiteSmoke = Color.WhiteSmoke;
Color backColorWhite = Color.White;
Color backColorWheat = Color.Wheat;
// Make backColor transparent for myBitmap.
myBitmap.MakeTransparent(backColor);
// OPTIONALLY, you may make any other "suspicious" back color transparent (usually gray, light gray or whitesmoke)
myBitmap.MakeTransparent(backColorGray);
myBitmap.MakeTransparent(backColorGrayLight);
myBitmap.MakeTransparent(backColorWhiteSmoke);
// Draw myBitmap to the screen.
e.Graphics.DrawImage(myBitmap, 0, 0, pictureBox1.Width, pictureBox1.Height); //myBitmap.Width, myBitmap.Height);
}
catch
{
try { pictureBox1.Image = cls_convertImagesByte.GetImageFromByte(newImg); }
catch { } //must do something
}
}
This is my class that is referenced in the above function:
class cls_convertImagesByte
{
public static Image GetImageFromByte(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
public static byte[] GetByteArrayFromImage(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
Thanks. chagbert.
From what I learned I can't do it within a windows form, as it doesn't have layers for the images. So guess will have to make it as WPF. :)
How did you create the background? Is that set by setting the Form.BackgroundImage?
If that background (the paper like image) is a container control, the transparency should just work.
However, If you are placing two PictureBox objects on top of eachother this doesn't work. The transparent area takes on the color of its parent object. If you have two PictureBox objects they both will have the Form as their parent. If this is your situation, it can be solved by setting the transparent image's Parent property to be the background image.
private void Form1_Load(object sender, EventArgs e)
{
transparentPictureBox.Parent = backgroundPictureBox;
}
When changing the Parent property, the Location of the tranparentPictureBox will become relative to its new parent. You'd have to subtract the x and y coordinates of the background image from the transparent image. See my answer on A PictureBox Question for an example with a screen shot.
AFAIK, you can not set the Parent in the Designer, only in code. Therefore, the Designer will still not show a transparent image, but at runtime it should.
The same problem occurs if you place a transparent Label on top of a PictureBox object.