⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 didevimg.cpp

📁 VC游戏编程基础
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    }

    if( 0 == ::GetObject( hbmpRender, sizeof( DIBSECTION ), &info ) )
    {
        hr = E_FAIL;
        goto LCleanReturn;
    }

    
    SelectObject( hdcRender, hbmpRender );
    SelectObject( hdcRender, m_hFont );
    SetBkMode( hdcRender, TRANSPARENT );

    FillBackground( hbmpRender, m_BkColor );

    // Create a bitmap to store the alpha channel for the bitmap. Since GDI
    // doesn't support alpha information, everything is drawn fully transparent.
    // As a workaround, whenever a 2D method is called on the render dc,
    // the same method will be called on the alpha dc. Before transfering the
    // image to the provided surface, the transparency information will be 
    // restored from the alpha bitmap. 
    hbmpAlpha = CreateDIBSection( hdcAlpha, &bmi, DIB_RGB_COLORS, NULL, NULL, NULL );
    if( NULL == hbmpAlpha )
    {
        hr = DIERR_OUTOFMEMORY;
        goto LCleanReturn;
    }

    // Clear the alpha channel
    DIBSECTION infoAlpha;
    if( 0 == ::GetObject( hbmpAlpha, sizeof(DIBSECTION), &infoAlpha ) )
    {
        hr = E_FAIL;
        goto LCleanReturn;
    }
    ZeroMemory( infoAlpha.dsBm.bmBits, infoAlpha.dsBm.bmWidthBytes * infoAlpha.dsBm.bmHeight );

    SelectObject( hdcAlpha, hbmpAlpha );

    SetBkMode( hdcAlpha, TRANSPARENT );
    SetTextColor( hdcAlpha, RGB(255, 255, 255) );
    SelectObject( hdcAlpha, GetStockObject( WHITE_PEN ) );
    SelectObject( hdcAlpha, m_hFont );
        

    // Draw callout and object text
    for( i=0; i < m_dwNumObjects; i++ )
    {
        COLORREF crNorm, crHigh, crCur;
        
        DIDICallout *pCallout = m_apObject[i]->GetCallout( m_dwActiveView );
        DIDIOverlay *pOverlay = m_apObject[i]->GetOverlay( m_dwActiveView );

        MAXSTRING    strCallout = {0};
        MAXSTRING    strObject  = {0};

        RECT rcFill = {0};
        
        // Callout may be invisible
        if( DIDICOS_INVISIBLE & m_apObject[i]->GetCalloutState() )
            continue;

        if( IsRectEmpty( &pOverlay->rcScaled ) ||
            IsRectEmpty( &pCallout->rcScaled ) )
            continue;

        m_apObject[i]->GetCalloutText( strCallout, MAX_PATH );
        m_apObject[i]->GetName( strObject, MAX_PATH );
        m_apObject[i]->GetCalloutColors( &crNorm, &crHigh );

        crCur = ( DIDICOS_HIGHLIGHTED & m_apObject[i]->GetCalloutState() ) ? crHigh : crNorm;
        
        SetTextColor( hdcRender, crNorm );
        
        DWORD dwFlags = DT_TOP | DT_END_ELLIPSIS | DT_NOCLIP;

        // Get the fill rect
        rcFill = pOverlay->rcScaled;
        DrawText( hdcRender, strObject, lstrlen( strObject ),
                  &rcFill, dwFlags | DT_CALCRECT );

        // Position the fill rect
        rcFill.left += pOverlay->rcScaled.right - rcFill.right;
        rcFill.right += pOverlay->rcScaled.right - rcFill.right;

        // Inflate the fill rect
        InflateRect( &rcFill, 5, 5 );

        // But make sure the rect still fits on the screen
        rcFill.left   = max( rcFill.left,   0 );
        rcFill.top    = max( rcFill.top,    0 );
        rcFill.right  = min( rcFill.right,  info.dsBm.bmWidth );
        rcFill.bottom = min( rcFill.bottom, info.dsBm.bmHeight );

        // Draw the object text
        DrawText( hdcRender, strObject, lstrlen( strObject ),
                  &(pOverlay->rcScaled), dwFlags | DT_RIGHT );

        if( hdcAlpha )
            DrawText( hdcAlpha, strObject, lstrlen( strObject ),
                      &(pOverlay->rcScaled), dwFlags | DT_RIGHT );
        
        SetTextColor( hdcRender, crCur );
        
        // Get the fill rect
        rcFill = pCallout->rcScaled;
        DrawText( hdcRender, strCallout, lstrlen( strCallout ),
                  &rcFill, dwFlags | DT_CALCRECT );

        // Inflate the fill rect
        InflateRect( &rcFill, 5, 5 );

        // But make sure the rect still fits on the screen
        rcFill.left   = max( rcFill.left,   0 );
        rcFill.top    = max( rcFill.top,    0 );
        rcFill.right  = min( rcFill.right,  info.dsBm.bmWidth );
        rcFill.bottom = min( rcFill.bottom, info.dsBm.bmHeight );

        // Draw the callout text
        DrawText( hdcRender, strCallout, lstrlen( strCallout ),
                  &(pCallout->rcScaled), dwFlags | DT_LEFT );

        if( hdcAlpha )
            DrawText( hdcAlpha, strCallout, lstrlen( strCallout ),
                      &(pCallout->rcScaled), dwFlags | DT_LEFT );

        // If the TOOLTIP flag is set and the callout text doesn't fit within
        // the scaled rect, we need to draw the full text
        if( DIDICOS_TOOLTIP & m_apObject[i]->GetCalloutState() )
        {
            SIZE TextSize = {0};
            
            // This string was modified by the first call to draw text, so we
            // need to get a fresh copy
            m_apObject[i]->GetCalloutText( strCallout, MAX_PATH-4 );
            GetTextExtentPoint32( hdcRender, strCallout, lstrlen( strCallout ), &TextSize );

            if( TextSize.cx > ( pCallout->rcScaled.right - pCallout->rcScaled.left ) )
            {
                // Yep, the text is too big and is marked as a tooltip candidate.
                RECT rcBitmap = { 0, 0, info.dsBm.bmWidth, info.dsBm.bmHeight };
                DrawTooltip( hdcRender, hdcAlpha, strCallout, &rcBitmap, &(pCallout->rcScaled),
                             CRFromColor( m_BkColor ), crNorm, crHigh );
                
            }

        }
    }

    // Finalize rendering
    GdiFlush();

    // Copy the freshly rendered image to the render target
    switch( eTarget )
    {
        case DIDIRT_SURFACE:
            // Since the image is being transfered to a Direct3D surface, the stored
            // alpha information could be used.
            ApplyAlphaChannel( hbmpRender, hbmpAlpha, ( (m_BkColor & ALPHA_MASK) == ALPHA_MASK ) );
            rcBitmap.right  = info.dsBm.bmWidth;
            rcBitmap.bottom = info.dsBm.bmHeight;

            hr = D3DXLoadSurfaceFromMemory( (LPDIRECT3DSURFACE9) pvTarget,
                                             NULL, NULL, info.dsBm.bmBits,
                                             D3DFMT_A8R8G8B8, 
                                             info.dsBm.bmWidthBytes,
                                             NULL, &rcBitmap, 
                                             D3DX_FILTER_NONE, 0 );
            break;

        case DIDIRT_DC:
            BitBlt( (HDC) pvTarget, 0, 0, info.dsBm.bmWidth, info.dsBm.bmHeight,
                          hdcRender, 0, 0, SRCCOPY );

            break;
    
        default:
            // Invalid render target
            hr = DIERR_INVALIDPARAM;
            goto LCleanReturn;
    }   


LCleanReturn:
    
    DeleteDC( hdcRender );
    DeleteDC( hdcAlpha );
    
    if( hbmpAlpha )
        DeleteObject( hbmpAlpha );

    if( hbmpRender )
        DeleteObject( hbmpRender );

    return hr;
}




//-----------------------------------------------------------------------------
// Name: RenderToTarget
// Desc: Renders an image of the device and its callouts 
//-----------------------------------------------------------------------------
HRESULT CDIDevImage::RenderToTarget( LPVOID pvTarget, DIDIRENDERTARGET eTarget )
{
    HRESULT    hr           = DI_OK;
    UINT       i            = 0; // Loop variable
    RECT       rcBitmap     = {0};
    HDC        hdcRender    = NULL;
    HDC        hdcAlpha     = NULL;
    DIBSECTION info         = {0};
    
    LPBYTE     pSavedPixels = NULL;
    LPBYTE     pCleanPixels = NULL;
    
    HBITMAP    hbmpAlpha    = NULL;
    BITMAPINFO bmi = {0};
    
    
    // Verify initialization
    if( false == m_bInitialized )
        return DIERR_NOTINITIALIZED;

    // Verify parameters
    if( NULL == pvTarget )
        return DIERR_INVALIDPARAM;

    // Sanity check
    if( m_dwActiveView >= m_dwNumViews )
        return E_FAIL;

    // Load images if not loaded already
    if( NULL == m_ahImages[ m_dwActiveView ] )
    {  
        // File UI not yet loaded
        if( FAILED( hr = LoadImages() ) )
            return hr;
    } 
    

    // Get information about the background image.
    if( 0 == ::GetObject( m_ahImages[ m_dwActiveView ], sizeof(DIBSECTION), &info ) )
        return E_FAIL;


    // Allocate space for the saved background images
    pSavedPixels = new BYTE[ info.dsBm.bmWidthBytes * info.dsBm.bmHeight ];
    if( NULL == pSavedPixels )
    {
        hr = DIERR_OUTOFMEMORY;
        goto LCleanReturn;
    }

    pCleanPixels = new BYTE[ info.dsBm.bmWidthBytes * info.dsBm.bmHeight ];
    if( NULL == pCleanPixels )
    {
        // Could not create a copy of the background image; release memory
        // here to avoid using unitialized pixels during cleanup.
        SAFE_DELETE_ARRAY( pSavedPixels );

        hr = DIERR_OUTOFMEMORY; 
        goto LCleanReturn;
    }

    // Save the background
    CopyMemory( pSavedPixels, info.dsBm.bmBits, 
                info.dsBm.bmWidthBytes * info.dsBm.bmHeight );
    
    // Draw overlays
    for( i=0; i < m_dwNumObjects; i++ )
    {  
        DIDIOverlay *pOverlay = m_apObject[i]->GetOverlay( m_dwActiveView );
        
        if( DIDICOS_HIGHLIGHTED & m_apObject[i]->GetCalloutState() )
        {     
            // Draw overlay
            if( pOverlay->hImage )    
                ApplyOverlay( m_ahImages[ m_dwActiveView ], &pOverlay->rcScaled, pOverlay->hImage );      
        }
    }

    // Before drawing callouts and lines on top of the composed image, save
    // a copy of the image bits. This will allow us to erase portions of lines
    // which intersect with the callout text.
    CopyMemory( pCleanPixels, info.dsBm.bmBits, 
                info.dsBm.bmWidthBytes * info.dsBm.bmHeight );
  
    // Load the background image into a device context for rendering
    hdcRender = CreateCompatibleDC( NULL );
    SelectObject( hdcRender, m_ahImages[ m_dwActiveView ] );
    
    SelectObject( hdcRender, m_hFont );
    SetBkMode( hdcRender, TRANSPARENT );
    SetBkColor( hdcRender, CRFromColor(m_BkColor) );
  
    hdcAlpha = CreateCompatibleDC( NULL );

    // Create a bitmap to store the alpha channel for the bitmap. Since GDI
    // doesn't support alpha information, everything is drawn fully transparent.
    // As a workaround, whenever a 2D method is called on the render dc,
    // the same method will be called on the alpha dc. Before transfering the
    // image to the provided surface, the transparency information will be 
    // restored from the alpha bitmap. 
    
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = info.dsBm.bmWidth;
    bmi.bmiHeader.biHeight = - (int) info.dsBm.bmHeight; // top-down
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;

    hbmpAlpha = CreateDIBSection( hdcAlpha, &bmi, DIB_RGB_COLORS, NULL, NULL, NULL );
    if( NULL == hbmpAlpha )
    {
        hr = DIERR_OUTOFMEMORY;
        goto LCleanReturn;
    }

    // Clear the alpha channel
    DIBSECTION infoAlpha;
    if( 0 == ::GetObject( hbmpAlpha, sizeof(DIBSECTION), &infoAlpha ) )
    {
        hr = E_FAIL;
        goto LCleanReturn;
    }
    ZeroMemory( infoAlpha.dsBm.bmBits, infoAlpha.dsBm.bmWidthBytes * infoAlpha.dsBm.bmHeight );

    SelectObject( hdcAlpha, hbmpAlpha );

    SetBkMode( hdcAlpha, TRANSPARENT );
    SetTextColor( hdcAlpha, RGB(255, 255, 255) );
    SelectObject( hdcAlpha, GetStockObject( WHITE_PEN ) );
    SelectObject( hdcAlpha, m_hFont );
     

    // Draw callout lines
    for( i=0; i < m_dwNumObjects; i++ )
    {
        COLORREF crNorm, crHigh, crCur;
        POINT    aptArrow[2] = {0}; 
        BOOL     bDrawArrow = FALSE;
        
        // Get the current callout
        DIDICallout *pCallout = m_apObject[i]->GetCallout( m_dwActiveView );

        // Callout may be invisible
        if( DIDICOS_INVISIBLE & m_apObject[i]->GetCalloutState() )
            continue;
        
        // Retrieve normal/highlighted colors
        m_apObject[i]->GetCalloutColors( &crNorm, &crHigh );

        // Set the current color based on callout state
        crCur = ( DIDICOS_HIGHLIGHTED & m_apObject[i]->GetCalloutState() ) ? crHigh : crNorm;
       

        DeleteObject( SelectObject( hdcRender, CreatePen( PS_SOLID, 3, CRFromColor(m_BkColor) ) ) ); 
        DeleteObject( SelectObject( hdcAlpha, CreatePen( PS_SOLID, 3, RGB(255, 255, 255) ) ) ); 

        // Draw callout lines
        MoveToEx( hdcRender, pCallout->aptLineScaled[0].x, pCallout->aptLineScaled[0].y, NULL );
        MoveToEx( hdcAlpha, pCallout->aptLineScaled[0].x, pCallout->aptLineScaled[0].y, NULL );
        
        for( UINT j=1; j < pCallout->dwNumPoints; j++ )
        {
            LineTo( hdcRender, pCallout->aptLineScaled[j].x, pCallout->aptLineScaled[j].y );
            LineTo( hdcAlpha, pCallout->aptLineScaled[j].x, pCallout->aptLineScaled[j].y );
        }

        // Draw arrow ends
        if( pCallout->dwNumPoints >= 2 )
        {
            DWORD dwEnd = pCallout->dwNumPoints-1;
            POINT p1 = pCallout->aptLineScaled[ dwEnd ];
            POINT p2 = pCallout->aptLineScaled[ dwEnd-1 ];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -