1 //-----------------------------------------------------------------------------
4 // Desc: Support functions for the user select driver dialog.
6 // Note: Since this code is destined for a static link library, the
7 // dialog dox is constructed manually. Otherwise, we would use a resource
8 // and save many lines of code. Manually constructing dialog boxes is not
9 // trivial and there are many issues (unicode, dword alignment, etc.)
13 // Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved.
14 //-----------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------
24 // Constants and function prototypes for the user select driver dialog
25 //-----------------------------------------------------------------------------
26 #define IDC_STATIC 0xffff
27 #define IDC_DRIVER_COMBO 1000
28 #define IDC_DEVICE_COMBO 1001
29 #define IDC_MODE_COMBO 1002
34 //-----------------------------------------------------------------------------
35 // External variables (declared in the D3DEnum.cpp file)
36 //-----------------------------------------------------------------------------
37 extern D3DEnum_DriverInfo* g_pCurrentDriver; // The selected DD driver
42 //-----------------------------------------------------------------------------
43 // Name: CopyToWideChar
44 //-----------------------------------------------------------------------------
45 static VOID CopyToWideChar( WCHAR** pstrOut, LPTSTR strIn )
47 DWORD dwLen = lstrlen( strIn );
48 WCHAR* strOut = *pstrOut;
50 #ifdef UNICODE // Copy Unicode to Unicode
51 _wcsncpy( strOut, strIn, dwLen );
52 strOut[dwLen] = L'\0';
53 #else // Copy Ansi to Unicode
54 dwLen = MultiByteToWideChar( CP_ACP, 0, strIn, dwLen, strOut, dwLen );
55 strOut[dwLen++] = L'\0'; // Add the null terminator
63 //-----------------------------------------------------------------------------
64 // Name: AddDialogControl()
65 // Desc: Internal function to help build the user select dialog
66 //-----------------------------------------------------------------------------
67 static VOID AddDialogControl( WORD** pp, DWORD dwStyle, SHORT x, SHORT y,
68 SHORT cx, SHORT cy, WORD id,
69 LPTSTR strClassName, LPTSTR strTitle )
71 // DWORD align the current ptr
72 DLGITEMTEMPLATE* p = (DLGITEMTEMPLATE*)(((((ULONG)(*pp))+3)>>2)<<2);
74 p->style = dwStyle | WS_CHILD | WS_VISIBLE;
75 p->dwExtendedStyle = 0L;
82 *pp = (WORD*)(++p); // Advance ptr
84 CopyToWideChar( (WCHAR**)pp, strClassName ); // Set Class name
85 CopyToWideChar( (WCHAR**)pp, strTitle ); // Set Title
87 (*pp)++; // Skip Extra Stuff
93 //-----------------------------------------------------------------------------
94 // Name: _BuildUserSelectDialog()
95 // Desc: Internal function to build the user select dialog
96 //-----------------------------------------------------------------------------
97 DLGTEMPLATE* _BuildDriverSelectTemplate()
99 // Allocate ample memory for building the template
100 DLGTEMPLATE* pDlgTemplate = new DLGTEMPLATE[50];
101 if( NULL == pDlgTemplate )
103 ZeroMemory( pDlgTemplate, 50*sizeof(DLGTEMPLATE) );
105 // Fill in the DLGTEMPLATE info
106 DLGTEMPLATE* pdt = pDlgTemplate;
107 pdt->style = DS_MODALFRAME | DS_NOIDLEMSG | DS_SETFOREGROUND |
108 DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE |
109 WS_CAPTION | WS_SYSMENU | DS_SETFONT;
110 pdt->dwExtendedStyle = 0L;
117 // Add menu array, class array, dlg title, font size and font name
118 WORD* pw = (WORD*)(++pdt);
119 *pw++ = L'\0'; // Set Menu array to nothing
120 *pw++ = L'\0'; // Set Class array to nothing
121 CopyToWideChar( (WCHAR**)&pw, TEXT( "Select New Direct3D Driver" ) ); // Dlg title
122 *pw++ = 8; // Font Size
123 CopyToWideChar( (WCHAR**)&pw, TEXT("Arial") ); // Font Name
125 // Add the okay button
126 AddDialogControl( &pw, BS_PUSHBUTTON | WS_TABSTOP, 65, 65, 51, 14,
127 IDOK, TEXT("BUTTON"), TEXT("OK") );
129 // Add the cancel button
130 AddDialogControl( &pw, BS_PUSHBUTTON | WS_TABSTOP, 123, 65, 51, 14,
131 IDCANCEL, TEXT("BUTTON"), TEXT("Cancel") );
133 // Add the driver select combobox
134 AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
136 IDC_DRIVER_COMBO, TEXT("COMBOBOX"), TEXT("") );
138 // Add the device select combobox
139 AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
141 IDC_DEVICE_COMBO, TEXT("COMBOBOX"), TEXT("") );
143 // Add the mode select combobox
144 AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
146 IDC_MODE_COMBO, TEXT("COMBOBOX"), TEXT("") );
148 // Add the "Driver:" text
149 AddDialogControl( &pw, SS_LEFT, 5, 5, 22, 13,
150 IDC_STATIC, TEXT("STATIC"), TEXT("Driver:") );
152 // Add the "Device:" text
153 AddDialogControl( &pw, SS_LEFT, 5, 24, 25, 13,
154 IDC_STATIC, TEXT("STATIC"), TEXT("Device:") );
156 // Add the "Mode:" text
157 AddDialogControl( &pw, SS_LEFT, 5, 44, 22, 13,
158 IDC_STATIC, TEXT("STATIC"), TEXT("Mode:") );
166 //-----------------------------------------------------------------------------
167 // Name: UpdateComboBoxesContent()
168 // Desc: Builds the list of drivers, devices and modes for the combo boxes
169 // in the driver select dialog box.
170 //-----------------------------------------------------------------------------
171 static VOID UpdateComboBoxesContent( HWND hDlg,
172 D3DEnum_DriverInfo** ppCurrentDriver,
173 D3DEnum_DeviceInfo** ppCurrentDevice,
174 D3DEnum_ModeInfo** ppCurrentMode,
177 // Check the parameters
178 if( (NULL==ppCurrentDriver) || (NULL==ppCurrentDevice) ||
179 (NULL==ppCurrentMode) )
182 // If the specified driver is NULL, use the first one in the list
183 if( NULL == *ppCurrentDriver)
184 (*ppCurrentDriver) = D3DEnum_GetFirstDriver();
186 // If the specified device is NULL, use the first one in the list
187 if( NULL == *ppCurrentDevice)
188 (*ppCurrentDevice) = (*ppCurrentDriver)->pFirstDevice;
190 // Reset the content in each of the combo boxes
191 SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_RESETCONTENT, 0, 0 );
192 SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_RESETCONTENT, 0, 0 );
193 SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_RESETCONTENT, 0, 0 );
195 // Build the list of drivers for the combo box
196 for( D3DEnum_DriverInfo* pDriver = D3DEnum_GetFirstDriver(); pDriver;
197 pDriver = pDriver->pNext )
199 // Add driver desc to the combo box
200 DWORD dwItem = SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO,
201 CB_ADDSTRING, 0, (LPARAM)pDriver->strDesc );
203 // Associate DriverInfo ptr with the item in the combo box
204 SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_SETITEMDATA,
205 (WPARAM)dwItem, (LPARAM)pDriver );
207 // If this is the current driver, set is as the current selection
208 if( pDriver == (*ppCurrentDriver) )
209 SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_SETCURSEL,
210 (WPARAM)dwItem, 0L );
213 // Build the list of devices for the combo box
214 for( D3DEnum_DeviceInfo* pDevice = (*ppCurrentDriver)->pFirstDevice; pDevice;
215 pDevice = pDevice->pNext )
217 // Add device name to the combo box
218 DWORD dwItem = SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO,
219 CB_ADDSTRING, 0, (LPARAM)pDevice->strName );
221 // Associate DeviceInfo ptr with the item in the combo box
222 SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_SETITEMDATA,
223 (WPARAM)dwItem, (LPARAM)pDevice );
225 // If this is the current device, set this as the current selection
226 if( pDevice == (*ppCurrentDevice) )
227 SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_SETCURSEL,
228 (WPARAM)dwItem, 0L );
231 if( (*ppCurrentDriver)->ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED
232 && ( NULL == (*ppCurrentDriver)->pGUID )
233 && (*ppCurrentDevice)->bCompatbileWithDesktop )
235 // Add windowed mode to the combo box of available modes
236 DWORD dwItem = SendDlgItemMessage( hDlg, IDC_MODE_COMBO,
237 CB_ADDSTRING, 0, (LPARAM)TEXT("Windowed mode") );
239 // Associate ModeInfo ptr with the item in the combo box
240 SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETITEMDATA,
241 (WPARAM)dwItem, (LPARAM)NULL );
243 // If the current device is windowed, set this as current
245 SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETCURSEL,
246 (WPARAM)dwItem, 0L );
249 // Build the list of modes for the combo box
250 for( D3DEnum_ModeInfo* pMode = (*ppCurrentDevice)->pFirstMode; pMode;
251 pMode = pMode->pNext )
253 // Add mode desc to the combo box
254 DWORD dwItem = SendDlgItemMessage( hDlg, IDC_MODE_COMBO,
256 (LPARAM)pMode->strDesc );
258 // Associate ModeInfo ptr with the item in the combo box
259 SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETITEMDATA,
260 (WPARAM)dwItem, (LPARAM)pMode );
262 // If this is the current mode, set is as the current selection
263 if( !bWindowed && ( pMode == (*ppCurrentMode) ) )
264 SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETCURSEL,
265 (WPARAM)dwItem, 0L );
272 //-----------------------------------------------------------------------------
273 // Name: _DriverSelectProc()
274 // Desc: Windows message handling function for the driver select dialog
275 //-----------------------------------------------------------------------------
276 BOOL CALLBACK _DriverSelectProc( HWND hDlg, UINT uiMsg, WPARAM wParam,
279 static D3DEnum_DriverInfo *pOldDriver, *pNewDriver;
280 static D3DEnum_DeviceInfo *pOldDevice, *pNewDevice;
281 static D3DEnum_ModeInfo *pOldMode, *pNewMode;
282 static BOOL bOldWindowed, bNewWindowed;
284 // Handle the initialization message
285 if( WM_INITDIALOG == uiMsg )
287 // Setup temp storage pointers for dialog
288 pNewDriver = pOldDriver = g_pCurrentDriver;
289 pNewDevice = pOldDevice = pOldDriver->pCurrentDevice;
290 pNewMode = pOldMode = pOldDevice->pCurrentMode;
291 bNewWindowed = bOldWindowed = pOldDevice->bWindowed;
293 UpdateComboBoxesContent( hDlg, &pOldDriver, &pOldDevice,
294 &pOldMode, bOldWindowed );
298 if( WM_COMMAND == uiMsg )
300 // Handle the case when the user hits the OK button
301 if( IDOK == LOWORD(wParam) )
303 // Check if any of the options were changed
304 if( ( pOldDriver != pNewDriver ) || ( pOldDevice != pNewDevice ) ||
305 ( pOldMode != pNewMode ) || ( bOldWindowed != bNewWindowed ) )
307 // Set actual ptrs from the temp ptrs used for the dialog
308 g_pCurrentDriver = pNewDriver;
309 g_pCurrentDriver->pCurrentDevice = pNewDevice;
310 g_pCurrentDriver->pCurrentDevice->pCurrentMode = pNewMode;
311 g_pCurrentDriver->pCurrentDevice->bWindowed = bNewWindowed;
313 EndDialog( hDlg, IDOK );
318 EndDialog( hDlg, IDCANCEL );
323 // Handle the case when the user hits the Cancel button
324 else if( IDCANCEL == LOWORD(wParam) )
326 EndDialog( hDlg, IDCANCEL );
330 // Handle the case when the user chooses an item in the combo boxes.
331 else if( CBN_SELENDOK == HIWORD(wParam) )
333 DWORD dwIndex = SendMessage( (HWND)lParam, CB_GETCURSEL,
335 LONG pNewObject = SendMessage( (HWND)lParam, CB_GETITEMDATA,
338 if( (CB_ERR==dwIndex) )
341 // Handle the case where one of these may have changed. The
342 // combo boxes will need to be updated to reflect the changes.
343 switch( LOWORD( wParam ) )
345 case IDC_DRIVER_COMBO:
346 if( pNewObject && pNewObject != (LONG)pNewDriver )
348 pNewDriver = (D3DEnum_DriverInfo*)pNewObject;
349 pNewDevice = pNewDriver->pCurrentDevice;;
350 pNewMode = pNewDevice->pCurrentMode;
351 bNewWindowed = pNewDevice->bWindowed;
354 case IDC_DEVICE_COMBO:
355 if( pNewObject && pNewObject != (LONG)pNewDevice )
357 pNewDevice = (D3DEnum_DeviceInfo*)pNewObject;
358 pNewMode = pNewDevice->pCurrentMode;
359 bNewWindowed = pNewDevice->bWindowed;
365 pNewMode = (D3DEnum_ModeInfo*)pNewObject;
366 bNewWindowed = FALSE;
373 UpdateComboBoxesContent( hDlg, &pNewDriver, &pNewDevice,
374 &pNewMode, bNewWindowed );