Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm trying to move a picture box fast as it is representing a bullet. However, there is a flickering effect and it obscures the image and it is very hard to see the bullet move. I have tried to use double buffering and Invalidating the picture box before its moved but to no avail. Any suggestions? Maybe im using double buffering wrong? (I have it set to be enabled when the form is loaded.)
Code
On the Form:
public void Shoot(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
PictureBox bulletImage = new PictureBox();
DoubleBuffered = true;
StandardBullet bullet = new StandardBullet(PB_CHARA.Location.X, PB_CHARA.Location.Y, FRM_GAME.MousePosition.X, FRM_GAME.MousePosition.Y, this.ClientRectangle, bulletImage);
Controls.Add(bulletImage);
}
}
Within the Standard Bullet class:
public class StandardBullet
{
public string ImageName = "DataBaseMod.Properties.Resources.StandardBullet_3x";
public int sizeX = 15;
public int sizeY = 19;
public int x = 0;
public int y = 0;
int charaPostitionX;
int charaPostitionY;
PictureBox bulletPoint;
public int[] vector = new int[2];
private System.Timers.Timer bulletTimer;
private System.Timers.Timer RemoveTimer;
System.Drawing.Rectangle FRMBounds;
//public delegate void UpdateControlsDelegate();
public StandardBullet(int charaPostiX, int charaPostiY, int MousePostiX, int MousePostiY, System.Drawing.Rectangle FRMboundaries, PictureBox bulletImage)
{
FRMBounds = FRMboundaries;
bulletPoint = bulletImage;
bulletPoint.Name = ImageName;
string filename = ImageName;
bulletPoint.BackgroundImage = DataBaseMod.Properties.Resources.StandardBullet_3x;
var size = new System.Drawing.Size(sizeX, sizeY);
bulletPoint.Size = size;
bulletPoint.BackgroundImageLayout = ImageLayout.Stretch;
charaPostitionX = charaPostiX;
charaPostitionY = charaPostiY;
x = charaPostiX;
y = charaPostiY;
vector[0] = charaPostiX - MousePostiX;
vector[1] = charaPostiY - MousePostiY;
vectorCalc();
bulletTimer = new System.Timers.Timer(10);
RemoveTimer = new System.Timers.Timer(100);
bulletTimer.Elapsed += TickHandler;
bulletTimer.AutoReset = true;
bulletTimer.Enabled = true;
RemoveTimer.Elapsed += removeTickHandler;
RemoveTimer.Enabled = true;
RemoveTimer.AutoReset = true;
}
public void TickHandler(object sender, ElapsedEventArgs e)
{
x = x + vector[0];
y = y + vector[1];
moveBullet();
}
public void removeTickHandler(object sender, ElapsedEventArgs e)
{
RemoveBullet();
}
public void moveBullet()
{
bulletPoint.BeginInvoke(new MethodInvoker(() => { bulletPoint.Location = new System.Drawing.Point(x, y); }));
}
public void vectorCalc()
{
if (vector[0] >= 1)
{
vector[0] = -10;
}
else if (vector[0] <= -1)
{
vector[0] = 10;
}
if (vector[1] >= 1)
{
vector[1] = -10;
}
else if (vector[1] <= -1)
{
vector[1] = 10;
}
}
public void RemoveBullet()
{
if (
(FRMBounds.Left >= bulletPoint.Bounds.Left) ||
( FRMBounds.Right <= bulletPoint.Bounds.Right) ||
(FRMBounds.Top >= bulletPoint.Bounds.Top) ||
(FRMBounds.Bottom <= bulletPoint.Bounds.Bottom)
)
{
Death();
return;
}
}
public void Death()
{
try
{
bulletTimer.Enabled = false;
bulletPoint.Invoke(new MethodInvoker(() => { FRM_GAME.KillBullet(bulletPoint); }));
RemoveTimer.Enabled = false;
}
catch(Exception e)
{
}
}
}
Thanks!
EDIT: I am going to remove this as i think the error may have been casued by my computer. I had two other games running whilst this one and i think this may have caused the poor rendering. Ran my code this morning and everything is fine. Sorry for this.
Using WinForms for dynamic graphics purposes is not a good idea. Instead of controls, try using Graphics and draw desired object on form (or panel or anywhere you want to).
Related
Im trying to make a chess board using classes from the first time. Im struggling with getting a variable from the first click event method and use it in the DrawRow method. I know its not finished but im really hung up on this bit and having a hard time continuing
private void ToolStripMenuItemDrawBoard_Click(object sender, EventArgs e)
{
//Prevents errors using try catch method
Graphics paper = pictureBoxDisplay.CreateGraphics();
try
{
int boardSize = int.Parse(ToolStripTextBoxBoardSize.Text);
if (boardSize > MIN_BOARD_SIZE || boardSize < MAX_BOARD_SIZE)
{
DrawRow();
}
else
{
MessageBox.Show("Between 2-10");
//Clears all textboxes
foreach (Control c in Controls)
{
if (c is TextBox)
{
c.Text = "";
}
}
}
}
}
public void DrawSquare()
{
Graphics paper = pictureBoxDisplay.CreateGraphics();
paper.DrawRectangle(penBlack, positionX, positionY, WIDTH, HEIGHT);
}
public void DrawRow(ToolStripMenuItemDrawBoard_Click(boardSize))
{
int columnNum = 0;
int counter = 0;
Graphics paper = pictureBoxDisplay.CreateGraphics();
while (boardSize < columnNum)
{
DrawSquare();
if ((counter % 2) == 0)
paper.FillRectangle(brDarkBrown, positionX, positionY, WIDTH, HEIGHT);
else if ((counter % 2) != 0)
paper.FillRectangle(brLightBrown, positionX, positionY, WIDTH, HEIGHT);
positionX = positionX + Width;
columnNum += 1;
}
}
Your question looks clear to me. I anyway can't believe it is what you're talking about.
private void ToolStripMenuItemDrawBoard_Click(object sender, EventArgs e)
{
//Prevents errors using try catch method
Graphics paper = pictureBoxDisplay.CreateGraphics();
try
{
int boardSize = int.Parse(ToolStripTextBoxBoardSize.Text);
if (boardSize > MIN_BOARD_SIZE || boardSize < MAX_BOARD_SIZE)
{
// Pass your board size to DrawRow()
DrawRow(boardSize);
}
else
{
// ..
}
}
}
// Declare your parameter (int boardsize)
public void DrawRow(int boardSize)
{
// boardSize accessable here
}
There you get it. As this got marked I advice you to read through the basics of C#-coding (or general coding).
i am trying to give my text editor multiple pages mode the problem is when the richtextbox reaches the last line it resizes and add a scroll bar which is not what i want, i made a code to transfer the last line of the richtextbox to the one that follows but it's moving the whole text instead and it's kind of sluggish, any help would be appreciated
public partial class Form1 : Form
{
protected static bool GetVisibleScrollbars(Control ctl)
{
int wndStyle = Win32.GetWindowLong(ctl.Handle, Win32.GWL_STYLE);
bool vsVisible = (wndStyle & Win32.WS_VSCROLL) != 0;
return vsVisible;
}
public Form1()
{
InitializeComponent();
}
List<RichTextBox> pages=new List<RichTextBox>();
int currentdocindex = 0;
public void AddPage()
{
RichTextBox B = new RichTextBox();
B.Size = richTextBox1.Size;
panel1.Controls.Add(B);
B.Location = new Point(pages[pages.Count - 1].Location.X, pages[pages.Count - 1].Location.Y + richTextBox1.Height + 20);
pages.Add(B);
B.SelectionIndent = 20;
B.SelectionRightIndent = 20;
B.Enter += new EventHandler(richTextBox_Enter);
}
private void richTextBox_Enter(object sender, EventArgs e)
{
int i = 0;
foreach (RichTextBox box in pages)
{
if (box == (RichTextBox)sender)
{
currentdocindex=i;
break;
}
i++;
}
label1.Text = (currentdocindex + 1).ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
pages.Add(richTextBox1);
richTextBox1.SelectionIndent = 20;
richTextBox1.SelectionRightIndent = 20;
}
private void richTextBox1_Enter(object sender, EventArgs e)
{
int i = 0;
foreach (RichTextBox box in pages)
{
if(box==(RichTextBox)sender)
{
currentdocindex=i;
break;
}
i++;
}
}
bool added = false;
private void timer1_Tick(object sender, EventArgs e)
{
int correntPageIndex = currentdocindex;
if (GetVisibleScrollbars(pages[currentdocindex]))
{
if (!added)
{
AddPage();
added = true;
}
}
else
{
added = false;
}
}
if(GetVisibleScrollbars(pages[correntPageIndex]))
{
string LastLineText = pages[correntPageIndex].Lines[pages[correntPageIndex].Lines.Count() - 1];
int LastLineStartIndex = pages[correntPageIndex].Text.LastIndexOf(LastLineText);
pages[correntPageIndex].SelectionStart = LastLineStartIndex;
pages[correntPageIndex].SelectionLength = pages[correntPageIndex].Text.Length - 1;
LastLineText = pages[correntPageIndex].SelectedRtf;
pages[correntPageIndex].Text = pages[correntPageIndex].Text.Remove(LastLineStartIndex);
pages[correntPageIndex + 1].SelectionStart = 0;
pages[correntPageIndex+1].SelectedRtf = LastLineText;
}
}
}
public class Win32
{
// offset of window style value
public const int GWL_STYLE = -16;
// window style constants for scrollbars
public const int WS_VSCROLL = 0x00200000;
public const int WS_HSCROLL = 0x00100000;
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
}
RichTextBox is a pain for this sort of thing, because to mutate a small portion of text you have to actually select the text first (which it appears you're attempting to do) and ensure the change only affects that text. It's a little nasty on the memory usage, but you might be better served by determining how many characters you want per page and subscribing to the KeyDown Event to determine when you move to a new page. Try to adapt something like this and see if it works better.
public void MyKeyDownHandler(object sender, System.Windows.Forms.KeyEventArgs e)
{
if(this.CurrentPageControl.RTB.Text.Length >= MY_LIMITING_CONSTANT_I_SET)
{
MyPageUserControl mpuc = new MyPageUserControl();
mpuc.RTB.Text = this.CurrentPageControl.RTB.Text.Split(' ').Last();
thePageCollectionIPresumeYouHave.Add(mpuc);
this.CurrentPageControl = thePageCollectionIPresumeYouHave.Last();
mpuc.RTB.Focus();
}
}
Caveat: I did that entirely from memory and without a chance to read all of your code ( I had to skim) because I'm at work.
Another Caveat: I assumed you put your RichTextBoxes in a custom "page" control. If you didn't, I hope my code shows you why you might want to.
I am creating this in regards to an issue I just ran in with. I am trying to create a primitive game of checkers using only buttons and so far I am just testing how to get the program to recognize selecting a button and moving the piece.
My Code:
private void Checkers_Load(object sender, EventArgs e)
{
}
string selectedChecker = "";
string currentButton = "";
int blankSpace = 0;
int[] Board = new int[64];
private void gameBoard()
{
foreach(var control in Controls)
{
var button = control as Button;
if(button != null)
{
if(button.Name == currentButton)
{
button.Image = System.Drawing.Image.FromFile("Red Checker.png");
}
else
{
MessageBox.Show("Dead.");
}
}
else
{
MessageBox.Show("Dead.");
}
}
}
private void attemptMove()
{
string substringChecker = null;
substringChecker = selectedChecker.Substring(0,2);
int selectedCheckerNumber = Convert.ToInt32(substringChecker);
string substringButton = null;
substringButton = currentButton.Substring(0,2);
int currentButtonNumber = Convert.ToInt32(substringButton);
if((selectedCheckerNumber + 3 == currentButtonNumber) || (selectedCheckerNumber + 4 == currentButtonNumber))
{
Board[currentButtonNumber] = Board[selectedCheckerNumber];
Board[selectedCheckerNumber] = blankSpace;
gameBoard();
}
}
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
{
int w = pictureBox1.Size.Width;
int h = pictureBox1.Size.Height;
int count = 8;
Bitmap b = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
w /= count;
h /= count;
Graphics g = Graphics.FromImage(b);
for (int i = 0; i < count; i++)
{
for (int j = 0; j < count; j++)
{
Color c = (i + j) % 2 == 0 ? Color.Red : Color.Black;
Brush br = new SolidBrush(c);
g.FillRectangle(br, i * w, j * h, w, h);
br.Dispose();
}
}
g.Dispose();
pictureBox1.Image = b;
pictureBox1.Refresh();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
//Close form
this.Close();
}
private void howToPlayToolStripMenuItem_Click(object sender, EventArgs e)
{
//MessageBox.Show("How to play a game of Checkers: Step 1 - Don't play.");
}
private void informationToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void checkerSpace18_Click(object sender, EventArgs e)
{
}
private void checkerSpace17_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string buttonClicked = btn.Name;
if (selectedChecker == "")
{
selectedChecker = buttonClicked;
}
else
{
currentButton = buttonClicked;
attemptMove();
}
}
}
My question goes with regards to my attemptMove() method. I run into a runtime error:
"An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll. Additional information: Input string was not in a correct format."
It seems to occur whenever I go to move the piece to the other cell adjacent to the piece after moving it once. It may be because my program is not updating the pictures of the buttons when the buttons switch, but I wanted to see if any guidance could be shed upon this issue.
You are setting the "selectedChecker" to the clicked button .Name property. Then you are using substring(0,2) to get the first 2 characters and try to convert that to an integer.
Since a Name property can't start with numbers, you are attempting to convert some random text to an integer property.
A better approach would be to use the Tag property to hold information about the number, this can be any value. You can then use the int.Parse to parse the Tag value of the button.
What is your naming convention for the buttons? Seems like you're trying to get a number from the name, but the conversion is failing.
If the button names are button00 through button63, then you should be able to get the number using Substring, starting at Name.Length - 2. Note that you must have all button names use a two digit number at the end (00, 01, 02, etc).
For example:
// Get the last two characters of the button name
string substringChecker = selectedChecker.Substring(selectedChecker.Length - 2);
// Convert the characters to an integer
int selectedCheckerNumber = Convert.ToInt32(substringChecker);
I have an array which is populated by MusicNotes. Each MusicNote is an object with it's properties, e.g. pitch and duration. Duration is created using a timer in the MusicNote class.
The problem is that when I iterate through the array and play all the sounds the duration of each MusicNote is lost and it will play the whole wav file (for each note).
I know that the problem is related to the timer and I know that it maybe related to the Play() method in the MusicNote but I don't have any ideas on how to fix it. I have posted my the code related to this problem.
public class MusicNote : PictureBox
{
Timer tmr1 = new Timer();
int tmr1duration;
public SoundPlayer sp = new SoundPlayer();
public Timer tmr = new Timer();
public int pitch; //The no. of the music key (e.g. the sound freuency).
public int noteDuration; //Shape of note.
public string noteShape;
static int xLoc = 0;
int yLoc = 100;
public MusicNote(int iPitch, int iNoteDuration)
: base()
{
pitch = iPitch;
noteDuration = iNoteDuration;
Size = new Size(40, 40);
this.BackColor = Color.Transparent;
this.MouseClick += new MouseEventHandler(MusicNote_MouseClick);
this.MouseDown += new MouseEventHandler(MusicNote_MouseDown);
this.MouseUp += new MouseEventHandler(MusicNote_MouseUp);
tmr1.Tick += new EventHandler(tmr1_Tick);
tmr.Tick += new EventHandler(ClockTick);
}
public void ShowNote()
{
if (this.noteDuration == 1) noteShape = "Quaver.png";
if (this.noteDuration == 4) noteShape = "Crotchet.png";
if (this.noteDuration == 7) noteShape = "minim.png";
if (this.noteDuration == 10) noteShape = "DotMin.png";
if (this.noteDuration == 12) noteShape = "SemiBreve.png";
this.BackgroundImage = Image.FromFile(noteShape);
this.BackColor = Color.Transparent;
Location = new Point(xLoc, yLoc);
xLoc = xLoc + 40;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
public void Play()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
//Timer to play the duration
this.tmr.Interval = 100 * this.noteDuration;
this.tmr.Start();
}
void ClockTick(object sender, EventArgs e)
{
sp.Stop();
tmr.Stop();
}
private void MusicNote_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Play();
}
}
}
}
And this is the class were I have the array...
public class MusicStaff: Panel
{
public ArrayList musicNotes = new ArrayList(); //Array to store the Music Notes.
SoundPlayer sp = new SoundPlayer();
public void AddNote(MusicNote newNote) //Method to add the notes.
{
musicNotes.Add(newNote);
}
public int ListSize()
{
return musicNotes.Count; //Returns the size of the list.
}
public void PlayAll()
{
foreach (MusicNote m in musicNotes)
{
m.Play();
}
I have removed some code from the classes which is not replated to the problem so that question is not too long. Any help how can I solve this would be greatly appreciated. Tks.
Try something like this:
public void PlayAll()
{
foreach (MusicNote m in musicNotes)
{
m.sp.Stop();
m.sp.PlaySync();
Thread.Sleep(m.noteDuration); //duration should be in milliseconds
}
}
Should this work you can remove your timer completely.
I suggest you look into the use of Properties in C# to not let fields be public.
By the way I did this assignment two years ago :)
I have a flag in the Form1 top level: addFrame wich is set to false in the constructor.
Then in the picnt event i check if its false let me draw if its true also let me draw. The problem here is that i want to be able to draw when im running the program first time !
But when im moving the trackBar to the right i dont want it to draw anything .
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
moveCounter++;
label6.Text = moveCounter.ToString();
if (addFrame == false)
{
WireObjectGraphics.Draw(wireObject1, g);
}
else
{
addFrame = false;
WireObjectGraphics.Draw(wireObject1, g);
}
}
This is the button click event where im clicking to set the addFrame to true:
private void button16_Click(object sender, EventArgs e)
{
wireObjectAnimation1.AddFrame();
addFrame = true;
trackBar1.Select();
}
And the scroll bar event in this case i want to make that if i move the trackBar to the right and there are no any draws already then just show the image in the pictureBox dont draw anything ! But if i move it to the right and there are already draws then do show them.
If i move it to the left allways show the previous draws.
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (addFrame == false)
{
}
else
{
currentFrameIndex = trackBar1.Value - 1;
textBox1.Text = "Frame Number : " + trackBar1.Value;
wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex));
trackBar1.Minimum = 0;
trackBar1.Maximum = fi.Length - 1;
if (checkBox1.Checked)
{
setpicture(trackBar1.Value);
Graphics g = Graphics.FromImage(pictureBox1.Image);
g.Clear(SystemColors.Control);
pictureBox1.Invalidate();
}
else
{
setpicture(trackBar1.Value);
}
pictureBox1.Refresh();
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = false;
button4.Enabled = false;
button8.Enabled = false;
SaveFormPicutreBoxToBitMapIncludingDrawings(currentFrameIndex);
return;
}
}
This is the draw function in the WireObjectGraphics class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace AnimationEditor
{
class WireObjectGraphics
{
static Point connectionPointStart;
static Point connectionPointEnd;
static SolidBrush brush;
static Pen p = null;
public WireObjectGraphics()
{
}
public static void Draw(WireObject wo, Graphics graphics)
{
brush = new SolidBrush(Color.Red);
p = new Pen(brush);
Graphics g = graphics;
WireObject wireObject1 = wo;
if (wireObject1 != null)
{
for (int idx = 0; idx < wireObject1.woc.Point_X.Count; ++idx)
{
Point dPoint = new Point((int)wireObject1.woc.Point_X[idx], (int)wireObject1.woc.Point_Y[idx]);
dPoint.X = dPoint.X - 5; // was - 2
dPoint.Y = dPoint.Y - 5; // was - 2
Rectangle rect = new Rectangle(dPoint, new Size(10, 10));
g.FillEllipse(brush, rect);
// bitmapGraphics.FillEllipse(brush, rect);
// g.FillEllipse(brush, rect);
}
for (int i = 0; i < wireObject1._connectionstart.Count; i++)
{
int startIndex = wireObject1._connectionstart[i];
int endIndex = wireObject1._connectionend[i];
connectionPointStart = new Point((int)wireObject1.woc.Point_X[startIndex], (int)wireObject1.woc.Point_Y[startIndex]);
connectionPointEnd = new Point((int)wireObject1.woc.Point_X[endIndex], (int)wireObject1.woc.Point_Y[endIndex]);
p.Width = 2;
g.DrawLine(p, connectionPointStart, connectionPointEnd);
// bitmapGraphics.DrawLine(p, connectionPointStart, connectionPointEnd);
}
}
}
}
}
What i need is that first time running the program to be able to draw !
Then when moving the trackBar to the righ to check if draws already exists show them if not exist show only the image and only when i click the button it will add the draws on the frame im on.
If i move to the left allways show the draws i did in the other frames.
WireObject class:
Constructor:
class WireObject
{
private string an;
private bool fnExt;
public string lockObject;
private int idx;
public WireObjectCoordinates woc;
private List<int> connectionStart = new List<int>();
private List<int> connectionEnd = new List<int>();
private const string version = "01.00";
string wo_name;
public WireObject( string name )
{
wo_name = name;
woc = new WireObjectCoordinates();
fnExt = false;
}
In the wireobject class i have some function like connecting points(pixels) like delete pixels like save and load...
WireObjectCoordinates class is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AnimationEditor
{
class WireObjectCoordinates
{
public List<float> Point_X = new List<float>();
public List<float> Point_Y = new List<float>();
public WireObjectCoordinates()
{
}
public WireObjectCoordinates(WireObjectCoordinates w)
{
Point_X.AddRange(w.Point_X);
Point_Y.AddRange(w.Point_Y);
}
public void Set(WireObjectCoordinates w)
{
if (w == null)
{
}
else
{
for (int i = 0; i < Point_X.Count; i++)
{
Point_X[i] = w.Point_X[i];
Point_Y[i] = w.Point_Y[i];
}
}
}
}
}
The problem is still in Form1 with the flag when to show the pixels i mean when and how to call the paint event like pictureBox1.Refresh(); but oncei t will use the Draw function inside and once it will not. When i run the program let me use the draw function once i moved the trackBar to the right dont use the draw function.
For a windows form control OnPaint is only called when a.) a window overlapping the current control is moved out of the way OR b.) you manually invalidate the control : http://msdn.microsoft.com/en-us/library/1e430ef4.aspx
So OnPaint should be getting called too often.