金磊 发自 凹非寺
量子位 报道 | 公众号 QbitAI

渲染3D图像,一个「记事本」就够了。

最近,GitHub上一名叫“Kyle Halladay”的小哥,便上传了这样一个项目,用记事本来渲染图像。

效果是这样的:

立方体旋转、阴影变化,还挺有内味的。

还有贪吃蛇效果的:

那么,小哥是如何拿记事本,就做到这些效果的呢?

正确的「记事本」打开方式

据小哥介绍,所有的输入和渲染效果,都是在记事本中完成。

在此之前,需要做一些设置工作。

首先,是将键盘事件(Key Event),发送到正在运行的记事本。

这里就要用到 Visual Studio 提供的一个叫 Spy + + 的工具,可以列出组成给定应用程序的所有窗口。

Spy + + 显示了要找的记事本子窗口是“编辑”窗口。

一旦我知道了这一点,就只需要搞清楚 Win32函数调用的正确组合,用来获得该 UI 元素的 HWND,然后将输入发送过去。

得到的 HWND 是这样的:

HWND GetWindowForProcessAndClassName(DWORD pid, const char* className)
{HWND curWnd = GetTopWindow(0); //0 arg means to get the window at the top of the Z orderchar classNameBuf[256];while (curWnd != NULL){DWORD curPid;DWORD dwThreadId = GetWindowThreadProcessId(curWnd, &curPid);if (curPid == pid){GetClassName(curWnd, classNameBuf, 256);if (strcmp(className, classNameBuf) == 0) return curWnd;HWND childWindow = FindWindowEx(curWnd, NULL, className, NULL);if (childWindow != NULL) return childWindow;}curWnd = GetNextWindow(curWnd, GW_HWNDNEXT);}return NULL;
}

一旦拿到了正确的控件 HWND,在记事本的编辑控件中绘制一个字符,便是使用 PostMessage 向它发送一个 WM char 事件的问题。

接下来,就是建一个内存扫描器 (Memory Scanner),这里要用到一个叫做 CheatEngine 的工具。

基本算法如下:

FOR EACH block of memory allocated by our target processIF that block is committed and read/write enabledScan the contents of that block for our byte patternIF WE FIND ITreturn that address

内存扫描程序需要做的第一件事,就是遍历进程分配的内存。

因为 Windows 上每个64位进程的虚拟内存范围是相同的,所以需要制作一个指向地址0的指针,然后使用 VirtualQueryEx 获取目标程序的虚拟地址信息。

将具有相同内存属性的内容页,组织到 MEMORY basic information 结构中,因此,可能是 VirtualQueryEx 为给定地址返回的结构包含超过1页的信息。

一旦有了第一个 MEMORY basic information 结构,在内存中进行迭代只需要将当前结构的 BaseAddress 和 RegionSize 成员添加到一起,并将新地址提供给 VirtualQueryEx 以获得下一组连续的页面。

char* FindBytePatternInProcessMemory(HANDLE process, const char* pattern, size_t patternLen)
{char* basePtr = (char*)0x0;MEMORY_BASIC_INFORMATION memInfo;while (VirtualQueryEx(process, (void*)basePtr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION))){const DWORD mem_commit = 0x1000;const DWORD page_readwrite = 0x04;if (memInfo.State == mem_commit && memInfo.Protect == page_readwrite){// search this memory for our pattern}basePtr = (char*)memInfo.BaseAddress + memInfo.RegionSize;}
}

然后,是在进程内存中,搜索字节模式 (Byte Pattern)的工作,此处需要一个叫做 ReadProcessMemory 的工具。

一旦内存被复制到本地可见的缓冲区,搜索字节模式就很容易了。

char* FindPattern(char* src, size_t srcLen, const char* pattern, size_t patternLen)
{char* cur = src;size_t curPos = 0;while (curPos < srcLen){if (memcmp(cur, pattern, patternLen) == 0){return cur;}curPos++;cur = &src[curPos];}return nullptr;
}
char* FindBytePatternInProcessMemory(HANDLE process, const char* pattern, size_t patternLen)
{MEMORY_BASIC_INFORMATION memInfo;char* basePtr = (char*)0x0;while (VirtualQueryEx(process, (void*)basePtr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION))){const DWORD mem_commit = 0x1000;const DWORD page_readwrite = 0x04;if (memInfo.State == mem_commit && memInfo.Protect == page_readwrite){char* remoteMemRegionPtr = (char*)memInfo.BaseAddress;char* localCopyContents = (char*)malloc(memInfo.RegionSize);SIZE_T bytesRead = 0;if (ReadProcessMemory(process, memInfo.BaseAddress, localCopyContents, memInfo.RegionSize, &bytesRead)){char* match = FindPattern(localCopyContents, memInfo.RegionSize, pattern, patternLen);if (match){uint64_t diff = (uint64_t)match - (uint64_t)(localCopyContents);char* processPtr = remoteMemRegionPtr + diff;return processPtr;}}free(localCopyContents);}basePtr = (char*)memInfo.BaseAddress + memInfo.RegionSize;}
}

需要注意的是,记事本将屏幕上的文本缓冲区作为 UTF-16数据存储,因此提供给 FindBytePatternInMemory ()的字节模式也必须是 UTF-16。

更多细节描述,可以参考文末的参考链接。

更多的「记事本」玩法

当然,关于记事本的别样玩法,还有好多。

例如,有拿记事本完成「快排」的可视化。

还有用记事本自制绘图软件的。

那么,你还有更炫酷的「记事本」玩法吗?

欢迎在评论区留言推荐~

参考链接

https://github.com/khalladay/render-with-notepadhttp://kylehalladay.com/blog/2020/05/20/Rendering-With-Notepad.htmlhttps://www.bilibili.com/video/BV1v4411e7Gy?from=search&seid=50634434912662370https://www.bilibili.com/video/BV1os411u7vD?from=search&seid=11201980142804134991

—完—

@量子位 · 追踪AI技术和产品新动态

深有感触的朋友,欢迎赞同、关注、分享三连վ'ᴗ' ի ❤

matlab的开方算法_正确的「记事本」打开方式:能渲染3D图像,还能玩贪吃蛇相关推荐

  1. 正确的「记事本」打开方式:能渲染3D图像,还能玩贪吃蛇

    金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 渲染3D图像,一个「记事本」就够了. 最近,GitHub上一名叫"Kyle Halladay"的小哥,便上传了这样一个项 ...

  2. matlab gui打开fig文件,使用Matlab創建GUI時重新定位「.fig」文件GUIDE

    我爲某些構建腳本開發了一個GUI,現在正在部署它.由於腳本將被部署到各種不同點的不同機器上,我需要使用團隊使用的標準目錄格式.使用Matlab創建GUI時重新定位「.fig」文件GUIDE GUI由一 ...

  3. 数据追加用什么函数_RL用算法发现算法:DeepMind 数据驱动「价值函数」自我更新,14款Atari游戏完虐人类!...

    [新智元导读]击败卡斯帕罗夫的「深蓝」并不是真正的人工智能,它过度依赖了人类设计的规则,而最近DeepMind的一项深度强化学习新研究表明,不用人工介入,完全数据驱动,算法自己就能发现算法. 「深蓝」 ...

  4. powerbi如何创建参数_创建PowerBI「参数」轻松搞定动态分析

    静态的分析经常不能满足实际分析的需要,还需要引入动态分析,通过调节某个维度的增减变化来观察对分析结果的影响.在PowerBI中,可以使用「参数」,以切片器的形式来控制变量,与其他指标进行交互,进而完成 ...

  5. 一杯水怎么测试_净水器行业「水」很深?手把手教你轻松选购!

    说到净水器,随着大家对生活品质的要求日益提升,也走入了越来越多的家庭. 我家早就用净水器了,当时住在老小区,管道老化,自来水有股漂白粉味.装了净水器之后,水质果然大大改善. 很多初次购买的朋友,很容易 ...

  6. AI版「女娲」来了!文字生成图像、视频,8类任务一个模型搞定

    来源丨机器之心 作者丨陈萍.小舟 AI会是未来的「造物者」吗? 近来,视觉合成任务备受关注.几天前英伟达的 GauGAN 刚刚上新了 2.0 版本,现在一个新视觉合成模型 Nüwa(女娲)也火了. 相 ...

  7. 「2012-12-29」3x3手机锁屏矩阵图像的组合数量

    这个问题,起源于@lzprgmr 的一个想法.「开手机的手势锁时想到个题,三乘三矩阵一共有几种手势? 注意手势是有向的,且不能重复访问同一节点.」 特地拿着手机试了下,型号是华为的荣耀+,系统是安卓的 ...

  8. python制作贪吃蛇游戏下载_自动玩贪吃蛇,满屏的蛇影当然由python制作AI贪吃蛇!...

    image 前提:本文实现AI贪吃蛇自行对战,加上人机对战,文章末尾附上源代码以及各位大佬的链接,还有一些实现步骤,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什 ...

  9. Ps 初学者教程「43」如何使用图层混合模式合成图像?

    欢迎观看 Photoshop 教程,小编带大家了解如何使用图层混合模式合成图像. 使用 Photoshop 制作合成图像最酷的地方在于,图像的合成有很多方法,某些合成甚至不需要进行任何选择和创建精确的 ...

最新文章

  1. Atitit.文件搜索工具 attilax 总结
  2. HTML+CSS基础(2)-HTML标签的简单介绍和网页注释
  3. 字符设备驱动笔记——中断方式按键驱动之linux异常处理结构(四)
  4. fastdfs 集群 java_FastDFS集群部署(转载 写的比较好)
  5. 并查集 (Union-Find)算法
  6. 浅谈line-height和vertical-align
  7. bzoj 2938: [Poi2000]病毒(AC自动机)
  8. 阶段3 1.Mybatis_12.Mybatis注解开发_8 mybatis注解开发使用二级缓存
  9. 打印容器_化妆品公司购买3D打印机能干什么?
  10. 羡慕别人表格做的快?6个Excel小技巧+25个Excel快捷键!收藏没错
  11. 浏览器 主页 被篡改 ,怎么都修改不回来(包括 Firefox ,google Chrome) KMS激活问题
  12. 用户和组管理及思维导图
  13. 【十八掌●武功篇】第七掌:MapReduce之倒排索引
  14. 手机群控软件免root
  15. 图解:网络硬件的发展史
  16. 使用Pyton将MAC地址转换成指定格式
  17. WPS表格excel实现下拉搜索(简单几步,轻松搞定)
  18. 深度学习解决机器阅读理解任务的研究进展
  19. vim autoformat php,vim - 如何在VI中整理HTML文件的缩进?
  20. 移动端最常用的四个框架

热门文章

  1. windows 安装 php memcached,Windows安装配置php+memcached的方法
  2. oracle 00980,ORA-00980如何解决
  3. 大学计算机测试试题,大学计算机基础 excel测试题 求答案~~喵~~
  4. python爬虫学习(二) 简易网页爬取
  5. Net混淆与用de4dot工具破解
  6. Python的序列化与反序列化
  7. Python面试题40问
  8. Python中type和object的关系
  9. include 路由 php,PHP简单路由
  10. r读取shape文件可视化_【R】提取 PCA 结果并利用 ggplot2 进行可视化