2888 lines
89 KiB
C++
2888 lines
89 KiB
C++
/*
|
|
* File: Cpanel.cpp
|
|
* Project: Universal Joystick Control Panel OLE Client
|
|
* Author: Brycej
|
|
* Date: 02/08/95 - Started this maddness...
|
|
* 04/15/97 - Updated to use DI interface
|
|
* Comments:
|
|
* window proc for General page in cpanel
|
|
*
|
|
* Copyright (c) 1995, Microsoft Corporation
|
|
*/
|
|
|
|
/*
|
|
// This is necessary LVS_EX_INFOTIP
|
|
#if (_WIN32_IE < 0x0500)
|
|
#undef _WIN32_IE
|
|
#define _WIN32_IE 0x0500
|
|
#endif
|
|
*/
|
|
|
|
|
|
#include <afxcmn.h>
|
|
#include <windowsx.h>
|
|
|
|
#ifndef _UNICODE
|
|
#define INC_OLE2
|
|
|
|
#include <objbase.h> // For COM stuff!
|
|
#endif
|
|
|
|
#include <initguid.h>
|
|
|
|
#include <cpl.h>
|
|
#include <winuser.h> // For RegisterDeviceNotification stuff!
|
|
#include <dbt.h> // for DBT_ defines!!!
|
|
#include <hidclass.h>
|
|
#include <malloc.h> // for _alloca
|
|
#include <regstr.h> // for REGSTR_PATH_JOYOEM reference!
|
|
|
|
#include "hsvrguid.h"
|
|
#include "cpanel.h"
|
|
#include "resource.h"
|
|
#include "joyarray.h"
|
|
|
|
// constants
|
|
const short ID_MYTIMER = 1000;
|
|
const short POLLRATE = 850;
|
|
const short NO_ITEM = -1;
|
|
|
|
#define IDC_WHATSTHIS 400
|
|
|
|
// externs
|
|
extern const DWORD gaHelpIDs[];
|
|
extern HINSTANCE ghInstance;
|
|
|
|
// externs for arguements!
|
|
extern BYTE nID, nStartPageDef, nStartPageCPL;
|
|
|
|
// DI globals
|
|
IDirectInputJoyConfig* pDIJoyConfig = 0;
|
|
LPDIRECTINPUT lpDIInterface = 0;
|
|
|
|
// Array of all available devices
|
|
#ifndef _UNICODE
|
|
WCHAR *pwszGameportDriverArray[MAX_GLOBAL_PORT_DRIVERS]; // List of enumerated Gameport Drivers
|
|
BYTE nGameportDriver; // Global Port Driver Enumeration Counter
|
|
#endif
|
|
|
|
WCHAR *pwszTypeArray[MAX_DEVICES]; // List of enumerated devices
|
|
WCHAR *pwszGameportBus[MAX_BUSSES]; // List of enumerated gameport buses
|
|
PJOY pAssigned[MAX_ASSIGNED]; // List of assigned devices
|
|
|
|
BYTE nGamingDevices; // Gaming Devices Enumeration Counter
|
|
BYTE nGameportBus; // Gameport Bus Enumeration Counter
|
|
BYTE nAssigned; // Number of elements in pAssigned array
|
|
BYTE nTargetAssigned; // Number of elements expected in pAssigned array when pending adds complete
|
|
BYTE nReEnum; // Counter used to decide when to reenumerate
|
|
|
|
GUID guidOccupied[MAX_BUSSES]; //Whether the gameport bus has been occupied.
|
|
|
|
short nFlags; // Flags for Update, User Mode, and if the user is on this page!
|
|
|
|
// local (module-scope) variables
|
|
static HWND hListCtrl;
|
|
short iItem = NO_ITEM; // index of selected item
|
|
extern short iAdvItem;
|
|
|
|
// Global to avoid creating in timer!
|
|
static LPDIJOYSTATE lpDIJoyState;
|
|
|
|
static UINT JoyCfgChangedMsg; // vjoyd JoyConfigChanged message
|
|
static BOOL WINAPI MsgSubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
static WNDPROC fpMainWindowProc;
|
|
|
|
#ifdef _UNICODE
|
|
static PVOID hNotifyDevNode;
|
|
#endif
|
|
|
|
// local message handlers
|
|
static BOOL OnInitDialog (HWND, HWND, LPARAM);
|
|
static void OnCommand (HWND, int, HWND, UINT);
|
|
static BOOL OnNotify (HWND, WPARAM, NMHDR*);
|
|
static void OnDestroy (HWND);
|
|
static void OnListViewContextMenu (HWND hDlg, LPARAM lParam);
|
|
|
|
#ifndef _UNICODE
|
|
BOOL AddListCtrlItem(BYTE nItemID, LPDIJOYCONFIG pJoyConfig);
|
|
#endif
|
|
|
|
|
|
// Share these with Add.cpp
|
|
void OnContextMenu (WPARAM wParam, LPARAM lParam);
|
|
void OnHelp (LPARAM);
|
|
|
|
#ifdef WINNT
|
|
// Share this one with Advanced.cpp
|
|
void RunWDMJOY ( void );
|
|
#endif
|
|
|
|
// local utility fns
|
|
static BOOL DetectHotplug ( HWND hDlg, BYTE nItemSelected );
|
|
static BOOL SetActive ( HWND hDlg );
|
|
static void UpdateListCtrl ( HWND hDlg );
|
|
static void UpdateButtonState ( HWND hDlg );
|
|
static void StatusChanged ( HWND hDlg, BYTE i );
|
|
|
|
JOY::JOY()
|
|
{
|
|
ID = nStatus = nButtons = -1;
|
|
clsidPropSheet = CLSID_LegacyServer;
|
|
fnDeviceInterface = 0;
|
|
}
|
|
|
|
JOY::~JOY()
|
|
{
|
|
if( fnDeviceInterface )
|
|
{
|
|
fnDeviceInterface->Unacquire();
|
|
fnDeviceInterface->Release();
|
|
fnDeviceInterface = 0;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//CPanelProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI CPanelProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch( uMsg )
|
|
{
|
|
case WM_ACTIVATEAPP:
|
|
if( nFlags & ON_PAGE )
|
|
{
|
|
if( wParam )
|
|
{
|
|
if( nFlags & UPDATE_FOR_GEN )
|
|
{
|
|
nFlags &= ~UPDATE_FOR_GEN;
|
|
UpdateListCtrl(hDlg);
|
|
}
|
|
|
|
// Set the focus!
|
|
if( nAssigned )
|
|
{
|
|
if( iItem == NO_ITEM )
|
|
iItem = 0;
|
|
|
|
if( pDIJoyConfig )
|
|
SetActive(hDlg);
|
|
|
|
// restore selection focus
|
|
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
|
|
} else {
|
|
UpdateButtonState(hDlg);
|
|
}
|
|
|
|
// the user is requesting that the CPL be shown
|
|
// and an extention associated with nID be Launched.
|
|
if( nID < NUMJOYDEVS )
|
|
{
|
|
|
|
BYTE nCount = (BYTE)::SendMessage(hListCtrl, LVM_GETITEMCOUNT, 0, 0);
|
|
|
|
while( nCount-- )
|
|
{
|
|
if( pAssigned[GetItemData(hListCtrl, (BYTE)iItem)]->ID == nID )
|
|
{
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
OnCommand(hDlg, IDC_BTN_PROPERTIES, 0, 0);
|
|
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// just to get nID > NUMJOYDEVS!
|
|
nID = (NUMJOYDEVS<<1);
|
|
}
|
|
} else
|
|
{
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
// Click Drag service for PropSheets!
|
|
PostMessage(GetParent(hDlg), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam);
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
if( !HANDLE_WM_INITDIALOG(hDlg, wParam, lParam, OnInitDialog) )
|
|
{
|
|
// Fix #108983 NT, Remove Flash on Error condition.
|
|
SetWindowPos(::GetParent(hDlg), HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW);
|
|
DestroyWindow(hDlg);
|
|
}
|
|
|
|
// if we want to set focus, get the control hWnd
|
|
// and set it as the wParam.
|
|
return(TRUE);
|
|
|
|
case WM_DESTROY:
|
|
HANDLE_WM_DESTROY(hDlg, wParam, lParam, OnDestroy);
|
|
return(1);
|
|
|
|
// OnTimer
|
|
case WM_TIMER:
|
|
{
|
|
BYTE i = nAssigned;
|
|
BYTE nButtons;
|
|
BYTE nLoop;
|
|
|
|
if( nReEnum )
|
|
{
|
|
if( !( --nReEnum & 3 ) )
|
|
{
|
|
// ISSUE-2001/03/29-timgill Much used code
|
|
// (MarcAnd) I hope this code is generally appropriate
|
|
// it appears in much the same form all over the place.
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
// Set the Update Flag!
|
|
nFlags |= UPDATE_ALL;
|
|
UpdateListCtrl(hDlg);
|
|
SetActive(hDlg);
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
}
|
|
}
|
|
|
|
while( i-- )
|
|
{
|
|
if( pAssigned[i]->fnDeviceInterface )
|
|
{
|
|
int nPollFail;
|
|
|
|
pAssigned[i]->fnDeviceInterface->Acquire();
|
|
|
|
// LOOKOUT RE-USE of nButtons!
|
|
nButtons = pAssigned[i]->nStatus;
|
|
|
|
nLoop = 5;
|
|
nPollFail = 0;
|
|
|
|
// Special work for the sidewinder folks...
|
|
// ACT LAB: You can't poll actrs.vxd (ACT LAB) too often, otherwise it fails.
|
|
// See Manbug 41049. - qzheng 8/1/2000
|
|
do
|
|
{
|
|
if( FAILED(pAssigned[i]->fnDeviceInterface->Poll()) ) {
|
|
nPollFail ++;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
Sleep(30);
|
|
} while( nLoop-- );
|
|
|
|
// Check to see if things have changed!
|
|
pAssigned[i]->nStatus = (nPollFail > 2) ? (BYTE)0 : (BYTE)JOY_US_PRESENT;
|
|
|
|
if( pAssigned[i]->nStatus != nButtons )
|
|
{
|
|
StatusChanged(hDlg, i);
|
|
}
|
|
|
|
// Check for button press and set focus to it!!!
|
|
if( pAssigned[i]->nStatus == JOY_US_PRESENT )
|
|
{
|
|
// Do the button press launch thing!
|
|
if( SUCCEEDED(pAssigned[i]->fnDeviceInterface->GetDeviceState(sizeof(DIJOYSTATE), lpDIJoyState)) )
|
|
{
|
|
nButtons = pAssigned[i]->nButtons;
|
|
|
|
// run up the list of buttons and check if there's one that's down!
|
|
while( nButtons-- )
|
|
{
|
|
if( lpDIJoyState->rgbButtons[nButtons] & 0x80 )
|
|
{
|
|
// SetFocus on Selected Item
|
|
SetListCtrlItemFocus(hListCtrl, i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if( nAssigned ) {
|
|
/*
|
|
* If the selected device is "Not Connected", grey out the property button.
|
|
*/
|
|
int id = GetItemData(hListCtrl, (BYTE)iItem);
|
|
PostDlgItemEnableWindow(hDlg, IDC_BTN_PROPERTIES, (BOOL)(pAssigned[id]->nStatus & JOY_US_PRESENT));
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
HANDLE_WM_COMMAND(hDlg, wParam, lParam, OnCommand);
|
|
return(1);
|
|
|
|
case WM_NOTIFY:
|
|
return(HANDLE_WM_NOTIFY(hDlg, wParam, lParam, OnNotify));
|
|
|
|
case WM_POWERBROADCAST:
|
|
switch( wParam )
|
|
{
|
|
case PBT_APMSUSPEND:
|
|
// Suspend operation!
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
break;
|
|
|
|
case PBT_APMRESUMESUSPEND:
|
|
case PBT_APMRESUMECRITICAL:
|
|
// Resume operation!
|
|
SetActive(hDlg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_DEVICECHANGE:
|
|
switch( (UINT)wParam )
|
|
{
|
|
case DBT_DEVICEQUERYREMOVE:
|
|
{
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
BYTE i = (BYTE)::SendMessage(hListCtrl, LVM_GETITEMCOUNT, 0, 0);
|
|
|
|
// Acquire All Devices that are Attached!!!
|
|
char nIndex;
|
|
|
|
while( i-- )
|
|
{
|
|
// get joystick config of item
|
|
nIndex = (char)GetItemData(hListCtrl, i);
|
|
|
|
if( pAssigned[nIndex]->nStatus & JOY_US_PRESENT )
|
|
pAssigned[nIndex]->fnDeviceInterface->Unacquire();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DBT_DEVICEARRIVAL:
|
|
case DBT_DEVICEREMOVECOMPLETE:
|
|
if( nFlags & ON_PAGE )
|
|
{
|
|
PostMessage(hDlg, WM_COMMAND, IDC_BTN_REFRESH, 0);
|
|
|
|
#if 0
|
|
if( !(nFlags & BLOCK_UPDATE) )
|
|
{
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
// Set the Update Flag!
|
|
nFlags |= UPDATE_ALL;
|
|
|
|
UpdateListCtrl(hDlg);
|
|
|
|
SetActive(hDlg);
|
|
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_HELP:
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
OnHelp(lParam);
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
nFlags &= ~ON_PAGE;
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
OnContextMenu(wParam, lParam);
|
|
nFlags |= ON_PAGE;
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// StatusChanged( HWND hDlg, BYTE i )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void StatusChanged( HWND hDlg, BYTE i )
|
|
{
|
|
// Update the buttons and set focus to changed item!
|
|
PostDlgItemEnableWindow(hDlg, IDC_BTN_PROPERTIES, (BOOL)(pAssigned[i]->nStatus & JOY_US_PRESENT));
|
|
|
|
if( pAssigned[0] )
|
|
{
|
|
PostDlgItemEnableWindow(hDlg, IDC_BTN_REMOVE, TRUE );
|
|
}
|
|
|
|
// Don't try to make this buffer any smaller...
|
|
// Remember... we also have "Not Connected"!
|
|
TCHAR sz[20];
|
|
|
|
// display result
|
|
VERIFY(LoadString(ghInstance, (pAssigned[i]->nStatus & JOY_US_PRESENT) ? IDS_GEN_STATUS_OK : IDS_GEN_STATUS_NOTCONNECTED, (LPTSTR)&sz, 20));
|
|
|
|
|
|
LVFINDINFO *lpFindInfo = new (LVFINDINFO);
|
|
ASSERT (lpFindInfo);
|
|
|
|
ZeroMemory(lpFindInfo, sizeof(LVFINDINFO));
|
|
|
|
lpFindInfo->flags = LVFI_PARAM;
|
|
lpFindInfo->lParam = i;
|
|
|
|
// Make sure you place i where it's suppose to be!
|
|
i = (BYTE)::SendMessage(hListCtrl, LVM_FINDITEM, (WPARAM)(int)-1, (LPARAM)(const LVFINDINFO*)lpFindInfo);
|
|
|
|
if( lpFindInfo )
|
|
delete (lpFindInfo);
|
|
|
|
SetItemText(hListCtrl, i, STATUS_COLUMN, sz);
|
|
::PostMessage(hListCtrl, LVM_UPDATE, (WPARAM)i, 0L);
|
|
SetListCtrlItemFocus(hListCtrl, i);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//OnInitDialog(HWND hDlg, HWND hWnd, LPARAM lParam)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL OnInitDialog(HWND hDlg, HWND hWnd, LPARAM lParam)
|
|
{
|
|
// initialize our list control
|
|
hListCtrl = GetDlgItem(hDlg, IDC_LIST_DEVICE);
|
|
ASSERT(hListCtrl);
|
|
|
|
// LVS_EX_ONECLICKACTIVATE removed per PSierra | LVS_EX_INFOTIP
|
|
::SendMessage(hListCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
|
|
|
|
if( !lpDIInterface )
|
|
{
|
|
if( FAILED(DirectInputCreate(ghInstance, DIRECTINPUT_VERSION, &lpDIInterface, NULL)) )
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("GCDEF.DLL: DirectInputCreate() failed\n"));
|
|
#endif
|
|
Error((short)IDS_INTERNAL_ERROR, (short)IDS_NO_DIJOYCONFIG);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
// Dynamically size the columns!
|
|
RECT rc;
|
|
::GetClientRect(hListCtrl, &rc);
|
|
|
|
// cut the list control into 1/4ths
|
|
rc.right >>= 2;
|
|
|
|
// This one get's 3/4ths
|
|
InsertColumn(hListCtrl, DEVICE_COLUMN, IDS_GEN_DEVICE_HEADING, (USHORT)(rc.right*3));
|
|
|
|
// Column heading for Status
|
|
InsertColumn(hListCtrl, STATUS_COLUMN, IDS_GEN_STATUS_HEADING, (USHORT)(rc.right+3));
|
|
|
|
if( !pDIJoyConfig )
|
|
{
|
|
|
|
// just in case CoCreateInstanceFailed...
|
|
if( FAILED(lpDIInterface->QueryInterface(IID_IDirectInputJoyConfig, (LPVOID*)&pDIJoyConfig)) )
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString (TEXT("JOY.CPL: CoCreateInstance Failed... Closing CPL!\n"));
|
|
#endif
|
|
Error((short)IDS_INTERNAL_ERROR, (short)IDS_NO_DIJOYCONFIG);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
VERIFY (SUCCEEDED(pDIJoyConfig->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_BACKGROUND)));
|
|
}
|
|
|
|
// Zero out the global counters!
|
|
#ifndef _UNICODE
|
|
nGameportDriver = 0;
|
|
#endif
|
|
nGamingDevices = nGameportBus = 0;
|
|
|
|
// Try to Acquire, if you fail... Disable the Add and Remove buttons!
|
|
if( pDIJoyConfig->Acquire() == DIERR_INSUFFICIENTPRIVS )
|
|
{
|
|
nFlags |= USER_MODE;
|
|
|
|
LONG style = ::GetWindowLong(hListCtrl, GWL_STYLE);
|
|
style &= ~LVS_EDITLABELS;
|
|
|
|
::SetWindowLong(hListCtrl, GWL_STYLE, style);
|
|
}
|
|
#ifdef WINNT
|
|
else
|
|
{
|
|
//Run the WDMJOY.INF file!!!
|
|
RunWDMJOY();
|
|
pDIJoyConfig->SendNotify();
|
|
}
|
|
#endif
|
|
|
|
if( FAILED(pDIJoyConfig->EnumTypes((LPDIJOYTYPECALLBACK)DIEnumJoyTypeProc, NULL)) )
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString( TEXT("JOY.CPL: Failed BuildEnumList!\n") );
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
// Don't allow Add if there is nothing to add!
|
|
// OR no port to add them to!
|
|
if( ((!nGameportBus) && (!nGamingDevices))
|
|
#ifdef _UNICODE
|
|
|| GetSystemMetrics(SM_REMOTESESSION)
|
|
#endif
|
|
) {
|
|
PostDlgItemEnableWindow(hDlg, IDC_BTN_ADD, FALSE);
|
|
}
|
|
|
|
// register the JOY_CONFIGCHANGED_MSGSTRING defined in MMDDK.H if you're on Memphis
|
|
JoyCfgChangedMsg = (nFlags & ON_NT) ? NULL : RegisterWindowMessage(TEXT("MSJSTICK_VJOYD_MSGSTR"));
|
|
|
|
// blj: Warning Message that you can't add any more devices!
|
|
if( nGamingDevices == MAX_DEVICES-1 )
|
|
Error((short)IDS_MAX_DEVICES_TITLE, (short)IDS_MAX_DEVICES_MSG);
|
|
|
|
// blj: beginning of fix for 5.0 to turn on all devices!
|
|
LPDIJOYCONFIG_DX5 pJoyConfig = new (DIJOYCONFIG_DX5);
|
|
ASSERT (pJoyConfig);
|
|
|
|
ZeroMemory(pJoyConfig, sizeof(DIJOYCONFIG_DX5));
|
|
|
|
pJoyConfig->dwSize = sizeof(DIJOYCONFIG_DX5);
|
|
|
|
// Set the hour glass
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
BYTE nIndex = nAssigned;
|
|
HRESULT hr;
|
|
|
|
while( nIndex )
|
|
{
|
|
hr = pDIJoyConfig->GetConfig(pAssigned[--nIndex]->ID, (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE);
|
|
|
|
if( (hr == S_FALSE) || FAILED(hr) )
|
|
continue;
|
|
|
|
if( pJoyConfig->hwc.dwUsageSettings & JOY_US_PRESENT )
|
|
continue;
|
|
|
|
pJoyConfig->hwc.dwUsageSettings |= JOY_US_PRESENT;
|
|
|
|
VERIFY(SUCCEEDED(pDIJoyConfig->SetConfig(pAssigned[nIndex]->ID, (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE)));
|
|
|
|
// Fix #55524
|
|
VERIFY(SUCCEEDED(pDIJoyConfig->GetConfig(pAssigned[nIndex]->ID, (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE)));
|
|
|
|
if( !(pJoyConfig->hwc.dwUsageSettings & JOY_US_PRESENT) )
|
|
{
|
|
if( SUCCEEDED(pDIJoyConfig->Acquire()) )
|
|
{
|
|
pJoyConfig->hwc.dwUsageSettings |= JOY_US_PRESENT;
|
|
pJoyConfig->hwc.hwv.dwCalFlags |= 0x80000000;
|
|
VERIFY(SUCCEEDED(pDIJoyConfig->SetConfig(pAssigned[nIndex]->ID, (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE)));
|
|
}
|
|
}
|
|
// end of Fix #55524
|
|
}
|
|
|
|
if( pJoyConfig ) delete (pJoyConfig);
|
|
// blj: end of fix for 5.0 to turn on all devices!
|
|
|
|
// Set the hour glass
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
HWND hParentWnd = GetParent(hDlg);
|
|
|
|
GetWindowRect(hParentWnd, &rc);
|
|
|
|
// Only center the dialog if this was the page that we started on!
|
|
if( (nStartPageCPL == 0) || (nStartPageCPL == NUMJOYDEVS) )
|
|
{
|
|
// Centre the Dialog!
|
|
SetWindowPos(hParentWnd, NULL,
|
|
(GetSystemMetrics(SM_CXSCREEN) - (rc.right-rc.left))>>1,
|
|
(GetSystemMetrics(SM_CYSCREEN) - (rc.bottom-rc.top))>>1,
|
|
NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
|
|
if( nStartPageCPL == NUMJOYDEVS )
|
|
PostMessage(hDlg, WM_COMMAND, IDC_BTN_ADD, 0);
|
|
}
|
|
|
|
// Do that move button thing!
|
|
MoveOK(hParentWnd);
|
|
|
|
// this is required because the CPL can be launched via RUNDLL32
|
|
if( ::IsWindow(hParentWnd) )
|
|
hParentWnd = GetParent(hParentWnd);
|
|
|
|
// Since the JOY_CONFIGCHANGED_MSGSTRING msg only gets sent to top-level
|
|
// windows, this calls for a subclass!
|
|
if( JoyCfgChangedMsg )
|
|
fpMainWindowProc = (WNDPROC)SetWindowLongPtr(hParentWnd, GWLP_WNDPROC, (LONG_PTR)MsgSubClassProc);
|
|
|
|
// Set bOnPage so WM_ACTIVATEAPP will work!
|
|
nFlags |= ON_PAGE;
|
|
|
|
// Update the list ctrl!
|
|
nFlags |= UPDATE_FOR_GEN;
|
|
|
|
// to put the selection on the first item on startup...
|
|
if( nAssigned )
|
|
iItem = 0;
|
|
|
|
lpDIJoyState = new (DIJOYSTATE);
|
|
ASSERT (lpDIJoyState);
|
|
|
|
ZeroMemory(lpDIJoyState, sizeof(DIJOYSTATE));
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code)
|
|
{
|
|
switch( id )
|
|
{
|
|
case IDC_WHATSTHIS:
|
|
{
|
|
// point to help file
|
|
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
|
|
ASSERT (pszHelpFileName);
|
|
|
|
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
|
|
WinHelp((HWND)hListCtrl, pszHelpFileName, HELP_WM_HELP, (ULONG_PTR)gaHelpIDs);
|
|
#ifdef _DEBUG
|
|
else
|
|
OutputDebugString(TEXT("JOY.CPL: OnCommand: LoadString Failed to find IDS_HELPFILENAME!\n"));
|
|
#endif // _DEBUG
|
|
|
|
if( pszHelpFileName ) {
|
|
delete[] (pszHelpFileName);
|
|
}
|
|
}
|
|
return;
|
|
|
|
case IDC_BTN_REMOVE:
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
nFlags &= ~ON_PAGE;
|
|
|
|
// Block Update, otherwise we'll be forced to update and we don't need to!
|
|
nFlags |= BLOCK_UPDATE;
|
|
|
|
if( nFlags & USER_MODE )
|
|
Error((short)IDS_USER_MODE_TITLE, (short)IDS_USER_MODE);
|
|
else if( DeleteSelectedItem((PBYTE)&iItem) )
|
|
{
|
|
UpdateButtonState(hDlg);
|
|
|
|
// Set the UpdateFlag!
|
|
nFlags |= UPDATE_FOR_ADV;
|
|
|
|
// Set the default push button to the Add button!
|
|
::PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)1, (LPARAM)LOWORD(FALSE));
|
|
}
|
|
|
|
// Unblock the WM_DEVICECHANGE message handler!
|
|
nFlags &= ~BLOCK_UPDATE;
|
|
|
|
nFlags |= ON_PAGE;
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
break;
|
|
|
|
case IDC_BTN_ADD:
|
|
// Don't set ON_PAGE flag!
|
|
// We need the WM_DEVICECHANGE message in the case a user plugs in a device!
|
|
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
ClearArrays();
|
|
|
|
// Clear everything up before you call this...
|
|
if( FAILED(pDIJoyConfig->EnumTypes((LPDIJOYTYPECALLBACK)DIEnumJoyTypeProc, NULL)) )
|
|
break;
|
|
|
|
nFlags &= ~ON_PAGE;
|
|
|
|
if( nFlags & USER_MODE )
|
|
{
|
|
Error((short)IDS_USER_MODE_TITLE, (short)IDS_USER_MODE);
|
|
}
|
|
// call AddDevice dialog
|
|
else if( DialogBox( ghInstance, (PTSTR)IDD_ADD, hDlg, (DLGPROC)AddDialogProc ) == IDOK )
|
|
{
|
|
SendMessage(hDlg, WM_COMMAND, IDC_BTN_REFRESH, 0);
|
|
}
|
|
|
|
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
|
|
|
|
nFlags &= ~BLOCK_UPDATE;
|
|
nFlags |= ON_PAGE;
|
|
|
|
// Now, we set it back active!
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
break;
|
|
|
|
case IDC_BTN_REFRESH:
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
nFlags |= UPDATE_ALL;
|
|
|
|
pDIJoyConfig->Acquire();
|
|
pDIJoyConfig->SendNotify();
|
|
|
|
UpdateListCtrl(hDlg);
|
|
UpdateButtonState(hDlg);
|
|
|
|
pDIJoyConfig->SendNotify();
|
|
pDIJoyConfig->Unacquire();
|
|
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
break;
|
|
|
|
case IDC_RENAME:
|
|
// Don't allow editing of Mouse or Keyboard names!
|
|
// Don't allow renaming if in USER mode!
|
|
if( !(nFlags & USER_MODE) )
|
|
{
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
::PostMessage(hListCtrl, LVM_EDITLABEL, (WPARAM)(int)iItem, 0);
|
|
}
|
|
return;
|
|
|
|
/* If we want this back...
|
|
case IDC_SW_HACK:
|
|
{
|
|
// SideWinder Hack button!
|
|
BYTE nID = pAssigned[GetItemData(hListCtrl, (BYTE)iItem)]->ID;
|
|
|
|
if (nID == 0)
|
|
{
|
|
::PostMessage(GetDlgItem(hDlg, IDC_SW_HACK), BM_SETCHECK, BST_CHECKED, 0);
|
|
//CheckDlgButton(hDlg, IDC_SW_HACK, BST_CHECKED);
|
|
break;
|
|
}
|
|
|
|
// Get the Selected Item and force its ID to Zero!
|
|
SwapIDs((BYTE)nID, (BYTE)0);
|
|
}
|
|
*/
|
|
// Missing break intentional!
|
|
// Used to fall into IDC_BTN_REFRESH!
|
|
|
|
case IDC_BTN_TSHOOT:
|
|
{
|
|
LPTSTR lpszCmd = new (TCHAR[STR_LEN_64]);
|
|
ASSERT (lpszCmd);
|
|
|
|
if( LoadString(ghInstance, IDS_TSHOOT_CMD, lpszCmd, STR_LEN_64) )
|
|
{
|
|
LPSTARTUPINFO pSi = (LPSTARTUPINFO)_alloca(sizeof(STARTUPINFO));
|
|
LPPROCESS_INFORMATION pPi = (LPPROCESS_INFORMATION)_alloca(sizeof(PROCESS_INFORMATION));
|
|
|
|
ZeroMemory(pSi, sizeof(STARTUPINFO));
|
|
ZeroMemory(pPi, sizeof(PROCESS_INFORMATION));
|
|
|
|
pSi->cb = sizeof(STARTUPINFO);
|
|
pSi->dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
|
|
pSi->wShowWindow = SW_NORMAL;
|
|
|
|
if( CreateProcess(0, lpszCmd, 0, 0, 0, 0, 0, 0, pSi, pPi) )
|
|
{
|
|
CloseHandle(pPi->hThread);
|
|
CloseHandle(pPi->hProcess);
|
|
}
|
|
}
|
|
|
|
if( lpszCmd )
|
|
delete[] (lpszCmd);
|
|
}
|
|
break;
|
|
|
|
#if 0 //disable UPDATE button, see manbug 33666.
|
|
case IDC_BTN_UPDATE:
|
|
if (DialogBox(ghInstance, MAKEINTRESOURCE(IDD_UPDATE), hDlg, CplUpdateProc) == IDOK)
|
|
{
|
|
Update( hDlg, 1, NULL ); //NO Proxy
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case IDC_BTN_PROPERTIES:
|
|
|
|
// Because PSN_KILLACTIVE is not sent... we do it ourselves
|
|
// kill status timer
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
nFlags &= ~ON_PAGE;
|
|
|
|
{
|
|
char nIndex = (char)GetItemData(hListCtrl, (BYTE)iItem);
|
|
|
|
// default to the first page!
|
|
#ifdef _DEBUG
|
|
HRESULT hr =
|
|
#endif _DEBUG
|
|
Launch(hDlg, pAssigned[nIndex], IsEqualIID(pAssigned[nIndex]->clsidPropSheet, CLSID_LegacyServer) ? 1 : 0);
|
|
|
|
#ifdef _DEBUG
|
|
switch( hr )
|
|
{
|
|
case DIGCERR_NUMPAGESZERO:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NUMPAGESZERO!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_NODLGPROC:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NODLGPROC!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_NOPREPOSTPROC:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NOPREPOSTPROC!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_NOTITLE:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NOTITLE!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_NOCAPTION:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NOCAPTION!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_NOICON:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NOICON!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_STARTPAGETOOLARGE:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_STARTPAGETOOLARGE!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_NUMPAGESTOOLARGE:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_NUMPAGESTOOLARGE!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case DIGCERR_INVALIDDWSIZE:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error DIGCERR_INVALIDDWSIZE!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case E_NOINTERFACE:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error E_NOINTERFACE!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
case E_OUTOFMEMORY:
|
|
TRACE (TEXT("JOY.CPL: Launch failed device ID #%d, Page #%d, with the error E_OUTOFMEMORY!\n"), pAssigned[nIndex]->ID, id);
|
|
break;
|
|
|
|
//case DIGCERR_NUMPAGESTOOLARGE:
|
|
//case DIGCERR_STARTPAGETOOLARGE:
|
|
|
|
default:
|
|
// Only display this return code if things are going Really weird.
|
|
TRACE (TEXT("JOY.CPL: Launch return code is %x %s!\n"), hr, strerror(hr));
|
|
break;
|
|
}
|
|
#endif // _DEBUG
|
|
|
|
nFlags |= ON_PAGE;
|
|
|
|
//OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: returned from Property sheet!\n"));
|
|
|
|
InvalidateRect(hDlg, NULL, TRUE);
|
|
UpdateWindow(hDlg);
|
|
|
|
// Now, we set it back active!
|
|
// create timer
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Set the focus where we left off!
|
|
if( iItem == NO_ITEM )
|
|
iItem = 0;
|
|
|
|
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// OnNotify(HWND hDlg, WPARAM idFrom, NMHDR* pnmhdr)
|
|
// Purpose: WM_NOTIFY Handler
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
BOOL OnNotify(HWND hDlg, WPARAM idFrom, NMHDR* pnmhdr)
|
|
{
|
|
switch( pnmhdr->code )
|
|
{
|
|
case PSN_QUERYCANCEL:
|
|
if( nFlags & UPDATE_INPROCESS )
|
|
nFlags &= ~UPDATE_INPROCESS;
|
|
break;
|
|
|
|
case LVN_BEGINLABELEDIT:
|
|
if( nFlags & USER_MODE )
|
|
return(TRUE);
|
|
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
::PostMessage((HWND)::SendMessage(hListCtrl, LVM_GETEDITCONTROL, 0, 0), EM_SETLIMITTEXT, MAX_STR_LEN, 0);
|
|
|
|
// This lets us know if the edit field is up!
|
|
nFlags |= UPDATE_INPROCESS;
|
|
return(FALSE);
|
|
|
|
/*
|
|
case LVN_GETINFOTIP:
|
|
{
|
|
LPLVHITTESTINFO lpHit = new (LVHITTESTINFO);
|
|
ASSERT (lpHit);
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
POINT pt;
|
|
GetCursorPos(&pt);
|
|
ScreenToClient(hListCtrl, &pt);
|
|
|
|
lpHit->pt = pt;
|
|
lpHit->flags = lpHit->iItem = lpHit->iSubItem = 0;
|
|
|
|
::SendMessage(hListCtrl, LVM_SUBITEMHITTEST, 0, (LPARAM)(LPLVHITTESTINFO)lpHit);
|
|
|
|
// We only want to support the device column!
|
|
if (lpHit->iSubItem == 0)
|
|
{
|
|
if (lpHit->flags & LVHT_ONITEMLABEL)
|
|
{
|
|
// Determine the text length of the column text
|
|
LPTSTR lpStr = new (TCHAR[MAX_STR_LEN+1]);
|
|
ASSERT (lpStr);
|
|
|
|
GetItemText(hListCtrl, lpHit->iItem, lpHit->iSubItem, lpStr, MAX_STR_LEN);
|
|
|
|
// Determine if the latter will fit inside the former...
|
|
SIZE size;
|
|
HDC hDC = GetDC(hListCtrl);
|
|
GetTextExtentPoint(hDC, lpStr, lstrlen(lpStr), &size);
|
|
ReleaseDC(hListCtrl, hDC);
|
|
|
|
// Determine how wide the column is!
|
|
short nWidth = (short)::SendMessage(hListCtrl, LVM_GETCOLUMNWIDTH, lpHit->iSubItem, 0);
|
|
|
|
bRet = (BOOL)(size.cx > nWidth);
|
|
|
|
if (bRet)
|
|
// if not, copy the text into lpHit->pszText
|
|
_tcscpy(((LPNMLVGETINFOTIP)pnmhdr)->pszText, lpStr);
|
|
|
|
if (lpStr)
|
|
delete[] (lpStr);
|
|
}
|
|
}
|
|
|
|
if (lpHit)
|
|
delete (lpHit);
|
|
|
|
return bRet;
|
|
}
|
|
*/
|
|
|
|
case LVN_ENDLABELEDIT:
|
|
if( nFlags & UPDATE_INPROCESS )
|
|
{
|
|
HWND hCtrl = (HWND)::SendMessage(hListCtrl, LVM_GETEDITCONTROL, 0, 0);
|
|
ASSERT(::IsWindow(hCtrl));
|
|
|
|
if( ::SendMessage(hCtrl, EM_GETMODIFY, 0, 0) )
|
|
{
|
|
BYTE nLen = (BYTE)lstrlen(((NMLVDISPINFO *)pnmhdr)->item.pszText);
|
|
|
|
if( (nLen > MAX_STR_LEN) || (nLen == 0) )
|
|
MessageBeep(MB_ICONHAND);
|
|
|
|
// Make sure the name is usable!
|
|
else if( _tcschr(((NMLVDISPINFO *)pnmhdr)->item.pszText, TEXT('\\')) )
|
|
{
|
|
Error((short)IDS_INVALID_NAME_TITLE, (short)IDS_INVALID_NAME);
|
|
} else
|
|
{
|
|
// Set the Update flag!
|
|
nFlags |= UPDATE_ALL;
|
|
|
|
LPDIPROPSTRING pDIPropString = new (DIPROPSTRING);
|
|
ASSERT (pDIPropString);
|
|
|
|
ZeroMemory(pDIPropString, sizeof(DIPROPSTRING));
|
|
|
|
pDIPropString->diph.dwSize = sizeof(DIPROPSTRING);
|
|
pDIPropString->diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
pDIPropString->diph.dwHow = DIPH_DEVICE;
|
|
|
|
#ifdef _UNICODE
|
|
wcscpy(pDIPropString->wsz, ((NMLVDISPINFO *)pnmhdr)->item.pszText);
|
|
#else
|
|
USES_CONVERSION;
|
|
wcscpy(pDIPropString->wsz, A2W(((NMLVDISPINFO *)pnmhdr)->item.pszText));
|
|
#endif
|
|
if( SUCCEEDED(pAssigned[iItem]->fnDeviceInterface->SetProperty(DIPROP_INSTANCENAME, &pDIPropString->diph)) )
|
|
{
|
|
SetItemText(hListCtrl, (BYTE)iItem, 0, ((NMLVDISPINFO *)pnmhdr)->item.pszText);
|
|
} else
|
|
{
|
|
Error((short)IDS_NO_RENAME_TITLE, (short)IDS_NO_RENAME);
|
|
}
|
|
|
|
if( pDIPropString )
|
|
delete (pDIPropString);
|
|
|
|
// Trip the flag so the Advanced page knows it needs to update!
|
|
nFlags |= UPDATE_FOR_ADV;
|
|
}
|
|
}
|
|
// Clear the InProcess flag!
|
|
nFlags &= ~UPDATE_INPROCESS;
|
|
|
|
}
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
break;
|
|
|
|
case LVN_KEYDOWN:
|
|
switch( ((LV_KEYDOWN*)pnmhdr)->wVKey )
|
|
{
|
|
case VK_DELETE:
|
|
if( iItem != NO_ITEM )
|
|
SendMessage(hDlg, WM_COMMAND, IDC_BTN_REMOVE, 0);
|
|
break;
|
|
|
|
case VK_F5:
|
|
nFlags |= UPDATE_ALL;
|
|
|
|
UpdateListCtrl(hDlg);
|
|
|
|
if( GetKeyState(VK_SHIFT) & 0x80 )
|
|
{
|
|
#ifdef WINNT
|
|
RunWDMJOY();
|
|
#endif
|
|
ClearArrays();
|
|
|
|
pDIJoyConfig->EnumTypes((LPDIJOYTYPECALLBACK)DIEnumJoyTypeProc, NULL);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
#if 0
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
CListCtrl *pCtrl = new (CListCtrl);
|
|
ASSERT(pCtrl);
|
|
|
|
pCtrl->Attach(hListCtrl);
|
|
|
|
if( ((NM_LISTVIEW*)pnmhdr)->iSubItem )
|
|
{
|
|
static bItemDirection = TRUE;
|
|
|
|
SortTextItems(pCtrl, 0, bItemDirection =! bItemDirection, 0, -1);
|
|
} else
|
|
{
|
|
static bLabelDirection = TRUE;
|
|
|
|
SortTextItems(pCtrl, 0, bLabelDirection =! bLabelDirection, 0, -1);
|
|
}
|
|
|
|
pCtrl->Detach();
|
|
|
|
if( pCtrl )
|
|
delete (pCtrl);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case LVN_ITEMCHANGED:
|
|
if( iItem != NO_ITEM )
|
|
{
|
|
// get index of selected item
|
|
// no point if it's not changed!
|
|
if( iItem != (short)((NM_LISTVIEW*)pnmhdr)->iItem )
|
|
{
|
|
int i = GetItemData(hListCtrl, (char)iItem);
|
|
|
|
iItem = (short)((NM_LISTVIEW*)pnmhdr)->iItem;
|
|
|
|
iAdvItem = pAssigned[i]->ID;
|
|
|
|
UpdateButtonState(hDlg);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_DBLCLK:
|
|
switch( idFrom )
|
|
{
|
|
case IDC_LIST_DEVICE:
|
|
if( iItem == NO_ITEM )
|
|
{
|
|
if( !(nFlags & USER_MODE) && nGameportBus )
|
|
OnCommand(hDlg, IDC_BTN_ADD, 0, 0);
|
|
} else if( IsWindowEnabled(GetDlgItem(hDlg, IDC_BTN_PROPERTIES)) )
|
|
{
|
|
// make sure the connected one has got an interface pointer...
|
|
OnCommand(hDlg, IDC_BTN_PROPERTIES, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PSN_KILLACTIVE:
|
|
KillTimer(hDlg, ID_MYTIMER);
|
|
|
|
nFlags &= ~ON_PAGE;
|
|
|
|
if( nFlags & UPDATE_INPROCESS )
|
|
SetFocus(hListCtrl);
|
|
|
|
#ifdef _UNICODE
|
|
if( hNotifyDevNode )
|
|
UnregisterDeviceNotification(hNotifyDevNode);
|
|
#endif
|
|
PostMessage(hDlg, WM_ACTIVATEAPP, FALSE, 0);
|
|
break;
|
|
|
|
case PSN_SETACTIVE:
|
|
nFlags |= ON_PAGE;
|
|
nFlags |= UPDATE_FOR_GEN;
|
|
|
|
#ifdef _UNICODE
|
|
// Set up the Device Notification
|
|
RegisterForDevChange(hDlg, &hNotifyDevNode);
|
|
#endif
|
|
SendMessage(hDlg, WM_ACTIVATEAPP, TRUE, 0);
|
|
break;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// OnDestroy(HWND hWnd)
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
void OnDestroy(HWND hWnd)
|
|
{
|
|
SetWindowPos( GetParent(hWnd), NULL, NULL, NULL, NULL, NULL,
|
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW);
|
|
|
|
if( lpDIJoyState )
|
|
delete (lpDIJoyState);
|
|
|
|
// if you are looking for where the following variables are deleted, look
|
|
// in DLL_PROCESS_DETACH in MAIN.CPP:
|
|
// pwszTypeArray, pwszGameportDriverArray, pwszGameportBus
|
|
// This is done because of the way several Microsoft games load the CPL and
|
|
// Don't Unload it between loads.
|
|
|
|
// Clear pAssigned
|
|
while( nAssigned )
|
|
{
|
|
if( pAssigned[--nAssigned] )
|
|
{
|
|
delete (pAssigned[nAssigned]);
|
|
|
|
pAssigned[nAssigned] = 0;
|
|
}
|
|
}
|
|
// delete all existing entries
|
|
//::PostMessage(hListCtrl, LVM_DELETEALLITEMS, 0, 0);
|
|
|
|
// release the DI JoyConfig interface pointer
|
|
if( pDIJoyConfig )
|
|
{
|
|
pDIJoyConfig->Release();
|
|
pDIJoyConfig = 0;
|
|
}
|
|
|
|
// release the DI Device interface pointer
|
|
if( lpDIInterface )
|
|
{
|
|
lpDIInterface->Release();
|
|
lpDIInterface = 0;
|
|
}
|
|
|
|
// Drop the subclass, else you'll crash!
|
|
if( !(nFlags & ON_NT) )
|
|
SetWindowLongPtr(GetParent(GetParent(hWnd)), GWLP_WNDPROC, (LONG_PTR)fpMainWindowProc);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// OnHelp(LPARAM lParam)
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
void OnHelp(LPARAM lParam)
|
|
{
|
|
// point to help file
|
|
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
|
|
ASSERT (pszHelpFileName);
|
|
|
|
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
|
|
{
|
|
if( ((LPHELPINFO)lParam)->iContextType == HELPINFO_WINDOW )
|
|
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, pszHelpFileName, HELP_WM_HELP, (ULONG_PTR)gaHelpIDs);
|
|
|
|
}
|
|
#ifdef _DEBUG
|
|
else OutputDebugString(TEXT("JOY.CPL: OnHelp: LoadString Failed to find IDS_HELPFILENAME!\n"));
|
|
#endif
|
|
|
|
if( pszHelpFileName )
|
|
delete[] (pszHelpFileName);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// OnContextMenu(WPARAM wParam)
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
void OnContextMenu(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// this prevents double handling of this message
|
|
if( (HWND)wParam == hListCtrl )
|
|
{
|
|
OnListViewContextMenu(GetParent((HWND)wParam), lParam);
|
|
return;
|
|
}
|
|
|
|
// point to help file
|
|
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
|
|
ASSERT (pszHelpFileName);
|
|
|
|
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
|
|
WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (ULONG_PTR)gaHelpIDs);
|
|
#ifdef _DEBUG
|
|
else OutputDebugString(TEXT("JOY.CPL: OnContextMenu: LoadString Failed to find IDS_HELPFILENAME!\n"));
|
|
#endif
|
|
|
|
if( pszHelpFileName )
|
|
delete[] (pszHelpFileName);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// OnListViewContextMenu(HWND hDlg)
|
|
// Purpose: Query the plug-in for the selected device for it's characteristics
|
|
// Then construct a menu to reflect your findings
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
void OnListViewContextMenu(HWND hDlg, LPARAM lParam)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
HMENU hPopupMenu = CreatePopupMenu();
|
|
ASSERT (hPopupMenu);
|
|
|
|
LPTSTR psz = new TCHAR[STR_LEN_32];
|
|
ASSERT (psz);
|
|
|
|
// Add the Refresh text
|
|
VERIFY(LoadString(ghInstance, IDS_REFRESH, psz, STR_LEN_32));
|
|
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_BTN_REFRESH, psz);
|
|
|
|
// Add the Add text
|
|
|
|
HWND hCtrl;
|
|
|
|
// Only Display Add menu option if we've found a GameportBus!!!
|
|
if( nGameportBus
|
|
#ifdef _UNICODE
|
|
&& !GetSystemMetrics(SM_REMOTESESSION)
|
|
#endif
|
|
)
|
|
{
|
|
hCtrl = GetDlgItem(hDlg, IDC_BTN_ADD);
|
|
ASSERT(hCtrl);
|
|
|
|
if( IsWindowEnabled(hCtrl) )
|
|
{
|
|
::SendMessage(hCtrl, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)(LPCTSTR)psz);
|
|
|
|
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_BTN_ADD, psz);
|
|
if( !bRet )
|
|
TRACE(TEXT("JOY.CPL: AppendMenu Failed to insert %s\n"), psz);
|
|
}
|
|
}
|
|
|
|
// Add the Remove text
|
|
hCtrl = GetDlgItem(hDlg, IDC_BTN_REMOVE);
|
|
ASSERT(hCtrl);
|
|
|
|
// Only Show it if it's available
|
|
if( IsWindowEnabled(hCtrl) && (iItem != NO_ITEM) )
|
|
{
|
|
::SendMessage(hCtrl, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)(LPCTSTR)psz);
|
|
|
|
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_BTN_REMOVE, psz);
|
|
if( !bRet )
|
|
TRACE(TEXT("JOY.CPL: AppendMenu Failed to insert %s\n"), psz);
|
|
}
|
|
|
|
// Add the Properties text
|
|
hCtrl = GetDlgItem(hDlg, IDC_BTN_PROPERTIES);
|
|
ASSERT (hCtrl);
|
|
|
|
if( IsWindowEnabled(hCtrl) )
|
|
{
|
|
::SendMessage(hCtrl, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)(LPCTSTR)psz);
|
|
|
|
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_BTN_PROPERTIES, psz);
|
|
if( !bRet )
|
|
TRACE(TEXT("JOY.CPL: AppendMenu Failed to insert %s\n"), psz);
|
|
}
|
|
|
|
// Add the Rename text if not a USER!
|
|
if( !(nFlags & USER_MODE) )
|
|
{
|
|
if( nAssigned && (iItem != NO_ITEM) )
|
|
{
|
|
VERIFY(LoadString(ghInstance, IDS_RENAME, psz, STR_LEN_32));
|
|
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_RENAME, psz);
|
|
}
|
|
}
|
|
|
|
bRet = AppendMenu(hPopupMenu, MF_SEPARATOR, 0, 0);
|
|
if( !bRet )
|
|
TRACE(TEXT("JOY.CPL: AppendMenu Failed to insert the separator!\n"), psz);
|
|
|
|
VERIFY(LoadString(ghInstance, IDS_WHATSTHIS, psz, STR_LEN_32));
|
|
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_WHATSTHIS, psz);
|
|
if( !bRet )
|
|
TRACE(TEXT("JOY.CPL: AppendMenu Failed to insert %s\n"), psz);
|
|
|
|
if( psz ) delete[] (psz);
|
|
|
|
POINT pt;
|
|
|
|
// lParam is -1 if we got here via Shift+F10
|
|
if( lParam > 0 )
|
|
{
|
|
pt.x = GET_X_LPARAM(lParam);
|
|
pt.y = GET_Y_LPARAM(lParam);
|
|
} else
|
|
{
|
|
// Centre the popup on the selected item!
|
|
|
|
// This get's a good X pos, but the y is the start of the control!
|
|
::SendMessage(hListCtrl, LVM_GETITEMPOSITION, iItem, (LPARAM)&pt);
|
|
|
|
RECT rc;
|
|
::GetClientRect(hListCtrl, &rc);
|
|
|
|
pt.x = rc.right>>1;
|
|
|
|
ClientToScreen(hListCtrl, &pt);
|
|
}
|
|
|
|
// restore selection focus
|
|
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
|
|
|
|
bRet = TrackPopupMenu (hPopupMenu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hDlg, NULL);
|
|
if( !bRet )
|
|
TRACE (TEXT("JOY.CPL: TrackPopupMenu Failed!\n"));
|
|
|
|
if(hPopupMenu) DestroyMenu (hPopupMenu); // PREFIX 45088
|
|
|
|
// Set the focus back to the item it came from!
|
|
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
|
|
}
|
|
|
|
|
|
int CALLBACK CompareStatusItems(LPARAM item1, LPARAM item2, LPARAM uDirection)
|
|
{
|
|
if( (((PJOY)item1)->nStatus & JOY_US_PRESENT) == (((PJOY)item2)->nStatus & JOY_US_PRESENT) )
|
|
return(0);
|
|
|
|
return(uDirection) ? -1 : 1;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: DeleteSelectedItem ( BYTE nItem )
|
|
//
|
|
// PARAMETERS: nItem - ID of item to remove
|
|
//
|
|
// PURPOSE: Prompt the user, delete the selected device from the listview, and update the registry
|
|
//
|
|
// RETURN: TRUE if successfull, FALSE otherwise
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL DeleteSelectedItem( PBYTE pnItem )
|
|
{
|
|
BYTE nItem = *pnItem;
|
|
|
|
// don't process if nothing is selected.
|
|
if( *pnItem == NO_ITEM )
|
|
return(FALSE);
|
|
|
|
LV_ITEM lvItem;
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iSubItem = 0;
|
|
lvItem.iItem = *pnItem;
|
|
|
|
if( !ListView_GetItem(hListCtrl, &lvItem) )
|
|
return(FALSE);
|
|
|
|
::PostMessage(hListCtrl, LVM_ENSUREVISIBLE, *pnItem, FALSE );
|
|
|
|
LPTSTR pszTitle = new TCHAR[STR_LEN_64];
|
|
ASSERT (pszTitle);
|
|
|
|
// Query user if they are sure!
|
|
VERIFY(LoadString(ghInstance, IDS_GEN_AREYOUSURE, pszTitle, STR_LEN_64));
|
|
|
|
// Get the name of the device for the message box!
|
|
|
|
//PREFIX #WI226554. Won't fix. Obsolete code, from Whistler on replaced with new version.
|
|
LPTSTR lptszTmp = new TCHAR[STR_LEN_64];
|
|
|
|
// Make sure the name isn't so long as to over-write the buffer!
|
|
if( GetItemText(hListCtrl, (BYTE)*pnItem, DEVICE_COLUMN, lptszTmp, STR_LEN_64) > 60 )
|
|
{
|
|
lptszTmp[60] = lptszTmp[61] = lptszTmp[62] = TEXT('.');
|
|
lptszTmp[63] = TEXT('\0');
|
|
}
|
|
|
|
LPTSTR pszMsg = new TCHAR[MAX_STR_LEN];
|
|
ASSERT (pszMsg);
|
|
|
|
wsprintf( pszMsg, pszTitle, lptszTmp);
|
|
|
|
if( lptszTmp )
|
|
delete[] (lptszTmp);
|
|
|
|
VERIFY(LoadString(ghInstance, IDS_GEN_AREYOUSURE_TITLE, pszTitle, STR_LEN_64));
|
|
|
|
BOOL bRet = (BOOL)(IDYES == MessageBox(GetFocus(), pszMsg, pszTitle, MB_ICONQUESTION | MB_YESNO | MB_APPLMODAL));
|
|
|
|
if( pszMsg ) delete[] (pszMsg);
|
|
if( pszTitle ) delete[] (pszTitle);
|
|
|
|
if( bRet )
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Check for privileges!
|
|
if( SUCCEEDED(hr = pDIJoyConfig->Acquire()) )
|
|
{
|
|
char nIndex = (char)GetItemData(hListCtrl, (BYTE)*pnItem);
|
|
|
|
// Set the hour glass
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
// Verify that you can delete the Config before you release the interface pointers!
|
|
if( SUCCEEDED(hr = pDIJoyConfig->DeleteConfig(pAssigned[nIndex]->ID)) )
|
|
{
|
|
// make sure VJOYD is initialized
|
|
if( !(nFlags & ON_NT) )
|
|
VERIFY (SUCCEEDED(pDIJoyConfig->SendNotify()));
|
|
|
|
::SendMessage(hListCtrl, LVM_DELETEITEM, (WPARAM)(int)*pnItem, 0);
|
|
|
|
// Move the last assigned to the hole... if there is one!
|
|
if( nIndex != (nAssigned-1) )
|
|
{
|
|
// Before you move the tail to the hole,
|
|
// Release() the interfaces at the hole!
|
|
pAssigned[nIndex]->fnDeviceInterface->Unacquire();
|
|
pAssigned[nIndex]->fnDeviceInterface->Release();
|
|
|
|
// Move the tail to the hole.
|
|
CopyMemory(pAssigned[nIndex], pAssigned[nAssigned-1], sizeof (JOY));
|
|
|
|
pAssigned[nAssigned-1]->fnDeviceInterface = 0;
|
|
|
|
// Don't forget to set the index in the item data!
|
|
SetItemData(hListCtrl, nItem, nIndex);
|
|
|
|
// Assign the tail to the hole so it gets deleted!
|
|
nIndex = nAssigned-1;
|
|
|
|
// Don't forget to set the index in the item data!
|
|
// QZheng: This line is very wrong!!!
|
|
//SetItemData(hListCtrl, (BYTE)*pnItem, nIndex);
|
|
|
|
}
|
|
|
|
// delete the memory...
|
|
if( pAssigned[nIndex] )
|
|
{
|
|
delete (pAssigned[nIndex]);
|
|
pAssigned[nIndex] = 0;
|
|
}
|
|
|
|
// Set the focus before you corrupt iItem
|
|
SetListCtrlItemFocus(hListCtrl, nIndex);
|
|
|
|
pDIJoyConfig->SendNotify(); //do more to make sure
|
|
|
|
pDIJoyConfig->Unacquire();
|
|
|
|
|
|
// dec nAssigned
|
|
nAssigned--;
|
|
|
|
// if there's no items, tell iItem about it!
|
|
if( nAssigned == 0 )
|
|
*pnItem = NO_ITEM;
|
|
} else if( hr == DIERR_UNSUPPORTED )
|
|
{
|
|
Error((short)IDS_GEN_AREYOUSURE_TITLE, (short)IDS_GEN_NO_REMOVE_USB);
|
|
}
|
|
|
|
// Set the hour glass
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
}
|
|
}
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: DIEnumJoyTypeProc( LPCWSTR pwszTypeName, LPVOID pvRef )
|
|
//
|
|
// PARAMETERS: LPCWSTR pwszTypeName - Type name of the device enumerated
|
|
// LPVOID pvRef -
|
|
//
|
|
// PURPOSE: To Enumerate the types of devices associated with this system
|
|
//
|
|
// RETURN: TRUE if successfull, FALSE otherwise
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL CALLBACK DIEnumJoyTypeProc( LPCWSTR pwszTypeName, LPVOID pvRef )
|
|
{
|
|
// Type info
|
|
LPDIJOYTYPEINFO_DX5 lpdiJoyInfo = (LPDIJOYTYPEINFO_DX5)_alloca(sizeof(DIJOYTYPEINFO_DX5));
|
|
ASSERT (lpdiJoyInfo);
|
|
|
|
ZeroMemory(lpdiJoyInfo, sizeof(DIJOYTYPEINFO_DX5));
|
|
|
|
lpdiJoyInfo->dwSize = sizeof(DIJOYTYPEINFO_DX5);
|
|
|
|
// populate the Type Info
|
|
switch( pDIJoyConfig->GetTypeInfo(pwszTypeName, (LPDIJOYTYPEINFO)lpdiJoyInfo, DITC_REGHWSETTINGS) )
|
|
{
|
|
// errors to continue with...
|
|
case DIERR_NOTFOUND:
|
|
TRACE(TEXT("JOY.CPL: GetTypeInfo returned DIERR_NOTFOUND for type %s!\n"), pwszTypeName);
|
|
return(DIENUM_CONTINUE);
|
|
|
|
// errors to stop with...
|
|
case DIERR_INVALIDPARAM:
|
|
TRACE(TEXT("JOY.CPL: GetTypeInfo returned DIERR_INVALIDPARAM!\n"));
|
|
case DIERR_NOMOREITEMS:
|
|
return(DIENUM_STOP);
|
|
}
|
|
|
|
|
|
// a quick check to make sure we don't have the infamous array out of bounds problem!
|
|
#ifndef _UNICODE
|
|
if( nGameportDriver > MAX_GLOBAL_PORT_DRIVERS-1 )
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumJoyTypeProc: Global Gameport Drivers have exceeded MAX_GLOBAL_PORT_DRIVERS!\n"));
|
|
#endif
|
|
return(DIENUM_STOP);
|
|
}
|
|
#endif
|
|
|
|
if( nGameportBus > MAX_BUSSES-1 )
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumJoyTypeProc: Enumerated Gameport busses have exceeded MAX_BUSSES!\n"));
|
|
#endif // _DEBUG
|
|
return(DIENUM_STOP);
|
|
}
|
|
|
|
if( nGamingDevices > MAX_DEVICES-1 )
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumJoyTypeProc: Enumerated Gameport busses have exceeded MAX_DEVICES!\n"));
|
|
#endif // _DEBUG
|
|
return(DIENUM_STOP);
|
|
}
|
|
|
|
// check to see if it's a global port driver
|
|
#ifndef _UNICODE
|
|
if( lpdiJoyInfo->hws.dwFlags & JOY_HWS_ISGAMEPORTDRIVER )
|
|
{
|
|
if( pwszGameportDriverArray[nGameportDriver] )
|
|
wcsncpy(pwszGameportDriverArray[nGameportDriver], pwszTypeName, wcslen(pwszTypeName)+1);
|
|
else
|
|
pwszGameportDriverArray[nGameportDriver] = _wcsdup(pwszTypeName);
|
|
nGameportDriver++;
|
|
} else
|
|
#endif // _UNICODE
|
|
if( lpdiJoyInfo->hws.dwFlags & JOY_HWS_ISGAMEPORTBUS )
|
|
{
|
|
if( pwszGameportBus[nGameportBus] )
|
|
wcscpy(pwszGameportBus[nGameportBus], pwszTypeName);
|
|
else
|
|
pwszGameportBus[nGameportBus] = _wcsdup(pwszTypeName);
|
|
nGameportBus++;
|
|
} else
|
|
{
|
|
if( !(lpdiJoyInfo->hws.dwFlags & JOY_HWS_AUTOLOAD) )
|
|
{
|
|
// it's a standard gaming device
|
|
if( pwszTypeArray[nGamingDevices] )
|
|
wcsncpy(pwszTypeArray[nGamingDevices], pwszTypeName, wcslen(pwszTypeName)+1);
|
|
else
|
|
pwszTypeArray[nGamingDevices] = _wcsdup(pwszTypeName);
|
|
nGamingDevices++;
|
|
}
|
|
}
|
|
return(DIENUM_CONTINUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: DIEnumDevicesProc(LPDIDEVICEINSTANCE lpDeviceInst, LPVOID lpVoid)
|
|
//
|
|
// PARAMETERS: LPDIDEVICEINSTANCE lpDeviceInst - Device Instance
|
|
// LPVOID lpVoid -
|
|
//
|
|
// PURPOSE: To Enumerate the devices associated with this system
|
|
//
|
|
// RETURN: TRUE if successfull, FALSE otherwise
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL CALLBACK DIEnumDevicesProc(LPDIDEVICEINSTANCE lpDeviceInst, LPVOID lpVoid)
|
|
{
|
|
LPDIRECTINPUTDEVICE pdiDevTemp;
|
|
|
|
pDIJoyConfig->Acquire();
|
|
|
|
// First Create the device
|
|
if( SUCCEEDED(lpDIInterface->CreateDevice(lpDeviceInst->guidInstance, &pdiDevTemp, 0)) )
|
|
{
|
|
PJOY pNewJoy = new JOY;
|
|
ASSERT (pNewJoy);
|
|
|
|
// Query for a device2 object
|
|
if( FAILED(pdiDevTemp->QueryInterface(IID_IDirectInputDevice2, (LPVOID*)&pNewJoy->fnDeviceInterface)) )
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumDevicesProc: QueryInterface failed!\n"));
|
|
#endif
|
|
// release the temporary object
|
|
pdiDevTemp->Release();
|
|
return(FALSE);
|
|
}
|
|
|
|
DIPROPDWORD *pDIPropDW = new (DIPROPDWORD);
|
|
ASSERT (pDIPropDW);
|
|
|
|
ZeroMemory(pDIPropDW, sizeof(DIPROPDWORD));
|
|
|
|
pDIPropDW->diph.dwSize = sizeof(DIPROPDWORD);
|
|
pDIPropDW->diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
pDIPropDW->diph.dwHow = DIPH_DEVICE;
|
|
|
|
// Get the device ID
|
|
VERIFY (SUCCEEDED(pdiDevTemp->GetProperty(DIPROP_JOYSTICKID, &pDIPropDW->diph)));
|
|
|
|
// release the temporary object
|
|
pdiDevTemp->Release();
|
|
|
|
pNewJoy->ID = (char)pDIPropDW->dwData;
|
|
|
|
if( pDIPropDW )
|
|
delete (pDIPropDW);
|
|
|
|
// Get the Type name
|
|
LPDIJOYCONFIG_DX5 lpDIJoyCfg = new (DIJOYCONFIG_DX5);
|
|
ASSERT (lpDIJoyCfg);
|
|
|
|
ZeroMemory(lpDIJoyCfg, sizeof(DIJOYCONFIG_DX5));
|
|
|
|
lpDIJoyCfg->dwSize = sizeof(DIJOYCONFIG_DX5);
|
|
|
|
VERIFY (SUCCEEDED(pDIJoyConfig->GetConfig(pNewJoy->ID, (LPDIJOYCONFIG)lpDIJoyCfg, DIJC_REGHWCONFIGTYPE | DIJC_CALLOUT)));
|
|
|
|
// Get the clsidConfig
|
|
LPDIJOYTYPEINFO lpDIJoyType = new (DIJOYTYPEINFO);
|
|
ASSERT(lpDIJoyType);
|
|
|
|
ZeroMemory(lpDIJoyType, sizeof(DIJOYTYPEINFO));
|
|
|
|
lpDIJoyType->dwSize = sizeof(DIJOYTYPEINFO);
|
|
|
|
VERIFY (SUCCEEDED(pDIJoyConfig->GetTypeInfo(lpDIJoyCfg->wszType, (LPDIJOYTYPEINFO)lpDIJoyType, DITC_CLSIDCONFIG | DITC_REGHWSETTINGS | DITC_FLAGS1 )));
|
|
|
|
if( lpDIJoyCfg )
|
|
delete (lpDIJoyCfg);
|
|
|
|
// if NULL, Leave as default.
|
|
if( !IsEqualIID(lpDIJoyType->clsidConfig, GUID_NULL) ) {
|
|
pNewJoy->fHasOemSheet = TRUE;
|
|
if( !(lpDIJoyType->dwFlags1 & JOYTYPE_DEFAULTPROPSHEET) ) {
|
|
pNewJoy->clsidPropSheet = lpDIJoyType->clsidConfig;
|
|
}
|
|
} else {
|
|
pNewJoy->fHasOemSheet = FALSE;
|
|
}
|
|
|
|
// Assign the number of buttons!
|
|
pNewJoy->nButtons = (BYTE)(lpDIJoyType->hws.dwNumButtons);
|
|
|
|
if( lpDIJoyType )
|
|
delete (lpDIJoyType);
|
|
|
|
// Set it's format!!!
|
|
if( SUCCEEDED(pNewJoy->fnDeviceInterface->SetDataFormat(&c_dfDIJoystick)) )
|
|
{
|
|
// Set it's Cooperative Level!
|
|
if( FAILED(pNewJoy->fnDeviceInterface->SetCooperativeLevel(GetParent((HWND)GetParent(hListCtrl)), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)) )
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumDevicesProc: SetCooperativeLevel Failed!\n"));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Add the item to the tree!
|
|
pAssigned[nAssigned] = pNewJoy;
|
|
|
|
// If you're on the General page!
|
|
if( nFlags & ON_PAGE )
|
|
{
|
|
// add to tree
|
|
LVITEM lvItem = {LVIF_TEXT | LVIF_PARAM, nAssigned, 0, 0, 0, lpDeviceInst->tszInstanceName, lstrlen(lpDeviceInst->tszInstanceName), 0, (LPARAM)nAssigned, 0};
|
|
::SendMessage(hListCtrl, LVM_INSERTITEM, 0, (LPARAM) (const LPLVITEM)&lvItem);
|
|
//InsertItem(hListCtrl, lpDeviceInst->tszInstanceName, nAssigned);
|
|
|
|
TCHAR sz[STR_LEN_32];
|
|
VERIFY(LoadString(ghInstance, IDS_GEN_STATUS_UNKNOWN, (LPTSTR)&sz, STR_LEN_32));
|
|
|
|
SetItemText(hListCtrl, nAssigned, STATUS_COLUMN, sz);
|
|
}
|
|
|
|
// Increment the array counter!
|
|
nAssigned++;
|
|
if( nAssigned == nTargetAssigned )
|
|
{
|
|
/*
|
|
* A new device arrived so assume there's no
|
|
* longer any point in checking on the timer.
|
|
*/
|
|
nTargetAssigned = (BYTE)-1;
|
|
nReEnum = 0;
|
|
}
|
|
|
|
}
|
|
return(DIENUM_CONTINUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: ClearArrays ( void )
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void ClearArrays( void )
|
|
{
|
|
#ifndef _UNICODE
|
|
while( nGameportDriver )
|
|
{
|
|
free(pwszGameportDriverArray[--nGameportDriver]);
|
|
pwszGameportDriverArray[nGameportDriver] = L'\0';
|
|
}
|
|
|
|
#endif // _UNICODE
|
|
while( nGamingDevices )
|
|
{
|
|
free(pwszTypeArray[--nGamingDevices]);
|
|
pwszTypeArray[nGamingDevices] = L'\0';
|
|
}
|
|
|
|
while( nGameportBus )
|
|
{
|
|
free(pwszGameportBus[--nGameportBus]);
|
|
pwszGameportBus[nGameportBus] = L'\0';
|
|
memset( &guidOccupied[nGameportBus], 0, sizeof(GUID) );
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: UpdateListCtrl( HWND hDlg )
|
|
//
|
|
// PARAMETERS: HWND hDlg - Handle to window to update
|
|
//
|
|
// PURPOSE: Refreshes enumerated device list
|
|
//
|
|
// RETURN: TRUE if successfull, FALSE otherwise
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
static void UpdateListCtrl( HWND hDlg )
|
|
{
|
|
if( !(nFlags & ON_PAGE) )
|
|
return;
|
|
|
|
// Turn Redraw off here else it will flicker!
|
|
::SendMessage(hListCtrl, WM_SETREDRAW, (WPARAM)FALSE, 0);
|
|
|
|
// delete all existing entries
|
|
::SendMessage(hListCtrl, LVM_DELETEALLITEMS, 0, 0);
|
|
|
|
Enumerate( hDlg );
|
|
|
|
// turn the flag off!
|
|
if( nFlags & UPDATE_FOR_GEN )
|
|
nFlags &= ~UPDATE_FOR_GEN;
|
|
|
|
// Turn the redraw flag back on!
|
|
::SendMessage (hListCtrl, WM_SETREDRAW, (WPARAM)TRUE, 0);
|
|
InvalidateRect(hListCtrl, NULL, TRUE);
|
|
}
|
|
|
|
//#ifdef _UNICODE
|
|
HRESULT Enumerate( HWND hDlg )
|
|
{
|
|
nFlags |= UPDATE_ALL;
|
|
|
|
// Clear pAssigned
|
|
while( nAssigned )
|
|
{
|
|
if( pAssigned[--nAssigned] )
|
|
{
|
|
delete (pAssigned[nAssigned]);
|
|
|
|
pAssigned[nAssigned] = 0;
|
|
}
|
|
}
|
|
|
|
// Enumerate the Joysticks and put them in the list... | DIEDFL_INCLUDEPHANTOMS
|
|
#ifdef _UNICODE
|
|
return(lpDIInterface->EnumDevices(DIDEVTYPE_JOYSTICK, (LPDIENUMDEVICESCALLBACK)DIEnumDevicesProc, (LPVOID)hDlg,
|
|
DIEDFL_ALLDEVICES ));
|
|
#else
|
|
return(lpDIInterface->EnumDevices(DIDEVTYPE_JOYSTICK, (LPDIENUMDEVICESCALLBACK)DIEnumDevicesProc, (LPVOID)hDlg,
|
|
DIEDFL_ALLDEVICES | DIEDFL_INCLUDEPHANTOMS));
|
|
#endif
|
|
}
|
|
/*
|
|
#else
|
|
HRESULT Enumerate( HWND hDlg )
|
|
{
|
|
// Clear pAssigned
|
|
while (nAssigned)
|
|
{
|
|
if (pAssigned[--nAssigned])
|
|
{
|
|
delete (pAssigned[nAssigned]);
|
|
|
|
pAssigned[nAssigned] = 0;
|
|
}
|
|
}
|
|
|
|
DIJOYCONFIG *pJoyConfig = new DIJOYCONFIG;
|
|
ASSERT (pJoyConfig);
|
|
|
|
pJoyConfig->dwSize = sizeof (DIJOYCONFIG);
|
|
|
|
LPDIJOYTYPEINFO pdiJoyTypeInfo = new DIJOYTYPEINFO;
|
|
ASSERT (pdiJoyTypeInfo);
|
|
|
|
pdiJoyTypeInfo->dwSize = sizeof (DIJOYTYPEINFO);
|
|
|
|
HRESULT hr;
|
|
|
|
// find and assign ID's
|
|
for (BYTE n = 0; n < NUMJOYDEVS; n++)
|
|
{
|
|
hr = pDIJoyConfig->GetConfig(n, pJoyConfig, DIJC_REGHWCONFIGTYPE | DIJC_GUIDINSTANCE);
|
|
|
|
if (hr == S_OK)
|
|
AddListCtrlItem(n, pJoyConfig);
|
|
}
|
|
|
|
// clean up, clean up... everybody do your share!
|
|
if (pJoyConfig) delete (pJoyConfig);
|
|
if (pdiJoyTypeInfo) delete (pdiJoyTypeInfo);
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL AddListCtrlItem(BYTE nItemID, LPDIJOYCONFIG pJoyConfig)
|
|
{
|
|
LPDIRECTINPUTDEVICE pdiDevTemp;
|
|
|
|
pDIJoyConfig->Acquire();
|
|
|
|
// First Create the device
|
|
if (SUCCEEDED(lpDIInterface->CreateDevice(pJoyConfig->guidInstance, &pdiDevTemp, 0)))
|
|
{
|
|
PJOY pNewJoy = new JOY;
|
|
ASSERT (pNewJoy);
|
|
|
|
// Query for a device2 object
|
|
if (FAILED(pdiDevTemp->QueryInterface(IID_IDirectInputDevice2, (LPVOID*)&pNewJoy->fnDeviceInterface)))
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumDevicesProc: QueryInterface failed!\n"));
|
|
#endif
|
|
// release the temporary object
|
|
pdiDevTemp->Release();
|
|
return FALSE;
|
|
}
|
|
|
|
DIPROPDWORD *pDIPropDW = new (DIPROPDWORD);
|
|
ASSERT (pDIPropDW);
|
|
|
|
ZeroMemory(pDIPropDW, sizeof(DIPROPDWORD));
|
|
|
|
pDIPropDW->diph.dwSize = sizeof(DIPROPDWORD);
|
|
pDIPropDW->diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
pDIPropDW->diph.dwHow = DIPH_DEVICE;
|
|
|
|
// Get the device ID
|
|
VERIFY (SUCCEEDED(pdiDevTemp->GetProperty(DIPROP_JOYSTICKID, &pDIPropDW->diph)));
|
|
|
|
// release the temporary object
|
|
pdiDevTemp->Release();
|
|
|
|
pNewJoy->ID = (char)pDIPropDW->dwData;
|
|
|
|
if (pDIPropDW)
|
|
delete (pDIPropDW);
|
|
|
|
// Get the Type name
|
|
LPDIJOYCONFIG_DX5 lpDIJoyCfg = new (DIJOYCONFIG_DX5);
|
|
ASSERT (lpDIJoyCfg);
|
|
|
|
ZeroMemory(lpDIJoyCfg, sizeof(DIJOYCONFIG_DX5));
|
|
|
|
lpDIJoyCfg->dwSize = sizeof(DIJOYCONFIG_DX5);
|
|
|
|
VERIFY (SUCCEEDED(pDIJoyConfig->GetConfig(pNewJoy->ID, (LPDIJOYCONFIG)lpDIJoyCfg, DIJC_REGHWCONFIGTYPE)));
|
|
|
|
// Get the clsidConfig
|
|
LPDIJOYTYPEINFO_DX5 lpDIJoyType = new (DIJOYTYPEINFO_DX5);
|
|
ASSERT(lpDIJoyType);
|
|
|
|
ZeroMemory(lpDIJoyType, sizeof(DIJOYTYPEINFO_DX5));
|
|
|
|
lpDIJoyType->dwSize = sizeof(DIJOYTYPEINFO_DX5);
|
|
|
|
VERIFY (SUCCEEDED(pDIJoyConfig->GetTypeInfo(lpDIJoyCfg->wszType, (LPDIJOYTYPEINFO)lpDIJoyType, DITC_CLSIDCONFIG)));
|
|
|
|
// if NULL, Leave as default.
|
|
if (!IsEqualIID(lpDIJoyType->clsidConfig, GUID_NULL))
|
|
pNewJoy->clsidPropSheet = lpDIJoyType->clsidConfig;
|
|
|
|
if (lpDIJoyType)
|
|
delete (lpDIJoyType);
|
|
|
|
// Set it's format!!!
|
|
if (FAILED(pNewJoy->fnDeviceInterface->SetDataFormat(&c_dfDIJoystick)))
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumDevicesProc: SetDataFormat() Failed!\n"));
|
|
#endif
|
|
}
|
|
|
|
// Set it's Cooperative Level!
|
|
if (FAILED(pNewJoy->fnDeviceInterface->SetCooperativeLevel(GetParent((HWND)GetParent(hListCtrl)), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)))
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("JOY.CPL: Cpanel.cpp: DIEnumDevicesProc: SetCooperativeLevel Failed!\n"));
|
|
#endif
|
|
}
|
|
|
|
// Add the item to the tree!
|
|
pAssigned[nAssigned] = pNewJoy;
|
|
|
|
// Get the number of buttons!
|
|
LPDIDEVCAPS_DX3 lpDIDevCaps = new (DIDEVCAPS_DX3);
|
|
ASSERT (lpDIDevCaps);
|
|
|
|
ZeroMemory(lpDIDevCaps, sizeof(DIDEVCAPS_DX3));
|
|
lpDIDevCaps->dwSize = sizeof(DIDEVCAPS_DX3);
|
|
|
|
pAssigned[nAssigned]->fnDeviceInterface->Acquire();
|
|
|
|
if (SUCCEEDED(pAssigned[nAssigned]->fnDeviceInterface->GetCapabilities((LPDIDEVCAPS)lpDIDevCaps)))
|
|
pAssigned[nAssigned]->nButtons = (BYTE)lpDIDevCaps->dwButtons;
|
|
|
|
if (lpDIDevCaps)
|
|
delete (lpDIDevCaps);
|
|
|
|
// If you're on the General page!
|
|
if (nFlags & ON_PAGE)
|
|
{
|
|
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;
|
|
|
|
pAssigned[nAssigned]->fnDeviceInterface->GetProperty(DIPROP_INSTANCENAME, &pDIPropStr->diph);
|
|
|
|
USES_CONVERSION;
|
|
|
|
// add to tree
|
|
LVITEM lvItem = {LVIF_TEXT | LVIF_PARAM, nAssigned, 0, 0, 0, W2A(pDIPropStr->wsz), lstrlen(W2A(pDIPropStr->wsz)), 0, (LPARAM)nAssigned, 0};
|
|
::SendMessage(hListCtrl, LVM_INSERTITEM, 0, (LPARAM) (const LPLVITEM)&lvItem);
|
|
|
|
TCHAR sz[STR_LEN_32];
|
|
VERIFY(LoadString(ghInstance, IDS_GEN_STATUS_UNKNOWN, (LPTSTR)&sz, STR_LEN_32));
|
|
|
|
SetItemText(hListCtrl, nAssigned, STATUS_COLUMN, sz);
|
|
|
|
if (pDIPropStr)
|
|
delete (pDIPropStr);
|
|
}
|
|
|
|
// Increment the array counter!
|
|
nAssigned++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif
|
|
*/
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: SetActive ( HWND hDlg )
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL SetActive(HWND hDlg)
|
|
{
|
|
// restore selection focus to nItemSelected
|
|
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
|
|
|
|
BYTE i = (BYTE)::SendMessage(hListCtrl, LVM_GETITEMCOUNT, 0, 0);
|
|
|
|
// Acquire All Devices that are Attached!!!
|
|
char nIndex;
|
|
|
|
while( i-- )
|
|
{
|
|
// get joystick config of item
|
|
nIndex = (char)GetItemData(hListCtrl, i);
|
|
|
|
if( pAssigned[nIndex]->nStatus & JOY_US_PRESENT )
|
|
pAssigned[nIndex]->fnDeviceInterface->Acquire();
|
|
}
|
|
|
|
// create timer
|
|
SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
|
|
|
|
UpdateButtonState( hDlg );
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: MsgSubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
//
|
|
// PARAMETERS: HWND hWnd
|
|
// UINT uMsg
|
|
// WPARAM wParam
|
|
// LPARAM lParam
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI MsgSubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// Only do this if you are ON THIS PAGE!
|
|
if( nFlags & ON_PAGE )
|
|
{
|
|
if( uMsg == JoyCfgChangedMsg )
|
|
{
|
|
if( !(nFlags & BLOCK_UPDATE) )
|
|
{
|
|
// kill status timer
|
|
KillTimer(hWnd, ID_MYTIMER);
|
|
nFlags |= UPDATE_ALL;
|
|
ClearArrays();
|
|
pDIJoyConfig->EnumTypes((LPDIJOYTYPECALLBACK)DIEnumJoyTypeProc, NULL);
|
|
UpdateListCtrl(hWnd);
|
|
SetActive(hWnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(BOOL)CallWindowProc(fpMainWindowProc, hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: Error ( short nTitleID, short nMsgID )
|
|
//
|
|
// PARAMETERS: nTitleID - Resource ID for Message Title
|
|
// nMsgID - Resource ID for Message
|
|
//
|
|
// PURPOSE: Prompt user when error occurs
|
|
//
|
|
// RETURN: TRUE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void Error(short nTitleID, short nMsgID)
|
|
{
|
|
LPTSTR lptTitle = new TCHAR[STR_LEN_64];
|
|
ASSERT (lptTitle);
|
|
|
|
if( LoadString(ghInstance, nTitleID, lptTitle, STR_LEN_64) )
|
|
{
|
|
LPTSTR lptMsg = new TCHAR[MAX_STR_LEN];
|
|
ASSERT (lptMsg);
|
|
|
|
if( LoadString(ghInstance, nMsgID, lptMsg, MAX_STR_LEN) )
|
|
MessageBox(NULL, lptMsg, lptTitle, MB_ICONHAND | MB_OK | MB_APPLMODAL);
|
|
|
|
if( lptMsg )
|
|
delete[] (lptMsg);
|
|
}
|
|
|
|
if( lptTitle )
|
|
delete[] (lptTitle);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: MoveOK ( HWND hParentWnd )
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void MoveOK(HWND hParentWnd)
|
|
{
|
|
// Hide the Cancel and move the OK...
|
|
HWND hCtrl = GetDlgItem(hParentWnd, IDCANCEL);
|
|
|
|
// if there is no IDCANCEL, we've been here before!
|
|
if( hCtrl )
|
|
{
|
|
RECT rc;
|
|
GetWindowRect(hCtrl, &rc);
|
|
|
|
DestroyWindow(hCtrl);
|
|
|
|
//POINT pt = {rc.left, rc.top};
|
|
|
|
//ScreenToClient(hParentWnd, &pt);
|
|
|
|
// This should take care of Mirroring and work for normal windows
|
|
MapWindowPoints(NULL, hParentWnd, (LPPOINT)&rc, 2);
|
|
|
|
hCtrl = GetDlgItem(hParentWnd, IDOK);
|
|
ASSERT(hCtrl);
|
|
|
|
//SetWindowPos(hCtrl, NULL, pt.x, pt.y, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER);
|
|
SetWindowPos(hCtrl, NULL, rc.left, rc.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER);
|
|
|
|
LPTSTR lpszDone = new TCHAR[12];
|
|
ASSERT (lpszDone);
|
|
|
|
// Used to be IDS_DONE, but we changed it from DONE to OK
|
|
VERIFY(LoadString(ghInstance, IDS_GEN_STATUS_OK, lpszDone, 12));
|
|
::SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)lpszDone);
|
|
|
|
if( lpszDone )
|
|
delete[] (lpszDone);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: UpdateButtonState ( HWND hDlg )
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void UpdateButtonState( HWND hDlg )
|
|
{
|
|
PostDlgItemEnableWindow(hDlg, IDC_BTN_REMOVE, (BOOL)nAssigned);
|
|
PostDlgItemEnableWindow(hDlg, IDC_BTN_PROPERTIES, (BOOL)nAssigned);
|
|
}
|
|
|
|
#ifdef WINNT
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: RunWDMJoy ( void )
|
|
//
|
|
// PURPOSE: Run wdmjoy.inf to install
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void RunWDMJOY( void )
|
|
{
|
|
//Check if we have already placed the first value
|
|
//HKLM,SYSTEM\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\VID_045E&PID_01F0
|
|
HKEY hKey;
|
|
|
|
long lTest = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REGSTR_PATH_JOYOEM TEXT("\\VID_045E&PID_01F0"),
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
if (lTest == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return;
|
|
}
|
|
|
|
|
|
LPTSTR lpszWDMJoy = new (TCHAR[STR_LEN_64]);
|
|
ASSERT (lpszWDMJoy);
|
|
|
|
// Check to see if the file is present
|
|
WIN32_FIND_DATA findData;
|
|
|
|
BYTE nLen = (BYTE)GetWindowsDirectory(lpszWDMJoy, STR_LEN_64);
|
|
VERIFY(LoadString(ghInstance, IDS_WDMJOY_INF, &lpszWDMJoy[nLen], STR_LEN_64-nLen));
|
|
|
|
HANDLE hFind = FindFirstFile(lpszWDMJoy, &findData);
|
|
|
|
// If you've found one... run it!
|
|
if( hFind != INVALID_HANDLE_VALUE )
|
|
{
|
|
LPTSTR lpStr = new (TCHAR[MAX_STR_LEN]);
|
|
ASSERT (lpStr);
|
|
|
|
// Copy the Windows directory to the buffer!
|
|
_tcsncpy(lpStr, lpszWDMJoy, nLen+1);
|
|
|
|
if( LoadString(ghInstance, IDS_WDMJOY, &lpStr[nLen], MAX_STR_LEN-nLen) )
|
|
{
|
|
// Put IDS_WDMJOY_INF on the end of the string!
|
|
_tcscpy(&lpStr[lstrlen(lpStr)], lpszWDMJoy);
|
|
|
|
LPSTARTUPINFO psi = new (STARTUPINFO);
|
|
ASSERT (psi);
|
|
|
|
ZeroMemory(psi, sizeof(STARTUPINFO));
|
|
|
|
psi->cb = sizeof(STARTUPINFO);
|
|
|
|
LPPROCESS_INFORMATION ppi = new (PROCESS_INFORMATION);
|
|
ASSERT (ppi);
|
|
|
|
ZeroMemory(ppi, sizeof(PROCESS_INFORMATION));
|
|
|
|
if( CreateProcess(0, lpStr, 0, 0, 0, 0, 0, 0, psi, ppi) )
|
|
{
|
|
CloseHandle(ppi->hThread);
|
|
CloseHandle(ppi->hProcess);
|
|
}
|
|
#ifdef _DEBUG
|
|
else OutputDebugString(TEXT("JOY.CPL: CPANEL.CPP: RunWDMJoy: CreateProcess Failed!\n"));
|
|
#endif
|
|
|
|
if( ppi )
|
|
delete (ppi);
|
|
|
|
if( psi )
|
|
delete (psi);
|
|
}
|
|
|
|
if( lpStr )
|
|
delete[] (lpStr);
|
|
}
|
|
|
|
FindClose(hFind);
|
|
|
|
if( lpszWDMJoy )
|
|
delete[] (lpszWDMJoy);
|
|
}
|
|
#endif
|
|
|
|
#ifdef _UNICODE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: RegisterForDevChange ( HWND hDlg, PVOID *hNoditfyDevNode )
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void RegisterForDevChange(HWND hDlg, PVOID *hNotifyDevNode)
|
|
{
|
|
DEV_BROADCAST_DEVICEINTERFACE *pFilterData = new (DEV_BROADCAST_DEVICEINTERFACE);
|
|
ASSERT (pFilterData);
|
|
|
|
ZeroMemory(pFilterData, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
|
|
|
|
pFilterData->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
|
pFilterData->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
pFilterData->dbcc_classguid = GUID_CLASS_INPUT;
|
|
|
|
*hNotifyDevNode = RegisterDeviceNotification(hDlg, pFilterData, DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
|
|
if( pFilterData )
|
|
delete (pFilterData);
|
|
}
|
|
#endif
|
|
|
|
|
|
// BEGINNING OF LIST CONTROL FUNCTIONS!
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: SetListCtrlItemFocus ( HWND hCtrl, BYTE nItem )
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
// BYTE nItem - Item to set focus to
|
|
//
|
|
// PURPOSE: Set focus to item in list control
|
|
//
|
|
// RETURN: NONE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void SetListCtrlItemFocus ( HWND hCtrl, BYTE nItem )
|
|
{
|
|
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
|
|
ASSERT (plvItem);
|
|
|
|
plvItem->lParam = plvItem->iSubItem = plvItem->iImage =
|
|
plvItem->cchTextMax = plvItem->iIndent = 0;
|
|
|
|
plvItem->mask = LVIF_STATE;
|
|
plvItem->iItem = nItem;
|
|
plvItem->state =
|
|
plvItem->stateMask = LVIS_FOCUSED | LVIS_SELECTED;
|
|
plvItem->pszText = NULL;
|
|
|
|
::SendMessage(hCtrl, LVM_SETITEM, 0, (LPARAM)(const LPLVITEM)plvItem);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: GetItemData(HWND hCtrl, BYTE nItem )
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
//
|
|
// BYTE nItem - Item to retrieve data from
|
|
// PURPOSE: Retrieve the lower char of the item's data
|
|
//
|
|
// RETURN: Item's data cast to a char
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
DWORD GetItemData(HWND hCtrl, BYTE nItem )
|
|
{
|
|
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
|
|
ASSERT (plvItem);
|
|
|
|
ZeroMemory(plvItem, sizeof(LVITEM));
|
|
|
|
plvItem->mask = LVIF_PARAM;
|
|
plvItem->iItem = nItem;
|
|
|
|
VERIFY(::SendMessage(hCtrl, LVM_GETITEM, 0, (LPARAM)(LPLVITEM)plvItem));
|
|
|
|
return(DWORD)plvItem->lParam;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: SetItemData(HWND hCtrl, BYTE nItem, DWORD dwFlag )
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
// BYTE nItem - Item to send data to
|
|
// DWORD dwFlag - DWORD to send to nItem
|
|
// PURPOSE: Set the extra memory associated with nItem to dwFlag
|
|
//
|
|
// RETURN: TRUE if Successful, FALSE otherwise
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL SetItemData(HWND hCtrl, BYTE nItem, DWORD dwFlag )
|
|
{
|
|
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
|
|
ASSERT (plvItem);
|
|
|
|
ZeroMemory(plvItem, sizeof(LVITEM));
|
|
|
|
plvItem->mask = LVIF_PARAM;
|
|
plvItem->iItem = nItem;
|
|
plvItem->lParam = dwFlag;
|
|
|
|
return(BOOL)::SendMessage(hCtrl, LVM_SETITEM, 0, (LPARAM)(const LPLVITEM)plvItem);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: InsertColumn (HWND hCtrl, BYTE nColumn, short nStrID, short nWidth)
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
// BYTE nColumn - Column to place string
|
|
// short nStrID - Resource ID for string
|
|
// short nWidth - Width of column
|
|
//
|
|
// PURPOSE: Insert a column in a list control
|
|
//
|
|
// RETURN: NONE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void InsertColumn (HWND hCtrl, BYTE nColumn, USHORT nStrID, USHORT nWidth)
|
|
{
|
|
// Allocate the structure
|
|
LPLVCOLUMN plvColumn = (LPLVCOLUMN)_alloca(sizeof(LVCOLUMN));
|
|
ASSERT (plvColumn);
|
|
|
|
ZeroMemory(plvColumn, sizeof(LVCOLUMN));
|
|
|
|
plvColumn->mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
|
|
plvColumn->fmt = LVCFMT_CENTER;
|
|
plvColumn->cx = nWidth;
|
|
|
|
plvColumn->pszText = (LPTSTR)_alloca(sizeof(TCHAR[STR_LEN_32]));
|
|
ASSERT (plvColumn->pszText);
|
|
|
|
plvColumn->cchTextMax = LoadString(ghInstance, nStrID, plvColumn->pszText, STR_LEN_32);
|
|
|
|
::SendMessage(hCtrl, LVM_INSERTCOLUMN, (WPARAM)(int)nColumn, (LPARAM)(const LPLVCOLUMN)plvColumn);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: SetItemText( HWND hCtrl, BYTE nItem, BYTE nSubItem, LPTSTR lpStr)
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
// BYTE nItem - Item to set
|
|
// BYTE nSubItem - SubItem to set
|
|
// LPTSTR lpStr - String to set
|
|
//
|
|
// PURPOSE: Set list control item text
|
|
//
|
|
// RETURN: NONE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void SetItemText( HWND hCtrl, BYTE nItem, BYTE nSubItem, LPTSTR lpStr)
|
|
{
|
|
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
|
|
ASSERT (plvItem);
|
|
|
|
plvItem->lParam = plvItem->stateMask = plvItem->iImage =
|
|
plvItem->state = plvItem->iIndent = 0;
|
|
|
|
plvItem->mask = LVIF_TEXT;
|
|
plvItem->iItem = nItem;
|
|
plvItem->iSubItem = nSubItem;
|
|
plvItem->cchTextMax = lstrlen(lpStr);
|
|
plvItem->pszText = lpStr;
|
|
|
|
::SendMessage(hCtrl, LVM_SETITEM, 0, (LPARAM)(const LPLVITEM)plvItem);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: GetItemText( HWND hCtrl, BYTE nItem, BYTE nSubItem, LPTSTR lpszBuff, BYTE nLen )
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
// BYTE nItem - Item to retrive text
|
|
// BYTE nSubItem - SubItem to retrieve text
|
|
// LPTSTR lpszBuff - Buffer for retrieved text
|
|
// BYTE nLen - Size of buffer
|
|
//
|
|
// PURPOSE: Retrieve text from a list control
|
|
//
|
|
// RETURN: length of retrieved string!
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BYTE GetItemText( HWND hCtrl, BYTE nItem, BYTE nSubItem, LPTSTR lpszBuff, BYTE nLen )
|
|
{
|
|
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
|
|
ASSERT (plvItem);
|
|
|
|
plvItem->lParam = plvItem->stateMask = plvItem->iImage =
|
|
plvItem->state = plvItem->iIndent = 0;
|
|
|
|
plvItem->mask = LVIF_TEXT;
|
|
plvItem->iItem = nItem;
|
|
plvItem->iSubItem = nSubItem;
|
|
plvItem->pszText = lpszBuff;
|
|
plvItem->cchTextMax = nLen;
|
|
|
|
return(BYTE)::SendMessage(hCtrl, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)(const LPLVITEM)plvItem);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: InsertItem(HWND hCtrl, LPTSTR lpszBuff )
|
|
//
|
|
// PARAMETERS: HWND hCtrl - Handle of ListControl to recieve the message
|
|
// BYTE nItem - Item to retrive text
|
|
// LPTSTR lpszBuff - Text to be inserted
|
|
//
|
|
// PURPOSE: Retrieve text from a list control
|
|
//
|
|
// RETURN: NONE BYTE nItem,
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BYTE InsertItem( HWND hCtrl, LPTSTR lpszBuff, BYTE nItem )
|
|
{
|
|
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
|
|
ASSERT (plvItem);
|
|
|
|
plvItem->state = plvItem->stateMask = plvItem->iImage =
|
|
plvItem->iItem = plvItem->iIndent = plvItem->iSubItem = 0;
|
|
|
|
plvItem->mask = LVIF_TEXT | LVIF_PARAM;
|
|
plvItem->pszText = lpszBuff;
|
|
plvItem->cchTextMax = lstrlen(lpszBuff);
|
|
plvItem->lParam = ID_NONE | nItem;
|
|
|
|
return(BYTE)::SendMessage(hCtrl, LVM_INSERTITEM, (WPARAM)0, (LPARAM)(const LPLVITEM)plvItem);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: Launch(HWND hWnd, BYTE nJoy, BYTE startpage)
|
|
//
|
|
// PARAMETERS: HWND hWnd - Handle to Dialog
|
|
// BYTE nJoy - Index into pAssigned global array of assigned devices
|
|
// BYTE nStartPage - Page to show first
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
//
|
|
// RETURN:
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT Launch(HWND hWnd, PJOY pJoy, BYTE nStartPage)
|
|
{
|
|
HRESULT hresRet;
|
|
|
|
ASSERT (::IsWindow(hWnd));
|
|
|
|
if( nStartPage > MAX_PAGES )
|
|
return(DIGCERR_STARTPAGETOOLARGE);
|
|
|
|
LPCDIGAMECNTRLPROPSHEET fnInterface;
|
|
|
|
/*
|
|
#ifdef _UNICODE
|
|
LPTSTR lpszWin32 = new (TCHAR[STR_LEN_64]);
|
|
ASSERT (lpszWin32);
|
|
|
|
_tcscpy(&lpszWin32[GetSystemDirectory(lpszWin32, STR_LEN_64)], TEXT("\\OLE32.DLL"));
|
|
//TEXT("OLE32.DLL")
|
|
HINSTANCE hOleInst = LoadLibrary(lpszWin32);
|
|
|
|
if (lpszWin32)
|
|
delete[] (lpszWin32);
|
|
|
|
if (!hOleInst)
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
#endif
|
|
*/
|
|
|
|
// Get the interface pointer if there is one!
|
|
// This reduces the memory footprint of the CPL but takes a bit more time to
|
|
// launch the property sheet pages!
|
|
/*
|
|
#ifdef _UNICODE
|
|
fnInterface = HasInterface(pJoy->clsidPropSheet, hOleInst);
|
|
|
|
if (!fnInterface)
|
|
{
|
|
// If the propsheet is not mine, try mine!
|
|
if (!IsEqualIID(pJoy->clsidPropSheet, CLSID_LegacyServer))
|
|
fnInterface = HasInterface(CLSID_LegacyServer, hOleInst);
|
|
}
|
|
|
|
FreeLibrary(hOleInst);
|
|
#else
|
|
*/
|
|
HRESULT hr;
|
|
|
|
//if( SUCCEEDED(hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED| COINIT_SPEED_OVER_MEMORY)) )
|
|
// OLE32 on Win95 does not have CoInitializeEx.
|
|
if( SUCCEEDED(hr = CoInitialize(NULL)) )
|
|
{
|
|
IClassFactory* ppv_classfactory;
|
|
|
|
if( SUCCEEDED(hr = CoGetClassObject(pJoy->clsidPropSheet, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&ppv_classfactory)) )
|
|
{
|
|
VERIFY(SUCCEEDED(ppv_classfactory->CreateInstance(NULL, IID_IDIGameCntrlPropSheet, (LPVOID *)&fnInterface)));
|
|
|
|
ppv_classfactory->Release();
|
|
} else {
|
|
fnInterface = 0;
|
|
}
|
|
} else {
|
|
fnInterface = 0;
|
|
}
|
|
|
|
//#endif
|
|
|
|
// By this point, you've tried twice (possibly)...
|
|
// if you don't have an interface by this point...
|
|
// QUIT!
|
|
if( !fnInterface )
|
|
{
|
|
Error((short)IDS_INTERNAL_ERROR, (short)IDS_NO_DIJOYCONFIG);
|
|
return(E_NOINTERFACE);
|
|
}
|
|
|
|
// here's where we are sending the property sheet an ID describing the location of the installed device!
|
|
fnInterface->SetID(pJoy->ID);
|
|
|
|
LPDIGCSHEETINFO pServerSheet;
|
|
|
|
// Get the property sheet info from the server
|
|
if( FAILED(fnInterface->GetSheetInfo(&pServerSheet)) )
|
|
{
|
|
TRACE(TEXT("JOY.CPL: CPANEL.CPP: Launch: GetSheetInfo Failed!\n"));
|
|
return(E_FAIL);
|
|
}
|
|
|
|
// test to make sure the number of pages is reasonable
|
|
if( pServerSheet->nNumPages == 0 )
|
|
return(DIGCERR_NUMPAGESZERO);
|
|
else if( (pServerSheet->nNumPages > MAX_PAGES) || (pServerSheet->nNumPages < nStartPage) )
|
|
return(DIGCERR_NUMPAGESTOOLARGE);
|
|
|
|
LPDIGCPAGEINFO pServerPage;
|
|
|
|
// step 2 : get the information for all the pages from the server
|
|
if( FAILED(fnInterface->GetPageInfo(&pServerPage)) )
|
|
{
|
|
TRACE(TEXT("JOY.CPL: CPANEL.CPP: Launch: GetPageInfo Failed!\n"));
|
|
return(E_FAIL);
|
|
}
|
|
|
|
|
|
// Allocate Memory for the pages!
|
|
HPROPSHEETPAGE *pPages = new (HPROPSHEETPAGE[pServerSheet->nNumPages]);
|
|
ASSERT (pPages);
|
|
|
|
ZeroMemory(pPages, sizeof(HPROPSHEETPAGE)*pServerSheet->nNumPages);
|
|
|
|
if( !pPages ) return(E_OUTOFMEMORY);
|
|
|
|
// Allocate Memory for the header!
|
|
LPPROPSHEETHEADER ppsh = new (PROPSHEETHEADER);
|
|
ASSERT (ppsh);
|
|
|
|
ZeroMemory(ppsh, sizeof(PROPSHEETHEADER));
|
|
|
|
ppsh->dwSize = sizeof(PROPSHEETHEADER);
|
|
ppsh->hwndParent = hWnd;
|
|
ppsh->hInstance = pServerPage[0].hInstance;
|
|
|
|
if( pServerSheet->fSheetIconFlag )
|
|
{
|
|
if( pServerSheet->lpwszSheetIcon )
|
|
{
|
|
// check to see if you are an INT or a WSTR
|
|
if( HIWORD((INT_PTR)pServerSheet->lpwszSheetIcon) )
|
|
{
|
|
// You are a string!
|
|
#ifdef _UNICODE
|
|
ppsh->pszIcon = pServerSheet->lpwszSheetIcon;
|
|
#else
|
|
USES_CONVERSION;
|
|
ppsh->pszIcon = W2A(pServerSheet->lpwszSheetIcon);
|
|
#endif
|
|
} else ppsh->pszIcon = (LPCTSTR)(pServerSheet->lpwszSheetIcon);
|
|
|
|
ppsh->dwFlags = PSH_USEICONID;
|
|
} else return(DIGCERR_NOICON);
|
|
}
|
|
|
|
// do we have a sheet caption ?
|
|
if( pServerSheet->lpwszSheetCaption )
|
|
{
|
|
#ifdef _UNICODE
|
|
ppsh->pszCaption = pServerSheet->lpwszSheetCaption;
|
|
#else
|
|
USES_CONVERSION;
|
|
ppsh->pszCaption = W2A(pServerSheet->lpwszSheetCaption);
|
|
#endif
|
|
ppsh->dwFlags |= PSH_PROPTITLE;
|
|
}
|
|
|
|
ppsh->nPages = pServerSheet->nNumPages;
|
|
ppsh->nStartPage = nStartPage;
|
|
|
|
// set the property pages inofrmation into the header
|
|
ppsh->phpage = pPages;
|
|
|
|
|
|
// OK, sheet stuff is done... now, time to do the pages!
|
|
|
|
#ifndef _UNICODE
|
|
USES_CONVERSION;
|
|
#endif
|
|
|
|
LPPROPSHEETPAGE lpPropPage = new (PROPSHEETPAGE);
|
|
ASSERT(lpPropPage);
|
|
|
|
ZeroMemory(lpPropPage, sizeof(PROPSHEETPAGE));
|
|
|
|
lpPropPage->dwSize = sizeof(PROPSHEETPAGE);
|
|
|
|
// 3.2 Now proceed to fill up each page
|
|
BYTE nIndex = 0;
|
|
do
|
|
{
|
|
// Assign the things that there are not questionable
|
|
lpPropPage->lParam = pServerPage[nIndex].lParam;
|
|
lpPropPage->hInstance = pServerPage[nIndex].hInstance;
|
|
|
|
// Add the title...
|
|
if( pServerPage[nIndex].lpwszPageTitle )
|
|
{
|
|
lpPropPage->dwFlags = PSP_USETITLE;
|
|
|
|
// Check to see if you are a String!!!
|
|
if( HIWORD((INT_PTR)pServerPage[nIndex].lpwszPageTitle) )
|
|
{
|
|
#ifdef _UNICODE
|
|
lpPropPage->pszTitle = pServerPage[nIndex].lpwszPageTitle;
|
|
#else
|
|
lpPropPage->pszTitle = W2A(pServerPage[nIndex].lpwszPageTitle);
|
|
#endif
|
|
} else lpPropPage->pszTitle = (LPTSTR)pServerPage[nIndex].lpwszPageTitle;
|
|
} else lpPropPage->pszTitle = NULL;
|
|
|
|
// if icon is required go ahead and add it.
|
|
if( pServerPage[nIndex].fIconFlag )
|
|
{
|
|
lpPropPage->dwFlags |= PSP_USEICONID;
|
|
|
|
// Check to see if you are an INT or a String!
|
|
if( HIWORD((INT_PTR)pServerPage[nIndex].lpwszPageIcon) )
|
|
{
|
|
// You're a string!!!
|
|
#ifdef _UNICODE
|
|
lpPropPage->pszIcon = pServerPage[nIndex].lpwszPageIcon;
|
|
#else
|
|
lpPropPage->pszIcon = W2A(pServerPage[nIndex].lpwszPageIcon);
|
|
#endif
|
|
} else lpPropPage->pszIcon = (LPCTSTR)(pServerPage[nIndex].lpwszPageIcon);
|
|
|
|
}
|
|
|
|
// if a pre - post processing call back proc is required go ahead and add it
|
|
if( pServerPage[nIndex].fProcFlag )
|
|
{
|
|
if( pServerPage[nIndex].fpPrePostProc )
|
|
{
|
|
lpPropPage->dwFlags |= PSP_USECALLBACK;
|
|
lpPropPage->pfnCallback = (LPFNPSPCALLBACK) pServerPage[nIndex].fpPrePostProc;
|
|
} else return(DIGCERR_NOPREPOSTPROC);
|
|
}
|
|
|
|
// and the essential "dialog" proc
|
|
if( pServerPage[nIndex].fpPageProc )
|
|
lpPropPage->pfnDlgProc = pServerPage[nIndex].fpPageProc;
|
|
else return(DIGCERR_NODLGPROC);
|
|
|
|
|
|
// Assign the Dialog Template!
|
|
if( HIWORD((INT_PTR)pServerPage[nIndex].lpwszTemplate) )
|
|
{
|
|
#ifdef _UNICODE
|
|
lpPropPage->pszTemplate = pServerPage[nIndex].lpwszTemplate;
|
|
#else
|
|
lpPropPage->pszTemplate = W2A(pServerPage[nIndex].lpwszTemplate);
|
|
#endif
|
|
} else lpPropPage->pszTemplate = (LPTSTR)pServerPage[nIndex].lpwszTemplate;
|
|
|
|
pPages[nIndex++] = CreatePropertySheetPage(lpPropPage);
|
|
} while( nIndex < pServerSheet->nNumPages );
|
|
|
|
if( lpPropPage )
|
|
delete (lpPropPage);
|
|
|
|
// step 5 : launch modal property sheet dialog
|
|
hresRet = (HRESULT)PropertySheet(ppsh);
|
|
|
|
if( pPages )
|
|
delete[] (pPages);
|
|
|
|
if( ppsh )
|
|
delete (ppsh);
|
|
|
|
if( fnInterface )
|
|
fnInterface->Release();
|
|
|
|
CoFreeUnusedLibraries(); //to free gcdef.dll now
|
|
|
|
//#ifndef _UNICODE
|
|
// Let COM go... on Memphis!
|
|
CoUninitialize();
|
|
|
|
|
|
if( hresRet )
|
|
{
|
|
switch( hresRet )
|
|
{
|
|
// In the event that the user wants to reboot...
|
|
case ID_PSREBOOTSYSTEM:
|
|
case ID_PSRESTARTWINDOWS:
|
|
#ifdef _DEBUG
|
|
TRACE(TEXT("JOY.CPL: PropertySheet returned a REBOOT request!\n"));
|
|
#endif
|
|
ExitWindowsEx(EWX_REBOOT, NULL);
|
|
break;
|
|
}
|
|
} else {
|
|
::PostMessage(hWnd, WM_COMMAND, (WPARAM)IDC_BTN_REFRESH, 0);
|
|
}
|
|
|
|
//#endif
|
|
|
|
// step 7 : return success / failure code back to the caller
|
|
return(hresRet);
|
|
}
|
|
|
|
/*
|
|
#ifdef _UNICODE
|
|
//////////////////////////////////////////////////////////////////////
|
|
// LPCDIGAMECNTRLPROPSHEET HasInterface(REFCLSID refCLSID, HINSTANCE hOleInst)
|
|
// Purpose: Tests for existance of rrid in refCLSID
|
|
LPCDIGAMECNTRLPROPSHEET HasInterface(REFCLSID refCLSID, HINSTANCE hOleInst)
|
|
{
|
|
typedef HRESULT (STDAPICALLTYPE * LPFNCOGETCLASSOBJECT)(REFCLSID, DWORD, COSERVERINFO *, REFIID, LPVOID *);
|
|
|
|
LPFNCOGETCLASSOBJECT fpCoGetClassObject = (LPFNCOGETCLASSOBJECT)GetProcAddress(hOleInst, "CoGetClassObject");
|
|
|
|
IClassFactory* ppv_classfactory;
|
|
LPCDIGAMECNTRLPROPSHEET fnInterface = 0;
|
|
|
|
if(SUCCEEDED(fpCoGetClassObject( refCLSID, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&ppv_classfactory)))
|
|
{
|
|
if(SUCCEEDED(ppv_classfactory->CreateInstance(NULL, IID_IDIGameCntrlPropSheet, (LPVOID *)&fnInterface)))
|
|
{
|
|
ppv_classfactory->Release();
|
|
}
|
|
else
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(TEXT("CPANEL.cpp: CreateInstance Failed!\n"));
|
|
#endif
|
|
// make sure the pointer is nulled
|
|
fnInterface = 0;
|
|
|
|
ppv_classfactory->Release();
|
|
}
|
|
}
|
|
else
|
|
#ifdef _DEBUG
|
|
else OutputDebugString(TEXT("CPANEL.cpp: LoadServerInterface Failed!\n"));
|
|
#endif
|
|
return fnInterface;
|
|
}
|
|
#endif // _UNICODE
|
|
*/
|