📄 gdi.c
字号:
/******************************************************
Copyright(c) 版权所有,1998-2005微逻辑。保留所有权利。
******************************************************/
/*****************************************************
文件说明:图形设备界面模块
版本号:3.0.0
开发时期:1998
作者:李林
修改记录:
2004-09-15,DrawText 的下画线 画在了上面
2004-05-21, 增加 StretchBlt
2004-05-10: 增加 TransparentBlt
2003-09-24: DoExtSelectClipRgn 没有对expose区域做处理
2003-09-13, SelectClipRgn( hdc, NULL ) mean valid the hdc default display surface
2003-09-13, TA_CENTER aligned horizontally not vertizontally
2003-09-06: LN, 在BRUSH & PEN结构增加 ->clrRef 成员
2003-07-22, SelectClipRgn( hdc, hrgn ), 当 hrgn==NULL时,清空 region
2003-07-22: DeleteDC( ... ) 不用 删掉 hBitmap, hBrush, hPen, ...
2003-07-14: 增加Arc 功能 和 GDCDATA-> arcMode 成员
2003-06-06: _GDCDATA 加入 OBJLIST obj,取代objType和ulOwner
2003-05-14 : CreateBitmap 为避免Heap的碎片化 对bitmap,当其所用缓存大小 大于 某大小时, 用VirtualAlloc
2003-05-06 :
1.LN 当SetBkMode( TRANSPARENT ) 并且 调用Rectangle
(用WHITE_BRUSH)有错误
2.增加对 FillRect( hdc, (COLOR_WINDOW+1) )的支持
******************************************************/
#include <eframe.h>
#include <efile.h>
#include <eassert.h>
#include <enls.h>
#include <eapisrv.h>
#include <gwmeobj.h>
#include <gdc.h>
#include <bheap.h>
#include <epwin.h>
#include <eprgn.h>
#include <winsrv.h>
#include <gdisrv.h>
#define XOFFSET( lpdc ) ((lpdc)->deviceOrg.x + (lpdc)->viewportOrg.x - (lpdc)->windowOrg.x)
#define YOFFSET( lpdc ) ((lpdc)->deviceOrg.y + (lpdc)->viewportOrg.y - (lpdc)->windowOrg.y)
#define WIDTH_LEFT( w ) ( (w) >> 1 )
#define WIDTH_TOP( w ) ( (w) >> 1 )
#define WIDTH_RIGHT( w ) ( (w) - ((w) >> 1) - 1 )
#define WIDTH_BOTTOM( w ) ( (w) - ((w) >> 1) - 1 )
#define ABS( x ) ( (x) >= 0 ? (x) : -(x) )
typedef struct __FILLRGN
{
const _RECTNODE FAR* lprNodes;
RECT rect;
}_FILLRGN;
typedef void ( * LPFILLFUN )( _LPCDISPLAYDRV lpDispDrv, _LPBLKBITBLT lpFillData, _FILLRGN * lpFillRgn );
#define _MAX_GDIOBJECT_NUM 10
static _GDCDATA * lpSysDC;//[_MAX_GDIOBJECT_NUM];
static CRITICAL_SECTION csDCList;
static LPOBJLIST lpDCObjList = NULL;
static HANDLE hSempore = NULL;
static int cwEllipsis;
_LPBITMAPDATA _GetHBITMAPPtr( HBITMAP );
_LPBRUSHDATA _GetHBRUSHPtr( HBRUSH hBrush );
BOOL ReleasePaintDC( HWND hWnd, HDC hdc );
extern HGDIOBJ WINAPI OEM_GetStockObject( int fObject );
static BOOL _DrawLine( _LPCDISPLAYDRV lpDispDrv, _LPRECTNODE lprn, _LINEDATA * lpLine, int x0, int y0, int x1, int y1 );
static void _FillTransparentRgn( _LPCDISPLAYDRV lpDispDrv, _LPBLKBITBLT lpFillData, _FILLRGN * lpFillRgn );
static void _FillRgn( _LPCDISPLAYDRV lpDispDrv, _LPBLKBITBLT lpFillData, _FILLRGN * lpFillRgn );
static int DoExtSelectClipRgn( HDC hdc, HRGN hrgn, int mode );
// **************************************************
// 声明:BOOL _InitialGdi( void )
// 参数:
// 无
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 初始化GDI
// 引用:
// 当GWME系统初始化时,回调用该函数
// ************************************************
BOOL _InitialGdi( void )
{
int i;
HFONT hFont;
_LPFONT lpFont;
InitializeCriticalSection( &csDCList );
csDCList.lpcsName = "CS-GDC";
lpSysDC = malloc( sizeof(_GDCDATA) * _MAX_GDIOBJECT_NUM );
if( lpSysDC )
{
for( i = 0; i < _MAX_GDIOBJECT_NUM; i++ )
{
lpSysDC[i].obj.objType = OBJ_NULL;
}
}
hFont = OEM_GetStockObject(SYSTEM_FONT);//系统默认的字体
lpFont = _GetHFONTPtr( hFont );
cwEllipsis = lpFont->lpDriver->lpWordWidth( lpFont->handle, ' ' );
//初始化信号量
hSempore = CreateSemaphore( NULL, _MAX_GDIOBJECT_NUM, _MAX_GDIOBJECT_NUM, NULL );
return TRUE;
}
// **************************************************
// 声明:void _DeInitialGdi( void )
// 参数:
// 无
// 返回值:
// 无
// 功能描述:
// 关闭GDI
// 引用:
// 与_InitialGdi对应,该函数释放已分配的资源
// ************************************************
void _DeInitialGdi( void )
{
CloseHandle( hSempore );
DeleteCriticalSection( &csDCList );
}
// **************************************************
// 声明:_LPCDISPLAYDRV GetDisplayDeviceDriver( _LPBITMAPDATA lpBitmap )
// 参数:
// IN lpBitmap - _BITMAPDATA结构指针
// 返回值:
// 假入成功,返回显示驱动程序接口;否则,返回NULL
// 功能描述:
// 得到一个兼容显示面的图形驱动程序接口
// 引用:
//
// ************************************************
_LPCDISPLAYDRV GetDisplayDeviceDriver( _LPBITMAPDATA lpBitmap )
{
_LPCDISPLAYDRV lpdd = NULL;
if( lpBitmap &&
lpBitmap->bmPlanes == 1 )
{
if( lpBitmap->bmBitsPixel == lpDisplayBitmap->bmBitsPixel )
lpdd = lpDrvDisplayDefault;
#ifdef HAVE_GDC_1BPP
else if( lpBitmap->bmBitsPixel == 1 )
lpdd = &_drvDisplay1BPP;
#endif
#ifdef HAVE_GDC_4BPP
else if( lpBitmap->bmBitsPixel == 4 )
lpdd = &_drvDisplay4BPP;
#endif
#ifdef HAVE_GDC_8BPP
else if( lpBitmap->bmBitsPixel == 8 ) //
lpdd = &_drvDisplay8BPP;
#endif
#ifdef HAVE_GDC_16BPP
else if( lpBitmap->bmBitsPixel == 16 ) //
lpdd = &_drvDisplay16BPP;
#endif
#ifdef HAVE_GDC_32BPP
else if( lpBitmap->bmBitsPixel == 32 ) //
lpdd = &_drvDisplay32BPP;
#endif
#ifdef HAVE_GDC_24BPP
else if( lpBitmap->bmBitsPixel == 24 )
lpdd = &_drvDisplay24BPP;
#endif
}
return lpdd;
}
// **************************************************
// 声明:static VOID _CheckGDCData( void )
// 参数:
// 无
// 返回值:
// 无
// 功能描述:
// 检查DC
// 引用:
//
// ************************************************
static VOID _CheckGDCData( void )
{
int i;
_LPGDCDATA p = NULL;
// 申请一个系统DC资源
p = lpSysDC;
for( i = 0; i < _MAX_GDIOBJECT_NUM; i++, p++ )
{
if( p->hwnd )
{
_LPWINDATA lpws;
//由窗口句柄得到其指针对象
lpws = _GetHWNDPtr( p->hwnd );
if( lpws )
{
DWORD dwOldPerm = SetProcPermissions( ~0 ); //得到对进程的存取权限
RETAILMSG( 1, ( "_CheckGDCData: win=%s,class=%s,flags=0x%x.\r\n", lpws->lpWinText, lpws->lpClass->wc.lpszClassName, p->uiFlags ) );
SetProcPermissions( dwOldPerm ); //得到对进程的存取权限
}
}
else
{
RETAILMSG( 1, ( "_CheckGDCData: null window,objType=0x%x,flags=0x%x.\r\n", p->obj.objType, p->uiFlags ) );
}
}
}
// **************************************************
// 声明:static _LPGDCDATA _AllocGDCData( void )
// 参数:
// 无
// 返回值:
// 假入成功,返回_GDCDATA结构指针;否则,返回NULL
// 功能描述:
// 从系统保留的DC里分配一个DC数据结构
// 引用:
//
// ************************************************
#define DEBUG_AllocGDCData 0
static _LPGDCDATA _AllocGDCData( void )
{
int i, count;
_LPGDCDATA p = NULL;
// 申请一个系统DC资源信号量,如果申请不到,则循环申请20次
// 我应该用更好的办法去做该功能。。。。
count = 0;
while( count < 20 )
{
if( WaitForSingleObject( hSempore, 100 ) == WAIT_OBJECT_0 )
break;
WARNMSG( DEBUG_AllocGDCData, (TEXT("_AllocGDCData:try get dc(%d)\r\n"), count ) );
count++;
}
if( count == 20 )
{ //没有得到资源,通常是系统有什么错误。
WARNMSG( DEBUG_AllocGDCData, (TEXT("_AllocGDCData:no enough DC solt, thread=0x%x\r\n"), GetCurrentThreadId() ) );
_CheckGDCData();
return NULL;
}
// 申请一个系统DC资源
count = 20; //试20次
while( count-- )
{
p = lpSysDC;
for( i = 0; i < _MAX_GDIOBJECT_NUM; i++, p++ )
{
if( p->obj.objType == OBJ_NULL &&
Interlock_TestExchange( (LPLONG)&p->obj.objType, OBJ_NULL, OBJ_DC ) == OBJ_NULL )
{
p->obj.ulOwner = (ULONG)GetCallerProcess();
return p;
}
}
}
// 不应该到这里
ASSERT( 0 );
ERRORMSG( DEBUG_AllocGDCData, (TEXT("error in _AllocGDCData: undef error!.\r\n") ) );
return NULL;
}
// **************************************************
// 声明:int UpdateDCState( UINT uiState )
// 参数:
// IN uiState -
// 返回值:
// 返回1;
// 功能描述:
// 更新DC状态
// 引用:
// 当窗口的Z序、大小改变并且窗口当前有正在使用的DC时,该DC对应的
// 窗口的内容(大小、裁剪区域)也虽之改变。这里就是告诉DC去重新更新
// 相关内容
// ************************************************
int UpdateDCState( UINT uiState )
{
int i;
_LPGDCDATA lpdc = lpSysDC;
for( i = 0; i < _MAX_GDIOBJECT_NUM; i++, lpdc++ )
{
if( lpdc->obj.objType != OBJ_NULL &&
lpdc->hwnd )
{
Interlock_TestExchange( (LPLONG)&lpdc->uiState, 0, 1 );
}
}
return 1;
}
// **************************************************
// 声明:static BOOL CALLBACK DelMemDCObj( LPOBJLIST lpObj, LPARAM lParam )
// 参数:
// IN lpObj - _GDCDATA对象
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 删除一个内存DC对象
// 引用:
//
// ************************************************
static BOOL CALLBACK DelMemDCObj( LPOBJLIST lpObj, LPARAM lParam )
{
_LPGDCDATA lpdc = (_LPGDCDATA)lpObj;
ASSERT( lpObj->objType == OBJ_MEMDC );
WinGdi_DeleteObject( lpdc->hrgn );
lpdc->obj.objType = OBJ_NULL;
BlockHeap_Free( hgwmeBlockHeap, 0, lpdc, sizeof(_GDCDATA) );
return TRUE;
}
// **************************************************
// 声明:BOOL WINAPI WinGdi_DeleteDC( HDC hdc )
// 参数:
// IN hdc - DC句柄
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 删除设备对象。你不能删除用GetDC得到的hdc, 你能用ReleaseDC去释放GetDC得到的hdc
// 引用:
// 系统API
// ************************************************
BOOL WINAPI WinGdi_DeleteDC( HDC hdc )
{
_LPGDCDATA lpdc = _GetHDCPtr( hdc );
if( lpdc && lpdc->obj.objType == OBJ_MEMDC ) // 合法吗?
{
EnterCriticalSection( &csDCList ); //进入互斥段
ObjList_Remove( &lpDCObjList, &lpdc->obj ); // 从链表移出
LeaveCriticalSection( &csDCList ); //离开互斥段
return DelMemDCObj( &lpdc->obj, 0 );//释放
}
else
{
WARNMSG( 1, ( "error at WinGdi_DeleteDC: invalid hdc(0x%x).\r\n", hdc ) );
return FALSE;
}
}
// **************************************************
// 声明:static BOOL DelSysDC( _LPGDCDATA lpdc )
// 参数:
// IN lpdc - _GDCDATA结构指针
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 删除DC,这里的DC是指用BeginPaint 或 GetDC 或 GetDCEx得到的
// 引用:
//
// ************************************************
static BOOL DelSysDC( _LPGDCDATA lpdc )
{
WinGdi_DeleteObject( lpdc->hrgn );
lpdc->uiState = 0;
lpdc->obj.ulOwner = 0;
Interlock_Exchange( (LPLONG)&lpdc->obj.objType, OBJ_NULL );
ReleaseSemaphore( hSempore, 1, NULL ); // 释放一个DC资源(信号量)
return TRUE;
}
// **************************************************
// 声明:BOOL ReleasePaintDC( HWND hWnd, HDC hdc )
// 参数:
// IN hWnd - 窗口句柄
// IN hdc - DC句柄
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -