I am using Windows Form application and using one button to generate random number and draw on form. when button is clicked, It is adding a random number using Graphics.Drawing method. Problem is when I hit the button first time it works fine and add a random number i.e 11111. When I hit button again it will add a new random number (on next position) but it will also change previous numbers to new generated random number.
Updated: (Added Complete Code)
Edit: I have moved Random outside of scoop so now it does not generate same number but still its changing old random numbers to other ones.
Main Class:
using System;
using System.Collections;
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 DrawingText
{
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
private ArrayList drawnItemsList;
Random rnd;
public Form1()
{
InitializeComponent();
drawnItemsList = new ArrayList();
this.rnd = new Random();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mouseMovePosition = e.Location;
if (e.Button == MouseButtons.Left)
mousePressdDown = 1;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
mouseDownPosition = e.Location;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
}
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition);
drawnItemsList.Add(a);
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a.old, a.cur);
}
draw(e.Graphics, mouseDownPosition, mouseMovePosition);
}
private void draw(Graphics e, Point mold, Point mcur)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
string header2 = rnd.Next().ToString();
RectangleF header2Rect = new RectangleF();
int moldX = mold.X - 5;
int moldY = mold.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(header2, useFont, Brushes.Black, header2Rect);
}
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
Drawing Data Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace DrawingText
{
[Serializable]
class DrawingData
{
private Point mold; // mouseDown position
private Point mcur; // mouseUp poslition
public DrawingData()
{
mold = new Point(0, 0);
mcur = new Point(0, 0);
}
public DrawingData(Point old, Point cur)
{
mold = old;
mcur = cur;
}
public Point old
{
get
{
return mold;
}
set
{
mold = value;
}
}
public Point cur
{
get
{
return mcur;
}
set
{
mcur = value;
}
}
}
}
3 times button clicked and it replaced old value with new one:
You need to store the random value with the point values in the DrawingData class, like this:
Main Class:
namespace DrawingText
{
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
private ArrayList drawnItemsList;
Random rnd;
public Form1()
{
InitializeComponent();
drawnItemsList = new ArrayList();
this.rnd = new Random();
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
}
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition, rnd.Next().ToString());
drawnItemsList.Add(a);
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a);
}
draw(e.Graphics, mouseDownPosition, mouseMovePosition);
}
private void draw(Graphics e, DrawingData a)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
RectangleF header2Rect = new RectangleF();
int moldX = a.old.X - 5;
int moldY = a.old.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(a.Rand, useFont, Brushes.Black, header2Rect);
}
}
}
}
Drawing Data Class:
namespace DrawingText
{
[Serializable]
public class DrawingData
{
private Point mold; // mouseDown position
private Point mcur; // mouseUp poslition
private string randValue; // random data value
public DrawingData()
{
mold = new Point(0, 0);
mcur = new Point(0, 0);
randValue = String.Empty;
}
public DrawingData(Point old, Point cur, string rand)
{
mold = old;
mcur = cur;
randValue = rand;
}
public Point old
{
get
{
return mold;
}
set
{
mold = value;
}
}
public Point cur
{
get
{
return mcur;
}
set
{
mcur = value;
}
}
public sting Rand
{
get
{
return randValue;
}
set
{
randValue = value;
}
}
}
You are recreating your random each time in the loop which will cause it to have the same seed, and the same first number. That's why all your numbers are the same. You should.
Move your random outside of the method and loop, and use it instead. Change the line Random rnd = new Random() to rnd = new Random(). You already have a variable in the class to hold the random.
If you want the previous random numbers to remain the same as the last time, you need to store them in a list somewhere and draw them on paint. You are currently creating a new set of random numbers each time.
This is made on the fly using graphics path:
GraphicsPath gp;
int moldX = 10;
int moldY = 10;
public Form1()
{
InitializeComponent();
gp = new GraphicsPath();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.FillPath(Brushes.Black, gp);
// if you want the numbers outlined do e.Graphics.DrawPath
}
private void button1_Click(object sender, EventArgs e)
{
AddToPath();
Invalidate();
}
private void AddToPath()
{
using (Font useFont = new Font("Gotham Medium", 28, FontStyle.Bold))
{
Random rnd = new Random();
string header2 = rnd.Next().ToString();
int strsize = TextRenderer.MeasureText(header2, useFont).Height;
StringFormat format = StringFormat.GenericDefault;
gp.AddString(header2, useFont.FontFamily, 1, 28, new Point(moldX, moldY), format);
moldX += 5;
moldY += strsize;
}
}
Related
I need help getting my program to match the "stored" colour with the current one in the same location then click the mouse if it's the same. The grabbing of the colour works great so far in my code just unsure how to match a colour and a point, etc.
Also a start/stop button for the loop would be nice.
My code so far:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Pixel_detection_test_3
{
public partial class PixelDetectionForm : Form
{
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
private const UInt32 MOUSEEVENTF_LEFTUP = 0x0004;
[DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, uint dwExtraInf);
private int pixelY;
private int pixelX;
private Point pixelYX;
private static Color currentColour;
private static Color storedColour;
public PixelDetectionForm()
{
InitializeComponent();
}
static Color GetPixel(Point position)
{
using (var bitmap = new Bitmap(1, 1))
{
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(position, new Point(0, 0), new Size(1, 1));
}
return bitmap.GetPixel(0, 0);
}
}
private void PixelDetectionForm_KeyDown(object sender, KeyEventArgs e)
{
// Get Cursor Pixel Position
if (e.KeyCode == Keys.F1 || e.KeyCode == Keys.F2)
{
pixelY = Cursor.Position.Y;
pixelX = Cursor.Position.X;
pixelYX = Cursor.Position;
textBoxYPos.Text = pixelY.ToString();
textBoxXPos.Text = pixelX.ToString();
e.Handled = true;
}
// Get Cursor Pixel Colour
if (e.KeyCode == Keys.F1 || e.KeyCode == Keys.F3)
{
storedColour = GetPixel(Cursor.Position);
textBoxColour.Text = storedColour.ToString().Remove(0, 14).TrimEnd(']');
panelColourDisplay.BackColor = storedColour;
e.Handled = true;
}
}
// Not working, need help with this
private async void buttonStart_Click(object sender, EventArgs e)
{
while (true)
{
GetPixel(pixelYX);
// Should get position of 'pixelY' and 'pixelX'
panelColourDisplay2.BackColor = GetPixel(Cursor.Position);
if (pixelYX == storedColour)
{
MousePress();
}
// Need this to prevent not responding
await Task.Delay(3);
}
}
private void MousePress()
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
private void PixelDetectionForm_Click(object sender, EventArgs e)
{
ActiveControl = null;
}
private void PixelDetectionForm_Activated(object sender, EventArgs e)
{
ActiveControl = null;
}
}
}
Thanks
Well, an alternative to the while..loop is using a Timer to achieve that.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Pixel_detection_test_3
{
public partial class PixelDetectionForm : Form
{
private readonly Timer Tmr;
private Point lastPoint;
//Assign this from your input code.
private Color targetColor;
public PixelDetectionForm()
{
Tmr = new Timer { Interval = 50 };
Tmr.Tick += (s, e) => FindMatches(Cursor.Position);
}
//...
In the timer's Tick event, the FindMatches(..) method is called to check the current Cursor.Position and add the distinct matches into a ListBox. You can replace the last part with what you really need to do when you find a match. Like calling the MousePress() method in your code:
//...
private void FindMatches(Point p)
{
//To avoid the redundant calls..
if (p.Equals(lastPoint)) return;
lastPoint = p;
using (var b = new Bitmap(1, 1))
using (var g = Graphics.FromImage(b))
{
g.CopyFromScreen(p, Point.Empty, b.Size);
var c = b.GetPixel(0, 0);
if (c.ToArgb().Equals(targetColor.ToArgb()) &&
!listBox1.Items.Cast<Point>().Contains(p))
{
listBox1.Items.Add(p);
listBox1.SelectedItem = p;
}
}
}
private void PixelDetectionForm_FormClosing(object sender, FormClosingEventArgs e)
{
Tmr.Dispose();
}
}
}
Start and stop the timer in the click events of the Start and Stop buttons.
Here's a demo:
Another alternative is to use the Global Mouse and Keyboard Hooks. Check this, this, and this for more details.
Edit 2/11/2020
If you just want to check whether a given color at a given point exists in a given image, then you can do:
private void buttonStart_Click(object sender, EventArgs e)
{
var targetColor = ...; //target color.
var targetPoint = ...; //target point.
var sz = Screen.PrimaryScreen.Bounds.Size;
using (var b = new Bitmap(sz.Width, sz.Height, PixelFormat.Format32bppArgb))
using (var g = Graphics.FromImage(b))
{
g.CopyFromScreen(Point.Empty, Point.Empty, b.Size, CopyPixelOperation.SourceCopy);
var bmpData = b.LockBits(new Rectangle(Point.Empty, sz), ImageLockMode.ReadOnly, b.PixelFormat);
var pixBuff = new byte[bmpData.Stride * bmpData.Height];
Marshal.Copy(bmpData.Scan0, pixBuff, 0, pixBuff.Length);
b.UnlockBits(bmpData);
for (var y = 0; y < b.Height; y++)
for(var x = 0; x < b.Width; x++)
{
var pos = (y * bmpData.Stride) + (x * 4);
var blue = pixBuff[pos];
var green = pixBuff[pos + 1];
var red = pixBuff[pos + 2];
var alpha = pixBuff[pos + 3];
if (Color.FromArgb(alpha, red, green, blue).ToArgb().Equals(targetColor.ToArgb()) &&
new Point(x, y).Equals(targetPoint))
{
//execute you code here..
MessageBox.Show("The given color exists at the given point.");
return;
}
}
}
MessageBox.Show("The given color doesn't exist at the given point.");
}
If you want to get a list of all the positions of a given color, then create a new List<Point>() and change the check condition to:
//...
var points = new List<Point>();
if (Color.FromArgb(alpha, red, green, blue).ToArgb().Equals(targetColor.ToArgb()))
{
points.Add(new Point(x, y));
}
I am stuck at trying to call a procedure and use some parameters in a new thread in C#. There is my 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.Threading;
namespace Random_colored_rectangles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread th;
Random rand;
System.Drawing.Color[] colors = new System.Drawing.Color[5] {Color.Orange, Color.Red, Color.Pink, Color.Black, Color.Gold };
private void DrawColor(Color color)
{
for (int i = 0; i < 100; i++)
{
DrawRectangle(color, 3 , rand.Next(0, this.Width), rand.Next(0, this.Height), 10, 10);
Thread.Sleep(100);
}
MessageBox.Show(color + " done");
}
private void DrawRectangle(Color barva, float width, int pos_x, int pos_y, int size_x, int size_y)
{
Pen myPen = new Pen(barva, width);
Graphics formGraphics;
formGraphics = plocha.CreateGraphics();
formGraphics.DrawRectangle(myPen, new Rectangle(pos_x, pos_y, size_x, size_y));
myPen.Dispose();
formGraphics.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.R)
{
th = new Thread(DrawColor);
th.Name = Convert.ToString(threadCount);
threadList.Add(th);
threadCount = threadCount + 1;
th.Start(colors[rand.Next(0, colors.Length)]);
}
}
}
}
This code should (after pressing R) make 100 random colored rectangles (the color is chosen from an array of few colors). But, I am unable to make my thread start the procedure DrawColor with a parameter of the random color select.
Can you please help me?
You could do it by using a Task.
Color theColorToPass = someColor;
Task.Factory.StartNew(color => {
DrawColor(color);
}, theColorToPass);
You could aswell access the array directly from within the Task though. I see no point in passing it to the Thread.
Using the advice of those more familiar with the do's and don'ts of C# (that is not me trying to sound mean or anything), I have devised a way to accomplish what you want without the need of CreateGraphics() or Thread.Sleep(). Unfortunately, this throws an OutOfMemoryException when it hits e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);. What does that mean?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Colors
{
public partial class Form1 : Form
{
Timer timer = new Timer { Interval = 100 };
Random rand = new Random();
Color[] colors = new Color[5]
{
Color.Black,
Color.Blue,
Color.Green,
Color.Purple,
Color.Red
};
List<Pen> usedPens = new List<Pen>();
List<Rectangle> usedRectangles = new List<Rectangle>();
Pen penToUse;
List<Rectangle> rectanglesToUse = new List<Rectangle>();
public Form1()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
penToUse = new Pen(GetRandomColor(), 3);
rectanglesToUse.Clear();
for (int i = 0; i < 100; i++)
rectanglesToUse.Add(GetRandomRectangle());
this.Refresh();
}
}
private Color GetRandomColor()
{
return colors[rand.Next(0, colors.Length)];
}
private Rectangle GetRandomRectangle()
{
return new Rectangle(rand.Next(0, Width), rand.Next(0, Height), 10, 10);
}
protected override void OnPaint(PaintEventArgs e)
{
for (int i = 0; i < usedRectangles.Count; i++)
e.Graphics.DrawRectangle(usedPens[i % 100], usedRectangles[i]);
timer.Tick += delegate
{
if (rectanglesToUse.Count > 0)
{
e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);
usedRectangles.Add(rectanglesToUse[0]);
rectanglesToUse.RemoveAt(0);
}
else
{
usedPens.Add(penToUse);
timer.Stop();
}
};
timer.Start();
}
}
}
I have a RichTextBox in my project which is for Jabber chatroom where i get all chat of users and maself.
I want to embed smileys in my project.i want a panel containing all smileys.and when click any smiley it must be sent.
like :) displays smile face
:# is angry face
They must be shown in richtextbox also in form of smiley not symbols like :)
How can i do this in c#.
I had found this code on stack overflow.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.SuspendLayout();
List<Bitmap> Smiles = new List<Bitmap>(); //Add images
ToolStripSplitButton _toolStripSplitButton = new ToolStripSplitButton();
_toolStripSplitButton.Size = new Size(23, 23);
//_toolStripSplitButton.Image = myImage; //Add the image of the stripSplitButton
ToolStrip _toolStrip = new ToolStrip();
_toolStrip.Size = new Size(ClientSize.Width, 10);
_toolStrip.Location = new Point(0, this.ClientSize.Height - _toolStrip.Height);
_toolStrip.BackColor = Color.LightGray;
_toolStrip.Dock = DockStyle.Bottom;
_toolStrip.Items.AddRange(new ToolStripItem[] { _toolStripSplitButton });
SmileBox smilebox = new SmileBox(new Point(_toolStripSplitButton.Bounds.Location.X, _toolStrip.Location.Y - 18), 6);
smilebox.Visible = false;
Controls.Add(smilebox);
foreach (Bitmap bmp in Smiles)
smilebox.AddItem(bmp);
_toolStripSplitButton.Click += new EventHandler(delegate(object sender, EventArgs e)
{
smilebox.Visible = true;
});
Click += new EventHandler(delegate(object sender, EventArgs e)
{
smilebox.Visible = false;
});
this.Controls.Add(_toolStrip);
this.ResumeLayout();
}
void Form1_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
class SmileBox : Panel
{
public List<Item> Items
{
get;
set;
}
Size _ItemSpace = new Size(20, 20);
Point _ItemLocation;
int _rowelements = 0;
public SmileBox(Point Location, int RowElements)
{
BackColor = Color.LightGray;
Height = _ItemSpace.Height;
Width = _ItemSpace.Width * RowElements;
this.Location = new Point(Location.X, Location.Y - Height);
_ItemLocation = new Point(0, 0);
_rowelements = RowElements;
}
int count = 1;
public void AddItem(Bitmap Image)
{
Item item = new Item(_ItemSpace, _ItemLocation, Image);
if (_ItemLocation.X + _ItemSpace.Width >= Width)
_ItemLocation = new Point(0, _ItemLocation.Y);
else
_ItemLocation = new Point(_ItemLocation.X + _ItemSpace.Width, _ItemLocation.Y);
if (count == _rowelements)
{
_ItemLocation = new Point(_ItemLocation.X, _ItemLocation.Y + _ItemSpace.Height);
Height += _ItemSpace.Height;
Location = new Point(Location.X, Location.Y - _ItemSpace.Height);
count = 0;
}
count++;
Controls.Add(item);
}
}
class Item : PictureBox
{
int _BorderSpace = 2;
public Item(Size Size, Point Location, Bitmap Image)
{
this.Size = new Size(Size.Width - 2 * _BorderSpace, Size.Height - 2 * _BorderSpace);
this.Location = new Point(Location.X + _BorderSpace, Location.Y + _BorderSpace);
this.Image = new Bitmap(Image, this.ClientSize);
Click += new EventHandler(delegate(object sender, EventArgs e)
{
//Here what do you want to do when the user click on the smile
});
MouseEnter += new EventHandler(delegate(object sender, EventArgs e)
{
Focus();
Invalidate();
});
}
protected override void OnMouseDown(MouseEventArgs e)
{
this.Focus();
base.OnMouseDown(e);
}
protected override void OnEnter(EventArgs e)
{
this.Invalidate();
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e)
{
this.Invalidate();
base.OnLeave(e);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if (this.Focused)
{
ClientRectangle.Inflate(-1, -1);
Rectangle rect = ClientRectangle;
ControlPaint.DrawFocusRectangle(pe.Graphics, rect);
}
}
}
The above code is not working for me as its too messy to understand.
Thanks in advance.
Try this code - this guy has written exactly the same:
http://www.codeproject.com/Articles/4544/Insert-Plain-Text-and-Images-into-RichTextBox-at-R
I am creating dynamic text fields and storing Position and font etc details in an Arraylist. So for example if I click 3 times on Form I am generating 3 random numbers and showing it on clicked position on form. I have one selector button when it is clicked then adding more text functionality is disabled.
Now after when selector button is clicked and if I click ( MouseDown event) on any text then it should move along mouse until MouseUp event is not fired and place on new drop position.
After hours of struggling and searching I found This Solution, So I saved the position and checked with IsPointOnLine method but still its not draggable.
Thank you for any help.
Update: managed to get foreach on place but its still not dragging the selected element.
Form1.Class
public partial class Form1 : Form
{
private Point mouseDownPosition = new Point(0, 0);
private Point mouseMovePosition = new Point(0, 0);
private int mousePressdDown;
IList drawnItemsList = new List<DrawingData>();
private bool dragging;
private bool isSelectorClicked; // if selector button is clicked
DrawingData draggingText;
Random rnd;
int clicked = 0;
public Form1()
{
InitializeComponent();
this.rnd = new Random();
this.isSelectorClicked = false;
dragging = false;
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mouseMovePosition = e.Location;
if (e.Button == MouseButtons.Left)
mousePressdDown = 1;
if (isSelectorClicked)
{
foreach (DrawingData a in drawnItemsList)
{
if (a.IsPointOnLine(e.Location, 5))
{
draggingText = a;
dragging = true;
}
}
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mouseDownPosition = e.Location;
if (dragging)
{
draggingText.cur = mouseDownPosition;
this.Invalidate();
}
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (mousePressdDown == 1 && isSelectorClicked == false)
{
label1.Text = "X: " + mouseMovePosition.X.ToString();
label2.Text = "Y: " + mouseMovePosition.Y.ToString();
this.Invalidate();
DrawingData a = new DrawingData(mouseMovePosition, mouseDownPosition, rnd.Next().ToString(), FontStyle.Bold, 30, "Candara", Brushes.Blue);
drawnItemsList.Add(a);
this.clicked++;
}
mousePressdDown = 0;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if(drawnItemsList.Count != 0)
{
foreach (DrawingData a in drawnItemsList)
{
draw(e.Graphics, a);
}
if (mousePressdDown != 0)
{
draw(e.Graphics, mouseDownPosition, mouseMovePosition, FontStyle.Bold, 30, "Candara", Brushes.Blue);
}
}
}
private void draw(Graphics e, Point mold, Point mcur, FontStyle fontWeight, int fontSize, string fontName, Brush fontColor)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font(fontName, fontSize, fontWeight))
{
string header2 = rnd.Next().ToString();
RectangleF header2Rect = new RectangleF();
int moldX = mold.X - 5;
int moldY = mold.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(header2, useFont, fontColor, header2Rect);
}
}
private void draw(Graphics e, DrawingData a)
{
Pen p = new Pen(Color.Black, 2);
using (Font useFont = new Font(a.FontName, a.FontSize, a.FontWeight))
{
string header2 = rnd.Next().ToString();
RectangleF header2Rect = new RectangleF();
int moldX = a.old.X - 5;
int moldY = a.old.Y;
header2Rect.Location = new Point(moldX, moldY);
header2Rect.Size = new Size(600, ((int)e.MeasureString(header2, useFont, 600, StringFormat.GenericTypographic).Height));
e.DrawString(a.Rand, useFont, a.FontColor, header2Rect);
}
}
private void Select_button_Click(object sender, EventArgs e)
{
this.isSelectorClicked = true;
}
private void WriteNewText_button_Click(object sender, EventArgs e)
{
this.isSelectorClicked = false;
}
}
DrawingData.Class
[Serializable]
public class DrawingData
{
private Point Start; // mouseDown position
private Point End; // mouseUp poslition
private string randValue; // random data value
private FontStyle fontWeight;
private int fontSize;
private string fontName;
private Brush fontColor;
public DrawingData()
{
Start = new Point(0, 0);
End = new Point(0, 0);
randValue = String.Empty;
fontWeight = FontStyle.Bold;
}
public DrawingData(Point old, Point cur, string rand, FontStyle fs, int fSize, string fName, Brush fColor)
{
Start = old;
End = cur;
randValue = rand;
fontWeight = fs;
fontSize = fSize;
fontName = fName;
fontColor = fColor;
}
public float slope
{
get
{
return (((float)End.Y - (float)Start.Y) / ((float)End.X - (float)Start.X));
}
}
public float YIntercept
{
get
{
return Start.Y - slope * Start.X;
}
}
public bool IsPointOnLine(Point p, int cushion)
{
float temp = (slope * p.X + YIntercept);
if (temp >= (p.Y - cushion) && temp <= (p.Y + cushion))
{
return true;
}
else
{
return false;
}
}
public FontStyle FontWeight
{
get
{
return fontWeight;
}
set
{
fontWeight = value;
}
}
public int FontSize
{
get
{
return fontSize;
}
set
{
fontSize = value;
}
}
public string FontName
{
get
{
return fontName;
}
set
{
fontName = value;
}
}
public Brush FontColor
{
get
{
return fontColor;
}
set
{
fontColor = value;
}
}
public Point old
{
get
{
return Start;
}
set
{
Start = value;
}
}
public Point cur
{
get
{
return End;
}
set
{
End = value;
}
}
public string Rand
{
get
{
return randValue;
}
set
{
randValue = value;
}
}
}
SOLVED: I was missing these lines in my mouse move method:
m.Start = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y);
m.End = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y);
You should move stuff in Form1_MouseMove instead of Form1_MouseUp.
Find the element you want to move in the Arraylist and assign it new position.
Redraw the element.
Also you should use IList<DrawingData> instead of ArrayList
Greetings
I genereated a terrain with this equation:
H(x,y) = (abs(sin(x * y)) + abs(sin(0,2 * x) + sin(0,4 * y)) + abs(cos(0,12 * x) + cos(0,47 * y))) * e^(0.005*(x+y))
Now, this gives me a mix of featuresize, and a nice slope. This works fine, when I plot it using scilab.
I tried to import this in a c# application.
The terrain is created in this code:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Collections.Generic;
namespace Kamera_eins
{
public partial class Terrain : Form
{
public double[,] DTM;
string response ;
public Terrain()
{
InitializeComponent();
response = "";
DTM = new double[2048/4,2048/4];
}
public void BoxTheSky()
{
}
public void BoxTheLand()
{
mesh();
surf();
}
public void begin()
{
}
public void mesh()
{
response = "";
int i = new int();
int j = new int();
i = 0;
j = 0;
for (i=0;i<2048/4 ;i++ ) {
for (j=0;j<2048/4 ;j++ ) {
DTM[i,j] = Math.Abs (Math.Sin (j*i)) + Math.Abs(Math.Sin(0.2*i) * Math.Sin(0.4*j) ) + Math.Abs(Math.Cos(0.12* i) * Math.Cos(0.47*j));
DTM[i,j] = Math.Pow(Math.E, (0.012* (i + j)));
}
}
response = "DTM mesh ready";
}
public void surf()
{
}
}
}
This is kept in a file called terrain.cs, and i make this a winform, because i plan to add a simple textbox, where i can later make some sort of realtime log of the process.
Now, there is another file, and in that file, intend to display this terrain. this second file goes as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
namespace Kamera_eins
{
public class viewport : Form
{
public Microsoft.DirectX.Direct3D.Device device = null;
public PresentParameters presentparameter = new PresentParameters();
public bool device_exists;
public bool show;
public int HEIGHT;
public int WIDTH;
public string paintDesc;
private float angle ;
private CustomVertex.PositionColored[] vertices;
public double[,] heightData;
private int[] indices;
private IndexBuffer ib;
private VertexBuffer vb;
private Microsoft.DirectX.DirectInput.Device keyb;
//public
public viewport()
{
this.ClientSize = new System.Drawing.Size(600, 600);
this.Text = "Terrain viewport";
WIDTH = 2048 / 4;
HEIGHT = 2048 / 4;
heightData = new double[HEIGHT,WIDTH];
keyb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
presentparameter.Windowed = true;
presentparameter.SwapEffect = SwapEffect.Discard;
presentparameter.AutoDepthStencilFormat = DepthFormat.D16;
presentparameter.EnableAutoDepthStencil = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
try {
device = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentparameter);
device.DeviceLost += new EventHandler(this.InvalidateDeviceObjects);
device.DeviceReset += new EventHandler(this.RestoreDeviceObjects);
device.Disposing += new EventHandler(this.DeleteDeviceObjects);
device.DeviceResizing += new CancelEventHandler(this.EnvironmentResizing);
device_exists = true;
} catch (Exception DirectException) {
device_exists = false;
}
}
private void setcamera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 50f);
device.Transform.View = Matrix.LookAtLH (new Vector3(0, 0, 100), new Vector3(0, 0, 0) , new Vector3(0,0,1) );
device.RenderState.Lighting = false;
device.RenderState.FillMode = FillMode.WireFrame;
device.RenderState.CullMode = Cull.None;
}
public void declareVertex()
{
vb = new VertexBuffer(typeof(CustomVertex.PositionColored), HEIGHT*WIDTH, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
vertices = new CustomVertex.PositionColored[HEIGHT*WIDTH];
for (int x=0;x< WIDTH;x++) {
for (int y=0; y< HEIGHT;y++) {
vertices[x + y * WIDTH].Position = new Vector3(x, y, (float)heightData[x,y]);
int r = Convert.ToInt32(205 * heightData[x,y] / 200 );
if(r>254)
r = 254;
vertices[x + y * WIDTH].Color = Color.FromArgb( r , 120 , 120).ToArgb();
}
}
vb.SetData(vertices, 0, LockFlags.None);
}
public void declareIndex()
{
ib = new IndexBuffer(typeof(int), (WIDTH-1)*(HEIGHT-1)*6, device, Usage.WriteOnly, Pool.Default);
indices = new int[(WIDTH-1)*(HEIGHT-1)*6];
for (int x=0;x< WIDTH-1;x++) {
for (int y=0; y< HEIGHT-1;y++) {
indices[(x+y*(WIDTH-1))*6] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+1] = (x+1)+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+2] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+3] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+4] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+5] = x+(y+1)*WIDTH;
}
}
ib.SetData(indices, 0, LockFlags.None);
}
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
MessageBox.Show("");
}
protected virtual void InvalidateDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void RestoreDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void DeleteDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void EnvironmentResizing(object sender, CancelEventArgs e)
{
}
public void run()
{
while(this.Created)
{
render();
setcamera();
// optional: loading the height using functional call:
// loadheight();
Application.DoEvents();
}
}
public void render()
{
if (device != null)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
//display terrain
device.VertexFormat = CustomVertex.PositionColored.Format;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;
device.Transform.World = Matrix.Translation(-HEIGHT/2, -WIDTH/2, 0)*Matrix.RotationZ(angle) ;
device.DrawIndexedPrimitives(PrimitiveType.TriangleFan, 0, 0, WIDTH*HEIGHT, 0, indices.Length/3);
//turn off lights now
device.EndScene();
device.Present();
this.Invalidate();
readkeyboard();
}
}
void readkeyboard()
{
KeyboardState keys = keyb.GetCurrentKeyboardState();
if (keys[Key.Delete])
{
angle+=0.03f;
}
if (keys[Key.Next])
{
angle-=0.03f;
}
}
public void openport()
{
}
protected override void OnPaint(PaintEventArgs e)
{
render();
setcamera();
}
}
}
Now, yet a third file calls the world creation and display:
void MainFormLoad(object sender, EventArgs e)
{
world = new World();
world.setterrain();
}
the surf and box-somthing functions do not yet do anything.
All what i get now, is just a black window (the device.clear(... ) part) - i tried to adjust the camera .. no success
please help, i want to show the terrain in the window ....