Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1578 lines
52 KiB

/*
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);
}
}