PagePlayers.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /////////////////////////////////////////////////////////////////////////////
  2. // PagePlayers.cpp : implementation file
  3. //
  4. #include "stdafx.h"
  5. #include "AllSrvUI.h"
  6. #include "AllSrvUISheet.h"
  7. #include "PagePlayers.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CPagePlayers property page
  15. IMPLEMENT_DYNAMIC(CPagePlayers, CPropertyPage)
  16. /////////////////////////////////////////////////////////////////////////////
  17. // Static Initializtion
  18. BEGIN_AUTO_SIZER_MAP(_AutoSizerMap)
  19. AUTO_SIZER_ENTRY(IDC_BOOT_PLAYERS , LeftRight, 0, Right, NoRefresh)
  20. AUTO_SIZER_ENTRY(IDC_BOOT_PLAYERS , TopBottom, 0, Bottom, NoRefresh)
  21. AUTO_SIZER_ENTRY(IDC_SEND_CHAT_CAPTION, TopBottom, 0, Bottom, NoRefresh)
  22. AUTO_SIZER_ENTRY(IDC_SEND_CHAT_TEXT , Right, 0, Right, NoRefresh)
  23. AUTO_SIZER_ENTRY(IDC_SEND_CHAT_TEXT , TopBottom, 0, Bottom, NoRefresh)
  24. AUTO_SIZER_ENTRY(IDC_PLAYER_LIST , Right, 0, Right, NoRefresh)
  25. AUTO_SIZER_ENTRY(IDC_PLAYER_LIST , Bottom, 0, Bottom, NoRefresh)
  26. END_AUTO_SIZER_MAP()
  27. /////////////////////////////////////////////////////////////////////////////
  28. // Message Map
  29. BEGIN_MESSAGE_MAP(CPagePlayers, CPropertyPage)
  30. //{{AFX_MSG_MAP(CPagePlayers)
  31. ON_NOTIFY(HDN_ENDDRAG, 0, OnEndDragPlayerList)
  32. ON_NOTIFY(HDN_ENDTRACK, 0, OnEndTrackPlayerList)
  33. ON_WM_TIMER()
  34. ON_NOTIFY(LVN_ITEMCHANGED, IDC_PLAYER_LIST, OnItemChangedPlayerList)
  35. ON_NOTIFY(LVN_DELETEITEM, IDC_PLAYER_LIST, OnDeleteItemPlayerList)
  36. ON_BN_CLICKED(IDC_BOOT_PLAYERS, OnBootPlayers)
  37. //}}AFX_MSG_MAP
  38. END_MESSAGE_MAP()
  39. /////////////////////////////////////////////////////////////////////////////
  40. // Construction
  41. CPagePlayers::CPagePlayers() :
  42. CPropertyPage(CPagePlayers::IDD)
  43. {
  44. //{{AFX_DATA_INIT(CPagePlayers)
  45. m_strSendChat = _T("");
  46. //}}AFX_DATA_INIT
  47. // Create a TCObj.Strings object
  48. HRESULT hr = m_spStrings.CreateInstance("TCObj.Strings");
  49. if (FAILED(hr))
  50. GetSheet()->HandleError(hr, "creating TCObj.Strings helper object", true);
  51. }
  52. /////////////////////////////////////////////////////////////////////////////
  53. // Attributes
  54. /////////////////////////////////////////////////////////////////////////////
  55. // Overrides
  56. void CPagePlayers::OnEvent(IAGCEvent* pEvent)
  57. {
  58. AGCEventID eEvent;
  59. if (FAILED(pEvent->get_ID(&eEvent)))
  60. return;
  61. switch (eEvent)
  62. {
  63. case EventID_GameCreated:
  64. case EventID_GameDestroyed:
  65. {
  66. UpdateUI();
  67. break;
  68. }
  69. case EventID_LoginGame:
  70. {
  71. AddPlayer(pEvent);
  72. break;
  73. }
  74. case EventID_LogoutGame:
  75. {
  76. RemovePlayer(pEvent);
  77. break;
  78. }
  79. case EventID_ShipChangesSectors:
  80. {
  81. SectorOrTeamChange(pEvent, 2, L"New Sector Name");
  82. break;
  83. }
  84. case EventID_LeaveTeam:
  85. case EventID_JoinTeam:
  86. {
  87. SectorOrTeamChange(pEvent, 1, L"TeamName");
  88. break;
  89. }
  90. case EventID_TeamInfoChange:
  91. {
  92. TeamInfoChange(pEvent);
  93. break;
  94. }
  95. }
  96. }
  97. BOOL CPagePlayers::OnSetActive()
  98. {
  99. // Reload the chat MRU from the registry
  100. LoadFromRegistry();
  101. // Update the UI
  102. UpdateUI();
  103. // Perform default processing
  104. return CPropertyPage::OnSetActive();
  105. }
  106. BOOL CPagePlayers::PreTranslateMessage(MSG* pMsg)
  107. {
  108. if (WM_KEYDOWN == pMsg->message)
  109. {
  110. if (VK_RETURN == pMsg->wParam)
  111. {
  112. if (&m_comboSendChat == GetFocus() ||
  113. &m_comboSendChat == GetFocus()->GetParent())
  114. {
  115. SendChat();
  116. return true;
  117. }
  118. }
  119. }
  120. // Perform default processing
  121. return CPropertyPage::PreTranslateMessage(pMsg);
  122. }
  123. void CPagePlayers::DoDataExchange(CDataExchange* pDX)
  124. {
  125. // Perform default processing
  126. CPropertyPage::DoDataExchange(pDX);
  127. //{{AFX_DATA_MAP(CPagePlayers)
  128. DDX_Control(pDX, IDC_BOOT_PLAYERS, m_btnBootPlayers);
  129. DDX_Control(pDX, IDC_SEND_CHAT_CAPTION, m_staticSendChat);
  130. DDX_Control(pDX, IDC_SEND_CHAT_TEXT, m_comboSendChat);
  131. DDX_CBString(pDX, IDC_SEND_CHAT_TEXT, m_strSendChat);
  132. DDX_Control(pDX, IDC_PLAYER_LIST, m_listPlayers);
  133. //}}AFX_DATA_MAP
  134. }
  135. LRESULT CPagePlayers::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  136. {
  137. LRESULT lr;
  138. if (m_AutoSizer.ProcessMessage(message, wParam, lParam, &lr))
  139. return lr;
  140. // Perform default processing
  141. return CPropertyPage::WindowProc(message, wParam, lParam);
  142. }
  143. /////////////////////////////////////////////////////////////////////////////
  144. // Implementation
  145. void CPagePlayers::LoadFromRegistry()
  146. {
  147. // Open/create the registry key
  148. CRegKey key;
  149. key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
  150. // PlayerListColumnOrder
  151. CComBSTR bstrColumnOrder;
  152. LoadRegString(key, TEXT("PlayerListColumnOrder"), bstrColumnOrder);
  153. m_spStrings->RemoveAll();
  154. m_spStrings->AddDelimited(CComBSTR(L","), bstrColumnOrder);
  155. long cOrderedColumns = 0;
  156. m_spStrings->get_Count(&cOrderedColumns);
  157. if (c_cColumns == cOrderedColumns)
  158. {
  159. int vecOrder[c_cColumns];
  160. for (CComVariant i(0L); V_I4(&i) < c_cColumns; ++V_I4(&i))
  161. {
  162. bstrColumnOrder.Empty();
  163. m_spStrings->get_Item(&i, &bstrColumnOrder);
  164. vecOrder[V_I4(&i)] = _wtoi(bstrColumnOrder);
  165. }
  166. m_listPlayers.SetColumnOrderArray(c_cColumns, vecOrder);
  167. }
  168. // PlayerListColumnWidths
  169. CComBSTR bstrColumnWidths;
  170. LoadRegString(key, TEXT("PlayerListColumnWidths"), bstrColumnWidths);
  171. m_spStrings->RemoveAll();
  172. m_spStrings->AddDelimited(CComBSTR(L","), bstrColumnWidths);
  173. long cWidthColumns = 0;
  174. m_spStrings->get_Count(&cWidthColumns);
  175. if (c_cColumns == cWidthColumns)
  176. {
  177. for (CComVariant i(0L); V_I4(&i) < c_cColumns; ++V_I4(&i))
  178. {
  179. bstrColumnWidths.Empty();
  180. m_spStrings->get_Item(&i, &bstrColumnWidths);
  181. m_listPlayers.SetColumnWidth(V_I4(&i), _wtoi(bstrColumnWidths));
  182. }
  183. }
  184. else
  185. {
  186. for (int i = 0; i < c_cColumns; ++i)
  187. {
  188. TCHAR szColumn[_MAX_PATH];
  189. LVCOLUMN lvc = {LVCF_TEXT, 0, 0, szColumn, sizeofArray(szColumn)};
  190. m_listPlayers.GetColumn(i, &lvc);
  191. int cx = m_listPlayers.GetStringWidth(CString(szColumn) + TEXT(" "));
  192. m_listPlayers.SetColumnWidth(i, cx);
  193. }
  194. }
  195. // SendChatMRU
  196. m_comboSendChat.ResetContent();
  197. CRegKey keyMRU;
  198. if (ERROR_SUCCESS == keyMRU.Create(key, TEXT("SendChatMRU")))
  199. {
  200. // Read the count of strings
  201. DWORD cStrings = 0;
  202. keyMRU.QueryValue(cStrings, TEXT(".Count"));
  203. // Read each string and add it to the combo box
  204. for (DWORD i = 0; i < cStrings; ++i)
  205. {
  206. TCHAR szInt[16];
  207. CString strMRUItem;
  208. LoadRegString(keyMRU, _itot(i, szInt, 10), strMRUItem);
  209. strMRUItem.TrimLeft();
  210. strMRUItem.TrimRight();
  211. if (!strMRUItem.IsEmpty())
  212. m_comboSendChat.InsertString(i, strMRUItem);
  213. }
  214. }
  215. }
  216. void CPagePlayers::SavePlayerListColumnOrderToRegistry()
  217. {
  218. // Open/create the registry key
  219. CRegKey key;
  220. key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
  221. // Get the current column ordering
  222. int vecOrder[c_cColumns];
  223. for (int iCol = 0; iCol < c_cColumns; ++iCol)
  224. vecOrder[iCol] = iCol;
  225. m_listPlayers.GetColumnOrderArray(vecOrder, c_cColumns);
  226. // Format a comma-delimited string of the column ordering
  227. CString strColumnOrder;
  228. for (int i = 0; i < c_cColumns; ++i)
  229. {
  230. if (i)
  231. strColumnOrder += ",";
  232. TCHAR szNum[16];
  233. strColumnOrder += _itot(vecOrder[i], szNum, 10);
  234. }
  235. // Save to the registry
  236. key.SetValue(strColumnOrder, TEXT("PlayerListColumnOrder"));
  237. }
  238. void CPagePlayers::SavePlayerListColumnWidthsToRegistry()
  239. {
  240. // Open/create the registry key
  241. CRegKey key;
  242. key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
  243. // Format a comma-delimited string of the column widths
  244. CString strColumnWidths;
  245. for (int i = 0; i < c_cColumns; ++i)
  246. {
  247. if (i)
  248. strColumnWidths += ",";
  249. TCHAR szNum[16];
  250. strColumnWidths += _itot(m_listPlayers.GetColumnWidth(i), szNum, 10);
  251. }
  252. // Save to the registry
  253. key.SetValue(strColumnWidths, TEXT("PlayerListColumnWidths"));
  254. }
  255. void CPagePlayers::SaveSendChatMRUToRegistry()
  256. {
  257. // Open/create the registry key
  258. CRegKey key;
  259. if (ERROR_SUCCESS != key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI))
  260. return;
  261. // SendChatMRU
  262. CRegKey keyMRU;
  263. if (ERROR_SUCCESS != keyMRU.Create(key, TEXT("SendChatMRU")))
  264. return;
  265. // Write the count of strings
  266. int cStrings = min(m_comboSendChat.GetCount(), c_cMaxChatsInRegistry);
  267. keyMRU.SetValue(cStrings, TEXT(".Count"));
  268. // Write each string
  269. for (int i = 0; i < cStrings; ++i)
  270. {
  271. TCHAR szInt[16];
  272. CString strMRUItem;
  273. m_comboSendChat.GetLBText(i, strMRUItem);
  274. keyMRU.SetValue(strMRUItem, _itot(i, szInt, 10));
  275. }
  276. }
  277. void CPagePlayers::UpdateUI(bool bUpdateData)
  278. {
  279. // Update data members from fields, if specified
  280. if (bUpdateData)
  281. UpdateData();
  282. // Determine if a game is in progress or not
  283. bool bGameInProgress = NULL != GetSheet()->GetGame();
  284. // Get the number of players that are selected
  285. UINT cSelectedItems = m_listPlayers.GetSelectedCount();
  286. // Enable/disable the controls as needed
  287. m_staticSendChat.EnableWindow(bGameInProgress && cSelectedItems);
  288. m_comboSendChat.EnableWindow(bGameInProgress && cSelectedItems);
  289. m_btnBootPlayers.EnableWindow(bGameInProgress && cSelectedItems);
  290. }
  291. void CPagePlayers::SendChat()
  292. {
  293. CWaitCursor wait;
  294. // Update data members from fields
  295. UpdateData();
  296. // Get the number of players that are selected
  297. UINT cSelectedItems = m_listPlayers.GetSelectedCount();
  298. if (!cSelectedItems)
  299. return;
  300. // Send the chat message to the selected users
  301. m_strSendChat.TrimLeft();
  302. m_strSendChat.TrimRight();
  303. if (!m_strSendChat.IsEmpty())
  304. {
  305. // Look for the text in the MRU list
  306. int iFound = m_comboSendChat.FindStringExact(-1, m_strSendChat);
  307. if (iFound >= 0)
  308. m_comboSendChat.DeleteString(iFound);
  309. // Insert the string at the top of the combo box list
  310. m_comboSendChat.InsertString(0, m_strSendChat);
  311. // Limit the number of chats in the MRU combo
  312. int cStrings;
  313. do
  314. {
  315. cStrings = m_comboSendChat.GetCount();
  316. if (cStrings > c_cMaxChatsInRegistry)
  317. {
  318. m_comboSendChat.DeleteString(cStrings - 1);
  319. }
  320. } while (cStrings > c_cMaxChatsInRegistry);
  321. // Send to the whole game, if all players are selected
  322. CComBSTR bstrSendChat(m_strSendChat);
  323. if (m_listPlayers.GetItemCount() == static_cast<int>(cSelectedItems))
  324. {
  325. GetSheet()->GetGame()->SendChat(bstrSendChat, -1);
  326. }
  327. else
  328. {
  329. // Loop through each selected user
  330. POSITION it = m_listPlayers.GetFirstSelectedItemPosition();
  331. while (it)
  332. {
  333. // Get the next item
  334. int iIndex = m_listPlayers.GetNextSelectedItem(it);
  335. _ASSERTE(-1 != iIndex);
  336. DWORD dwItemData = m_listPlayers.GetItemData(iIndex);
  337. // Interpret the item's lParam
  338. IAdminShip* pShip = reinterpret_cast<IAdminShip*>(dwItemData);
  339. _ASSERTE(pShip);
  340. // Send the chat to the ship
  341. pShip->SendChat(bstrSendChat, -1);
  342. }
  343. }
  344. // Clear the string
  345. m_strSendChat.Empty();
  346. UpdateData(false);
  347. // Update the MRU list
  348. SaveSendChatMRUToRegistry();
  349. }
  350. }
  351. void CPagePlayers::PopulatePlayersList()
  352. {
  353. CWaitCursor wait;
  354. LPCSTR pszContext = "retrieving collection of players in game";
  355. // Clear the contents of the list
  356. m_listPlayers.DeleteAllItems();
  357. // Do nothing else if there is no game in progress
  358. if (NULL == GetSheet()->GetGame())
  359. return;
  360. // Get the collection of users in the game
  361. IAdminUsersPtr spUsers;
  362. HRESULT hr = GetSheet()->GetGame()->get_Users(&spUsers);
  363. if (FAILED(hr))
  364. {
  365. GetSheet()->HandleError(hr, pszContext, true);
  366. return;
  367. }
  368. // Get the enumerator object from the collection
  369. IUnknownPtr spEnumUnk;
  370. if (FAILED(hr = spUsers->get__NewEnum(&spEnumUnk)))
  371. {
  372. GetSheet()->HandleError(hr, pszContext, true);
  373. return;
  374. }
  375. IEnumVARIANTPtr spEnum(spEnumUnk);
  376. if (NULL == spEnum)
  377. {
  378. GetSheet()->HandleError(E_NOINTERFACE, pszContext, true);
  379. return;
  380. }
  381. // Iterate through each player from the enumerator
  382. int iIndex = 0;
  383. CComVariant players[32];
  384. do
  385. {
  386. // Fetch the next block of players from the enumerator
  387. ULONG cFetched;
  388. if (FAILED(hr = spEnum->Next(sizeofArray(players), players, &cFetched)))
  389. {
  390. GetSheet()->HandleError(hr, pszContext, true);
  391. return;
  392. }
  393. // Add each player to the list
  394. for (ULONG i = 0; i < cFetched; ++i)
  395. {
  396. // Convert the VARIANT to IDispatch, if not already
  397. VARTYPE vt = V_VT(&players[i]);
  398. if (VT_DISPATCH != vt && VT_UNKNOWN != vt)
  399. {
  400. GetSheet()->HandleError(DISP_E_TYPEMISMATCH, pszContext, true);
  401. return;
  402. }
  403. // Ensure that the IDispatch supports IAdminUser
  404. IAdminUserPtr spUser(V_DISPATCH(&players[i]));
  405. if (NULL == spUser)
  406. {
  407. GetSheet()->HandleError(E_NOINTERFACE, pszContext, true);
  408. return;
  409. }
  410. // Clear the VARIANT in the array
  411. players[i].Clear();
  412. // Get the ship object of the user
  413. IAdminShipPtr spShip;
  414. if (FAILED(hr = spUser->get_Ship(&spShip)))
  415. {
  416. GetSheet()->HandleError(hr, pszContext, true);
  417. return;
  418. }
  419. // Get the interesting properties of the User
  420. CComBSTR bstrName, bstrTeam, bstrSector;
  421. // Model Name
  422. spShip->get_Name(&bstrName);
  423. // Team
  424. IAGCTeamPtr spTeam;
  425. spShip->get_Team(&spTeam);
  426. if (NULL != spTeam)
  427. spTeam->get_Name(&bstrTeam);
  428. // Sector
  429. IAGCSectorPtr spSector;
  430. spShip->get_Sector(&spSector);
  431. if (NULL != spSector)
  432. spSector->get_Name(&bstrSector);
  433. // Add the ship to the list
  434. USES_CONVERSION;
  435. m_listPlayers.InsertItem(iIndex, OLE2CT(bstrName));
  436. m_listPlayers.SetItemText(iIndex, c_iColumnTeam, OLE2CT(bstrTeam));
  437. m_listPlayers.SetItemText(iIndex, c_iColumnSector, OLE2CT(bstrSector));
  438. m_listPlayers.SetItemData(iIndex, reinterpret_cast<DWORD>(spShip.Detach()));
  439. ++iIndex;
  440. }
  441. } while (S_FALSE != hr);
  442. }
  443. void CPagePlayers::AddPlayer(IAGCEvent* pEvent)
  444. {
  445. CWaitCursor wait;
  446. LPCSTR pszContext = "adding new player to the list";
  447. HRESULT hr;
  448. // Get the interesting properties of the event
  449. CComBSTR bstrName;
  450. pEvent->get_SubjectName(&bstrName);
  451. long idPlayer = -1;
  452. pEvent->get_SubjectID(&idPlayer);
  453. // Name must not be empty
  454. _ASSERTE(bstrName.Length());
  455. // Name must not already be in list
  456. USES_CONVERSION;
  457. LV_FINDINFO lvfi = {LVFI_STRING, OLE2CT(bstrName)};
  458. int iIndex = m_listPlayers.FindItem(&lvfi);
  459. _ASSERTE(-1 == iIndex);
  460. // Get the IAdminUser for the specified user
  461. IAdminUserPtr spUser;
  462. // if (FAILED(hr = GetSheet()->GetServer()->get_LookupUser(
  463. // static_cast<AGCUniqueID>(idPlayer), &spUser)))
  464. if (FAILED(hr = GetSheet()->GetServer()->get_FindUser(bstrName, &spUser)))
  465. {
  466. GetSheet()->HandleError(hr, pszContext, true);
  467. return;
  468. }
  469. // Get the ship object of the user
  470. IAdminShipPtr spShip;
  471. if (FAILED(hr = spUser->get_Ship(&spShip)))
  472. {
  473. GetSheet()->HandleError(hr, pszContext, true);
  474. return;
  475. }
  476. // Add the user to the list
  477. iIndex = m_listPlayers.GetItemCount();
  478. m_listPlayers.InsertItem(iIndex, OLE2CT(bstrName));
  479. m_listPlayers.SetItemText(iIndex, c_iColumnTeam, TEXT(""));
  480. m_listPlayers.SetItemText(iIndex, c_iColumnSector, TEXT(""));
  481. m_listPlayers.SetItemData(iIndex, reinterpret_cast<DWORD>(spShip.Detach()));
  482. }
  483. void CPagePlayers::RemovePlayer(IAGCEvent* pEvent)
  484. {
  485. // Get the interesting properties of the event
  486. CComBSTR bstrName;
  487. pEvent->get_SubjectName(&bstrName);
  488. // Name must not be empty
  489. _ASSERTE(bstrName.Length());
  490. // Name must already be in list
  491. USES_CONVERSION;
  492. LV_FINDINFO lvfi = {LVFI_STRING, OLE2CT(bstrName)};
  493. int iIndex = m_listPlayers.FindItem(&lvfi);
  494. _ASSERTE(-1 != iIndex);
  495. // Remove the item from the list
  496. m_listPlayers.DeleteItem(iIndex);
  497. }
  498. void CPagePlayers::SectorOrTeamChange(IAGCEvent* pEvent, int iColumn,
  499. LPCOLESTR pszProperty)
  500. {
  501. CWaitCursor wait;
  502. // Get the interesting properties of the event
  503. CComBSTR bstrName, bstrProperty;
  504. pEvent->get_SubjectName(&bstrName);
  505. CComVariant varNewPropertyName;
  506. pEvent->get_Property(&CComVariant(pszProperty), &varNewPropertyName);
  507. varNewPropertyName.ChangeType(VT_BSTR);
  508. bstrProperty = V_BSTR(&varNewPropertyName);
  509. // Name must not be empty
  510. _ASSERTE(bstrName.Length());
  511. // Find the list item with the specified name
  512. USES_CONVERSION;
  513. LV_FINDINFO lvfi = {LVFI_STRING, OLE2CT(bstrName)};
  514. int iIndex = m_listPlayers.FindItem(&lvfi);
  515. _ASSERTE(iIndex >= 0);
  516. // Change the sub-item of the list item
  517. m_listPlayers.SetItemText(iIndex, iColumn,
  518. bstrProperty.Length() ? OLE2CT(bstrProperty) : TEXT(""));
  519. }
  520. void CPagePlayers::TeamInfoChange(IAGCEvent* pEvent)
  521. {
  522. CWaitCursor wait;
  523. // Get the interesting properties of the event
  524. CComBSTR bstrTeam, bstrTeamNew;
  525. pEvent->get_SubjectName(&bstrTeam);
  526. CComVariant varTeamNew;
  527. pEvent->get_Property(&CComVariant(L"NewTeamName"), &varTeamNew);
  528. varTeamNew.ChangeType(VT_BSTR);
  529. CString strTeam(bstrTeam), strTeamNew(V_BSTR(&varTeamNew));
  530. // Name must not be empty
  531. _ASSERTE(!strTeam.IsEmpty());
  532. // Loop through each item in the list
  533. int cPlayers = m_listPlayers.GetItemCount();
  534. for (int i = 0; i < cPlayers; ++i)
  535. {
  536. // Get the list item's team name
  537. CString str(m_listPlayers.GetItemText(i, c_iColumnTeam));
  538. // Change the team name of this item, if it has the old team name
  539. if (str == strTeam)
  540. m_listPlayers.SetItemText(i, c_iColumnTeam, strTeamNew);
  541. }
  542. }
  543. /////////////////////////////////////////////////////////////////////////////
  544. // Message Handlers
  545. BOOL CPagePlayers::OnInitDialog()
  546. {
  547. // Register for events of interest
  548. GetSheet()->GetSession()->ActivateEvents(EventID_GameCreated, -1);
  549. GetSheet()->GetSession()->ActivateEvents(EventID_GameDestroyed, -1);
  550. GetSheet()->GetSession()->ActivateEvents(EventID_LoginGame, -1);
  551. GetSheet()->GetSession()->ActivateEvents(EventID_LogoutGame, -1);
  552. GetSheet()->GetSession()->ActivateEvents(EventID_ShipChangesSectors, -1);
  553. GetSheet()->GetSession()->ActivateEvents(EventID_LeaveTeam, -1);
  554. GetSheet()->GetSession()->ActivateEvents(EventID_JoinTeam, -1);
  555. GetSheet()->GetSession()->ActivateEvents(EventID_TeamInfoChange, -1);
  556. // Perform default processing
  557. CPropertyPage::OnInitDialog();
  558. // Initialize the AutoSize object
  559. m_AutoSizer.SetWindowAndRules(*this, _AutoSizerMap);
  560. // Set the list view control extended styles
  561. DWORD dwExStyle = LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP;
  562. m_listPlayers.SetExtendedStyle(dwExStyle);
  563. // Add columns to the list view control
  564. m_listPlayers.InsertColumn(c_iColumnName , CString((LPCSTR)IDS_COLUMN_PLAYER));
  565. m_listPlayers.InsertColumn(c_iColumnTeam , CString((LPCSTR)IDS_COLUMN_TEAM ));
  566. m_listPlayers.InsertColumn(c_iColumnSector, CString((LPCSTR)IDS_COLUMN_SECTOR));
  567. // Load previous values from registry
  568. LoadFromRegistry();
  569. // Update fields from data members
  570. UpdateData(false);
  571. // Update the UI
  572. UpdateUI();
  573. // Populate the list of players
  574. PopulatePlayersList();
  575. // Set the focus to the first tabstop control
  576. return true;
  577. }
  578. void CPagePlayers::OnEndDragPlayerList(NMHDR* pNMHDR, LRESULT* pResult)
  579. {
  580. HD_NOTIFY* phdn = (HD_NOTIFY*)pNMHDR;
  581. if (pNMHDR->hwndFrom != m_listPlayers.GetHeaderCtrl()->GetSafeHwnd())
  582. return;
  583. // Defer saving the new column ordering for a few seconds
  584. KillTimer(c_idTimerReorder);
  585. SetTimer(c_idTimerReorder, c_dwDelayReorder, NULL);
  586. *pResult = 0;
  587. }
  588. void CPagePlayers::OnEndTrackPlayerList(NMHDR* pNMHDR, LRESULT* pResult)
  589. {
  590. HD_NOTIFY* phdn = (HD_NOTIFY*)pNMHDR;
  591. if (pNMHDR->hwndFrom != m_listPlayers.GetHeaderCtrl()->GetSafeHwnd())
  592. return;
  593. // Defer saving the new column widths until controls have updated
  594. KillTimer(c_idTimerResize);
  595. SetTimer(c_idTimerResize, c_dwDelayResize, NULL);
  596. *pResult = 0;
  597. }
  598. void CPagePlayers::OnTimer(UINT nIDEvent)
  599. {
  600. switch (nIDEvent)
  601. {
  602. case c_idTimerReorder:
  603. KillTimer(nIDEvent);
  604. SavePlayerListColumnOrderToRegistry();
  605. return;
  606. case c_idTimerResize:
  607. KillTimer(nIDEvent);
  608. SavePlayerListColumnWidthsToRegistry();
  609. return;
  610. }
  611. // Perform default processing
  612. CPropertyPage::OnTimer(nIDEvent);
  613. }
  614. void CPagePlayers::OnItemChangedPlayerList(NMHDR* pNMHDR, LRESULT* pResult)
  615. {
  616. // Interpret the message parameters
  617. NM_LISTVIEW* pNMLV = reinterpret_cast<NM_LISTVIEW*>(pNMHDR);
  618. // Update the UI if an item selection has changed
  619. if (pNMLV->uChanged & LVIF_STATE)
  620. UpdateUI();
  621. // Obligatory result code
  622. *pResult = 0;
  623. }
  624. void CPagePlayers::OnDeleteItemPlayerList(NMHDR* pNMHDR, LRESULT* pResult)
  625. {
  626. // Interpret the message parameters
  627. NM_LISTVIEW* pNMLV = reinterpret_cast<NM_LISTVIEW*>(pNMHDR);
  628. // Interpret the item's lParam
  629. IAdminShip* pShip = reinterpret_cast<IAdminShip*>(pNMLV->lParam);
  630. _ASSERTE(pShip);
  631. // Release the interface
  632. pShip->Release();
  633. // Obligatory result code
  634. *pResult = 0;
  635. }
  636. void CPagePlayers::OnBootPlayers()
  637. {
  638. HRESULT hr;
  639. LPCSTR pszContext = "booting player from the game";
  640. // Get the count of selected players
  641. int cSelected = m_listPlayers.GetSelectedCount();
  642. _ASSERTE(cSelected);
  643. // Display a confirmation dialog
  644. CString strText;
  645. if (1 == cSelected)
  646. strText.LoadString(IDS_BOOT_SELECTED_ONE);
  647. else
  648. strText.Format(IDS_BOOT_SELECTED, cSelected);
  649. // Display the message box
  650. UINT nFlags = MB_ICONQUESTION | MB_YESNO;
  651. int nResponse = MessageBox(strText, NULL, nFlags);
  652. if (IDYES != nResponse)
  653. return;
  654. // Loop through each selected user
  655. POSITION it = m_listPlayers.GetFirstSelectedItemPosition();
  656. while (it)
  657. {
  658. // Get the next item
  659. int iIndex = m_listPlayers.GetNextSelectedItem(it);
  660. _ASSERTE(-1 != iIndex);
  661. DWORD dwItemData = m_listPlayers.GetItemData(iIndex);
  662. // Interpret the item's lParam
  663. IAdminShip* pShip = reinterpret_cast<IAdminShip*>(dwItemData);
  664. _ASSERTE(pShip);
  665. // Get the User property of the Ship
  666. IAdminUserPtr spUser;
  667. if (FAILED(hr = pShip->get_User(&spUser)))
  668. {
  669. GetSheet()->HandleError(hr, pszContext, false);
  670. return;
  671. }
  672. // Boot the player from the game
  673. if (FAILED(hr = spUser->Boot()))
  674. {
  675. GetSheet()->HandleError(hr, pszContext, false);
  676. return;
  677. }
  678. }
  679. // Give the focus to the list control
  680. m_listPlayers.SetFocus();
  681. // Remove the "Default Button" style
  682. m_btnBootPlayers.SetButtonStyle(
  683. m_btnBootPlayers.GetButtonStyle() & ~BS_DEFPUSHBUTTON);
  684. }