此示例代码手动读取位图文件,使用CreateDIBSection()
使GDI为它分配内存,并创建hbitmap句柄。然后使用MemoryDC将位图绘制到窗口DC:
ftp://ftp.oreilly.com/examples/9781572319950/cd_contents/Chap15/DibSect/DibSect.c
hdc = BeginPaint (hwnd, &ps) ;
...
hdcMem = CreateCompatibleDC (hdc) ;
为什么不能将GetDC()
与NULL
或hwndDesktop
一起使用?为什么我们不能缓存设备上下文而不是重复创建它?
如果机器只有一个显示设备,而我们仅绘制到Windows,为什么我们需要不断协调位图和设备上下文?将像素数据复制到GDI提供的缓冲区后,当该HBITMAP加载到DC中并被绘制时,GDI是否会更新它?如果用户也希望借鉴,是否需要同步访问? (要先致电GDIFlush()
吗?)
当大多数对象属性都是不透明和抽象的时,很难弄清楚这一点。我已经阅读了几乎所有相关的MSDN,很多Petzold的书和一些文章:
Guide to WIN32 Paint for Intermediates
Programming Windows®, Fifth Edition
编辑:
我认为我的问题可以归结为:
设备上下文是显示的类型,还是可以显示的图形数据的实例。一台计算机通常只有少数几个显示器,但可能要显示数百个东西。
答案 0 :(得分:0)
GetDC(NULL)
是屏幕HDC,并且屏幕是共享资源,因此您只应在此HDC上执行读/查询操作。由于DWM,在Vista或更高版本上写入此HDC并不是一个好主意。
由于HDC只能包含一个位图,一个画笔和一支笔,因此Windows /应用程序显然需要图形引擎提供的多个HDC。
您可以指望CreateCompatibleDC
相对便宜一些,我相信Windows可以分发DC缓存。如果要创建游戏/动画类型的应用程序,则可能需要自己缓存其中一些图形对象,而普通的应用程序则不应。
除非在多个线程之间共享GDI对象,否则通常不调用GDIFlush
。如果要混合原始像素字节访问和GDI,可以使用SetDIBits
。
我并没有真正获得“一次屏幕”参数,自Windows 98以来Windows就支持多台显示器,并且您无法做很多事情来阻止用户连接另一台显示器。
答案 1 :(得分:0)
我认为您的问题是您对Microsoft的事物名称,Microsoft的名称“设备上下文”以及诸如“ CreateCompatibleDC”之类的调用感到困惑。
“设备上下文”是一个不好的名字。 Win32文档将告诉您设备上下文是一种数据结构,用于存储用于渲染图形命令的特定设备的状态。这只是部分正确。查看存在的不同类型的DC:(1)屏幕设备上下文,(2)打印机设备上下文,(3)内存中位图使用的设备上下文,以及(4)图元文件设备上下文。在这些文件中,只有(1)或(2)实际上确实在执行文档中声称的工作。在其他情况下,设备上下文用作绘制调用的目标,而不是某些物理设备状态的容器。 (在图元文件DC的情况下确实非常明显:图元文件是Win32的一种古老的东西,基本上只是缓存GDI调用,以供稍后重播,这是一种粗略的矢量格式。)
在Win32的假定的面向对象的编程版本中,设备上下文可以是某个类的实例,这些类实现了暴露图形绘制调用的接口。此类的更好称呼是“ Graphics”之类的东西,实际上在GDI +中实际上就是类似的构造。当我们通过CreateDC,CreateCompatibleDC等“创建”时,我们将创建这些对象之一。当我们获取GetDC时,我们将抓住一个已经存在的对象。
要回答您的问题:
是设备上下文是显示的类型,还是可以显示的图形数据的实例。 ?
从某种意义上讲,它们是显示器的类型。您可以将它们视为具有私有实现的对象类的实例,这些实现公开了公开界面,并公开了绘图命令。
为什么不能将GetDC()与NULL或hwndDesktop一起使用?
不能将GetDC(NULL)用作要在其中选择内存中位图的设备上下文,因为在这种情况下,您需要创建一个尚不存在的设备上下文。 GetDC(NULL)就像已经在使用的单例实例。
因此,通常您通常使用CreateCompatibleDC(NULL)或CreateCompatibleDC(hdcScreen)。同样,CreateCompatibleDC(...)是一个令人困惑的名称。想象一下这里发生的事情的假设的面向对象版本。假设有一个由RasterGraphics,PrinterGraphics和MetafileGraphics实现的IGraphics接口。想象一下“ RasterGraphics”类同时用于屏幕和内存中的位图。然后,CreateCompatibleDC(...)就像工厂调用Graphics.CreateFrom(IGraphics g)一样,它返回一个具有相同具体类型的新实例,并可能初始化了一些状态变量。
为什么我们不能缓存设备上下文而不是重复创建它?
可以。您无需在函数调用之间删除设备上下文。人们经常这样做的唯一原因是它们是一种共享的有限资源,而创建它们的成本很低。我认为实际上,在Windows的旧版本中,它们曾经非常受限制,因此,旧的Win32程序员往往不会将它们从Windows 95的老式内存中缓存出来。
如果该计算机只有一个显示设备,而我们仅绘制到Windows,为什么我们需要不断协调位图和设备上下文?
不要认为CreateCompatibleDC(...)中的“兼容”是“与屏幕协调”,而是将其视为“好吧,Windows,我想创建您的图形界面对象之一,并且我希望像这样的一种,这是一种普通的光栅图形,不适用于打印机或图元文件。”