获得了HBITMAP,如何获得BITMAPINFOHEADER以及位图文件的数据区?

Passants 2004-07-25 03:36:28
获得了HBITMAP,如何获得BITMAPINFOHEADER以及位图文件的数据区?
用来填写函数StretchDIBits?
...全文
792 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
qqhuangshen 2004-07-25
  • 打赏
  • 举报
回复
如果仅仅想使用StretchDIBBits函数,这里给你提供一段代码:
CBitmap m_Bitmap;

m_Bitmap.Attach(hBitmap);

CDC MemDC;

CBitmap *oldBmp;

BITMAP bmpInfo;

int bmWidth,bmHeight;

MemDC.CreateCompatibleDC(pDC);

oldBmp=MemDC.SelectObject(&m_Bitmap);
m_Bitmap.GetBitmap(&bmpInfo); //获取位图的尺寸

bmWidth=bmpInfo.bmWidth;

bmHeight=bmpInfo.bmHeight;

CRect rect;

pDC->GetClientRect(&rect);

pDC->StrechBlt(0,0,bmWidth,bmHeight,&MemDC,0,0,rect.Width,rect.Height,SRCCOPY);

MemDC.SelectObject(oldBmp); //使位图m_Bitmap脱离设备上下文

qqhuangshen 2004-07-25
  • 打赏
  • 举报
回复
先用CBitmap 里的attach函数将HBITMAP选入类中。然后,这里给你提供一个函数
HANDLE DDBToDIB( CBitmap& bitmap, DWORD dwCompression, CPalette* pPal )
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC hDC;
HPALETTE hPal;


ASSERT( bitmap.GetSafeHandle() );

// The function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL;

// If a palette has not been supplied use defaul palette
hPal = (HPALETTE) pPal->GetSafeHandle();
if (hPal==NULL)
hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

// Get bitmap information
bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

// Initialize the bitmapinfoheader
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

// Compute the size of the infoheader and the color table
int nColors = (1 << bi.biBitCount);
if( nColors > 256 )
nColors = 0;
dwLen = bi.biSize + nColors * sizeof(RGBQUAD);

// We need a device context to get the DIB from
hDC = GetDC(NULL);
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);

// Allocate enough memory to hold bitmapinfoheader and color table
hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

if (!hDIB){
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}

lpbi = (LPBITMAPINFOHEADER)hDIB;

*lpbi = bi;

// Call GetDIBits with a NULL lpBits param, so the device driver
// will calculate the biSizeImage field
GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

bi = *lpbi;

// If the driver did not fill in the biSizeImage field, then compute it
// Each scan line of the image is aligned on a DWORD (32bit) boundary
if (bi.biSizeImage == 0){
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
* bi.biHeight;

// If a compression scheme is used the result may infact be larger
// Increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}

// Realloc the buffer so that it can hold all the bits
dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
hDIB = handle;
else{
GlobalFree(hDIB);

// Reselect the original palette
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}

// Get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hDIB;

// FINALLY get the DIB
BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
0L, // Start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi // address for bitmap bits
+ (bi.biSize + nColors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table

if( !bGotBits )
{
GlobalFree(hDIB);

SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}

SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return hDIB;
}
调用系统提供的一些DIB函数就可以获得这些信息(其实,在这个函数过程中。通过锁定句柄已经获得了BITMAPINFOHEADER结构,而通过BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),0L,(DWORD)bi.biHeight,(LPBYTE)lpbi+ (bi.biSize + nColors * sizeof(RGBQUAD)), (LPBITMAPINFO)lpbi,(DWORD)DIB_RGB_COLORS)获得了图像的象素信息)
名牌大灰狼 2004-07-25
  • 打赏
  • 举报
回复
详细教程http://www-scf.usc.edu/~flv/ipbook/chap01.htm
查看位的信息(右键查看): 1.文件头 2.信息头 3.RGB掩码(如果有的话) 显示出来的形式如下: BITMAPFILEHEADER* = 0x02800048 BITMAPFILEHEADER .bfType = 0x4D42 .bfSize = 552158 .bfReserved1 = 0 .bfReserved2 = 0 .bfOffBits = 66 BITMAPINFOHEADER .biSize = 40 .biWidth = 353 .biHeight = 391 .biPlanes = 1 .biBitCount = 32 .biCompression = BI_BITFIELDS .biSizeImage = 552092 .biXPelsPerMeter = 0 .biYPelsPerMeter = 0 .biClrUsed = 0 .biClrImportant = 0 Red Mask = 00FF0000 Green Mask = 0000FF00 Blue Mask = 000000FF 说明: 1.第一行为内存中malloc出来的地址,由于是虚拟内存,不看也罢 2.该程序不止可以查看BITMAPINFOHEADER类型的位, 其余三种类型也可查看,分别为: BITMAPCOREHEADER、BITMAPV4HEADER、BITMAPV5HEADER 3.最后三行的RGB Mask是颜色掩码,对于BITMAPINFOHEADER类型来说,不一定有。 4.右键功能是查看信息,左键是左右镜像操作,由于是底层数据直接每行左右互换, 而对于1、4位深的这两种位,底层数据操作涉及位操作,而我还在写这个位类, 故暂不支持,只支持8位以上的水平镜像操作。 5.支持剪切板操作,并且是以CF_DIB或CF_DIBV5呼叫GetClipboardData函数的, 复制时,也是以该参数呼叫SetClipboardData函数的。 你可以复制其他地方的片过来,以查看片属性。 6.程序中运行中保存在内存中的片是BITMAPFILEHEADER*指针,不是HBITMAP, 呼叫的显示函数是SetDIBitsToDevice函数。 7.鼠标在片上移动是,右边填充鼠标点的颜色,标题栏也有相关显示。 下边显示鼠标点附近11*11像素范围的放大像,正中间用十字叉线画出。 取色是直接在底层取数据解析。 8.改程序在《windows程序设计》上的一个例子改编而来,并且正在完善该位类中, 以加入更多丰富的底层操作功能。 改试验程序主要供想研究位结构的人查看用。 9.windows搞出了4种位种类,真作孽~~ 另,16、24、32位深的位也可以有颜色表的,该程序已考虑在内。 10.下面四种压缩格式暂不支持: BI_RLE8、BI_RLE4、BI_JPEG、BI_PNG 11.随带的附件中,有几张不同格式的位,你可以试验打开查看。 有问题联系:hastings1986@163.com
windows平台上支持BITMAPCOREHEADER、BITMAPINFOHEADER、BITMAPV4HEADER、BITMAPV5HEADER四种类型位的类库! 简单用法举例: DibBitmap bmp,ret,tmp; bmp.Open(_T("E:\\bmp.bmp"));//打开 bmp.ConvertBit(4,ret);//转为4位位,ret保存返回值 ret.RotateLeft(tmp);//向左旋转90度,tmp保存返回值 tmp.Invert();//所有像素反色,即RGB(1,2,3)变为RGB(254,253,252) tmp.At(10,10)=tmp.At(20,20);//单个像素点的取值和赋值操作 tmp.At(10,20)=ret.At(30,30);//注意,设置成的颜色如果颜色表内不存在,会设置成相近色 tmp.At(20,10)=RGB(255,0,0); bmp.AlphaBlend(0,0,tmp,128,RGB(255,255,255),true);//tmp以透明度128画到bmp的(0,0)处,其中tmp中的白色会镂空 bmp.Mirror();//bmp水平翻转 bmp.ConvertBit(16,ret,true);//转为5-6-5型16位位,ret保存返回值 ret.SetClipbrd();//存入剪切板中 ret.Save(_T("E:\\bmp2.bmp"));//保存到文件 该类的头文件接口大致如下: class DibBitmap { BITMAPFILEHEADER* m_pbmfh; DWORD m_size;//保存m_pbmfh中malloc出来的内存大小,即是capacity//不为0时保证像是可以处理的 public: enum BmType{NONE=0,CORETYPE,INFOTYPE,V4TYPE,V5TYPE}; public: class reference { //略.. }; public://DibBitmap01.cpp DibBitmap(); explicit DibBitmap(LPCTSTR pstrFileName); explicit DibBitmap(BITMAPFILEHEADER* pbmfh);//只是简单的赋值给成员变量m_pbmfh DibBitmap(HDC hdc, HBITMAP hBitmap, int BitCount);//1,4,8;16,24,32 DibBitmap(const DibBitmap& rhs); ~DibBitmap(); bool Open(LPCTSTR pstrFileName);//打开失败会Close() bool Save(LPCTSTR pstrFileName)const; void Close(); void Swap(DibBitmap& rhs); DibBitmap& operator=(const DibBitmap& rhs);//不一定申请过新内存 public://DibBitmap01.cpp BITMAPFILEHEADER* Get();//获取文件头 const BITMAPFILEHEADER* Get()const; BITMAPINFOHEADER* GetInfoHead();//获取信息头 const BITMAPINFOHEADER* GetInfoHead()const; RGBQUAD* GetQuad();//获取颜色表//没有颜色表,则返回NULL const RGBQUAD* GetQuad()const; BYTE* GetByte();//获取素位 const BYTE* GetByte()const; bool GetMask(DWORD* dwMask,bool b565=false)const; //dwMask个数为四,需要屏蔽码时,依次存入RGB屏蔽码,并返回true //当为BITMAPV4HEADER以上时,还存入AlphaMask;b565参数同GetClr bool Attach(BITMAPFILEHEADER* pbmfh); BITMAPFILEHEADER* Detach();//返回值最后须free掉 HBITMAP CreateBitmap(HDC hdc)const;//返回值最后须DeleteObject掉 HBITMAP CreateDibSection ()const;//返回值最后须DeleteObject掉 BmType Type()const; DWORD Capacity()const;//返回m_size的值//注意,此值可能小于实际malloc的内存长度 DWORD FileSize()const;//整个文件的大小//不是返回m_size的值,m_size的值大于等于此返回值 DWORD BitsSize()const;//素位的大小,即去掉文件头,信息头和颜色表之后的大小 DWORD Offset()const;//素位的偏移量 LONG Width()const; LONG Height()const;//可能为负值 WORD Planes()const; WORD BitCount()const; DWORD ClrUsed()const; //一般是4,8位才小于2^(4,8),其余的等于对应颜色数,m_pbmfh为空时返回0,32位时,返回-1,16位555位颜色数按565算 public://DibBitmap02.cpp LPTSTR DisplayDibHeader (LPTSTR szBuffer)const;//szBuffer得大于1200个//返回szBuffer RGBQUAD GetClr(size_t x,size_t y,bool b565=false)const; //获取(x,y)处的颜色值,已考虑方向问题,b565只有在16位深位且没有屏蔽码时才有用,指明是5-5-5还是5-6-5 COLORREF GetRGBClr(size_t x,size_t y,bool b565=false)const;//条件同上//返回的最高位为0 bool GetClipbrd(HWND hwnd);//失败不一定会Close() void SetClipbrd(HWND hwnd)const; //If hwnd is NULL, the open clipboard is associated with the current task. void Mirror(bool bHoriz);//镜像//false表示垂直镜像 public://DibBitmap03.cpp void Invert(bool b565=false);//反色//在这里b565参数不起任何作用 RGBQUAD Invert(size_t x,size_t y,bool b565=false);//(x,y)处的颜色反色,返回反色后的近似颜色 RGBQUAD SetClr(size_t x,size_t y,RGBQUAD quad,bool b565=false);//设置颜色,返回设置成的最相近的颜色 COLORREF SetRGBClr(size_t x,size_t y,COLORREF clr,bool b565=false);//设置颜色,返回设置成的最相近的颜色 //以下两个函数相当牛逼,可直接引用修改颜色 COLORREF At(size_t x,size_t y,bool b565=false)const;//获取(x,y)处的颜色 reference At(size_t x,size_t y,bool b565=false);//获取(x,y)处的颜色引用,可直接进行修改 void AlphaBlend(int x,int y,const DibBitmap& rhs,BYTE bAlpha,COLORREF clr,bool bClr=false,bool b565=false); //把rhs以透明度bAlpha画到this中的(x,y)处(可以为负),注意:当&rhs==this时直接返回,啥也不操作 //若bClr为true,则clr参数有用,rhs中颜色值为clr的像素点完全透明 void RotateLeft(DibBitmap& ret)const; //this旋转(逆时针90度)后存入ret中,若this原先为空,则不改变ret,注意:当&ret==this时直接返回,啥也不操作 void RotateRight(DibBitmap& ret)const; //this旋转(顺时针90度)后存入ret中,若this原先为空,则不改变ret,注意:当&ret==this时直接返回,啥也不操作 void RotateOpposite();//旋转180度,注意后面没有const,此函数是旋转自身 public://DibBitmap04.cpp bool ConvertBit(WORD BitCount,DibBitmap& ret,bool b565=false)const; //转为同类型的不同位数位//1,4,8;16,24,32,注意:当&ret==this时直接返回,啥也不操作 }; 说明: 此类支持四种位格式: BITMAPCOREHEADER、BITMAPINFOHEADER、BITMAPV4HEADER、BITMAPV5HEADER。 该类像素点坐标序号从0开始,原点位于位左上角,不管位信息头的高度字段是否为负,内部都已作转化处理 暂不支持这四种位的以下几种情况: 1、biCompression字段为BI_RLE4,BI_RLE8,BI_JPEG,BI_PNG的位; 2、BITMAPV5HEADER时,bV5CSType字段等于PROFILE_LINKED或PROFILE_EMBEDDED时的位。 有问题联系:hastings1986@163.com
用于片处理,包括打开,存储,移动等,。 //====================================================================== // 文件: Dib.cpp // 内容: 设备无关位类-源文件 // 功能: (1)位的加载与保存; // (2)位信息的获取; // (3)位数据的获取; // (3)位的显示; // (4)位的转换; // (5)位相关判断; //====================================================================== #include "StdAfx.h" #include "Dib.h" //======================================================= // 函数功能: 构造函数,初始化数据成员 // 输入参数: 无 // 返回值: 无 //======================================================= CDib::CDib(void) { // 数据成员初始化 strcpy(m_fileName, ""); m_lpBmpFileHeader = NULL; m_lpDib = NULL; m_lpBmpInfo = NULL; m_lpBmpInfoHeader = NULL; m_lpRgbQuad = NULL; m_lpData = NULL; m_hPalette = NULL; m_bHasRgbQuad = FALSE; m_bValid = FALSE; m_rgbsum=0; } //======================================================= // 函数功能: 析构函数,释放内存空间 // 输入参数: 无 // 返回值: 无 //======================================================= CDib::~CDib(void) { // 清理空间 Empty(); } //======================================================= // 函数功能: 从文件加载位 // 输入参数: LPCTSTR lpszPath-待加载位文件路径 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::LoadFromFile(LPCTSTR lpszPath) { // 记录位文件名 strcpy(m_fileName, lpszPath); // 以读模式打开位文件 CFile dibFile; if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite)) { return FALSE; } // 清理空间 Empty(FALSE); // 为位文件头分配空间,并初始化为0 m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); // 读取位文件头 int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { return FALSE; } // 判断此文件是不是位文件(“0x4d42”代表“BM”) if(m_lpBmpFileHeader->bfType == 0x4d42) { // 是位文件 //AfxMessageBox("m_lpBmpFileHeader->bfType == 0x4d42"); // 计算除位文件头的空间大小,分配空间并初始化为0 DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER); m_lpDib = new BYTE[dwDibSize]; //(LPBYTE) new BYTE[lHeight*lineBytes24] //m_lpOldDib = new BYTE[dwDibSize]; memset(m_lpDib, 0, dwDibSize); //memset(m_lpOldDib, 0, dwDibSize); // 读取除位文件头的所有数据 dibFile.Read(m_lpDib, dwDibSize); //dibFile.Read(m_lpOldDib, dwDibSize); // 关闭位文件 dibFile.Close(); // 设置位信息指针 m_lpBmpInfo = (LPBITMAPINFO)m_lpDib; // 设置位信息头指针 m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib; // 设置位颜色表指针 m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize); // 如果位没有设置位使用的颜色数,设置它 if(m_lpBmpInfoHeader->biClrUsed == 0) { m_lpBmpInfoHeader->biClrUsed = GetNumOfColor(); //AfxMessageBox("24位"); //CString strColor; //strColor.Format("m_lpBmpInfoHeader->biClrUsed :%d",m_lpBmpInfoHeader->biClrUsed); //AfxMessageBox(strColor); } // 计算颜色表长度 DWORD dwRgbQuadLength = CalcRgbQuadLength(); //m_lpBmpInfoHeader->biPlanes = 1; //CString strColor; //strColor.Format("m_lpBmpInfoHeader->biCompression :%d", m_lpBmpInfoHeader->biPlanes); //AfxMessageBox(strColor); // 设置位数据指针 //m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength; m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength; //m_lpOldData= m_lpOldDib + ((LPBITMAPINFOHEADER)m_lpOldDib)->biSize + dwRgbQuadLength; // 判断是否有颜色表 if(m_lpRgbQuad == (LPRGBQUAD)m_lpData) { m_lpRgbQuad = NULL; // 将位颜色表指针置空 m_bHasRgbQuad = FALSE; // 无颜色表 //AfxMessageBox("无颜色表"); } else { m_bHasRgbQuad = TRUE; // 有颜色表 MakePalette(); // 根据颜色表生成调色板 //AfxMessageBox("加载生成调色板"); } // 设置位大小(因为很多位文件都不设置此项) m_lpBmpInfoHeader->biSizeImage = GetSize(); // 位有效 m_bValid = TRUE; return TRUE; } else { // 不是位文件 AfxMessageBox("该不是位!"); m_bValid = FALSE; return FALSE; } } //======================================================= // 函数功能: 将位保存到文件 // 输入参数: LPCTSTR lpszPath-位文件保存路径 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= /*BOOL CDib::SaveToFile(LPCTSTR lpszPath) { // 以写模式打开文件 HDC hdc,hdcMem; HBITMAP hBitMap = NULL; CBitmap *pBitMap = NULL; CDC *pMemDC = NULL; BYTE *pBits; hdc = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL); hdcMem = CreateCompatibleDC(hdc); hBitMap = CreateDIBSection(hdcMem,m_lpBmpInfo,DIB_PAL_COLORS,(void **)&pBits,NULL,0); pBitMap = new CBitmap; pBitMap->Attach(hBitMap); pMemDC = new CDC; pMemDC->Attach(hdcMem); pMemDC->SelectObject(pBitMap); pMemDC->SetBkMode(TRANSPARENT); //pMemDC->SetBkMode(OPAQUE); //添加自绘形 m_myview->DrawLine(pMemDC); CFile dibFile; if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive)) { return FALSE; } // 记录位文件名 strcpy(m_fileName, lpszPath); // 将文件头结构写进文件 dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER)); // 将文件信息头结构写进文件 dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER)); // 计算颜色表长度 DWORD dwRgbQuadlength = CalcRgbQuadLength(); // 如果有颜色表的话,将颜色表写进文件 if(dwRgbQuadlength != 0) { dibFile.Write(m_lpRgbQuad, dwRgbQuadlength); } // 将位数据写进文件 DWORD dwDataSize = GetLineByte() * GetHeight(); dibFile.Write(m_lpData, dwDataSize); // 关闭文件 dibFile.Close(); return TRUE; } */ //======================================================= // 函数功能: 获取位文件名 // 输入参数: 无 // 返回值: LPCTSTR-位文件名 //======================================================= LPCTSTR CDib::GetFileName() { return m_fileName; } //======================================================= // 函数功能: 获取位宽度 // 输入参数: 无 // 返回值: LONG-位宽度 //======================================================= LONG CDib::GetWidth() { return m_lpBmpInfoHeader->biWidth; } //======================================================= // 函数功能: 获取位高度 // 输入参数: 无 // 返回值: LONG-位高度 //======================================================= LONG CDib::GetHeight() { return m_lpBmpInfoHeader->biHeight; } //======================================================= // 函数功能: 获取位的宽度和高度 // 输入参数: 无 // 返回值: CSize-位的宽度和高度 //======================================================= CSize CDib::GetDimension() { return CSize(GetWidth(), GetHeight()); } //======================================================= // 函数功能: 获取位大小 // 输入参数: 无 // 返回值: DWORD-位大小 //======================================================= DWORD CDib::GetSize() { if(m_lpBmpInfoHeader->biSizeImage != 0) { return m_lpBmpInfoHeader->biSizeImage; } else { return GetWidth() * GetHeight(); } } //======================================================= // 函数功能: 获取单个像素所占位数 // 输入参数: 无 // 返回值: WORD-单个像素所占位数 //======================================================= WORD CDib::GetBitCount() { return m_lpBmpInfoHeader->biBitCount; } //======================================================= // 函数功能: 获取每行像素所占字节数 // 输入参数: 无 // 返回值: UINT-每行像素所占字节数 //======================================================= UINT CDib::GetLineByte() { return (GetWidth() * GetBitCount() /8 + 3) / 4 * 4; } //======================================================= // 函数功能: 获取位颜色数 // 输入参数: 无 // 返回值: DWORD-位颜色数 //======================================================= DWORD CDib::GetNumOfColor() { UINT dwNumOfColor; if ((m_lpBmpInfoHeader->biClrUsed == 0) && (m_lpBmpInfoHeader->biBitCount < 9)) { switch (m_lpBmpInfoHeader->biBitCount) { case 1: dwNumOfColor = 2; break; case 4: dwNumOfColor = 16; break; case 8: dwNumOfColor = 256; } } else { dwNumOfColor = m_lpBmpInfoHeader->biClrUsed; //CString strColor; //strColor.Format("dwNumOfColor:%d",dwNumOfColor); //AfxMessageBox(strColor); } return dwNumOfColor; } //======================================================= // 函数功能: 计算位颜色表长度 // 输入参数: 无 // 返回值: DWORD-位颜色表长度 //======================================================= DWORD CDib::CalcRgbQuadLength() { DWORD dwNumOfColor = GetNumOfColor(); if(dwNumOfColor > 256) { dwNumOfColor = 0; } CString strColor; strColor.Format("dwNumOfColor:%d",dwNumOfColor); //AfxMessageBox(strColor); return dwNumOfColor * sizeof(RGBQUAD); } //======================================================= // 函数功能: 计算位像素的起始位置 // 输入参数: 无 // 返回值: LPBYTE-位像素的起始位置 //======================================================= LPBYTE CDib::GetBits() { return (m_lpDib+((LPBITMAPINFOHEADER)m_lpDib)->biSize+CalcRgbQuadLength()); } //======================================================= // 函数功能: 获取位颜色表 // 输入参数: 无 // 返回值: LPRGBQUAD-位颜色表指针 //======================================================= LPRGBQUAD CDib::GetRgbQuad() { return m_lpRgbQuad; } //======================================================= // 函数功能: 获取位数据 // 输入参数: 无 // 返回值: LPBYTE-位数据指针 //======================================================= LPBYTE CDib::GetData() { return m_lpData; } //======================================================= // 函数功能: 根据颜色表生成调色板 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::MakePalette() { // 计算颜色表长度 DWORD dwRgbQuadLength = CalcRgbQuadLength(); CString strColor; strColor.Format("dwRgbQuadLength:%d",dwRgbQuadLength); //AfxMessageBox(strColor); // 如果颜色表长度为0,则不生成逻辑调色板 if(dwRgbQuadLength == 0) { return FALSE; } //删除旧的调色板对象 if(m_hPalette != NULL) { DeleteObject(m_hPalette); m_hPalette = NULL; } // 申请缓冲,初始化为0 DWORD dwNumOfColor = GetNumOfColor(); DWORD dwSize = 2 * sizeof(WORD) + dwNumOfColor * sizeof(PALETTEENTRY); LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[dwSize]; memset(lpLogPalette, 0, dwSize); // 生成逻辑调色板 lpLogPalette->palVersion = 0x300; lpLogPalette->palNumEntries = dwNumOfColor; LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad; for(int i = 0; i < dwNumOfColor; i++) { lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed; lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen; lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue; lpLogPalette->palPalEntry[i].peFlags = 0; lpRgbQuad++; } // 创建逻辑调色板 m_hPalette = CreatePalette(lpLogPalette); // 释放缓冲 delete [] lpLogPalette; return TRUE; } //======================================================= // 函数功能: 显示位 // 输入参数: // CDC *pDC-设备环境指针 // CPoint origin-显示矩形域的左上角 // CSize size-显示矩形域的尺寸 // 返回值: // BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size) { // 位无效,无法绘制,返回错误 if(!IsValid()) { return FALSE; } // 旧的调色板句柄 HPALETTE hOldPalette = NULL; // 如果位指针为空,则返回FALSE if(m_lpDib == NULL) { return FALSE; } // 如果位有调色板,则选进设备环境中 if(m_hPalette != NULL) { hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE); } // 设置位伸缩模式 pDC->SetStretchBltMode(COLORONCOLOR); // 将位在pDC所指向的设备上进行显示 StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy, 0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY); // 恢复旧的调色板 if(hOldPalette != NULL) { SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE); } return TRUE; } //======================================================= // 函数功能: 24位彩色位转8位灰度位 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::RgbToGrade() { // 位无效,失败返回 if(!IsValid()) { AfxMessageBox("该位无效!"); return FALSE; } // 是压缩位,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } // 如果不是灰度位,才需要转换 if(!IsGrade()) { // 获取原位信息 LONG lHeight = GetHeight(); LONG lWidth = GetWidth(); UINT uLineByte = GetLineByte(); // 计算灰度位数据所需空间 UINT uGradeBmpLineByte = (lWidth * 8 / 8 + 3) / 4 * 4; DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算灰度位所需空间 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + dwGradeBmpDataSize; // 设置灰度位文件头 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); lpGradeBmpFileHeader->bfType = 0x4d42; lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize; lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; lpGradeBmpFileHeader->bfReserved1 = 0; lpGradeBmpFileHeader->bfReserved2 = 0; // 为灰度位分配空间,并初始化为0 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize]; memset(lpGradeBmp, 0, dwGradeBmpSize); // 设置灰度位信息头 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp); lpGradeBmpInfoHeader->biBitCount = 8; lpGradeBmpInfoHeader->biClrImportant = 0; lpGradeBmpInfoHeader->biClrUsed = 256; lpGradeBmpInfoHeader->biCompression = BI_RGB; lpGradeBmpInfoHeader->biHeight = lHeight; lpGradeBmpInfoHeader->biPlanes = 1; lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER); lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize; lpGradeBmpInfoHeader->biWidth = lWidth; lpGradeBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter; lpGradeBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter; // 设置灰度位颜色表 LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER)); // 初始化8位灰度的调色板信息 LPRGBQUAD lpRgbQuad; for(int k = 0; k < 256; k++) { lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k); lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k; lpRgbQuad->rgbRed = k; lpRgbQuad->rgbReserved = 0; } // 灰度位数据处理 BYTE r, g, b; LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); // 进行颜色转换 for(int i = 0; i < lHeight; i++) { for(int j = 0; j < lWidth; j++) { b = m_lpData[i * uLineByte + 3 * j]; g = m_lpData[i * uLineByte + 3 * j + 1]; r = m_lpData[i * uLineByte + 3 * j + 2]; lpGradeBmpData[i * uGradeBmpLineByte + j] = (BYTE)(0.299 * r + 0.587 * g + 0.114 * b); } } // 释放原有位空间 Empty(FALSE); // 重新设定原位指针指向 m_lpBmpFileHeader = lpGradeBmpFileHeader; m_lpDib = lpGradeBmp; m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp); m_lpBmpInfoHeader = lpGradeBmpInfoHeader; m_lpRgbQuad = lpGradeBmpRgbQuad; m_lpData = lpGradeBmpData; // 设置颜色表标志 m_bHasRgbQuad = TRUE; // 设置位有效标志 m_bValid = TRUE; // 生成调色板 MakePalette(); } AfxMessageBox("转换成功,请保存8位灰度!"); return TRUE; } //======================================================= // 函数功能: 8位彩色位转24位彩色 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::GraphToRgb() { // 位无效,失败返回 if(!IsValid()) { AfxMessageBox("该位无效!"); return FALSE; } // 是压缩位,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } if(GetBitCount()==24) { AfxMessageBox("该位已是24位,不用转换!"); return FALSE; } if(GetBitCount()!=8) { AfxMessageBox("该位不是8位,不能转换,请用画软件将其另存为成24位!"); return FALSE; } // 如果不是24位,才需要转换 // 获取原位信息 LONG lHeight = GetHeight(); LONG lWidth = GetWidth(); UINT uLineByte = GetLineByte(); // 计算24位数据所需空间 //return (GetWidth() * GetBitCount() /8 + 3) / 4 * 4; UINT uGradeBmpLineByte = (lWidth * 24/8 + 3) / 4 * 4; DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算24位所需空间 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 0 + dwGradeBmpDataSize; // 设置24位文件头 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); lpGradeBmpFileHeader->bfType = 0x4d42; lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize; lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); lpGradeBmpFileHeader->bfReserved1 = 0; lpGradeBmpFileHeader->bfReserved2 = 0; // 为24位分配空间,并初始化为0 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize]; memset(lpGradeBmp, 0, dwGradeBmpSize); // 设置24位信息头 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp); lpGradeBmpInfoHeader->biBitCount = 24; lpGradeBmpInfoHeader->biClrImportant = 0; lpGradeBmpInfoHeader->biClrUsed = 0; lpGradeBmpInfoHeader->biCompression = BI_RGB; lpGradeBmpInfoHeader->biHeight = lHeight; lpGradeBmpInfoHeader->biPlanes = 1; lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER); lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize; lpGradeBmpInfoHeader->biWidth = lWidth; lpGradeBmpInfoHeader->biXPelsPerMeter = 0; lpGradeBmpInfoHeader->biYPelsPerMeter = 0; // 设置24位颜色表 //LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER)); // 初始化8位灰度的调色板信息 /*LPRGBQUAD lpRgbQuad; for(int k = 0; k < 256; k++) { lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k); lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k; lpRgbQuad->rgbRed = k; lpRgbQuad->rgbReserved = 0; }*/ // 24位数据处理 //BYTE r, g, b; //LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 0); // 进行颜色转换 LONG lineBytes24=(lWidth * 24 / 8 + 3) / 4 * 4; LONG lineBytes8=(lWidth * 8 / 8 + 3) / 4 * 4; //LONG lineBytes24=(lWidth * 24 + 31) / 32 * 4; //LONG lineBytes8=(lWidth * 8 + 31) / 32 * 4; //CString strColor; //strColor.Format("lineBytes24 :%d,lineBytes8 :%d", lineBytes24,lineBytes8); //AfxMessageBox(strColor); LPBYTE lpGradeBmpData =(LPBYTE) new BYTE[lHeight*lineBytes24]; for(int i = 0; i < lHeight; i++) { for(int j = 0,n=0; j < lineBytes8; j++,n++) { BYTE gray=*(m_lpData+lineBytes8*i+j); *(lpGradeBmpData+lineBytes24*i+n)=gray; n++; *(lpGradeBmpData+lineBytes24*i+n)=gray; n++; *(lpGradeBmpData+lineBytes24*i+n)=gray; /*lpGradeBmpData[lineBytes24*i+j ]= m_lpData[lineBytes8*i+j]; lpGradeBmpData[lineBytes24*i+j+1]= m_lpData[lineBytes8*i+j]; lpGradeBmpData[lineBytes24*i+j+2]= m_lpData[lineBytes8*i+j];*/ } } // 释放原有位空间 //AfxMessageBox("转换成功"); Empty(FALSE); // 重新设定原位指针指向 m_lpBmpFileHeader = lpGradeBmpFileHeader; m_lpDib = lpGradeBmp; m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp); m_lpBmpInfoHeader = lpGradeBmpInfoHeader; //m_lpRgbQuad = lpGradeBmpRgbQuad; m_lpData = lpGradeBmpData; // 设置颜色表标志 //m_bHasRgbQuad = TRUE; // 设置位有效标志 m_bValid = TRUE; // 生成调色板 //MakePalette(); AfxMessageBox("转换成功,请保存24位!"); return TRUE; } //======================================================= // 函数功能: 判断是否含有颜色表 // 输入参数: 无 // 返回值: 判断结果:TRUE-含有颜色表;FALSE-不含颜色表 //======================================================= BOOL CDib::HasRgbQuad() { return m_bHasRgbQuad; } //======================================================= // 函数功能: 判断是否是灰度 // 输入参数: 无 // 返回值: 判断结果:TRUE-是灰度;FALSE-是彩色 //======================================================= BOOL CDib::IsGrade() { return (GetBitCount() < 9 && GetBitCount() > 0); } //======================================================= // 函数功能: 判断位是否有效 // 输入参数: 无 // 返回值: 判断结果:TRUE-位有效;FALSE-位无效 //======================================================= BOOL CDib::IsValid() { return m_bValid; } //======================================================= // 函数功能: 清理空间 // 输入参数: BOOL bFlag-TRUE 全部清空;FALSE 部分清空 // 返回值: 无 //======================================================= void CDib::Empty(BOOL bFlag) { // 文件名清空 if(bFlag) { strcpy(m_fileName, ""); } // 释放位文件头指针空间 if(m_lpBmpFileHeader != NULL) { delete [] m_lpBmpFileHeader; m_lpBmpFileHeader = NULL; } // 释放位指针空间 if(m_lpDib != NULL) { delete [] m_lpDib; m_lpDib = NULL; m_lpBmpInfo = NULL; m_lpBmpInfoHeader = NULL; m_lpRgbQuad = NULL; m_lpData = NULL; } // 释放调色板 if(m_hPalette != NULL) { DeleteObject(m_hPalette); m_hPalette = NULL; } // 设置不含颜色表 m_bHasRgbQuad = FALSE; // 设置位无效 m_bValid = FALSE; } BOOL CDib::CountClr(int r,int g,int b,int fanwei) { m_rgbsum=0; // 位无效,失败返回 if(!IsValid()) { AfxMessageBox("该位无效!"); return FALSE; } if(GetBitCount()!=24) { CString str; str.Format("该位是%d位,无法统计,请用画软件将其另存为成24位!",GetBitCount()); AfxMessageBox(str); return FALSE; } // 是压缩位,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } //LoadFromFile((LPCTSTR)m_fileName); // 获取原位信息 LONG lHeight=GetHeight(); LONG lWidth=GetWidth(); UINT uLineByte=GetLineByte(); // 灰度位数据处理 int R=0, G=0, B=0; //int R1=0, G1=0, B1=0; // 进行颜色转换 int clrfanwei; int clrjizhun=0.299 * r + 0.587 * g + 0.114 * b;//基准灰度 for(int i = 0; i < lHeight; i++) { for(int j = 0; j < lWidth; j++) { //(BYTE)(0.299 * r + 0.587 * g + 0.114 * b); B = *(m_lpData+i * uLineByte + 3 * j); G = *(m_lpData+i * uLineByte + 3 * j + 1); R = *(m_lpData+i * uLineByte + 3 * j + 2); int someonegray=0.299 * R + 0.587 * G + 0.114 * B; if(clrjizhun<128)//标定深色域为缺陷 { clrfanwei=clrjizhun+fanwei; if(clrfanwei>255) clrfanwei=255; if(someonegray<=clrfanwei && someonegray>=clrjizhun) { if(r==255 && g==0 && b==0) { *(m_lpData+i * uLineByte + 3 * j)=255; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=0; } else { *(m_lpData+i * uLineByte + 3 * j)=0; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=255; } m_rgbsum++; } } else//标定浅色域为缺陷 { clrfanwei=clrjizhun-fanwei; if(clrfanwei<0) clrfanwei=0; if(someonegray>=clrfanwei && someonegray<=clrjizhun) { if(r==255 && g==0 && b==0) { *(m_lpData+i * uLineByte + 3 * j)=255; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=0; } else { *(m_lpData+i * uLineByte + 3 * j)=0; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=255; } m_rgbsum++; } } } } return TRUE; } BOOL CDib::TranslationRight(long lXOffset,long lYOffset) { long i; long j; long lWidth,lHeight; lWidth=GetWidth(); lHeight=GetHeight(); //LPBYTE lpSrcDIBBits; long lLineBytes; lLineBytes=GetLineByte(); if (lXOffset<=0 || lYOffset<=0) { return FALSE; } for(i=0;i=0) { *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j))=*(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j-lXOffset)); *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j) + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j-lXOffset) + 1); *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j) + 2)=*(m_lpData+(i+index)* lLineBytes + 3 * (lWidth-j-lXOffset) + 2); } else { break; } } else { if((i+index)
转载同事的测试例子,也许大家可以看看 // MyFade.cpp : implementation file // #include "stdafx.h" #include "MyFade.h" #pragma warning(disable: 4201) #include #pragma comment(lib,"winmm.lib") #pragma warning(default: 4201) #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define WC_FADEWND _T("FadeWnd") ///////////////////////////////////////////////////////////////////////////// // CMyFade CMyFade::CMyFade(CWnd* pParent) { // register the window WNDCLASS wndcls; HINSTANCE hInst = AfxGetInstanceHandle(); if (!(::GetClassInfo(hInst, WC_FADEWND, &wndcls))) { // otherwise we need to register a new class wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wndcls.lpfnWndProc = ::DefWindowProc; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hInstance = hInst; wndcls.hIcon = NULL; // no application icon wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW); wndcls.hbrBackground = NULL; // no background wndcls.lpszMenuName = NULL; // no manu application wndcls.lpszClassName = WC_FADEWND; if (!AfxRegisterClass(&wndcls)) AfxThrowResourceException(); } m_hBitmap = NULL; m_hNewBitmap = NULL; m_pWndLock = NULL; } CMyFade::~CMyFade() { if (m_hBitmap) { DeleteObject(m_hBitmap); m_hBitmap = NULL; } if (m_hNewBitmap) { DeleteObject(m_hNewBitmap); m_hNewBitmap = NULL; } if (m_pWndLock) { m_pWndLock->SetFocus(); } } BEGIN_MESSAGE_MAP(CMyFade, CWnd) //{{AFX_MSG_MAP(CMyFade) ON_WM_PAINT() ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMyFade message handlers void CMyFade::FadeScreen(CWnd *pParent) { if(pParent) { CMyFade *pFade=new CMyFade(pParent); if(pFade) { pFade->Create(pParent, CRect(0, 0, 0, 0)); } } } void CMyFade::OnDraw(CDC* pDC) { CRect rc; GetWindowRect(rc); HDC hbmDC=CreateCompatibleDC(pDC->GetSafeHdc()); HBITMAP hOldbmp=(HBITMAP)::SelectObject(hbmDC, m_hNewBitmap); // 将屏幕位再输入到屏幕上去 BitBlt(pDC->GetSafeHdc(), 0, 0, rc.Width(), rc.Height(), hbmDC, 0, 0, SRCCOPY); SelectObject(hbmDC, hOldbmp); DeleteObject(hbmDC); } void CMyFade::OnPaint() { CPaintDC dc(this); OnDraw(&dc); } HBITMAP CMyFade::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 height int xScrn, yScrn; // screen resolution HGDIOBJ hOldBitmap, hBitmap; if (IsRectEmpty(lpRect)) return NULL; hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); hMemDC = CreateCompatibleDC(hScrDC); xScrn = GetDeviceCaps(hScrDC, HORZRES); yScrn = GetDeviceCaps(hScrDC, VERTRES); nX = lpRect->left; nY = lpRect->top; nX2 = lpRect->right; nY2 = lpRect->bottom; if (nX < 0) nX = 0; if (nY < 0) nY = 0; if (nX2 > xScrn) nX2 = xScrn; if (nY2 > yScrn) nY2 = yScrn; nWidth = nX2 - nX; nHeight = nY2 - nY; hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); hOldBitmap = SelectObject(hMemDC, hBitmap); // 将屏幕输入到内存DC里面去,再通过SelectObject到位句柄里面 BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); // 将刚刚得到到的屏幕位置换出句柄 hBitmap=SelectObject(hMemDC, hOldBitmap); DeleteDC(hScrDC); DeleteDC(hMemDC); return (HBITMAP)hBitmap; } BOOL CMyFade::Create(CWnd *pParent, CRect rc) { if (!pParent || !IsWindow(pParent->GetSafeHwnd())) { MessageBox("error1"); return false; } CClientDC dcParent(pParent); if (dcParent.GetDeviceCaps(RASTERCAPS) & RC_PALETTE) { MessageBox("error2"); return FALSE; } GetDesktopWindow()->GetWindowRect(rc); CString szText; GetDesktopWindow()->GetWindowText(szText); if (!CWnd::CreateEx( 0, WC_FADEWND, szText, WS_POPUP | WS_CHILD | WS_VISIBLE, rc, pParent, NULL, NULL)) { MessageBox("error3"); return FALSE; } /* if(pParent!=GetDesktopWindow()) { m_pWndLock=pParent; m_pWndLock->EnableWindow(false); HRGN hRgn=CreateRectRgn(0, 0, 0, 0); int regiontype=m_pWndLock->GetWindowRgn(hRgn); if(regiontype!=ERROR) { MessageBox("error4"); SetWindowRgn(hRgn, false); } DeleteObject(hRgn); } */ m_hBitmap = CopyScreenToBitmap(rc); SetTimer(1, 2000, NULL); } ////////////////////////////////////////////////////////////////////////// // 核心函数,将屏幕变暗 HBITMAP CMyFade::FadeBitmap(HBITMAP hBmp, double dfTrans) { HBITMAP hRetBmp = NULL; if (hBmp) { HDC hBufferDC = CreateCompatibleDC(NULL); HGDIOBJ hPrevBufObject = SelectObject(hBufferDC, hBmp); HDC hDirectDC = CreateCompatibleDC(NULL); // DC for working if (hDirectDC) { BITMAP bm; GetObject(hBmp, sizeof(bm), &bm); BITMAPINFO bmInfo; ZeroMemory(&bmInfo,sizeof(bmInfo)); bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biWidth = bm.bmWidth; bmInfo.bmiHeader.biHeight = bm.bmHeight; bmInfo.bmiHeader.biPlanes = 1; bmInfo.bmiHeader.biBitCount = 32; UINT* ptPixels; HBITMAP hDirectBitmap = CreateDIBSection(hDirectDC, (BITMAPINFO*)&bmInfo, DIB_RGB_COLORS,(void**)&ptPixels, NULL, 0); if (hDirectBitmap) { // 将hDirectBitmap放入hDirectDC中处理 HGDIOBJ hPrevBufDirObject = SelectObject(hDirectDC, hDirectBitmap); // 当前将原hBmp即屏幕的所有像素写入到hDirectDC // 即需要对像素灰度处理的DC中 BitBlt(hDirectDC,0,0,bm.bmWidth,bm.bmHeight,hBufferDC,0,0,SRCCOPY); int iAlpha = (int)(255.0 * dfTrans / 100.0); int nSize = bm.bmWidth * bm.bmHeight; for (int i=0; i> 16; int iSrcG = ptPixels[i] & 0x0000ff00 >> 8; int iSrcB = ptPixels[i] & 0x000000ff; int iGrey = (iSrcR * 54 + iSrcG * 182 + iSrcB * 19) >> 8; COLORREF Col =iGrey ; //RGB(iGrey, iGrey, iGrey) ; ptPixels[i] = RGB( (GetBValue( Col ) * iAlpha + iSrcB * (255 - iAlpha)) >> 8, (GetGValue( Col ) * iAlpha + iSrcG * (255 - iAlpha)) >> 8, (GetRValue( Col ) * iAlpha + iSrcR * (255 - iAlpha)) >> 8 ); } SelectObject(hDirectDC,hPrevBufDirObject); hRetBmp = hDirectBitmap; } DeleteDC(hDirectDC); } SelectObject(hBufferDC, hPrevBufObject); DeleteDC(hBufferDC); } return hRetBmp; } static i=0; void CMyFade::OnTimer(UINT nIDEvent) { CWnd::OnTimer(nIDEvent); CClientDC dc(this); i+=2; if(i>100) { KillTimer(1); return; } DWORD dwStartCount = timeGetTime(); if(m_hNewBitmap) { DeleteObject(m_hNewBitmap); m_hNewBitmap = NULL; } m_hNewBitmap = FadeBitmap(m_hBitmap,(double)i); OnDraw(&dc); DWORD dwEndCount = timeGetTime(); // tick counter in milliseconds }

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

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

试试用AI创作助手写篇文章吧