📄 gdi.c
字号:
if( rcSrc.top < blt.lprcDest->top )
blt.yPositive = 0; //从右到左
if( rcSrc.left < blt.lprcDest->left )
blt.xPositive = 0; //从下到上
}
lpDispDrv->lpBlkBitBlt( &blt ); //绘制到显示面
}
lprnNode = lprnNode->lpNext;//下一个裁剪区
}
}
else
{ //非同一个显示面
if( ( blt.lpDestImage->bmBitsPixel == blt.lpSrcImage->bmBitsPixel ||
blt.lpSrcImage->bmBitsPixel == 1 ) )
{ //数据格式相同或者源格式是黑白位图格式
//设置绘制方向为从左到右,从上到下
blt.yPositive = 1;
blt.xPositive = 1;
//遍历每一个裁剪域,如果可显示则绘制
while( lprnNode )
{ //得到内交区域
if( IntersectRect( &rcDest, &rcClip, &lprnNode->rect ) )
{
rcSrc = rcDest;
OffsetRect( &rcSrc, xoff, yoff );
lpDispDrv->lpBlkBitBlt( &blt ); //绘制到显示面
}
lprnNode = lprnNode->lpNext; //下一个裁剪区
}
}
else if( lpdcSrc->lpDispDrv )
{ // 不同的位图格式, 需要对每一个点进行处理 ,点对点拷贝 pixel -> pixel
// 这个将会大量的处理时间!
_LPCDISPLAYDRV lpSrcDispDrv = lpdcSrc->lpDispDrv;
_PIXELDATA pxSrc, pxDest;
pxSrc.lpDestImage = blt.lpSrcImage;
pxSrc.pattern = 0xff;
pxSrc.rop = R2_NOP;// read only
pxDest.lpDestImage = blt.lpDestImage;
pxDest.pattern = 0xff;
switch( dwRop )
{
case SRCCOPY: // dest = src
pxDest.rop = R2_COPYPEN;
break;
case SRCAND: // dest = src & dst
pxDest.rop = R2_MASKPEN;
break;
case SRCINVERT: // dest = src ^ dst
pxDest.rop = R2_MASKPEN;
break;
case SRCPAINT: // dest = src | dst
pxDest.rop = R2_MERGEPEN;
break;
case NOTSRCCOPY: // dest = ~src
pxDest.rop = R2_NOTCOPYPEN;
break;
case MERGEPAINT: // dest = (~src) | dest
pxDest.rop = R2_MERGENOTPEN;
break;
default:
SetLastError( ERROR_INVALID_PARAMETER );
goto _ERROR;
}
//遍历每一个裁剪域,如果可显示则绘制
while( lprnNode )
{ //得到内交区域
if( IntersectRect( &rcDest, &rcClip, &lprnNode->rect ) )
{
rcSrc = rcDest;
OffsetRect( &rcSrc, xoff, yoff );
//对每个点进行转换
//PixelTransfer( lpDispDrv, &pxDest, &rcDest, lpSrcDispDrv, &pxSrc, &rcSrc, NULL, 0, 0, -1 );
PixelTransfer( lpdcDest, &pxDest, &rcDest, lpdcSrc, &pxSrc, &rcSrc, NULL, 0, 0, -1 );
}
lprnNode = lprnNode->lpNext;//下一个裁剪区
}
}
}
return TRUE;
}
_ERROR:
return FALSE;
}
// **************************************************
// 声明:BOOL WINAPI WinGdi_TransparentBlt(
// HDC hdcDest - 目标DC
// int xDest - 目标x坐标
// int yDest - 目标x坐标
// int width,
// int height,
// HDC hdcSrc,
// int xSrc,
// int ySrc,
// int widthSrc,
// int heightSrc,
// DWORD clTransparent )
// 参数:
// IN hdcDest - 目标DC
// IN xDest - 目标矩形左上角X坐标
// IN yDest - 目标矩形左上角Y坐标
// IN width - 目标矩形宽度
// IN height - 目标矩形高度
// IN hdcSrc - 源DC
// IN xSrc - 源矩形左上角X坐标
// IN ySrc - 源矩形左上角Y坐标
// IN width - 源矩形宽度
// IN height - 源矩形高度
// IN clTransparent - 透明色,假如 (clTransparent & 0x80000000) != 0,
// 则说明 clTransparent 是表示一个在源位图的设备相关的颜色值,否则,是一个RGB值
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 从源DC向目标DC进行透明位图传送
// 引用:
// 系统API
// ************************************************
BOOL WINAPI WinGdi_TransparentBlt(HDC hdcDest,
int xDest,
int yDest,
int width,
int height,
HDC hdcSrc,
int xSrc,
int ySrc,
int widthSrc,
int heightSrc,
DWORD clTransparent )
{
_LPGDCDATA lpdcDest = _GetSafeDrawPtr( hdcDest );//得到目标DC对象指针
_LPGDCDATA lpdcSrc = _GetSafeDrawPtr( hdcSrc );//得到源DC对象指针
_LPRGNDATA lprgn;
_LPRECTNODE lprnNode;
_BLKBITBLT blt;
RECT rcSrc, rcTemp, rcClip, rcDest;
int xoff, yoff, xSrcOff, ySrcOff;
if( lpdcDest && lpdcSrc && lpdcDest->lpDispDrv )
{
_LPCDISPLAYDRV lpDispDrv = lpdcDest->lpDispDrv; //目标DC驱动程序
lprgn = _GetHRGNPtr( lpdcDest->hrgn );
//源/目标位图数据结构
blt.lpDestImage = _GetHBITMAPPtr( lpdcDest->hBitmap );
blt.lpSrcImage = _GetHBITMAPPtr( lpdcSrc->hBitmap );
//当前刷子
blt.lpBrush = NULL;//&lpdcSrc->brushAttrib;
if( !(lprgn && blt.lpDestImage && blt.lpSrcImage) )
goto _ERROR;
blt.lprcSrc = &rcSrc;
blt.lprcDest = &rcDest;
blt.dwRop = SRCCOPY;
// in bitblt, mono bitmap , 1 mean backcolor, 0 mean textcolor
blt.solidColor = lpdcSrc->lpDispDrv->lpRealizeColor( clTransparent, lpdcSrc->lpdwPal, lpdcSrc->wPalNumber, lpdcSrc->wPalFormat );//lpdcDest->backColor;
blt.solidBkColor = lpdcDest->textColor;
blt.backMode = TRANSPARENT;//lpdcDest->backMode;
//当前源DC在显示设备上的偏移
xSrcOff = XOFFSET( lpdcSrc );
ySrcOff = YOFFSET( lpdcSrc );
//转换源坐标到设备坐标
rcTemp.left = xSrc;
rcTemp.top = ySrc;
rcTemp.right = rcTemp.left + width;
rcTemp.bottom = rcTemp.top + height;
OffsetRect( &rcTemp, xSrcOff, ySrcOff );
//当前目标DC在显示设备上的偏移
xoff = XOFFSET( lpdcDest );
yoff = YOFFSET( lpdcDest );
//转换目标坐标到设备坐标
rcClip.left = xDest;
rcClip.top = yDest;
rcClip.right = rcClip.left + width;
rcClip.bottom = rcClip.top + height;
OffsetRect( &rcClip, xoff, yoff );
//得到源和目标的共同区域
if( rcTemp.left < 0 )
{
rcClip.left -= rcTemp.left;
}
if( rcTemp.top < 0 )
{
rcClip.top -= rcTemp.top;
}
if( rcTemp.right > blt.lpSrcImage->bmWidth )
{
rcClip.right -= rcTemp.right - blt.lpSrcImage->bmWidth;
}
if( rcTemp.bottom > blt.lpSrcImage->bmHeight )
{
rcClip.bottom -= rcTemp.bottom - blt.lpSrcImage->bmHeight;
}
//源坐标在目标上的投射点相对偏移
xoff = xSrc + XOFFSET( lpdcSrc ) - xDest - xoff;
yoff = ySrc + YOFFSET( lpdcSrc ) - yDest - yoff;
//目标裁剪域
lprnNode = lprgn->lpNodeFirst;
/* supprt later
if( blt.lpDestImage->bmBits == blt.lpSrcImage->bmBits )
{ //相同的显示面
//遍历每一个裁剪域,如果可显示则绘制
while( lprnNode )
{ //得到内交区域
if( IntersectRect( &rcDest, &rcClip, &lprnNode->rect ) )
{
rcSrc = rcDest;
OffsetRect( &rcSrc, xoff, yoff );
//设置绘制方向为从左到右,从上到下
blt.yPositive = 1;
blt.xPositive = 1;
//
if( IntersectRect( &rcTemp, &rcSrc, &rcDest ) )
{ //因为是相同的显示面,所以必须确定正确的拷贝顺序
//这里表示目标矩形与源矩形有重叠并且必须反向拷贝
if( rcSrc.top < blt.lprcDest->top )
blt.yPositive = 0; //从右到左
if( rcSrc.left < blt.lprcDest->left )
blt.xPositive = 0; //从下到上
}
lpDispDrv->lpBlkBitTransparentBlt( &blt ); //绘制到显示面
}
lprnNode = lprnNode->lpNext;//下一个裁剪区
}
}
else
*/
{ //非同一个显示面
/* //support later
if( ( blt.lpDestImage->bmBitsPixel == blt.lpSrcImage->bmBitsPixel ||
blt.lpSrcImage->bmBitsPixel == 1 ) )
{ //数据格式相同或者源格式是黑白位图格式
//设置绘制方向为从左到右,从上到下
blt.yPositive = 1;
blt.xPositive = 1;
//遍历每一个裁剪域,如果可显示则绘制
while( lprnNode )
{ //得到内交区域
if( IntersectRect( &rcDest, &rcClip, &lprnNode->rect ) )
{
rcSrc = rcDest;
OffsetRect( &rcSrc, xoff, yoff );
lpDispDrv->lpBlkBitTransparentBlt( &blt ); //绘制到显示面
}
lprnNode = lprnNode->lpNext; //下一个裁剪区
}
}
else if( lpdcSrc->lpDispDrv )
*/
{ // 不同的位图格式, 需要对每一个点进行处理 ,点对点拷贝 pixel -> pixel
// 这个将会大量的处理时间!
_LPCDISPLAYDRV lpSrcDispDrv = lpdcSrc->lpDispDrv;
_PIXELDATA pxSrc, pxDest;
pxSrc.lpDestImage = blt.lpSrcImage;
pxSrc.pattern = 0xff;
pxSrc.rop = R2_NOP;// read only
pxDest.lpDestImage = blt.lpDestImage;
pxDest.pattern = 0xff;
pxDest.rop = R2_COPYPEN;
//遍历每一个裁剪域,如果可显示则绘制
while( lprnNode )
{ //得到内交区域
if( IntersectRect( &rcDest, &rcClip, &lprnNode->rect ) )
{
rcSrc = rcDest;
OffsetRect( &rcSrc, xoff, yoff );
//对每个点进行转换
PixelTransfer( lpdcDest, &pxDest, &rcDest, lpdcSrc, &pxSrc, &rcSrc, NULL, 0, 0, clTransparent );
}
lprnNode = lprnNode->lpNext;//下一个裁剪区
}
}
}
return TRUE;
}
_ERROR:
return FALSE;
}
// **************************************************
// 声明:
// 参数:
// IN
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
//
// 引用:
//
// ************************************************
extern int _WinGdi_ConvertImageColorValue(
_LPCDISPLAYDRV lpDrv,
_LPBITMAP_DIB lpDestImage, // dest image data
LPCRECT lprcDestClip,
CONST BITMAPINFO * lpbi,// src image info
LPCRECT lprcSrcClip,
DWORD dwStartScanLine, // src start scan line
DWORD dwScanLineNum,
DWORD dwScanLineWidth,
LPCBYTE lpbData,// src bitmap bits data
int fuColorUse // use src's RGB or PAL
);
// **************************************************
// 声明:int WINAPI WinGdi_SetDIBitsToDevice(
// HDC hdc, // handle to DC
// int xDest, // x-coord of destination upper-left corner
// int yDest, // y-coord of destination upper-left corner
// DWORD dwWidth, // source rectangle width
// DWORD dwHeight, // source rectangle height
// int xSrc, // x-coord of source lower-left corner
// int ySrc, // y-coord of source lower-left corner
// UINT uStartScan, // first scan line in array
// UINT cScanLines, // number of scan lines
// CONST VOID *lpvBits, // array of DIB bits
// CONST BITMAPINFO *lpbmi, // bitmap information
// UINT fuColorUse // RGB or palette indexes
// )
// 参数:
// IN hdc – 目标DC
// IN xDest – 输出到目标矩形的x坐标
// IN yDest – 输出到目标矩形的y坐标
// IN dwWidth – 输出到目标矩形的宽度
// IN dwHeight – 输出到目标矩形的高度
// IN xSrc – 源DIB点数据的开始x位置
// IN ySrc – 源DIB点数据的开始y位置
// IN uStartScan – DIB数据的开始扫描行
// IN cScanLines – DIB数据的扫描行行数
// IN lpvBits – 包含DIB数据的指针
// IN lpbmi - BITMAPINFO结构指针,用于描述lpvBits的数据信息
// IN fuColorUse - 说明BITMAPINFO结构成员bmiColors的类型:
// DIB_PAL_COLORS – bmiColors为16索引数组,每一个索引值指向当前hdc的调色板的对应项
// DIB_RGB_COLORS – bmiColors为红、绿、蓝颜色数组
// 返回值:
// 假如成功,返回实际拷贝的扫描行数;否则,返回0
// 功能描述:
// 设置DIB数据到目标设备对应的矩形里
// 引用:
// 系统API
// ************************************************
int WINAPI WinGdi_SetDIBitsToDevice(
HDC hdc, // handle to DC
int xDest, // x-coord of destination upper-left corner
int yDest, // y-coord of destination upper-left corner
DWORD dwWidth, // source rectangle width
DWORD dwHeight, // source rectangle height
int xSrc, // x-coord of source lower-left corner
int ySrc, // y-coord of source lower-left corner
UINT uStartScan, // first scan line in array
UINT cScanLines, // number of scan lines
CONST VOID *lpvBits, // array of DIB bits
CONST BITMAPINFO *lpbmi, // bitmap information
UINT fuColorUse // RGB or palette indexes
)
{ // 得到DC对象指针
_LPGDCDATA lpdc = _GetSafeDrawPtr( hdc );
if( lpdc && lpbmi )
{
_LPBITMAPDATA lpImage = NULL;//
_LPCDISPLAYDRV lpDrv;
UINT uiHeight = ABS(lpbmi->bmiHeader.biHeight);
//得到DC显示面
lpImage = _GetHBITMAPPtr( lpdc->hBitmap );
lpDrv = lpdc->lpDispDrv;
if( lpDrv == NULL )
return 0; //非法
if( lpImage )
{
int iDir;
// 源扫描行字节数
int iScanLineBytes = (lpbmi->bmiHeader.biBitCount * lpbmi->bmiHeader.biWidth + 31) / 32 * 4; // align to dword
int iMinWidth, iMinHeight;
RECT rcSrc, rcDst, rcTemp;
int xoff = XOFFSET( lpdc );
int yoff = YOFFSET( lpdc );
_LPRGNDATA lprgn;
_LPRECTNODE lprnNode;
//颜色数据是从底到顶排列的吗 ?
if( lpbmi->bmiHeader.biHeight > 0 )
iDir = -1; //是从底到顶排列的
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -