Memory DC与hBitmap

DC 即Device Context,是GDI内部的一个资料结构,一个DC会和某个特定的显示设备(如打印机、屏幕等)产生关联。我们如果能取得该DC的handle 那我们便可以在这显示设备上写字、画图。

在Form 或Picturebox中都有一个hdc的属性,指的便是这东西,但是,怎麽又会有一个Memory DC呢?这是一个存在记忆体内的 dc ,它除了不像form picturebox能将图形、文字显示出来之外,其他的几乎都相同,它也可以用在所有的 GDI API 呼叫之上,其实我们在VB中早就有使用上这 Memory DC 了,只是没有自觉。当我们设 form picturebox的AutoRedraw = True时, hdc所指的便是Momoory DC,这时我们在其上作绘图动作,都没有显示在form上,这便是先前说的,它只是在记忆体中,不会真的画出图。而我们下 refresh指令时,便是将这MemoryDC上的图,copy到 form/PictureBox上。

另外我们也可以使用

CreateCompatibleDC() API 它传入一个 hDc ,代表产生的 Memory DC和 hdc相容,若传0则是与屏幕相容的 Memory DC hMemDC = CreateCompatibleDC(0)

这时候,该hMemDC所指的绘图区有多大呢?其实只有一个单色Pixel,直到我们使用SelectObject( hMemDC, hBitmap)

那hMemDC显示区就会有和hBitmap一样的宽度、高度、颜色选择等。 而且我们在hMemDC上的任何绘图,也都会反映在 hBitMap上,也就是说,原本hBitMap所指的图,於SelectObject(hMemDC, hBitMap)後,我们使用gdi函式在hMemDC上画一条线,那麽该hBitmap所指的图也会有一条线了。

接下来令人心烦的是hBitmap如何取得,在vb可以使用以下的两个方式:

1.使用Form/PictureBox上Image属性(它是个物件),不管我们放入Form/PictureBox中Picture属性的图是否是Bitmap图,Image所指的,是一份存在记忆体中的Bitmap图, (这是我的想法,因我查了一下,Image.Type 永远说是BitMap图,而不管Picture属性的图是那一种类型),而Image.Handle所指,便是这bitmap图的hBitmap。但是,不要高兴太早,这hBitmap的范围可比你想像中的大,如果有一个PictureBox大小100*100 而设定一个50*50 的图於其上, 那PictureBox.Image的大小是100*100,因为它所指的是整个PictureBox的图,而刚好PictureBox上有图形显示於其上。而如何才能取得 50*50的hBitMap呢,我会用"偷吃部",指定 PictureBox比50*50小(如:1*1)而且设定AutoSize = True,BorderStyle = 0 当我们用LoadPicture把图形放进来时,

PictureBox会放大成与该图的大小相同,那麽,PictureBox.Image的大小也会随之放大

2.使用StdPicture物,而後用LoadPicture将图放进来,但是这一定只能使用BitMap图,

要不然StdPicture.Handle不会是hBitmap,而是其他Handle( 如:hIcon)如果使用api,可以使用 hBitMap = CreateCompatibleBitmap(hDc, Height, Width) 那会产生一个高Height * 宽 Width大小(Pixels)的BitMap图,而且该BitMap图和Hdc所指的物件有相同的颜色数,且Bits Per Pixels也相同。然而该BitMap图里什麽也没有,一般我们接着使用 SelectObject(hdc, hBitMap) 而利用hDc来绘图,这一切的绘图就会反映在hBitMap上,而我们一般会以MemoryDC来当作hdc的传入值,等绘图动作完了,我们便可以把这Memory DC删除(DeleteDC()),而只单纯的留下hBitmap。如:

hMemDc = CreateCompatibleDc(0)

hBitMap = CreateCompatibleBitMap(Screen.ActiveForm.hDc, 100,100)

Call SelectObject(hMemDc, hBitMap)

'执行一些绘图指令,如:Textout() StretchBltStretchBlt() BitBlt()DeleteDC hMemDc

当然,如果我们不知道图形的大小时,CreateCompatibleBitMap就不是那麽方便了,要知道图形的大小我们也可以由PictureBox.Picture中Width/Height这两个属性来做,但是还得经过一下转换,因为这两个值的单位是HiMetric,要使用ScaleX() ScaleY()来转成Pixels即ScaleX(picture1.Picture.Width, vbHiMetric, vbPixels)才是我们想要的宽度,ScaleY(picture1.Picture.Height, vbHiMetric, vbPixels)才是我们想要的高度 。另外也可以使用以下的方式来取得hBitmap'假设有一个PictureBox而我们事先已Load一个图进来了。

Dim bm As Bitmap, hBmp as Long

GetObject Picture1.Picture, Len(bm), bm '取得PictureBox内图形的的BitMap结构hBmp = CreateBitmapIndirect(bm) '产生一个Bitmap图,该图的大小颜色数由bm所控制 hmemDC = CreateCompatibleDC(Picture1.hDC) SelectObject hmemDC, hBmp 'hmemDC的大小和hBmp相同了

picture1.AutoRedraw = True'将Picture1的图画在hmemDc上,如此,hBmp便是我们所要的。

BitBlt hmemDC, 0, 0, bm.bmWidth, bm.bmHeight, picture1.hDC, 0, 0, vbSrcCopy

时间: 2024-10-03 10:56:36

Memory DC与hBitmap的相关文章

vc应用CPictureEx类(重载CStatic类)加载gif动画

1.PictureEx.h文件: //////////////////////////////////////////////////////////////////////// PictureEx.cpp: implementation of the CPictureEx class.//// Picture displaying control with support for the following formats:// GIF (including animated GIF87a a

将HDC保存为BMP文件

HDC在MSDN中的全称为:The handle of device context.通常,我们都是用来做相应的显示操作.        熟悉WIN32的朋友对于其应该不会陌生,经常采用GetDC,GetWindowDC等等来获取其句柄.而用得最多的,可能就是BeginPaint,如: view plaincopy to clipboardprint? case WM_PAINT:       HDC hdc = BeginPaint(hWnd,&ps);       ...       End

VC中实现带有背景位图的树型控件

当前许多应用程序都在使用树型控件时为其添加了背景位图,增强的控件的魅力,然而对于Visual C++编程爱好者来说,使用Visual C++MFC提供的树型控件(CTreeCtrl)本身就是一个难点,至于如何使该控件能够带有背景位图,那就更加是一个令人困惑的问题了.本实例对CTreeCtrl类进行了增强,不仅使它带有背景位图,而且解决了在点击树型控件时背景位图闪动的问题,另外,通过在对话框中使用该控件来显示三级目录,演示了树型控件的基本使用方法.下图为程序编译后的运行效果图: 图一.带背景图的树

BeginPaint和GetDC的区别

这是个windows编程问题. BeginPaint和GetDC的区别 第一种情况显示出来的字很正常. ********************************************************************************    caseWM_PAINT:          gdc = BeginPaint (hwnd, &ps);          TextOut (gdc, 0, 0, s, strlen (s));          EndPain

Screen Capture

#define PW_WINDOW 9001 #define PW_CLIENT 9002 HBITMAP CMyProgramDlg::CopyScreenToBitmap(LPRECT lpRect) { HDC hScrDC, hMemDC; // screen DC and memory DC int nX, nY, nX2, nY2; // coordinates of rectangle to grab int nWidth, nHeight; // DIB width and he

把图片框的完整内容复制到剪贴板

VB本身不允许你将一个Form.UserControl或PictureBox上的完整图片复制到剪贴板.如果你使用Clipboard.SetData,将只复制被载入这个对象的位图.通过使用API方法,你可以超越这个限制,保证全部内容都被复制,包括你刚刚画上的任何图形. 开始一个新项目,在窗体上放置一个Command和一个PictureBox.将PictureBox的Autoredraw属性设为1.然后添加一个标准模块,把以下代码复制进去. Private Type RECT Left As Lon

程序启动画面

在VC知识库上看到许多有关程序启动画面的程序而我觉得程序讲求的是"简而易懂",不需要太多的技巧,只要程序写的出来就好,于是我以另外一种简便的方式来设计程序启动画面同时在程序启动时播放音效,此程序的关键在于Sleep以及PlaySound这两个API函数与StrectBlt这个函数必须记得连结winmm.lib才可使用PlaySound函数,具体方法如下: 在CSplashWindow::CSplashWindow()建构函数当中加载位图以作为程序启动画面 CSplashWindow::

C/C++项目实战--屏幕截图

模仿腾讯QQ截图功能: // ScreenCapture.cpp : 定义应用程序的入口点. // #include "stdafx.h" #include "ScreenCapture.h" #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING];

mfc-MFC做一个截屏程序,保存到剪切板后怎么打开这个图

问题描述 MFC做一个截屏程序,保存到剪切板后怎么打开这个图 我在做一个MFC截图,不知道代码是否有错,估计没错,现在的疑问是如果代码没错的话,截完图保存到剪切板了,然后到哪里打开这个图void C截图Dlg::GetScreenCapture(){ //桌面窗口的设备上下文DC//画布 HDC hDesktopDC = ::CreateDC(_T(""DISPLAY"")NULLNULLNULL); //加::指出是API函数调用,不是成员函数调用 HDC hMe