picturebox Control is not working C# .NET (Visual Studio) - c#

I'm doing a Piano Keyboard which also has a Music Staff with it so that when you press a Key on the Keyboard, according to the duration a music note (crotchet, semi-breve etc) pops up on the Music Staff.
I have a Form (called Form1) which in it it has a Panel (Panel1) which contains the Keyboard Keys made of Buttons. I also have a Music Staff made of a PictureBox which holds the staff (or stave don't know what it's called) and a Test Text Box which holds the pitches (basically the note played as they are mapped)
The problem is this. I need to make the music notes show on the staff (pictureBox1) so in Form1 which is acting as the main class but whenever I write
mn = new MusicNote (nPos,nPitch, duration,nShape);
pictureBox1.Controls.Add(this.mn);
pictureBox1.Controls[pictureBox1.Controls.Count - 1].BringToFront(); //Bring the notes OVER the Stave
It basically doesn't work BUT when I replace every pictureBox1 with just this OR panel1 (e.g.)
this.Controls.Add(this.mn);
it shows the Music Note either on the FORM1 (the grey space) or on the Keyboard itself (see further down to see the Keyboard). The problem is that with this, it doesn't actually adds to the PictureBox but to the Form1/Panel
Do you have any idea how to fix this and make the music Notes actually PART of the PictureBox1? because I also need some methods to work on that pictureBox like when I click one of the Notes they actually play that sound with that duration (in which I still need to figure out how to pass the Controls From Form1.cs to MusicNote.cs)
Part of the coding for MusicNote.cs which has to do with the "adding" of the image is this below:
public class MusicNote : PictureBox
{
public int pitch;
public int duration;
public string noteShape;
string nShape;
bool isDragging = false;
public string rootFolder = #"..\..\\bin\\Debug\\images\\";
ArrayList al = new ArrayList();
SoundPlayer sp = new SoundPlayer();
Timer t1 = new Timer();
public MusicNote(int x, int mPitch, int mDuration,string nShape)
: base()
{
pitch = mPitch;
duration = mDuration;
noteShape = nShape;
Location = new Point(x, 100);
this.Size = new Size(35, 40);
//--------- Get the Image of Note ----------
Bitmap bmp = new Bitmap(#rootFolder + nShape + ".bmp");
this.Image = bmp;
this.BackColor = Color.Transparent;
//-------Mouse Events-------
this.MouseDown += new MouseEventHandler(StartDrag);
this.MouseUp += new MouseEventHandler(StopDrag);
this.MouseMove += new MouseEventHandler(NoteDrag);
}
etc
...
...
...
}
Form1.cs Coding (posting all as all are connected from one method to another)
The Problem lies in private void onMouseUp (object sender, MouseEventArgs e) which is the last method
using System;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Media;
using System.Collections;
namespace Piano
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Objects of Music Note, Piano Keys, and all variables surronding the Keyboard and Notes
WhiteKey wk;
BlackKey bk;
public int pitch;
public int duration = 0;
string nShape = "";
public const int xOff = 35;
int count = 0;
int nPos = 0;
public string rootFolder = #"..\..\\bin\\Debug\\images\\";
MusicNote mn;
MusicStaff ms;
SoundPlayer sp = new SoundPlayer();
Stopwatch sw = new Stopwatch();
//--------------- White and Black Keys Creation both Buttons and Position------------------
public int[] wKeys = { 1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18, 20, 22, 24, 25 }; //White Keys notes numbers (pitch)
public int[] bKeys = { 0, 2, 0, 4, 0, 0, 7, 0, 9, 0, 11, 0, 0, 14, 0, 16, 0, 0, 19, 0, 21, 0, 23, 0, 0 }; //Black Keys notes numbers (pitch)
int[] wPos = { 35, 70, 105, 140, 175, 210, 245, 280, 315, 350, 385, 420, 455, 490, 525 }; // Position of White Keys on the Panel
int[] bPos = { 0, 57, 0, 92, 0, 0, 162, 0, 197, 0, 232, 0, 0, 302, 0, 337, 0, 0, 407, 0, 442, 0, 477, 0, 1 }; //Position of the Black Keys in the Panel
private void Form1_Load(object sender, System.EventArgs e)
{
for (int i = 0; i < 15; i++)
{
WhiteKey wk = new WhiteKey(wKeys[i], wPos[i]-35,0); //create a new white Key with [i] Pitch, at that x position and at y =0 position
wk.MouseDown += onMouseDown; //Plays the Key and starts Timer
wk.MouseUp += onMouseUp; // Holds the data like Time and shape and so
this.panel1.Controls.Add(wk); //Give it control (to play and edit)
}
for (int i = 0; i < 25; i++) //same for the Black Keys but instead we use 25 keys and those denoted at 0 are where the WHITE KEYS should be placed
{
if (bKeys[i] != 0)
{
//Same as above but for Black Key which is inherits from WhiteKey
bk = new BlackKey(bKeys[i], bPos[i]-35, 0);
bk.MouseDown += onMouseDown;
bk.MouseUp += onMouseUp;
this.panel1.Controls.Add(bk);
this.panel1.Controls[this.panel1.Controls.Count - 1].BringToFront(); //Make the Black Keys show OVER the white
}
}
}
//Method showing what happens when you do a MouseDown Event
private void onMouseDown(object sender, MouseEventArgs e)
{
wk = sender as WhiteKey; //gets the WhiteKey Controls
pitch = wk.pitch; //assign pitch
sp.SoundLocation = #"..\\..\\bin\\Debug\\sound\\mapped\\" + pitch + ".wav"; //find that pressed note
sp.Play(); //play it
sw.Reset(); //Reset Stop Watch
sw.Start(); //Start Time
}
private void timeTick(object sender, EventArgs e)
{
duration++;
}
private void onMouseUp (object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
sw.Stop(); //Stop time
duration = (int)sw.ElapsedMilliseconds / 100;
textBox.Text += (string)(pitch + " , "); //add the Pitch used to the textbox
// Will determine the Music Note Image
if (duration >= 0 && duration < 2)
{
nShape = "Quaver";
}
else if (duration >= 2 && duration < 5)
{
nShape = "Crotchet";
}
else if (duration >= 5 && duration < 8)
{
nShape = "minim";
}
else if (duration >= 8 && duration < 10)
{
nShape = "DotMin";
}
else if (duration >= 10)
{
nShape = "SemiBreve";
}
count++; //will help Determine the 'x' coordiante of the Music Note
nPos = xOff * count; //moves the x-coordinate by 35 pixels each note
mn = new MusicNote(nPos,pitch,duration,nShape); //Creation of a new MusicNote
pictureBox1.Controls.Add(this.mn); //PROBLEM --- Doesn't add to the PictureBox (Does Nothing)
pictureBox1.Controls[pictureBox1.Controls.Count - 1].BringToFront(); //Brought to front of stave to make sure it doesn't get hidden in background
}
}
}
}
Any Idea how I can add CONTROL to the PictureBox1 and make the Music Note Show? Because I managed to make it Show on the Form1 and the Panel1 but failed on a pictureBox
How the Piano Looks with music notes on FORM1
According to the Visual Studio DEBUGGER [Piano.Form1]
http://postimg.org/image/vdu0x1gv1/
N.B Sorry for the long post but I don't know exactly how to explain the problem.

I think the Program was just messing with me.. I tried changing something to png and back to bmp and Now it's working perfectly.. I do not know why but It's the same Code there is up there
Thanks to those who have seen the question.

To play sound in picture box do this
[DllImport("winmm.dll")]
private static extern bool PlaySound(string lpszName, int hModule, int dwFlags);
and PlaySound("your sound loc ", 1, 0x0011);

Related

Placing buffered matrix rotated graphic on a fixed image

I am trying to put a movable needle (pointer) on a fixed graphic of a gauge (meter). The needle is moved by using a matrix rotate on a buffered graphics. I can get the fixed graphic and the needle to show. But when I render to the screen the last placed image deletes the prior graphic. I am using a timer to get the needle animation and a track bar input to produce the movement. The needle does the exact movement I am looking for.
I just cannot get the fixed background and needle to appear at the same time.
Any ideas?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Dial01
{
public partial class dial01Form : Form
{
// Establishes timer for graphics animation
private Timer timer01 = new Timer();
/* Establishes a graphic buffer to write to
* prior display on screen */
private Graphics myGraphics;
private BufferedGraphics myBufferedGraphics1;
// Establishes manager for embedded resources (Images)
private System.Resources.ResourceManager myRM = new
System.Resources.ResourceManager("Resources.resx",
System.Reflection.Assembly.GetExecutingAssembly());
int y = 0; // Rotation value
Graphics g,g1; // Graphics objects
public dial01Form()
{
// Establishes size of Dial01Form
this.Width = 500;
this.Height = 500;
// Gets reference to the current BufferedGraphicsContext
BufferedGraphicsContext myContext1 = BufferedGraphicsManager.Current;
// Specifically sets maximum buffer size
myContext1.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
// Sets the buffer size
myBufferedGraphics1 = myContext1.Allocate(this.CreateGraphics(),
new Rectangle(0, 0, this.Width, this.Height));
// Actvates timer and sets interval
timer01.Enabled = true;
timer01.Tick += onTimer;
timer01.Interval = 20;
timer01.Start();
// Initializes form components
InitializeComponent();
}
private void onTimer(object sender, System.EventArgs e)
{
myGraphics = this.CreateGraphics();
// Initializes graphics buffer variable
g1 = myBufferedGraphics1.Graphics;
// Clears graphic buffer with a color
g1.Clear(SystemColors.Control);
// Initializes an image variable for Dial Outline
Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250;
// Draw Dial Outline to graphics buffer
myGraphics.DrawImage(dial01Outline, (ClientSize.Width / 2) - 100,
(ClientSize.Height / 2) - 100);
// Goto drawPointer method passing trackBar1 value
drawPointer(trackBar1.Value);
// Render buffered graphics to screen
// myBufferedGraphics.Render(Graphics.FromHwnd(this.Handle));
myBufferedGraphics1.Render();
}
public int drawPointer(int trkBarValue)
{
int x = trkBarValue;
y = 0;
if (225 + x <= 360) { y = 222 + x; }
else if (225 + x > 360) { y = x - 135; }
// These two labels are for testing purposes
label1.Text = ("Trk Bar Val = " + x).ToString();
label2.Text = ("Ptr value = " + y).ToString();
y = y + 180;
// Matrix rotation to pointer
Matrix myMatrix = new Matrix();
myMatrix.Rotate(y, MatrixOrder.Append);
myMatrix.Translate(this.ClientSize.Width / 2,
this.ClientSize.Height / 2, MatrixOrder.Append);
g1.Transform = myMatrix;
// Pointer polygon
PointF point1 = new PointF(0.0F, 0.0F);
PointF point2 = new PointF(0.0F, 50.0F);
PointF point3 = new PointF(3.0F, 55.0F);
PointF point4 = new PointF(7.0F, 50.0F);
PointF point5 = new PointF(7.0F, 0.0F);
PointF[] polyPoints =
{
point1,
point2,
point3,
point4,
point5
};
g1.FillPolygon(Brushes.Black, polyPoints);
return y;
}
private void dial01Form_Load(object sender, EventArgs e)
{
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
}
}
}
The general graphics approach you've taken is not appropriate for a winforms app.
The way graphics works in winforms, whenever the form is covered/uncovered/resized/etc, Windows tells it to repaint itself. Anything you've done with CreateGraphics will be overwritten at this point. This is why you shouldn't call CreateGraphics.
Instead, you should intercept the repainting process via the Paint event, and do all your custom painting there. You can still repaint on a timer, you just call Invalidate() inside the timer, which causes the form to repaint as soon as it can.
This is the general shape of the "right way" to do it:
public partial class dial01Form : Form
{
private Timer timer01 = new Timer();
int y = 0; // Rotation value
public dial01Form()
{
// Establishes size of Dial01Form
this.Width = 500;
this.Height = 500;
// Actvates timer and sets interval
timer01.Enabled = true;
timer01.Tick += onTimer;
timer01.Interval = 20;
timer01.Start();
// handle the paint event
this.Paint += OnPaint;
// Initializes form components
InitializeComponent();
}
private void OnPaint(object sender, PaintEventArgs e)
{
// all painting here, targeting e.Graphics
e.Graphics.Clear(SystemColors.Control);
Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250;
e.Graphics.DrawImage(dial01Outline, (ClientSize.Width / 2) - 100,
(ClientSize.Height / 2) - 100);
drawPointer(e.Graphics, trackBar1.Value);
}
private void onTimer(object sender, System.EventArgs e)
{
this.Invalidate();
}
public int drawPointer(Graphics g1, int trkBarValue)
{
// elided: same code as before, but using the g1 parameter instead of a field
}
}
You shouldn't have problems with flickering, I think - double-buffering is enabled by default. Make sure your form's DoubleBuffered property is set to True though.

How to move PictureBox in TableLayoutPanel grid from keyboard?

I'm quite new at C#, but I'm trying to move a picturebox, by pressing the up-down-left-right keys from the keyboard, in a grid TableLayoutPanel(I made the grid at runtime). The grid is 23x23, has brickblock images border(each cell at the border contains a brickblock image in an imagebox) and an imagebox with a mouse in the middle. What I'm trying to do is moving the mouse image from the central cell(which is 11x11) in another cell by pressing one of the control keys mentioned above. It seems I can't get a grip on the idea of eventHandler... . The code works very good 'till I want to make the picturebox move. I've put the whole code, maybe the problem is in a place I didn't notice, but I think that the problem is KeyDown += new KeyEventHandler(Form2_KeyDown) or/end private void Form2_KeyDown(object sender, KeyEventArgs e){...} .
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace IndividualProject
{
public partial class Form2 : Form
{
PictureBox picturebox5 = new PictureBox
{
Visible = true,
Anchor = AnchorStyles.Top,
SizeMode = PictureBoxSizeMode.Normal,
Dock = DockStyle.Fill,
Margin = new Padding(0)
};
public Form2()
{
InitializeComponent();
// MaximizeBox = false;
//size
int h = Screen.PrimaryScreen.WorkingArea.Height / 2;
int w = Screen.PrimaryScreen.WorkingArea.Width / 2;
Size = new Size(w / 2 + w / 7, h + h / 4 + h / 7);
//location
StartPosition = FormStartPosition.CenterScreen;
//form style
FormBorderStyle = FormBorderStyle.FixedSingle;
//menuStrip1.BackColor = Color.Beige;
//lives and score container
#region livesAndScore
lasContainer.Size = new Size(Width / 2 + Width / 3 + Width / 7, Height / 13);
lasContainer.BackColor = Color.Lavender;
lasContainer.BorderStyle = BorderStyle.Fixed3D;
lasContainer.Dock = DockStyle.Top;
lasContainer.SplitterDistance = Width / 2 - Width / 69;
//labels
lives.Location = new Point(lasContainer.Panel1.Width / 12, lives.Height / 2);
score.Location = new Point(lasContainer.Panel2.Width / 12, score.Height / 2);
//picturebox
live3.Location = new Point(lasContainer.Panel1.Width / 3, lives.Height / 2);
live2.Location = new Point(lasContainer.Panel1.Width / 2, lives.Height / 2);
live1.Location = new Point(lasContainer.Panel1.Width / 2 + lasContainer.Panel1.Width / 6, lives.Height / 2);
#endregion livesAndScore
//gamePanel
gamePanel.Dock = DockStyle.Fill;
gamePanel.BackColor = Color.SkyBlue;
gamePanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single; // REMOVE WHEN FINISHED !!!!!!!!!!!
//making the grid
#region grid
gamePanel.ColumnCount = 23;
gamePanel.RowCount = 23;
gamePanel.ColumnStyles.Clear();
gamePanel.RowStyles.Clear();
int iIndex, jIndex = 0;
for (iIndex = 0; iIndex < gamePanel.ColumnCount; iIndex++)
{
gamePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 4.34F));
gamePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 4.34F));
}
#endregion grid
while(jIndex < gamePanel.ColumnCount)
{
#region picturebox1
PictureBox picturebox1 = new PictureBox
{
Visible = true,
Anchor = AnchorStyles.Top,
SizeMode = PictureBoxSizeMode.Normal,
BackColor = Color.Sienna,
Dock = DockStyle.Fill,
Margin = new Padding(0)
};
if(jIndex < gamePanel.ColumnCount - 1)
{
gamePanel.Controls.Add(picturebox1, jIndex, 0);
picturebox1.ImageLocation = #"..\..\ResourcesPh\brickblock.png";
}
#endregion picturebox1
#region picturebox2
PictureBox picturebox2 = new PictureBox
{
Visible = true,
Anchor = AnchorStyles.Top,
SizeMode = PictureBoxSizeMode.Normal,
BackColor = Color.Sienna,
Dock = DockStyle.Fill,
Margin = new Padding(0)
};
if (jIndex < gamePanel.ColumnCount - 1)
{
gamePanel.Controls.Add(picturebox2, 0, jIndex + 1);
picturebox2.ImageLocation = #"..\..\ResourcesPh\brickblock.png";
}
#endregion picturebox2
#region picturebox3
PictureBox picturebox3 = new PictureBox
{
Visible = true,
Anchor = AnchorStyles.Top,
SizeMode = PictureBoxSizeMode.Normal,
BackColor = Color.Sienna,
Dock = DockStyle.Fill,
Margin = new Padding(0)
};
if(jIndex < gamePanel.ColumnCount - 1)
{
gamePanel.Controls.Add(picturebox3, gamePanel.ColumnCount - 1 - jIndex, gamePanel.RowCount - 1);
picturebox3.ImageLocation = #"..\..\ResourcesPh\brickblock.png";
}
#endregion picturebox3
#region picturebox4
PictureBox picturebox4 = new PictureBox
{
Visible = true,
Anchor = AnchorStyles.Top,
SizeMode = PictureBoxSizeMode.Normal,
BackColor = Color.Sienna,
Dock = DockStyle.Fill,
Margin = new Padding(0),
};
if(jIndex < gamePanel.ColumnCount - 1)
{
gamePanel.Controls.Add(picturebox4, gamePanel.ColumnCount - 1, gamePanel.RowCount - 1 - jIndex - 1);
picturebox4.ImageLocation = #"..\..\ResourcesPh\brickblock.png";
}
#endregion picturebox4
jIndex++;
}
//the starting point of the mouse
#region mouseStartPoint
//PictureBox picturebox5 = new PictureBox
//{
// Visible = true,
// Anchor = AnchorStyles.Top,
// SizeMode = PictureBoxSizeMode.Normal,
// BackColor = Color.Sienna,
// Dock = DockStyle.Fill,
// Margin = new Padding(0)
//};
gamePanel.Controls.Add(picturebox5, 11, 11);
picturebox5.ImageLocation = #"..\..\ResourcesPh\mouse.png";
#endregion mouseStartPoint
KeyDown += new KeyEventHandler(Form2_KeyDown);
}
private void Form2_KeyDown(object sender, KeyEventArgs e)
{
int x = 11, y = 11;
if (e.KeyCode == Keys.Right)
x += 1;
if (e.KeyCode == Keys.Left)
x -= 1;
if (e.KeyCode == Keys.Up)
y -= 1;
if (e.KeyCode == Keys.Down)
y += 1;
gamePanel.Controls.Remove(picturebox5);
gamePanel.Controls.Add(picturebox5, x, y);
picturebox5.ImageLocation = #"..\..\ResourcesPh\mouse.png";
Refresh();
}
private void howToPlayToolStripMenuItem_Click(object sender, EventArgs e)
{
Hide();
Form3 f3 = new Form3();
f3.FormClosed += (s, args) => Close(); //event handler on closing Form2 after Form3 is opened
f3.Show();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
TableLayoutPanel Grid
You are always setting the starting position back to 11, 11 on every key click. Move your declaration outside of that scope:
int x = 11, y = 11;
private void Form2_KeyDown(object sender, KeyEventArgs e) {
Here's a greatly simplified approach for moving your mouse, I get straight to the point and kept things to a bare minimum, yet effective :D
Here are the tiles I've used:
And here's the code !
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
private Dictionary<int, Image> _dictionary;
private Size _imageSize;
private int[] _level;
private Size _levelSize;
private Point _mousePos;
public Form1()
{
InitializeComponent();
pictureBox1.Paint += PictureBox1_Paint;
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeLevel();
Redraw();
}
private void InitializeLevel()
{
var imageEmpty = Image.FromFile("empty.png");
var imageMouse = Image.FromFile("mouse.png");
var imageWall = Image.FromFile("wall.png");
_level = new[]
{
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 1, 1, 1, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0
};
_levelSize = new Size(5, 5);
_imageSize = new Size(25, 25);
_dictionary = new Dictionary<int, Image>();
_dictionary.Add(0, imageWall);
_dictionary.Add(1, imageEmpty);
_dictionary.Add(2, imageMouse);
_mousePos = new Point();
}
private void Redraw()
{
pictureBox1.Invalidate();
}
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
var graphics = e.Graphics;
graphics.Clear(Color.Transparent);
// draw level
var i = 0;
foreach (var tile in _level)
{
var x = i % _levelSize.Width;
var y = i / _levelSize.Width;
var image = _dictionary[tile];
graphics.DrawImage(image, new Point(x * _imageSize.Width, y * _imageSize.Height));
i++;
}
// draw hero !
graphics.DrawImage(_dictionary[2], _mousePos);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
var up = keyData == Keys.Up;
var down = keyData == Keys.Down;
var left = keyData == Keys.Left;
var right = keyData == Keys.Right;
var processed = up || down || left || right;
if (!processed) return base.ProcessCmdKey(ref msg, keyData);
// move the hero !
var x = 0;
var y = 0;
if (left) x--;
if (right) x++;
if (up) y--;
if (down) y++;
_mousePos.X += x;
_mousePos.Y += y;
Redraw();
return true;
}
}
}
Obviously you'll still want to check collisions, define your logic and such ...
Go on and give it a try !
Welcome to SO and good luck :D

Apply custom shape to any image

I need to apply a custom shape (this, a .jpg) to any image I load into my application, using Windows Forms if possible (since my whole project is made in Winforms), but I guess I can use WPF if it's needed.
So for example if I have a photo like this, the result should be like this (I made this with Photoshop for you to see), maybe even without the white borders if possible (please note that the image was resized and centered to fit the custom shape, and that's how it should be).
I can't figure out how to do this, but from what I've searched I suppose it has something to do with brushes (TextureBrush, ImageBrush, etc).
Regards.
it seems to me that you want to apply a mask, you could do it with something like this (using /unsafe code):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace testImageBlender
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap imBase;
Bitmap imMask,imMask2;
Bitmap blendedImage;
private void Form1_Load(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
imBase = new Bitmap(openFileDialog1.FileName);
imMask = new Bitmap(openFileDialog2.FileName);
blendedImage = new Bitmap(openFileDialog2.FileName);
blendImage();
}
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (imBase != null)
{
if (imMask != null)
{
if (blendedImage != null)
{
e.Graphics.DrawImage(blendedImage, e.ClipRectangle);
}
}
}
}
private void blendImage()
{
Rectangle mRec = new Rectangle(0, 0, imMask.Width, imMask.Height);
float intensity = 0;
//playing around with images to get pixel format 24bpp RGB, most probably a very bad way of doing it, but I don't know enough about image format and lockbits to do it nice and clean yet
imMask2 = new Bitmap(imMask);
Graphics.FromImage(imBase).DrawImage(imBase, 0, 0, imMask.Width, imMask.Height);
Graphics.FromImage(blendedImage).DrawImage(imMask, 0, 0, imMask.Width, imMask.Height);
Graphics.FromImage(imMask2).DrawImage(imMask, 0, 0, imMask.Width, imMask.Height);
BitmapData imageData = imBase.LockBits(mRec, ImageLockMode.ReadOnly, imBase.PixelFormat);
BitmapData maskData = imMask2.LockBits(mRec, ImageLockMode.ReadOnly, imMask.PixelFormat);
BitmapData blendedData = blendedImage.LockBits(mRec, ImageLockMode.WriteOnly, blendedImage.PixelFormat);
unsafe
{
byte* imagePointer = (byte*)imageData.Scan0;
byte* maskPointer = (byte*)maskData.Scan0;
byte* blendedPointer = (byte*)blendedData.Scan0;
for (int i = 0; i < mRec.Height; i++)
{
for (int j = 0; j < mRec.Width; j++)
{
intensity = 1-((float)(maskPointer[0] + maskPointer[1] + maskPointer[2])) / ((float)3 * 255);
for (int k = 0; k < 3; k++)
{
blendedPointer[k] = (intensity>0.8)?(byte)((float)imagePointer[k]):(byte)255;
}
// 3 bytes per pixel
imagePointer += 3;
maskPointer += 3;
blendedPointer += 3;
}
// Moving the pointers to the next pixel row
imagePointer += imageData.Stride - (mRec.Width * 3);
maskPointer += maskData.Stride - (mRec.Width * 3);
blendedPointer += blendedData.Stride - (mRec.Width * 3);
}
}
imBase.UnlockBits(imageData);
imMask2.UnlockBits(maskData);
blendedImage.UnlockBits(blendedData);
}
}
}
this is very much inspired by Balazs Tihanyi answers on Draw image on top of another image with blending mode color
Here is an example tuned for the image you linked to:
using (var source = (Bitmap) Image.FromFile(#"image filename"))
{
using (var target = new Bitmap(source.Width, source.Height))
{
using (var graphics = Graphics.FromImage(target))
{
using (var path = new GraphicsPath())
{
path.StartFigure();
path.AddLine(161, 665, 223, 624);
path.AddLine(223, 624, 252, 568);
path.AddLine(252, 568, 239, 525);
path.AddLine(239, 525, 200, 432);
path.AddLine(200, 432, 178, 343);
path.AddLine(178, 343, 156, 198);
path.AddLine(156, 198, 161, 131);
path.AddLine(161, 131, 248, 38);
path.AddLine(248, 38, 366, 4);
path.AddLine(366, 4, 657, 10);
path.AddLine(657, 10, 735, 70);
path.AddLine(735, 70, 741, 195);
path.AddLine(741, 195, 746, 282);
path.AddLine(746, 282, 762, 410);
path.AddLine(762, 410, 730, 498);
path.AddLine(730, 498, 686, 582);
path.AddLine(686, 582, 727, 669);
path.CloseFigure();
graphics.Clip = new Region(path);
}
graphics.DrawImage(source, 0, 0);
}
this.PictureBox.Image = new Bitmap(target);
}
}

Drawn shape in Picturebox doesn't clear

I am trying to show a train that moves on the map .so let me explain my method ,i draw my map on Picturebox Map,and my trains on another picturebox train,i put the Train PictureBox on map picturebox .
More details:https://stackoverflow.com/a/9158849/2538037
So i use two function here :
public void DrawMap()
{
var graph = Graphics.FromImage(map);
List<Point> lstPointLeft = new List<Point>();
foreach (var t in lstSensorLeft)
{
Point objPoint = new Point(t.XLocation, t.YLocation);
lstPointLeft.Add(objPoint);
Rectangle rectSens = new Rectangle(t.XLocation, t.YLocation, 3, 3);
try
{
graph.FillRectangle(whiteBrush, rectSens);
}
catch (Exception ea)
{
}
if (t.StationId != null)
{
Rectangle rectEhsansq = new Rectangle(t.XLocation - 6, t.YLocation - 6, 12, 12);
graph.FillRectangle(blueBrush, rectEhsansq);
graph.DrawString(ObjStationRepository.FindBy(i => i.Id == t.StationId).First().Name, pictureBoxMetroMap.Font, Brushes.White, t.XLocation +40, t.YLocation +50);
}
}
List<Point> lstPointRight = new List<Point>();
foreach (var t in lstSensorRight)
{
Point objPoint = new Point(t.XLocation + 30, t.YLocation + 30);
lstPointRight.Add(objPoint);
Rectangle rectSens = new Rectangle(t.XLocation + 30, t.YLocation + 30, 3, 3);
graph.FillRectangle(whiteBrush, rectSens);
if (t.StationId != null)
{
Rectangle rectPosition = new Rectangle(t.XLocation + 24, t.YLocation + 24, 12, 12);
graph.FillRectangle(blueBrush, rectPosition);
graph.DrawString(ObjStationRepository.FindBy(i => i.Id == t.StationId).First().Name, pictureBoxMetroMap.Font, Brushes.White, t.XLocation - 50, t.YLocation - 30);
}
}
graph.DrawLines(pLine, lstPointLeft.ToArray());
graph.DrawLines(pLine, lstPointRight.ToArray());
pictureBoxMetroMap.Image = map;
}
This function draws map ,and this function draws my trains on another picturebox:
public void DrawOnlineTrain()
{
var graph = Graphics.FromImage(map);
if (OnlineTrainList.Count > 0)
{
foreach (OnlineTrain t in OnlineTrainList.ToList())
{
// graph.Dispose();
Rectangle rectTrainState = new Rectangle(t.XTrainLocation.Value - 3,
t.YTrainLocation.Value - 3,
7, 7);
graph.FillRectangle(RedBrush, rectTrainState);
}
}
pictureBoxonlineTrain.Image = map;
}
So i use a thread to update the Train picturebox ,i call the thread in form_load :
private void frmMain_Load(object sender, EventArgs e)
{
pictureBoxonlineTrain.Parent = pictureBoxMetroMap;
map= new Bitmap(pictureBoxMetroMap.Size.Width, pictureBoxMetroMap.Size.Height);
UpdateListBox = new UpdateListBoxDelegate(this.UpdateStatus);
// Initialise and start worker thread
workerThread = new Thread(new ThreadStart(this.GetOnlineTrain));
workerThread.Start();
}
So in the thread i start a method that gets the location of online train:
public void GetOnlineTrain()
{
while(true)
{
OnlineTrainRepository objOnlineTrainRepository = new OnlineTrainRepository();
OnlineTrainList = objOnlineTrainRepository.GetAll().ToList();
objOnlineTrainRepository = null;
Invoke(UpdateListBox);
}
}
Here i start UpdateListBox that draw my Train:
private void UpdateStatus()
{
foreach (OnlineTrain onlineTrain in OnlineTrainList.ToList())
{
lstLog.Items.Add("Train Id=" + onlineTrain.TrainId + " | Current x position=" + onlineTrain.XTrainLocation + " | Current y position=" + onlineTrain.YTrainLocation);
pictureBoxonlineTrain.Image = null;
DrawOnlineTrain();
}
}
As you can see here to show movement i have to clear the old location of trains ,and i do that using :
pictureBoxonlineTrain.Image = null;
But it doesn't work ,and every rectangle is remain on my screen ?!!!
Best regards
1. To address your problem directly
you never clear the bitmap! Note that you are drawing on top of everything that is already there when using Graphics.FromImage
you use one and the same Bitmap object for all drawing. So (in combination with the previous point) you basically have the entire "scene" in map all the time - no need to have several PictureBoxes in that case!
be careful: if a PictureBox refresehes while you're drawing, the unfinished state will be visible! You are manipulating the very image that is shown.
2. What I would do
render everything to one buffer (you are using Bitmap which is fine, but maybe consider using BufferedGraphics)
render that to a control whenever you like (or it's Paint event fires) instead of using a PictureBox

how to generate cubes randomly in opengl / c#

I'm trying to build a game 'blocks' which sees the matches cubes and delete them.
This code makes two cubes and moves them along the y-axis. Then, it supposed to disappear and 100 cube in different places to appear. My problem is I don't know how to make the cubes look disappearing nor how to write the function 'cube generation' , I'm writing in 3d.
Any help of what should I do.
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 Tao.OpenGl;
using System.Threading;
using Tao.FreeGlut;
namespace TAOSample
{
class VertexDania{
double vx, vy , vz;
public double X{
get{return vx;}
set{ vx = value;}
}
public double Y{
get{return vy;}
set{ vy = value;}
}
public double Z{
get{return vz;}
set{ vz = value;}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
simpleOpenGlControl1.InitializeContexts();
Gl.glClearColor(1, 1, 0, 0);
Gl.glClearDepth(1.0);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluPerspective(45, simpleOpenGlControl1.Height /(double)simpleOpenGlControl1.Width, 0.1, 1000);
Gl.glViewport(0, 0, simpleOpenGlControl1.Width, simpleOpenGlControl1.Height);
Tao.FreeGlut.Glut.glutInit();
}
private void simpleOpenGlControl1_Paint(object sender, PaintEventArgs e)
{
Gl.glEnable(Gl.GL_LIGHTING);
Gl.glEnable(Gl.GL_LIGHT0);
Gl.glEnable(Gl.GL_COLOR_MATERIAL);
Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();
VertexDania[] points = new VertexDania[]
{
new VertexDania{X=0 , Y=0.73 , Z=-0.75},
new VertexDania{X=0.1 , Y=0.85 , Z=-0.75},
new VertexDania{X=-0.01 , Y=0.95 , Z=-0.75},
new VertexDania{X=-0.1 , Y=0.80 , Z=-0.75},
new VertexDania{X=0.1 , Y=0.65 , Z=-1},
new VertexDania{X=0 , Y=0.5 , Z=-0.75},
new VertexDania{X=-0.1 , Y=0.6 , Z=-1}
};
VertexDania[] point = new VertexDania[]
{
new VertexDania{X=0, Y=0.23, Z=-0.75},
new VertexDania{X=0.1 , Y=0.35 , Z=-0.75},
new VertexDania{X=-0.01 , Y=0.45 , Z=-0.75},
new VertexDania{X=-0.1 , Y=0.30 , Z=-0.75},
new VertexDania{X=0.1 , Y=0.1 , Z=-0.75},
new VertexDania{X=0 , Y=0.0 , Z=-0.75},
new VertexDania{X=-0.1, Y=0.1, Z=-0.75}
};
double[,] normals = new double[,]
{
{0,0,1},
{0,0,-1},
{0,0,-1}
};
int[,] faces = new int[,]
{
{0 , 1 ,4 , 5},
{0 , 3 , 6 , 5},
{0, 3 , 2 , 1}
};
Gl.glColor3d(1, 0, 0);
Gl.glTranslated(0, ymove, 0.1);
for (int i = 0; i < faces.GetLength(0); i++)
{
Gl.glNormal3d(normals[i, 0], normals[i, 1], normals[i, 2]);
Gl.glBegin(Gl.GL_QUADS);
for (int j = 0; j < 4; j++)
{
Gl.glVertex3d(points[faces[i, j]].X, points[faces[i, j]].Y, points[faces[i, j]].Z);
}
Gl.glEnd();
Gl.glNormal3d(normals[i, 0], normals[i, 1], normals[i, 2]);
Gl.glBegin(Gl.GL_QUADS);
for (int j = 0; j < 4; j++)
{
Gl.glVertex3d(point[faces[i, j]].X, point[faces[i, j]].Y, point[faces[i, j]].Z);
}
Gl.glEnd();
}
if (ymove >= -3)
ymove -= 0.03;
}
void redrawThread()
{
while (true)
{
Thread.Sleep(50);
simpleOpenGlControl1.Invoke(new Action(delegate()
{
simpleOpenGlControl1.Draw();
}));
}
}
private void Form1_Load(object sender, EventArgs e)
{
Thread t = new Thread(redrawThread);
t.IsBackground = true;
t.Start();
}
private void simpleOpenGlControl1_Resize(object sender, EventArgs e)
{
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluPerspective(45, simpleOpenGlControl1.Width / (double)simpleOpenGlControl1.Height, 0.1, 100);
Gl.glViewport(0, 0, simpleOpenGlControl1.Width, simpleOpenGlControl1.Height);
// Gl.glMatrixMode(Gl.GL_MODELVIEW);
}
}
}
This is about data structure / organization than anything else. Since you know how to draw a cube you can start by making a Cube class. This is fairly trivial with immediate mode OpenGL (what you are using)
Since you know how to draw a cube, this class should be fairly easy :
class Cube
{
// Member variables
x,y,z position
r,g,b color
// Functions
public Cube(position, color); // Constructor
public draw(); // draw the cube
}
Then you need a structure that keeps the information about what you should be drawing.
class CubeGroup
{
// Member variables
private Cube[] cubes; // cube array
// Member functions
public AddCube(Cube in_cube); // Adds a cube
public DeleteCube(int index); // Removes a cube
public draw(); // Draws this group of cubes
....
}
You need at least some structures to help you achieving your goal. This makes you able to at least manage one set of cubes. You need to carefully think about what operations you want to do on your data and make structures that makes sense for this. It seems you want your data to change over time as well. Then you need some other structure to deal with that.
This is just pure speculation at this point, but hopefully it might lead you in the right direction. The classes here are just examples and in no way meant to be "the solution".

Categories

Resources