如何绘制不断变化的图形 [英] how to draw constantly changing graphics

查看:158
本文介绍了如何绘制不断变化的图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在(除Java之外没有这样做,看看史蒂夫麦克劳德的是如何解决它),所以很明显我吸它。在这里当前鼠标的位置64像素拿得出一个形式有点大。问题是,这是一种慢,我不知道从哪里开始固定。



除此之外,我做了一个计时器线程,即不断呼吁更新图形时,它的完成与文本有点FPS,展现真正的东西是如何迅速吸引



图像,例如:(图片是从A中的智能跟踪的信微软VS2010)





来源例如:

 ; 
使用System.Collections.Generic;
使用System.ComponentModel;
使用System.Data这;
使用System.Drawing中;
使用System.Linq的;
使用System.Text;使用System.Windows.Forms的
;使用System.Runtime.InteropServices
;

命名空间缩小
{
公共部分Form1类:表格
{
静态类dllRef
{
函数[DllImport( USER32.DLL)]
[返回:的MarshalAs(UnmanagedType.Bool)
静态的extern BOOL GetCursorPos(出点LPPOINT);

函数[DllImport(user32.dll中)]
静态外部的IntPtr的GetDC(IntPtr的HWND);

函数[DllImport(user32.dll中)]
静态外部的Int32 ReleaseDC(HWND的IntPtr,IntPtr的HDC);

函数[DllImport(GDI32.DLL)]
静态外部UINT与getPixel(IntPtr的HDC,诠释nXPos,诠释nYPos);

//从http://www.pinvoke.net/default.aspx/gdi32/GetPixel.html
静态公共的System.Drawing.Color getPixelColor(INT X,int y)对{
IntPtr的HDC =的GetDC(IntPtr.Zero);
UINT像素=与getPixel(HDC,X,Y);
ReleaseDC(IntPtr.Zero,HDC);
彩色颜色= Color.FromArgb((int)的(象素&放大器; 0x000000FF)
(INT)(象素&放大器; 0x0000FF00)GT;→8,
(INT)(象素&放大器; 0x00FF0000)GT;> 16);
返回色;
}
静态公共System.Drawing.Point getMousePosition(){
点P =新的点();
GetCursorPos(出P);
返回磷;
}
}

公共Form1的(){
的InitializeComponent();
this.Size =新的大小(400,400);
this.Text =图像放大;
this.Location =新点(640,0);
this.image =新位图(320,320);
this.timeRef = DateTime.Now;
this.BackColor = Color.White;
定时T =新的Timer();
t.Interval = 25;
t.Tick + =新的EventHandler(Timer_Tick);
t.Start();
}

无效公开Timer_Tick(对象发件人,EventArgs eArgs){
this.Form1_Paint(这一点,新PaintEventArgs的(this.CreateGraphics(),新的Rectangle(0,0, this.Width,this.Height)));
}

私人布尔isdone = TRUE;
私人INT ITER = 0;
私人位图图像;
私人的DateTime timeRef;
私人无效Form1_Paint(对象发件人,PaintEventArgs的E){
如果(isdone){
isdone = FALSE;
INT步= 40;
点P = dllRef.getMousePosition();
笔myPen =新朋(Color.Gray,1);
SolidBrush myBrush = NULL;
位图图像2 =新位图(320,340);

图形GC = Graphics.FromImage(IMAGE2);

的for(int x = 0; X< 8; X ++){
为(INT Y = 0; Y< 8; Y ++){
myBrush =新SolidBrush (dllRef.getPixelColor(PX - 4 + X,PY - 4 + Y));
gc.FillEllipse(myBrush,X *一步,Y *一步,一步 - 3步 - 3);
gc.DrawEllipse(myPen,X *一步,Y *一步,一步 - 3步 - 3);
}
}
StringBuilder的SB =新的StringBuilder();
sb.Append(ITER)
.Append(在帧)
.Append(的String.Format({0:0} ###,((DateTime.Now -this.timeRef).TotalMilliseconds)/ 1000))
.Append(S);
gc.FillRectangle(新SolidBrush(this.BackColor),新的Rectangle(0,320,320,40));
gc.DrawString(sb.ToString(),新的字体(宋体,12),新SolidBrush(Color.Black),10,320);
gc.Dispose();
isdone = TRUE;
ITER ++;
图像= IMAGE2,
}
e.Graphics.DrawImage(图像,35F,15F);
}
}
}

在改变我做这一是〜98%的速度:

 系统使用; 
使用System.Collections.Generic;
使用System.ComponentModel;
使用System.Data这;
使用System.Drawing中;
使用System.Linq的;
使用System.Text;使用System.Windows.Forms的
;使用System.Runtime.InteropServices
;


命名空间缩小
{
公共部分Form1类:表格
{
静态类dllRef
{
函数[DllImport(user32.dll中)]
[返回:的MarshalAs(UnmanagedType.Bool)
静态的extern BOOL GetCursorPos(出点LPPOINT);

函数[DllImport(user32.dll中)]
静态外部的IntPtr的GetDC(HWND的IntPtr);

函数[DllImport(user32.dll中)]
静态外部的Int32 ReleaseDC(HWND的IntPtr,IntPtr的HDC);

函数[DllImport(GDI32.DLL)]
静态外部UINT与getPixel(IntPtr的HDC,诠释nXPos,诠释nYPos);

//从http://www.pinvoke.net/default.aspx/gdi32/GetPixel.html
静态公共的System.Drawing.Color getPixelColor(INT X,int y)对{
IntPtr的HDC =的GetDC(IntPtr.Zero);
UINT像素=与getPixel(HDC,X,Y);
ReleaseDC(IntPtr.Zero,HDC);
彩色颜色= Color.FromArgb((int)的(象素&放大器; 0x000000FF)
(INT)(象素&放大器; 0x0000FF00)GT;→8,
(INT)(象素&放大器; 0x00FF0000)GT;> 16);
返回色;
}
静态公共System.Drawing.Point getMousePosition(){
点P =新的点();
GetCursorPos(出P);
返回磷;
}
}

公共Form1的(){
的InitializeComponent();
this.Size =新的大小(400,400);
this.Text =图像放大;
this.Location =新点(640,0);
this.image =新位图(320,340);
this.timeRef = DateTime.Now;
this.BackColor = Color.White;
定时T =新的Timer();
t.Interval = 25;
t.Tick + =新的EventHandler(Timer_Tick);
t.Start();
}

公共无效Timer_Tick(对象发件人,EventArgs eArgs){
this.Form1_Paint(这一点,新PaintEventArgs的(this.CreateGraphics(),新的Rectangle(0,0, this.Width,this.Height)));
}

私人布尔isdone = TRUE;
私人INT ITER = 0;
私人位图图像;
私人的DateTime timeRef;
私人无效Form1_Paint(对象发件人,PaintEventArgs的E){
如果(isdone){
isdone = FALSE;
INT步= 40;
点P = dllRef.getMousePosition();
SolidBrush myBrush = NULL;
位图HC =新位图(8,8);使用(笔myPen =新朋(Color.Gray,1))使用使用(显卡GF =图形(图形GC = Graphics.FromImage(图片))



。 FromImage(HC))
{
gf.CopyFromScreen(PX - 4,PY - 4,0,0,新尺寸(8,8),
CopyPixelOperation.SourceCopy);

的for(int x = 0; X< 8; X ++)
{
为(INT Y = 0; Y< 8; Y ++)
{
myBrush =新SolidBrush(hc.GetPixel(X,Y));
gc.FillEllipse(myBrush,X *一步,Y *一步,一步 - 3步 - 3);
gc.DrawEllipse(myPen,X *一步,Y *一步,一步 - 3步 - 3);
}
}

双TS =((DateTime.Now - this.timeRef).TotalMilliseconds)/ 1000;
StringBuilder的SB =新的StringBuilder();
sb.Append(++ ITER).Append(在帧).Append(的String.Format({0:0} ###,TS))。追加(S) ;

gc.FillRectangle(新SolidBrush(this.BackColor),新的Rectangle(0,320,320,40));
gc.DrawString(sb.ToString(),新的字体(宋体,12),新SolidBrush(Color.Black),10,320);

}

isdone = TRUE;
}
e.Graphics.DrawImage(图像,35F,15F);
}
}
}


解决方案

有一件事情,应该加快速度是,如果你做的的GetDC 只有一次,并得到你所需要的,然后调用像素的 ReleaseDC 。因此,而不是:

 每个像素
的GetDC
读取的像素
ReleaseDC

您有:

 的GetDC 
为每个像素
读取的像素和存储价值
ReleaseDC

然后处理存储的像素。



这是说,你可能不关闭使用更好的 GetPixel 所有的,因为我似乎记得它是非常低效的。我怀疑你有更好的表现就可以抓取整个屏幕成位图,并从那里得到的像素。也许回答这个问题可以帮助你:的http:// stackoverflow.com/questions/362986/how-may-i-capture-the-screen-in-a-bitmap


Have not done this before (except in java, look how Steve McLeod fixed it), so obviously I suck at it. Here 64 pixels around current mouse position get drawn little bigger on a form. Problem is, that it's 'kind of' to slow, and I have no idea where to start fixing.

Besides that, I made a timer thread, that constantly calls update graphics when it's finished and a little fps like text, to show really how fast things are drawn.

Image example: (Image is from letter 'a' in "IntelliTrace" in Microsoft VS2010)

Source example:

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(p.X - 4 + x, p.Y - 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);
        }
    }
}

After changes i made, this one is ~98% faster:

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(p.X - 4, p.Y - 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);
        }
    }
}

解决方案

One thing that should speed things up is if you do the GetDC just once and get all of the pixels you need, then call ReleaseDC. So rather than:

for each pixel
  GetDC
  Read Pixel
  ReleaseDC

You have:

GetDC
for each pixel
  read pixel and store value
ReleaseDC

Then process the stored pixels.

That said, you're probably better off not using GetPixel at all, as I seem to remember it being terribly inefficient. I suspect you'd have better performance just grabbing the entire screen into a bitmap and getting the pixels from there. Perhaps the answer to this question will help you: http://stackoverflow.com/questions/362986/how-may-i-capture-the-screen-in-a-bitmap

这篇关于如何绘制不断变化的图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆