windows-nt/Source/XPSP1/NT/multimedia/directx/gamectrl/client/retrocfg.cpp

1777 lines
41 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*==========================================================================;
*
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
*
* File: retrocfg.cpp
* Content: Implement the RetroConfigProcess function, and supporting functions
* History:
* Date By Reason
* ============
* 10/13/99 pnewson created
* 10/27/99 pnewson Fix: Bug #113692 & #113943 - support for new dplay app flags
* 11/04/99 pnewson Bug #115279 - added HWND to check audio setup calls
* - call audio setup automatically when retrofit enabled
* 12/03/99 scottle Merged into joy.cpl, and handed to pnewson to bug fix.
* 01/25/2000 pnewson Removed "unlisted games" checkbox
* 02/15/2000 pnewson Assorted bug fixes:
* millen 131837
* millen 131794
* millen 131889
* 03/23/2000 rodtoll Changed include dsound.x --> dsprv.h
* 04/05/2000 pnewson Changed format of "More Information" dialog box.
* 04/10/2000 pnewson changes to make 64bit builds work.
* 06/21/2000 rodtoll Bug #36213 - DX8 options panel should only appear on Millenium
* Panel will not load on any other OS.
* rodtoll Bug #30776 - Game options control panel gives Unexpected error if no device is present
* 09/28/2000 rodtoll Bug #46003 - DPVOICE: Memory leak when joy.cpl closed without clicking voice tab
*
***************************************************************************/
#include <windows.h>
#include <tchar.h>
#include <initguid.h>
#include <mmsystem.h>
#include <dsound.h>
#include <dsprv.h> // need for GUID instances
#include "dvoice.h"
#include "resource.h"
#include "retrocfg.h"
#include "dndbg.h"
#include "creg.h"
#include "dvosal.h"
#include <commctrl.h>
#include <shellapi.h>
#include <windowsx.h>
#include "joyarray.h"
#include "..\\..\\..\\dplay\\dplobby\\dplobby\\dplobby.h"
INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR RetrofitInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR RetrofitSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR RetrofitApplyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR RetrofitResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR RetrofitDetailsHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK WizardCancelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK WizardLaunchProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK ConfirmHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK SoundInitFailureProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK WizardErrorProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK VoiceEnabledProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK DetailsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK PrevHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR ListViewLButtonDownHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR ListViewLButtonDblClkHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR ListViewKeydownHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void ClearAllCheckboxes(HWND hDlg, HWND hwndListView, LONG lNumItems);
void MySetCheckState(HWND hwnd, int iItem, BOOL bChecked);
BOOL MyGetCheckState(HWND hwnd, int iItem);
BOOL MyToggleCheckState(HWND hwnd, int iItem);
static void RetrofitOnAdvHelp (LPARAM);
static void RetrofitOnContextMenu (WPARAM wParam, LPARAM lParam);
// These defines have been repeated here instead of inclucing dplobpr.h
// because it causes build problems.
#define DPLAY_REGISTRY_APPS L"Software\\Microsoft\\DirectPlay\\Applications"
#define REGSTR_VAL_FLAGS L"dwFlags"
#define REGSTR_VAL_FILE L"File"
#define REGSTR_VAL_PATH L"Path"
#define MAX_ICONS 2048
// Gasp! globals!
HIMAGELIST g_himagelist = NULL;
int g_iCheckboxEmptyIndex;
int g_iCheckboxFullIndex;
HINSTANCE g_hResDLLInstance;
LPDIRECTPLAYVOICETEST g_IDirectPlayVoiceSetup = NULL;
#define COLUMN_HEADER_SIZE 32
TCHAR g_tstrColumnHeader1[COLUMN_HEADER_SIZE];
TCHAR g_tstrColumnHeader2[COLUMN_HEADER_SIZE];
WNDPROC g_ListViewProc;
#define MESSAGE_BOX_SCRATCH_SIZE 128
// From Main.cpp
extern HINSTANCE ghInstance;
// externals for context help
extern const DWORD gaHelpIDs[];
typedef HRESULT (* PFGETDEVICEID)(LPCGUID, LPGUID);
#undef DPF_MODNAME
#define DPF_MODNAME "DPVoiceCheckForDefaultDevices"
// DPVoiceCheckForDefaultDevices
//
// This function returns DV_OK if this system has at least a single playback
// and recording device.
//
HRESULT DPVoiceCheckForDefaultDevices()
{
HRESULT hr = DV_OK;
HMODULE hModule = NULL;
PFGETDEVICEID pfGetDeviceID = NULL;
GUID guidTmp;
hModule = LoadLibraryA("dsound.dll");
if (!hModule)
{
hr = GetLastError();
DPF(DVF_ERRORLEVEL, "Error loading dsound.dll - 0x%x", hr);
goto CHECKDEVICE_ERROR;
}
// attempt to get a pointer to the GetDeviceId function
pfGetDeviceID = (PFGETDEVICEID)GetProcAddress(hModule, "GetDeviceID");
if( !pfGetDeviceID )
{
hr = GetLastError();
DPF(DVF_ERRORLEVEL, "Error getting default devices - 0x%x", hr );
hr = DVERR_GENERIC;
goto CHECKDEVICE_ERROR;
}
hr = (*pfGetDeviceID)( &DSDEVID_DefaultPlayback, &guidTmp );
if( FAILED( hr ) )
{
DPF( DVF_ERRORLEVEL, "Error getting default playback device hr=0x%x", hr );
goto CHECKDEVICE_ERROR;
}
hr = (*pfGetDeviceID)( &DSDEVID_DefaultCapture, &guidTmp );
if( FAILED( hr ) )
{
DPF( DVF_ERRORLEVEL, "Error getting default capture device hr=0x%x", hr );
goto CHECKDEVICE_ERROR;
}
CHECKDEVICE_ERROR:
if( hModule )
FreeLibrary( hModule );
DPF_EXIT();
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "DPVoiceCheckOS"
// DPVoiceCheckOS
//
// This function returns DV_OK if this is a platform the retrofit runs on.
//
// This function will return DVERR_GENERIC if this is a platform the retrofit does not
// run on.
//
HRESULT DPVoiceCheckOS()
{
OSVERSIONINFO osVerInfo;
LONG lLastError;
osVerInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if( GetVersionEx( &osVerInfo ) )
{
// Win2K
if( osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
// NOTE: If we enable Whistler support we have to ensure that this returns an error
// if we're booting in safe-mode!
/*
// Whistler -- Major Version = 5 & Build # > 2195
if( osVerInfo.dwMajorVersion == 5 && osVerInfo.dwBuildNumber > 2195 )
{
return DV_OK;
}*/
return DVERR_GENERIC;
}
// Win9X
else
{
// Millenium Major = 4, Minor = 90
if( (HIBYTE(HIWORD(osVerInfo.dwBuildNumber)) == 4) &&
(LOBYTE(HIWORD(osVerInfo.dwBuildNumber)) == 90) )
{
return DV_OK;
}
return DVERR_GENERIC;
}
}
else
{
lLastError = GetLastError();
DPF( 0, "Error getting version info: 0x%x", lLastError );
return DVERR_GENERIC;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "DVoiceCPLInit"
HRESULT DVoiceCPLInit(void)
{
DPF_ENTER();
HRESULT hr = S_OK;
GUID guidTmp;
g_hResDLLInstance = ghInstance;
// Check to ensure we're on Millenium or Whistler. If we aren't we want to hide this
// control panel.
//
hr = DPVoiceCheckOS();
if( FAILED( hr ) )
{
DPF( DVF_ERRORLEVEL, "Error checking OS. Not a supported OS hr=0x%x", hr );
return hr;
}
// Check to ensure there is at least a default playback and default capture device in the
// system. If there is not we want to hide the control panel.
//
hr = DPVoiceCheckForDefaultDevices();
if( FAILED( hr ) )
{
DPF( DVF_ERRORLEVEL, "Error checking for play/cap device hr=0x%x", hr );
return hr;
}
if (FAILED(CoInitialize(NULL)))
{
DPF_EXIT();
return E_FAIL;
}
hr = CoCreateInstance(CLSID_DirectPlayVoiceTest,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDirectPlayVoiceTest,
(LPVOID *) &g_IDirectPlayVoiceSetup);
if( FAILED( hr ) )
{
DPF( DVF_ERRORLEVEL, "Failed to create test interface hr=0x%x", hr );
DPF_EXIT();
return hr;
}
DPF_EXIT();
return hr;
} // End DVoiceCPLInit();
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitProc"
INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
INT_PTR fRet;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG :
fRet = RetrofitInitDialogHandler(hDlg, message, wParam, lParam);
break;
case WM_NOTIFY :
{
LPNMHDR lpnm = (LPNMHDR) lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE :
fRet = RetrofitSetActiveHandler(hDlg, message, wParam, lParam);
break;
case PSN_APPLY :
fRet = RetrofitApplyHandler(hDlg, message, wParam, lParam);
break;
case PSN_RESET :
fRet = RetrofitResetHandler(hDlg, message, wParam, lParam);
break;
case LVN_ITEMCHANGED :
PropSheet_Changed(GetParent(hDlg), hDlg);
fRet = TRUE;
break;
default :
break;
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_DETAILS:
fRet = RetrofitDetailsHandler(hDlg, message, wParam, lParam);
break;
}
break;
case WM_DESTROY:
fRet = RetrofitDestroyHandler(hDlg, message, wParam, lParam);
break;
case WM_HELP:
RetrofitOnAdvHelp(lParam);
return(TRUE);
case WM_CONTEXTMENU:
RetrofitOnContextMenu(wParam, lParam);
return(TRUE);
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitInitDialogHandler"
INT_PTR RetrofitInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
CRegistry cregApps;
CRegistry cregApp;
DWORD dwIndex;
DWORD dwListViewIndex;
WCHAR swzBuffer[MAX_REGISTRY_STRING_SIZE];
TCHAR tszBuffer[MAX_REGISTRY_STRING_SIZE];
WCHAR swzFilename[MAX_REGISTRY_STRING_SIZE];
WCHAR swzPath[MAX_REGISTRY_STRING_SIZE];
TCHAR tszFilename[MAX_REGISTRY_STRING_SIZE];
TCHAR tszPathAndFile[MAX_REGISTRY_STRING_SIZE * 2 + 1];
DWORD dwStrLen;
HKEY hkApps;
LONG lRet;
HRESULT hr;
LVITEM lvitem;
LVCOLUMN lvcolumn;
RECT rect;
HWND hwndListView;
HICON hiLarge;
HICON hiSmall;
int iIconXSize;
int iIconYSize;
int iIconIndex;
int iScrollWidth;
DWORD dwGlobalFlags;
HICON hiconDefault;
HDC hdc;
TEXTMETRIC tm;
int iChars;
// create the image list for the icons
iIconXSize = GetSystemMetrics(SM_CXSMICON);
if (iIconXSize == 0)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed, code: %i", lRet);
goto error_level_0;
}
iIconYSize = GetSystemMetrics(SM_CYSMICON);
if (iIconYSize == 0)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed, code: %i", lRet);
goto error_level_0;
}
g_himagelist = ImageList_Create(iIconXSize, iIconYSize, ILC_MASK, 0, MAX_ICONS);
if (g_himagelist == NULL)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "ImageList_Create failed, code: %i", lRet);
goto error_level_0;
}
// Load the default icon for the image list
hiconDefault = LoadIcon(g_hResDLLInstance, MAKEINTRESOURCE(IDI_LIST_DEFAULT));
if (hiconDefault == NULL)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "LoadIcon failed, code: %i", lRet);
goto error_level_0;
}
// get a handle to the list view control
hwndListView = GetDlgItem(hDlg, IDC_LIST_GAMES);
if (hwndListView == NULL)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
goto error_level_0;
}
// subclass the list view
g_ListViewProc = (WNDPROC)SetWindowLongPtr(hwndListView, GWLP_WNDPROC, (INT_PTR)ListViewSubclassProc);
if (g_ListViewProc == NULL)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "SetWindowLong failed, code: %i", lRet);
goto error_level_0;
}
// add the enable column to the list view control
hdc = GetDC(hDlg);
if (hdc == NULL)
{
DPF(DVF_ERRORLEVEL, "GetDC failed");
goto error_level_0;
}
if (GetTextMetrics(hdc, &tm) == 0)
{
DPF(DVF_ERRORLEVEL, "GetTextMetrics failed");
goto error_level_0;
}
ZeroMemory(&lvcolumn, sizeof(lvcolumn));
lvcolumn.mask = LVCF_ORDER|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvcolumn.iOrder = 1;
lvcolumn.iSubItem = 1;
ZeroMemory(g_tstrColumnHeader2, COLUMN_HEADER_SIZE*sizeof(TCHAR));
iChars = LoadString(g_hResDLLInstance,
IDS_ENABLED_COLUMN_HEADER,
g_tstrColumnHeader2,
COLUMN_HEADER_SIZE);
if (iChars == 0)
{
DPF(DVF_ERRORLEVEL, "LoadString failed");
goto error_level_0;
}
lvcolumn.pszText = g_tstrColumnHeader2;
lvcolumn.cx = tm.tmAveCharWidth * iChars;
if (ListView_InsertColumn(hwndListView, 1, &lvcolumn) == -1)
{
DPF(DVF_ERRORLEVEL, "ListView_InsertColumn failed");
goto error_level_0;
}
// add the game column to the list view control
ZeroMemory(&lvcolumn, sizeof(lvcolumn));
lvcolumn.mask = LVCF_ORDER|LVCF_WIDTH|LVCF_TEXT;
lvcolumn.iOrder = 0;
if (!GetClientRect(hwndListView, &rect))
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "GetClientRect failed, code: %i", lRet);
goto error_level_0;
}
iScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
if (iScrollWidth == 0)
{
DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed");
goto error_level_0;
}
lvcolumn.cx = rect.right - rect.left - iScrollWidth - (iChars * tm.tmAveCharWidth);
ZeroMemory(g_tstrColumnHeader1, COLUMN_HEADER_SIZE*sizeof(TCHAR));
iChars = LoadString(g_hResDLLInstance,
IDS_GAMES_COLUMN_HEADER,
g_tstrColumnHeader1,
COLUMN_HEADER_SIZE);
if (iChars == 0)
{
DPF(DVF_ERRORLEVEL, "LoadString failed");
goto error_level_0;
}
lvcolumn.pszText = g_tstrColumnHeader1;
if (ListView_InsertColumn(hwndListView, 0, &lvcolumn) == -1)
{
DPF(DVF_ERRORLEVEL, "ListView_InsertColumn failed");
goto error_level_0;
}
// put checkboxes into the list view control
//ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_CHECKBOXES);
ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_SUBITEMIMAGES);
// add the small image list to the list view control
ListView_SetImageList(hwndListView, g_himagelist, LVSIL_SMALL);
// add icons to the image list for selected and cleared checkboxes
hiSmall = (HICON)LoadImage(
g_hResDLLInstance,
MAKEINTRESOURCE(IDI_CHECKBOX_EMPTY),
IMAGE_ICON,
iIconXSize,
iIconYSize,
LR_SHARED);
if (hiSmall == NULL)
{
DPF(DVF_ERRORLEVEL, "Unable to load empty checkbox icon resource");
goto error_level_0;
}
g_iCheckboxEmptyIndex = ImageList_AddIcon(g_himagelist, hiSmall);
if (g_iCheckboxEmptyIndex == -1)
{
DPF(DVF_ERRORLEVEL, "Unable to add empty checkbox icon to image list");
goto error_level_0;
}
hiSmall = (HICON)LoadImage(
g_hResDLLInstance,
MAKEINTRESOURCE(IDI_CHECKBOX_FULL),
IMAGE_ICON,
iIconXSize,
iIconYSize,
LR_SHARED);
if (hiSmall == NULL)
{
DPF(DVF_ERRORLEVEL, "Unable to load full checkbox icon resource");
goto error_level_0;
}
g_iCheckboxFullIndex = ImageList_AddIcon(g_himagelist, hiSmall);
if (g_iCheckboxFullIndex == -1)
{
DPF(DVF_ERRORLEVEL, "Unable to add full checkbox icon to image list");
goto error_level_0;
}
// open the applications area of the registry
if (!cregApps.Open(HKEY_LOCAL_MACHINE, DPLAY_REGISTRY_APPS, FALSE))
{
DPF(DVF_ERRORLEVEL, "Unable to open DirectPlay applications registry key");
goto error_level_0;
}
hkApps = cregApps.GetHandle();
// default the global checkbox to off
/*
if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, FALSE))
{
DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
// don't bail, continue
}
*/
// get the dwFlags value from the root of the applications area
if (cregApps.ReadDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
{
// set the checkbox if indicated
/*
if (dwGlobalFlags & DPLAPP_AUTOVOICE)
{
if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, TRUE))
{
DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
// don't bail, continue
}
}
*/
}
else
{
DPF(DVF_ERRORLEVEL, "Unable to read flags DirectPlay applications registry key");
// don't bail, continue
}
// enum the apps and add them to the list box
dwIndex = 0;
dwListViewIndex = 0;
while(1)
{
dwStrLen = MAX_REGISTRY_STRING_SIZE;
if (!cregApps.EnumKeys(swzBuffer, &dwStrLen, dwIndex))
{
// that's all, we're done.
break;
}
if (!cregApp.Open(hkApps, swzBuffer, FALSE))
{
DPF(DVF_ERRORLEVEL, "Unable to open application registry key");
continue;
}
// get the app flags so we know if we want
// to add this item to the list.
DWORD dwFlags;
if (!cregApp.ReadDWORD(REGSTR_VAL_FLAGS, dwFlags))
{
DPF(DVF_ERRORLEVEL, "CRegistry::ReadDWORD failed");
// forgive this error, since apps registered with
// older versions of DirectPlay will not have
// flags entries, set dwFlags to zero.
dwFlags = 0;
}
if (dwFlags & DPLAPP_NOENUM || dwFlags & DPLAPP_SELFVOICE)
{
// This app is either hidden, or implements it's own
// voice comms. We don't want to add it to the list,
// so continuue with the next iteration.
++dwIndex;
cregApp.Close();
continue;
}
// get the name of the key in a TCHAR
if (!OSAL_WideToTChar(tszBuffer, swzBuffer, MAX_REGISTRY_STRING_SIZE))
{
DPF(DVF_ERRORLEVEL, "OSAL_WideToAnsi failed");
++dwIndex;
cregApp.Close();
continue;
}
// get the application's icon
dwStrLen = MAX_REGISTRY_STRING_SIZE;
if (!cregApp.ReadString(REGSTR_VAL_FILE, swzFilename, &dwStrLen))
{
DPF(DVF_ERRORLEVEL, "CRegistry::ReadString failed");
++dwIndex;
cregApp.Close();
continue;
}
hr = OSAL_WideToTChar(tszFilename, swzFilename, dwStrLen);
if (FAILED(hr))
{
DPF(DVF_ERRORLEVEL, "OSAL_WidToAnsi failed, code: %i", hr);
++dwIndex;
cregApp.Close();
continue;
}
dwStrLen = MAX_REGISTRY_STRING_SIZE;
if (!cregApp.ReadString(REGSTR_VAL_PATH, swzPath, &dwStrLen))
{
DPF(DVF_ERRORLEVEL, "CRegistry::ReadString failed");
++dwIndex;
cregApp.Close();
continue;
}
if (!cregApp.Close())
{
DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
++dwIndex;
continue;
}
hr = OSAL_WideToTChar(tszPathAndFile, swzPath, MAX_REGISTRY_STRING_SIZE);
if (FAILED(hr))
{
DPF(DVF_ERRORLEVEL, "OSAL_AllocAndConvertToANSI failed, code: %i", hr);
++dwIndex;
continue;
}
if (tszPathAndFile[_tcslen(tszPathAndFile)-1] != '\\')
{
// since there isn't one there, tack on the trailing backslash
_tcscat(tszPathAndFile, _T("\\"));
}
_tcscat(tszPathAndFile, tszFilename);
ExtractIconEx(tszPathAndFile, 0, &hiLarge, &hiSmall, 1);
// don't need the large icon.
if (hiLarge != NULL)
{
DestroyIcon(hiLarge);
}
// add the small icon to the image list if it is valid
if (hiSmall != NULL)
{
iIconIndex = ImageList_AddIcon(g_himagelist, hiSmall);
}
else
{
iIconIndex = ImageList_AddIcon(g_himagelist, hiconDefault);
}
if (iIconIndex == -1)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "ImageList_AddIcon failed, code: %i", lRet);
++dwIndex;
continue;
}
lvitem.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE;
lvitem.iImage = iIconIndex;
if (hiSmall != NULL)
{
DestroyIcon(hiSmall);
}
lvitem.iItem = dwListViewIndex;
lvitem.iSubItem = 0;
lvitem.state = 0;
lvitem.stateMask = 0;
lvitem.pszText = tszBuffer;
lvitem.cchTextMax = 0;
lvitem.lParam = dwFlags;
lvitem.iIndent = 0;
if (ListView_InsertItem(hwndListView, &lvitem) == -1)
{
DPF(DVF_ERRORLEVEL, "ListView_InsertItem failed");
++dwIndex;
continue;
}
lvitem.mask = LVIF_IMAGE;
lvitem.iItem = dwListViewIndex;
lvitem.iSubItem = 1;
// check the flags to see if this item should be initially selected
if (dwFlags & DPLAPP_AUTOVOICE)
{
// select this item in the list
lvitem.iImage = g_iCheckboxFullIndex;
}
else
{
lvitem.iImage = g_iCheckboxEmptyIndex;
}
if (ListView_SetItem(hwndListView, &lvitem) == -1)
{
DPF(DVF_ERRORLEVEL, "ListView_SetItem failed");
ListView_DeleteItem(hwndListView, dwListViewIndex);
++dwIndex;
continue;
}
++dwIndex;
++dwListViewIndex;
}
if (!cregApps.Close())
{
DPF(DVF_ERRORLEVEL, "Unable to close DirectPlay applications registry key");
}
// If there is at least one item in the list, set the focus to the first item
// in the list so it will be marked when the user first comes to this tab.
if (dwListViewIndex > 0)
{
ListView_SetItemState(hwndListView, 0, LVIS_FOCUSED, LVIS_FOCUSED);
}
DPF_EXIT();
return TRUE;
error_level_0:
DPF_EXIT();
return TRUE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitSetActiveHandler"
INT_PTR RetrofitSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitApplyHandler"
INT_PTR RetrofitApplyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
LONG lRet;
LONG lNumItems;
LONG lIndex;
TCHAR tszItemText[MAX_REGISTRY_STRING_SIZE];
WCHAR swzItemText[MAX_REGISTRY_STRING_SIZE];
CRegistry cregApps;
CRegistry cregApp;
HKEY hkApps;
HWND hwndListView;
LVITEM lvitem;
DWORD dwFlags;
HRESULT hr1;
HRESULT hr2;
BOOL fItemsSelected;
INT_PTR intptr;
BOOL fTestRun = FALSE;
// Get a handle to the list view
hwndListView = GetDlgItem(hDlg, IDC_LIST_GAMES);
if (hwndListView == NULL)
{
lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
goto error_level_0;
}
// Get the number of items in the list view
lNumItems = ListView_GetItemCount(hwndListView);
// Prescan the list to see if any items have been
// checked off.
fItemsSelected = FALSE;
lvitem.mask = LVIF_IMAGE;
lvitem.iSubItem = 1;
for (lIndex = 0; lIndex < lNumItems; ++lIndex)
{
lvitem.iItem = lIndex;
if (!ListView_GetItem(hwndListView, &lvitem))
{
DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
goto error_level_0;
}
if (lvitem.iImage == g_iCheckboxFullIndex)
{
fItemsSelected = TRUE;
}
}
// look at the checkbox for unlisted games as well
/*
if (IsDlgButtonChecked(hDlg, IDC_UNLISTEDCHECK) == BST_CHECKED)
{
fItemsSelected = TRUE;
}
*/
if (fItemsSelected)
{
// Before we allow the user to enable the retrofit, we are going
// to make sure that setup has been run on the default
// devices, and run it forcibly if required.
hr1 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, NULL, DVFLAGS_QUERYONLY);
switch (hr1)
{
case DV_FULLDUPLEX:
// The sound hardware is fine, do nothing special.
break;
case DV_HALFDUPLEX:
// The wizard has been run before, but the result was half duplex.
// Give the user the option to run the wizard again, or continue
// with the half duplex limitation.
intptr = DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_PREV_HALFDUPLEX),
hDlg, PrevHalfDuplexProc);
switch (intptr)
{
case IDOK:
// the user has accepted half duplex mode, exit the control panel
break;
case IDCANCEL:
// the use hit the X or esc. Escape back to the control panel, and
// do not exit it
goto error_level_1;
case IDC_RUNTEST:
default:
// default should not occur, but treat as a run test
fTestRun = TRUE;
hr2 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, hDlg, 0);
break;
}
break;
default:
// With any other result, either the wizard hasn't been run, or it failed
// really badly. Run it again, but warn the user we're about to run the wizard,
// and give them the chance to bail.
if (DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_LAUNCH),
hDlg, WizardLaunchProc) != IDOK)
{
// treat this as if they bailed out of the wizard itself.
fTestRun = TRUE;
hr2 = DVERR_USERCANCEL;
}
else
{
fTestRun = TRUE;
hr2 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, hDlg, 0);
}
break;
}
// if the test was run, deal with the results
if (fTestRun)
{
switch (hr2)
{
case DV_FULLDUPLEX:
// The user just exited from the wizard, so we don't want to
// kick them completely out of the control panel. They should
// have to hit OK again in the control panel.
goto error_level_1;
break;
case DV_HALFDUPLEX:
// the user is only getting half duplex, confirm that they want
// to use voice chat anyway. If they don't, clear all checkboxes
// and don't exit the control panel.
if (DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_CONFIRM_HALFDUPLEX),
hDlg, ConfirmHalfDuplexProc) != IDOK)
{
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
}
// The user just exited from the wizard, so we don't want to
// kick them completely out of the control panel. They should
// have to hit OK again in the control panel.
goto error_level_1;
case DVERR_SOUNDINITFAILURE:
// The sound test failed miserably. Let the user know they cannot use
// voice chat, clear all the checkboxes and exit the control panel
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_CONFIRM_SOUNDINITFAILURE),
hDlg, SoundInitFailureProc);
goto error_level_1;
case DVERR_USERCANCEL:
// The user canceled the wizard, inform them they cannot use
// voice chat and clear all the checkboxes. Don't exit the property sheet.
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_CANCELED),
hDlg, WizardCancelProc);
goto error_level_1;
default:
// Anything else is unexpect and should be treated as an error.
// Display an error message, clear the checkboxes, and DO exit the propery sheet
ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_ERROR),
hDlg, WizardErrorProc);
goto error_level_1;
}
}
}
// If we get here, the test was already run on the default
// devices, and it returned either halfduplex or fullduplex,
// so we can set the bits as we please.
// Open the applications registry key
if (!cregApps.Open(HKEY_LOCAL_MACHINE, DPLAY_REGISTRY_APPS, FALSE))
{
DPF(DVF_ERRORLEVEL, "CRegistry::Open failed");
goto error_level_1;
}
hkApps = cregApps.GetHandle();
// set the autovoice bit - maintaint the state of the rest of the bits
// in case we add more global flags later
/*
if (!cregApps.ReadDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
{
DPF(DVF_ERRORLEVEL, "Error reading default flags from applications key");
dwGlobalFlags = 0;
// continue anyway
}
if (IsDlgButtonChecked(hDlg, IDC_UNLISTEDCHECK) == BST_CHECKED)
{
dwGlobalFlags |= DPLAPP_AUTOVOICE;
}
else
{
dwGlobalFlags &= ~DPLAPP_AUTOVOICE;
}
if (cregApps.WriteDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
{
DPF(DVF_ERRORLEVEL, "Error writing default flags to application key");
// continue anyway
}
*/
// loop through the items and set the app's flags according to
// the selected state of the list view
for (lIndex = 0; lIndex < lNumItems; ++lIndex)
{
// get the item info
lvitem.mask = LVIF_TEXT|LVIF_PARAM;
lvitem.iItem = lIndex;
lvitem.iSubItem = 0;
lvitem.state = 0;
lvitem.stateMask = 0;
lvitem.pszText = tszItemText;
lvitem.cchTextMax = MAX_REGISTRY_STRING_SIZE;
lvitem.iImage = 0;
lvitem.lParam = 0;
lvitem.iIndent = 0;
if (!ListView_GetItem(hwndListView, &lvitem))
{
DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
goto error_level_1;
}
dwFlags = (DWORD)lvitem.lParam;
if (!OSAL_TCharToWide(swzItemText, tszItemText, MAX_REGISTRY_STRING_SIZE))
{
DPF(DVF_ERRORLEVEL, "OSAL_AnsiToWide failed");
goto error_level_1;
}
lvitem.mask = LVIF_IMAGE;
lvitem.iItem = lIndex;
lvitem.iSubItem = 1;
if (!ListView_GetItem(hwndListView, &lvitem))
{
DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
goto error_level_1;
}
if (lvitem.iImage == g_iCheckboxFullIndex)
{
dwFlags |= DPLAPP_AUTOVOICE;
}
else
{
dwFlags &= ~DPLAPP_AUTOVOICE;
}
if (!cregApp.Open(hkApps, swzItemText, FALSE))
{
DPF(DVF_ERRORLEVEL, "CRegistry::Open failed");
goto error_level_1;
}
if (!cregApp.WriteDWORD(REGSTR_VAL_FLAGS, dwFlags))
{
DPF(DVF_ERRORLEVEL, "CRegistry::WriteDWORD failed");
goto error_level_1;
}
if (!cregApp.Close())
{
DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
goto error_level_1;
}
}
if (!cregApps.Close())
{
DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
goto error_level_1;
}
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
DPF_EXIT();
return TRUE;
error_level_1:
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
error_level_0:
DPF_EXIT();
return TRUE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitResetHandler"
INT_PTR RetrofitResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitDetailsHandler"
INT_PTR RetrofitDetailsHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_MOREINFO),
hDlg, DetailsProc);
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "RetrofitDestroyHandler"
INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
if( g_himagelist )
{
// clean up the image list
ImageList_Destroy(g_himagelist);
g_himagelist = NULL;
}
if( g_IDirectPlayVoiceSetup )
{
// release the IDirectPlayVoiceSetup interface
g_IDirectPlayVoiceSetup->Release();
g_IDirectPlayVoiceSetup = NULL;
}
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "WizardCancelProc"
INT_PTR CALLBACK WizardCancelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_WARNING);
SendDlgItemMessage(hDlg, IDC_ICON_NOTCOMPLETE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "WizardLaunchProc"
INT_PTR CALLBACK WizardLaunchProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_INFORMATION);
SendDlgItemMessage(hDlg, IDC_ICON_INFORMATION, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "PrevHalfDuplexProc"
INT_PTR CALLBACK PrevHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_WARNING);
SendDlgItemMessage(hDlg, IDC_WARNING_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
case IDC_RUNTEST:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ConfirmHalfDuplexProc"
INT_PTR CALLBACK ConfirmHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_WARNING);
SendDlgItemMessage(hDlg, IDC_ICON_WARNING, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "SoundInitFailureProc"
INT_PTR CALLBACK SoundInitFailureProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_ERROR);
SendDlgItemMessage(hDlg, IDC_ICON_ERROR, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "WizardErrorProc"
INT_PTR CALLBACK WizardErrorProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_ERROR);
SendDlgItemMessage(hDlg, IDC_ICON_ERROR, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "VoiceEnabledProc"
INT_PTR CALLBACK VoiceEnabledProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
HICON hIcon;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
hIcon = LoadIcon(NULL, IDI_INFORMATION);
SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "DetailsProc"
INT_PTR CALLBACK DetailsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
BOOL fRet;
static TCHAR *szMoreInfo = NULL;
static const int c_iMoreInfoStrLen = 2048;
fRet = FALSE;
switch (message)
{
case WM_INITDIALOG:
/*
hIcon = LoadIcon(NULL, IDI_INFORMATION);
SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
hIcon = LoadIcon(NULL, IDI_WARNING);
SendDlgItemMessage(hDlg, IDC_WARNING_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
*/
szMoreInfo = (TCHAR*)malloc((c_iMoreInfoStrLen-1)*sizeof(TCHAR));
if (szMoreInfo != NULL)
{
if (LoadString(g_hResDLLInstance, IDS_VOICEMOREINFO, szMoreInfo, c_iMoreInfoStrLen) != 0)
{
SetDlgItemText(hDlg, IDC_MOREINFO, szMoreInfo);
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
fRet = TRUE;
break;
default:
break;
}
break;
default:
break;
}
DPF_EXIT();
return fRet;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ClearAllCheckboxes"
void ClearAllCheckboxes(HWND hDlg, HWND hwndListView, LONG lNumItems)
{
LONG lIndex;
// get a handle to the list view control
HWND hwnd = GetDlgItem(hDlg, IDC_LIST_GAMES);
if (hwnd == NULL)
{
LONG lRet = GetLastError();
DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
return;
}
for (lIndex = 0; lIndex < lNumItems; ++lIndex)
{
MySetCheckState(hwnd, lIndex, FALSE);
}
/*
if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, FALSE))
{
DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
}
*/
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
return;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ListViewSubclassProc"
INT_PTR CALLBACK ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
LRESULT lResult;
switch (message)
{
case WM_LBUTTONDOWN:
ListViewLButtonDownHandler(hwnd, message, wParam, lParam);
break;
case WM_LBUTTONDBLCLK:
ListViewLButtonDblClkHandler(hwnd, message, wParam, lParam);
break;
case WM_KEYDOWN:
ListViewKeydownHandler(hwnd, message, wParam, lParam);
break;
default:
break;
}
lResult = CallWindowProc(g_ListViewProc, hwnd, message, wParam, lParam);
DPF_EXIT();
return lResult;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ListViewLButtonDownHandler"
INT_PTR ListViewLButtonDownHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
LVHITTESTINFO lvHitTestInfo;
lvHitTestInfo.pt.x = GET_X_LPARAM(lParam);
lvHitTestInfo.pt.y = GET_Y_LPARAM(lParam);
ListView_SubItemHitTest(hwnd, &lvHitTestInfo);
if (lvHitTestInfo.flags & LVHT_ONITEMICON && lvHitTestInfo.iSubItem == 1)
{
MyToggleCheckState(hwnd, lvHitTestInfo.iItem);
}
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ListViewLButtonDblClkHandler"
INT_PTR ListViewLButtonDblClkHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
LVHITTESTINFO lvHitTestInfo;
lvHitTestInfo.pt.x = GET_X_LPARAM(lParam);
lvHitTestInfo.pt.y = GET_Y_LPARAM(lParam);
ListView_HitTest(hwnd, &lvHitTestInfo);
if (lvHitTestInfo.flags & LVHT_ONITEMICON|LVHT_ONITEMLABEL)
{
LVITEM lvitem;
lvitem.mask = LVIF_IMAGE;
lvitem.iItem = lvHitTestInfo.iItem;
lvitem.iSubItem = 1;
if (ListView_GetItem(hwnd, &lvitem))
{
// we got the image, toggle the state
if (lvitem.iImage == g_iCheckboxEmptyIndex)
{
lvitem.iImage = g_iCheckboxFullIndex;
}
else
{
lvitem.iImage = g_iCheckboxEmptyIndex;
}
ListView_SetItem(hwnd, &lvitem);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
}
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "ListViewKeydownHandler"
INT_PTR ListViewKeydownHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DPF_ENTER();
int iItem;
switch (wParam)
{
case VK_SPACE:
// The space bar was hit. Figure out if one of the
// list view items has focus and if so, toggle the
// checkbox state
iItem = ListView_GetNextItem(hwnd, -1, LVNI_FOCUSED|LVNI_SELECTED);
if (iItem != -1)
{
MyToggleCheckState(hwnd, iItem);
}
break;
default:
break;
}
DPF_EXIT();
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "MySetCheckState"
void MySetCheckState(HWND hwnd, int iItem, BOOL bChecked)
{
LVITEM lvitem;
lvitem.mask = LVIF_IMAGE;
lvitem.iItem = iItem;
lvitem.iSubItem = 1;
if (ListView_GetItem(hwnd, &lvitem))
{
// we got the image, set the check state
if (bChecked)
{
lvitem.iImage = g_iCheckboxFullIndex;
}
else
{
lvitem.iImage = g_iCheckboxEmptyIndex;
}
ListView_SetItem(hwnd, &lvitem);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "MyGetCheckState"
BOOL MyGetCheckState(HWND hwnd, int iItem)
{
LVITEM lvitem;
lvitem.mask = LVIF_IMAGE;
lvitem.iItem = iItem;
lvitem.iSubItem = 1;
if (ListView_GetItem(hwnd, &lvitem))
{
// we got the image, return the state
if (lvitem.iImage == g_iCheckboxEmptyIndex)
{
return FALSE;
}
else
{
return TRUE;
}
}
return FALSE;
}
#undef DPF_MODNAME
#define DPF_MODNAME "MyToggleCheckState"
BOOL MyToggleCheckState(HWND hwnd, int iItem)
{
LVITEM lvitem;
lvitem.mask = LVIF_IMAGE;
lvitem.iItem = iItem;
lvitem.iSubItem = 1;
BOOL fRet = FALSE;
if (ListView_GetItem(hwnd, &lvitem))
{
// we got the image, toggle the state
if (lvitem.iImage == g_iCheckboxEmptyIndex)
{
lvitem.iImage = g_iCheckboxFullIndex;
fRet = FALSE;
}
else
{
lvitem.iImage = g_iCheckboxEmptyIndex;
fRet = TRUE;
}
ListView_SetItem(hwnd, &lvitem);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
return fRet;
}
////////////////////////////////////
// copied verbatim from appman.cpp
////////////////////////////////////
#define STR_LEN_32 32 // used by these functions...
static void RetrofitOnAdvHelp(LPARAM lParam)
{
DNASSERT (lParam);
// point to help file
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
DNASSERT (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: AppMan.cpp: OnAdvHelp: LoadString Failed to find IDS_HELPFILENAME!\n"));
#endif // _DEBUG
if( pszHelpFileName )
delete[] (pszHelpFileName);
}
////////////////////////////////////
// copied verbatim from appman.cpp
////////////////////////////////////
static void RetrofitOnContextMenu(WPARAM wParam, LPARAM lParam)
{
// HWND hListCtrl = NULL
DNASSERT (wParam);
#if 0
hListCtrl = GetDlgItem((HWND) wParam, IDC_APPMAN_DRIVE_LIST);
// If you are on the ListCtrl...
if( (HWND)wParam == hListCtrl )
{
SetFocus(hListCtrl);
// Don't attempt if nothing selected
if( iItem != NO_ITEM )
OnListviewContextMenu(hListCtrl,lParam);
} else
#endif
{
// point to help file
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
DNASSERT (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: appman.cpp: OnContextMenu: LoadString Failed to find IDS_HELPFILENAME!\n"));
#endif // _DEBUG
if( pszHelpFileName )
delete[] (pszHelpFileName);
}
}