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

📄 ddraw02dlg.cpp

📁 《Visual C 6.0高级编程技术——DirectX篇》程序源代码
💻 CPP
字号:
// DDraw02Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "DDraw02.h"
#include "DDraw02Dlg.h"

// Inserted code begin
#define INITGUID

#include <windowsx.h>
#include <stdio.h>
#include "ddraw.h"

// Forward function prototypes of callback functions
BOOL WINAPI EnumerateDirectDrawDeviceCallback( GUID FAR *pGUID, LPSTR pDriverDescription, LPSTR pDriverName, LPVOID pContext );
BOOL WINAPI EnumerateDisplayModesCallback( LPDDSURFACEDESC pDDSDesc, LPVOID pContext );
// Inserted code end

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDDraw02Dlg dialog

CDDraw02Dlg::CDDraw02Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDDraw02Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDDraw02Dlg)
	m_nDevice = -1;
	m_strModes = _T("");
	//}}AFX_DATA_INIT

// Inserted code begin
  m_pDD = NULL;
  m_pDD2 = NULL;
// Inserted code end

	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDDraw02Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDDraw02Dlg)
	DDX_Control(pDX, IDC_SET_MODES, m_ctlButtonSetModes);
	DDX_Control(pDX, IDC_ENUMERATE_MODES, m_ctlButtonEnumerateModes);
	DDX_Control(pDX, IDC_MODES, m_ctlListBoxModes);
	DDX_Control(pDX, IDC_DEVICE, m_ctlComboBoxDevice);
	DDX_CBIndex(pDX, IDC_DEVICE, m_nDevice);
	DDX_LBString(pDX, IDC_MODES, m_strModes);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDDraw02Dlg, CDialog)
	//{{AFX_MSG_MAP(CDDraw02Dlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_ENUMERATE_MODES, OnEnumerateModes)
	ON_BN_CLICKED(IDC_SET_MODES, OnSetModes)
	ON_WM_DELETEITEM()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDDraw02Dlg message handlers

BOOL CDDraw02Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
// Inserted code begin
  // Enumerate the DirectDraw devices.
  if( FAILED( DirectDrawEnumerate( ( LPDDENUMCALLBACK )EnumerateDirectDrawDeviceCallback, ( LPVOID )&m_ctlComboBoxDevice ) ) )
	{
    OutputDebugString( "Couldn't enumerate devices.\n" );
    return FALSE;
  }
	m_ctlComboBoxDevice.SetCurSel( 0 );
// Inserted code end

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDDraw02Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDDraw02Dlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDDraw02Dlg::OnQueryDragIcon()
{
	return ( HCURSOR )m_hIcon;
}

void CDDraw02Dlg::OnEnumerateModes() 
{
	// TODO: Add your control notification handler code here
// Inserted code begin
  LPDDSURFACEDESC pDesc = NULL;
  LPGUID pDevice = NULL;

  // Get the surface description referenced in the list box.
  int nIndex = m_ctlComboBoxDevice.GetCurSel();
  // Get the unique id for the selected device. If it's
	// the primary device, the id will be NULL.
	pDevice = ( LPGUID )( m_ctlComboBoxDevice.GetItemData( nIndex ) );

  // Create the DirectDraw object.
  if( FAILED( ::DirectDrawCreate( pDevice, &m_pDD, NULL ) ) )
	{
    DestroyDirectDrawObjects();
    OutputDebugString( "Couldn't create DirectDraw object.\n" );
    SendMessage( WM_CLOSE, 0, 0 ); // EndDialog( hwnd, FALSE );
		return;
  }
  
	// Query the appropriate interface.
  if( FAILED( m_pDD->QueryInterface( IID_IDirectDraw2, ( LPVOID * )&m_pDD2 ) ) )
	{
    DestroyDirectDrawObjects();
    OutputDebugString( "Couldn't query the interface.\n" );
    SendMessage( WM_CLOSE, 0, 0 ); // EndDialog( hwnd, FALSE );
		return;
  }

	// Release the interface we don't need.
  m_pDD->Release();

  // Set the cooperative level. Give us the
  // ability to change the bit depth, and don't
  // fiddle with our window.
	HWND hWnd = ( HWND )( this->GetSafeHwnd() );
  if( FAILED( m_pDD2->SetCooperativeLevel( hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_NOWINDOWCHANGES ) ) )
	{
    DestroyDirectDrawObjects();
    OutputDebugString( "Couldn't set cooperative level.\n" );
    SendMessage( WM_CLOSE, 0, 0 ); // EndDialog( hwnd, FALSE );
		return;
  }

  // Enumerate the available modes.
  if( FAILED( m_pDD2->EnumDisplayModes( 0, NULL, ( LPVOID )&m_ctlListBoxModes, ( LPDDENUMMODESCALLBACK )EnumerateDisplayModesCallback ) ) )
	{
    DestroyDirectDrawObjects();
    OutputDebugString( "Couldn't enumerate modes.\n" );
    SendMessage( WM_CLOSE, 0, 0 ); // EndDialog( hwnd, FALSE );
		return;
  }
  m_ctlListBoxModes.SetCurSel( 0 );

  m_ctlButtonEnumerateModes.EnableWindow( FALSE );
  m_ctlButtonSetModes.EnableWindow( TRUE );
// Inserted code end
}

void CDDraw02Dlg::OnSetModes() 
{
	// TODO: Add your control notification handler code here
// Inserted code begin
  LPDDSURFACEDESC pDesc = NULL;

  // Get the surface description referenced in the list box.
  int nIndex = m_ctlListBoxModes.GetCurSel();
	pDesc = ( LPDDSURFACEDESC )( m_ctlListBoxModes.GetItemData( nIndex ) );

  // Set the new display mode.
  if( FAILED( m_pDD2->SetDisplayMode( pDesc->dwWidth, pDesc->dwHeight, pDesc->ddpfPixelFormat.dwRGBBitCount, pDesc->dwRefreshRate, 0 ) ) )
	{
    DestroyDirectDrawObjects();
    OutputDebugString( "Couldn't set the mode.\n" );
    SendMessage( WM_CLOSE, 0, 0 ); // EndDialog( hwnd, FALSE );
		return;
  }
// Inserted code end
}

void CDDraw02Dlg::OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT pDeleteItemStruct) 
{
	// TODO: Add your message handler code here and/or call default
// Inserted code begin
  // A clean way to free the memory allocated
  // when the list and combo boxes are filled.
  // Don't use this technique on NT -- the
  // message isn't sent.
  LPVOID pHeap = ( LPVOID )pDeleteItemStruct->itemData;
  if( pHeap ) 
	{
    free( pHeap );
  }
// Inserted code end

  CDialog::OnDeleteItem(nIDCtl, pDeleteItemStruct);
}

// Inserted code begin

////////////////////////////////////////////////////////
//
// BOOL WINAPI EnumerateDirectDrawDeviceCallback( GUID FAR *, LPSTR, LPSTR, LPVOID )
// 
// Callback function of DirectDrawEnumerate
// 
BOOL WINAPI EnumerateDirectDrawDeviceCallback( GUID FAR *pGUID, LPSTR pDriverDescription, LPSTR pDriverName, LPVOID pContext )
{
  LONG   nIndex;
  CComboBox *pComboBoxDevice = reinterpret_cast< CComboBox * >( pContext );
//  CComboBox *pComboBoxDevice = ( CComboBox * )( pContext );  // OK
//  CComboBox *pComboBoxDevice = static_cast< CComboBox * >( pContext );  // OK
//  CComboBox *pComboBoxDevice = dynamic_cast< CComboBox * >( pContext );  // Error
  if( pComboBoxDevice == NULL )
    return DDENUMRET_CANCEL;
//  HWND   hWnd = ( HWND )pContext;
  LPVOID pDevice = NULL;

  nIndex = pComboBoxDevice->AddString( pDriverDescription );
//  nIndex = ::SendMessage( hWnd, CB_ADDSTRING, 0, ( LPARAM )pDriverDescription );
	// If it got added to the list box, create a copy of the GUID
  // and store a pointer to it in the list box.
  if( nIndex != LB_ERR )
  {
    // Make sure to check for NULL -- NULL corresponds to the 
    // primary device, which isn't given a GUID.
    if( pGUID == NULL ) 
		{
      pDevice = NULL;
    }
    else
    {
      pDevice = ( LPGUID )malloc( sizeof( GUID ) );
      if( !pDevice )
				return FALSE;
      memcpy( pDevice, pGUID, sizeof( GUID ) );
    }
    pComboBoxDevice->SetItemData( nIndex, ( DWORD )pDevice );
//    ::SendMessage( hWnd, CB_SETITEMDATA, nIndex, ( LPARAM )pDevice );
  }
  else 
  {
    return DDENUMRET_CANCEL;
  }
  return DDENUMRET_OK;
}

////////////////////////////////////////////////////////
//
// BOOL WINAPI EnumerateDisplayModesCallback( LPDDSURFACEDESC, LPVOID )
// 
// Callback function of DirectDrawEnumerate
// 
BOOL WINAPI EnumerateDisplayModesCallback( LPDDSURFACEDESC pDDSDesc, LPVOID pContext )
{
  LONG   nIndex;
  char   szBuffer[256];
  CListBox *pListBoxModes = reinterpret_cast< CListBox * >( pContext );
//  HWND   hWnd = ( HWND )pContext;
  LPVOID pDesc = NULL;

  wsprintf( szBuffer, "%dx%dx%dx%d", 
            pDDSDesc->dwWidth,
            pDDSDesc->dwHeight,
            pDDSDesc->ddpfPixelFormat.dwRGBBitCount,
            pDDSDesc->dwRefreshRate );
  nIndex = pListBoxModes->AddString( szBuffer );
//  nIndex = ::SendMessage( hWnd, LB_ADDSTRING, 0, ( LONG )( LPSTR )szBuffer );
  
  // If it got added to the list box, create a copy of the
  // surface description and store a pointer to it in the
  // list box. We'll use it later to set the mode.
  if( nIndex != LB_ERR )
  {
    pDesc = ( LPDDSURFACEDESC )malloc( sizeof( DDSURFACEDESC ) );
    if( !pDesc )
			return FALSE;
    memcpy( pDesc, pDDSDesc, sizeof( DDSURFACEDESC ) );
    pListBoxModes->SetItemData( nIndex, ( DWORD )pDesc );
//    ::SendMessage( hWnd, LB_SETITEMDATA, nIndex, ( LPARAM )pDesc );
  }
  else 
  {
    return DDENUMRET_CANCEL;
  }
  return DDENUMRET_OK;
}

void CDDraw02Dlg::DestroyDirectDrawObjects()
{
  if( m_pDD2 != NULL )
  {
    m_pDD2->Release();
    m_pDD2 = NULL;
  }
}

// Inserted code end

⌨️ 快捷键说明

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