|
|
在内存DC中,同时用API绘图和内存拷贝绘图时的遮挡问题如何解决?
问题:按照我的思路是,内存拷贝绘图在API绘图之后,因该会把API绘制的图形遮挡,但事实相反,API绘制的图形永远都在内存拷贝绘制的图形之上,这是为什么,请各位大侠帮帮小弟!
截图如下:
绘图代码如下:
//开始绘图
GDI.BeginDraw();
GDI.EraseBackground();//擦除背景
//API绘制打印信息
for( int i = 0; i < PrinterSystem.GetPrinterCount(); i++ )
{
::memset( szBuffer, 0, NUMLINES( szBuffer ) );
::TextOut( GDI.GetRenderDC(), 10, cyChar * i, szBuffer,
wsprintf ( szBuffer, TEXT("%d : %s"), i, PrinterSystem.GetPrinterName(i).c_str() ) );
}
//API绘制一矩形框
Rectangle( GDI.GetRenderDC(), 0, 0, 100, 100 );
//通过内存拷贝绘制一位图
GDI.DrawImage( ButtonPosX, ButtonPosY,
ButtonW, ButtonH,
pButtonData );
GDI.EndDraw();
//结束绘图
说明:
其中的GDI是CGDI类的一个对象,CGDI类定义如下:
//绘制系统
class CGDI
{
public:
CGDI()
{
::memset( this, 0, sizeof( *this ) );
}
~CGDI(){}
bool Initialize( HWND hWnd, unsigned long w, unsigned long h );
bool Release();
bool BeginDraw();
bool EraseBackground();
bool DrawImage( long x, long y,
unsigned long ulWidth, unsigned long ulHeight,
unsigned char* pData );
bool EndDraw();
HDC GetRenderDC(){return m_hRenderDC;}
bool ReSize( unsigned long w, unsigned long h );
private:
unsigned long m_ulWidth;
unsigned long m_ulHeight;
HWND m_hWnd;
HDC m_hDC;
HDC m_hRenderDC;
HBITMAP m_hRenderBMP;
unsigned char* m_pRenderBuffer;
};
实现如下:
//绘制系统
bool CGDI::Initialize( HWND hWnd, unsigned long w, unsigned long h )
{
if( NULL == hWnd )return false;
if( 0 == w || 0 == h )return false;
m_hWnd = hWnd;
m_ulWidth = w;
m_ulHeight = h;
m_hDC = ::GetDC ( m_hWnd );
if( NULL == m_hDC )return false;
m_hRenderDC = ::CreateCompatibleDC( m_hDC );
if( NULL == m_hRenderDC )return false;
New( &m_pRenderBuffer, m_ulWidth*m_ulHeight*4 );
if( NULL == m_pRenderBuffer )return false;
::memset( m_pRenderBuffer, 0, m_ulWidth*m_ulHeight*4 );
return true;
}
bool CGDI::Release()
{
if( NULL != m_hRenderBMP ): eleteObject( m_hRenderBMP );
if( NULL != m_hRenderDC )::DeleteDC ( m_hRenderDC );
if( NULL != m_hWnd && NULL != m_hDC )::ReleaseDC( m_hWnd, m_hDC );
ReleasePointer( m_pRenderBuffer );
return true;
}
bool CGDI::BeginDraw()
{
m_hRenderBMP = ::CreateBitmap( m_ulWidth, m_ulHeight, 1, 32, m_pRenderBuffer );
::SelectObject( m_hRenderDC, m_hRenderBMP );
return true;
}
bool CGDI::EraseBackground()
{
::memset( m_pRenderBuffer, 0, m_ulWidth*m_ulHeight*4 );
return true;
}
bool CGDI::DrawImage( long x, long y,
unsigned long ulWidth, unsigned long ulHeight,
unsigned char* pData )
{
if( x >= (long)m_ulWidth || y >= (long)m_ulHeight || x <= (long)-ulWidth || y <= (long)-ulHeight )return false;
if( NULL == pData )return false;
long SL = 0, ST = 0;
long DL = 0, DT = 0;
long W = 0, H = 0;
if( x < 0 )
{
SL = -x;
DL = 0;
W = ulWidth - SL;
if( W > m_ulWidth )W = m_ulWidth;
}
else
{
SL = 0;
DL = x;
W = ulWidth;
if( ( W + DL ) > m_ulWidth )W = m_ulWidth - DL;
}
if( y < 0 )
{
ST = -y;
DT = 0;
H = ulHeight - ST;
if( H > m_ulHeight )H = m_ulHeight;
}
else
{
ST = 0;
DT = y;
H = ulHeight;
if( ( H + DT ) > m_ulHeight )H = m_ulHeight - DT;
}
long S = 0, D = 0, A = 0, cx = 0, cy = 0;
for( cy = 0; cy < H; cy++ )
{
for( cx = 0; cx < W; cx++ )
{
A = ( int )pData[ ( ( cy + ST ) * ulWidth + ( cx + SL ) ) * 4 + 3 ];
S = ( int )pData[ ( ( cy + ST ) * ulWidth + ( cx + SL ) ) * 4 ];
D = ( int )m_pRenderBuffer[ ( ( cy + DT ) * m_ulWidth + ( cx + DL ) ) * 4 ];
D = S * A + D * ( 255 - A );
D = D >> 8;
m_pRenderBuffer[ ( ( cy + DT ) * m_ulWidth + ( cx + DL ) ) * 4 ] = ( unsigned char )D;
S = ( int )pData[ ( ( cy + ST ) * ulWidth + ( cx + SL ) ) * 4 + 1];
D = ( int )m_pRenderBuffer[ ( ( cy + DT ) * m_ulWidth + ( cx + DL ) ) * 4 + 1 ];
D = S * A + D * ( 255 - A );
D = D >> 8;
m_pRenderBuffer[ ( ( cy + DT ) * m_ulWidth + ( cx + DL ) ) * 4 + 1 ] = ( unsigned char )D;
S = ( int )pData[ ( ( cy + ST ) * ulWidth + ( cx + SL ) ) * 4 + 2];
D = ( int )m_pRenderBuffer[ ( ( cy + DT ) * m_ulWidth + ( cx + DL ) ) * 4 + 2 ];
D = S * A + D * ( 255 - A );
D = D >> 8;
m_pRenderBuffer[ ( ( cy + DT ) * m_ulWidth + ( cx + DL ) ) * 4 + 2 ] = ( unsigned char )D;
}
}
return true;
}
bool CGDI::EndDraw()
{
::BitBlt ( m_hDC, 0, 0, m_ulWidth, m_ulHeight, m_hRenderDC, 0, 0, SRCCOPY );
::DeleteObject( m_hRenderBMP );
return true;
}
bool CGDI::ReSize( unsigned long w, unsigned long h )
{
if( 0 == w || 0 == h )return false;
if( m_ulWidth != w || m_ulHeight != h )
{
ReleasePointer( m_pRenderBuffer );
New( &m_pRenderBuffer, w*h*4 );
if( NULL == m_pRenderBuffer )return false;
::memset( m_pRenderBuffer, 0, w*h*4 );
}
m_ulWidth = w;
m_ulHeight = h;
return true;
}
|
|