如何绘制不断变化的图形

之前没有这样做过( 除了在java中 ,看看Steve McLeod是如何修复它的),所以显然我很沮丧。 这里,当前鼠标位置周围的64个像素在表格上绘制得更大。 问题是,它有点’缓慢’,我不知道从哪里开始修复。

除此之外,我制作了一个计时器线程,它在完成后不断调用更新图形,并且像文本一样点fps,以显示绘制事物的速度。

图像示例:(图像来自Microsoft VS2010中“IntelliTrace”中的字母’a’)

替代文字

来源示例:

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.Runtime.InteropServices; namespace Zoom { public partial class Form1 : Form { static class dllRef { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetCursorPos(out Point lpPoint); [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("user32.dll")] static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); // from http://www.pinvoke.net/default.aspx/gdi32/GetPixel.html static public System.Drawing.Color getPixelColor(int x, int y) { IntPtr hdc = GetDC(IntPtr.Zero); uint pixel = GetPixel(hdc, x, y); ReleaseDC(IntPtr.Zero, hdc); Color color = Color.FromArgb((int)(pixel & 0x000000FF), (int)(pixel & 0x0000FF00) >> 8, (int)(pixel & 0x00FF0000) >> 16); return color; } static public System.Drawing.Point getMousePosition() { Point p = new Point(); GetCursorPos(out p); return p; } } public Form1() { InitializeComponent(); this.Size = new Size(400,400); this.Text="Image zoom"; this.Location = new Point(640, 0); this.image = new Bitmap(320, 320); this.timeRef = DateTime.Now; this.BackColor = Color.White; Timer t = new Timer(); t.Interval = 25; t.Tick += new EventHandler(Timer_Tick); t.Start(); } public void Timer_Tick(object sender, EventArgs eArgs) { this.Form1_Paint(this, new PaintEventArgs(this.CreateGraphics(), new Rectangle(0, 0, this.Width, this.Height))); } private bool isdone = true; private int iter = 0; private Bitmap image; private DateTime timeRef; private void Form1_Paint(object sender, PaintEventArgs e) { if (isdone) { isdone = false; int step = 40; Point p = dllRef.getMousePosition(); Pen myPen = new Pen(Color.Gray, 1); SolidBrush myBrush = null; Bitmap image2 = new Bitmap(320, 340); Graphics gc = Graphics.FromImage(image2); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { myBrush = new SolidBrush(dllRef.getPixelColor(pX - 4 + x, pY - 4 + y)); gc.FillEllipse(myBrush, x * step, y * step, step - 3, step - 3); gc.DrawEllipse(myPen, x * step, y * step, step - 3, step - 3); } } StringBuilder sb = new StringBuilder(); sb.Append(iter) .Append(" frames in ") .Append(String.Format("{0:0.###}", ((DateTime.Now-this.timeRef).TotalMilliseconds)/1000)) .Append("s."); gc.FillRectangle(new SolidBrush(this.BackColor), new Rectangle( 0, 320, 320, 40)); gc.DrawString(sb.ToString(),new Font("Arial", 12),new SolidBrush(Color.Black), 10, 320); gc.Dispose(); isdone = true; iter++; image = image2; } e.Graphics.DrawImage(image, 35f, 15f); } } } 

在我做出改变后,这个改变了~98%:

 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.Runtime.InteropServices; namespace Zoom { public partial class Form1 : Form { static class dllRef { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetCursorPos(out Point lpPoint); [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("user32.dll")] static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); // from http://www.pinvoke.net/default.aspx/gdi32/GetPixel.html static public System.Drawing.Color getPixelColor(int x, int y) { IntPtr hdc = GetDC(IntPtr.Zero); uint pixel = GetPixel(hdc, x, y); ReleaseDC(IntPtr.Zero, hdc); Color color = Color.FromArgb((int)(pixel & 0x000000FF), (int)(pixel & 0x0000FF00) >> 8, (int)(pixel & 0x00FF0000) >> 16); return color; } static public System.Drawing.Point getMousePosition() { Point p = new Point(); GetCursorPos(out p); return p; } } public Form1() { InitializeComponent(); this.Size = new Size(400,400); this.Text="Image zoom"; this.Location = new Point(640, 0); this.image = new Bitmap(320, 340); this.timeRef = DateTime.Now; this.BackColor = Color.White; Timer t = new Timer(); t.Interval = 25; t.Tick += new EventHandler(Timer_Tick); t.Start(); } public void Timer_Tick(object sender, EventArgs eArgs) { this.Form1_Paint(this, new PaintEventArgs(this.CreateGraphics(), new Rectangle(0, 0, this.Width, this.Height))); } private bool isdone = true; private int iter = 0; private Bitmap image; private DateTime timeRef; private void Form1_Paint(object sender, PaintEventArgs e) { if (isdone) { isdone = false; int step = 40; Point p = dllRef.getMousePosition(); SolidBrush myBrush = null; Bitmap hc = new Bitmap(8, 8); using (Pen myPen = new Pen(Color.Gray, 1)) using (Graphics gc = Graphics.FromImage(image)) using (Graphics gf = Graphics.FromImage(hc)) { gf.CopyFromScreen(pX - 4, pY - 4, 0, 0, new Size(8, 8), CopyPixelOperation.SourceCopy); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { myBrush = new SolidBrush(hc.GetPixel(x, y)); gc.FillEllipse(myBrush, x * step, y * step, step - 3, step - 3); gc.DrawEllipse(myPen, x * step, y * step, step - 3, step - 3); } } double ts = ((DateTime.Now - this.timeRef).TotalMilliseconds) / 1000; StringBuilder sb = new StringBuilder(); sb.Append(++iter).Append(" frames in ").Append(String.Format("{0:0.###}", ts)).Append("s."); gc.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(0, 320, 320, 40)); gc.DrawString(sb.ToString(), new Font("Arial", 12), new SolidBrush(Color.Black), 10, 320); } isdone = true; } e.Graphics.DrawImage(image, 35f, 15f); } } } 

应该加快速度的一件事是,如果你只使用一次GetDC并获得所需的所有像素,那么请调用ReleaseDC 。 所以而不是:

 for each pixel GetDC Read Pixel ReleaseDC 

你有:

 GetDC for each pixel read pixel and store value ReleaseDC 

然后处理存储的像素。

也就是说,你可能最好不要使用GetPixel ,因为我似乎记得它非常低效。 我怀疑你有更好的性能,只需将整个屏幕抓到一个位图并从那里获取像素。 也许这个问题的答案可以帮助您: 将屏幕捕获到位图中