导航
  • 主页
  • VC综合技术
  • 互联网技术
  • MFC AppLauncher
  • .NET 技术
  • 界面
  • 进程
  • 算法
  • 硬件/系统
  • 数据库
  • VC++技术资源

紧急求助:如果显示一副图片,该图片的颜色信息已知,而且宽跟高已知?(只能用Windows GDI API,不用MFC)

WinstonSword 2004-04-01 02:18:38
这是我写的代码,可是没作用,请各位兄弟帮忙看看:

HBITMAP bmp ;
bmp= CreateBitmap(iWidth, iHeight, 1, 24, lpvBits);
HDC memorydc = CreateCompatibleDC(hDC);

HGDIOBJ old=SelectObject(memorydc,bmp);
if (old==NULL) return S_OK; //程序到这一句就退出了
BitBlt(hDC,0, 0, iWidth, iHeight, memorydc, 0, 0, SRCCOPY);

DeleteObject(SelectObject(memorydc, old));
DeleteDC(memorydc);

其中lpvBits就是存放着bitmap的颜色信息。
其格式如下(假设width=3.height=1)
{0,0,0,0,0,0,0,0,0} 表示RGB(0,0,0)、RGB(0,0,0)、RGB(0,0,0)这样三个象素。


请诸位兄弟姐妹帮忙看看,原因到底在哪里,不甚感激。
...全文
65 点赞 收藏 1
写回复
1 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
itmaster 2004-04-01
显示位图
好吧,加回到主题上面来吧.在一个窗口上最简单的画图操作得借助于对消息WM_PAINT的处理.当你的窗口第次显示的时候,从最小化状态复原时,或是当这个窗口上面的窗口移开后,Windows将会发送一个WM_PAINT消息给这个窗口,让这个窗口知道它需要重新画它的内容了.当你在屏幕上画某个东西时,这个东西并不是永久性的.如果有什么东西把它遮住的话(比如又有另外一个窗口遮住了我们的当前窗口),它就等于是被涂掉了.那么当显示这个东西的时间来了后,你需要再一次地将它画出来.
HBITMAP g_hbmBall = NULL;

case WM_CREATE:
g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
if(g_hbmBall == NULL)
MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
break;

第一步当然是调用位图,这对于位图资源来说是非常简单的,这和调用其它资源没有什么显著的区别.然后我们就可以开始画了....
case WM_PAINT:
{
BITMAP bm;
PAINTSTRUCT ps;

HDC hdc = BeginPaint(hwnd, &ps);

HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = SelectObject(hdcMem, g_hbmBall);

GetObject(g_hbmBall, sizeof(bm), &bm);

BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);

EndPaint(hwnd, &ps);
}
break;

获得窗口设备上下文
开始我们声明我们需要的两个变量.请注意第一个是BITMAP,不是HBITMAP.BITMAP是一个结构体,这个结构体用来存贮有关HBITMAP的信息.而HBITMAP才是一个实际上的图形设备接口GDI对象.我们需要一种方法来获取HBITMAP的高度和宽度,这样我们使用了GetObject()函数.这个函数和它的名字不同,它并不是去获得一个对象,而是这个对象的相关信息."GetObjectInfo"也许才是一个更合适的名称.GetObject()函数可以为各种各样类型的图形设备接口对象工作,区别的地方就在于这个函数的第二个参数和结构的大小.

PAINTSRUCT是一个结构,这个结构包含了有关要绘画的窗口的信息,以及要画什么的确切信息.对于最简单的任务,你可以简单地忽略它包含的信息,但是在调用BeginPaint()函数时,我们需要PAINTSTRUCT.BeginPaint()函数正如它的名字所提示的那样,它是专门设计用来处理WM_PAINT消息的.但如果处理的不是WM_PAINT消息,你可以使用GetDc()函数,这个函数我们等一下将在计时器动画中接触到...但是对于WM_PAINT,我们使用BeginPaint()函数和EndPaint()函数.

BeginPaint() BeginPaint()函数返回我们的一个设备上下文句柄HDC,它代表的是一个句柄,一个处理WM_PAINT消息的句柄.我们在这个设备上下文句柄HDC上执行的任何画画的操作都会立即在屏幕上显示出来.

为位图建立内存设备上下文
正如我上面提到的那样,为了画出一幅位图,我们需要在内存中创建一个设备上下文....要做到这一点最容易的方法就是用CreateCompatibleDC()函数.这给了我们一个内存设备上下文,它与设备上下文句柄在窗口的颜色深度和显示属性方面保持了一致性.

现在我们调用SelectObject()函数来选择位图,将位图放到这个小心的存放了默认位图的设备上下文中,这样我们等一下就可以替代它,而且不会泄漏图形设备接口GDI对象.

画图
一旦我们得到了要填充到BITMAP结构中的位图的大小尺寸后,我们可以调用BitBlt()函数把图片从我们的内存设备上下文拷贝到窗口设备上下文,然后在显示在屏幕上.正如以往一样,你可以在MSDN中查找每一个参数,但是简而言之它们是:目的地,位置和大小,源地址和原始位置,最后就是Raster Operation(ROP 代码),这个代码是指定如何完成拷贝.在这里,我们只是希望简单地拷贝.

BitBlt() is probably the all time happiest function in all of the Win32 API and is the staple diet of anyone learning to write games or other graphics applications in windows. It was probably the first API that I memorised all the parameters to.

清除
在这时,们位图应该显示在屏幕上,而且我们需要清除它们.第一个要做的事情就是把内存设备上下文恢复成我们刚获得它的状态,这也就意味着要将内存设备上下文中的默认位图重新替换回来,也就是替换成我们保存好的默认位图.下一步我们可以用DeleteDC()函数删除这个内存设备上下文.

最后我们用EndPaint()函数释放从BeginPaint()函数中获取的窗口设备上下文.

消灭一个设备上下文句柄有点麻烦,因为这里至少有三种方法可以做这件事.首先这取决于你是怎么样获取它的.这里有一个获取和释放一个设备上下文句柄的普通方法的列表.

GetDC() - ReleaseDC()
BeginPaint() - EndPaint()
CreateCompatibleDC() - DeleteDC()
最后,当我们的程序终止时,我们希望我们分配的任何资源.从技术上来说,这并不是绝对需要的.因为现代的Windows平台当你的程序存在时,对于释放任何东西都是相当好的.当时掌握我们对象的轨迹总是一个好主意.而且毫无疑问的一点是,在windows中仍然还存在bug,特别是老的版本它不会清除你的所有的图形设备接口对象,假如你没有做一个完全的工作的话.

case WM_DESTROY:
DeleteObject(g_hbmBall);
PostQuitMessage(0);
break;

回复
发动态
发帖子
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……