Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1296 lines
44 KiB
C++
1296 lines
44 KiB
C++
//-----------------------------------------------------------------------------
|
|
// File: Wizard.cpp
|
|
//
|
|
// Desc: UI routines
|
|
//
|
|
// Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
|
|
//-----------------------------------------------------------------------------
|
|
#include "duel.h"
|
|
#include "prsht.h"
|
|
#include "wizard.h"
|
|
#include "lobby.h"
|
|
#include "DPUtil.h"
|
|
#include "gameproc.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Globals
|
|
//-----------------------------------------------------------------------------
|
|
extern HINSTANCE g_hInst; // Program instance
|
|
extern HWND g_hwndMain; // Main window
|
|
extern LPDIRECTPLAY4 g_pDP; // DPlay object pointer
|
|
extern BOOL g_bHostPlayer; // Is the user hosting/joining a game
|
|
extern DPID g_LocalPlayerDPID;// Player id
|
|
extern LPGUID g_pAppGUID; // Duel's guid
|
|
extern BOOL g_bUseProtocol; // DPlay Protocol messaging
|
|
|
|
static BOOL gbWaitForLobby; // We will Wait for Settings from Lobby
|
|
static HFONT ghTitleFont; // Font for titles on setup wizard
|
|
static HFONT ghHeadingFont; // Font for headings on setup wizard
|
|
static int gnSession; // Index for tree view images
|
|
static int gnPlayer; // Index for tree view images
|
|
static HKEY ghDuelKey = NULL; // Duel registry key handle
|
|
static DWORD gdwDuelDisp; // Key created or opened
|
|
static HTREEITEM ghtiSession; // Points to a visible session item in
|
|
// tree ctl used for inserting players
|
|
static HWND ghWndSPCtl; // Handle to service provider control
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetupFonts()
|
|
// Desc: Initializes font structures (used for wizard controls)
|
|
//-----------------------------------------------------------------------------
|
|
BOOL SetupFonts()
|
|
{
|
|
LOGFONT lf;
|
|
TCHAR strFontName[MAX_FONTNAME];
|
|
HDC hDC = GetDC(g_hwndMain);
|
|
if (!hDC)
|
|
return FALSE;
|
|
|
|
LoadString(g_hInst, IDS_WIZARD_FONTNAME, strFontName, MAX_FONTNAME);
|
|
|
|
ZeroMemory(&lf,sizeof(lf));
|
|
lf.lfHeight = -MulDiv(11,GetDeviceCaps(hDC, LOGPIXELSY),72);
|
|
lf.lfWeight = 500;
|
|
lf.lfItalic = TRUE;
|
|
_tcscpy( lf.lfFaceName, strFontName );
|
|
ghTitleFont = CreateFontIndirect(&lf);
|
|
|
|
ZeroMemory(&lf,sizeof(lf));
|
|
lf.lfHeight = -MulDiv(11,GetDeviceCaps(hDC, LOGPIXELSY),72);
|
|
lf.lfWeight = 500;
|
|
_tcscpy( lf.lfFaceName, strFontName );
|
|
ghHeadingFont = CreateFontIndirect(&lf);
|
|
|
|
ReleaseDC(g_hwndMain, hDC);
|
|
|
|
if (!ghTitleFont || !ghHeadingFont)
|
|
{
|
|
CleanupFonts();
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CleanupFonts()
|
|
// Desc: Cleans up font structures
|
|
//-----------------------------------------------------------------------------
|
|
VOID CleanupFonts()
|
|
{
|
|
if (ghTitleFont)
|
|
DeleteObject(ghTitleFont);
|
|
if (ghHeadingFont)
|
|
DeleteObject(ghHeadingFont);
|
|
ghTitleFont = NULL;
|
|
ghHeadingFont = NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RegSet()
|
|
// Desc: Stores a data value in the registry
|
|
//-----------------------------------------------------------------------------
|
|
LONG RegSet( const TCHAR* strName, const BYTE* pData, DWORD dwSize )
|
|
{
|
|
#ifdef UNICODE
|
|
dwSize *= 2; // calc number of bytes
|
|
#endif
|
|
return RegSetValueEx( ghDuelKey, strName, 0, REG_SZ, pData, dwSize );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RegGet()
|
|
// Desc: Queries a value from the registry
|
|
//-----------------------------------------------------------------------------
|
|
LONG RegGet( const TCHAR* strName, BYTE* pData, DWORD* pdwDataSize )
|
|
{
|
|
DWORD dwType;
|
|
|
|
return RegQueryValueEx( ghDuelKey, strName, NULL, &dwType, pData,
|
|
pdwDataSize );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DoWizard()
|
|
// Desc: Creates and launches a wizard (property sheets) for user input
|
|
//-----------------------------------------------------------------------------
|
|
DWORD WINAPI DoWizard(LPVOID pv)
|
|
{
|
|
PROPSHEETPAGE psp[4];
|
|
PROPSHEETHEADER psh;
|
|
TCHAR strTitle1[MAX_WINDOWTITLE];
|
|
TCHAR strTitle2[MAX_WINDOWTITLE];
|
|
TCHAR strTitle3[MAX_WINDOWTITLE];
|
|
TCHAR strTitle4[MAX_WINDOWTITLE];
|
|
TCHAR strTitle5[MAX_WINDOWTITLE];
|
|
|
|
CoInitialize(NULL);
|
|
|
|
// Setup the property pages
|
|
|
|
LoadString(g_hInst, IDS_WIZARD_TITLE_GS, strTitle1, MAX_WINDOWTITLE);
|
|
LoadString(g_hInst, IDS_WIZARD_TITLE_SP, strTitle2, MAX_WINDOWTITLE);
|
|
LoadString(g_hInst, IDS_WIZARD_TITLE_JS, strTitle3, MAX_WINDOWTITLE);
|
|
LoadString(g_hInst, IDS_WIZARD_TITLE_HS, strTitle4, MAX_WINDOWTITLE);
|
|
LoadString(g_hInst, IDS_WIZARD_TITLE, strTitle5, MAX_WINDOWTITLE);
|
|
|
|
psp[0].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[0].dwFlags = PSP_USETITLE;
|
|
psp[0].hInstance = g_hInst;
|
|
#ifdef NONAMELESSUNION
|
|
psp[0].u.pszTemplate = MAKEINTRESOURCE(IDD_GAMESETUP);
|
|
psp[0].u2.pszIcon = NULL;
|
|
#else
|
|
psp[0].pszTemplate = MAKEINTRESOURCE(IDD_GAMESETUP);
|
|
psp[0].pszIcon = NULL;
|
|
#endif
|
|
psp[0].pfnDlgProc = (DLGPROC)DlgProcGameSetup;
|
|
psp[0].pszTitle = strTitle1;
|
|
psp[0].lParam = 0;
|
|
psp[0].pfnCallback = NULL;
|
|
|
|
psp[1].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[1].dwFlags = PSP_USETITLE;
|
|
psp[1].hInstance = g_hInst;
|
|
#ifdef NONAMELESSUNION
|
|
psp[1].u.pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEPROVIDER);
|
|
psp[1].u2.pszIcon = NULL;
|
|
#else
|
|
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEPROVIDER);
|
|
psp[1].pszIcon = NULL;
|
|
#endif
|
|
psp[1].pfnDlgProc = (DLGPROC)DlgProcChooseProvider;
|
|
psp[1].pszTitle = strTitle2;
|
|
psp[1].lParam = 0;
|
|
psp[1].pfnCallback = NULL;
|
|
|
|
psp[2].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[2].dwFlags = PSP_USETITLE;
|
|
psp[2].hInstance = g_hInst;
|
|
#ifdef NONAMELESSUNION
|
|
psp[2].u.pszTemplate = MAKEINTRESOURCE(IDD_JOINSESSION);
|
|
psp[2].u2.pszIcon = NULL;
|
|
#else
|
|
psp[2].pszTemplate = MAKEINTRESOURCE(IDD_JOINSESSION);
|
|
psp[2].pszIcon = NULL;
|
|
#endif
|
|
psp[2].pfnDlgProc = (DLGPROC)DlgProcJoinSession;
|
|
psp[2].pszTitle = strTitle3;
|
|
psp[2].lParam = 0;
|
|
psp[2].pfnCallback = NULL;
|
|
|
|
psp[3].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[3].dwFlags = PSP_USETITLE;
|
|
psp[3].hInstance = g_hInst;
|
|
#ifdef NONAMELESSUNION
|
|
psp[3].u.pszTemplate = MAKEINTRESOURCE(IDD_HOSTSESSION);
|
|
psp[3].u2.pszIcon = NULL;
|
|
#else
|
|
psp[3].pszTemplate = MAKEINTRESOURCE(IDD_HOSTSESSION);
|
|
psp[3].pszIcon = NULL;
|
|
#endif
|
|
psp[3].pfnDlgProc = (DLGPROC)DlgProcHostSession;
|
|
psp[3].pszTitle = strTitle4;
|
|
psp[3].lParam = 0;
|
|
psp[3].pfnCallback = NULL;
|
|
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD;
|
|
psh.hwndParent = g_hwndMain;
|
|
psh.hInstance = g_hInst;
|
|
#ifdef NONAMELESSUNION
|
|
psh.u.pszIcon = NULL;
|
|
psh.u2.nStartPage = 0;
|
|
psh.u3.ppsp = (LPCPROPSHEETPAGE) &psp;
|
|
#else
|
|
psh.pszIcon = NULL;
|
|
psh.nStartPage = 0;
|
|
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
|
|
#endif
|
|
psh.pszCaption = strTitle5;
|
|
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
|
|
psh.pfnCallback = NULL;
|
|
|
|
// open/create duel registry key
|
|
if( ERROR_SUCCESS != RegCreateKeyEx( HKEY_CURRENT_USER, DUEL_KEY, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS, NULL, &ghDuelKey,
|
|
&gdwDuelDisp ) )
|
|
{
|
|
TRACE(_T("Failed to create/open registry key\n"));
|
|
ShowError(IDS_WIN_ERROR);
|
|
goto ABORT;
|
|
}
|
|
|
|
if (!SetupFonts())
|
|
{
|
|
TRACE(_T("Failed to create fonts\n"));
|
|
ShowError(IDS_WIN_ERROR);
|
|
goto ABORT;
|
|
}
|
|
|
|
// launch the wizard
|
|
if (PropertySheet(&psh) < 0)
|
|
{
|
|
TRACE(_T("PropertySheet failed (comctl32.dll)\n"));
|
|
ShowError(IDS_WIN_ERROR);
|
|
goto ABORT;
|
|
}
|
|
|
|
CleanupFonts();
|
|
|
|
// Are we going to wait for a lobby to connect to us?
|
|
if (gbWaitForLobby)
|
|
gbWaitForLobby = DPLobbyWait();
|
|
// gbWaitForLobby now means we successfully got our connection settings
|
|
|
|
// Do we have our settings or a game session?
|
|
if( gbWaitForLobby || DPUtil_IsDPlayInitialized() )
|
|
{
|
|
// success
|
|
CoUninitialize();
|
|
PostMessage(g_hwndMain, UM_LAUNCH, (WPARAM)gbWaitForLobby, 0);
|
|
gbWaitForLobby = FALSE; // done with this flag
|
|
return 0;
|
|
}
|
|
|
|
ABORT:
|
|
// failure
|
|
CoUninitialize();
|
|
PostMessage(g_hwndMain, UM_ABORT, 0, 0);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DPEnumConnectionsCallback()
|
|
// Desc: Creates SP list box entries and associates connection data with them
|
|
//-----------------------------------------------------------------------------
|
|
BOOL FAR PASCAL DPEnumConnectionsCallback( const GUID* pguidSP,
|
|
VOID* pConnection, DWORD dwSize,
|
|
const DPNAME* pName, DWORD dwFlags,
|
|
VOID* pContext )
|
|
{
|
|
HWND hWnd = (HWND)pContext;
|
|
LRESULT iIndex;
|
|
VOID* pConnectionBuffer;
|
|
|
|
// Store service provider name in combo box
|
|
#ifdef UNICODE
|
|
iIndex = SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)pName->lpszShortName );
|
|
#else
|
|
iIndex = SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)pName->lpszShortNameA );
|
|
#endif
|
|
|
|
if( iIndex == CB_ERR )
|
|
return TRUE;
|
|
|
|
// Make space for Connection Shortcut
|
|
pConnectionBuffer = GlobalAllocPtr( GHND, dwSize );
|
|
if( pConnectionBuffer == NULL )
|
|
return TRUE;
|
|
|
|
// Store pointer to GUID in combo box
|
|
memcpy( pConnectionBuffer, pConnection, dwSize );
|
|
|
|
if( iIndex != LB_ERR )
|
|
SendMessage( hWnd, LB_SETITEMDATA, iIndex, (LPARAM)pConnectionBuffer );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DlgProcChooseProvider()
|
|
// Desc: Dialog procedure for the choose service provider dialog
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CALLBACK DlgProcChooseProvider( HWND hDlg, UINT msg, WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
VOID* pCon = NULL;
|
|
static LONG iIndex;
|
|
static HWND hWndCtl;
|
|
HRESULT hr;
|
|
|
|
switch( msg )
|
|
{
|
|
case WM_NOTIFY:
|
|
switch( ((NMHDR FAR *)lParam)->code )
|
|
{
|
|
case PSN_SETACTIVE:
|
|
PropSheet_SetWizButtons( GetParent(hDlg),
|
|
PSWIZB_BACK | PSWIZB_NEXT );
|
|
return TRUE;
|
|
|
|
case PSN_WIZNEXT:
|
|
// Release previously selected DPlay object, if any.
|
|
DPUtil_Release();
|
|
if( iIndex != LB_ERR )
|
|
{
|
|
pCon = (VOID*)SendMessage( hWndCtl, LB_GETITEMDATA,
|
|
iIndex, 0 );
|
|
if( pCon )
|
|
{
|
|
// Create directplay object
|
|
if( SUCCEEDED( DPUtil_InitDirectPlay( pCon ) ) )
|
|
{
|
|
if( g_bHostPlayer ) // Skip to host page
|
|
SetWindowLong( hDlg, DWL_MSGRESULT,
|
|
IDD_HOSTSESSION );
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ShowError(IDS_DPLAY_ERROR_IDC);
|
|
}
|
|
}
|
|
}
|
|
SetWindowLong( hDlg, DWL_MSGRESULT, -1 );
|
|
return TRUE;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
ReleaseSPData();
|
|
DPUtil_Release(); // Indicates no game session
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
SendDlgItemMessage( hDlg, IDC_SP_TITLE, WM_SETFONT,
|
|
(WPARAM)ghTitleFont, MAKELPARAM(TRUE,0) );
|
|
|
|
hWndCtl = GetDlgItem( hDlg, IDC_SERVICEPROVIDERS );
|
|
if( hWndCtl == NULL )
|
|
return TRUE;
|
|
|
|
// Remember the service provider control. used later in freeing
|
|
// sp information.
|
|
ghWndSPCtl = hWndCtl;
|
|
|
|
if( FAILED( hr = DPUtil_InitDirectPlay( pCon ) ) )
|
|
{
|
|
// Class not available, so tell them to get DPlay 6 or later
|
|
if( (hr == REGDB_E_CLASSNOTREG) || (hr == REGDB_E_IIDNOTREG) ||
|
|
(hr == E_NOINTERFACE))
|
|
ShowError(IDS_DPLAY_ERROR_CLSID);
|
|
else
|
|
ShowError(IDS_DPLAY_ERROR_IDC);
|
|
|
|
SetWindowLong( hDlg, DWL_MSGRESULT, -1 );
|
|
PostQuitMessage( -1 );
|
|
return TRUE;
|
|
}
|
|
|
|
//Insert all available connections into the connection listbox.
|
|
g_pDP->EnumConnections( g_pAppGUID, DPEnumConnectionsCallback,
|
|
hWndCtl, 0 );
|
|
SetFocus( hWndCtl );
|
|
|
|
SendMessage( hWndCtl, LB_SETCURSEL, iIndex, 0 );
|
|
iIndex = SendMessage( hWndCtl, LB_GETCURSEL, 0, 0 );
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
if( HIWORD(wParam) == LBN_SELCHANGE )
|
|
{
|
|
iIndex = SendMessage( hWndCtl, LB_GETCURSEL, 0, 0 );
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DlgProcGameSetup()
|
|
// Desc: Dialog procedure for the Game Setup Dialog.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CALLBACK DlgProcGameSetup (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static BOOL bWaitForLobby;
|
|
switch (msg)
|
|
{
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR FAR *) lParam)->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
if (bWaitForLobby)
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
|
|
else
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
|
|
return(TRUE);
|
|
|
|
case PSN_WIZNEXT:
|
|
if (g_bHostPlayer)
|
|
g_bUseProtocol = (SendDlgItemMessage(hDlg, IDC_USEPROTOCOL,
|
|
BM_GETCHECK, 0, 0)
|
|
== BST_CHECKED);
|
|
else
|
|
g_bUseProtocol = FALSE;
|
|
return(TRUE);
|
|
|
|
case PSN_WIZFINISH: // only if WaitForLobby selected
|
|
gbWaitForLobby = bWaitForLobby;
|
|
// fall thru
|
|
case PSN_QUERYCANCEL:
|
|
ReleaseSPData();
|
|
DPUtil_Release(); // Indicates no game session
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
// setup title fonts
|
|
SendDlgItemMessage(hDlg, IDC_GAMESETUP_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_JOINSESSION, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_HOSTSESSION, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_WAITFORLOBBY, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_USEPROTOCOL, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
// host by default
|
|
g_bHostPlayer = TRUE;
|
|
gbWaitForLobby = bWaitForLobby = FALSE;
|
|
SendDlgItemMessage(hDlg, IDC_HOSTSESSION, BM_SETCHECK, 1, 0);
|
|
SendDlgItemMessage(hDlg, IDC_JOINSESSION, BM_SETCHECK, 0, 0);
|
|
SendDlgItemMessage(hDlg, IDC_WAITFORLOBBY, BM_SETCHECK, 0, 0);
|
|
SendDlgItemMessage(hDlg, IDC_USEPROTOCOL, BM_SETCHECK, g_bUseProtocol, 0);
|
|
return(TRUE);
|
|
|
|
case WM_COMMAND:
|
|
if (HIWORD(wParam) == BN_CLICKED)
|
|
switch (LOWORD(wParam))
|
|
{
|
|
// Enable Use Protocol check box only if Hosting is selected
|
|
// Enable Finish Button only if WaitForLobby is selected
|
|
case IDC_HOSTSESSION:
|
|
g_bHostPlayer = TRUE;
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USEPROTOCOL), TRUE);
|
|
if (bWaitForLobby)
|
|
{
|
|
bWaitForLobby = FALSE;
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
|
|
}
|
|
return(TRUE);
|
|
|
|
case IDC_JOINSESSION:
|
|
if (g_bHostPlayer)
|
|
{
|
|
g_bHostPlayer = FALSE;
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USEPROTOCOL), FALSE);
|
|
}
|
|
if (bWaitForLobby)
|
|
{
|
|
bWaitForLobby = FALSE;
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
|
|
}
|
|
return(TRUE);
|
|
|
|
case IDC_WAITFORLOBBY:
|
|
bWaitForLobby = TRUE;
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
|
|
if (g_bHostPlayer)
|
|
{
|
|
g_bHostPlayer = FALSE;
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USEPROTOCOL), FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: EnumPlayer()
|
|
// Desc: EnumeratePlayer callback. Inserts player information into the passed
|
|
// in tree view control.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL WINAPI EnumPlayer( DPID pidID, DWORD dwPlayerType, const DPNAME* pName,
|
|
DWORD dwFlags, VOID* pContext )
|
|
{
|
|
HWND hWnd = (HWND)pContext;
|
|
HTREEITEM hItem;
|
|
|
|
#ifdef UNICODE
|
|
hItem = AddItemToTree( hWnd, pName->lpszShortName, 0, -1 );
|
|
#else
|
|
hItem = AddItemToTree( hWnd, pName->lpszShortNameA, 0, -1 );
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: EnumSession()
|
|
// Desc: EnumSessions callback. Inserts session description information in the
|
|
// passed in tree view control.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL WINAPI EnumSession( const DPSESSIONDESC2* pDPSessionDesc,
|
|
DWORD* pdwTimeOut, DWORD dwFlags, VOID* pContext )
|
|
{
|
|
HWND hWnd = (HWND)pContext;
|
|
HTREEITEM hItem;
|
|
TREEDATA* pdata;
|
|
|
|
if( dwFlags & DPESC_TIMEDOUT )
|
|
return FALSE; // don't try again
|
|
|
|
if( hWnd == NULL )
|
|
return FALSE;
|
|
|
|
// allocate memory to remember the guid
|
|
pdata = (TREEDATA*)malloc(sizeof(TREEDATA));
|
|
if( NULL == pdata )
|
|
return FALSE;
|
|
|
|
pdata->guid = pDPSessionDesc->guidInstance;
|
|
pdata->dwRefresh = 1;
|
|
|
|
#ifdef UNICODE
|
|
hItem = AddItemToTree( hWnd, pDPSessionDesc->lpszSessionName,
|
|
(DWORD)pdata, 1);
|
|
#else
|
|
hItem = AddItemToTree( hWnd, pDPSessionDesc->lpszSessionNameA,
|
|
(DWORD)pdata, 1);
|
|
#endif
|
|
|
|
if( hItem )
|
|
{
|
|
// It was new
|
|
TreeView_SelectItem( hWnd, hItem );
|
|
// Enumerate players for new session
|
|
DPUtil_EnumPlayers( (GUID*)&pDPSessionDesc->guidInstance, EnumPlayer,
|
|
(VOID*)hWnd, DPENUMPLAYERS_SESSION );
|
|
}
|
|
else
|
|
{
|
|
// It was already in the tree
|
|
free( pdata );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ResetTreeRefresh()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID ResetTreeRefresh( HWND hwndTV )
|
|
{
|
|
TV_ITEM item;
|
|
HTREEITEM hItem;
|
|
TREEDATA* psearchdata;
|
|
|
|
memset( &item, 0, sizeof(item) );
|
|
|
|
// Get the first app item (child of the running apps item)
|
|
hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_ROOT,(LPARAM) NULL);
|
|
|
|
while (hItem)
|
|
{
|
|
// gets its data
|
|
item.mask = TVIF_PARAM;
|
|
item.hItem = hItem;
|
|
SendMessage( hwndTV, TVM_GETITEM, 0, (LPARAM)&item );
|
|
// set the dwRefresh to 0
|
|
psearchdata = (TREEDATA*)item.lParam;
|
|
if (psearchdata) psearchdata->dwRefresh = 0;
|
|
SendMessage( hwndTV, TVM_SETITEM, 0, (LPARAM)&item );
|
|
|
|
// get the next one
|
|
hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem );
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RemoveStaleSessions()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID RemoveStaleSessions( HWND hwndTV )
|
|
{
|
|
TV_ITEM item;
|
|
HTREEITEM hItem,hItemNext;
|
|
TREEDATA* psearchdata;
|
|
|
|
memset(&item,0,sizeof(item));
|
|
|
|
// get the first app item (child of the running apps item)
|
|
hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_ROOT,(LPARAM) NULL);
|
|
|
|
while (hItem)
|
|
{
|
|
// get the next one
|
|
hItemNext = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem );
|
|
|
|
// gets its data
|
|
item.mask = TVIF_PARAM;
|
|
item.hItem = hItem;
|
|
SendMessage( hwndTV, TVM_GETITEM, 0, (LPARAM)&item );
|
|
|
|
// if dwRefresh is still 0, it wasn't enum'ed
|
|
psearchdata = (TREEDATA*)item.lParam;
|
|
if (psearchdata && (0 == psearchdata->dwRefresh))
|
|
{
|
|
free(psearchdata);
|
|
SendMessage( hwndTV, TVM_DELETEITEM, 0, (LPARAM)hItem );
|
|
}
|
|
|
|
hItem = hItemNext;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DlgProcJoinSession()
|
|
// Desc: Dialog procedure for Join Session Dialog
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CALLBACK DlgProcJoinSession( HWND hDlg, UINT msg, WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
static NM_TREEVIEW nmtv;
|
|
static HWND hWndCtl;
|
|
static TCHAR strPlayerName[MAX_PLAYERNAME+1];
|
|
static HANDLE dphEvent = NULL;
|
|
static UINT idTimer = 0;
|
|
|
|
TV_ITEM tvItem;
|
|
TCHAR strSessionName[MAX_SESSIONNAME+1];
|
|
DWORD dwPNameSize;
|
|
HRESULT hr = DP_OK;
|
|
HTREEITEM htiCur, htiNext;
|
|
GUID* pGuid;
|
|
|
|
switch( msg )
|
|
{
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR FAR *) lParam)->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
// Only the back button is valid at this point
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
|
|
|
|
if( hWndCtl )
|
|
TreeView_DeleteAllItems( hWndCtl );
|
|
|
|
// Enum sessions and let dplay decide the timeout
|
|
hr = DPUtil_EnumSessions( 0, EnumSession, (VOID*)hWndCtl,
|
|
DPENUMSESSIONS_ASYNC );
|
|
if( FAILED(hr) )
|
|
return FALSE;
|
|
|
|
// Enumerate players for all sessions
|
|
ghtiSession = TreeView_GetFirstVisible( hWndCtl );
|
|
|
|
while( ghtiSession )
|
|
{
|
|
// delete previous players from display
|
|
if ((htiNext = htiCur = TreeView_GetChild(hWndCtl, ghtiSession))
|
|
!= (HTREEITEM)0)
|
|
{
|
|
do
|
|
{
|
|
htiNext = TreeView_GetNextSibling(hWndCtl, htiCur);
|
|
TreeView_DeleteItem(hWndCtl, htiCur);
|
|
htiCur = htiNext;
|
|
} while (htiNext);
|
|
}
|
|
|
|
tvItem.hItem = ghtiSession;
|
|
tvItem.pszText = strSessionName;
|
|
tvItem.cchTextMax = MAX_SESSIONNAME;
|
|
TreeView_GetItem(hWndCtl, &tvItem);
|
|
// enumerate players for selected session
|
|
DPUtil_EnumPlayers( (GUID*)tvItem.lParam, EnumPlayer, (LPVOID) hWndCtl, DPENUMPLAYERS_SESSION);
|
|
ghtiSession = TreeView_GetNextItem(hWndCtl, ghtiSession, TVGN_NEXTVISIBLE);
|
|
}
|
|
|
|
// set Finish button highlite
|
|
if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) &&
|
|
(htiCur = TreeView_GetSelection(hWndCtl)))
|
|
{
|
|
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
|
|
SetFocus(hWndCtl);
|
|
|
|
// start up timer
|
|
idTimer = SetTimer(hDlg, ENUM_TIMER_ID, ENUM_TIMEOUT, NULL);
|
|
|
|
return(TRUE);
|
|
|
|
case PSN_WIZFINISH:
|
|
if (idTimer)
|
|
{
|
|
KillTimer(hDlg, idTimer);
|
|
idTimer = 0;
|
|
}
|
|
|
|
// add user selections to registry
|
|
if (ghDuelKey)
|
|
{
|
|
RegSet(TEXT("PlayerName"), (CONST BYTE *)strPlayerName,
|
|
sizeof(strPlayerName));
|
|
}
|
|
|
|
// get the session guid
|
|
if (nmtv.itemNew.lParam)
|
|
{
|
|
// user selected a session item, so just grab its lParam
|
|
pGuid = (GUID*)nmtv.itemNew.lParam;
|
|
}
|
|
else
|
|
{
|
|
// user selected a player item, so grab its parent's (session) lParam
|
|
htiCur = TreeView_GetParent(hWndCtl, nmtv.itemNew.hItem);
|
|
if (!htiCur)
|
|
{
|
|
// fail finish
|
|
ShowError(IDS_WIZARD_ERROR_GSG);
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, -1);
|
|
return (TRUE);
|
|
}
|
|
|
|
tvItem.hItem = htiCur;
|
|
tvItem.pszText = strSessionName;
|
|
tvItem.cchTextMax = MAX_SESSIONNAME;
|
|
TreeView_GetItem(hWndCtl, &tvItem);
|
|
pGuid = (GUID*)tvItem.lParam;
|
|
}
|
|
|
|
// Open session
|
|
if( FAILED( hr = DPUtil_OpenSession( pGuid ) ) )
|
|
{
|
|
// Fail finish
|
|
ShowError(IDS_DPLAY_ERROR_JS);
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, -1);
|
|
return TRUE;
|
|
}
|
|
|
|
// create player
|
|
if( FAILED( hr = DPUtil_CreatePlayer( &g_LocalPlayerDPID, strPlayerName,
|
|
NULL, NULL, 0 ) ) )
|
|
{
|
|
// fail finish
|
|
ShowError(IDS_DPLAY_ERROR_CP);
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, -1);
|
|
return (TRUE);
|
|
}
|
|
|
|
// everything went well, release allocated memory and finish
|
|
ReleaseSessionData(hWndCtl);
|
|
ReleaseSPData();
|
|
return(TRUE);
|
|
|
|
case PSN_QUERYCANCEL:
|
|
if (idTimer)
|
|
{
|
|
KillTimer(hDlg, idTimer);
|
|
idTimer = 0;
|
|
}
|
|
DPUtil_EnumSessions(0, EnumSession, (LPVOID)hWndCtl,
|
|
DPENUMSESSIONS_STOPASYNC);
|
|
ReleaseSessionData(hWndCtl);
|
|
ReleaseSPData();
|
|
DPUtil_Release(); // Indicates no game session
|
|
return(TRUE);
|
|
|
|
case PSN_WIZBACK:
|
|
if (idTimer)
|
|
{
|
|
KillTimer(hDlg, idTimer);
|
|
idTimer = 0;
|
|
}
|
|
DPUtil_EnumSessions(0, EnumSession, (LPVOID)hWndCtl,
|
|
DPENUMSESSIONS_STOPASYNC);
|
|
ReleaseSessionData(hWndCtl);
|
|
return(TRUE);
|
|
|
|
case TVN_SELCHANGING:
|
|
nmtv = *((NM_TREEVIEW *) lParam);
|
|
|
|
// set Finish button status
|
|
if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) &&
|
|
(htiCur = TreeView_GetSelection(hWndCtl)))
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
return(FALSE);
|
|
|
|
case NM_CLICK:
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
case WM_INITDIALOG:
|
|
// setup title fonts
|
|
SendDlgItemMessage(hDlg, IDC_JOIN_SESSION_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_JOIN_PLAYER_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
|
|
// setup user's previous data
|
|
dwPNameSize = MAX_PLAYERNAME+1;
|
|
strPlayerName[0]=0;
|
|
if (ghDuelKey && (RegGet(TEXT("PlayerName"),(LPBYTE)strPlayerName,&dwPNameSize) == ERROR_SUCCESS))
|
|
SetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName);
|
|
|
|
hWndCtl = GetDlgItem(hDlg, IDC_JOIN_SESSION);
|
|
if (hWndCtl == NULL) return(TRUE);
|
|
InitTreeViewImageLists(hWndCtl);
|
|
return(TRUE);
|
|
|
|
case WM_TIMER:
|
|
|
|
// guard against leftover timer messages after timer has been killed
|
|
if (!idTimer) break;
|
|
|
|
ResetTreeRefresh(hWndCtl);
|
|
// enum sessions and let dplay decide the timeout
|
|
hr = DPUtil_EnumSessions(0, EnumSession, (LPVOID) hWndCtl,
|
|
DPENUMSESSIONS_ASYNC);
|
|
if (FAILED(hr) && hr != DPERR_CONNECTING)
|
|
{
|
|
KillTimer(hDlg, idTimer);
|
|
idTimer = 0;
|
|
if (hr != DPERR_USERCANCEL)
|
|
ShowError(IDS_DPLAY_ERROR_ES);
|
|
}
|
|
|
|
RemoveStaleSessions(hWndCtl);
|
|
|
|
// set Finish button highlite
|
|
if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) &&
|
|
(htiCur = TreeView_GetSelection(hWndCtl)))
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_JOIN_PLAYERNAME:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
// set Finish button status
|
|
if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) &&
|
|
(htiCur = TreeView_GetSelection(hWndCtl)))
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DlgProcHostSession()
|
|
// Desc: Dialog proc for Host Session Dialog
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CALLBACK DlgProcHostSession(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static TCHAR strSessionName[MAX_SESSIONNAME+1];
|
|
static TCHAR strPlayerName[MAX_PLAYERNAME+1];
|
|
HRESULT hr;
|
|
DWORD dwPNameSize, dwSNameSize;
|
|
|
|
switch( msg )
|
|
{
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR FAR *) lParam)->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName, MAX_SESSIONNAME) &&
|
|
GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName, MAX_PLAYERNAME))
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
return(TRUE);
|
|
|
|
case PSN_WIZFINISH:
|
|
// add user selections to registry
|
|
if (ghDuelKey)
|
|
{
|
|
RegSet(TEXT("PlayerName"), (CONST BYTE *)strPlayerName, sizeof(strPlayerName));
|
|
RegSet(TEXT("SessionName"), (CONST BYTE *)strSessionName, sizeof(strSessionName));
|
|
}
|
|
|
|
// create session
|
|
if ((hr = DPUtil_CreateSession(strSessionName)) != DP_OK)
|
|
{
|
|
// fail finish
|
|
ShowError(IDS_DPLAY_ERROR_CS);
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, -1);
|
|
return (TRUE);
|
|
}
|
|
|
|
// create player
|
|
if( FAILED( hr = DPUtil_CreatePlayer( &g_LocalPlayerDPID, strPlayerName,
|
|
NULL, NULL, 0 ) ) )
|
|
{
|
|
ShowError(IDS_DPLAY_ERROR_CP);
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, -1);
|
|
return (TRUE);
|
|
}
|
|
|
|
// everything went well, release allocated memory and finish
|
|
ReleaseSPData();
|
|
return(TRUE);
|
|
|
|
case PSN_WIZBACK:
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, IDD_CHOOSEPROVIDER);
|
|
return(TRUE);
|
|
|
|
case PSN_QUERYCANCEL:
|
|
// release allocated memory
|
|
ReleaseSPData();
|
|
// release dplay
|
|
DPUtil_Release(); // Indicates no game session
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
case WM_INITDIALOG:
|
|
// setup title font
|
|
SendDlgItemMessage(hDlg, IDC_HOST_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_HOST_SESSION_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
SendDlgItemMessage(hDlg, IDC_HOST_PLAYER_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
|
|
|
|
dwPNameSize = MAX_PLAYERNAME+1;
|
|
dwSNameSize = MAX_SESSIONNAME+1;
|
|
strPlayerName[0]=0;
|
|
strSessionName[0]=0;
|
|
if (ghDuelKey)
|
|
{
|
|
if (RegGet(TEXT("PlayerName"), (LPBYTE)strPlayerName, &dwPNameSize) == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName);
|
|
if (RegGet(TEXT("SessionName"), (LPBYTE)strSessionName, &dwSNameSize) == ERROR_SUCCESS)
|
|
SetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName);
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_HOST_SESSIONNAME:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName, MAX_SESSIONNAME) &&
|
|
GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName, MAX_PLAYERNAME))
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_HOST_PLAYERNAME:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName, MAX_SESSIONNAME) &&
|
|
GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName, MAX_PLAYERNAME))
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitTreeViewImageLists()
|
|
// Desc: Creates an image list, adds bitmaps to it, and associates the image
|
|
// list with a tree-view control.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL InitTreeViewImageLists(HWND hwndTV)
|
|
{
|
|
HIMAGELIST himl; // handle of image list
|
|
HBITMAP hbmp; // handle of bitmap
|
|
|
|
// Create the image list.
|
|
if ((himl = ImageList_Create(CX_BITMAP, CY_BITMAP,
|
|
FALSE, NUM_BITMAPS, 0)) == NULL)
|
|
return FALSE;
|
|
|
|
// Add the session and player bitmaps.
|
|
hbmp = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_CLOSED_SESSION));
|
|
gnSession = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
|
|
DeleteObject(hbmp);
|
|
|
|
hbmp = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_PLAYER));
|
|
gnPlayer = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
|
|
DeleteObject(hbmp);
|
|
|
|
// Fail if not all of the images were added.
|
|
if (ImageList_GetImageCount(himl) < 2)
|
|
return FALSE;
|
|
|
|
// Associate the image list with the tree-view control.
|
|
TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FindItemInTree()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HTREEITEM FindItemInTree( HWND hwndTV, TREEDATA* pdata )
|
|
{
|
|
TV_ITEM item;
|
|
HTREEITEM hItem;
|
|
TREEDATA* psearchdata;
|
|
|
|
memset(&item,0,sizeof(item));
|
|
|
|
// get the first app item (child of the running apps item)
|
|
hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_ROOT,(LPARAM) NULL);
|
|
|
|
while (hItem)
|
|
{
|
|
// gets its data
|
|
item.mask = TVIF_PARAM;
|
|
item.hItem = hItem;
|
|
SendMessage( hwndTV, TVM_GETITEM, 0, (LPARAM)&item );
|
|
// is this the one?
|
|
psearchdata = (TREEDATA*)item.lParam;
|
|
if( IsEqualGUID( psearchdata->guid, pdata->guid ) )
|
|
{
|
|
// mark the item as seen
|
|
psearchdata->dwRefresh = 1;
|
|
SendMessage( hwndTV, TVM_SETITEM, 0, (LPARAM)&item );
|
|
return hItem;
|
|
}
|
|
// try the next one
|
|
hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem );
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: AddItemToTree()
|
|
// Desc: Adds items to a tree-view control.
|
|
//-----------------------------------------------------------------------------
|
|
HTREEITEM AddItemToTree( HWND hwndTV, TCHAR* strItem, DWORD dwData,
|
|
int nLevel )
|
|
{
|
|
static HTREEITEM hPrev = (HTREEITEM) TVI_FIRST;
|
|
static HTREEITEM hPrevRootItem = NULL;
|
|
static HTREEITEM hPrevLev2Item = NULL;
|
|
HTREEITEM hItem;
|
|
TV_ITEM tvi;
|
|
TV_INSERTSTRUCT tvins;
|
|
|
|
if( 1 == nLevel )
|
|
{
|
|
hItem = FindItemInTree( hwndTV, (TREEDATA*)dwData );
|
|
if (hItem) return NULL;
|
|
}
|
|
memset( &tvi,0,sizeof(tvi) );
|
|
memset( &tvins,0,sizeof(tvins) );
|
|
|
|
tvi.mask = TVIF_TEXT | TVIF_IMAGE
|
|
| TVIF_SELECTEDIMAGE | TVIF_PARAM;
|
|
|
|
// Set the state
|
|
if (nLevel == 1)
|
|
{
|
|
tvi.mask |= TVIF_STATE;
|
|
tvi.state = TVIS_SELECTED;
|
|
}
|
|
|
|
// Set the text of the item.
|
|
tvi.pszText = strItem;
|
|
|
|
// Set the image
|
|
if (nLevel == 1)
|
|
{
|
|
tvi.iImage = gnSession;
|
|
tvi.iSelectedImage = gnSession;
|
|
}
|
|
else
|
|
{
|
|
tvi.iImage = gnPlayer;
|
|
tvi.iSelectedImage = gnPlayer;
|
|
}
|
|
|
|
|
|
// Save the heading level in the item's application-defined
|
|
// data area.
|
|
tvi.lParam = (LPARAM) dwData;
|
|
|
|
#ifdef NONAMELESSUNION
|
|
tvins.u.item = tvi;
|
|
#else
|
|
tvins.item = tvi;
|
|
#endif
|
|
tvins.hInsertAfter = hPrev;
|
|
|
|
// Set the parent item based on the specified level.
|
|
if (nLevel == -1)
|
|
tvins.hParent = hPrevRootItem;
|
|
else if (nLevel == 1)
|
|
tvins.hParent = TVI_ROOT;
|
|
else if (nLevel == 2)
|
|
tvins.hParent = hPrevRootItem;
|
|
else
|
|
tvins.hParent = hPrevLev2Item;
|
|
|
|
// Add the item to the tree-view control.
|
|
hPrev = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0,
|
|
(LPARAM) (LPTV_INSERTSTRUCT) &tvins);
|
|
|
|
// Save the handle of the item.
|
|
if (nLevel == 1)
|
|
hPrevRootItem = hPrev;
|
|
else if (nLevel == 2)
|
|
hPrevLev2Item = hPrev;
|
|
|
|
return hPrev;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ReleaseSessionData()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID ReleaseSessionData(HWND hWndCtl)
|
|
{
|
|
HTREEITEM htiSession = TreeView_GetRoot( hWndCtl );
|
|
|
|
while( htiSession )
|
|
{
|
|
TCHAR strSessionName[MAX_SESSIONNAME+1];
|
|
TV_ITEM tvItem;
|
|
tvItem.hItem = htiSession;
|
|
tvItem.pszText = strSessionName;
|
|
tvItem.cchTextMax = MAX_SESSIONNAME;
|
|
|
|
TreeView_GetItem( hWndCtl, &tvItem );
|
|
if( tvItem.lParam )
|
|
free( (VOID*)tvItem.lParam );
|
|
|
|
htiSession = TreeView_GetNextSibling( hWndCtl, htiSession );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ReleaseSPData()
|
|
// Desc: Releases the memory allocated for service provider guids
|
|
// depends on global variable ghWndSPControl
|
|
//-----------------------------------------------------------------------------
|
|
VOID ReleaseSPData()
|
|
{
|
|
LPVOID lpCon = NULL;
|
|
int count,index;
|
|
|
|
if (ghWndSPCtl)
|
|
{
|
|
count = SendMessage(ghWndSPCtl, LB_GETCOUNT, 0, 0);
|
|
for (index = 0; index < count; index++)
|
|
{
|
|
lpCon = (LPVOID) SendMessage(ghWndSPCtl, LB_GETITEMDATA, index, 0);
|
|
if (lpCon) GlobalFreePtr(lpCon);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|