C# Flickering when moving an object with several shapes - c#

I'm working on a program in which I want to move a character composed by several shapes (rectangle,circle,point) but when the character moves, it flickers.
I have tried several solutions like change the DoubleBuffered, SetStyle but they doesn't work and I don't know how i can do this.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Carrosse
{
public partial class EcranAccueil : Form
{
private Capitaine cptHaddock;
private BufferedGraphics bufferG = null;
private Graphics g;
public EcranAccueil()
{
InitializeComponent();
// Modification contre le scintillement - Creation d'une mémoire tampon graphique
bufferG = BufferedGraphicsManager.Current.Allocate(TV.CreateGraphics(), TV.DisplayRectangle);
g = bufferG.Graphics;
}
private void btnCreercptHaddock_Click(object sender, EventArgs e)
{
this.cptHaddock = new Capitaine(this.TV, 50, 80, 60, 20);
this.cptHaddock.Pot = Color.Blue;
this.cptHaddock.Afficher(this.TV.Handle);
this.btnMarcherSimple.Enabled = true;
this.btnChangerRapidite.Enabled = true;
this.btnMarcherContinu.Enabled = true;
}
private void btnMarcherSimple_Click(object sender, EventArgs e)
{
this.cptHaddock.AvancerDroit(this.TV.Handle, this.timerImage, 16, 0);
this.cptHaddock.AvancerGauche(this.TV.Handle, this.timerImage, 16, 0);
}
private void btnChangerRapidite_Click(object sender, EventArgs e)
{
try
{
this.timerImage.Interval = Int32.Parse(tbRapidite.Text);
}
catch (Exception)
{
tbRapidite.Text = "Valeur non valide !";
}
}
private void btnMarcherContinu_Click(object sender, EventArgs e)
{
for (int i = 0; i < 4; i++)
{
this.cptHaddock.AvancerDroit(this.TV.Handle, this.timerImage, 16, 0);
this.cptHaddock.AvancerGauche(this.TV.Handle, this.timerImage, 16, 0);
}
}
}
}
The button btnCreercptHaddock creates the character.
The buttons btnMarcherSimple and btnMarcherContinu moves the character.
The button changes the speed of the character via a timer with the help of an input.
I can provide the others parts of my program but I have something like 10 classes.
PS : I'm student and I'm learning C# so my code is maybe not optimized so if you have comments or advices, I would be happy to hear them.
EDIT: gif of the animation : https://i.gyazo.com/68ded3fba8fddbf281a424bbb523f2d2.gif (All the flickers don't appear in the gif but they appear during all the animation)

Set this code in your form. It will remove the flicker. By setting ExStyle which is actually WS_EX_TRANSPARENT flag, it makes window control invisible to mouse events, which in turn reduces significant amount of flicker.
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; //WS_EX_TRANSPARENT flag
return cp;
}
}
Hope it helps

Related

Disable Text Scrolling when text is longer than the TextBox Width

I have a customTextBox1 on a Form.
customTextbox1 multiline is false and TextAlign is set to center.MaxLength is 23. And the customTextBox1 width is 92.customTextBox1 Font is set to "MS ゴシック", 12F.
When I type "12345678901234567890123" in the TextBox, the text is scrolling to the last character.Also,when I click on the text , the text is highlighted blue and I can drag to the left and right of the text.
.NetFramework 3.5
What I want is 2 things:
1)when the text is longer than TextBox width, I don't want to scroll to the last character.I want to stop scrolling at the right margin of the TextBox.
for example,
when I type "1234567890123456", I want to show "12345678901"and the rest of the overflow text should not be shown.
2)when I Click and Drag the text, I want to show "12345678901" only
And want to get rid of the blue highlighted selection too.
1)overflow text is showing
2)i can click and drag to the end of the text and beginning of the text
here is my code
CustomTextBox
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DisabledTextSelectForm
{
public partial class CustomTextBox : TextBox
{
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
public CustomTextBox()
{
InitializeComponent();
}
}
}
Form1
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;
namespace DisabledTextSelectForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
customTextBox1.AutoSize = true;
customTextBox1.Size = new Size(92,21);
customTextBox1.Multiline = false;
customTextBox1.TextAlign = HorizontalAlignment.Center;
customTextBox1.MaxLength = 23;
customTextBox1.Font = new Font("MS ゴシック", 12F);
}
}
}
Update1 :
I want to do this strange behavior of textBox because I am making a exact replica of an application written in other language which is not supported anymore. So we have to write it in C#. Both application will run on windows.
In the old application, there is a textBox in which user can type in ID numbers.
1)That textBox does not show overflow text.
If I type ("12345678901234567890123") ,it only show "12345678901" but if I click backspace [13]times, the text begins "1234567890". so I know the overflow text are there just not showing.
2)I can't click and drag the text right and left as in C# textBox.
I have manage to replicate No.1 behavior though.
Here is my code
CustomTextBox
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Runtime.InteropServices;
namespace DisabledTextSelectForm
{
public partial class CustomTextBox : TextBox
{
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
public bool DisabledScrolling { get; set; }
int caretPos = 0;
public CustomTextBox()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
var isDigit = char.IsDigit(e.KeyChar);
var isBackSpace = e.KeyChar == (char)Keys.Back;
var diffWidth = 0;
if (Text.Length >= 2)
{
var firstChar = TextRenderer.MeasureText(Text[0].ToString(), Font);
var secondChar = TextRenderer.MeasureText(Text.Substring(0, 2).ToString(), Font);
diffWidth = secondChar.Width - firstChar.Width;
caretPos = Width / diffWidth;
}
if (caretPos != 0 && Text.Length >= caretPos && DisabledScrolling)
{
if (isDigit)
{
Text = Text.Length < MaxLength ? Text + e.KeyChar.ToString() : Text;
}
else if (isBackSpace)
{
Text = Text.Substring(0,Text.Length - 1);
}
ScrollTo(caretPos - 1);
e.Handled = true;
}
base.OnKeyPress(e);
}
private void ScrollTo(int scrollPosition)
{
if (Text.Length >= scrollPosition)
{
Select(scrollPosition, 0);
ScrollToCaret();
}
}
}
}
Form1
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;
namespace DisabledTextSelectForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
customTextBox1.DisabledScrolling = true;
customTextBox1.AutoSize = true;
customTextBox1.Size = new Size(92,21);
customTextBox1.Multiline = false;
customTextBox1.TextAlign = HorizontalAlignment.Center;
customTextBox1.MaxLength = 23;
customTextBox1.Font = new Font("MS ゴシック", 12F);
}
}
}
I know how to disable clicking and draging of Text in TextBox.
Add a Timer then set it Enable with 10 ms interval and in Tick event of your Timer put this code:
private void timer1_Tick(object sender, EventArgs e)
{
textBox1.SelectionLength = 0;
textBox1.SelectionStart = 0;
textBox1.ScrollToCaret();
}
In MouseMove event of your TextBox put this code:
private void textBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
textBox1.SelectionLength = 0;
textBox1.SelectionStart = 0;
textBox1.ScrollToCaret();
}
In KeyDown event of your TextBox put this code:
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
textBox1.SelectionStart = textBox1.Text.Length;
}
Add this code in initialize block
public Form1()
{
InitializeComponent();
textBox1.HideSelection = true;
}

viola jones recognize faces with emgucv and C#

can viola jones recognize faces without any addition method like PCA or anything else ? how's the accurancity? and how to get rid the false negative in detecting? because there's so much false negative in viola jones detecting. if you know something please tell me.
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 Emgu.CV.Util;
using Emgu.CV.Features2D;
using Emgu.CV;
using Emgu.CV.GPU;
using Emgu.CV.VideoStab;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
namespace deteksi_wajah
{
public partial class Form1 : Form
{
Capture capture; // untuk koneksi ke webcam
HaarCascade haar;
public Form1()
{
InitializeComponent();
}
//method
//Proses image aquisision bertipe rgb
private void prosesFrame(object sender, EventArgs arg)
{
Image < Bgr, byte > image = capture.QueryFrame(); //hasil koneksi gambar didapat bertipe rbg
imageBox1.Image = image; // citra yg didapat berada dalam box
if( image != null)
{
Image < Gray, byte > gray = image.Convert<Gray,byte>();
var faces = gray.DetectHaarCascade(haar, 1.1 , 1,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(20,20))[0];
foreach (var face in faces)
{
Image<Gray,byte>hasil = image.Copy(face.rect).Convert<Gray,byte>().Resize(100, 100, INTER.CV_INTER_CUBIC);
image.Draw(face.rect, new Bgr(Color.Red),3);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
if (capture == null)
{
try
{
capture = new Capture();
}
catch
{
}
}
//jika camera tidak sama dengan null
if (capture != null)
{
if (btn_start.Text == "Pause")
{
btn_start.Text = "Resume";
Application.Idle -= prosesFrame; // mengaktifkan kamera
}
else
{
btn_start.Text = "Pause";
Application.Idle += prosesFrame;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
haar = new HaarCascade("haarcascade_frontalface_default.xml");
}
}
}
I think the problem with your code is the parameters in detection are too small.
gray.DetectHaarCascade(haar, 1.1 , 1,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(20,20))
Try increase the minNeighbor and minSize value. minNeighbor = 1 do no grouping and cause a lot of false positive. For me, with my current camera at 1280*720 resolution, minNeighbor = 10 and minSize = 100,100 did a very good job.

Edit the background of a button in c#

I have a little problem of mine to solve. I have a button which has an image background.I tried to color the whole button but the image can not be seen after coloring the whole button. How can I edit this "imagebutton" like in this example? http://i.stack.imgur.com/XaQQQ.png
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 bura
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
if (button2.BackgroundImage != null)
{
button2.BackgroundImage = null;
button2.BackColor = Color.Black;
}
else {
button2.BackgroundImageLayout = ImageLayout.Stretch;
button2.BackgroundImage = Image.FromFile("C:\\Users\\rati\\Desktop\\ks.png");
}
}
private void button3_Click(object sender, EventArgs e)
{
button2.BackgroundImageLayout = ImageLayout.Stretch;
button2.BackgroundImage = Image.FromFile("C:\\Users\\rati\\Desktop\\ks.png");
}
}
}
This
Just made a button by using the designer with the following code:
this.button1.BackColor = System.Drawing.Color.DodgerBlue;
this.button1.BackgroundImage = global::WindowsFormsApplication.Properties.Resources.ChargeImage;
this.button1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.button1.Image = global::WindowsFormsApplication.Properties.Resources.DatabaseImage;
this.button1.Location = new System.Drawing.Point(12, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(264, 160);
this.button1.TabIndex = 0;
this.button1.UseVisualStyleBackColor = false;
And that is the result:
So what is your problem?
You can edit your pictures with a method like this:
private static void DrawLinesOnBitmap(Bitmap bmp)
{
using (var p = new Pen(Color.Black, 5))
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawLine(p, 0, 0, bmp.Width, bmp.Height);
}
}
}
This method adds a line from the left top corner to the right bottom corner. Just draw some more lines and you should get your wanted result.

Issue with transparent images with a transparent background

I'm having a problem with displaying transparent images with a transparent background. The transparent background takes the color of the underlying control and that is fine ... bu the problem is that some details (lines) on the underlying background are being covered the the images as can be seen in the image below.
Here is the code I am using.... This is the code for the notes....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Drawing;
namespace Simpe_Piano_new
{
class MusicNote: PictureBox
{
public SoundPlayer sp = new SoundPlayer();
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;
public MusicNote(int iPitch, int iNoteDuration)
: base()
{
pitch = iPitch;
noteDuration = iNoteDuration;
Size = new Size(40, 40);
}
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((pitch * 40) - 40, 100);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
public void PlaySound()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
}
public void StopSound()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Stop();
}
public void Play()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
//Time to play the duration
tmr.Interval = noteDuration;
tmr.Start();
tmr.Tick += new System.EventHandler(ClockTick);
}
void ClockTick(object sender, EventArgs e)
{
sp.Stop();
tmr.Stop();
}
}
}
This is the code for the underlying control..the music staff
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace Simpe_Piano_new
{
public class MusicStaff: Panel
{
Pen myPen;
Graphics g;
public MusicStaff()
{
this.Size = new Size(1000, 150);
this.Location = new Point(0, 0);
this.BackColor = Color.Transparent;
this.Paint += new PaintEventHandler(DrawLines);
}
private void DrawLines(object sender, PaintEventArgs pea)
{
myPen = new Pen(Color.Black, 1);
g = this.CreateGraphics();
for (int i = 1; i < 6; i++)
{
g.DrawLine(myPen, 0, (this.Height / 6) * i, this.Width, (this.Height / 6) * i);
}
}
}
}
I have found that C# does not handle transparency really well...
Any help would be greatly appreciated..
add the top control "MusicNote" in the children of the underlying control "MusicStaff"
something like that after -Initializing all components-
// mStaff: the MusicStaff object
// mNote: the MusicNote object
mStaff.Children.Add(mNote);
in old scenario, the form is the parent of both of them, so they display the form background in any transparent area
after modifying the parent of the "MusicNote", it displays the "MusicStaff" background in the transparent area
I hope that help!
Two mistakes. PictureBox supports transparent images well, as long as you set its BackColor property to Color.Transparent. Which you did for the MusicStaff but not for the MusicNote. Layered transparency does not work, you don't need MusicStaff to be transparent, just the picture boxes.
This kind of transparency is simulated by asking the Parent to paint itself into the control to provide the background pixels. Which is your second mistake, you use CreateGraphics() in your DrawLines() method. Which draws directly to the screen, not the control surface. You must use pea.Graphics here.
Do note that the value-add you get from using PictureBox is a very low one. Controls are expensive and you'll easily burn up hundreds of them to display a sheet of music. You'll notice, it will become slow to paint itself. You avoid this by having MusicStaff just paint the notes itself, using Graphics.DrawImage() gets the job done. Transparency effects are now much simpler as well, just layers of paint. Which is the way WPF does it. The only inconvenience you'll have to deal with is that mouse hit testing isn't as simple anymore, you need to map the panel's MouseDown event's coordinates to a note. Just keep a List that keeps track where every note is displayed. You'll use that for painting as well as mouse hit testing.

How to improve this C# animation code

I have the code below which is an implementation of a marquee label. I'd like the marquee label to run at the most efficient rate possible on the computer while maintaining a constant speed across different computers. I'd like the amount of "frames" that are skipped to be minimized so that the program takes full advantage of the computer it's being run on. But at the same time I don't necessarily want to consume 100% of the CPU (are those statements contradictory? I'm not sure).
Currently I'm sleeping 10 milliseconds for each iteration of the animation loop. This feels wasteful to me and it seems like it might slow down the animation on slower computers that might need those extra 10 milliseconds. I'm not sure what the best value is to use in the sleep method or even if I should sleep at all. I've read some about Sleep(0) and Sleep(1) and Yield and SpinWait, but I can't make sense of it all.
Also is it a bad thing to call Invalidate too much? Can I overload it by calling it too much?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Diagnostics;
using Timer = System.Timers.Timer;
using System.Threading;
namespace Scoreboard
{
public class MarqueeLabel : Label
{
private float _marqueeOffset;
private float _marqueeMeasurement;
public MarqueeLabel()
{
UseCompatibleTextRendering = true;
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
Thread t = new Thread(ThreadRun);
t.IsBackground = true;
t.Start();
}
public void ThreadRun()
{
long time = DateTime.Now.Ticks;
long diff = 0;
while (true)
{
float step = -((float)diff / (20 * TimeSpan.TicksPerMillisecond)); //change "frame" based on the elapsed time
_marqueeOffset = _marqueeOffset >= -_marqueeMeasurement ? _marqueeOffset + step : Width;
Invalidate();
Thread.Sleep(10); // how long should i wait here?
long temp = DateTime.Now.Ticks;
diff = temp - time;
time = temp;
}
}
protected override void OnPaint(PaintEventArgs e)
{
StringFormat stringFormat = new StringFormat();
stringFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
stringFormat.Trimming = StringTrimming.None;
stringFormat.Alignment = StringAlignment.Near;
Rectangle rect = ClientRectangle;
rect.X += (int)_marqueeOffset;
e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), rect, stringFormat);
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
MeasureText();
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
MeasureText();
}
void MeasureText()
{
_marqueeMeasurement = CreateGraphics().MeasureString(Text, Font).Width;
}
}
}

Categories