home *** CD-ROM | disk | FTP | other *** search
/ Game Programming in C++ - Start to Finish / GameProgrammingS.iso / developer_install / ReplicaNetFreewareV5_4.exe / data1.cab / Program_Executable_Files / Common3DApp / Src / didcfgview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-10-30  |  113.7 KB  |  3,851 lines

  1. //-----------------------------------------------------------------------------
  2. // File: didcfgview.cpp
  3. //
  4. // Desc: Interface for retrieving and rendering DirectInput Device
  5. //       configuration view( implemenation ). Feel free to use 
  6. //       this class as a starting point for adding extra functionality.
  7. //
  8. //
  9. // Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11. #define DIRECTINPUT_VERSION 0x0800
  12. #include <d3d8.h>
  13. #include <d3dx8tex.h>
  14. #include <assert.h>
  15. #include <tchar.h>
  16. #include "didcfgview.h"
  17. #include "dxutil.h"
  18.  
  19.  
  20.  
  21.  
  22. //-----------------------------------------------------------------------------
  23. // Name: DIDCfgView()
  24. // Desc: constructor
  25. //-----------------------------------------------------------------------------
  26. DIDCfgView::DIDCfgView()
  27.     :   m_lpViewManager( NULL ),
  28.         m_lpCalloutManager( NULL ),
  29.         m_bIsInit( FALSE ),
  30.         m_nView( DIDCV_INVALID_ID ),
  31.         m_lpDidImgHeader( NULL ),
  32.         m_lpCustomViewInfo( NULL ),
  33.         m_lpDIDevice( NULL ),
  34.         m_bCanBeCollapsed( FALSE ),
  35.         m_bIsCollapsed( FALSE ),
  36.         m_lpDiaf( NULL ),
  37.         m_crFore( RGB( 0xff, 0xff, 0xff ) ),
  38.         m_crBack( RGB( 0x0, 0x0, 0x0 ) ),
  39.         m_crHighlight( RGB( 0x33, 0x33, 0x33 ) ),
  40.         m_crHighlightLine( RGB( 0x99, 0xff, 0x0 ) ),
  41.         m_hFont( NULL )
  42. {
  43.     _tcscpy( m_tszDefaultText, TEXT( "- - -" ) );
  44.     ZeroMemory( &m_ptOrigin, sizeof( POINT ) );
  45. }
  46.  
  47.  
  48.  
  49.  
  50. //-----------------------------------------------------------------------------
  51. // Name: ~DIDCfgView()
  52. // Desc: destructor
  53. //-----------------------------------------------------------------------------
  54. DIDCfgView::~DIDCfgView()
  55. {
  56.     CleanUp();
  57.     
  58.     if( m_hFont )
  59.     {
  60.         // free the font
  61.         DeleteObject( m_hFont );
  62.         m_hFont = NULL;
  63.     }
  64. }
  65.  
  66.  
  67.  
  68.  
  69. //-----------------------------------------------------------------------------
  70. // Name: Init()
  71. // Desc: initializes the DIDCfgView object with a DirectInputDevice8
  72. //       reference.  upon successful completion of this functions, image
  73. //       and callout data for the device should be successfully retrieved,
  74. //       loaded, and processed, ready to be used.( ultimately, after optionally 
  75. //       setting the action format, callout state, performing hit tests, etc -
  76. //       the image can be drawn by calling RenderView(). )  this Init()
  77. //       must be called successfully before anything else can be used.
  78. //-----------------------------------------------------------------------------
  79. HRESULT DIDCfgView::Init( LPDIRECTINPUTDEVICE8 lpDidev )
  80. {
  81.     HRESULT hr;
  82.  
  83.     // always start clean
  84.     CleanUp();
  85.  
  86.     // sanity check
  87.     if( NULL == lpDidev )
  88.     {
  89.         return DIERR_INVALIDPARAM;
  90.     }
  91.  
  92.     // allocate objects
  93.     hr = InitAlloc();
  94.     if( FAILED( hr ) )
  95.     {
  96.         CleanUp();
  97.         return hr;
  98.     }
  99.  
  100.     // retrieve the image info from DirectInput
  101.     hr = InitImageInfoRetrieve( lpDidev );
  102.     if( FAILED( hr ) )
  103.     {
  104.         // no device image on system, let's build our own
  105.         hr = InitCustomViews( lpDidev );
  106.         if( FAILED( hr ) )
  107.         {
  108.             CleanUp();
  109.             return hr;
  110.         }
  111.  
  112.         // keep a reference for custom views, since we might
  113.         // need the device to reconstruct collapsed views
  114.         m_lpDIDevice = lpDidev;
  115.         m_lpDIDevice->AddRef();
  116.     }
  117.     else
  118.     {
  119.         // process the image info from DirectInput
  120.         hr = InitImageInfoProcess();
  121.         if( FAILED( hr ) )
  122.         {
  123.             CleanUp();
  124.             return hr;
  125.         }
  126.     }
  127.  
  128.     m_bIsInit = TRUE;
  129.     return S_OK;
  130. }
  131.  
  132.  
  133.  
  134.  
  135. //-----------------------------------------------------------------------------
  136. // Name: CleanUp()
  137. // Desc: resets the cfgview object, freeing memory and other resources
  138. //       this method is idempotent.
  139. //-----------------------------------------------------------------------------
  140. VOID DIDCfgView::CleanUp()
  141. {
  142.     m_bIsInit = FALSE;
  143.     m_nView = -1;
  144.     m_bCanBeCollapsed = FALSE;
  145.     m_bIsCollapsed = FALSE;
  146.     
  147.     if( m_lpDidImgHeader )
  148.     {
  149.         // free array
  150.         SAFE_DELETE_ARRAY( m_lpDidImgHeader->lprgImageInfoArray );
  151.  
  152.         // free the imginfoheader
  153.         delete m_lpDidImgHeader;
  154.         m_lpDidImgHeader = NULL;
  155.     }
  156.  
  157.     // free the view manager
  158.     SAFE_DELETE( m_lpViewManager );
  159.  
  160.     // free callout manager
  161.     SAFE_DELETE( m_lpCalloutManager );
  162.  
  163.     // free the custom view info
  164.     SAFE_DELETE( m_lpCustomViewInfo );
  165.  
  166.     // release the DirectInputDevice
  167.     SAFE_RELEASE( m_lpDIDevice );
  168.  
  169.     if( m_lpDiaf )
  170.     {
  171.         // free the DIACTION array
  172.         SAFE_DELETE_ARRAY( m_lpDiaf->rgoAction );
  173.  
  174.         // free the DIACTIONFORMAT
  175.         delete m_lpDiaf;
  176.         m_lpDiaf = NULL;
  177.     }
  178. }
  179.  
  180.  
  181.  
  182.  
  183. //-----------------------------------------------------------------------------
  184. // Name: SetActionFormat()
  185. // Desc: sets the action format mapping for this cfgview object.  the action
  186. //       format should be relevant to the same DirectInputDevice that was
  187. //       used to initialize this object.  this information will be used when
  188. //       the configuration view is rendered.
  189. //-----------------------------------------------------------------------------
  190. HRESULT DIDCfgView::SetActionFormat( LPDIACTIONFORMAT lpDiaf )
  191. {
  192.     UINT i;
  193.  
  194.     // make sure this object has been properly initialized
  195.     if( FALSE == m_bIsInit )
  196.         return DIERR_NOTINITIALIZED;
  197.  
  198.     // clear any actions currently mapped
  199.     m_lpCalloutManager->ClearAllActionMaps();
  200.  
  201.     // no DIACTIONFORMAT passed in, error
  202.     if( NULL == lpDiaf )
  203.         return DIERR_INVALIDPARAM;
  204.  
  205.     // set each action mapping
  206.     for( i = 0; i < lpDiaf->dwNumActions; i++ )
  207.     {
  208.         m_lpCalloutManager->SetActionMap( &( lpDiaf->rgoAction[i] ), 
  209.                                           lpDiaf->rgoAction[i].dwObjID );
  210.     }
  211.  
  212.     // if we build custom views
  213.     if( m_lpCustomViewInfo )
  214.     {
  215.         // determine if views can be compacted
  216.         m_bCanBeCollapsed = m_lpCalloutManager->CalcCanBeCollapsed();
  217.  
  218.         // keep copy of the action map
  219.         if( m_bCanBeCollapsed )
  220.             if( FALSE == CopyActionMap( lpDiaf ) )
  221.                 return DIERR_OUTOFMEMORY;
  222.     }
  223.  
  224.     return S_OK;
  225. }
  226.  
  227.  
  228.  
  229.  
  230. //-----------------------------------------------------------------------------
  231. // Name: RebuildViews()
  232. // Desc: collapses or exands the views
  233. //-----------------------------------------------------------------------------
  234. HRESULT DIDCfgView::RebuildViews( BOOL bCompact )
  235. {
  236.     UINT i;
  237.     INT  iNumViews;
  238.  
  239.     // make sure this has been properly initialized
  240.     if( FALSE == m_bIsInit )
  241.         return DIERR_NOTINITIALIZED;
  242.  
  243.     if( NULL == m_lpDiaf )
  244.         return DIERR_NOTINITIALIZED;
  245.  
  246.     if( FALSE == m_bCanBeCollapsed )
  247.         return DIERR_INVALIDPARAM;
  248.  
  249.     // build the custom views, expand or compact
  250.     InitCustomViews( m_lpDIDevice, bCompact );
  251.  
  252.     // set the action map
  253.     for( i = 0; i < m_lpDiaf->dwNumActions; i++ )
  254.     {
  255.         m_lpCalloutManager->SetActionMap( &( m_lpDiaf->rgoAction[i] ), 
  256.                                           m_lpDiaf->rgoAction[i].dwObjID );
  257.     }
  258.  
  259.     // get the new number of views;
  260.     iNumViews = m_lpViewManager->GetNumViews();
  261.  
  262.     // bound the current view id
  263.     if( iNumViews == 0 )
  264.         m_nView = DIDCV_INVALID_ID;
  265.  
  266.     if( m_nView >= iNumViews )
  267.         m_nView  = iNumViews - 1;
  268.  
  269.     // keep track of whether the views are compact or not
  270.     m_bIsCollapsed = bCompact;
  271.  
  272.     return S_OK;
  273. }
  274.  
  275.  
  276.  
  277.  
  278. //-----------------------------------------------------------------------------
  279. // Name: SetCalloutState()
  280. // Desc: sets the state for a given callout.  the flags are:
  281. //
  282. //       DIDCV_DRAWCALLOUT - draws the callout
  283. //       DIDCV_DRAWOVERLAY - draws the overlay
  284. //       DIDCV_DRAWHIGHLIGHT - draws highlight
  285. //       DIDCV_DRAWEMPTYCALLOUT - draws the callout even if an action mapping
  286. //          is not present
  287. //       DIDCV_DRAWFULLNAME - draws the full name of action, if the
  288. //          callout clips part of the string
  289. //
  290. //       the dwFlags argument should be a bitwise AND of none, any, or all of
  291. //       the values.
  292. //-----------------------------------------------------------------------------
  293. HRESULT DIDCfgView::SetCalloutState( DWORD dwFlags, DWORD dwObjID )
  294. {
  295.     DidcvCalloutState calloutState;
  296.     BOOL bResult;
  297.     
  298.     // make sure this object has been properly initialized
  299.     if( FALSE == m_bIsInit )
  300.         return DIERR_NOTINITIALIZED;
  301.  
  302.     // set the state structure to match the dword
  303.     calloutState.SetFlag( dwFlags );
  304.  
  305.     // set the state for the object id( if exist )
  306.     bResult = m_lpCalloutManager->SetCalloutState( &calloutState, dwObjID );
  307.  
  308.     // could be an invalid object id
  309.     if( FALSE == bResult )
  310.         return DIERR_INVALIDPARAM;
  311.  
  312.     return DI_OK;
  313. }
  314.  
  315.  
  316.  
  317.  
  318. //-----------------------------------------------------------------------------
  319. // Name: SetAllCalloutState()
  320. // Desc: sets the state for all callouts.  see SetCalloutState for flag value
  321. //-----------------------------------------------------------------------------
  322. HRESULT DIDCfgView::SetAllCalloutState( DWORD dwFlags )
  323. {
  324.     DidcvCalloutState calloutState;
  325.     BOOL bResult;
  326.     
  327.     // make sure this object has been properly initialized
  328.     if( FALSE == m_bIsInit )
  329.         return DIERR_NOTINITIALIZED;
  330.  
  331.     // set the state structure to match the dword
  332.     calloutState.SetFlag( dwFlags );
  333.  
  334.     // set the state for the object id( if exist )
  335.     bResult = m_lpCalloutManager->SetAllCalloutState( &calloutState );
  336.  
  337.     // could be an invalid object id
  338.     if( FALSE == bResult )
  339.         return DIERR_INVALIDPARAM;
  340.  
  341.     return DI_OK;
  342. }
  343.  
  344.  
  345.  
  346.  
  347. //-----------------------------------------------------------------------------
  348. // Name: GetCalloutState()
  349. // Desc: returns the state for a given callout.  see SetCalloutState comments
  350. //       for explanation of the flags values
  351. //-----------------------------------------------------------------------------
  352. HRESULT DIDCfgView::GetCalloutState( LPDWORD lpdwFlags, DWORD dwObjID )
  353. {
  354.     DidcvCalloutState calloutState;
  355.     BOOL bResult;
  356.  
  357.     // make sure this object has been properly initialized
  358.     if( FALSE == m_bIsInit )
  359.         return DIERR_NOTINITIALIZED;
  360.  
  361.     // sanity check
  362.     if( NULL == lpdwFlags )
  363.         return DIERR_INVALIDPARAM;
  364.  
  365.     // retrieve callout state from the callout manager
  366.     bResult = m_lpCalloutManager->GetCalloutState( &calloutState, dwObjID );
  367.  
  368.     // did not find state info
  369.     if( FALSE == bResult )
  370.         return DIERR_INVALIDPARAM;
  371.  
  372.     // construct flag from the state
  373.     *lpdwFlags = calloutState.MakeFlag();
  374.  
  375.     return DI_OK;
  376. }
  377.  
  378.  
  379.  
  380.  
  381. //-----------------------------------------------------------------------------
  382. // Name: GetObjectIDByLocation()
  383. // Desc: for a given point in image coordinate, returns a callout with which
  384. //       the point intersects.  if not found, the functions return success,
  385. //       and the return argument will be set to NULL.
  386. //-----------------------------------------------------------------------------
  387. HRESULT DIDCfgView::GetObjectIDByLocation( LPDWORD lpdwObjID, LPPOINT pPt )
  388. {
  389.     POINT ptTransform;
  390.  
  391.     // make sure this object has been properly initialized
  392.     if( FALSE == m_bIsInit )
  393.         return DIERR_NOTINITIALIZED;
  394.  
  395.     // sanity check
  396.     if( NULL == lpdwObjID )
  397.         return DIERR_INVALIDPARAM;
  398.  
  399.     // transform by new origin
  400.     ptTransform.x = pPt->x - m_ptOrigin.x;
  401.     ptTransform.y = pPt->y - m_ptOrigin.y;
  402.  
  403.     // pass pt into the callout manager with the current view for hit test
  404.     *lpdwObjID = m_lpCalloutManager->GetObjectIDByLocation( &ptTransform, m_nView );
  405.  
  406.     return DI_OK;
  407. }
  408.  
  409.  
  410.  
  411.  
  412. //-----------------------------------------------------------------------------
  413. // Name: SetCurrentView()
  414. // Desc: set the current view for the DIDCfgView object.  all further
  415. //       operations will be done in the context of this new view.
  416. //-----------------------------------------------------------------------------
  417. HRESULT DIDCfgView::SetCurrentView( INT nView )
  418. {
  419.     // make sure this object has been properly initialized
  420.     if( FALSE == m_bIsInit )
  421.         return DIERR_NOTINITIALIZED;
  422.  
  423.     // sanity check
  424.     if( nView < 0 || nView >=( INT ) m_lpViewManager->GetNumViews() )
  425.         return DIERR_INVALIDPARAM;
  426.  
  427.     // set the view
  428.     m_nView = nView;
  429.  
  430.     return DI_OK;
  431. }
  432.  
  433.  
  434.  
  435.  
  436. //-----------------------------------------------------------------------------
  437. // Name: GetCurrentView()
  438. // Desc: returns the current view identifier
  439. //-----------------------------------------------------------------------------
  440. HRESULT DIDCfgView::GetCurrentView( LPINT lpnView  )
  441. {
  442.     // make sure this object has been properly initialized
  443.     if( FALSE == m_bIsInit )
  444.         return DIERR_NOTINITIALIZED;
  445.  
  446.     // sanity check
  447.     if( NULL == lpnView )
  448.         return DIERR_INVALIDPARAM;
  449.  
  450.     // copy the view
  451.     *lpnView = m_nView;
  452.  
  453.     return DI_OK;
  454. }
  455.  
  456.  
  457.  
  458.  
  459. //-----------------------------------------------------------------------------
  460. // Name: GetInfo()
  461. // Desc: retrieves information from DIDCfgView
  462. //-----------------------------------------------------------------------------
  463. HRESULT DIDCfgView::GetInfo( DIDCfgViewInfo* pCfgViewInfo )
  464. {
  465.     // sanity checks
  466.     if( NULL == pCfgViewInfo )
  467.         return DIERR_INVALIDPARAM;
  468.  
  469.     ZeroMemory( pCfgViewInfo, sizeof( DIDCfgViewInfo ) );
  470.  
  471.     // always return whether the Config Viewer is initialized or not
  472.     pCfgViewInfo->bIsInit = m_bIsInit;
  473.  
  474.     // make sure this object has been properly initialized
  475.     if( FALSE == m_bIsInit )
  476.         return DIERR_NOTINITIALIZED;
  477.  
  478.     // set the information to be returned
  479.     pCfgViewInfo->iCurrentViewID = m_nView;
  480.     pCfgViewInfo->iNumTotalViews =( INT )m_lpViewManager->GetNumViews();
  481.     pCfgViewInfo->dwNumUniqueCallouts = m_lpCalloutManager->GetNumUniqueCallouts();
  482.     pCfgViewInfo->bCanBeCollapsed = m_bCanBeCollapsed;
  483.     pCfgViewInfo->bIsCollapsed = m_bIsCollapsed;
  484.  
  485.     return DI_OK;
  486. }
  487.  
  488.  
  489.  
  490.  
  491. //-----------------------------------------------------------------------------
  492. // Name: SetColors()
  493. // Desc: sets the foreground( text ) color, background and highlight color,
  494. //       the highlighted callout color
  495. //-----------------------------------------------------------------------------
  496. VOID DIDCfgView::SetColors( COLORREF crFore, COLORREF crBack, 
  497.                             COLORREF crHighlight, COLORREF crHighlightLine )
  498. {
  499.     m_crFore = crFore;
  500.     m_crBack = crBack;
  501.     m_crHighlight = crHighlight;
  502.     m_crHighlightLine = crHighlightLine;
  503. }
  504.  
  505.  
  506.  
  507.  
  508. //-----------------------------------------------------------------------------
  509. // Name: GetColor()
  510. // Desc: returns the colors currently being using in rendering
  511. //-----------------------------------------------------------------------------
  512. VOID DIDCfgView::GetColors( COLORREF* pCrFore, COLORREF* pCrBack, 
  513.                             COLORREF* pCrHighlight, COLORREF* pCrHighlightLine )
  514. {
  515.     if( pCrFore ) *pCrFore = m_crFore;
  516.     if( pCrBack ) *pCrBack = m_crBack;
  517.     if( pCrHighlight ) *pCrHighlight = m_crHighlight;
  518.     if( pCrHighlightLine ) *pCrHighlightLine = m_crHighlightLine;
  519. }
  520.  
  521.  
  522.  
  523.  
  524. //-----------------------------------------------------------------------------
  525. // Name: SetFont()
  526. // Desc: sets the font used to draw the text
  527. //-----------------------------------------------------------------------------
  528. HRESULT DIDCfgView::SetFont( const TCHAR* pctszFontName, DWORD dwAttribs )
  529. {
  530.     HDC hDCMem;
  531.     HFONT hFont;
  532.     HRESULT hr = DI_OK;
  533.  
  534.     if( NULL == pctszFontName )
  535.     {
  536.         if( m_hFont )
  537.             DeleteObject( m_hFont );
  538.     }
  539.     else
  540.     {
  541.         // create a memory device context
  542.         hDCMem = CreateCompatibleDC( NULL );
  543.  
  544.         // create font
  545.         hFont = DidcvCreateFont( hDCMem, pctszFontName, DIDCV_DEFAULT_FONT_SIZE, 
  546.                                  0, dwAttribs, FALSE );
  547.  
  548.         if( NULL == hFont )
  549.             hr = DIERR_INVALIDPARAM;
  550.         else
  551.         {
  552.             if( m_hFont )
  553.                 DeleteObject( m_hFont );
  554.  
  555.             m_hFont = hFont;
  556.         }
  557.  
  558.         // clean up
  559.         DeleteDC( hDCMem );
  560.     }
  561.  
  562.     return hr;
  563. }
  564.  
  565.  
  566.  
  567.  
  568. //-----------------------------------------------------------------------------
  569. // Name: GetFont()
  570. // Desc: sets the font used to draw the text
  571. //-----------------------------------------------------------------------------
  572. HFONT   DIDCfgView::GetFont()
  573. {
  574.     return m_hFont;
  575. }
  576.  
  577.  
  578.  
  579.  
  580. //-----------------------------------------------------------------------------
  581. // Name: SetViewOrigin
  582. // Desc: tells DIDCfgView where to start drawing and performing hit tests
  583. //       on the surface being rendered on
  584. //-----------------------------------------------------------------------------
  585. HRESULT DIDCfgView::SetViewOrigin( const POINT* pPtOrg, POINT* pPtOldOrg )
  586. {
  587.     if( NULL == pPtOrg )
  588.         return DIERR_INVALIDPARAM;
  589.  
  590.     // return the current origin
  591.     if( pPtOldOrg )
  592.     {
  593.         pPtOldOrg->x = m_ptOrigin.x;
  594.         pPtOldOrg->y = m_ptOrigin.y;
  595.     }
  596.  
  597.     // set the current origin to new origin
  598.     m_ptOrigin.x = pPtOrg->x;
  599.     m_ptOrigin.y = pPtOrg->y;
  600.  
  601.     return DI_OK;
  602. }
  603.  
  604.  
  605.  
  606.  
  607. //-----------------------------------------------------------------------------
  608. // Name: CalcCenterOrgForCurrentView()
  609. // Desc: calculate the coordinate where to set the origin, in order for the
  610. //       current view to be centered on the drawing surface, lpImgSize should
  611. //       contain the dimensions of the drawing surface.  if the view is
  612. //       larger than the drawing area, then( 0, 0 ) will be returned
  613. //-----------------------------------------------------------------------------
  614. HRESULT DIDCfgView::CalcCenterOrgForCurrentView( const SIZE* pSurfaceSize, 
  615.                                                  POINT* pCenterOrg, BOOL bSetOrigin )
  616. {
  617.     if( FALSE == m_bIsInit )
  618.         return DIERR_NOTINITIALIZED;
  619.  
  620.     // sanity check
  621.     if( NULL == pSurfaceSize || NULL == pCenterOrg )
  622.         return DIERR_INVALIDPARAM;
  623.  
  624.     INT x = 0, y = 0;
  625.     DidcvView* pView;
  626.     SIZE imgSize;
  627.  
  628.     // get the current view
  629.     pView = m_lpViewManager->GetImage( m_nView );
  630.  
  631.     // get the size and find the coordinate at which to center the image
  632.     // note that x == 0 and y == 0 if surface width and height
  633.     // is not as big as the image width and height, respectively
  634.     if( pView && pView->GetViewSize( &imgSize ) )
  635.     {
  636.         if( imgSize.cx < pSurfaceSize->cx )
  637.             x =( pSurfaceSize->cx - imgSize.cx ) / 2;
  638.         if( imgSize.cy < pSurfaceSize->cy )
  639.             y =( pSurfaceSize->cy - imgSize.cy ) / 2;
  640.     }
  641.  
  642.     // set the values to be returns
  643.     pCenterOrg->x = x;
  644.     pCenterOrg->y = y;
  645.  
  646.     // if bSetOrigin is TRUE, then set the view origin for this object
  647.     if( bSetOrigin )
  648.         SetViewOrigin( pCenterOrg, NULL );
  649.  
  650.     return S_OK;
  651. }
  652.  
  653.  
  654.  
  655.  
  656. //-----------------------------------------------------------------------------
  657. // Name: SetDefaultText()
  658. // Desc: sets the default text for callouts that doesn't have action mapped
  659. //-----------------------------------------------------------------------------
  660. VOID DIDCfgView::SetDefaultText( const TCHAR* pctszDefaultText, DWORD length )
  661. {
  662.     // copy up to MAX_PATH characters
  663.     size_t numToCopy =( length < MAX_PATH ? length : MAX_PATH );
  664.     _tcsncpy( m_tszDefaultText, pctszDefaultText, numToCopy );
  665.  
  666.     // if we copied MAX_PATH, make sure it is NULL terminated
  667.     if( numToCopy == MAX_PATH )
  668.         m_tszDefaultText [MAX_PATH - 1] = 0;
  669. }
  670.  
  671.  
  672.  
  673.  
  674. //-----------------------------------------------------------------------------
  675. // Name: RenderView()
  676. // Desc: draws the configuration view to HBITMAP, a DDB or a DIB
  677. //-----------------------------------------------------------------------------
  678. HRESULT DIDCfgView::RenderView( HBITMAP hBitmap, BOOL bIsDib )
  679. {
  680.     HDC hDCMem;
  681.     HGDIOBJ hOldBitmap;
  682.     DIBSECTION dibs;
  683.     HRESULT hr;
  684.  
  685.     // make sure this object has been properly initialized
  686.     if( FALSE == m_bIsInit )
  687.         return DIERR_NOTINITIALIZED;
  688.  
  689.     // sanity check
  690.     if( NULL == hBitmap )
  691.         return DIERR_INVALIDPARAM;
  692.  
  693.     // create a memory DC compatible with the current display
  694.     hDCMem = CreateCompatibleDC( NULL );
  695.     // select the surface to drawn on into the HDC
  696.     hOldBitmap = SelectObject( hDCMem, hBitmap );
  697.  
  698.     // render, passing in as much data as we can safely acquire
  699.     if( bIsDib && GetObject( hBitmap, sizeof( DIBSECTION ), &dibs ) )
  700.         hr = RenderView( hDCMem, dibs.dsBm.bmBits, dibs.dsBm.bmWidth, dibs.dsBm.bmHeight );
  701.     else
  702.         hr = RenderView( hDCMem );
  703.  
  704.     // clean up
  705.     SelectObject( hDCMem, hOldBitmap );
  706.     DeleteDC( hDCMem );
  707.  
  708.     return hr;
  709. }
  710.  
  711.  
  712.  
  713.  
  714. //-----------------------------------------------------------------------------
  715. // Name: RenderView()
  716. // Desc: draws the configuration view to an HDC
  717. //-----------------------------------------------------------------------------
  718. HRESULT DIDCfgView::RenderView( HDC hdc )
  719. {
  720.     return RenderView( hdc, NULL, 0, 0 );
  721. }
  722.  
  723.  
  724.  
  725.  
  726. //-----------------------------------------------------------------------------
  727. // Name: RenderView()
  728. // Desc: draws the configuration view to an HDC
  729. //-----------------------------------------------------------------------------
  730. HRESULT DIDCfgView::RenderView( HDC hdc, VOID* pBits, INT width, INT height )
  731. {
  732.     DidcvView* pView;
  733.     const DidcvCalloutSet* pSet;
  734.     int iDCStackNum;
  735.     
  736.     // make sure this object has been properly initialized
  737.     if( FALSE == m_bIsInit )
  738.         return DIERR_NOTINITIALIZED;
  739.  
  740.     if( NULL == hdc )
  741.         return DIERR_INVALIDPARAM;
  742.  
  743.     pView = m_lpViewManager->GetImage( m_nView );
  744.     
  745.     // no valid view set
  746.     if( NULL == pView )
  747.         return DIERR_NOTINITIALIZED;
  748.  
  749.  
  750.     // set rendering options for HDC
  751.     HBRUSH hBkBrush = CreateSolidBrush( m_crHighlight );
  752.     HPEN hLinePen = CreatePen( PS_SOLID, 0, m_crFore );
  753.     HPEN hHighlightPen = CreatePen( PS_SOLID, 0, m_crHighlight );
  754.     HPEN hHighlightLinePen = CreatePen( PS_SOLID, 0, m_crHighlightLine );
  755.  
  756.     // save the state of the DC on the context stack
  757.     iDCStackNum = SaveDC( hdc );
  758.  
  759.     // select the new highlight background color brush
  760.     SelectObject( hdc, hBkBrush );
  761.     // select the callout line color
  762.     SelectObject( hdc, hLinePen );
  763.     // set text color
  764.     SetTextColor( hdc, m_crFore );
  765.     // set background color
  766.     SetBkColor( hdc, m_crBack );
  767.     // shift the origin
  768.     SetViewportOrgEx( hdc, m_ptOrigin.x, m_ptOrigin.y, NULL );
  769.     // the bk mode for drawing text
  770.     SetBkMode( hdc, TRANSPARENT );
  771.  
  772.     // draw the current view
  773.     pView->Render( hdc, pBits, width, height, &m_ptOrigin );
  774.  
  775.     // get the set of callouts associated with the current view
  776.     pSet = m_lpCalloutManager->GetCalloutSetByView( m_nView );
  777.  
  778.     if( pSet )
  779.     {
  780.         // Get the list of callout in the set.
  781.         // A callout is the line drawn from each axis/button to a label
  782.         const GwArray <DidcvCallout *> & arr = pSet->GetInternalArrayRef();
  783.         const DidcvCalloutData* pData;
  784.  
  785.         UINT i;
  786.         BOOL bCalloutEmpty;
  787.         DWORD dwNumPts = 0;
  788.         const POINT* lpPts;
  789.         TCHAR szBuffer[MAX_PATH];
  790.         TCHAR szCopy[MAX_PATH];
  791.         DidcvActionMap* lpActionMap;
  792.         DWORD dwTextFlags, dwTextAlign;
  793.  
  794.         if( m_hFont )
  795.         {
  796.             // set the font
  797.             SelectObject( hdc, m_hFont );
  798.         }
  799.  
  800.         // for each callout (the line drawn from each axis/button to a label)
  801.         for( i = 0; i < arr.Size(); i++ )
  802.         {
  803.             // the data associated
  804.             pData = arr[i]->GetDataRef();
  805.             const RECT* rect = &( arr[i]->GetCalloutRect() );
  806.  
  807.             // get the action map, if one exists
  808.             lpActionMap = pData->lpActionMap;
  809.             if( lpActionMap && lpActionMap->dia.lptszActionName )
  810.                 bCalloutEmpty = FALSE;
  811.             else
  812.                 bCalloutEmpty = TRUE;
  813.  
  814.             // draw the callout for the control
  815.             if( !bCalloutEmpty || pData->lpState->bDrawEmptyCallout )
  816.             {
  817.                 // draw the highlight first
  818.                 if( pData->lpState->bDrawHighlight )
  819.                 {
  820.                     // draw the highlight
  821.                     SelectObject( hdc, hHighlightPen );
  822.                     Rectangle( hdc, rect->left, rect->top, rect->right, rect->bottom );
  823.  
  824.                     // set pen to highlight line
  825.                     SelectObject( hdc, hHighlightLinePen );
  826.  
  827.                     // set back ground color to highlight color
  828.                     SetBkColor( hdc, m_crHighlight );
  829.  
  830.                     // set the text color to highlightline color
  831.                     // SetTextColor( hdc, m_crHighlightLine );
  832.                 }
  833.  
  834.                 // draw the overlay image
  835.                 if( pData->lpState->bDrawOverlay )
  836.                 {
  837.                     arr[i]->DrawOverlay( hdc, pBits, width, height, &m_ptOrigin );
  838.                 }
  839.  
  840.                 // draw the callout line and text
  841.                 if( pData->lpState->bDrawCallout )
  842.                 {
  843.                     // draw the callout line
  844.                     lpPts = arr[i]->GetCalloutLine( &dwNumPts );
  845.                     DidcvPolyLineArrow( hdc, lpPts,( INT ) dwNumPts, FALSE );
  846.  
  847.                     // set the draw text options
  848.                     dwTextFlags = DT_WORDBREAK | DT_NOPREFIX | DT_END_ELLIPSIS 
  849.                                 | DT_EDITCONTROL | DT_MODIFYSTRING;
  850.  
  851.                     if( !bCalloutEmpty )
  852.                     {
  853.                         // copy the text
  854.                         _tcscpy( szBuffer, lpActionMap->dia.lptszActionName );
  855.  
  856.                         // reset the text flags
  857.                         dwTextAlign = arr[i]->GetTextAlign();
  858.  
  859.                         // check horizontal alignment
  860.                         if( dwTextAlign & DIDAL_LEFTALIGNED )
  861.                             dwTextFlags |= DT_LEFT;
  862.                         else if( dwTextAlign & DIDAL_RIGHTALIGNED )
  863.                             dwTextFlags |= DT_RIGHT;
  864.                         else //( dwTextAlign & DIDAL_CENTERED )
  865.                             dwTextFlags |= DT_CENTER;
  866.  
  867.                         // check vertical alignment
  868.                         if( dwTextAlign & DIDAL_TOPALIGNED )
  869.                             dwTextFlags |= DT_TOP;
  870.                         else if( dwTextAlign & DIDAL_BOTTOMALIGNED )
  871.                             dwTextFlags |= DT_SINGLELINE | DT_BOTTOM;
  872.                         else //( dwTextAlign & DIDAL_MIDDLE )
  873.                             dwTextFlags |= DT_SINGLELINE | DT_VCENTER;
  874.  
  875.                     }
  876.                     else
  877.                     {
  878.                         // copy and draw the default text
  879.                         _tcscpy( szBuffer, m_tszDefaultText );
  880.                         dwTextFlags |= DT_VCENTER | DT_SINGLELINE;
  881.                     }
  882.  
  883.                     // make a copy
  884.                     _tcscpy( szCopy, szBuffer );
  885.  
  886.                     // draw the text
  887.                     DrawText( hdc, szCopy, -1,( LPRECT ) rect, dwTextFlags );
  888.  
  889.                     // rendered string truncated
  890.                     if( pData->lpState->bDrawFullname && _tcscmp( szCopy, szBuffer ) )
  891.                     {
  892.                         RenderFullname( hdc, szBuffer, rect );
  893.                     }
  894.  
  895.                     if( pData->lpState->bDrawHighlight )
  896.                     {
  897.                         // reset the pen
  898.                         SelectObject( hdc, hLinePen );
  899.  
  900.                         // reset the back ground color
  901.                         SetBkColor( hdc, m_crBack );
  902.  
  903.                         // reset the text color
  904.                         // SetTextColor( hdc, m_crFore );
  905.                     }
  906.                 }
  907.             }
  908.         }
  909.     }
  910.  
  911.     // restore DC state
  912.     RestoreDC( hdc, iDCStackNum );
  913.  
  914.     // clean up
  915.     DeleteObject( hBkBrush );
  916.     DeleteObject( hLinePen );
  917.     DeleteObject( hHighlightPen );
  918.     DeleteObject( hHighlightLinePen );
  919.  
  920.     return S_OK;
  921. }
  922.  
  923.  
  924.  
  925.  
  926. //-----------------------------------------------------------------------------
  927. // Name: RenderFullname()
  928. // Desc: renders a box with the full name inside
  929. //-----------------------------------------------------------------------------
  930. VOID DIDCfgView::RenderFullname( HDC hdc, const TCHAR* pctszFullname, 
  931.                                  const RECT* pCalloutRect )
  932. {
  933.     HFONT hFont, hOldFont;
  934.     HBRUSH hBrush, hOldBrush;
  935.     COLORREF crOldTextColor;
  936.     TEXTMETRIC tm;
  937.     RECT rect;
  938.     DWORD dwTextFlags;
  939.     int len, width, height;
  940.  
  941.     // check the length
  942.     len = _tcslen( pctszFullname );
  943.     if( 0 == len )
  944.         return;
  945.  
  946.     // create the font to use in the box to display the full name
  947.     // we hard-code Courier to ensure we have a fix-width font
  948.     hFont = DidcvCreateFont( hdc, TEXT( "Courier" ), 
  949.                              DIDCV_DEFAULT_FONT_SIZE, 0, 0, FALSE );
  950.  
  951.     // use the foreground color as the background
  952.     hBrush = CreateSolidBrush( m_crFore );
  953.     // and vice versa
  954.     crOldTextColor = SetTextColor( hdc, m_crBack );
  955.  
  956.     hOldFont =( HFONT ) SelectObject( hdc, hFont );
  957.     hOldBrush =( HBRUSH ) SelectObject( hdc, hBrush );
  958.  
  959.     // get the width and height of the text
  960.     GetTextMetrics( hdc, &tm );
  961.     width = tm.tmAveCharWidth * len + 8;
  962.     height = tm.tmHeight + tm.tmExternalLeading + 4;
  963.  
  964.     // for now draw over the callout rect
  965.     rect.left = pCalloutRect->left;
  966.     rect.top = pCalloutRect->top;
  967.     rect.right = rect.left + width;
  968.     rect.bottom = pCalloutRect->bottom;
  969.  
  970.     // draw the rectangle
  971.     Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
  972.  
  973.     // draw the text
  974.     dwTextFlags = DT_NOPREFIX | DT_EDITCONTROL | DT_CENTER | 
  975.                   DT_VCENTER | DT_SINGLELINE;
  976.     DrawText( hdc, pctszFullname, -1, &rect, dwTextFlags );
  977.  
  978.     // restore HDC objects
  979.     SelectObject( hdc, hOldFont );
  980.     SelectObject( hdc, hOldBrush );
  981.     SetTextColor( hdc, crOldTextColor );
  982.  
  983.     // clean up
  984.     DeleteObject( hFont );
  985.     DeleteObject( hBrush );
  986. }
  987.  
  988.  
  989.  
  990.  
  991. //-----------------------------------------------------------------------------
  992. // Name: InitAlloc()
  993. // Desc: helper function to dynamically allocate memory for internal data
  994. //       structures.
  995. //-----------------------------------------------------------------------------
  996. HRESULT DIDCfgView::InitAlloc()
  997. {
  998.     // allocate a view manager, callout manager
  999.     m_lpViewManager = new DidcvViewManager;
  1000.     m_lpCalloutManager = new DidcvCalloutManager;
  1001.  
  1002.     // ensure that memory has been allocated
  1003.     if( NULL == m_lpViewManager || NULL == m_lpCalloutManager )
  1004.     {
  1005.         CleanUp();
  1006.         return DIERR_OUTOFMEMORY;
  1007.     }
  1008.  
  1009.     return S_OK;
  1010. }
  1011.  
  1012.  
  1013.  
  1014.  
  1015. //-----------------------------------------------------------------------------
  1016. // Name: InitImageInfoRetrieve()
  1017. // Desc: helper function to retrieve callout / image data from
  1018. //       DirectInput
  1019. //-----------------------------------------------------------------------------
  1020. HRESULT DIDCfgView::InitImageInfoRetrieve( LPDIRECTINPUTDEVICE8 lpDidev )
  1021. {
  1022.     HRESULT hr;
  1023.  
  1024.     // allocate a DIDEVICEIMAGEINFOHEADER
  1025.     m_lpDidImgHeader = new DIDEVICEIMAGEINFOHEADER;
  1026.  
  1027.     // make sure memory has been allocated
  1028.     if( NULL == m_lpDidImgHeader )
  1029.     {
  1030.         return DIERR_OUTOFMEMORY;
  1031.     }
  1032.  
  1033.     // zero out the DIDEVICEIMAGEINFOHEADER
  1034.     ZeroMemory( m_lpDidImgHeader, sizeof( DIDEVICEIMAGEINFOHEADER ) );
  1035.  
  1036.     // properly initialize the structure before it can be used
  1037.     m_lpDidImgHeader->dwSize = sizeof( DIDEVICEIMAGEINFOHEADER );
  1038.     m_lpDidImgHeader->dwSizeImageInfo = sizeof( DIDEVICEIMAGEINFO );
  1039.  
  1040.     // since m_lpDidImgHeader->dwBufferSize is 0, this call serves to determine
  1041.     // the minimum buffer size required to hold information for all the images
  1042.     hr = lpDidev->GetImageInfo( m_lpDidImgHeader );
  1043.     if( FAILED( hr ) )
  1044.     {
  1045.         return DIERR_INVALIDPARAM; 
  1046.     }
  1047.  
  1048.     // at this point, m_lpDidImgHeader->dwBufferUsed has been set by
  1049.     // the GetImageInfo method to minimum buffer size needed, so allocate.
  1050.     m_lpDidImgHeader->dwBufferSize = m_lpDidImgHeader->dwBufferUsed;
  1051.     m_lpDidImgHeader->lprgImageInfoArray = new DIDEVICEIMAGEINFO[ m_lpDidImgHeader->dwBufferSize / 
  1052.                                                                   sizeof( DIDEVICEIMAGEINFO ) ];
  1053.  
  1054.     // make sure memory has been allocated
  1055.     if( m_lpDidImgHeader->lprgImageInfoArray == NULL )
  1056.     {
  1057.         return DIERR_OUTOFMEMORY;
  1058.     }
  1059.  
  1060.     // now that the dwBufferSize has been filled, and lprgImageArray allocated,
  1061.     // we call GetImageInfo again to get the image data
  1062.     hr = lpDidev->GetImageInfo( m_lpDidImgHeader );
  1063.     if( FAILED( hr ) )
  1064.     {
  1065.         return DIERR_INVALIDPARAM;
  1066.     }
  1067.  
  1068.     return S_OK;
  1069. }
  1070.  
  1071.  
  1072.  
  1073.  
  1074. //-----------------------------------------------------------------------------
  1075. // Name: InitImageInfoProcess()
  1076. // Desc: helper function to process the image/callout information to
  1077. //       get them ready to be used.
  1078. //-----------------------------------------------------------------------------
  1079. HRESULT DIDCfgView::InitImageInfoProcess()
  1080. {
  1081.     DWORD num_elements, i;
  1082.     DidcvView* pView = NULL;
  1083.     BOOL bLoadComplete = TRUE;
  1084.     DidcvCallout* pCallout = NULL;
  1085.     DWORD dwNumViews, dwNumCallouts, dwNumUniqueObjIDs;
  1086.  
  1087.     // a pre-condition of this method is that m_lpDidImgHeader != NULL
  1088.     assert( m_lpDidImgHeader != NULL );
  1089.  
  1090.     // calcuate the number of elements in the image info array
  1091.     num_elements = m_lpDidImgHeader->dwBufferUsed / m_lpDidImgHeader->dwSizeImageInfo;
  1092.  
  1093.     // determines sizes ahead of time
  1094.     CalcSizes( m_lpDidImgHeader->lprgImageInfoArray, num_elements, &dwNumViews, 
  1095.                &dwNumCallouts, &dwNumUniqueObjIDs );
  1096.  
  1097.     // set the capacity of the managers ahead of time
  1098.     m_lpViewManager->SetCapacity( dwNumViews );
  1099.     m_lpCalloutManager->SetCapacity( dwNumCallouts, dwNumUniqueObjIDs, dwNumViews );
  1100.  
  1101.     // first pass to process all configuration image, in order
  1102.     for( i = 0; i < num_elements; i++ )
  1103.     {
  1104.         // check to see if the element is a configuration image
  1105.         if( m_lpDidImgHeader->lprgImageInfoArray[i].dwFlags & DIDIFT_CONFIGURATION )
  1106.         {
  1107.             pView = DidcvBitmapView::Create( m_lpDidImgHeader->lprgImageInfoArray[i].tszImagePath,
  1108.                                              m_lpDidImgHeader->lprgImageInfoArray[i].dwFlags );
  1109.  
  1110.             if( NULL == pView )
  1111.             {
  1112.                 bLoadComplete = FALSE;
  1113.                 continue;
  1114.             }
  1115.             
  1116.             // add new image to the ImageManager, along with the array index, 
  1117.             // which is referred by callout entries
  1118.             m_lpViewManager->AddImage( pView,( INT )i );
  1119.         }
  1120.     }
  1121.  
  1122.     // second pass to process all overlays
  1123.     for( i = 0; i < num_elements; i++ )
  1124.     {
  1125.         // check to see if the element is a control overlay entry
  1126.         if( m_lpDidImgHeader->lprgImageInfoArray[i].dwFlags & DIDIFT_OVERLAY )
  1127.         {
  1128.             pCallout = DidcvCallout::Create( &( m_lpDidImgHeader->lprgImageInfoArray[i] ) );
  1129.  
  1130.             if( NULL == pCallout )
  1131.             {
  1132.                 bLoadComplete = FALSE;
  1133.                 continue;
  1134.             }
  1135.             
  1136.             // try to get the appropriate view, by the offset in the image array
  1137.             pView = m_lpViewManager->GetImageByOffset( m_lpDidImgHeader->lprgImageInfoArray[i].dwViewID );
  1138.  
  1139.             if( NULL == pView )
  1140.             {
  1141.                 bLoadComplete = FALSE;
  1142.                 continue;
  1143.             }
  1144.  
  1145.             // add new image to the ImageManager, along with the array index, 
  1146.             // which is referred by callout entries
  1147.             m_lpCalloutManager->AddCallout( pCallout, pView->GetID() );
  1148.         }
  1149.     }
  1150.  
  1151.     // free unused dynamic memory
  1152.     m_lpCalloutManager->TrimArrays();
  1153.  
  1154.     // appropriate error code for bLoadComplete != TRUE is not returned at this time
  1155.     return S_OK;
  1156. }
  1157.  
  1158.  
  1159.  
  1160.  
  1161. //-----------------------------------------------------------------------------
  1162. // Name: CalcSizes()
  1163. // Desc: helper function to determine the number of views and callouts in
  1164. //       in the image info array.
  1165. //-----------------------------------------------------------------------------
  1166. VOID DIDCfgView::CalcSizes( const DIDEVICEIMAGEINFO* lprgImageInfoArray, 
  1167.                             DWORD dwNumElements, LPDWORD lpNumViews, 
  1168.                             LPDWORD lpNumCallouts, LPDWORD lpNumDistinctObjID )
  1169. {
  1170.     DWORD i, j;
  1171.  
  1172.     // set everything to 0
  1173.     *lpNumViews = *lpNumCallouts = *lpNumDistinctObjID = 0;
  1174.  
  1175.     for( i = 0; i < dwNumElements; i++ )
  1176.     {
  1177.         // figure out how many of each
  1178.         if( lprgImageInfoArray[i].dwFlags & DIDIFT_CONFIGURATION )
  1179.           ( *lpNumViews ) ++;
  1180.         else if( lprgImageInfoArray[i].dwFlags & DIDIFT_OVERLAY )
  1181.         {
  1182.           ( *lpNumCallouts ) ++;
  1183.  
  1184.             // find to see if dwObjID unique so far
  1185.             for( j = 0; j < i; j++ )
  1186.                 if( lprgImageInfoArray[j].dwObjID == lprgImageInfoArray[i].dwObjID )
  1187.                     break;
  1188.  
  1189.             if( j == i ) // current id unique
  1190.               ( *lpNumDistinctObjID )++;
  1191.         }
  1192.     }
  1193. }
  1194.  
  1195.  
  1196.  
  1197.  
  1198. //-----------------------------------------------------------------------------
  1199. // Name: enum DidcvEnumDataType
  1200. // Desc: constants for the dwType member of the DidcvEnumDeviceData
  1201. //-----------------------------------------------------------------------------
  1202. enum DidcvEnumDataType
  1203. {
  1204.     DIDCV_EDT_COUNT = 1,    // count
  1205.     DIDCV_EDT_SAVE  = 2     // save each item
  1206. };
  1207.  
  1208.  
  1209.  
  1210.  
  1211. //-----------------------------------------------------------------------------
  1212. // Name: IsObjectOnExcludeList()
  1213. // Desc: Exclude these objects from the view
  1214. //-----------------------------------------------------------------------------
  1215. BOOL IsObjectOnExcludeList( DWORD dwOfs )
  1216. {
  1217.     if (dwOfs == DIK_PREVTRACK  ||
  1218.         dwOfs == DIK_NEXTTRACK  ||
  1219.         dwOfs == DIK_MUTE       ||
  1220.         dwOfs == DIK_CALCULATOR ||
  1221.         dwOfs == DIK_PLAYPAUSE  ||
  1222.         dwOfs == DIK_MEDIASTOP  ||
  1223.         dwOfs == DIK_VOLUMEDOWN ||
  1224.         dwOfs == DIK_VOLUMEUP   ||
  1225.         dwOfs == DIK_WEBHOME    ||
  1226.         dwOfs == DIK_SLEEP      ||
  1227.         dwOfs == DIK_WEBSEARCH  ||
  1228.         dwOfs == DIK_WEBFAVORITES ||
  1229.         dwOfs == DIK_WEBREFRESH ||
  1230.         dwOfs == DIK_WEBSTOP    ||
  1231.         dwOfs == DIK_WEBFORWARD ||
  1232.         dwOfs == DIK_WEBBACK    ||
  1233.         dwOfs == DIK_MYCOMPUTER ||
  1234.         dwOfs == DIK_MAIL       ||
  1235.         dwOfs == DIK_MEDIASELECT)
  1236.         return TRUE;
  1237.  
  1238.     return FALSE;
  1239. }
  1240.  
  1241.  
  1242.  
  1243.  
  1244. //-----------------------------------------------------------------------------
  1245. // Name: DidcvEnumDeviceObjectsCallback()
  1246. // Desc: enumerates the objects( keys) on an device
  1247. //-----------------------------------------------------------------------------
  1248. BOOL CALLBACK DidcvEnumDeviceObjectsCallback( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef )
  1249. {
  1250.     // get the struct that is passed in
  1251.     DidcvCustomViewInfo* lpData =( DidcvCustomViewInfo* ) pvRef;
  1252.     if( NULL == lpData )
  1253.         return DIENUM_STOP;
  1254.  
  1255.     // Exclude certain keys on advanced keyboards
  1256.     if( IsObjectOnExcludeList( lpddoi->dwOfs ) )
  1257.         return DIENUM_CONTINUE;
  1258.  
  1259.     if( lpData->dwType == DIDCV_EDT_COUNT )
  1260.     {
  1261.         // simply count
  1262.         lpData->dwCount++;
  1263.     }
  1264.     else if( lpData->dwType == DIDCV_EDT_SAVE )
  1265.     {
  1266.         if( lpData->dwSize < lpData->dwCount )
  1267.         {
  1268.             // instantiate new object instance
  1269.             lpData->rgObjData[lpData->dwSize] = new DIDEVICEOBJECTINSTANCE;
  1270.             memcpy( lpData->rgObjData[lpData->dwSize], lpddoi, sizeof( DIDEVICEOBJECTINSTANCE ) );
  1271.             lpData->dwSize++;
  1272.         }
  1273.         else
  1274.         {
  1275.             // this should not happen
  1276.             return DIENUM_STOP;
  1277.         }
  1278.     }
  1279.     else
  1280.         return DIENUM_STOP;
  1281.  
  1282.     return DIENUM_CONTINUE;
  1283. }
  1284.  
  1285.  
  1286.  
  1287.  
  1288. //-----------------------------------------------------------------------------
  1289. // Name: InitCustomViews()
  1290. // Desc: initializes custom views by retrieving device data, and calling
  1291. //       ConstructCustomView() to make views using bitmap images for
  1292. //       the device controls 
  1293. //-----------------------------------------------------------------------------
  1294. HRESULT DIDCfgView::InitCustomViews( LPDIRECTINPUTDEVICE8 lpDevice, BOOL bUseInternal )
  1295. {
  1296.     HRESULT hr;
  1297.  
  1298.     // reset the info
  1299.     if( m_lpCustomViewInfo )
  1300.         m_lpCustomViewInfo->CleanUp();
  1301.     else
  1302.     {
  1303.         m_lpCustomViewInfo = new DidcvCustomViewInfo;
  1304.         if( NULL == m_lpCustomViewInfo )
  1305.             return DIERR_OUTOFMEMORY;
  1306.     }
  1307.  
  1308.     // get a count of how many controls there are
  1309.     m_lpCustomViewInfo->dwType = DIDCV_EDT_COUNT;
  1310.  
  1311.     if( bUseInternal )
  1312.     {
  1313.         if( m_lpCalloutManager == NULL )
  1314.             return DIERR_INVALIDPARAM;
  1315.  
  1316.         // count internal objects that have action mapping
  1317.         m_lpCalloutManager->EnumObjects( lpDevice, DidcvEnumDeviceObjectsCallback, 
  1318.                                          m_lpCustomViewInfo, TRUE );
  1319.     }
  1320.     else
  1321.     {
  1322.         // count from device
  1323.         lpDevice->EnumObjects( DidcvEnumDeviceObjectsCallback, m_lpCustomViewInfo, DIDFT_ALL );
  1324.     }
  1325.  
  1326.     if( m_lpCustomViewInfo->dwCount == 0 )
  1327.     {
  1328.         m_lpCustomViewInfo->CleanUp();
  1329.         return DIERR_INVALIDPARAM;
  1330.     }
  1331.  
  1332.     // do a second time to get the objects
  1333.     m_lpCustomViewInfo->dwType = DIDCV_EDT_SAVE;
  1334.     m_lpCustomViewInfo->rgObjData = new LPDIDEVICEOBJECTINSTANCE[m_lpCustomViewInfo->dwCount];
  1335.     if( NULL == m_lpCustomViewInfo->rgObjData )
  1336.     {
  1337.         m_lpCustomViewInfo->CleanUp();
  1338.         return DIERR_OUTOFMEMORY;
  1339.     }
  1340.  
  1341.     if( bUseInternal )
  1342.     {
  1343.         if( m_lpCalloutManager == NULL )
  1344.             return DIERR_INVALIDPARAM;
  1345.  
  1346.         // get the internal objects that have action mapping
  1347.         m_lpCalloutManager->EnumObjects( lpDevice, DidcvEnumDeviceObjectsCallback, 
  1348.                                          m_lpCustomViewInfo, TRUE );
  1349.     }
  1350.     else
  1351.     {
  1352.         // get a list of all objects for the device
  1353.         lpDevice->EnumObjects( DidcvEnumDeviceObjectsCallback, 
  1354.                                m_lpCustomViewInfo, DIDFT_ALL );
  1355.     }
  1356.  
  1357.     if( m_lpCustomViewInfo->dwSize == 0 )
  1358.     {
  1359.         m_lpCustomViewInfo->CleanUp();
  1360.         return DIERR_INVALIDPARAM;
  1361.     }
  1362.  
  1363.     // build the custom views
  1364.     if( FAILED( hr = BuildCustomViews() ) )
  1365.     {
  1366.         m_lpCustomViewInfo->CleanUp();
  1367.         return hr;
  1368.     }
  1369.  
  1370.     return S_OK;
  1371. }
  1372.  
  1373.  
  1374.  
  1375.  
  1376. //-----------------------------------------------------------------------------
  1377. // Name: BuildCustomViews()
  1378. // Desc: makes custom views
  1379. //-----------------------------------------------------------------------------
  1380. HRESULT DIDCfgView::BuildCustomViews()
  1381. {
  1382.     DidcvView* pView;
  1383.     DidcvCallout* pCallout;
  1384.     DWORD dwNumViews, dwStartIndex, dwFinishIndex;
  1385.     DWORD i, j;
  1386.     DIDEVICEIMAGEINFO devImageInfo;
  1387.  
  1388.     // pre-condition of this method - m_lpCustomViewInfo must be loaded
  1389.     assert( m_lpCustomViewInfo && m_lpCustomViewInfo->rgObjData );
  1390.  
  1391.     // calculate the number of views needed
  1392.     dwNumViews = DidcvCustomView::CalcNumViews( m_lpCustomViewInfo->dwSize );
  1393.     assert( dwNumViews );
  1394.  
  1395.     // reset
  1396.     m_lpViewManager->CleanUp();
  1397.     m_lpCalloutManager->CleanUp();
  1398.  
  1399.     // set the initial capacity
  1400.     if( FALSE == m_lpViewManager->SetCapacity( dwNumViews ) )
  1401.         return DIERR_OUTOFMEMORY;
  1402.  
  1403.     if( FALSE == m_lpCalloutManager->SetCapacity( m_lpCustomViewInfo->dwSize, 
  1404.                                                   m_lpCustomViewInfo->dwSize, dwNumViews ) )
  1405.         return DIERR_OUTOFMEMORY;
  1406.  
  1407.     dwStartIndex = 0;
  1408.     for( i = 0; i < dwNumViews; i++ )
  1409.     {
  1410.         // create views, each for a section of object array
  1411.         pView = DidcvCustomView::Create( m_lpCustomViewInfo, dwStartIndex, 
  1412.                                          &dwFinishIndex );
  1413.         if( NULL == pView )
  1414.             return DIERR_OUTOFMEMORY;
  1415.  
  1416.         // add the view to the manager
  1417.         if( FAILED( m_lpViewManager->AddImage( pView ) ) )
  1418.         {
  1419.             delete pView;
  1420.             continue;
  1421.         }
  1422.  
  1423.         for( j = dwStartIndex; j <= dwFinishIndex; j++ )
  1424.         {
  1425.             ZeroMemory( &devImageInfo, sizeof( DIDEVICEIMAGEINFO ) );
  1426.  
  1427.             // construct our own image info
  1428.             devImageInfo.dwFlags = DIDIFT_OVERLAY;
  1429.             // figure out the callout information for each object
  1430.             DidcvCustomView::CalcImageInfo( j, &( devImageInfo.rcOverlay ), 
  1431.                                             &( devImageInfo.dwcValidPts ),
  1432.                                             devImageInfo.rgptCalloutLine, 
  1433.                                             &( devImageInfo.rcCalloutRect ) );
  1434.             devImageInfo.dwTextAlign = DIDAL_LEFTALIGNED;
  1435.             devImageInfo.dwObjID = m_lpCustomViewInfo->rgObjData[j]->dwType;
  1436.  
  1437.             // create the callout and add
  1438.             pCallout = DidcvCallout::Create( &devImageInfo );
  1439.             m_lpCalloutManager->AddCallout( pCallout, pView->GetID() );
  1440.         }
  1441.  
  1442.         dwStartIndex = dwFinishIndex + 1;
  1443.     }
  1444.  
  1445.     return S_OK;
  1446. }
  1447.  
  1448.  
  1449.  
  1450.  
  1451. //-----------------------------------------------------------------------------
  1452. // Name: CopyActionMap()
  1453. // Desc: copies a DIACTIONFORMAT
  1454. //-----------------------------------------------------------------------------
  1455. BOOL DIDCfgView::CopyActionMap( LPDIACTIONFORMAT lpDiaf )
  1456. {
  1457.     if( m_lpDiaf )
  1458.     {
  1459.         // free the DIACTIONFORMAT
  1460.         if( m_lpDiaf->rgoAction )
  1461.             delete [] m_lpDiaf->rgoAction;
  1462.         delete m_lpDiaf;
  1463.         m_lpDiaf = NULL;
  1464.     }
  1465.  
  1466.     if( lpDiaf == NULL )
  1467.         return TRUE;
  1468.  
  1469.     m_lpDiaf = new DIACTIONFORMAT;
  1470.     if( m_lpDiaf == NULL )
  1471.         return FALSE;
  1472.  
  1473.     // copy the DIACTIONFORMAT
  1474.     memcpy( m_lpDiaf, lpDiaf, sizeof( DIACTIONFORMAT ) );
  1475.     if( lpDiaf->rgoAction )
  1476.     {
  1477.         // copy the internal array
  1478.         m_lpDiaf->rgoAction = new DIACTION[lpDiaf->dwNumActions];
  1479.         if( m_lpDiaf->rgoAction == NULL )
  1480.             return FALSE;
  1481.  
  1482.         memcpy( m_lpDiaf->rgoAction, lpDiaf->rgoAction, 
  1483.                 sizeof( DIACTION ) * lpDiaf->dwNumActions );
  1484.     }
  1485.  
  1486.     return TRUE;
  1487. }
  1488.  
  1489.  
  1490.  
  1491.  
  1492. //-----------------------------------------------------------------------------
  1493. // Name: CleanUp()
  1494. // Desc: release the resource for the CustomViewInfo
  1495. //-----------------------------------------------------------------------------
  1496. void DidcvCustomViewInfo::CleanUp()
  1497. {
  1498.     // free the custom view data
  1499.     if( rgObjData )
  1500.     {
  1501.         DWORD i;
  1502.         // free each item
  1503.         for( i = 0; i < dwSize; i++)
  1504.             if( rgObjData[i] )
  1505.                 delete rgObjData[i];
  1506.  
  1507.         // free the array
  1508.         delete [] rgObjData;
  1509.         rgObjData = NULL;
  1510.     }
  1511.  
  1512.     dwCount = 0;
  1513.     dwSize = 0;
  1514. }
  1515.  
  1516.  
  1517.  
  1518.  
  1519. //-----------------------------------------------------------------------------
  1520. // Name: DidcvBitmap()
  1521. // Desc: Constructor
  1522. //-----------------------------------------------------------------------------
  1523. DidcvBitmap::DidcvBitmap()
  1524.     : m_hbitmap( NULL ),
  1525.       m_lpBits( NULL )
  1526. {
  1527.     ZeroMemory( &m_size, sizeof( SIZE ) );
  1528.  
  1529.     // register with the alpha blend module
  1530.     DidcvAlphaBlend::AddClient();
  1531. }
  1532.  
  1533.  
  1534.  
  1535.  
  1536. //-----------------------------------------------------------------------------
  1537. // Name: ~DidcvBitmap()
  1538. // Desc: Destructor
  1539. //-----------------------------------------------------------------------------
  1540. DidcvBitmap::~DidcvBitmap()
  1541. {
  1542.     CleanUp();
  1543.  
  1544.     // release the alpha blending module
  1545.     DidcvAlphaBlend::ReleaseClient();
  1546. }
  1547.  
  1548.  
  1549.  
  1550.  
  1551. //-----------------------------------------------------------------------------
  1552. // Name: GetSize()
  1553. // Desc: retrieves the size of the bitmap - return FALSE if there is no bitmap
  1554. //-----------------------------------------------------------------------------
  1555. BOOL DidcvBitmap::GetSize( SIZE* lpSize ) const
  1556. {
  1557.     if( NULL == m_hbitmap )
  1558.         return FALSE;
  1559.  
  1560.     memcpy( lpSize, &m_size, sizeof( SIZE ) );
  1561.     return TRUE;
  1562. }
  1563.  
  1564.  
  1565.  
  1566.  
  1567. //-----------------------------------------------------------------------------
  1568. // Name: Draw()
  1569. // Desc: Draws onto a HDC, at( xStart, yStart )
  1570. //-----------------------------------------------------------------------------
  1571. BOOL DidcvBitmap::Draw( HDC hDC, INT xStart, INT yStart )
  1572. {
  1573.     if( NULL == m_hbitmap )
  1574.         return FALSE;
  1575.  
  1576.     BITMAP bm;
  1577.     HDC hdcMem;
  1578.     POINT ptSize, ptOrg;
  1579.  
  1580.     // create memory DC
  1581.     hdcMem = CreateCompatibleDC( hDC );
  1582.     SelectObject( hdcMem, m_hbitmap );
  1583.     SetMapMode( hdcMem, GetMapMode( hDC ) );
  1584.  
  1585.     // get bitmap info
  1586.     GetObject( m_hbitmap, sizeof( BITMAP ),( LPVOID ) &bm );
  1587.  
  1588.     ptSize.x = bm.bmWidth;
  1589.     ptSize.y = bm.bmHeight;
  1590.     DPtoLP( hDC, &ptSize, 1 );
  1591.  
  1592.     ptOrg.x = 0;
  1593.     ptOrg.y = 0;
  1594.     DPtoLP( hdcMem, &ptOrg, 1 );
  1595.  
  1596.     // blit
  1597.     BitBlt( hDC, xStart, yStart, ptSize.x, ptSize.y, 
  1598.             hdcMem, ptOrg.x, ptOrg.y, SRCCOPY );
  1599.  
  1600.     // free the memory DC
  1601.     DeleteDC( hdcMem );
  1602.  
  1603.     return TRUE;
  1604. }
  1605.  
  1606.  
  1607.  
  1608.  
  1609. //-----------------------------------------------------------------------------
  1610. // Name: Blend()
  1611. // Desc: draw the bitmap into HDC with alpha blending( xStart, yStart )
  1612. //-----------------------------------------------------------------------------
  1613. BOOL DidcvBitmap::Blend( HDC hDC, INT xStart, INT yStart )
  1614. {
  1615.     return DidcvAlphaBlend::Blend( hDC, xStart, yStart, 
  1616.                                    m_size.cx, m_size.cy, m_hbitmap, &m_size );
  1617. }
  1618.  
  1619.  
  1620.  
  1621.  
  1622. //-----------------------------------------------------------------------------
  1623. // Name: Blend()
  1624. // Desc: blend this bitmap unto the image
  1625. //-----------------------------------------------------------------------------
  1626. BOOL DidcvBitmap::Blend( VOID* lpBits, INT xStart, INT yStart, INT width, INT height )
  1627. {
  1628.     return DidcvAlphaBlend::Blend( lpBits, xStart, yStart, width, height, 
  1629.                                    m_lpBits, m_size.cx, m_size.cy );
  1630. }
  1631.  
  1632.  
  1633.  
  1634.  
  1635. //-----------------------------------------------------------------------------
  1636. // Name: GetHandle()
  1637. // Desc: return the GDI HBITMAP handle
  1638. //-----------------------------------------------------------------------------
  1639. HBITMAP DidcvBitmap::GetHandle()
  1640. {
  1641.     return m_hbitmap;
  1642. }
  1643.  
  1644.  
  1645.  
  1646.  
  1647. //-----------------------------------------------------------------------------
  1648. // Name: GetBits()
  1649. // Desc: returns a pointer to the bits
  1650. //-----------------------------------------------------------------------------
  1651. LPVOID DidcvBitmap::GetBits()
  1652. {
  1653.     return m_lpBits;
  1654. }
  1655.  
  1656.  
  1657.  
  1658.  
  1659. //-----------------------------------------------------------------------------
  1660. // Name: Create()
  1661. // Desc: static function to instantiate a bitmap object from a pathname
  1662. //-----------------------------------------------------------------------------
  1663. DidcvBitmap* DidcvBitmap::Create( LPCTSTR tszFilename )
  1664. {
  1665.     return CreateViaD3dx( tszFilename );
  1666. }
  1667.  
  1668.  
  1669.  
  1670.  
  1671. //-----------------------------------------------------------------------------
  1672. // Name: Create()
  1673. // Desc: static function to instantiate a bitmap object from dimensions
  1674. //-----------------------------------------------------------------------------
  1675. DidcvBitmap* DidcvBitmap::Create( INT width, INT height )
  1676. {
  1677.     BITMAPINFO bmi;
  1678.     DidcvBitmap* bm;
  1679.     HBITMAP hbm;
  1680.     VOID* lpBits;
  1681.  
  1682.     // sanity check
  1683.     if( width <= 0 || height <= 0 )
  1684.         return NULL;
  1685.  
  1686.     // make the header
  1687.     ZeroMemory( &bmi, sizeof( BITMAPINFO ) );
  1688.     bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader );
  1689.     bmi.bmiHeader.biWidth = width;
  1690.     bmi.bmiHeader.biHeight = height;
  1691.     bmi.bmiHeader.biPlanes = 1;
  1692.     bmi.bmiHeader.biBitCount = 32;
  1693.     bmi.bmiHeader.biCompression = BI_RGB;
  1694.     bmi.bmiHeader.biSizeImage = 0;
  1695.     bmi.bmiHeader.biXPelsPerMeter = 0;
  1696.     bmi.bmiHeader.biYPelsPerMeter = 0;
  1697.     bmi.bmiHeader.biClrUsed = 0;
  1698.     bmi.bmiHeader.biClrImportant = 0;
  1699.  
  1700.     // create a DIBSection
  1701.     hbm = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS, &lpBits, NULL, 0 );
  1702.     if( hbm == NULL )
  1703.         return NULL;
  1704.  
  1705.     // allocate an object
  1706.     bm = new DidcvBitmap;
  1707.     if( NULL == bm )
  1708.         return NULL;
  1709.  
  1710.     // set the members
  1711.     bm->m_hbitmap;
  1712.     bm->m_lpBits = lpBits;
  1713.     bm->m_size.cx = width;
  1714.     bm->m_size.cy = height;
  1715.  
  1716.     return bm;
  1717. }
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723. //-----------------------------------------------------------------------------
  1724. // Name: CleanUp()
  1725. // Desc: helper function to free resources
  1726. //-----------------------------------------------------------------------------
  1727. void DidcvBitmap::CleanUp()
  1728. {
  1729.     if( m_hbitmap )
  1730.     {
  1731.         DeleteObject( m_hbitmap );
  1732.         m_hbitmap = NULL;
  1733.     }
  1734.  
  1735.     m_lpBits = NULL;
  1736.     ZeroMemory( &m_size, sizeof( SIZE ) );
  1737. }
  1738.  
  1739.  
  1740.  
  1741.  
  1742. //-----------------------------------------------------------------------------
  1743. // Name: FigureSize()
  1744. // Desc: determines the size of the bitmap
  1745. //-----------------------------------------------------------------------------
  1746. void DidcvBitmap::FigureSize()
  1747. {
  1748.     BITMAP bm;
  1749.  
  1750.     if( NULL == m_hbitmap )
  1751.         return;
  1752.  
  1753.     if( 0 == GetObject( ( HGDIOBJ ) m_hbitmap, sizeof( BITMAP ),( LPVOID ) &bm ) )
  1754.         return;
  1755.  
  1756.     m_size.cx = abs( bm.bmWidth );
  1757.     m_size.cy = abs( bm.bmHeight );
  1758. }
  1759.  
  1760.  
  1761.  
  1762.  
  1763. //-----------------------------------------------------------------------------
  1764. // static members of DidcvAlphaBlend
  1765. //-----------------------------------------------------------------------------
  1766. DIDCV_ALPHABLEND DidcvAlphaBlend::s_alphaBlendProc = NULL;
  1767. HMODULE          DidcvAlphaBlend::s_hDll = NULL;
  1768. DWORD            DidcvAlphaBlend::s_dwNumClients = 0;
  1769.  
  1770.  
  1771.  
  1772.  
  1773. //-----------------------------------------------------------------------------
  1774. // Name: AddClient()
  1775. // Desc: static alpha blending initialization function
  1776. //       this bumps the reference count by one for each time it is called
  1777. //-----------------------------------------------------------------------------
  1778. BOOL DidcvAlphaBlend::AddClient()
  1779. {
  1780.     // try to the AlphaBlend function
  1781.     if( s_alphaBlendProc == NULL )
  1782.     {
  1783.         s_hDll = LoadLibrary( DIDCV_ALPHABLEND_DLL_NAME );
  1784.  
  1785.         if( s_hDll )
  1786.         {
  1787.             s_alphaBlendProc =( DIDCV_ALPHABLEND ) GetProcAddress( s_hDll, 
  1788.                                 DIDCV_ALPHABLEND_PROC_NAME );
  1789.             if( !s_alphaBlendProc )
  1790.             { 
  1791.                 FreeLibrary( s_hDll );
  1792.                 s_hDll = NULL;
  1793.             }
  1794.         }
  1795.     }
  1796.  
  1797.     // bump the reference count
  1798.     s_dwNumClients ++;
  1799.  
  1800.     return( s_alphaBlendProc != NULL );
  1801. }
  1802.  
  1803.  
  1804.  
  1805.  
  1806. //-----------------------------------------------------------------------------
  1807. // Name: ReleaseClient()
  1808. // Desc: static alpha blend function called when a client detach
  1809. //-----------------------------------------------------------------------------
  1810. BOOL DidcvAlphaBlend::ReleaseClient()
  1811. {
  1812.     if( s_dwNumClients )
  1813.         s_dwNumClients --;
  1814.  
  1815.     // if reference count 0, then free resources
  1816.     if( s_dwNumClients == 0 )
  1817.     {
  1818.         s_alphaBlendProc = NULL;
  1819.  
  1820.         if( s_hDll )
  1821.         {
  1822.             FreeLibrary( s_hDll );
  1823.             s_hDll = NULL;
  1824.         }
  1825.     }
  1826.  
  1827.     return TRUE;
  1828. }
  1829.  
  1830.  
  1831.  
  1832. //-----------------------------------------------------------------------------
  1833. // Name: Blend()
  1834. // Desc: blends images by hand
  1835. //-----------------------------------------------------------------------------
  1836. BOOL DidcvAlphaBlend::Blend( VOID* lpDestBits, INT xStart, INT yStart, 
  1837.                              INT destWidth, INT destHeight, VOID* lpSrcBits, 
  1838.                              INT srcWidth, INT srcHeight )
  1839. {
  1840.     if( !lpDestBits || !lpSrcBits )
  1841.         return FALSE;
  1842.  
  1843.     // calculate the strides
  1844.     INT destStride = destWidth * 4;
  1845.     INT destOffset = xStart * 4;
  1846.     INT srcStride = srcWidth * 4;
  1847.     INT i, j;
  1848.  
  1849.     // clip the rectangle to draw to if necessary
  1850.     if( ( xStart + srcWidth ) >( destWidth ) )
  1851.         srcWidth = destWidth - xStart;
  1852.     if( ( yStart + srcHeight ) >( destHeight ) )
  1853.         srcHeight = destHeight - yStart;
  1854.  
  1855.     // the DIB bits are is indexed from bottom, left corner, so need to reverse horizontally
  1856.     BYTE* pDestStart = ( BYTE* ) lpDestBits + 
  1857.                        ( ( destHeight - yStart - 1 ) * destStride ) + destOffset;
  1858.     BYTE* pSrcStart =( BYTE* ) lpSrcBits + ( srcHeight - 1 ) * srcStride;
  1859.     BYTE destAlpha, srcAlpha;
  1860.  
  1861.     for( i = 0; i < srcHeight; i++ )
  1862.     {
  1863.         for( j = 0; j < srcStride; j += 4 )
  1864.         {
  1865.             // calculate src and dest alpha
  1866.             destAlpha = 0xff - pSrcStart[j + 3];
  1867.             srcAlpha = pSrcStart[j + 3];
  1868.  
  1869.             if( !srcAlpha ) continue;
  1870.             if( !destAlpha )
  1871.                 *(( DWORD* )&pDestStart[j]) = *((DWORD *)&pSrcStart[j]);
  1872.             else
  1873.             {
  1874.                 // set the R, G, B components
  1875.                 pDestStart [j] =( pDestStart[j] * destAlpha + pSrcStart[j] * srcAlpha ) / 0xff;
  1876.                 pDestStart [j+1] =( pDestStart[j+1] * destAlpha + pSrcStart[j+1] * srcAlpha ) / 0xff;
  1877.                 pDestStart [j+2] =( pDestStart[j+2] * destAlpha + pSrcStart[j+2] * srcAlpha ) / 0xff;
  1878.             }
  1879.         }
  1880.  
  1881.         // advance the pointers
  1882.         pDestStart -= destStride;
  1883.         pSrcStart -= srcStride;
  1884.     }
  1885.  
  1886.     return TRUE;
  1887. }
  1888.  
  1889.  
  1890.  
  1891.  
  1892. //-----------------------------------------------------------------------------
  1893. // Name: Blend()
  1894. // Desc: blends a bitmap into the HDC
  1895. //-----------------------------------------------------------------------------
  1896. BOOL DidcvAlphaBlend::Blend( HDC hDC, INT xStart, INT yStart, INT width, 
  1897.                              INT height, HBITMAP hbitmap, const SIZE* lpSize )
  1898. {
  1899.     if( hDC == NULL || hbitmap == NULL || lpSize == NULL )
  1900.         return FALSE;
  1901.  
  1902. #if( WINVER >= 0x400 )
  1903.  
  1904.     HDC hDCbm = CreateCompatibleDC( hDC );
  1905.     if( hDCbm == NULL )
  1906.         return FALSE;
  1907.  
  1908. // this is done to resolve differences in header files
  1909. #ifdef AC_SRC_ALPHA
  1910.     BLENDFUNCTION blendfn = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  1911. #else
  1912.     BLENDFUNCTION blendfn = { AC_SRC_OVER, 0, 255, 0x1 };
  1913. #endif
  1914.  
  1915.     HGDIOBJ hOldBitmap = SelectObject( hDCbm, hbitmap );
  1916.     BOOL bRet = s_alphaBlendProc( hDC, xStart, yStart, width, height, 
  1917.                                   hDCbm, 0, 0, lpSize->cx, lpSize->cy, blendfn );
  1918.     SelectObject( hDCbm, hOldBitmap ); 
  1919.     DeleteDC( hDCbm );
  1920.  
  1921.     return TRUE;
  1922.  
  1923. #else
  1924.  
  1925.     return FALSE;
  1926.  
  1927. #endif
  1928.  
  1929. }
  1930.  
  1931.  
  1932.  
  1933.  
  1934. //-----------------------------------------------------------------------------
  1935. // Name: DidcvCallout()
  1936. // Desc: Constructor
  1937. //-----------------------------------------------------------------------------
  1938. DidcvCallout::DidcvCallout()
  1939.     : m_nViewRef( DIDCV_INVALID_ID ),
  1940.       m_lpDataRef( NULL ),
  1941.       m_lpOverlayBitmap( NULL )
  1942. {
  1943.     ZeroMemory( &m_devImgInfo, sizeof( DIDEVICEIMAGEINFO ) );
  1944. }
  1945.  
  1946.  
  1947.  
  1948.  
  1949. //-----------------------------------------------------------------------------
  1950. // Name: ~DidcvCallout()
  1951. // Desc: destructor
  1952. //-----------------------------------------------------------------------------
  1953. DidcvCallout::~DidcvCallout()
  1954. {
  1955.     if( m_lpOverlayBitmap )
  1956.     {
  1957.         delete m_lpOverlayBitmap;
  1958.         m_lpOverlayBitmap = NULL;
  1959.     }
  1960. }
  1961.  
  1962.  
  1963.  
  1964.  
  1965. //-----------------------------------------------------------------------------
  1966. // Name: GetObjID()
  1967. // Desc: returns the object ID
  1968. //-----------------------------------------------------------------------------
  1969. DWORD DidcvCallout::GetObjID() const
  1970. {
  1971.     return m_devImgInfo.dwObjID;
  1972. }
  1973.  
  1974.  
  1975.  
  1976.  
  1977. //-----------------------------------------------------------------------------
  1978. // Name: GetOverlayRect()
  1979. // Desc: returns the overlay rect for the callout
  1980. //-----------------------------------------------------------------------------
  1981. const RECT & DidcvCallout::GetOverlayRect() const
  1982. {
  1983.     return m_devImgInfo.rcOverlay;
  1984. }
  1985.  
  1986.  
  1987.  
  1988.  
  1989. //-----------------------------------------------------------------------------
  1990. // Name: GetCalloutRect()
  1991. // Desc: returns the callout rect, where the action text is displayed
  1992. //-----------------------------------------------------------------------------
  1993. const RECT & DidcvCallout::GetCalloutRect() const
  1994. {
  1995.     return m_devImgInfo.rcCalloutRect;
  1996. }
  1997.  
  1998.  
  1999.  
  2000.  
  2001. //-----------------------------------------------------------------------------
  2002. // Name: GetCalloutLine()
  2003. // Desc: returns the callout line segments as a const array
  2004. //-----------------------------------------------------------------------------
  2005. const POINT* DidcvCallout::GetCalloutLine( DWORD* lpNumPts ) const
  2006. {
  2007.     if( NULL != lpNumPts )
  2008.         *lpNumPts = m_devImgInfo.dwcValidPts;
  2009.  
  2010.     return m_devImgInfo.rgptCalloutLine;
  2011. }
  2012.  
  2013.  
  2014.  
  2015.  
  2016. //-----------------------------------------------------------------------------
  2017. // Name: GetTextAlign()
  2018. // Desc: return the text alignment for the callout
  2019. //-----------------------------------------------------------------------------
  2020. DWORD DidcvCallout::GetTextAlign() const
  2021. {
  2022.     return m_devImgInfo.dwTextAlign;
  2023. }
  2024.  
  2025.  
  2026.  
  2027.  
  2028. //-----------------------------------------------------------------------------
  2029. // Name: GetOverlayOffset()
  2030. // Desc: returns the index of the callout in the original image info array
  2031. //       returned by DirectInputDevice8::GetImage()
  2032. //-----------------------------------------------------------------------------
  2033. DWORD DidcvCallout::GetOverlayOffset() const
  2034. {
  2035.     return m_devImgInfo.dwViewID;
  2036. }
  2037.  
  2038.  
  2039.  
  2040.  
  2041. //-----------------------------------------------------------------------------
  2042. // Name: GetAssociatedViewID()
  2043. // Desc: returns the internally assigned( by DIDCfgView ) identifier of a
  2044. //       view that this callout is assicated with
  2045. //-----------------------------------------------------------------------------
  2046. INT DidcvCallout::GetAssociatedViewID() const
  2047. {
  2048.     return m_nViewRef;
  2049. }
  2050.  
  2051.  
  2052.  
  2053.  
  2054. //-----------------------------------------------------------------------------
  2055. // Name: SetAssociatedViewID()
  2056. // Desc: sets the view with which this callout is associated with
  2057. //-----------------------------------------------------------------------------
  2058. void DidcvCallout::SetAssociatedViewID( INT nViewRef )
  2059. {
  2060.     m_nViewRef = nViewRef;
  2061. }
  2062.  
  2063.  
  2064.  
  2065.  
  2066. //-----------------------------------------------------------------------------
  2067. // Name: HitTest()
  2068. // Desc: tests to determines whether a point is contained the associated
  2069. //       regions of this callout.  coordinates are relative to the left top
  2070. //       corner of the image
  2071. //-----------------------------------------------------------------------------
  2072. DWORD DidcvCallout::HitTest( LPPOINT lpPt ) const
  2073. {
  2074.     if( NULL == lpPt )
  2075.         return FALSE;
  2076.  
  2077.     // if in overlay rectangle, then hit
  2078.     //    if( PtInRect( &( m_devImgInfo.rcOverlay ), *lpPt ) )
  2079.     //        return TRUE;
  2080.  
  2081.     // if in callout rectangle, then hit
  2082.     if( PtInRect( &( m_devImgInfo.rcCalloutRect ), *lpPt ) )
  2083.         return TRUE;
  2084.  
  2085.     return FALSE;
  2086. }
  2087.  
  2088.  
  2089.  
  2090.  
  2091. //-----------------------------------------------------------------------------
  2092. // Name: DrawOverlay()
  2093. // Desc: draws the overlay image
  2094. //-----------------------------------------------------------------------------
  2095. DWORD DidcvCallout::DrawOverlay( HDC hDC, VOID* lpBits, INT width, 
  2096.                                  INT height, const POINT* ptOrigin )
  2097. {
  2098.     BOOL res = FALSE;
  2099.  
  2100.     if( m_lpOverlayBitmap )
  2101.     {
  2102.         // alpha blend with pointers only
  2103.         if( lpBits )
  2104.             res = m_lpOverlayBitmap->Blend( lpBits, 
  2105.                         m_devImgInfo.rcOverlay.left + ptOrigin->x, 
  2106.                         m_devImgInfo.rcOverlay.top  + ptOrigin->y, 
  2107.                         width, height );
  2108.  
  2109.         if( !res )
  2110.         {
  2111.             // try alpha blending with hDC
  2112.             res = m_lpOverlayBitmap->Blend( hDC, m_devImgInfo.rcOverlay.left, 
  2113.                                             m_devImgInfo.rcOverlay.top );
  2114.         }
  2115.     }
  2116.  
  2117.     return res;
  2118. }
  2119.  
  2120.  
  2121.  
  2122.  
  2123. //-----------------------------------------------------------------------------
  2124. // Name: SetDataRef()
  2125. // Desc: attach a pointer to the callout data relevant to this callout
  2126. //-----------------------------------------------------------------------------
  2127. void DidcvCallout::SetDataRef( const DidcvCalloutData* lpData )
  2128. {
  2129.     m_lpDataRef = lpData;
  2130. }
  2131.  
  2132.  
  2133.  
  2134.  
  2135. //-----------------------------------------------------------------------------
  2136. // Name: GetDataRef()
  2137. // Desc: retrieved the the data reference stored with this callout
  2138. //-----------------------------------------------------------------------------
  2139. const DidcvCalloutData* DidcvCallout::GetDataRef() const
  2140. {
  2141.     return m_lpDataRef;
  2142. }
  2143.  
  2144.  
  2145.  
  2146.  
  2147. //-----------------------------------------------------------------------------
  2148. // Name: Create()
  2149. // Desc: static function for instantiating a DidcvCallout
  2150. //-----------------------------------------------------------------------------
  2151. DidcvCallout* DidcvCallout::Create( LPDIDEVICEIMAGEINFO lpDevImgInfo )
  2152. {
  2153.     DidcvCallout* lpCallout = NULL;
  2154.  
  2155.     if( NULL == lpDevImgInfo )
  2156.         return NULL;
  2157.  
  2158.     // allocate
  2159.     lpCallout = new DidcvCallout;
  2160.  
  2161.     if( NULL == lpCallout )
  2162.         return NULL;
  2163.  
  2164.     // copy the device image info
  2165.     memcpy( &( lpCallout->m_devImgInfo ), lpDevImgInfo, sizeof( DIDEVICEIMAGEINFO ) );
  2166.  
  2167.     if( lpDevImgInfo->tszImagePath )
  2168.     {
  2169.         // load the overlay
  2170.         lpCallout->m_lpOverlayBitmap = DidcvBitmap::Create( lpDevImgInfo->tszImagePath );
  2171.     }
  2172.  
  2173.     return lpCallout;
  2174. }
  2175.  
  2176.  
  2177.  
  2178.  
  2179. //-----------------------------------------------------------------------------
  2180. // Name: DidcvCalloutManager()
  2181. // Desc: Constructor
  2182. //-----------------------------------------------------------------------------
  2183. DidcvCalloutManager::DidcvCalloutManager() 
  2184.     : m_calloutList( DIDCV_DEFAULT_CALLOUT_MANAGER_ARRAY_SIZE ),
  2185.       m_calloutSetListByObjID( DIDCV_DEFAULT_CALLOUT_MANAGER_ARRAY_SIZE ),
  2186.       m_calloutSetListByView( DIDCV_DEFAULT_CALLOUT_MANAGER_ARRAY_SIZE )
  2187. { }
  2188.  
  2189.  
  2190.  
  2191.  
  2192. //-----------------------------------------------------------------------------
  2193. // Name: ~DidcvCalloutManager()
  2194. // Desc: destructor
  2195. //-----------------------------------------------------------------------------
  2196. DidcvCalloutManager::~DidcvCalloutManager()
  2197. {
  2198.     CleanUp();
  2199. }
  2200.  
  2201.  
  2202.  
  2203.  
  2204. //-----------------------------------------------------------------------------
  2205. // Name: CleanUp()
  2206. // Desc: reset the callout manager, freeing resources
  2207. //-----------------------------------------------------------------------------
  2208. void DidcvCalloutManager::CleanUp()
  2209. {
  2210.     UINT i;
  2211.  
  2212.     // free the entries
  2213.     for( i = 0; i < m_calloutList.Size(); i++ )
  2214.         if( m_calloutList[i] )
  2215.             delete m_calloutList[i];
  2216.  
  2217.     // free the view callout set
  2218.     for( i = 0; i < m_calloutSetListByView.Size(); i++ )
  2219.         if( m_calloutSetListByView[i] )
  2220.             delete m_calloutSetListByView[i];
  2221.  
  2222.     // free the obj id callout set
  2223.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2224.     {
  2225.         if( m_calloutSetListByObjID[i] )
  2226.         {
  2227.             DidcvCalloutData* lpCalloutData = 
  2228.               ( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2229.  
  2230.             // is there is data attached, deallocate it
  2231.             if( lpCalloutData )
  2232.             {
  2233.                 if( lpCalloutData->lpState )
  2234.                     delete lpCalloutData->lpState;
  2235.  
  2236.                 if( lpCalloutData->lpActionMap )
  2237.                     delete lpCalloutData->lpActionMap;
  2238.  
  2239.                 delete lpCalloutData;
  2240.             }
  2241.  
  2242.             delete m_calloutSetListByObjID[i];
  2243.         }
  2244.     }
  2245.  
  2246.     // set the array size to 0
  2247.     m_calloutList.SetSize( 0 );
  2248.     m_calloutSetListByObjID.SetSize( 0 );
  2249.     m_calloutSetListByView.SetSize( 0 );
  2250. }
  2251.  
  2252.  
  2253.  
  2254.  
  2255. //-----------------------------------------------------------------------------
  2256. // Name: SetCapacity()
  2257. // Desc: sets the capacity in advance
  2258. //-----------------------------------------------------------------------------
  2259. BOOL DidcvCalloutManager::SetCapacity( DWORD dwNumCallouts, DWORD dwNumUniqueObjID, 
  2260.                                        DWORD dwNumViews, BOOL bDeleteContent )
  2261. {
  2262.     if( bDeleteContent )
  2263.         CleanUp();
  2264.  
  2265.     m_calloutList.SetSize( dwNumCallouts );
  2266.     m_calloutSetListByObjID.SetSize( dwNumUniqueObjID );
  2267.     m_calloutSetListByView.SetSize( dwNumViews );
  2268.  
  2269.     return TRUE;
  2270. }
  2271.  
  2272.  
  2273.  
  2274.  
  2275. //-----------------------------------------------------------------------------
  2276. // Name: AddCallout()
  2277. // Desc: adds a callout object to be stored and managed by this object
  2278. //-----------------------------------------------------------------------------
  2279. BOOL DidcvCalloutManager::AddCallout( DidcvCallout* lpCallout, INT nView )
  2280. {
  2281.     DidcvCalloutSet*  lpViewSet  = NULL;
  2282.     DidcvCalloutSet*  lpObjIDSet = NULL;
  2283.     DidcvCalloutData* lpData     = NULL;
  2284.  
  2285.     // sanity check
  2286.     if( NULL == lpCallout || lpCallout->GetObjID() == 0 || nView < 0 )
  2287.         return FALSE;
  2288.  
  2289.     // append to complete list
  2290.     m_calloutList.PushBack( lpCallout );
  2291.  
  2292.     // ----------- organize by view
  2293.  
  2294.     // look to see if CalloutSet exist for the view
  2295.     lpViewSet = Find( m_calloutSetListByView,( DWORD ) nView );
  2296.  
  2297.     // no set exist - new view
  2298.     if( NULL == lpViewSet )
  2299.     {
  2300.         lpViewSet = new DidcvCalloutSet;
  2301.         lpViewSet->SetIdentifier( ( DWORD ) nView );
  2302.         m_calloutSetListByView.PushBack( lpViewSet );
  2303.     }
  2304.  
  2305.     // append callout to the view set
  2306.     lpViewSet->AddCallout( lpCallout );
  2307.  
  2308.     // ----------- organize by object id
  2309.  
  2310.     // look to see if CalloutSet exist for the ObjID
  2311.     lpObjIDSet = Find( m_calloutSetListByObjID, lpCallout->GetObjID() );
  2312.  
  2313.     if( NULL == lpObjIDSet )
  2314.     {
  2315.         // new set of callout
  2316.         lpObjIDSet = new DidcvCalloutSet;
  2317.         lpObjIDSet->SetIdentifier( lpCallout->GetObjID() );
  2318.         // allocate new data to be associated
  2319.         lpObjIDSet->SetData( lpData = new DidcvCalloutData( 
  2320.             new DidcvCalloutState( DIDCV_ALL_CALLOUT_STATE_SET ),
  2321.             NULL ) );
  2322.         m_calloutSetListByObjID.PushBack( lpObjIDSet );
  2323.     }
  2324.     else
  2325.     {
  2326.         lpData =( DidcvCalloutData* ) lpObjIDSet->GetData();
  2327.     }
  2328.  
  2329.     // append callout
  2330.     lpObjIDSet->AddCallout( lpCallout );
  2331.  
  2332.     // set data reference
  2333.     lpCallout->SetDataRef( lpData );
  2334.  
  2335.     return TRUE;
  2336. }
  2337.  
  2338.  
  2339.  
  2340.  
  2341. //-----------------------------------------------------------------------------
  2342. // Name: GetObjectIDByLocation()
  2343. // Desc: given a point( in image coordinate ) and a view, returns a callout 
  2344. //     ( if any ) that contains the point.
  2345. //-----------------------------------------------------------------------------
  2346. DWORD DidcvCalloutManager::GetObjectIDByLocation( LPPOINT lpPt, INT nView )
  2347. {
  2348.     UINT i, size;
  2349.     DidcvCalloutSet* lpViewSet = NULL;
  2350.  
  2351.     // sanity check
  2352.     if( NULL == lpPt || nView < 0 )
  2353.         return 0;
  2354.  
  2355.     // look for the the callout set by view
  2356.     lpViewSet = Find( m_calloutSetListByView,( DWORD )nView );
  2357.  
  2358.     // if not found, return
  2359.     if( NULL == lpViewSet )
  2360.         return 0;
  2361.  
  2362.     // obtain a const reference, fast + safe
  2363.     const GwArray <DidcvCallout *> & arr = lpViewSet->GetInternalArrayRef();
  2364.  
  2365.     size = arr.Size();
  2366.  
  2367.     // loop through the callouts
  2368.     for( i = 0; i < size; i++ )
  2369.     {
  2370.         // return the first hit
  2371.         if( arr[i]->HitTest( lpPt ) != 0 )
  2372.             return arr[i]->GetObjID();
  2373.     }
  2374.  
  2375.     // no hits
  2376.     return 0;
  2377. }
  2378.  
  2379.  
  2380.  
  2381.  
  2382. //-----------------------------------------------------------------------------
  2383. // Name: SetCalloutState()
  2384. // Desc: set the state for a particular callout
  2385. //-----------------------------------------------------------------------------
  2386. BOOL DidcvCalloutManager::SetCalloutState( const DidcvCalloutState* lpCalloutState, 
  2387.                                            DWORD dwObjID )
  2388. {
  2389.     DidcvCalloutData* lpInternalCalloutData;
  2390.  
  2391.     // sanity check
  2392.     if( NULL == lpCalloutState )
  2393.         return FALSE;
  2394.  
  2395.     // get the data associated with the object
  2396.     lpInternalCalloutData = GetCalloutData( dwObjID );
  2397.  
  2398.     // not found
  2399.     if( NULL == lpInternalCalloutData )
  2400.         return FALSE;
  2401.  
  2402.     // set the internal state to the new state
  2403.     lpInternalCalloutData->lpState->SmartSet( lpCalloutState );
  2404.  
  2405.     return TRUE;
  2406. }
  2407.  
  2408.  
  2409.  
  2410.  
  2411. //-----------------------------------------------------------------------------
  2412. // Name: SetCalloutState()
  2413. // Desc: set the state for a particular callout
  2414. //-----------------------------------------------------------------------------
  2415. BOOL DidcvCalloutManager::SetAllCalloutState( const DidcvCalloutState* lpCalloutState )
  2416. {
  2417.     DidcvCalloutData* lpInternalCalloutData;
  2418.     UINT i;
  2419.  
  2420.     // sanity check
  2421.     if( NULL == lpCalloutState )
  2422.         return FALSE;
  2423.  
  2424.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2425.     {
  2426.         // get the data associated with the object
  2427.         lpInternalCalloutData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2428.  
  2429.         // not found
  2430.         if( NULL == lpInternalCalloutData )
  2431.         {
  2432.             // internal error
  2433.             continue;
  2434.         }
  2435.  
  2436.         // set the internal state to the new state
  2437.         lpInternalCalloutData->lpState->SmartSet( lpCalloutState );
  2438.     }
  2439.  
  2440.     return TRUE;
  2441. }
  2442.  
  2443.  
  2444.  
  2445.  
  2446. //-----------------------------------------------------------------------------
  2447. // Name: GetCalloutState()
  2448. // Desc: retrieves the state for a given callout
  2449. //-----------------------------------------------------------------------------
  2450. BOOL DidcvCalloutManager::GetCalloutState( DidcvCalloutState* lpCalloutState, 
  2451.                                            DWORD dwObjID )
  2452. {
  2453.     DidcvCalloutData* lpInternalCalloutData;
  2454.  
  2455.     if( NULL == lpCalloutState )
  2456.         return FALSE;
  2457.  
  2458.     // get the data associated with the object
  2459.     lpInternalCalloutData = GetCalloutData( dwObjID );
  2460.  
  2461.     // not found
  2462.     if( NULL == lpInternalCalloutData )
  2463.         return FALSE;
  2464.  
  2465.     // copy the internal state
  2466.     lpCalloutState->Copy( lpInternalCalloutData->lpState );
  2467.  
  2468.     return TRUE;
  2469. }
  2470.  
  2471.  
  2472.  
  2473.  
  2474. //-----------------------------------------------------------------------------
  2475. // Name: SetActionMap()
  2476. // Desc: sets the action mapping for a particular callout
  2477. //-----------------------------------------------------------------------------
  2478. BOOL DidcvCalloutManager::SetActionMap( const LPDIACTION lpAction, DWORD dwObjID )
  2479. {
  2480.     DidcvCalloutSet* lpCalloutSet = NULL;
  2481.     DidcvCalloutData* lpInternalCalloutData = NULL;
  2482.     DidcvActionMap* lpActionMap = NULL;
  2483.  
  2484.     // find the set associated with the control
  2485.     lpCalloutSet = Find( m_calloutSetListByObjID, dwObjID );
  2486.  
  2487.     // not found
  2488.     if( NULL == lpCalloutSet )
  2489.         return FALSE;
  2490.  
  2491.     // get the data associated with the object
  2492.     lpInternalCalloutData =( DidcvCalloutData* ) lpCalloutSet->GetData();
  2493.  
  2494.     // every set should have a callout data reference, if not - internal error
  2495.     assert ( lpInternalCalloutData != NULL );
  2496.  
  2497.     if( NULL == lpAction )
  2498.     {
  2499.         // if lpAction is NULL, then reset the action map
  2500.         if( lpInternalCalloutData->lpActionMap )
  2501.         {
  2502.             delete lpInternalCalloutData->lpActionMap;
  2503.             lpInternalCalloutData->lpActionMap = NULL;
  2504.         }
  2505.  
  2506.         lpActionMap;
  2507.     }
  2508.     else
  2509.     {
  2510.         // allocate, if necessary
  2511.         if( NULL == lpInternalCalloutData->lpActionMap )
  2512.             lpActionMap = lpInternalCalloutData->lpActionMap = new DidcvActionMap;
  2513.  
  2514.         // store the information
  2515.         memcpy( &( lpInternalCalloutData->lpActionMap->dia ), 
  2516.                 lpAction, sizeof( DIACTION ) );
  2517.     }
  2518.  
  2519.     return TRUE;
  2520. }
  2521.  
  2522.  
  2523.  
  2524.  
  2525. //-----------------------------------------------------------------------------
  2526. // Name: GetActionMap()
  2527. // Desc: retrieves the action map for a particular callout
  2528. //-----------------------------------------------------------------------------
  2529. BOOL DidcvCalloutManager::GetActionMap( DidcvActionMap* lpActionMap, DWORD dwObjID )
  2530. {
  2531.     DidcvCalloutData* lpInternalCalloutData;
  2532.  
  2533.     // get the data associated with the object
  2534.     lpInternalCalloutData = GetCalloutData( dwObjID );
  2535.  
  2536.     // not found
  2537.     if( NULL == lpInternalCalloutData || NULL == lpInternalCalloutData->lpActionMap )
  2538.         return FALSE;
  2539.  
  2540.     // copy internal data to be returned
  2541.     lpActionMap->Copy( lpInternalCalloutData->lpActionMap );
  2542.  
  2543.     return TRUE;
  2544. }
  2545.  
  2546.  
  2547.  
  2548.  
  2549. //-----------------------------------------------------------------------------
  2550. // Name: GetNumUniqueCallouts()
  2551. // Desc: returns the number of unique callouts
  2552. //-----------------------------------------------------------------------------
  2553. UINT DidcvCalloutManager::GetNumUniqueCallouts() const
  2554. {
  2555.     return m_calloutSetListByObjID.Size();
  2556. }
  2557.  
  2558.  
  2559.  
  2560.  
  2561. //-----------------------------------------------------------------------------
  2562. // Name: ClearAllActionMaps()
  2563. // Desc: resets( and frees ) all action maps associated with all callouts in
  2564. //       the manager
  2565. //-----------------------------------------------------------------------------
  2566. void DidcvCalloutManager::ClearAllActionMaps()
  2567. {
  2568.     UINT i;
  2569.     DidcvCalloutData* lpInternalCalloutData;
  2570.  
  2571.     // run through callout set list
  2572.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2573.     {
  2574.         // get the data associated with each
  2575.         lpInternalCalloutData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2576.         
  2577.         if( lpInternalCalloutData->lpActionMap )
  2578.         {
  2579.             // free and reset action maps
  2580.             delete lpInternalCalloutData->lpActionMap;
  2581.             lpInternalCalloutData->lpActionMap = NULL;
  2582.         }
  2583.     }
  2584. }
  2585.  
  2586.  
  2587.  
  2588.  
  2589. //-----------------------------------------------------------------------------
  2590. // Name: EnumObjects()
  2591. // Desc: enumerates the list of objects - the dwMapOnly specifies if only
  2592. //       objects with action assign
  2593. //-----------------------------------------------------------------------------
  2594. BOOL DidcvCalloutManager::EnumObjects( LPDIRECTINPUTDEVICE8 lpDevice, 
  2595.                                        LPDIENUMDEVICEOBJECTSCALLBACK lpCallback, 
  2596.                                        LPVOID pvRef, DWORD dwMapOnly )
  2597. {
  2598.     UINT i;
  2599.     DidcvCalloutData* lpData;
  2600.     DIDEVICEOBJECTINSTANCE objInst;
  2601.  
  2602.     if( lpDevice == NULL || lpCallback == NULL )
  2603.         return FALSE;
  2604.  
  2605.     // go through list of unique callouts
  2606.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2607.     {
  2608.         // get the data associated with the callout set
  2609.         lpData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2610.  
  2611.         // if do all or if action mapped
  2612.         if( !dwMapOnly || lpData->lpActionMap )
  2613.         {
  2614.             ZeroMemory( &objInst, sizeof( DIDEVICEOBJECTINSTANCE ) );
  2615.             objInst.dwSize = sizeof( DIDEVICEOBJECTINSTANCE );
  2616.  
  2617.             // get the info about the object from the device
  2618.             lpDevice->GetObjectInfo( &objInst, 
  2619.                         m_calloutSetListByObjID[i]->GetIdentifier(), DIPH_BYID );
  2620.             lpCallback( &objInst, pvRef );
  2621.         }
  2622.     }
  2623.     
  2624.     return TRUE;
  2625. }
  2626.  
  2627.  
  2628.  
  2629.  
  2630. //-----------------------------------------------------------------------------
  2631. // Name: CalcCanBeCollapsed()
  2632. // Desc: figures out if there are any unmapped callouts
  2633. //-----------------------------------------------------------------------------
  2634. BOOL DidcvCalloutManager::CalcCanBeCollapsed()
  2635. {
  2636.     UINT i;
  2637.     DidcvCalloutData* lpData;
  2638.  
  2639.     for( i = 0; i < m_calloutSetListByObjID.Size(); i ++ )
  2640.     {
  2641.         lpData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2642.  
  2643.         // if we find any non-mapped callouts
  2644.         if( lpData->lpActionMap == NULL )
  2645.             return TRUE;
  2646.     }
  2647.  
  2648.     return FALSE;
  2649. }
  2650.  
  2651.  
  2652.  
  2653.  
  2654. //-----------------------------------------------------------------------------
  2655. // Name: TrimArrays()
  2656. // Desc: trims the internal array( and frees unnecessary memory )
  2657. //-----------------------------------------------------------------------------
  2658. void DidcvCalloutManager::TrimArrays()
  2659. {
  2660.     // this shouldn't have to do anything if the sizes were preset
  2661.     m_calloutList.Trim();
  2662.     m_calloutSetListByObjID.Trim();
  2663.     m_calloutSetListByView.Trim();
  2664.  
  2665.     UINT i;
  2666.  
  2667.     for( i = 0; i < m_calloutSetListByObjID.Size(); i ++ )
  2668.         m_calloutSetListByObjID[i]->TrimArrays();
  2669.  
  2670.     for( i = 0; i < m_calloutSetListByView.Size(); i ++ )
  2671.         m_calloutSetListByView[i]->TrimArrays();
  2672. }
  2673.  
  2674.  
  2675.  
  2676.  
  2677. //-----------------------------------------------------------------------------
  2678. // Name: GetCalloutDataRef()
  2679. // Desc: returns the( const ) data associated with a particular callout
  2680. //-----------------------------------------------------------------------------
  2681. const DidcvCalloutData* DidcvCalloutManager::GetCalloutDataRef( DWORD dwObjID ) const
  2682. {
  2683.     return GetCalloutData( dwObjID );
  2684. }
  2685.  
  2686.  
  2687.  
  2688.  
  2689. //-----------------------------------------------------------------------------
  2690. // Name: GetCalloutSetByView()
  2691. // Desc: return the callout set for a given view, if any
  2692. //-----------------------------------------------------------------------------
  2693. const DidcvCalloutSet* DidcvCalloutManager::GetCalloutSetByView( INT nView ) const
  2694. {
  2695.     return Find( m_calloutSetListByView,( DWORD ) nView );
  2696. }
  2697.  
  2698.  
  2699.  
  2700.  
  2701. //-----------------------------------------------------------------------------
  2702. // Name: GetCalloutSetByObjID()
  2703. // Desc: returns the callout set for a given callout, if any
  2704. //-----------------------------------------------------------------------------
  2705. const DidcvCalloutSet* DidcvCalloutManager::GetCalloutSetByObjID( DWORD dwObjID ) const
  2706. {
  2707.     return Find( m_calloutSetListByView, dwObjID );
  2708. }
  2709.  
  2710.  
  2711.  
  2712.  
  2713. //-----------------------------------------------------------------------------
  2714. // Name: Find()
  2715. // Desc: helper function to find a callout set from an array, using 
  2716. //       an identifier
  2717. //-----------------------------------------------------------------------------
  2718. DidcvCalloutSet* DidcvCalloutManager::Find( const GwArray <DidcvCalloutSet *> & arr, 
  2719.                                             DWORD dwIdentifier ) const
  2720. {
  2721.     // TODO: this function can be optimized if needed
  2722.     UINT i, size;
  2723.  
  2724.     size = arr.Size();
  2725.  
  2726.     for( i = 0; i < size; i++ )
  2727.     {
  2728.         if( arr[i]->GetIdentifier() == dwIdentifier )
  2729.             return arr[i];
  2730.     }
  2731.  
  2732.     return NULL;
  2733. }
  2734.  
  2735.  
  2736.  
  2737.  
  2738. //-----------------------------------------------------------------------------
  2739. // Name: GetCalloutData()
  2740. // Desc: helper function that returns the callout data for a given callout
  2741. //-----------------------------------------------------------------------------
  2742. DidcvCalloutData* DidcvCalloutManager::GetCalloutData( DWORD dwObjID ) const
  2743. {
  2744.     DidcvCalloutData* lpData;
  2745.     DidcvCalloutSet* lpCalloutSet;
  2746.  
  2747.     // find the set of callout with the id
  2748.     lpCalloutSet = Find( m_calloutSetListByObjID, dwObjID );
  2749.  
  2750.     // if not found
  2751.     if( NULL == lpCalloutSet )
  2752.         return NULL;
  2753.  
  2754.     // return the data associated with the object
  2755.     lpData =( DidcvCalloutData* ) lpCalloutSet->GetData();
  2756.  
  2757.     if( NULL == lpData || NULL == lpData->lpState )
  2758.     {
  2759.         // internal error, must handle differently
  2760.         assert( 0 );
  2761.         return NULL;
  2762.     }
  2763.  
  2764.     return lpData;
  2765. }
  2766.  
  2767.  
  2768.  
  2769.  
  2770. //-----------------------------------------------------------------------------
  2771. // Name: DidcvCalloutSet()
  2772. // Desc: Constructor
  2773. //-----------------------------------------------------------------------------
  2774. DidcvCalloutSet::DidcvCalloutSet()
  2775.     : m_calloutList( DIDCV_DEFAULT_CALLOUT_SET_ARRAY_SIZE ),
  2776.       m_dwSetID( 0 ),
  2777.       m_lpData( NULL )
  2778. { }
  2779.  
  2780.  
  2781.  
  2782.  
  2783. //-----------------------------------------------------------------------------
  2784. // Name: ~DidcvCalloutSet()
  2785. // Desc: destructor
  2786. //-----------------------------------------------------------------------------
  2787. DidcvCalloutSet::~DidcvCalloutSet()
  2788. {
  2789.     CleanUp();
  2790. }
  2791.  
  2792.  
  2793.  
  2794.  
  2795. //-----------------------------------------------------------------------------
  2796. // Name: CleanUp()
  2797. // Desc: resets the object, and frees any resources
  2798. //-----------------------------------------------------------------------------
  2799. void DidcvCalloutSet::CleanUp()
  2800. {
  2801.     // set the array back to default size
  2802.     m_calloutList.SetSize( 0 );
  2803.  
  2804.     // reset the set id
  2805.     m_dwSetID = 0;
  2806.  
  2807.     // reset the data pointer
  2808.     m_lpData = NULL;
  2809. }
  2810.  
  2811.  
  2812.  
  2813.  
  2814. //-----------------------------------------------------------------------------
  2815. // Name: TrimArrays()
  2816. // Desc: resize arrays to free unused memory
  2817. //-----------------------------------------------------------------------------
  2818. void DidcvCalloutSet::TrimArrays()
  2819. {
  2820.     m_calloutList.Trim();
  2821. }
  2822.  
  2823.  
  2824.  
  2825. //-----------------------------------------------------------------------------
  2826. // Name: AddCallout()
  2827. // Desc: adds a callout reference to the set
  2828. //-----------------------------------------------------------------------------
  2829. BOOL DidcvCalloutSet::AddCallout( DidcvCallout* lpCallout )
  2830. {
  2831.     // if NULL, return FALSE
  2832.     if( NULL == lpCallout )
  2833.         return FALSE;
  2834.  
  2835.     // append to list
  2836.     m_calloutList.PushBack( lpCallout );
  2837.  
  2838.     return TRUE;
  2839. }
  2840.  
  2841.  
  2842.  
  2843.  
  2844. //-----------------------------------------------------------------------------
  2845. // Name: Apply()
  2846. // Desc: using a instantiation of DidcvCalloutApplicant, applies it to every
  2847. //       every callout in the group
  2848. //-----------------------------------------------------------------------------
  2849. void DidcvCalloutSet::Apply( DidcvCalloutApplicant* lpCalloutApp )
  2850. {
  2851.     UINT i, size;
  2852.  
  2853.     size = m_calloutList.Size();
  2854.  
  2855.     // loop through entries, and apply each
  2856.     for( i = 0; i < size; i++ )
  2857.     {
  2858.         // if FALSE is returned, then stop
  2859.         if( FALSE == lpCalloutApp->Apply( m_calloutList[i] ) )
  2860.             break;
  2861.     }
  2862. }
  2863.  
  2864.  
  2865.  
  2866.  
  2867. //-----------------------------------------------------------------------------
  2868. // Name: GetInternalArray()
  2869. // Desc: returns a const reference to the array that stores the callout
  2870. //       references
  2871. //-----------------------------------------------------------------------------
  2872. const GwArray <DidcvCallout *> & DidcvCalloutSet::GetInternalArrayRef() const
  2873. {
  2874.     return m_calloutList;
  2875. }
  2876.  
  2877.  
  2878.  
  2879.  
  2880. //-----------------------------------------------------------------------------
  2881. // Name: SetIdentifier()
  2882. // Desc: assigned a unique identifier to the set
  2883. //-----------------------------------------------------------------------------
  2884. void DidcvCalloutSet::SetIdentifier( DWORD dwID )
  2885. {
  2886.     m_dwSetID = dwID;
  2887. }
  2888.  
  2889.  
  2890.  
  2891.  
  2892. //-----------------------------------------------------------------------------
  2893. // Name: GetIdentifier()
  2894. // Desc: returns the identifier associated with this set
  2895. //-----------------------------------------------------------------------------
  2896. DWORD DidcvCalloutSet::GetIdentifier() const
  2897. {
  2898.     return m_dwSetID;
  2899. }
  2900.  
  2901.  
  2902.  
  2903.  
  2904. //-----------------------------------------------------------------------------
  2905. // Name: SetData()
  2906. // Desc: attach a void pointer with this set
  2907. //-----------------------------------------------------------------------------
  2908. void DidcvCalloutSet::SetData( void* lpData )
  2909. {
  2910.     m_lpData = lpData;
  2911. }
  2912.  
  2913.  
  2914.  
  2915.  
  2916. //-----------------------------------------------------------------------------
  2917. // Name: GetData()
  2918. // Desc: returns the data associated with this set
  2919. //-----------------------------------------------------------------------------
  2920. void* DidcvCalloutSet::GetData() const
  2921. {
  2922.     return m_lpData;
  2923. }
  2924.  
  2925.  
  2926.  
  2927.  
  2928. //-----------------------------------------------------------------------------
  2929. // Name: PutLinePoint()
  2930. // Desc: draws a line to a point
  2931. //-----------------------------------------------------------------------------
  2932. void PutLinePoint( HDC hDC, POINT p )
  2933. {
  2934.     MoveToEx( hDC, p.x, p.y, NULL );
  2935.     LineTo( hDC, p.x + 1, p.y );
  2936. }
  2937.  
  2938.  
  2939.  
  2940.  
  2941. //-----------------------------------------------------------------------------
  2942. // Name: SmartSet()
  2943. // Desc: copies valid members of other
  2944. //-----------------------------------------------------------------------------
  2945. void DidcvCalloutState::SmartSet( const DidcvCalloutState* other )
  2946. {
  2947.     if( other->dwFlags & DIDCV_DRAWCALLOUT )
  2948.         bDrawCallout = other->bDrawCallout;
  2949.  
  2950.     if( other->dwFlags & DIDCV_DRAWOVERLAY )
  2951.         bDrawOverlay = other->bDrawOverlay;
  2952.  
  2953.     if( other->dwFlags & DIDCV_DRAWHIGHLIGHT )
  2954.         bDrawHighlight = other->bDrawHighlight;
  2955.  
  2956.     if( other->dwFlags & DIDCV_DRAWEMPTYCALLOUT )
  2957.         bDrawEmptyCallout = other->bDrawEmptyCallout;
  2958.  
  2959.     if( other->dwFlags & DIDCV_DRAWFULLNAME )
  2960.         bDrawFullname = other->bDrawFullname;
  2961. }
  2962.  
  2963.  
  2964.  
  2965.  
  2966. //-----------------------------------------------------------------------------
  2967. // Name: MakeFlag()
  2968. // Desc: makes a DWORD flag
  2969. //-----------------------------------------------------------------------------
  2970. DWORD DidcvCalloutState::MakeFlag() const
  2971. {
  2972.     DWORD dwExtFlags = 0;
  2973.  
  2974.     if( ( dwFlags & DIDCV_DRAWCALLOUT ) && bDrawCallout )
  2975.         dwExtFlags |= DIDCV_DRAWCALLOUT;
  2976.  
  2977.     if( ( dwFlags & DIDCV_DRAWOVERLAY ) && bDrawOverlay )
  2978.         dwExtFlags |= DIDCV_DRAWOVERLAY;
  2979.  
  2980.     if( ( dwFlags & DIDCV_DRAWHIGHLIGHT ) && bDrawHighlight )
  2981.         dwExtFlags |= DIDCV_DRAWHIGHLIGHT;
  2982.  
  2983.     if( ( dwFlags & DIDCV_DRAWEMPTYCALLOUT ) && bDrawEmptyCallout )
  2984.         dwExtFlags |= DIDCV_DRAWEMPTYCALLOUT;
  2985.  
  2986.     if( ( dwFlags & DIDCV_DRAWFULLNAME ) && bDrawFullname )
  2987.         dwExtFlags |= DIDCV_DRAWFULLNAME;
  2988.  
  2989.     return dwExtFlags;
  2990. }
  2991.  
  2992.  
  2993.  
  2994.  
  2995. //-----------------------------------------------------------------------------
  2996. // Name: SetFlag()
  2997. // Desc: given a flag, sets the members
  2998. //-----------------------------------------------------------------------------
  2999. void DidcvCalloutState::SetFlag( DWORD dwExtFlags )
  3000. {
  3001.     dwFlags = DIDCV_ALL_CALLOUT_STATE_SET;
  3002.  
  3003.     bDrawCallout = ( dwExtFlags & DIDCV_DRAWCALLOUT ) != 0;
  3004.     bDrawOverlay = ( dwExtFlags & DIDCV_DRAWOVERLAY ) != 0;
  3005.     bDrawHighlight = ( dwExtFlags & DIDCV_DRAWHIGHLIGHT ) != 0;
  3006.     bDrawEmptyCallout = ( dwExtFlags & DIDCV_DRAWEMPTYCALLOUT ) != 0;
  3007.     bDrawFullname = ( dwExtFlags & DIDCV_DRAWFULLNAME ) != 0;
  3008. }
  3009.  
  3010.  
  3011.  
  3012.  
  3013. //-----------------------------------------------------------------------------
  3014. // Name: DidcvPolyLineArrow()
  3015. // Desc: draws a line using an array of line segments, with optional shadows
  3016. //-----------------------------------------------------------------------------
  3017. void DidcvPolyLineArrow( HDC hDC, const POINT *rgpt, int nPoints, BOOL bDoShadow )
  3018. {
  3019.     int i;
  3020.  
  3021.     if( rgpt == NULL || nPoints < 1 )
  3022.         return;
  3023.  
  3024.     if( nPoints > 1 )
  3025.         for( i = 0; i < nPoints - 1; i++ )
  3026.         {
  3027.             SPOINT a = rgpt[i], b = rgpt[i + 1];
  3028.  
  3029.             if( bDoShadow )
  3030.             {
  3031.                 int rise = abs( b.y - a.y ), run = abs( b.x - a.x );
  3032.                 bool vert = rise > run;
  3033.                 int ord = vert ? 1 : 0;
  3034.                 int nord = vert ? 0 : 1;
  3035.                 
  3036.                 for( int o = -1; o <= 1; o += 2 )
  3037.                 {
  3038.                     SPOINT c( a ), d( b );
  3039.                     c.a[nord] += o;
  3040.                     d.a[nord] += o;
  3041.                     MoveToEx( hDC, c.x, c.y, NULL );
  3042.                     LineTo( hDC, d.x, d.y );
  3043.                 }
  3044.  
  3045.                 bool reverse = a.a[ord] > b.a[ord];
  3046.                 SPOINT e( reverse ? b : a ), f( reverse ? a : b );
  3047.                 e.a[ord] -= 1;
  3048.                 f.a[ord] += 1;
  3049.                 PutLinePoint( hDC, e );
  3050.                 PutLinePoint( hDC, f );
  3051.             }
  3052.             else
  3053.             {
  3054.                 MoveToEx( hDC, a.x, a.y, NULL );
  3055.                 LineTo( hDC, b.x, b.y );
  3056.             }
  3057.         }
  3058.  
  3059.     POINT z = rgpt[nPoints - 1];
  3060.  
  3061.     if( bDoShadow )
  3062.     {
  3063.         POINT pt[5] = {
  3064.             { z.x, z.y + 2 },
  3065.             { z.x + 2, z.y },
  3066.             { z.x, z.y - 2 },
  3067.             { z.x - 2, z.y }, };
  3068.         pt[4] = pt[0];
  3069.         Polyline( hDC, pt, 5 );
  3070.     }
  3071.     else
  3072.     {
  3073.         MoveToEx( hDC, z.x - 1, z.y, NULL );
  3074.         LineTo( hDC, z.x + 2, z.y );
  3075.         MoveToEx( hDC, z.x, z.y - 1, NULL );
  3076.         LineTo( hDC, z.x, z.y + 2 );
  3077.     }
  3078. }
  3079.  
  3080.  
  3081.  
  3082.  
  3083. //-----------------------------------------------------------------------------
  3084. // Name: DidcvCreateFont()
  3085. // Desc: Creates a GDI font object( code adapted from Charles Petzold )
  3086. //-----------------------------------------------------------------------------
  3087. HFONT DidcvCreateFont( HDC hdc, const TCHAR* szFaceName, int iDeciPtHeight, 
  3088.                        int iDeciPtWidth, int iAttributes, BOOL fLogRes)
  3089. {
  3090.      FLOAT      cxDpi, cyDpi ;
  3091.      HFONT      hFont ;
  3092.      LOGFONT    lf ;
  3093.      POINT      pt ;
  3094.      TEXTMETRIC tm ;
  3095.  
  3096.      SaveDC( hdc ) ;
  3097.  
  3098.      SetGraphicsMode( hdc, GM_ADVANCED ) ;
  3099.      ModifyWorldTransform( hdc, NULL, MWT_IDENTITY ) ;
  3100.      SetViewportOrgEx( hdc, 0, 0, NULL ) ;
  3101.      SetWindowOrgEx  ( hdc, 0, 0, NULL ) ;
  3102.  
  3103.      if( fLogRes)
  3104.      {
  3105.           cxDpi =( FLOAT) GetDeviceCaps( hdc, LOGPIXELSX ) ;
  3106.           cyDpi =( FLOAT) GetDeviceCaps( hdc, LOGPIXELSY ) ;
  3107.      }
  3108.      else
  3109.      {
  3110.           cxDpi =( FLOAT)( 25.4 * GetDeviceCaps( hdc, HORZRES ) /
  3111.                                   GetDeviceCaps( hdc, HORZSIZE ) ) ;
  3112.  
  3113.           cyDpi =( FLOAT)( 25.4 * GetDeviceCaps( hdc, VERTRES ) /
  3114.                                   GetDeviceCaps( hdc, VERTSIZE ) ) ;
  3115.      }
  3116.  
  3117.      pt.x =( int)( iDeciPtWidth  * cxDpi / 72 ) ;
  3118.      pt.y =( int)( iDeciPtHeight * cyDpi / 72 ) ;
  3119.  
  3120.      DPtoLP( hdc, &pt, 1) ;
  3121.  
  3122.      lf.lfHeight         = -( int)( fabs( (float)pt.y) / 10.0 + 0.5 ) ;
  3123.      lf.lfWidth          = 0 ;
  3124.      lf.lfEscapement     = 0 ;
  3125.      lf.lfOrientation    = 0 ;
  3126.      lf.lfWeight         = iAttributes & DIDCV_FONT_BOLD      ? 700 : 0 ;
  3127.      lf.lfItalic         = iAttributes & DIDCV_FONT_ITALIC    ?   1 : 0 ;
  3128.      lf.lfUnderline      = iAttributes & DIDCV_FONT_UNDERLINE ?   1 : 0 ;
  3129.      lf.lfStrikeOut      = iAttributes & DIDCV_FONT_STRIKEOUT ?   1 : 0 ;
  3130.      lf.lfCharSet        = 0 ;
  3131.      lf.lfOutPrecision   = 0 ;
  3132.      lf.lfClipPrecision  = 0 ;
  3133.      lf.lfQuality        = 0 ;
  3134.      lf.lfPitchAndFamily = 0 ;
  3135.  
  3136.      _tcscpy( lf.lfFaceName, szFaceName ) ;
  3137.  
  3138.      hFont = CreateFontIndirect( &lf ) ;
  3139.  
  3140.      if( iDeciPtWidth != 0 )
  3141.      {
  3142.           hFont =( HFONT ) SelectObject( hdc, hFont );
  3143.           GetTextMetrics( hdc, &tm );
  3144.           DeleteObject( SelectObject( hdc, hFont ) ) ;
  3145.           lf.lfWidth =( int)( tm.tmAveCharWidth * fabs((float) pt.x ) / 
  3146.                               fabs( (float)pt.y ) + 0.5 ) ;
  3147.  
  3148.           hFont = CreateFontIndirect( &lf ) ;
  3149.      }
  3150.  
  3151.      RestoreDC( hdc, -1) ;
  3152.  
  3153.      return hFont ;
  3154. }
  3155.  
  3156.  
  3157.  
  3158.  
  3159. //-----------------------------------------------------------------------------
  3160. // Name: DidcvView()
  3161. // Desc: Constructor
  3162. //-----------------------------------------------------------------------------
  3163. DidcvView::DidcvView()
  3164.     : m_nOffset( DIDCV_INVALID_ID ),
  3165.       m_nID( DIDCV_INVALID_ID )
  3166. { }
  3167.  
  3168.  
  3169.  
  3170.  
  3171. //-----------------------------------------------------------------------------
  3172. // Name: SetOffset()
  3173. // Desc: sets the offset from the original index returned by GetImage
  3174. //-----------------------------------------------------------------------------
  3175. void DidcvView::SetOffset( INT nOffset )
  3176. {
  3177.     m_nOffset = nOffset;
  3178. }
  3179.  
  3180.  
  3181.  
  3182.  
  3183. //-----------------------------------------------------------------------------
  3184. // Name: GetOffset()
  3185. // Desc: returns the original GetImage offset
  3186. //-----------------------------------------------------------------------------
  3187. INT DidcvView::GetOffset() const
  3188. {
  3189.     return m_nOffset;
  3190. }
  3191.  
  3192.  
  3193.  
  3194.  
  3195. //-----------------------------------------------------------------------------
  3196. // Name: SetID()
  3197. // Desc: sets the internally assigned unique identifier
  3198. //-----------------------------------------------------------------------------
  3199. void DidcvView::SetID( INT nID )
  3200. {
  3201.     m_nID = nID;
  3202. }
  3203.  
  3204.  
  3205.  
  3206.  
  3207. //-----------------------------------------------------------------------------
  3208. // Name: GetID()
  3209. // Desc: returns the internally assigned unique identifier
  3210. //-----------------------------------------------------------------------------
  3211. INT DidcvView::GetID() const
  3212. {
  3213.     return m_nID;
  3214. }
  3215.  
  3216.  
  3217.  
  3218.  
  3219. //-----------------------------------------------------------------------------
  3220. // Name: Create()
  3221. // Desc: static function to the instantiate a DidcvView object from filename
  3222. //-----------------------------------------------------------------------------
  3223. DidcvBitmapView* DidcvBitmapView::Create( LPCTSTR tszFilename, DWORD dwFlags )
  3224. {
  3225.     DidcvBitmapView* lpView;
  3226.     DidcvBitmap* lpBm;
  3227.  
  3228.     lpView = new DidcvBitmapView();
  3229.     if( NULL == lpView )
  3230.         return NULL;
  3231.  
  3232.     lpBm = DidcvBitmap::Create( tszFilename );
  3233.     if( NULL == lpBm )
  3234.     {
  3235.         delete lpView;
  3236.         return NULL;
  3237.     }
  3238.  
  3239.     lpView->m_lpBitmap = lpBm ;
  3240.  
  3241.     return lpView;
  3242. }
  3243.  
  3244.  
  3245.  
  3246.  
  3247. //-----------------------------------------------------------------------------
  3248. // Name: DidcvBitmapView()
  3249. // Desc: constructor
  3250. //-----------------------------------------------------------------------------
  3251. DidcvBitmapView::DidcvBitmapView()
  3252.     : DidcvView(),
  3253.       m_lpBitmap( NULL )
  3254. { }
  3255.  
  3256.  
  3257.  
  3258.  
  3259. //-----------------------------------------------------------------------------
  3260. // Name: ~DidcvBitmapView()
  3261. // Desc: Destructor
  3262. //-----------------------------------------------------------------------------
  3263. DidcvBitmapView::~DidcvBitmapView()
  3264. {
  3265.     SAFE_DELETE( m_lpBitmap );
  3266. }
  3267.  
  3268.  
  3269.  
  3270.  
  3271. //-----------------------------------------------------------------------------
  3272. // Name: GetViewSize()
  3273. // Desc: returns the size of the view image
  3274. //-----------------------------------------------------------------------------
  3275. BOOL DidcvBitmapView::GetViewSize( SIZE* lpSize ) const
  3276. {
  3277.     if( NULL == lpSize )
  3278.         return FALSE;
  3279.  
  3280.     if( NULL == m_lpBitmap )
  3281.     {
  3282.         lpSize->cx = 0;
  3283.         lpSize->cy = 0;
  3284.  
  3285.         return FALSE;
  3286.     }
  3287.  
  3288.     return m_lpBitmap->GetSize( lpSize );
  3289. }
  3290.  
  3291.  
  3292.  
  3293.  
  3294. //-----------------------------------------------------------------------------
  3295. // Name: Render()
  3296. // Desc: renders the view to a HDC
  3297. //-----------------------------------------------------------------------------
  3298. void DidcvBitmapView::Render( HDC hdc, VOID* lpBits, INT width, INT height, 
  3299.                               const POINT* ptOrigin )
  3300. {
  3301.     BOOL res = FALSE;
  3302.  
  3303.     // nothing to draw
  3304.     if( NULL == m_lpBitmap )
  3305.         return;
  3306.  
  3307.     // alpha blend by hand
  3308.     if( lpBits )
  3309.         res = m_lpBitmap->Blend( lpBits, ptOrigin->x, ptOrigin->y, width, height );
  3310.  
  3311.     if( !res )
  3312.     {
  3313.         // try alpha blending with hDC
  3314.         res = m_lpBitmap->Blend( hdc, 0, 0 );
  3315.  
  3316.         if( !res )
  3317.             // no alpha blending available - just draw
  3318.             m_lpBitmap->Draw( hdc, 0 , 0 );
  3319.     }
  3320. }
  3321.  
  3322.  
  3323.  
  3324.  
  3325. //-----------------------------------------------------------------------------
  3326. // Name: DidcvCustomView()
  3327. // Desc: constructor
  3328. //-----------------------------------------------------------------------------
  3329. DidcvCustomView::DidcvCustomView( const DidcvCustomViewInfo* lpInfo, 
  3330.                                   DWORD dwStartIndex, DWORD dwEndIndex )
  3331.     : m_lpCustomViewInfoRef( lpInfo ),
  3332.       m_dwStartIndex( dwStartIndex ),
  3333.       m_dwEndIndex( dwEndIndex )
  3334. { }
  3335.  
  3336.  
  3337.  
  3338.  
  3339. //-----------------------------------------------------------------------------
  3340. // Name: GetViewSize()
  3341. // Desc: retrieves the size of the view
  3342. //-----------------------------------------------------------------------------
  3343. BOOL DidcvCustomView::GetViewSize( SIZE* lpSize ) const
  3344. {
  3345.     if( NULL == lpSize )
  3346.         return FALSE;
  3347.  
  3348.     lpSize->cx = DIDCV_CUSTOM_VIEW_WIDTH;
  3349.     lpSize->cy = DIDCV_CUSTOM_VIEW_HEIGHT;
  3350.  
  3351.     return TRUE;
  3352. }
  3353.  
  3354.  
  3355.  
  3356. #define DIDCV_CUSTOM_BORDER_WIDTH       8
  3357. #define DIDCV_CUSTOM_BOX_WIDTH          90
  3358. #define DIDCV_CUSTOM_BOX_CONTROL_WIDTH  70
  3359. #define DIDCV_CUSTOM_BOX_HEIGHT         24
  3360. #define DIDCV_CUSTOM_LINE_BORDER        8
  3361. #define DIDCV_CUSTOM_LINE_BOX_WIDTH     32
  3362. #define DIDCV_CUSTOM_VIEWS_PER_COL     ( ( DIDCV_CUSTOM_VIEW_HEIGHT -( 2 * DIDCV_CUSTOM_BORDER_WIDTH ) ) / DIDCV_CUSTOM_BOX_HEIGHT )
  3363. //-----------------------------------------------------------------------------
  3364. // Name: Render()
  3365. // Desc: draws the custom view
  3366. //-----------------------------------------------------------------------------
  3367. VOID DidcvCustomView::Render( HDC hdc, VOID* lpBits, INT width, INT height, 
  3368.                               const POINT* pptOrigin )
  3369. {
  3370.     TCHAR tszBuffer[MAX_PATH];
  3371.     DWORD dwTextFlags = DT_WORDBREAK | DT_NOPREFIX | DT_END_ELLIPSIS 
  3372.                       | DT_EDITCONTROL | DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
  3373.     RECT rect;
  3374.     DWORD i;
  3375.  
  3376.     if( NULL == m_lpCustomViewInfoRef )
  3377.         return;
  3378.  
  3379.     for( i = m_dwStartIndex; i <= m_dwEndIndex; i++ )
  3380.     {
  3381.         // calculate coordinates based on the index
  3382.         CalcCoordinates( i, &rect );
  3383.         // copy the callout name into the buffer
  3384.         _tcscpy( tszBuffer, m_lpCustomViewInfoRef->rgObjData[i]->tszName );
  3385.         // draw the text
  3386.         DrawText( hdc, tszBuffer, -1,( LPRECT ) &rect, dwTextFlags );
  3387.     }
  3388. }
  3389.  
  3390.  
  3391.  
  3392.  
  3393. //-----------------------------------------------------------------------------
  3394. // Name: CalcCoordinates()
  3395. // Desc: calculate coordinates for control string
  3396. //-----------------------------------------------------------------------------
  3397. void DidcvCustomView::CalcCoordinates( DWORD dwIndex, LPRECT lpRect )
  3398. {
  3399.     POINT ptStart;
  3400.  
  3401.     // mod the index
  3402.     dwIndex = dwIndex % ( DIDCV_CUSTOM_VIEWS_PER_COL* 2 );
  3403.  
  3404.     // start at the top left
  3405.     ptStart.x = DIDCV_CUSTOM_BORDER_WIDTH;
  3406.     if( dwIndex >= DIDCV_CUSTOM_VIEWS_PER_COL )
  3407.     {
  3408.         // shift into the right column
  3409.         ptStart.x += DIDCV_CUSTOM_VIEW_WIDTH / 2;
  3410.         dwIndex -= DIDCV_CUSTOM_VIEWS_PER_COL;
  3411.     }
  3412.     ptStart.y = DIDCV_CUSTOM_BORDER_WIDTH + ( dwIndex* DIDCV_CUSTOM_BOX_HEIGHT );
  3413.  
  3414.     // set the coordinate
  3415.     lpRect->left = ptStart.x;
  3416.     lpRect->top = ptStart.y;
  3417.     lpRect->right = lpRect->left + DIDCV_CUSTOM_BOX_CONTROL_WIDTH;
  3418.     lpRect->bottom = lpRect->top + DIDCV_CUSTOM_BOX_HEIGHT;
  3419. }
  3420.  
  3421.  
  3422.  
  3423.  
  3424. //-----------------------------------------------------------------------------
  3425. // Name: Create()
  3426. // Desc: static function to instantiate a view
  3427. //-----------------------------------------------------------------------------
  3428. DidcvCustomView* DidcvCustomView::Create( const DidcvCustomViewInfo* lpInfo, 
  3429.                                           DWORD dwStartIndex, DWORD* lpFinishIndex )
  3430. {
  3431.     DWORD dwIndex;
  3432.  
  3433.     if( dwStartIndex >= lpInfo->dwSize )
  3434.         return NULL;
  3435.  
  3436.     // calculate how many can fit
  3437.     dwIndex = DIDCV_CUSTOM_VIEWS_PER_COL;
  3438.     dwIndex *= 2;
  3439.     dwIndex += dwStartIndex;
  3440.     dwIndex --;
  3441.     
  3442.     if( dwIndex >= lpInfo->dwSize )
  3443.         dwIndex = lpInfo->dwSize - 1;
  3444.  
  3445.     if( lpFinishIndex )
  3446.         *lpFinishIndex = dwIndex;
  3447.  
  3448.     return new DidcvCustomView( lpInfo, dwStartIndex, dwIndex );
  3449. }
  3450.  
  3451.  
  3452.  
  3453.  
  3454. //-----------------------------------------------------------------------------
  3455. // Name: CalcNumViews()
  3456. // Desc: calculates the number of views from a total count of controls
  3457. //-----------------------------------------------------------------------------
  3458. DWORD DidcvCustomView::CalcNumViews( DWORD dwCount )
  3459. {
  3460.     DWORD dwIndex;
  3461.     DWORD result;
  3462.  
  3463.     dwIndex = DIDCV_CUSTOM_VIEWS_PER_COL;
  3464.     dwIndex *= 2;
  3465.  
  3466.     result = dwCount / dwIndex +( dwCount % dwIndex ? 1 : 0 );
  3467.  
  3468.     return result;
  3469. }
  3470.  
  3471.  
  3472.  
  3473.  
  3474. //-----------------------------------------------------------------------------
  3475. // Name: CalcImageInfo()
  3476. // Desc: calculates the image info for a custom control
  3477. //-----------------------------------------------------------------------------
  3478. BOOL DidcvCustomView::CalcImageInfo( DWORD index, LPRECT rcOverlay, 
  3479.                                      LPDWORD dwNumPoints, LPPOINT rgptCalloutLine, 
  3480.                                      LPRECT rcCalloutRect )
  3481. {
  3482.     POINT ptStart;
  3483.  
  3484.     // mod the index
  3485.     index = index %( DIDCV_CUSTOM_VIEWS_PER_COL* 2 );
  3486.  
  3487.     ptStart.x = DIDCV_CUSTOM_BORDER_WIDTH + DIDCV_CUSTOM_BOX_CONTROL_WIDTH;
  3488.     if( index >= DIDCV_CUSTOM_VIEWS_PER_COL )
  3489.     {
  3490.         ptStart.x += DIDCV_CUSTOM_VIEW_WIDTH / 2;
  3491.         index -= DIDCV_CUSTOM_VIEWS_PER_COL;
  3492.     }
  3493.     ptStart.y = DIDCV_CUSTOM_BORDER_WIDTH +( index * DIDCV_CUSTOM_BOX_HEIGHT );
  3494.  
  3495.     // do nothing with the overlay rect at this point
  3496.     ZeroMemory( rcOverlay, sizeof( RECT ) );
  3497.     
  3498.     *dwNumPoints = 2;
  3499.     rgptCalloutLine[1].x = ptStart.x + DIDCV_CUSTOM_LINE_BORDER;
  3500.     rgptCalloutLine[1].y = ptStart.y +( DIDCV_CUSTOM_BOX_HEIGHT / 2 );
  3501.     rgptCalloutLine[0].x = rgptCalloutLine[1].x + DIDCV_CUSTOM_LINE_BOX_WIDTH - 
  3502.                            2 * DIDCV_CUSTOM_LINE_BORDER;
  3503.     rgptCalloutLine[0].y = rgptCalloutLine[1].y;
  3504.     
  3505.     rcCalloutRect->left = ptStart.x + DIDCV_CUSTOM_LINE_BOX_WIDTH;
  3506.     rcCalloutRect->top = ptStart.y;
  3507.     rcCalloutRect->right = rcCalloutRect->left + DIDCV_CUSTOM_BOX_WIDTH;
  3508.     rcCalloutRect->bottom = rcCalloutRect->top + DIDCV_CUSTOM_BOX_HEIGHT;
  3509.  
  3510.     return TRUE;
  3511. }
  3512.  
  3513.  
  3514.  
  3515.  
  3516. //-----------------------------------------------------------------------------
  3517. // Name: DidcvViewManager()
  3518. // Desc: constructor
  3519. //-----------------------------------------------------------------------------
  3520. DidcvViewManager::DidcvViewManager()
  3521.     : m_ppViewTable( NULL ),
  3522.       m_capacity( 0 ),
  3523.       m_size( 0 )
  3524. {
  3525.     // initialized
  3526. }
  3527.  
  3528.  
  3529.  
  3530.  
  3531. //-----------------------------------------------------------------------------
  3532. // Name: ~DidcvViewManager()
  3533. // Desc: destructor
  3534. //-----------------------------------------------------------------------------
  3535. DidcvViewManager::~DidcvViewManager()
  3536. {
  3537.     CleanUp();
  3538. }
  3539.  
  3540.  
  3541.  
  3542.  
  3543. //-----------------------------------------------------------------------------
  3544. // Name: SetSize()
  3545. // Desc: sets the capacity of the view manager
  3546. //-----------------------------------------------------------------------------
  3547. BOOL DidcvViewManager::SetCapacity( UINT uCapacity, BOOL bDeleteContent )
  3548. {
  3549.     if( m_ppViewTable )
  3550.     {
  3551.         if( bDeleteContent )
  3552.             CleanUp();
  3553.         else
  3554.             free( m_ppViewTable );
  3555.     }
  3556.  
  3557.     m_capacity = uCapacity;
  3558.     m_size = 0;
  3559.     m_ppViewTable =( DidcvView ** ) malloc( uCapacity * sizeof( DidcvView* ) );
  3560.  
  3561.     if( NULL == m_ppViewTable )
  3562.     {
  3563.         m_capacity = 0;
  3564.         return FALSE;
  3565.     }
  3566.  
  3567.     return TRUE;
  3568. }
  3569.  
  3570.  
  3571.  
  3572.  
  3573. //-----------------------------------------------------------------------------
  3574. // Name: CleanUp()
  3575. // Desc: frees the table and the contents of the table
  3576. //-----------------------------------------------------------------------------
  3577. void DidcvViewManager::CleanUp()
  3578. {
  3579.     UINT i;
  3580.  
  3581.     if( m_ppViewTable )
  3582.     {
  3583.         // free the entries
  3584.         for( i = 0; i < m_size ; i++ )
  3585.             if( m_ppViewTable [i] )
  3586.                 delete m_ppViewTable [i];
  3587.  
  3588.         // free the table
  3589.         free( m_ppViewTable );
  3590.         m_ppViewTable = NULL;
  3591.     }
  3592. }
  3593.  
  3594.  
  3595.  
  3596.  
  3597. //-----------------------------------------------------------------------------
  3598. // Name: AddImage()
  3599. // Desc: adds a DidcvView to the to be stored and managed
  3600. //-----------------------------------------------------------------------------
  3601. BOOL DidcvViewManager::AddImage( DidcvView* lpView, INT nOffset )
  3602. {
  3603.     // save the offset value in the View object
  3604.     lpView->SetOffset( nOffset );
  3605.  
  3606.     // try to allocate the first free entry
  3607.     if( m_size >= m_capacity )
  3608.     {
  3609.         lpView->SetID( DIDCV_INVALID_ID );
  3610.         return FALSE;
  3611.     }
  3612.  
  3613.     m_ppViewTable [m_size] = lpView;
  3614.  
  3615.     // save the table entry as the unique view id
  3616.     lpView->SetID( ( INT )m_size );
  3617.  
  3618.     m_size ++;
  3619.  
  3620.     return TRUE;
  3621. }
  3622.  
  3623.  
  3624.  
  3625.  
  3626. //-----------------------------------------------------------------------------
  3627. // Name: GetImage()
  3628. // Desc: returns the DidcvView for a given internal identifier
  3629. //-----------------------------------------------------------------------------
  3630. DidcvView* DidcvViewManager::GetImage( INT nID )
  3631. {
  3632.     // make sure is within bounds
  3633.     if( nID < 0 ||( UINT ) nID >= m_capacity )
  3634.         return NULL;
  3635.  
  3636.     // return the view object in the table
  3637.     return m_ppViewTable[ nID ];
  3638. }
  3639.  
  3640.  
  3641.  
  3642.  
  3643. //-----------------------------------------------------------------------------
  3644. // Name: GetImageByOffset()
  3645. // Desc: returns the DidcvView for a given offset from the original GetImage
  3646. //       image info array
  3647. //-----------------------------------------------------------------------------
  3648. DidcvView* DidcvViewManager::GetImageByOffset( INT nOffset )
  3649. {
  3650.     DWORD i;
  3651.     if( nOffset < 0 )
  3652.         return NULL;
  3653.  
  3654.     // look for the offset in the entry
  3655.     for( i = 0; i < m_size; i++ )
  3656.         if( m_ppViewTable[i] &&( m_ppViewTable[i]->GetOffset() == nOffset ) )
  3657.             return m_ppViewTable[i];
  3658.  
  3659.     return NULL;
  3660. }
  3661.  
  3662.  
  3663.  
  3664.  
  3665. //-----------------------------------------------------------------------------
  3666. // Name: GetNumViews()
  3667. // Desc: returns the number of images currently stored in the view manager
  3668. //-----------------------------------------------------------------------------
  3669. UINT DidcvViewManager::GetNumViews() const
  3670. {
  3671.     return m_size;
  3672. }
  3673.  
  3674.  
  3675.  
  3676.  
  3677. //-----------------------------------------------------------------------------
  3678. // Name: DidcvDirect3DSurface8Clone
  3679. // Desc: a clone surface
  3680. //-----------------------------------------------------------------------------
  3681. class DidcvDirect3DSurface8Clone : public IUnknown
  3682. {
  3683. private:
  3684.     int m_iRefCount;
  3685.     BYTE *m_pData;
  3686.     D3DSURFACE_DESC m_Desc;
  3687.  
  3688. public:
  3689.     DidcvDirect3DSurface8Clone() : m_pData( NULL ), m_iRefCount( 1 ) { }
  3690.     ~DidcvDirect3DSurface8Clone() { delete[] m_pData; }
  3691.  
  3692. public:     
  3693.     // IUnknown methods
  3694.     STDMETHOD( QueryInterface )( REFIID  riid, VOID  **ppvObj ) { return E_NOINTERFACE; }
  3695.     STDMETHOD_( ULONG,AddRef )() { return ++m_iRefCount; }
  3696.     STDMETHOD_( ULONG,Release )()
  3697.     {
  3698.         if( !--m_iRefCount )
  3699.         {
  3700.             delete this;
  3701.             return 0;
  3702.         }
  3703.         return m_iRefCount;
  3704.     }
  3705.  
  3706.     // IBuffer methods
  3707.     STDMETHOD( SetPrivateData )( REFGUID riid, CONST VOID *pvData, DWORD cbData, DWORD   dwFlags ) { return S_OK; }
  3708.     STDMETHOD( GetPrivateData )( REFGUID riid, VOID* pvData, DWORD  *pcbData ) { return S_OK; }
  3709.     STDMETHOD( FreePrivateData )( REFGUID riid ) { return S_OK; }
  3710.     STDMETHOD( GetContainer )( REFIID riid, void **ppContainer ) { return S_OK; }
  3711.     STDMETHOD( GetDevice )( IDirect3DDevice8 **ppDevice ) { return S_OK; }
  3712.  
  3713.     // IDirect3DSurface8 methods
  3714.     STDMETHOD_( D3DSURFACE_DESC, GetDesc )() { return m_Desc; }
  3715.     STDMETHOD( LockRect )( D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD dwFlags )
  3716.     {
  3717.         // Assume the entire surface is being locked.
  3718.         pLockedRect->Pitch = m_Desc.Width * 4;
  3719.         pLockedRect->pBits = m_pData;
  3720.         return S_OK;
  3721.     }
  3722.     STDMETHOD( UnlockRect )() { return S_OK; }
  3723.     BOOL Create( int iWidth, int iHeight )
  3724.     {
  3725.         m_pData = new BYTE[iWidth * iHeight * 4];
  3726.         if( !m_pData ) return FALSE;
  3727.  
  3728.         m_Desc.Format = D3DFMT_A8R8G8B8;
  3729.         m_Desc.Type = D3DRTYPE_SURFACE;
  3730.         m_Desc.Usage = 0;
  3731.         m_Desc.Pool = D3DPOOL_SYSTEMMEM;
  3732.         m_Desc.Size = iWidth * iHeight * 4;
  3733.         m_Desc.MultiSampleType = D3DMULTISAMPLE_NONE;
  3734.         m_Desc.Width = iWidth;
  3735.         m_Desc.Height = iHeight;
  3736.         return TRUE;
  3737.     }
  3738. };
  3739.  
  3740.  
  3741.  
  3742.  
  3743. //-----------------------------------------------------------------------------
  3744. // Name: GetCloneSurface()
  3745. // Desc: 
  3746. //-----------------------------------------------------------------------------
  3747. IDirect3DSurface8* GetCloneSurface( int iWidth, int iHeight )
  3748. {
  3749.     DidcvDirect3DSurface8Clone *pSurf = new DidcvDirect3DSurface8Clone;
  3750.  
  3751.     if( !pSurf ) return NULL;
  3752.     if( !pSurf->Create( iWidth, iHeight ) )
  3753.     {
  3754.         delete pSurf;
  3755.         return NULL;
  3756.     }
  3757.  
  3758.     return( IDirect3DSurface8* )pSurf;
  3759. }
  3760.  
  3761.  
  3762.  
  3763.  
  3764. //-----------------------------------------------------------------------------
  3765. // Name: CreateViaD3Dx()
  3766. // Desc: loads a bitmap from .BMP or .PNG using D3Dx
  3767. //-----------------------------------------------------------------------------
  3768. DidcvBitmap* DidcvBitmap::CreateViaD3dx( LPCTSTR tszFileName )
  3769. {
  3770.     LPDIRECT3DSURFACE8 lpSurf = NULL;
  3771.     HRESULT hr;
  3772.     D3DXIMAGE_INFO d3dxImgInfo;
  3773.     DidcvBitmap* pbm = NULL;
  3774.     BYTE* pbData = NULL;
  3775.     UINT y, i;
  3776.     UINT width, height, pitch;
  3777.  
  3778.     lpSurf = GetCloneSurface( DIDCV_MAX_IMAGE_WIDTH, DIDCV_MAX_IMAGE_HEIGHT );
  3779.     if( lpSurf )
  3780.     {
  3781.         if( FAILED( D3DXLoadSurfaceFromFile( lpSurf, NULL, NULL, tszFileName, 
  3782.                                 NULL, D3DX_FILTER_NONE, 0, &d3dxImgInfo ) ) )
  3783.             goto label_release;
  3784.     }
  3785.  
  3786.     width = d3dxImgInfo.Width;
  3787.     height = d3dxImgInfo.Height;
  3788.     pitch = width * 4;
  3789.  
  3790.     // Create a bitmap and copy the texture content onto it.
  3791.     LPBYTE pDIBBits;
  3792.     HBITMAP hDIB;
  3793.     BITMAPINFO bmi;
  3794.     bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader );
  3795.     bmi.bmiHeader.biWidth = width;
  3796.     bmi.bmiHeader.biHeight = height;
  3797.     bmi.bmiHeader.biPlanes = 1;
  3798.     bmi.bmiHeader.biBitCount = 32;
  3799.     bmi.bmiHeader.biCompression = BI_RGB;
  3800.     bmi.bmiHeader.biSizeImage = 0;
  3801.     bmi.bmiHeader.biXPelsPerMeter = 0;
  3802.     bmi.bmiHeader.biYPelsPerMeter = 0;
  3803.     bmi.bmiHeader.biClrUsed = 0;
  3804.     bmi.bmiHeader.biClrImportant = 0;
  3805.     hDIB = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS,( LPVOID* )&pDIBBits, NULL, 0 );
  3806.     if( !hDIB )
  3807.          goto label_release;
  3808.  
  3809.     // Lock the surface
  3810.     D3DLOCKED_RECT D3DRect;
  3811.     hr = lpSurf->LockRect( &D3DRect, NULL, 0 );
  3812.     if( FAILED( hr ) )
  3813.          goto label_release;
  3814.     
  3815.     // Copy the bits
  3816.     // Note that the image is reversed in Y direction, so we need to re-reverse it.
  3817.     for( y = 0; y < height; ++y )
  3818.         CopyMemory( pDIBBits +( y * pitch ),( LPBYTE ) D3DRect.pBits + 
  3819.                     ( ( height - y ) * D3DRect.Pitch ), width * 4 );  // 512 pixels per line, 32 bits per pixel
  3820.  
  3821.     // process the pixel data based on alpha for blending
  3822.     pbData =( LPBYTE ) pDIBBits;
  3823.     for( i = 0; i < width * height; ++i )
  3824.     {
  3825.         BYTE bAlpha = pbData[i * 4 + 3];
  3826.         pbData[i * 4] = pbData[i * 4] * bAlpha / 255;
  3827.         pbData[i * 4 + 1] = pbData[i * 4 + 1] * bAlpha / 255;
  3828.         pbData[i * 4 + 2] = pbData[i * 4 + 2] * bAlpha / 255;
  3829.     }
  3830.  
  3831.     // Unlock
  3832.     lpSurf->UnlockRect();
  3833.  
  3834.     pbm = new DidcvBitmap;
  3835.     if( NULL == pbm )
  3836.         goto label_release;
  3837.  
  3838.     pbm->m_hbitmap = hDIB;
  3839.     pbm->m_lpBits = pDIBBits;
  3840.     pbm->FigureSize();
  3841.  
  3842.  
  3843. label_release:
  3844.  
  3845.     if( lpSurf ) lpSurf->Release();
  3846.     if( !pbm && hDIB )
  3847.         DeleteObject( hDIB );
  3848.  
  3849.     return pbm;
  3850. }
  3851.