如何绘制不断变化的图形

2024-01-06

以前没有这样做过(除了在java中 https://stackoverflow.com/questions/3742731/java-how-to-draw-constantly-changing-graphics,看看怎么样史蒂夫·麦克劳德 https://stackoverflow.com/users/2959/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(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);
        }
    }
}

经过我的更改后,这个速度快了约 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(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);
        }
    }
}

应该加快速度的一件事是如果你这样做GetDC只需一次即可获取所需的所有像素,然后调用ReleaseDC。所以而不是:

for each pixel
  GetDC
  Read Pixel
  ReleaseDC

你有:

GetDC
for each pixel
  read pixel and store value
ReleaseDC

然后处理存储的像素。

也就是说,你最好不要使用GetPixel根本没有,因为我似乎记得它的效率非常低。我怀疑您只需将整个屏幕抓取到位图并从那里获取像素即可获得更好的性能。也许这个问题的答案会对你有所帮助:将屏幕捕获为位图 https://stackoverflow.com/questions/362986/how-may-i-capture-the-screen-in-a-bitmap

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何绘制不断变化的图形 的相关文章

  • 将 Stream 反序列化为 List 或任何其他类型

    尝试将流反序列化为List
  • 在动态事件处理程序中引用“this”

    在我的 myClass 类中 我使用 Reflection Emit 为 myClass 类成员之一动态编写事件处理程序 我已经成功地做到了这一点 现在 我想修改事件处理程序以调用 myClass 类中的实例方法之一 但是 我无法弄清楚如何
  • 起订量要求?违背了目的?

    是否需要虚拟化您想要模拟的所有属性访问器就违背了模拟的目的 我的意思是 如果我必须修改我的对象并虚拟化我想要模拟的每个访问器 我难道不能继承我的类并自己模拟它吗 你的问题非常有效 但如果你仔细想想 没有其他方法可以模拟课程 如果你采用一个接
  • SharpZipLib - 将文件夹/目录添加到 zip 存档

    通过示例 我很好地掌握了如何提取 zip 文件 几乎在每个示例中 识别 ZipEntry 是否为目录的方法如下 string directoryName Path GetDirectoryName theEntry Name string
  • 为什么 VB.NET 和 C# 中针对值检查 null 存在差异?

    In VB NET http en wikipedia org wiki Visual Basic NET有时候是这样的 Dim x As System Nullable Of Decimal Nothing Dim y As System
  • 将图像文件从网址复制到本地文件夹?

    我有该图像的网址 例如 http testsite com web abc jpg http testsite com web abc jpg 我想将该 URL 复制到 c images 中的本地文件夹中 而且当我将该文件复制到文件夹中时
  • 如何使用 MVVM 更新 WPF 中编辑的数据? [复制]

    这个问题在这里已经有答案了 我正在为聊天应用程序构建 UI 设计 在尝试更新所选联系人的消息时遇到问题 选择现有联系人 选择编辑选项 然后编辑其属性 例如用户名和图像 后 唯一进行的更改是联系人的用户名和图像 我仍然想更改 MessageM
  • 是否允许将类模板类型参数键入相同的名称?

    这似乎可以在 MSVC 中按预期编译甚至工作 但它是合法的 C 代码吗 它是否能保证执行此处所期望的操作 即将模板类型导出到结构体的同名用户 template
  • 为什么这个函数指针赋值在直接赋值时有效,但在使用条件运算符时无效?

    本示例未使用 include 在 MacOS10 14 Eclipse IDE 上编译 使用 g 选项 O0 g3 Wall c fmessage length 0 假设这个变量声明 int fun int 这无法通过 std touppe
  • 静态类变量与外部变量相同,只是具有类作用域吗?

    在我看来 静态类变量与外部变量相同 因为你只需要declare它在static int x extern int x语句 并在其他地方实际定义它 通常在 cpp 文件中 静态类变量 h file class Foo static int x
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 如何在编译C代码时禁用警告?

    我正在使用 32 位 Fedora 14 系统 我正在使用编译我的源代码gcc 有谁知道如何在编译c代码时禁用警告 EDIT 是的 我知道 最好的办法是修复这些警告以避免任何未定义 未知的行为 但目前在这里 我第一次编写了巨大的代码 并且在
  • 如何在ggplot2中使用希腊符号?

    我的类别需要用希腊字母命名 我在用ggplot2 并且它与数据配合得很好 不幸的是 我无法弄清楚如何将这些希腊符号放在 x 轴上 在刻度线处 并使它们出现在图例中 有什么办法可以做到吗 更新 我看了一下link https github c
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 操纵 setter 以避免 null

    通常我们有 public string code get set 如果最终有人将代码设置为 null 我需要避免空引用异常 我尝试这个想法 有什么帮助吗 public string code get set if code null cod
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 正确使用“extern”关键字

    有一些来源 书籍 在线材料 解释了extern如下 extern int i declaration has extern int i 1 definition specified by the absence of extern 并且有支
  • 如何使用收益返回和递归获得字母的每个组合?

    我有几个像这样的字符串列表 可能有几十个列表 1 A B C 2 1 2 3 3 D E F 这三个仅作为示例 用户可以从几十个具有不同数量元素的类似列表中进行选择 再举个例子 这对于用户来说也是一个完全有效的选择 25 empty 4 1
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • g++ C++0x 枚举类编译器警告

    我一直在将可怕的 C 类型安全伪枚举重构为新的 C 0x 类型安全枚举 因为它们是way更具可读性 不管怎样 我在导出的类中使用它们 所以我明确地将它们标记为导出 enum class attribute visibility defaul

随机推荐

  • 更新 Heroku 上的堆栈

    我有一个小应用程序在那里运行 使用heroku buildpack perl https github com miyagawa heroku buildpack perl构建包 这只是一个小Plack http p3rl org Plac
  • 调用析构函数后访问对象

    在下面的代码中我调用 destructor 明确地 但是该对象仍然可以访问 我怎样才能删除它 让它消失 class Queue public node top NULL points to the top of the queue meth
  • DbContext 不返回本地对象

    我正在使用工作单元模式 在 webapi 请求上执行所有操作后调用 dbcontext SaveChanges 在请求的一部分中 我将一个新客户添加到 dbcontext dbContext Customers Add new Custom
  • 未找到 com.google.android.gms.internal.zzaja 的类文件

    我正在使用 Fragment 来设计 Firebase 简单登录注册 我收到错误OnCreateView 初始化方法 auth FirebaseAuth getInstance 错误 错误 58 28 错误 无法访问 zzaja 未找到 c
  • 如何将 C# 变量添加到 html 模态

    In my ASP Net应用程序 我有一个启动模式的按钮 这onClick事件触发启动模式的 C 后台代码 然后 我调用数据表并使用数据表中的值填充字符串变量 protected void uxTicketHistoryButton Cl
  • SQL Server 2008:多语句UDF可以返回UDT吗? [复制]

    这个问题在这里已经有答案了 多语句 UDF 是否有可能返回用户定义的表类型 而不是在其返回参数中定义的表 所以而不是 CREATE FUNCTION MyFunc p1 int p2 char RETURNS SomeVar TABLE c
  • 从用户定义的设置中设置 Info.plist 中的布尔属性

    通过用户定义的设置在 Info plist 文件中设置属性非常简单 只需使用 YOUR SETTING NAME 作为值即可 但是 是否可以对布尔属性执行此操作 布尔值的 plist 文件中的结构是
  • 从 Android 上的 Gmail 应用程序下载附件的意图过滤器

    我有带有意图过滤器 ACTION VIEW 的Android应用程序来打开文件并将其导入到我的应用程序中 我希望将文件附件从 Gmail 应用程序下载到我的应用程序中 某些文件类型 即 jpg png txt 可以正确保存 但有些文件类型则
  • 浮点数输出中的“%!s”是什么?

    我得到的坐标 位置 是 2 个 float64 数字的输出 它看起来像这样 s float64 42 539679 s float64 42 601339 这是我第一次看到这样的东西 那么 s 是什么 TypeOf 表示 s float64
  • 如何在 Spring Boot 中从 application.yml 读取具有特殊字符的属性

    应用程序 yml mobile type mobile codes BlackBerry BBSS Samsung SAMS Samsung Vodafone SAMSVV 从应用程序 yml 文件中读取 三星 沃达丰 密钥时 我们得到了
  • 如何替换 SwiftUI 中已弃用的 .animation() ?

    The animation 修饰符在 iOS 15 中已被弃用 但我不确定我是否理解 Xcode 建议的等效项 animation value works animation easeInOut duration 2 animation w
  • 使用 Mercurial 在多个服务器上自动进行 Web 部署

    最近 当我们开始使用 Mercurial 进行 Web 开发时 我一直在研究 Mercurial 的一些工作流程 我们需要一种自动化的方法来将推送到测试和实时实例的更改传播到多个端点 这是这个想法的示意图 Dev Push V Push L
  • 将日历转换为本地日期

    我决定从 5 5 升级到 Optaplanner 7 5 Nurseroster 但遇到了一些愚蠢的问题 下面是其中之一 我之前使用的例程如下 然而现在新版本需要 LocalDate 我有一个 MySql 数据库后端 用户通过日历选择名册日
  • 插入 SQL VBA

    我试图选择第一个表中但不在第二个表中的记录 并使用 VBA 中的 sql 语句将它们插入到第二个表中 我已在下面启动它 但我不确定为什么它不起作用 我对 sql 相当陌生 因此我们将不胜感激 MySQL INSERT INTO Client
  • 无法将 R 中的因子转换为数字

    我试过了 i lt as numeric as character Impress i lt as numeric as character levels Impress i lt as numeric paste Impress 我总是得
  • 使用 LCDS 将不可变的 Java 类序列化为 ActionScript

    我有一个复杂的对象 该对象由 LCDS DataServices 数据管理进行管理 并使用自定义汇编程序进行创建 更新等 绝大多数对象层次结构都已正确序列化 反序列化 但在序列化不可变的 java 类时我遇到了障碍 在仅使用 java 的世
  • 使用 chrome.storage.local.set 存储数据的安全性如何

    我使用 chrome storage local set 将选项数据存储在 chrome 扩展中 这些数据的安全性如何 有权访问其存储文件的任何人都可以轻松读取它吗 它不安全 并且根据 chrome storage 官方文档 https d
  • 悬停标题文本和背景的本机/默认颜色

    在 chrome firefox 中 将鼠标悬停在元素上会显示其标题 标题为黄色背景和黑色文本 有谁知道exact每种颜色都是十六进制还是 RGB 谢谢 蒂姆 拍摄屏幕截图 在 Photoshop 中打开它 使用颜色选择器查找值 在 OSX
  • C++ Protobuf 添加已分配的重复数字字段

    我有一条简单的消息 其中包含大量重复的数字字段 syntax proto3 option cc enable arenas true message bigData repeated double info 1 在运行时 数据到达时已经分配
  • 如何绘制不断变化的图形

    以前没有这样做过 除了在java中 https stackoverflow com questions 3742731 java how to draw constantly changing graphics 看看怎么样史蒂夫 麦克劳德