|
|
/*
File: add.cpp Project: Universal Joystick Control Panel OLE Client Author: Brycej Date: 14/Feb/97 Comments: window proc for add dialog
Copyright (c) 1995, Microsoft Corporation */
#include <afxcmn.h>
#include <windowsx.h>
#include <regstr.h> // for REGSTR_VAL_JOYOEMNAME reference!
#include "cpanel.h"
#include "joyarray.h"
#include <initguid.h>
#pragma warning(disable:4200)
#include <gameport.h>
#pragma warning(default:4200)
// table of default joystick configs
extern WCHAR *pwszTypeArray[MAX_DEVICES]; // List of enumerated gameport devices
extern WCHAR *pwszGameportBus[MAX_BUSSES]; // List of enumerated gameport buses
extern PJOY pAssigned[MAX_ASSIGNED]; // List of assigned devices
extern BYTE nAssigned; // Number of elements in pAssigned array
extern BYTE nTargetAssigned; // Number of elements expected when pending adds complete
extern BYTE nReEnum; // Counter used to decide when to reenumerate
extern GUID guidOccupied[MAX_BUSSES]; //Whether the gameport bus has been occupied.
extern BYTE nGameportBus, nGamingDevices;
extern IDirectInputJoyConfig *pDIJoyConfig; extern short iItem; extern short nFlags; // Flags set in CPANEL.CPP!
// extern functions defined in CPANEL.CPP
extern void OnContextMenu(WPARAM wParam, LPARAM lParam); extern void OnHelp (LPARAM);
// local message handlers
static BOOL OnInitDialog(HWND, HWND, LPARAM); static void OnClose(HWND); static void OnCommand(HWND, int, HWND, UINT);
static char AddSelectedItem( HWND hDlg ); static BOOL UpdateListCtrl ( HWND hCtrl ); static char GetNextAvailableID( void ); static BOOL IsTypeActive( short *nArrayIndex ); static BOOL GetNextAvailableVIDPID(LPWSTR lpwszType ); //static BOOL IsCustomType(BYTE nIndex);
static void PostHScrollBar(HWND hCtrl, LPCTSTR lpStr, BYTE nStrLen);
extern const DWORD g_aHelpIDs[];
extern HINSTANCE ghInstance;
LPTSTR lpszAutoDetect;
const int NO_ITEM = -1; #define MAX_ANALOG_BUTTONS 4
#define MAX_ANALOG_AXIS 4
// This will become a problem when we support > 500 ports!
#define AUTODETECT_PORT 100
// Consider achieving this from calculation of width of listview
static short iAddItem = NO_ITEM;
BOOL WINAPI AddDialogProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_DESTROY: DestroyIcon((HICON)SendMessage(hDlg, WM_GETICON, (WPARAM)ICON_SMALL, 0));
if( nGameportBus > 1 ) if( lpszAutoDetect ) delete[] (lpszAutoDetect); break;
case WM_LBUTTONDOWN: // Click Drag service for PropSheets!
PostMessage(hDlg, WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam); break;
case WM_INITDIALOG: return(BOOL)HANDLE_WM_INITDIALOG(hDlg, wParam, lParam, OnInitDialog);
case WM_COMMAND: HANDLE_WM_COMMAND(hDlg, wParam, lParam, OnCommand); return(1);
case WM_VKEYTOITEM: if( LOWORD(wParam) == VK_DELETE ) { HWND hWnd = GetDlgItem(hDlg, IDC_DEVICE_LIST);
// determine if it's a custom type... if so... delete it
// Get the next object with the SELECTED attribute
iAddItem = (short)::SendMessage(hWnd, LB_GETCURSEL, 0, 0);
short nArrayIndex = (short)::SendMessage(hWnd, LB_GETITEMDATA, (WPARAM)iAddItem, 0);
// test to make sure they aren't trying to delete a standard type
if( *pwszTypeArray[nArrayIndex] == L'#' ) break;
// test that the device is a custom type (user or IHV defined)
// ISSUE-2001/03/29-timgill the number of times we retrieve the same data is ridiculous
LPDIJOYTYPEINFO lpdiJoyInfo = new (DIJOYTYPEINFO); ASSERT (lpdiJoyInfo);
if( lpdiJoyInfo ) { /*
* warning, abuse of S_OK == 0 == strcmp( identical strings ) ahead */ HRESULT CmpRes;
ZeroMemory(lpdiJoyInfo, sizeof(*lpdiJoyInfo));
lpdiJoyInfo->dwSize = sizeof(*lpdiJoyInfo);
/*
* Test the hardware ID */ CmpRes = pDIJoyConfig->GetTypeInfo(pwszTypeArray[nArrayIndex], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_HARDWAREID); if( SUCCEEDED( CmpRes ) ) { #ifndef WINNT
if( lpdiJoyInfo->wszHardwareId[0] == L'\0' ) { /*
* No hardware ID, so look for a callout VxD * If there is none, we have a custom type. */ CmpRes = pDIJoyConfig->GetTypeInfo(pwszTypeArray[nArrayIndex], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_CALLOUT); CmpRes = ( SUCCEEDED( CmpRes ) && ( lpdiJoyInfo->wszCallout[0] == L'\0' ) ) ? S_OK : S_FALSE; } else #endif
{ const WCHAR wszAnalogRoot[] = L"gameport\\vid_045e&pid_01";
CmpRes = (HRESULT)_wcsnicmp( lpdiJoyInfo->wszHardwareId, wszAnalogRoot, (sizeof(wszAnalogRoot)/sizeof(wszAnalogRoot[0]) ) - 1 ); } } else { CmpRes = S_FALSE; }
// clean-up!
delete (lpdiJoyInfo);
if( CmpRes != S_OK ) { // This is not an analog type so leave alone
break; } } else { // If we can't test the type, do nothing
break; }
// test to make sure you are not deleting objects
if( IsTypeActive(&nArrayIndex) ) { Error((short)IDS_GEN_AREYOUSURE_TITLE, (short)IDS_NO_REMOVE); break; }
// This buffer has to be big enough for the name and the "are you sure..." message!
LPTSTR pszMsg = new TCHAR[MAX_STR_LEN+STR_LEN_64]; ASSERT (pszMsg);
LPTSTR pszTitle = new TCHAR[STR_LEN_128]; ASSERT (pszTitle);
// Query user if they are sure!
VERIFY(LoadString(ghInstance, IDS_GEN_AREYOUSURE, pszTitle, MAX_STR_LEN));
LPTSTR pszTmp = new TCHAR[(short)SendMessage(hWnd, LB_GETTEXTLEN, (WPARAM)iAddItem, 0)+1]; ASSERT (pszTmp);
SendMessage(hWnd, LB_GETTEXT, (WPARAM)iAddItem, (LPARAM)(LPCTSTR)pszTmp);
wsprintf( pszMsg, pszTitle, pszTmp);
if( pszTmp ) delete[] (pszTmp);
VERIFY(LoadString(ghInstance, IDS_GEN_AREYOUSURE_TITLE, pszTitle, STR_LEN_128));
HRESULT hr = MessageBox(hWnd, pszMsg, pszTitle, MB_ICONQUESTION | MB_YESNO | MB_APPLMODAL);
if( pszMsg ) delete[] (pszMsg); if( pszTitle ) delete[] (pszTitle);
if( IDYES == hr ) {
if( SUCCEEDED(hr = pDIJoyConfig->Acquire()) ) { // traverse the list and delete any configuration that may have this type assigned to it!
//DeleteAssignedType( pwszTypeArray[nArrayIndex] );
// returns E_ACCESSDENIED if it's a default item.
hr = pDIJoyConfig->DeleteType(pwszTypeArray[nArrayIndex]); ASSERT(SUCCEEDED(hr));
pDIJoyConfig->Unacquire();
// the dec is for the zero based device list!
// decrement the indexes
nGamingDevices--;
// don't move if you're on the last entry!
if( nArrayIndex != nGamingDevices ) { // To avoid deleting and recreating...
// Let's see if we have room to put this string!
BYTE nLen = (BYTE)wcslen(pwszTypeArray[nArrayIndex])+1;
// Make sure pwszTypeArray[nArrayIndex] is larger than pwszTypeArray[nCount]
if( nLen < (BYTE)wcslen(pwszTypeArray[nGamingDevices])+1 ) { if( pwszTypeArray[nArrayIndex] ) free(pwszTypeArray[nArrayIndex]);
pwszTypeArray[nArrayIndex] = _wcsdup(pwszTypeArray[nGamingDevices]); ASSERT (pwszTypeArray[nArrayIndex]); } // move the end element to the place of the deleted one
else wcsncpy(pwszTypeArray[nArrayIndex], pwszTypeArray[nGamingDevices], wcslen(pwszTypeArray[nGamingDevices])+1);
// update the extra memory to reflect the new index!
// First, find the item in the listbox and get the index...
LPDIJOYTYPEINFO_DX5 lpdiJoyInfo = new (DIJOYTYPEINFO_DX5); ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO_DX5));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
if( SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[nArrayIndex], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_DISPLAYNAME)) ) { char n = (char)SendMessage(hWnd, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpdiJoyInfo->wszDisplayName); SendMessage(hWnd, LB_SETITEMDATA, (WPARAM)n, (LPARAM)nArrayIndex); }
// clean-up!
if( lpdiJoyInfo ) delete (lpdiJoyInfo); }
// delete the end element from the array
if( pwszTypeArray[nGamingDevices] ) { free(pwszTypeArray[nGamingDevices]); pwszTypeArray[nGamingDevices] = 0; }
// Remove the entry from the list control
SendMessage(hWnd, LB_DELETESTRING, (WPARAM)iAddItem, 0);
// Enable the buttons!
if( nGamingDevices < MAX_DEVICES-1 ) { HWND hParent = GetParent(hWnd); ASSERT (hParent);
PostDlgItemEnableWindow(hParent, IDC_CUSTOM, TRUE); PostDlgItemEnableWindow(hParent, IDC_ADD_NEW, TRUE); }
if( iAddItem != nGamingDevices-1 ) iAddItem--;
// Set the focus to the next available item
PostMessage(hWnd, LB_SETCURSEL, (WPARAM)(iAddItem == NO_ITEM) ? 0 : iAddItem, 0); } } break; } else return(-1);
// case WM_NOTIFY:
/// return HANDLE_WM_NOTIFY(hDlg, wParam, lParam, OnNotify);
case WM_HELP: OnHelp(lParam); return(1);
case WM_CONTEXTMENU: OnContextMenu(wParam, lParam); return(1); } return(0); }
BOOL OnInitDialog(HWND hDlg, HWND hWnd, LPARAM lParam) { HICON hIcon = (HICON)LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CPANEL), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); ASSERT (hIcon);
if( hIcon ) ::PostMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
if( nFlags & ON_NT ) DestroyWindow(GetDlgItem(hDlg, IDC_WDM)); else { HKEY hKey;
// remove the WDM flag unless otherwise specified!
if( RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\MediaResources\\joystick\\<FixedKey>"), &hKey) == ERROR_SUCCESS ) { DWORD n; DWORD dwSize = sizeof (DWORD);
if( RegQueryValueEx(hKey, TEXT("UseWDM"), 0, 0, (LPBYTE)&n, &dwSize) == ERROR_SUCCESS ) { if( n ) DestroyWindow(GetDlgItem(hDlg, IDC_WDM)); } }
RegCloseKey(hKey); }
// a simple debug test to verify that the template hasn't gotten DIALOGEX style again!
HWND hCtrl = GetDlgItem(hDlg, IDC_DEVICE_LIST); ASSERT (hCtrl);
// Fill up the Device List
if( !UpdateListCtrl(hCtrl) ) { TRACE(TEXT("JOY.CPL: ADD.CPP: Failed UpdateListCtrl!\n")); return(FALSE); }
// If there is only one, don't confuse the user with the combo box
if( nGameportBus > 1 ) { // Allocate for AutoDetect Gameport!
lpszAutoDetect = new (TCHAR[STR_LEN_32]); ASSERT (lpszAutoDetect);
VERIFY(LoadString(ghInstance, IDS_AUTO_DETECT, lpszAutoDetect, STR_LEN_32));
hCtrl = GetDlgItem(hDlg, IDC_GAMEPORTLIST); ASSERT (hCtrl);
if( !PopulatePortList(hCtrl) ) { TRACE(TEXT("JOY.CPL: ADD.CPP: Failed PopulatePortList!\n")); return(FALSE); }
LPDIJOYTYPEINFO lpdiJoyInfo = new DIJOYTYPEINFO; ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO);
VERIFY(SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[0], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_FLAGS1)));
// Search for AutoDetect in the list!
char nIndex = (char)::SendMessage(hCtrl, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCTSTR)lpszAutoDetect);
// If it's got the JOYTYPE_NOAUTODETECTGAMEPORT flag, remove AutoDetect from the ListCtrl
if( lpdiJoyInfo->dwFlags1 & JOYTYPE_NOAUTODETECTGAMEPORT ) { // it could fail because the entry is not available...
if( nIndex != CB_ERR ) ::SendMessage(hCtrl, CB_DELETESTRING, (WPARAM)nIndex, 0);
} // Otherwise, verify that AutoDetect is present... if not, add it!
else { // it could fail because the entry is not available...
if( nIndex == CB_ERR ) ::SendMessage(hCtrl, CB_SETITEMDATA, ::SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)lpszAutoDetect), AUTODETECT_PORT); }
if( lpdiJoyInfo ) delete (lpdiJoyInfo);
SetWindowPos( hCtrl, NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
SetWindowPos( GetDlgItem(hDlg, IDC_GAMEPORT), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); }
// blj: Warning Message that you can't add any more devices!
if( nGamingDevices == MAX_DEVICES-1 ) { // Disable the Custom Button!
PostDlgItemEnableWindow(hDlg, IDC_CUSTOM, FALSE); PostDlgItemEnableWindow(hDlg, IDC_ADD_NEW, FALSE);
// Give the user a error message!
Error((short)IDS_MAX_DEVICES_TITLE, (short)IDS_MAX_DEVICES_MSG); }
return(0); }
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code)
//
// PARAMETERS: hDlg -
// id -
// hWndCtl -
// code -
//
// PURPOSE: WM_COMMAND message handler
///////////////////////////////////////////////////////////////////////////////
void OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code) { switch( id ) { case IDC_ADD_NEW: if( SUCCEEDED(pDIJoyConfig->AddNewHardware(hDlg, GUID_MediaClass)) ) { ClearArrays();
if( FAILED(pDIJoyConfig->EnumTypes((LPDIJOYTYPECALLBACK)DIEnumJoyTypeProc, NULL)) ) { TRACE(TEXT("JOY.CPL: ADD.CPP: Failed BuildEnumList!\n")); return; }
// Warning Message that you can't add any more devices!
if( nGamingDevices == MAX_DEVICES-1 ) { // Disable the Custom Button!
PostDlgItemEnableWindow(hDlg, IDC_CUSTOM, FALSE); PostDlgItemEnableWindow(hDlg, IDC_ADD_NEW, FALSE);
// Give the user a error message!
Error((short)IDS_MAX_DEVICES_TITLE, (short)IDS_MAX_DEVICES_MSG); }
if( !UpdateListCtrl(GetDlgItem(hDlg, IDC_DEVICE_LIST)) ) { TRACE(TEXT("JOY.CPL: ADD.CPP: Failed to update the list control on the add page!\n")); return; } } break;
case IDC_CUSTOM: // DialogBox returns either IDCANCEL or the index into the list of
// defined types!
if( IDOK == DialogBox(ghInstance, (PTSTR)IDD_CUSTOM, hDlg, (DLGPROC)CustomDialogProc) ) { HWND hCtrl = GetDlgItem(hDlg, IDC_DEVICE_LIST);
// blj: Warning Message that you can't add any more devices!
if( nGamingDevices == MAX_DEVICES-1 ) { // Disable the Custom Button!
PostDlgItemEnableWindow(hDlg, IDC_CUSTOM, FALSE);
// Give the user a error message!
Error((short)IDS_MAX_DEVICES_TITLE, (short)IDS_MAX_DEVICES_MSG); }
// Now, put the focus on the newly created item!
LPDIJOYTYPEINFO_DX5 lpdiJoyInfo = new (DIJOYTYPEINFO_DX5); ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO_DX5));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
// Get nGamingDevices from pwszTypeArray
// Subtract 1 from nGamingDevices because the list is 0 based!
if( SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[nGamingDevices-1], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_DISPLAYNAME | DITC_REGHWSETTINGS)) ) { #ifdef _UNICODE
iAddItem = (short)SendMessage(hCtrl, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)lpdiJoyInfo->wszDisplayName); SendMessage(hCtrl, LB_SETITEMDATA, (WPARAM)iAddItem, (LPARAM)nGamingDevices-1); PostHScrollBar(hCtrl, lpdiJoyInfo->wszDisplayName, (BYTE)wcslen(lpdiJoyInfo->wszDisplayName)); #else
USES_CONVERSION; iAddItem = (short)SendMessage(hCtrl, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)W2A(lpdiJoyInfo->wszDisplayName)); SendMessage(hCtrl, LB_SETITEMDATA, (WPARAM)iAddItem, (LPARAM)nGamingDevices-1); PostHScrollBar(hCtrl, W2A(lpdiJoyInfo->wszDisplayName), (BYTE)wcslen(lpdiJoyInfo->wszDisplayName)); #endif
// SetFocus to that item!
SendMessage(hCtrl, LB_SETCURSEL, (WPARAM)iAddItem, 0);
OnCommand(hDlg, IDC_DEVICE_LIST, 0, LBN_SELCHANGE); }
// clean-up!
if( lpdiJoyInfo ) delete (lpdiJoyInfo); } break;
case IDC_DEVICE_LIST: if( code == LBN_SELCHANGE ) { iAddItem = (short)SendMessage(hWndCtl, LB_GETCURSEL, 0, 0);
BYTE nArrayID = (BYTE)SendMessage(hWndCtl, LB_GETITEMDATA, (WPARAM)iAddItem, 0);
LPDIJOYTYPEINFO lpdiJoyInfo = new DIJOYTYPEINFO; ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO);
DWORD dwFlags = DITC_REGHWSETTINGS;
if( nGameportBus > 1 ) dwFlags |= DITC_FLAGS1;
VERIFY(SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[nArrayID], (LPDIJOYTYPEINFO)lpdiJoyInfo, dwFlags))); /*
if (nGameportBus > 1) { HWND hCtrl = GetDlgItem(hDlg, IDC_GAMEPORTLIST);
// Search for AutoDetect in the list!
char nIndex = (char)::SendMessage(hCtrl, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCTSTR)lpszAutoDetect);
// If it's got the JOYTYPE_NOAUTODETECTGAMEPORT flag, remove AutoDetect from the ListCtrl
if (lpdiJoyInfo->dwFlags1 & JOYTYPE_NOAUTODETECTGAMEPORT) { // it could fail because the entry is not available...
if (nIndex != CB_ERR) ::SendMessage(hCtrl, CB_DELETESTRING, (WPARAM)nIndex, 0); } // Otherwise, verify that AutoDetect is present... if not, add it!
else { // it could fail because the entry is not available...
if (nIndex == CB_ERR) ::SendMessage(hCtrl, CB_SETITEMDATA, ::SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)lpszAutoDetect), AUTODETECT_PORT); } ::PostMessage(hCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); } */
PostDlgItemEnableWindow(hDlg, IDC_JOY1HASRUDDER, (lpdiJoyInfo->hws.dwFlags & JOY_HWS_HASR) ? FALSE : TRUE);
if( lpdiJoyInfo ) delete (lpdiJoyInfo);
break; }
if( code != LBN_DBLCLK ) break;
case IDOK: iAddItem = (short)SendDlgItemMessage(hDlg, IDC_DEVICE_LIST, LB_GETCURSEL, 0, 0);
if( iAddItem == NO_ITEM ) break;
// Check to see if they have a GamePortList
{ HWND hCtrl = GetDlgItem(hDlg, IDC_GAMEPORTLIST); ASSERT (hCtrl);
if( IsWindowVisible(hCtrl) ) { // Check to see if the user has a port selected!
if( SendMessage(hCtrl, CB_GETCURSEL, 0, 0) == CB_ERR ) { // blj: TODO: Clear this message with UE
Error((short)IDS_NO_GAMEPORT_TITLE, (short)IDS_NO_GAMEPORT); break; } } }
iItem = 0; AddSelectedItem(hDlg);
case IDCANCEL: EndDialog(hDlg, id); break; } }
/// Custom Dialog procedure
BOOL WINAPI CustomDialogProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam) { static LPWSTR lpwszVIDPID;
switch( uMsg ) { case WM_DESTROY: { HICON hIcon = (HICON)SendMessage(hDlg, WM_GETICON, (WPARAM)ICON_SMALL, 0); DestroyIcon(hIcon); } break;
case WM_LBUTTONDOWN: // Click Drag service for PropSheets!
PostMessage(hDlg, WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam); break;
case WM_HELP: OnHelp(lParam); return(1);
case WM_CONTEXTMENU: OnContextMenu(wParam, lParam); return(TRUE);
case WM_INITDIALOG: // Set up the Buttons and Axis combo boxs!
{ HICON hIcon = (HICON)LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CPANEL), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); ASSERT (hIcon);
if( hIcon ) ::PostMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
// Return if no available VID/PIDs found!
lpwszVIDPID = new (WCHAR[STR_LEN_32]); ASSERT (lpwszVIDPID);
pDIJoyConfig->Acquire();
if( !GetNextAvailableVIDPID(lpwszVIDPID) ) { if( lpwszVIDPID ) delete[] (lpwszVIDPID);
EndDialog(hDlg, IDCANCEL);
// Let the user know that they need to remove some "Custom" devices!
Error((short)IDS_NO_NAME_TITLE, (short)IDS_NOAVAILABLEVIDPID );
return(FALSE); }
// init id list
BYTE nButtons = MAX_ANALOG_BUTTONS; TCHAR szTmp[3];
HWND hCtrl = GetDlgItem(hDlg, IDC_COMBO_BUTTONS);
// Fill the Buttons combo...
do { itoa(nButtons, (LPTSTR)&szTmp); SendMessage(hCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)(LPCTSTR)szTmp); } while( nButtons-- );
// Set Default to four buttons
SendMessage(hCtrl, CB_SETCURSEL, MAX_ANALOG_BUTTONS, 0);
// Use nButtons for Axis...
nButtons = MAX_ANALOG_AXIS;
hCtrl = GetDlgItem(hDlg, IDC_COMBO_AXIS);
// Fill the Axis combo...
do { itoa(nButtons--, (LPTSTR)&szTmp); SendMessage(hCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)(LPCTSTR)szTmp); } while( nButtons > 1 );
// Set Default to two Axis
SendMessage(hCtrl, CB_SETCURSEL, 0, 0); }
::PostMessage(GetDlgItem(hDlg, IDC_SPECIAL_JOYSTICK), BM_SETCHECK, BST_CHECKED, 0);
SendDlgItemMessage(hDlg, IDC_EDIT_NAME, EM_LIMITTEXT, (WPARAM)MAX_STR_LEN, 0); return(1);
case WM_COMMAND: switch( LOWORD(wParam) ) { case IDOK: { // defines for error states!
#define DUPLICATE_NAME 0x01
#define NO_NAME 0x02
#define INVALID_NAME 0x04
BYTE nLen = (BYTE)SendDlgItemMessage(hDlg, IDC_EDIT_NAME, EM_LINELENGTH, 0, 0);
LPTSTR pszTypeName = NULL;
if( nLen ) { pszTypeName = new (TCHAR[nLen+1]); ASSERT (pszTypeName);
// Get the Type/Display Name
GetDlgItemText(hDlg, IDC_EDIT_NAME, (LPTSTR)pszTypeName, nLen+1);
if( _tcschr(pszTypeName, TEXT('\\')) ) nLen = INVALID_NAME; else { // Make sure it's not a duplicate!
// start of fix #9269
LPDIJOYTYPEINFO_DX5 lpdiGetJoyInfo = new DIJOYTYPEINFO_DX5; ASSERT (lpdiGetJoyInfo);
ZeroMemory(lpdiGetJoyInfo, sizeof(DIJOYTYPEINFO_DX5));
lpdiGetJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
// Clean-up nLen!
BYTE n = nLen = 0;
// Search for a Duplicate Display Name!!!
while( pwszTypeArray[n] ) { if( FAILED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[n++], (LPDIJOYTYPEINFO)lpdiGetJoyInfo, DITC_DISPLAYNAME)) ) { TRACE(TEXT("JOY.CPL: ADD.CPP: GetTypeInfo Failed!\n")); continue; } #ifndef _UNICODE
USES_CONVERSION; #endif
if( _tcsncmp(pszTypeName, #ifdef _UNICODE
lpdiGetJoyInfo->wszDisplayName, #else
W2A(lpdiGetJoyInfo->wszDisplayName), #endif
wcslen(lpdiGetJoyInfo->wszDisplayName)+1) == 0 ) { nLen = DUPLICATE_NAME; break; } }
if( lpdiGetJoyInfo ) { delete (lpdiGetJoyInfo); } // end of fix #9269
} } else nLen = NO_NAME;
// Check for an error!
if( nLen ) { if( pszTypeName ) delete[] (pszTypeName);
// Give the user the appropriate error!
switch( nLen ) { case DUPLICATE_NAME: Error((SHORT)IDS_NO_NAME_TITLE, (SHORT)IDS_DUPLICATE_TYPE); break;
case NO_NAME: Error((short)IDS_NO_NAME_TITLE, (short)IDS_NO_NAME); break;
case INVALID_NAME: Error((short)IDS_NO_NAME_TITLE, (short)IDS_INVALID_NAME); break; }
// Set Focus to the Dialog
SetFocus(hDlg);
HWND hCtrl = GetDlgItem(hDlg, IDC_EDIT_NAME); ASSERT (hCtrl);
// Set Focus to the Control
SetFocus(hCtrl);
// hilite the error
PostMessage(hCtrl, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
return(FALSE); }
// set the type information
LPDIJOYTYPEINFO lpdiJoyInfo = new (DIJOYTYPEINFO); ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO);
#ifndef _UNICODE
USES_CONVERSION; #endif
// Set the Display Name
wcsncpy(lpdiJoyInfo->wszDisplayName, #ifdef _UNICODE
pszTypeName, #else
A2W(pszTypeName), #endif // _UNICODE
lstrlen(pszTypeName)+1);
if( pszTypeName ) delete[] (pszTypeName);
// Set the GUID - default to LegacyServer
// Per Marcus, we don't want to do this anymore!
//lpdiJoyInfo->clsidConfig = CLSID_LegacyServer;
// Set the Hardware Settings
lpdiJoyInfo->hws.dwNumButtons = (DWORD)SendDlgItemMessage(hDlg, IDC_COMBO_BUTTONS, CB_GETCURSEL, 0, 0);
switch( SendDlgItemMessage(hDlg, IDC_COMBO_AXIS, CB_GETCURSEL, 0, 0) ) { // R Axis
case 1: // Check to see which button got checked...
lpdiJoyInfo->hws.dwFlags |= ::SendMessage(GetDlgItem(hDlg, IDC_HASRUDDER), BM_GETCHECK, 0, 0) ? JOY_HWS_HASR : JOY_HWS_HASZ; break;
// Z Axis
case 2: lpdiJoyInfo->hws.dwFlags |= JOY_HWS_HASR; lpdiJoyInfo->hws.dwFlags |= JOY_HWS_HASZ; break;
// X/Y are default!
default: lpdiJoyInfo->hws.dwFlags = 0; break; }
lpdiJoyInfo->hws.dwFlags |= ::SendMessage(GetDlgItem(hDlg, IDS_CUSTOM_HASPOV), BM_GETCHECK, 0, 0) ? JOY_HWS_HASPOV : 0;
// Get Special char's status
lpdiJoyInfo->hws.dwFlags |= ::SendMessage(GetDlgItem(hDlg, IDC_SPECIAL_JOYSTICK), BM_GETCHECK, 0, 0) ? 0 : ::SendMessage(GetDlgItem(hDlg, IDC_SPECIAL_PAD), BM_GETCHECK, 0, 0) ? JOY_HWS_ISGAMEPAD : ::SendMessage(GetDlgItem(hDlg, IDC_SPECIAL_AUTO), BM_GETCHECK, 0, 0) ? JOY_HWS_ISCARCTRL : JOY_HWS_ISYOKE; // default to Yoke!
// Set up wszHardwareId
wcscpy(lpdiJoyInfo->wszHardwareId, L"GamePort\\");
// This blocks the Huge DisplayName bug!
// DINPUT change requires VID/PID at the end of the hardware ID... it was
//StrNCatW(lpdiJoyInfo->wszHardwareId, lpwszVIDPID, 245);
// Win95 does not like StrNCatW, we will use wcsncat
wcsncat(lpdiJoyInfo->wszHardwareId, lpwszVIDPID, 245);
if( SUCCEEDED(pDIJoyConfig->Acquire()) ) { #ifdef _UNICODE
if( FAILED(pDIJoyConfig->SetTypeInfo(lpwszVIDPID, lpdiJoyInfo, DITC_DISPLAYNAME | DITC_CLSIDCONFIG | DITC_REGHWSETTINGS | DITC_HARDWAREID)) ) #else
if( FAILED(pDIJoyConfig->SetTypeInfo(lpwszVIDPID, lpdiJoyInfo, DITC_DISPLAYNAME | DITC_CLSIDCONFIG | DITC_REGHWSETTINGS ) ) ) #endif
{ #ifdef _DEBUG
OutputDebugString(TEXT("JOY.CPL: ADD.CPP: CustomDlgProc: SetTypeInfo Failed!\n")); #endif
}
// Create the memory for the Custom device and stick it into the array!
pwszTypeArray[nGamingDevices++] = _wcsdup(lpwszVIDPID);
pDIJoyConfig->Unacquire(); }
if( lpdiJoyInfo ) delete (lpdiJoyInfo); }
case IDCANCEL: if( lpwszVIDPID ) delete[] (lpwszVIDPID);
EndDialog(hDlg, LOWORD(wParam)); break;
case IDC_SPECIAL_JOYSTICK: case IDC_SPECIAL_YOKE: case IDC_SPECIAL_PAD: case IDC_SPECIAL_AUTO: CheckRadioButton(hDlg, IDC_SPECIAL_JOYSTICK, IDC_SPECIAL_AUTO, IDC_SPECIAL_JOYSTICK); break;
case IDC_COMBO_AXIS: // Show/Hide IDC_HASRUDDER based on Selection of 3 Axis
if( HIWORD(wParam) == CBN_SELCHANGE ) { const USHORT nCtrlArray[] = {IDC_HASRUDDER, IDC_HASZAXIS}; BYTE nCtrls = sizeof(nCtrlArray)/sizeof(short);
// the '1' in the comparison is because the CB is Zero based!
BOOL bShow = (BOOL)(SendDlgItemMessage(hDlg, IDC_COMBO_AXIS, CB_GETCURSEL, 0, 0) == 1);
do { SetWindowPos( GetDlgItem(hDlg, nCtrlArray[--nCtrls]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((bShow) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); } while( nCtrls );
if( bShow ) ::PostMessage(GetDlgItem(hDlg, IDC_HASZAXIS), BM_SETCHECK, BST_CHECKED, 0); } break; } return(1);
case WM_CLOSE: EndDialog(hDlg, 0); return(1); } return(0); }
char GetNextAvailableID( void ) { LPDIJOYCONFIG_DX5 pJoyConfig = new (DIJOYCONFIG_DX5); ASSERT (pJoyConfig);
ZeroMemory(pJoyConfig, sizeof(DIJOYCONFIG_DX5));
pJoyConfig->dwSize = sizeof (DIJOYCONFIG_DX5);
char i = 0;
do { switch( pDIJoyConfig->GetConfig(i, (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE) ) { case S_FALSE: case DIERR_NOMOREITEMS: case DIERR_NOTFOUND: case E_FAIL: goto EXIT;
default: i++; break; } } while( i < NUMJOYDEVS );
i = -1;
// And it's Error time!
Error((short)IDS_NO_IDS_TITLE, (short)IDS_NO_IDS);
EXIT: if( pJoyConfig ) delete (pJoyConfig);
return(i); }
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: AddSelectedItem(HWND hDlg)
//
// PARAMETERS: hDlg - Handle to page
//
// PURPOSE: Adds selected item from List box.
///////////////////////////////////////////////////////////////////////////////
char AddSelectedItem( HWND hDlg ) { static BYTE n; DWORD dwFlags; HRESULT hr; int nID; #ifdef SUPPORT_TWO_2A2B
BOOL f2_2A2B = FALSE; #endif
nID = GetNextAvailableID();
// GetNextAvailableID returns -1 if it fails!
if( nID < 0 ) return((char)nID);
// Type info
LPDIJOYTYPEINFO_DX5 lpdiJoyInfo = new (DIJOYTYPEINFO_DX5); ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO_DX5));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
BYTE nArrayID = (BYTE)SendDlgItemMessage(hDlg, IDC_DEVICE_LIST, LB_GETITEMDATA, (WPARAM)iAddItem, 0);
VERIFY(SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[nArrayID], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_REGHWSETTINGS | DITC_CALLOUT | DITC_DISPLAYNAME)));
#ifdef SUPPORT_TWO_2A2B
#ifndef _UNICODE
if( wcscmp( pwszTypeArray[nArrayID], L"#<" ) == 0 ) { f2_2A2B = TRUE; lpdiJoyInfo->hws.dwFlags = 0; pwszTypeArray[nArrayID][1] = L'2'; } else { f2_2A2B = FALSE; } #endif
#endif
LPDIJOYCONFIG pTempJoyConfig = new DIJOYCONFIG; ASSERT (pTempJoyConfig);
ZeroMemory(pTempJoyConfig, sizeof(DIJOYCONFIG));
pTempJoyConfig->dwSize = sizeof (DIJOYCONFIG);
pTempJoyConfig->hwc.hws = lpdiJoyInfo->hws; pTempJoyConfig->hwc.hws.dwFlags |= JOY_HWS_ISANALOGPORTDRIVER;
// Do the Rudder Flags!
if( ::SendMessage(GetDlgItem(hDlg, IDC_JOY1HASRUDDER), BM_GETCHECK, 0, 0) ) { pTempJoyConfig->hwc.hws.dwFlags |= JOY_HWS_HASR; pTempJoyConfig->hwc.dwUsageSettings |= JOY_US_HASRUDDER; }
// set default to present
pTempJoyConfig->hwc.dwUsageSettings |= JOY_US_PRESENT;
pTempJoyConfig->hwc.dwType = nArrayID;
wcsncpy(pTempJoyConfig->wszCallout, lpdiJoyInfo->wszCallout, wcslen(lpdiJoyInfo->wszCallout)+1);
wcsncpy(pTempJoyConfig->wszType, pwszTypeArray[nArrayID], wcslen(pwszTypeArray[nArrayID])+1);
LPWSTR lpszPortName = NULL;
if( SUCCEEDED(pDIJoyConfig->Acquire()) ) { // This stops Memphis and gameport-less systems!!!
if( nGameportBus ) {
// no point asking the Combo box if there's really no choice!
if( nGameportBus > 1 ) { n = (BYTE)SendDlgItemMessage(hDlg, IDC_GAMEPORTLIST, CB_GETITEMDATA, (WPARAM)SendDlgItemMessage(hDlg, IDC_GAMEPORTLIST, CB_GETCURSEL, 0, 0), 0); } else { n = 0; }
if( n == AUTODETECT_PORT ) { #ifdef _DEBUG
OutputDebugString(TEXT("JOY.CPL: ADD.CPP: Selected Port is AutoDetect!\n")); #endif
pTempJoyConfig->guidGameport = GUID_GAMEENUM_BUS_ENUMERATOR; } else { // Zero the memory because the buffer still contains the old data!!!
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO_DX5)); lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
#ifdef _DEBUG
TRACE(TEXT("JOY.CPL: ADD.CPP: Port List index is %d or %s!\n"), n, pwszGameportBus[n]); #endif
if( SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszGameportBus[n], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_CLSIDCONFIG | DITC_DISPLAYNAME)) ) { pTempJoyConfig->guidGameport = lpdiJoyInfo->clsidConfig; lpszPortName = _wcsdup(lpdiJoyInfo->wszDisplayName); } } }
// This is for Memphis and odd case NT systems!
if( pTempJoyConfig->guidGameport == GUID_NULL ) { pTempJoyConfig->guidGameport = GUID_GAMEENUM_BUS_ENUMERATOR; #ifdef _DEBUG
OutputDebugString(TEXT("JOY.CPL: ADD.CPP: Selected Port did not return a clsidConfig so AutoDetect is being used!\n")); #endif
}
// Set the hour glass
SetCursor(LoadCursor(NULL, IDC_WAIT));
// ISSUE-2001/03/29-timgill (MarcAnd) Why would we want to block updates when we're adding a device?
#if 1
// Unblock the WM_DEVICECHANGE message handler!
nFlags &= ~BLOCK_UPDATE; nFlags |= ON_PAGE;
/*
* Set the nReEnum counter going so that for the next n WM_TIMER * messages (or until the device arrives) we can consider * doing a refresh. * The value is somewhat arbitrary. */ nReEnum = 43; /*
* Set a target for the number of devices so that the extra * reenumerations can be avoided if this target is reached. */ nTargetAssigned = nAssigned+1; #else
nFlags |= BLOCK_UPDATE; #endif
dwFlags = DIJC_REGHWCONFIGTYPE | DIJC_CALLOUT; dwFlags |= ::SendDlgItemMessage(hDlg, IDC_WDM, BM_GETCHECK, 0, 0) ? DIJC_WDMGAMEPORT : 0;
if( FAILED(hr = pDIJoyConfig->SetConfig(nID, pTempJoyConfig, dwFlags)) ) { // Let the user know what happend!
if( hr == E_ACCESSDENIED ) { // Let the use know that the port is already occupied and that they need to remove that device or
// re-assign the device to an unoccupied port.
LPDIJOYCONFIG lpJoyCfg = new (DIJOYCONFIG); ASSERT (lpJoyCfg);
ZeroMemory(lpJoyCfg, sizeof(DIJOYCONFIG));
lpJoyCfg->dwSize = sizeof(DIJOYCONFIG);
// Cycle threw pAssigned and find the device with the same port name!
BYTE nIndex = nAssigned;
do { if( SUCCEEDED(pDIJoyConfig->GetConfig(pAssigned[--nIndex]->ID, lpJoyCfg, DIJC_WDMGAMEPORT)) ) { if( lpJoyCfg->guidGameport == pTempJoyConfig->guidGameport ) break; } } while( nIndex );
if( lpJoyCfg ) delete (lpJoyCfg);
DIPROPSTRING *pDIPropStr = new (DIPROPSTRING); ASSERT (pDIPropStr);
ZeroMemory(pDIPropStr, sizeof(DIPROPSTRING));
pDIPropStr->diph.dwSize = sizeof(DIPROPSTRING); pDIPropStr->diph.dwHeaderSize = sizeof(DIPROPHEADER); pDIPropStr->diph.dwHow = DIPH_DEVICE;
// Ok now.. you found it... use the Device pointer to get it's Friendly name!
if( SUCCEEDED(pAssigned[nIndex]->fnDeviceInterface->GetProperty(DIPROP_INSTANCENAME, &pDIPropStr->diph)) ) { // Put ellipse in text to avoid buffer over-flow.
// Limit displayed name to 50 chars... not completely arbitrary,
// we need to leave room in the Message string...
// who knows how long the string will get when translated!
if( wcslen(pDIPropStr->wsz) > 50 ) { pDIPropStr->wsz[47] = pDIPropStr->wsz[48] = pDIPropStr->wsz[49] = L'.'; pDIPropStr->wsz[50] = L'\0'; }
LPTSTR lptszMsgFormat = new (TCHAR[MAX_STR_LEN]); ASSERT (lptszMsgFormat); VERIFY(LoadString(ghInstance, IDS_ADD_PORT_MSGFORMAT, lptszMsgFormat, MAX_STR_LEN));
LPTSTR lptszMsg = new (TCHAR[MAX_STR_LEN]); ASSERT (lptszMsg);
// Format the message
wsprintf(lptszMsg, lptszMsgFormat, pDIPropStr->wsz, lpszPortName, pAssigned[nIndex]->ID+1);
VERIFY(LoadString(ghInstance, IDS_ADD_PORT_OCCUPIED, lptszMsgFormat, MAX_STR_LEN));
MessageBox(hDlg, lptszMsg, lptszMsgFormat, MB_ICONHAND | MB_OK | MB_APPLMODAL);
if( lptszMsgFormat ) delete[] (lptszMsgFormat);
if( lptszMsg ) delete[] (lptszMsg); }
if( pDIPropStr ) delete (pDIPropStr); } else if( hr == DIERR_DEVICEFULL ) { Error((short)IDS_GAMEPORT_OCCUPIED_TITLE, (short)IDS_GAMEPORT_OCCUPIED); } else { // Something Ugly happened!
Error((short)IDS_NO_GAMENUM_TITLE, (short)IDS_NO_GAMENUM); } } else { #ifdef _UNICODE
// Fix #55524
if( SUCCEEDED(pDIJoyConfig->GetConfig(nID, pTempJoyConfig, DIJC_REGHWCONFIGTYPE)) ) { if( !(pTempJoyConfig->hwc.dwUsageSettings & JOY_US_PRESENT) ) { pTempJoyConfig->hwc.dwUsageSettings |= JOY_US_PRESENT; pTempJoyConfig->hwc.hwv.dwCalFlags |= 0x80000000; pTempJoyConfig->hwc.hws.dwFlags |= JOY_HWS_ISANALOGPORTDRIVER;
VERIFY(SUCCEEDED(pDIJoyConfig->SetConfig(nID, pTempJoyConfig, DIJC_REGHWCONFIGTYPE))); } } // end of Fix #55524
#endif
// make sure VJOYD is notified
if( !(nFlags & ON_NT) ) { pDIJoyConfig->SendNotify(); Sleep(10); pDIJoyConfig->SendNotify(); }
#ifndef _UNICODE
#ifdef SUPPORT_TWO_2A2B
/*
* Add the other part of Two_2Axis_2Button joystick. */ if( f2_2A2B ) { nID = GetNextAvailableID(); if( nID >= 0 ){ hr = pDIJoyConfig->SetConfig(nID, pTempJoyConfig, dwFlags);
if( SUCCEEDED(hr) ) { if( !(nFlags & ON_NT) ) pDIJoyConfig->SendNotify(); } } } #endif
#endif
}
if( lpszPortName ) free(lpszPortName);
// Set the standard pointer
SetCursor(LoadCursor(NULL, IDC_ARROW));
pDIJoyConfig->Unacquire(); }
if( lpdiJoyInfo ) delete (lpdiJoyInfo);
if( pTempJoyConfig ) delete (pTempJoyConfig);
return((char)nID); }
BOOL UpdateListCtrl( HWND hCtrl ) { // Turn Redraw off here else it will flicker!
::SendMessage(hCtrl, WM_SETREDRAW, (WPARAM)FALSE, 0);
// delete all existing entries
::SendMessage(hCtrl, LB_RESETCONTENT, 0, 0);
// Type info
LPDIJOYTYPEINFO_DX5 lpdiJoyInfo = new (DIJOYTYPEINFO_DX5); ASSERT (lpdiJoyInfo);
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO_DX5));
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
#ifndef _UNICODE
USES_CONVERSION; #endif
BYTE nIndex = nGamingDevices-1;
::SendMessage(hCtrl, LB_SETCOUNT, (WPARAM)(int)nIndex, 0);
LPWSTR lpStr = new WCHAR[MAX_STR_LEN]; ASSERT (lpStr);
BYTE nLargestStringLen = 0;
do { if( SUCCEEDED(pDIJoyConfig->GetTypeInfo(pwszTypeArray[nIndex], (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_DISPLAYNAME)) ) { #ifdef _UNICODE
::SendMessage(hCtrl, LB_SETITEMDATA, (WPARAM)::SendMessage(hCtrl, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)lpdiJoyInfo->wszDisplayName), (LPARAM)nIndex); #else
::SendMessage(hCtrl, LB_SETITEMDATA, (WPARAM)::SendMessage(hCtrl, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)W2A(lpdiJoyInfo->wszDisplayName)), (LPARAM)nIndex); #endif
if( wcslen(lpdiJoyInfo->wszDisplayName) > nLargestStringLen ) { nLargestStringLen = (BYTE)wcslen(lpdiJoyInfo->wszDisplayName); wcscpy(lpStr, lpdiJoyInfo->wszDisplayName); } } } while( nIndex-- );
if( lpdiJoyInfo ) delete (lpdiJoyInfo);
#ifdef _UNICODE
PostHScrollBar(hCtrl, lpStr, nLargestStringLen); #else
PostHScrollBar(hCtrl, W2A(lpStr), nLargestStringLen); #endif
if( lpStr ) delete[] (lpStr);
// Select the default selection to the 0th device type
iAddItem = 0;
::PostMessage(hCtrl, LB_SETCURSEL, (WPARAM)iAddItem, 0);
// Turn the redraw flag back on!
::SendMessage (hCtrl, WM_SETREDRAW, (WPARAM)TRUE, 0); InvalidateRect(hCtrl, NULL, TRUE); return(TRUE); }
// Please check to see if nGameportBus is > 0 before a call to this function!
// It will work, but What a waste!
BOOL PopulatePortList( HWND hCtrl ) { if( !::IsWindow(hCtrl) ) { TRACE(TEXT("JOY.CPL: PopulatePortList: HWND passed to PopulatePortList is NOT a valid Window!\n")); return(FALSE); }
SendMessage(hCtrl, CB_SETEXTENDEDUI, TRUE, 0);
// temp so we don't damage the global!
BYTE n = nGameportBus;
LPDIJOYTYPEINFO lpDIJoyTypeInfo = new (DIJOYTYPEINFO); ASSERT(lpDIJoyTypeInfo);
#ifndef _UNICODE
USES_CONVERSION; #endif
lpDIJoyTypeInfo->dwSize = sizeof(DIJOYTYPEINFO);
// Populate the list as they were enumerated.
do { if( FAILED(pDIJoyConfig->GetTypeInfo(pwszGameportBus[--n], lpDIJoyTypeInfo, DITC_DISPLAYNAME)) ) { TRACE(TEXT("JOY.CPL: ADD.CPP: GetTypeInfo failed!\n")); continue; }
// put the name in the list and place the index of the port array
// in it's item data...
SendMessage(hCtrl, CB_SETITEMDATA, #ifdef _UNICODE
SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)lpDIJoyTypeInfo->wszDisplayName), n); #else
SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)W2A(lpDIJoyTypeInfo->wszDisplayName)), n); #endif
// Just in case you're curious, we're going backwards so the default
// port is the lowest available one.
} while( n );
// Don't forget Auto-Detect!
// But only if there's more than one port!
::SendMessage(hCtrl, CB_SETITEMDATA, ::SendMessage(hCtrl, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)lpszAutoDetect), AUTODETECT_PORT);
// While you're at it, check to see if one is available...
// if so, put it as the default!
::PostMessage(hCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
if( lpDIJoyTypeInfo ) delete (lpDIJoyTypeInfo);
return(TRUE); }
static BOOL IsTypeActive( short *nArrayIndex ) { if( *nArrayIndex > nGamingDevices ) { #ifdef _DEBUG
OutputDebugString(TEXT("JOY.CPL: IsTypeActive: nArrayIndex > nGamingDevices!\n")); #endif
return(FALSE); }
BOOL bRet = FALSE;
BYTE nIndex = nAssigned; BYTE nStrLen = (BYTE)wcslen(pwszTypeArray[*nArrayIndex])+1;
LPDIJOYCONFIG_DX5 lpDIJoyConfig = new (DIJOYCONFIG_DX5); ASSERT (lpDIJoyConfig);
ZeroMemory(lpDIJoyConfig, sizeof(DIJOYCONFIG_DX5));
lpDIJoyConfig->dwSize = sizeof (DIJOYCONFIG_DX5);
// find the assigned ID's
while( nIndex-- ) { if( SUCCEEDED(pDIJoyConfig->GetConfig(pAssigned[nIndex]->ID, (LPDIJOYCONFIG)lpDIJoyConfig, DIJC_REGHWCONFIGTYPE)) ) { // if you find it... break out!
if( wcsncmp(lpDIJoyConfig->wszType, pwszTypeArray[*nArrayIndex], nStrLen) == 0 ) { bRet = TRUE; *nArrayIndex = nIndex; break; } } }
if( lpDIJoyConfig ) delete (lpDIJoyConfig);
return(bRet); }
BOOL GetNextAvailableVIDPID(LPWSTR lpwszType ) { // Make the VID/PID to compare from the following formula
// VID_045e&PID_100+JOY_HW_LASTENTRY to 100+JOY_HW_LASTENTRY+0xf
HKEY hKey; BYTE n = JOY_HW_LASTENTRY;
wcsncpy(lpwszType, L"VID_045E&PID_0100", 18);
const WCHAR wszLookup[] = L"0123456789ABCDEF";
do { if( n < 0x10 ) { lpwszType[16] = wszLookup[n]; } else { lpwszType[15] = wszLookup[1]; lpwszType[16] = wszLookup[n%0x10]; }
n++;
if( FAILED(pDIJoyConfig->OpenTypeKey(lpwszType, KEY_READ, &hKey)) ) break;
RegCloseKey(hKey);
} while( n < (JOY_HW_LASTENTRY+0x11) );
return(BOOL)(n < 0x1d); }
//
// PostDlgItemEnableWindow(HWND hDlg, USHORT nItem, BOOL bEnabled)
//
void PostDlgItemEnableWindow(HWND hDlg, USHORT nItem, BOOL bEnabled) { HWND hCtrl = GetDlgItem(hDlg, nItem);
if( hCtrl ) PostEnableWindow(hCtrl, bEnabled); }
//
// PostEnableWindow(HWND hCtrl, BOOL bEnabled)
//
void PostEnableWindow(HWND hCtrl, BOOL bEnabled) { DWORD dwStyle = GetWindowLong(hCtrl, GWL_STYLE);
// No point Redrawing the Window if there's no change!
if( bEnabled ) { if( dwStyle & WS_DISABLED ) dwStyle &= ~WS_DISABLED; else return; } else { if( !(dwStyle & WS_DISABLED) ) dwStyle |= WS_DISABLED; else return; }
SetWindowLong(hCtrl, GWL_STYLE, dwStyle);
RedrawWindow(hCtrl, NULL, NULL, RDW_INTERNALPAINT | RDW_INVALIDATE); }
/*
BOOL IsCustomType(BYTE nIndex) { BOOL bRet = FALSE;
// First verify VID is 045E
WCHAR *pwStr = StrStrW(pwszTypeArray[nIndex],L"VID_"); if (pwStr) { // Increment the pointer over the VID_ and test for 045E
pwStr = &pwStr[4];
if (_wcsnicmp(pwStr, L"045e", 4) == 0) { OutputDebugString(TEXT("Hit \n"));
// Now, increment the pointer over 045e and &PID_ and test for the range!
pwStr = &pwStr[9];
// Second, verify PID is between 0x100 + JOY_HW_LASTENTRY and
// 0x100 + JOY_HW_LASTENTRY + 0xf
bRet = TRUE; } }
return bRet; } */
void PostHScrollBar(HWND hCtrl, LPCTSTR lpStr, BYTE nStrLen) { SIZE sz; HDC hDC = GetWindowDC(hCtrl); if( hDC != NULL ) /* PREFIX MANBUGS: 29336*/ { GetTextExtentPoint32(hDC, lpStr, nStrLen, &sz); ReleaseDC(hCtrl, hDC); ::PostMessage(hCtrl, LB_SETHORIZONTALEXTENT, (WPARAM)sz.cx, 0); } }
|