diff src/win32/VideoMode.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/VideoMode.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,347 @@
     1.4 +// VideoMode.cpp : implementation file
     1.5 +//
     1.6 +
     1.7 +#include "stdafx.h"
     1.8 +#include "resource.h"
     1.9 +
    1.10 +///		#define _AFXDLL /// EVIL
    1.11 +///		#include "afxwin.h" /// EVIL
    1.12 +///		#include "afxdll_.h" /// EVIL
    1.13 +
    1.14 +#define DIRECTDRAW_VERSION 0x0700
    1.15 +#include "ddraw.h"
    1.16 +
    1.17 +#include "VideoMode.h"
    1.18 +
    1.19 +#include "../common/System.h" // for system messages
    1.20 +
    1.21 +#define MAX_DRIVERS         32                  // 32 drivers maximum
    1.22 +
    1.23 +//-----------------------------------------------------------------------------
    1.24 +// Local structures
    1.25 +//-----------------------------------------------------------------------------
    1.26 +// Keeps data on the available DDraw drivers
    1.27 +struct
    1.28 +{
    1.29 +	char     szDescription[128];
    1.30 +	char     szName[128];
    1.31 +	GUID *   pGUID;
    1.32 +	GUID     GUIDcopy;
    1.33 +	HMONITOR hm;
    1.34 +} Drivers[MAX_DRIVERS];
    1.35 +
    1.36 +//-----------------------------------------------------------------------------
    1.37 +// Local data
    1.38 +//-----------------------------------------------------------------------------
    1.39 +static int gDriverCnt = 0;                      // Total number of drivers
    1.40 +static GUID *gpSelectedDriverGUID;
    1.41 +
    1.42 +//-----------------------------------------------------------------------------
    1.43 +// Name: DDEnumCallbackEx()
    1.44 +// Desc: This call back is used to determine the existing available DDraw
    1.45 +//       devices, so the user can pick which one to run on.
    1.46 +//-----------------------------------------------------------------------------
    1.47 +BOOL WINAPI
    1.48 +DDEnumCallbackEx(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID pContext, HMONITOR hm)
    1.49 +{
    1.50 +	if (pGUID)
    1.51 +	{
    1.52 +		Drivers[gDriverCnt].GUIDcopy = *pGUID;
    1.53 +		Drivers[gDriverCnt].pGUID    = &Drivers[gDriverCnt].GUIDcopy;
    1.54 +	}
    1.55 +	else
    1.56 +		Drivers[gDriverCnt].pGUID = NULL;
    1.57 +	Drivers[gDriverCnt].szDescription[127] = '\0';
    1.58 +	Drivers[gDriverCnt].szName[127]        = '\0';
    1.59 +	strncpy(Drivers[gDriverCnt].szDescription, pDescription, 127);
    1.60 +	strncpy(Drivers[gDriverCnt].szName, pName, 127);
    1.61 +	Drivers[gDriverCnt].hm = hm;
    1.62 +	if (gDriverCnt < MAX_DRIVERS)
    1.63 +		gDriverCnt++;
    1.64 +	else
    1.65 +		return DDENUMRET_CANCEL;
    1.66 +	return DDENUMRET_OK;
    1.67 +}
    1.68 +
    1.69 +//-----------------------------------------------------------------------------
    1.70 +// Name: DDEnumCallback()
    1.71 +// Desc: This callback is used only with old versions of DDraw.
    1.72 +//-----------------------------------------------------------------------------
    1.73 +BOOL WINAPI
    1.74 +DDEnumCallback(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID context)
    1.75 +{
    1.76 +	return (DDEnumCallbackEx(pGUID, pDescription, pName, context, NULL));
    1.77 +}
    1.78 +
    1.79 +static HRESULT WINAPI addVideoMode(LPDDSURFACEDESC2 surf, LPVOID lpContext)
    1.80 +{
    1.81 +	HWND h = (HWND)lpContext;
    1.82 +	char buffer[50];
    1.83 +
    1.84 +	switch (surf->ddpfPixelFormat.dwRGBBitCount)
    1.85 +	{
    1.86 +	case 16:
    1.87 +	case 24:
    1.88 +	case 32:
    1.89 +		if (surf->dwWidth >= 640 && surf->dwHeight >= 480)
    1.90 +		{
    1.91 +			sprintf(buffer, "%4dx%4dx%2d", surf->dwWidth, surf->dwHeight,
    1.92 +			        surf->ddpfPixelFormat.dwRGBBitCount);
    1.93 +			int pos = ::SendMessage(h, LB_ADDSTRING, 0, (LPARAM)buffer);
    1.94 +			::SendMessage(h, LB_SETITEMDATA, pos,
    1.95 +			              (surf->ddpfPixelFormat.dwRGBBitCount << 24) |
    1.96 +			              ((surf->dwWidth & 4095) << 12) |
    1.97 +			              (surf->dwHeight & 4095));
    1.98 +		}
    1.99 +	}
   1.100 +
   1.101 +	return DDENUMRET_OK;
   1.102 +}
   1.103 +
   1.104 +int winVideoModeSelect(CWnd *pWnd, GUID **guid)
   1.105 +{
   1.106 +	HINSTANCE h = /**/ ::LoadLibrary("ddraw.dll");
   1.107 +
   1.108 +	// If ddraw.dll doesn't exist in the search path,
   1.109 +	// then DirectX probably isn't installed, so fail.
   1.110 +	if (!h)
   1.111 +		return -1;
   1.112 +
   1.113 +	gDriverCnt = 0;
   1.114 +
   1.115 +	// Note that you must know which version of the
   1.116 +	// function to retrieve (see the following text).
   1.117 +	// For this example, we use the ANSI version.
   1.118 +	LPDIRECTDRAWENUMERATEEX lpDDEnumEx;
   1.119 +	lpDDEnumEx = (LPDIRECTDRAWENUMERATEEX)
   1.120 +	             GetProcAddress(h, "DirectDrawEnumerateExA");
   1.121 +
   1.122 +	// If the function is there, call it to enumerate all display
   1.123 +	// devices attached to the desktop, and any non-display DirectDraw
   1.124 +	// devices.
   1.125 +	if (lpDDEnumEx)
   1.126 +		lpDDEnumEx(DDEnumCallbackEx, NULL,
   1.127 +		           DDENUM_ATTACHEDSECONDARYDEVICES |
   1.128 +		           DDENUM_NONDISPLAYDEVICES
   1.129 +		           );
   1.130 +	else
   1.131 +	{
   1.132 +		/*
   1.133 +		 * We must be running on an old version of DirectDraw.
   1.134 +		 * Therefore MultiMon isn't supported. Fall back on
   1.135 +		 * DirectDrawEnumerate to enumerate standard devices on a
   1.136 +		 * single-monitor system.
   1.137 +		 */
   1.138 +		BOOL (WINAPI *lpDDEnum)(LPDDENUMCALLBACK, LPVOID);
   1.139 +
   1.140 +		lpDDEnum = (BOOL (WINAPI *)(LPDDENUMCALLBACK, LPVOID))
   1.141 +		           GetProcAddress(h, "DirectDrawEnumerateA");
   1.142 +		if (lpDDEnum)
   1.143 +			lpDDEnum(DDEnumCallback, NULL);
   1.144 +
   1.145 +		/* Note that it could be handy to let the OldCallback function
   1.146 +		 * be a wrapper for a DDEnumCallbackEx.
   1.147 +		 *
   1.148 +		 * Such a function would look like:
   1.149 +		 *    BOOL FAR PASCAL OldCallback(GUID FAR *lpGUID,
   1.150 +		 *                                LPSTR pDesc,
   1.151 +		 *                                LPSTR pName,
   1.152 +		 *                                LPVOID pContext)
   1.153 +		 *    {
   1.154 +		 *         return Callback(lpGUID,pDesc,pName,pContext,NULL);
   1.155 +		 *    }
   1.156 +		 */
   1.157 +	}
   1.158 +
   1.159 +	int selected = 0;
   1.160 +
   1.161 +	if (gDriverCnt > 1)
   1.162 +	{
   1.163 +		VideoDriverSelect d(pWnd);
   1.164 +
   1.165 +		selected = d.DoModal();
   1.166 +
   1.167 +		if (selected == -1)
   1.168 +		{
   1.169 +			// If the library was loaded by calling LoadLibrary(),
   1.170 +			// then you must use FreeLibrary() to let go of it.
   1.171 +			/**/ ::FreeLibrary(h);
   1.172 +
   1.173 +			return -1;
   1.174 +		}
   1.175 +	}
   1.176 +
   1.177 +	HRESULT (WINAPI *DDrawCreateEx)(GUID *, LPVOID *, REFIID, IUnknown *);
   1.178 +	DDrawCreateEx = (HRESULT (WINAPI *)(GUID *, LPVOID *, REFIID, IUnknown *))
   1.179 +	                GetProcAddress(h, "DirectDrawCreateEx");
   1.180 +
   1.181 +	LPDIRECTDRAW7 ddraw = NULL;
   1.182 +	if (DDrawCreateEx)
   1.183 +	{
   1.184 +		HRESULT hret = DDrawCreateEx(Drivers[selected].pGUID,
   1.185 +		                             (void * *)&ddraw,
   1.186 +		                             IID_IDirectDraw7,
   1.187 +		                             NULL);
   1.188 +		if (hret != DD_OK)
   1.189 +		{
   1.190 +			systemMessage(0, "Error during DirectDrawCreateEx: %08x", hret);
   1.191 +			/**/ ::FreeLibrary(h);
   1.192 +			return -1;
   1.193 +		}
   1.194 +	}
   1.195 +	else
   1.196 +	{
   1.197 +		// should not happen....
   1.198 +		systemMessage(0, "Error getting DirectDrawCreateEx");
   1.199 +		/**/ ::FreeLibrary(h);
   1.200 +		return -1;
   1.201 +	}
   1.202 +
   1.203 +	VideoMode dlg(ddraw, pWnd);
   1.204 +
   1.205 +	int res = dlg.DoModal();
   1.206 +
   1.207 +	if (res != -1)
   1.208 +	{
   1.209 +		*guid = Drivers[selected].pGUID;
   1.210 +	}
   1.211 +	ddraw->Release();
   1.212 +	ddraw = NULL;
   1.213 +
   1.214 +	// If the library was loaded by calling LoadLibrary(),
   1.215 +	// then you must use FreeLibrary() to let go of it.
   1.216 +	/**/ ::FreeLibrary(h);
   1.217 +
   1.218 +	return res;
   1.219 +}
   1.220 +
   1.221 +/////////////////////////////////////////////////////////////////////////////
   1.222 +// VideoMode dialog
   1.223 +
   1.224 +VideoMode::VideoMode(LPDIRECTDRAW7 pDraw, CWnd*pParent /*=NULL*/)
   1.225 +	: CDialog(VideoMode::IDD, pParent)
   1.226 +{
   1.227 +	//{{AFX_DATA_INIT(VideoMode)
   1.228 +	// NOTE: the ClassWizard will add member initialization here
   1.229 +	//}}AFX_DATA_INIT
   1.230 +	pDirectDraw = pDraw;
   1.231 +}
   1.232 +
   1.233 +void VideoMode::DoDataExchange(CDataExchange*pDX)
   1.234 +{
   1.235 +	CDialog::DoDataExchange(pDX);
   1.236 +	//{{AFX_DATA_MAP(VideoMode)
   1.237 +	DDX_Control(pDX, IDC_MODES, m_modes);
   1.238 +	//}}AFX_DATA_MAP
   1.239 +}
   1.240 +
   1.241 +BEGIN_MESSAGE_MAP(VideoMode, CDialog)
   1.242 +//{{AFX_MSG_MAP(VideoMode)
   1.243 +ON_LBN_SELCHANGE(IDC_MODES, OnSelchangeModes)
   1.244 +ON_BN_CLICKED(ID_CANCEL, OnCancel)
   1.245 +ON_BN_CLICKED(ID_OK, OnOk)
   1.246 +//}}AFX_MSG_MAP
   1.247 +END_MESSAGE_MAP()
   1.248 +
   1.249 +/////////////////////////////////////////////////////////////////////////////
   1.250 +// VideoMode message handlers
   1.251 +
   1.252 +void VideoMode::OnSelchangeModes()
   1.253 +{
   1.254 +	int item = m_modes.GetCurSel();
   1.255 +
   1.256 +	GetDlgItem(ID_OK)->EnableWindow(item != -1);
   1.257 +}
   1.258 +
   1.259 +void VideoMode::OnCancel()
   1.260 +{
   1.261 +	EndDialog(-1);
   1.262 +}
   1.263 +
   1.264 +void VideoMode::OnOk()
   1.265 +{
   1.266 +	int cur = m_modes.GetCurSel();
   1.267 +
   1.268 +	if (cur != -1)
   1.269 +	{
   1.270 +		cur = m_modes.GetItemData(cur);
   1.271 +	}
   1.272 +	EndDialog(cur);
   1.273 +}
   1.274 +
   1.275 +BOOL VideoMode::OnInitDialog()
   1.276 +{
   1.277 +	CDialog::OnInitDialog();
   1.278 +
   1.279 +	// check for available fullscreen modes
   1.280 +	pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, m_modes.m_hWnd,
   1.281 +	                              addVideoMode);
   1.282 +
   1.283 +	GetDlgItem(ID_OK)->EnableWindow(FALSE);
   1.284 +	CenterWindow();
   1.285 +
   1.286 +	return TRUE; // return TRUE unless you set the focus to a control
   1.287 +	             // EXCEPTION: OCX Property Pages should return FALSE
   1.288 +}
   1.289 +
   1.290 +/////////////////////////////////////////////////////////////////////////////
   1.291 +// VideoDriverSelect dialog
   1.292 +
   1.293 +VideoDriverSelect::VideoDriverSelect(CWnd*pParent /*=NULL*/)
   1.294 +	: CDialog(VideoDriverSelect::IDD, pParent)
   1.295 +{
   1.296 +	//{{AFX_DATA_INIT(VideoDriverSelect)
   1.297 +	// NOTE: the ClassWizard will add member initialization here
   1.298 +	//}}AFX_DATA_INIT
   1.299 +}
   1.300 +
   1.301 +void VideoDriverSelect::DoDataExchange(CDataExchange*pDX)
   1.302 +{
   1.303 +	CDialog::DoDataExchange(pDX);
   1.304 +	//{{AFX_DATA_MAP(VideoDriverSelect)
   1.305 +	DDX_Control(pDX, IDC_DRIVERS, m_drivers);
   1.306 +	//}}AFX_DATA_MAP
   1.307 +}
   1.308 +
   1.309 +BEGIN_MESSAGE_MAP(VideoDriverSelect, CDialog)
   1.310 +//{{AFX_MSG_MAP(VideoDriverSelect)
   1.311 +ON_BN_CLICKED(ID_OK, OnOk)
   1.312 +ON_BN_CLICKED(ID_CANCEL, OnCancel)
   1.313 +ON_LBN_SELCHANGE(IDC_DRIVERS, OnSelchangeDrivers)
   1.314 +//}}AFX_MSG_MAP
   1.315 +END_MESSAGE_MAP()
   1.316 +
   1.317 +/////////////////////////////////////////////////////////////////////////////
   1.318 +// VideoDriverSelect message handlers
   1.319 +
   1.320 +void VideoDriverSelect::OnCancel()
   1.321 +{
   1.322 +	EndDialog(-1);
   1.323 +}
   1.324 +
   1.325 +void VideoDriverSelect::OnOk()
   1.326 +{
   1.327 +	EndDialog(m_drivers.GetCurSel());
   1.328 +}
   1.329 +
   1.330 +BOOL VideoDriverSelect::OnInitDialog()
   1.331 +{
   1.332 +	CDialog::OnInitDialog();
   1.333 +
   1.334 +	for (int i = 0; i < gDriverCnt; i++)
   1.335 +	{
   1.336 +		m_drivers.AddString(Drivers[i].szDescription);
   1.337 +	}
   1.338 +
   1.339 +	GetDlgItem(ID_OK)->EnableWindow(FALSE);
   1.340 +	CenterWindow();
   1.341 +
   1.342 +	return TRUE; // return TRUE unless you set the focus to a control
   1.343 +	             // EXCEPTION: OCX Property Pages should return FALSE
   1.344 +}
   1.345 +
   1.346 +void VideoDriverSelect::OnSelchangeDrivers()
   1.347 +{
   1.348 +	GetDlgItem(ID_OK)->EnableWindow(m_drivers.GetCurSel() != -1);
   1.349 +}
   1.350 +