📄 gdi.c
字号:
// 释放一个基于窗口的DC
// 引用:
//
// ************************************************
// the option export for win.c
BOOL ReleasePaintDC( HWND hWnd, HDC hdc )
{
_LPGDCDATA lpdc = _GetHDCPtr( hdc );
if( lpdc && lpdc->obj.objType == OBJ_DC )
{ // 测试该DC是否与该窗口相关
if( (LONG)hWnd == Interlock_TestExchange( (LONG*)&lpdc->hwnd, (LONG)hWnd, NULL ) )
{ //是,释放它
return DelSysDC( lpdc );
}
else
{
WARNMSG( 1, ( "error at ReleasePaintDC: the hdc(0x%x) did'nt alloc by the hWnd(0x%x).\r\n", hdc, hWnd ) );
}
}
return FALSE;
}
// **************************************************
// 声明:HDC GetPaintDC( HWND hwnd, LPCRECT lprect, HRGN hrgnClip, UINT uiFlags )
// 参数:
// IN hwnd - 窗口句柄
// IN lprect - 窗口矩形(设备坐标)
// IN hrgnClip - 裁剪区域
// IN uiFlags - 标志
// 返回值:
// 假入成功,返回分配的DC句柄;否则,返回NULL
// 功能描述:
// 从系统分配一个DC用于绘图
// 引用:
//
// ************************************************
HDC GetPaintDC( HWND hwnd, LPCRECT lprect, HRGN hrgnClip, UINT uiFlags )
{
_LPGDCDATA lpdc = _AllocGDCData();// 得到一个DC结构
if( lpdc )
{
lpdc->hrgn = hrgnClip;
lpdc->hPen = OEM_GetStockObject(BLACK_PEN);//系统默认的PEN
lpdc->penAttrib = _GetHPENPtr( lpdc->hPen )->penAttrib;
lpdc->hBrush = OEM_GetStockObject(WHITE_BRUSH);//系统默认刷子
lpdc->brushAttrib = _GetHBRUSHPtr( lpdc->hBrush )->brushAttrib;
lpdc->hFont = OEM_GetStockObject(SYSTEM_FONT);//系统默认的字体
// 2004-02-16
lpdc->hBitmap = (HBITMAP)hbmpDisplayBitmap;//lpDisplayBitmap;//系统默认位图
//
lpdc->lpDispDrv = lpDrvDisplayDefault;//系统默认图形驱动程序
lpdc->deviceOrg.x = lprect->left;//窗口在设备的左上角x坐标
lpdc->deviceOrg.y = lprect->top;//窗口在设备的左上角y坐标
lpdc->deviceExt.cx = lprect->right - lprect->left;//窗口宽度
lpdc->deviceExt.cy = lprect->bottom - lprect->top;//窗口高度
lpdc->stretchMode = 0;//伸缩模式
lpdc->mapMode = MM_TEXT;//映射模式MM_TEXT
lpdc->rop = R2_COPYPEN;//笔操作模式
lpdc->arcMode = AD_CLOCKWISE;//顺时针画弧, AD_COUNTERCLOCKWISE;
lpdc->backMode = OPAQUE;//不透明背景
lpdc->backColor = (DWORD)OEM_GetStockObject( SYS_STOCK_WHITE );//默认的背景色
lpdc->textColor = (DWORD)OEM_GetStockObject( SYS_STOCK_BLACK );//默认的文本色
lpdc->textAlign = TA_TOP | TA_LEFT;//文本对齐模式
lpdc->position.x = lpdc->position.y = 0;//当前的默认绘图起点
lpdc->windowOrg = lpdc->viewportOrg = lpdc->position;//窗口原点,视区原点
lpdc->uiState = 0; // 状态
lpdc->uiFlags = uiFlags;//标志
lpdc->hwnd = hwnd;//关联窗口
lpdc->lpdwPal = 0; //默认的调色板
lpdc->wPalNumber = 0; //默认的调色板
lpdc->wPalFormat = 0; //默认的调色板
return (HDC)PTR_TO_HANDLE( lpdc ); // 将DC指针转化为句柄
}
return NULL;
}
// **************************************************
// 声明:BOOL DeleteDCObject( HANDLE hOwner )
// 参数:
// IN hOwner - 拥有者句柄
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 清除拥有者的所有之前分配而没有释放的DC。通常当一个进程退出时,调用该功能去清除
// 进程没有释放的DC
// 引用:
//
// ************************************************
BOOL DeleteDCObject( HANDLE hOwner )
{
int i;
_LPGDCDATA lpdc;
EnterCriticalSection( &csDCList );//进入互斥段
//清除所有的属于拥有者对象
ObjList_Delete( &lpDCObjList, (ULONG)hOwner, DelMemDCObj, 0 );
LeaveCriticalSection( &csDCList );//离开互斥段
// release sysdc
lpdc = lpSysDC;
for( i = 0; i < _MAX_GDIOBJECT_NUM; i++, lpdc++ )
{
if( lpdc->obj.objType != OBJ_NULL &&
lpdc->obj.ulOwner == (ULONG)hOwner ) //属于拥有者 ?
{ //是
InterlockedExchange( (LONG*)&lpdc->hwnd, NULL );
DelSysDC( lpdc );
}
}
return 1;
}
// **************************************************
// 声明:HDC WINAPI WinGdi_CreateCompatibleDC(HDC hdc)
// 参数:
// IN hdc - DC句柄
// 返回值:
// 假入成功,返回DC句柄;否则,返回NULL
// 功能描述:
// 创建兼容于hdc的内存DC
// 引用:
// 系统API
// ************************************************
HDC WINAPI WinGdi_CreateCompatibleDC(HDC hdc)
{
_LPGDCDATA lpSrcDC = NULL;
_LPGDCDATA lpdc;
if( hdc )
{
lpSrcDC = _GetHDCPtr( hdc );
if( lpSrcDC == NULL )
return NULL;
}
lpdc = (_LPGDCDATA)BlockHeap_Alloc( hgwmeBlockHeap, BLOCKHEAP_ZERO_MEMORY, sizeof(_GDCDATA) ); // 分配DC结构
// lpdc = (_LPGDCDATA)BLK_Alloc( 0, sizeof(_GDCDATA) ); // 分配DC结构
if( lpdc ) // 分配成功?
{ //是,初始化DC为1x1的黑白位图格式
// hrgn 不能用 OEM_GetStockObject, 因为当选进bitmap后,需要改变其裁剪矩形的大小
lpdc->lpDispDrv = &_drvDisplay1BPP;
lpdc->lpdwPal = 0; //默认的调色板
lpdc->wPalNumber = 0; //默认的调色板
lpdc->wPalFormat = 0; //默认的调色板
lpdc->hrgn = WinRgn_CreateRect( 0, 0, 1, 1 );//OEM_GetStockObject(SYS_STOCK_RGN);
//初始化为黑笔
lpdc->hPen = OEM_GetStockObject(BLACK_PEN);
//设置设备依赖笔数据结构
lpdc->penAttrib = _GetHPENPtr( lpdc->hPen )->penAttrib;
//设置设备依赖颜色
lpdc->penAttrib.color = lpdc->lpDispDrv->lpRealizeColor(lpdc->penAttrib.clrRef, lpdc->lpdwPal, lpdc->wPalNumber, lpdc->wPalFormat );
//设置设备依赖刷子数据结构
lpdc->hBrush = OEM_GetStockObject(WHITE_BRUSH);
lpdc->brushAttrib = _GetHBRUSHPtr( lpdc->hBrush )->brushAttrib;
//设置设备依赖颜色
lpdc->brushAttrib.color = lpdc->lpDispDrv->lpRealizeColor(lpdc->brushAttrib.clrRef, lpdc->lpdwPal, lpdc->wPalNumber, lpdc->wPalFormat);
//默认字体
lpdc->hFont = OEM_GetStockObject(SYSTEM_FONT);
//默认显示面
lpdc->hBitmap = OEM_GetStockObject(SYS_STOCK_BITMAP1x1);
ASSERT( lpdc->hBitmap );
//设备原点
lpdc->deviceOrg.x = 0;
lpdc->deviceOrg.y = 0;
lpdc->deviceExt.cx = 0;
lpdc->deviceExt.cy = 0;
lpdc->stretchMode = 0;
lpdc->mapMode = MM_TEXT;
lpdc->rop = R2_COPYPEN;
lpdc->backMode = OPAQUE;
lpdc->backColor = 0xffffffffl;
lpdc->textColor = 0;
lpdc->textAlign = TA_TOP | TA_LEFT;
lpdc->position.x = lpdc->position.y = 0;
lpdc->windowOrg = lpdc->viewportOrg = lpdc->position;
lpdc->hwnd = NULL;
}
if( lpdc )
{ //插入DC对象链表
EnterCriticalSection( &csDCList );
ObjList_Init( &lpDCObjList, &lpdc->obj, OBJ_MEMDC, (ULONG)GetCallerProcess() );
LeaveCriticalSection( &csDCList );
return (HDC)PTR_TO_HANDLE( lpdc ); // 转化为句柄
}
return NULL;
}
// **************************************************
// 声明:HBITMAP WINAPI WinGdi_CreateCompatibleBitmap(HDC hdc, int iWidth, int iHeight)
// 参数:
// IN hdc - 设备DC
// IN iWidth - 位图宽度
// IN iHeight - 位图高度
// 返回值:
// 假入成功,返回非NULL位图句柄;否则,返回NULL
// 功能描述:
// 创建兼容DC的位图
// 引用:
// 系统API
// ************************************************
HBITMAP WINAPI WinGdi_CreateCompatibleBitmap(HDC hdc, int iWidth, int iHeight)
{
if( hdc )
{
_LPGDCDATA lpdc = _GetHDCPtr( hdc );
if( lpdc )
{ //有效
_LPBITMAPDATA lpImage = _GetHBITMAPPtr( lpdc->hBitmap );
return lpImage ? WinGdi_CreateBitmap( iWidth, iHeight, lpImage->bmPlanes, lpImage->bmBitsPixel, 0 ) : NULL;
}
}
else
{ // 用屏幕DC, use screen dc
return WinGdi_CreateBitmap( iWidth, iHeight, lpDisplayBitmap->bmPlanes, lpDisplayBitmap->bmBitsPixel, 0 );
}
return NULL;
}
// **************************************************
// 声明:_LPGDCDATA _GetSafeDrawPtr( HDC hdc )
// 参数:
// IN hdc - DC句柄
// 返回值:
// 假如成功,返回_LPGDCDATA指针;否则,返回NULL
// 功能描述:
// 得到安全的DC.
// 1.检查DC是否合法; 2.检查DC的状态是否改变,如果是,更新它
// 引用:
//
// ************************************************
extern int _GetRgnInfo(HRGN hrgn);
#define DEBUG_GETSAFEDRAWPTR 0
_LPGDCDATA _GetSafeDrawPtr( HDC hdc )
{ // 由句柄得到其对象指针
_LPGDCDATA lpdc = (_LPGDCDATA)HANDLE_TO_PTR( hdc );
if( lpdc )
{
if( ( (WORD)GET_OBJ_TYPE( lpdc) == OBJ_MEMDC ||
(WORD)GET_OBJ_TYPE( lpdc ) == OBJ_DC ) )
{ // 类型有效
if( lpdc->hwnd )
{ // 该DC 与窗口关联,如果这时窗口坐标改变,需要同时更新DC
int iUpdate = 0;
int iRgn;
while( lpdc->uiState &&
Interlock_TestExchange( (LPLONG)&lpdc->uiState, 1, 0 ) )
{ //改变
_LPWINDATA lpws;
RECT rect;
HRGN hRgn;
UINT uiFlags = lpdc->uiFlags;
iUpdate++; // use to test
iRgn = SIMPLEREGION;
//由窗口句柄得到其指针对象
lpws = _GetHWNDPtr( lpdc->hwnd );
//得到DC的显示屏幕矩形
if( uiFlags & DCX_WINDOW )
{ //窗口DC
rect = lpws->rectWindow;
}
else
{ //客户DC
rect = lpws->rectClient;
OffsetRect( &rect, lpws->rectWindow.left, lpws->rectWindow.top );
}
//设备原点
lpdc->deviceOrg.x = rect.left;
lpdc->deviceOrg.y = rect.top;
lpdc->deviceExt.cx = rect.right - rect.left;
lpdc->deviceExt.cy = rect.bottom - rect.top;
// LockWindow(); ////2003.1.26
//得到窗口的暴露矩形域
iRgn = GetExposeRgn( lpdc->hwnd, uiFlags, &hRgn );
if( iRgn == NULLREGION ||
iRgn == ERROR )
{ //暴露矩形域为空或有一个错误
WinRgn_SetRect( lpdc->hrgn, 0, 0, 0, 0 );
}
else
{
if( ( uiFlags & (DCX_VALIDATE | DCX_INTERSECTUPDATE) ) == (DCX_VALIDATE | DCX_INTERSECTUPDATE) )
{ // 当前DC 用户调用BeginPaint返回的,需要与系统重绘区域进行运算 为a dc from beginpaint
HRGN hClip;
//锁住系统重绘区域
__LockRepaintRgn( &hClip ); // 2003.1.26
iRgn = WinRgn_Combine( lpdc->hrgn, lpdc->hrgn, hClip, RGN_OR );
__UnlockRepaintRgn(); //2003.1.26
if( !( iRgn == NULLREGION ||
iRgn == ERROR ) )
iRgn = WinRgn_Combine( lpdc->hrgn, lpdc->hrgn, hRgn, RGN_AND );
DEBUGMSG( DEBUG_GETSAFEDRAWPTR, ( "update dc from BeginPaint,%d,class=%s.\r\n", iUpdate, lpws->lpClass->wc.lpszClassName ) );
}
else
{ // 将新的可视区域拷贝到DC now copy hRgn to dc
WinRgn_Combine( lpdc->hrgn, hRgn, NULL, RGN_COPY );
}
}
//删除临时 区域
WinGdi_DeleteObject( hRgn );
// UnlockWindow(); //2003.1.26
if( iRgn == NULLREGION ||
iRgn == ERROR )
{
DEBUGMSG( DEBUG_GETSAFEDRAWPTR, ( "GetSafeDrawPtr_0:null rgn, class=%s, title=%s.\r\n", lpws->lpClass->wc.lpszClassName, lpws->lpWinText ) );
return NULL;
}
#ifdef __DEBUG
if( iUpdate > 5 )
{
DEBUGMSG( DEBUG_GETSAFEDRAWPTR, ( "update dc loop...%d.\r\n", iUpdate ) );
}
#endif
}
if( _GetRgnInfo( lpdc->hrgn ) == NULLREGION )
{
#ifdef __DEBUG
//_LPWINDATA lpws = _GetHWNDPtr( ((_LPGDCDATA)hdc)->hwnd );
//RETAILMSG( 1, ( "GetSafeDrawPtr_1:null rgn, class=%s, title=%s.\r\n", lpws->lpClass->wc.lpszClassName, lpws->lpWinText ) );
#endif
return NULL;
}
}
return lpdc;
}
}
SetLastError( ERROR_INVALID_HANDLE );
WARNMSG( 1, (TEXT( "Invalid hdc handle: 0x%x\r\n" ), hdc ) );
return NULL;
}
// **************************************************
// 声明:_LPGDCDATA _GetHDCPtr( HDC hdc )
// 参数:
// IN hdc - DC 句柄
// 返回值:
// 假如成功,返回_LPGDCDATA指针;否则,返回NULL
// 功能描述:
// 得到安全的DC.
// 1.检查DC是否合法;
// 引用:
//
// ************************************************
_LPGDCDATA _GetHDCPtr( HDC hdc )
{
_LPGDCDATA lpdc = (_LPGDCDATA)HANDLE_TO_PTR( hdc );
if( lpdc &&
( (WORD)GET_OBJ_TYPE( lpdc) == OBJ_MEMDC ||
(WORD)GET_OBJ_TYPE( lpdc ) == OBJ_DC
)
)
{
return lpdc;
}
SetLastError( ERROR_INVALID_HANDLE );
WARNMSG( 1, ("error: Invalid HDC handle=0x%x\r\n", hdc) );
return NULL;
}
// **************************************************
// 声明:DWORD _Gdi_UnrealizeColor( DWORD dwRealizeColor, DWORD * lpPal, UINT uiPalNum, UINT uiSrcColorType )
// 参数:
// IN dwRealizeColor - 设备相关的颜色值
// IN uiSrcColorType - 颜色类型
// IN lpPal - 色板指针
// IN uiPalNum - 色板项目数
// 返回值:
// 假如成功,返回设备无关的颜色值;否则,返回0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -