///////////////////////////////////////////////////////////////////////////// // PagePlayers.cpp : implementation file // #include "stdafx.h" #include "AllSrvUI.h" #include "AllSrvUISheet.h" #include "PagePlayers.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPagePlayers property page IMPLEMENT_DYNAMIC(CPagePlayers, CPropertyPage) ///////////////////////////////////////////////////////////////////////////// // Static Initializtion BEGIN_AUTO_SIZER_MAP(_AutoSizerMap) AUTO_SIZER_ENTRY(IDC_BOOT_PLAYERS , LeftRight, 0, Right, NoRefresh) AUTO_SIZER_ENTRY(IDC_BOOT_PLAYERS , TopBottom, 0, Bottom, NoRefresh) AUTO_SIZER_ENTRY(IDC_SEND_CHAT_CAPTION, TopBottom, 0, Bottom, NoRefresh) AUTO_SIZER_ENTRY(IDC_SEND_CHAT_TEXT , Right, 0, Right, NoRefresh) AUTO_SIZER_ENTRY(IDC_SEND_CHAT_TEXT , TopBottom, 0, Bottom, NoRefresh) AUTO_SIZER_ENTRY(IDC_PLAYER_LIST , Right, 0, Right, NoRefresh) AUTO_SIZER_ENTRY(IDC_PLAYER_LIST , Bottom, 0, Bottom, NoRefresh) END_AUTO_SIZER_MAP() ///////////////////////////////////////////////////////////////////////////// // Message Map BEGIN_MESSAGE_MAP(CPagePlayers, CPropertyPage) //{{AFX_MSG_MAP(CPagePlayers) ON_NOTIFY(HDN_ENDDRAG, 0, OnEndDragPlayerList) ON_NOTIFY(HDN_ENDTRACK, 0, OnEndTrackPlayerList) ON_WM_TIMER() ON_NOTIFY(LVN_ITEMCHANGED, IDC_PLAYER_LIST, OnItemChangedPlayerList) ON_NOTIFY(LVN_DELETEITEM, IDC_PLAYER_LIST, OnDeleteItemPlayerList) ON_BN_CLICKED(IDC_BOOT_PLAYERS, OnBootPlayers) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Construction CPagePlayers::CPagePlayers() : CPropertyPage(CPagePlayers::IDD) { //{{AFX_DATA_INIT(CPagePlayers) m_strSendChat = _T(""); //}}AFX_DATA_INIT // Create a TCObj.Strings object HRESULT hr = m_spStrings.CreateInstance("TCObj.Strings"); if (FAILED(hr)) GetSheet()->HandleError(hr, "creating TCObj.Strings helper object", true); } ///////////////////////////////////////////////////////////////////////////// // Attributes ///////////////////////////////////////////////////////////////////////////// // Overrides void CPagePlayers::OnEvent(IAGCEvent* pEvent) { AGCEventID eEvent; if (FAILED(pEvent->get_ID(&eEvent))) return; switch (eEvent) { case EventID_GameCreated: case EventID_GameDestroyed: { UpdateUI(); break; } case EventID_LoginGame: { AddPlayer(pEvent); break; } case EventID_LogoutGame: { RemovePlayer(pEvent); break; } case EventID_ShipChangesSectors: { SectorOrTeamChange(pEvent, 2, L"New Sector Name"); break; } case EventID_LeaveTeam: case EventID_JoinTeam: { SectorOrTeamChange(pEvent, 1, L"TeamName"); break; } case EventID_TeamInfoChange: { TeamInfoChange(pEvent); break; } } } BOOL CPagePlayers::OnSetActive() { // Reload the chat MRU from the registry LoadFromRegistry(); // Update the UI UpdateUI(); // Perform default processing return CPropertyPage::OnSetActive(); } BOOL CPagePlayers::PreTranslateMessage(MSG* pMsg) { if (WM_KEYDOWN == pMsg->message) { if (VK_RETURN == pMsg->wParam) { if (&m_comboSendChat == GetFocus() || &m_comboSendChat == GetFocus()->GetParent()) { SendChat(); return true; } } } // Perform default processing return CPropertyPage::PreTranslateMessage(pMsg); } void CPagePlayers::DoDataExchange(CDataExchange* pDX) { // Perform default processing CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CPagePlayers) DDX_Control(pDX, IDC_BOOT_PLAYERS, m_btnBootPlayers); DDX_Control(pDX, IDC_SEND_CHAT_CAPTION, m_staticSendChat); DDX_Control(pDX, IDC_SEND_CHAT_TEXT, m_comboSendChat); DDX_CBString(pDX, IDC_SEND_CHAT_TEXT, m_strSendChat); DDX_Control(pDX, IDC_PLAYER_LIST, m_listPlayers); //}}AFX_DATA_MAP } LRESULT CPagePlayers::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { LRESULT lr; if (m_AutoSizer.ProcessMessage(message, wParam, lParam, &lr)) return lr; // Perform default processing return CPropertyPage::WindowProc(message, wParam, lParam); } ///////////////////////////////////////////////////////////////////////////// // Implementation void CPagePlayers::LoadFromRegistry() { // Open/create the registry key CRegKey key; key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI); // PlayerListColumnOrder CComBSTR bstrColumnOrder; LoadRegString(key, TEXT("PlayerListColumnOrder"), bstrColumnOrder); m_spStrings->RemoveAll(); m_spStrings->AddDelimited(CComBSTR(L","), bstrColumnOrder); long cOrderedColumns = 0; m_spStrings->get_Count(&cOrderedColumns); if (c_cColumns == cOrderedColumns) { int vecOrder[c_cColumns]; for (CComVariant i(0L); V_I4(&i) < c_cColumns; ++V_I4(&i)) { bstrColumnOrder.Empty(); m_spStrings->get_Item(&i, &bstrColumnOrder); vecOrder[V_I4(&i)] = _wtoi(bstrColumnOrder); } m_listPlayers.SetColumnOrderArray(c_cColumns, vecOrder); } // PlayerListColumnWidths CComBSTR bstrColumnWidths; LoadRegString(key, TEXT("PlayerListColumnWidths"), bstrColumnWidths); m_spStrings->RemoveAll(); m_spStrings->AddDelimited(CComBSTR(L","), bstrColumnWidths); long cWidthColumns = 0; m_spStrings->get_Count(&cWidthColumns); if (c_cColumns == cWidthColumns) { for (CComVariant i(0L); V_I4(&i) < c_cColumns; ++V_I4(&i)) { bstrColumnWidths.Empty(); m_spStrings->get_Item(&i, &bstrColumnWidths); m_listPlayers.SetColumnWidth(V_I4(&i), _wtoi(bstrColumnWidths)); } } else { for (int i = 0; i < c_cColumns; ++i) { TCHAR szColumn[_MAX_PATH]; LVCOLUMN lvc = {LVCF_TEXT, 0, 0, szColumn, sizeofArray(szColumn)}; m_listPlayers.GetColumn(i, &lvc); int cx = m_listPlayers.GetStringWidth(CString(szColumn) + TEXT(" ")); m_listPlayers.SetColumnWidth(i, cx); } } // SendChatMRU m_comboSendChat.ResetContent(); CRegKey keyMRU; if (ERROR_SUCCESS == keyMRU.Create(key, TEXT("SendChatMRU"))) { // Read the count of strings DWORD cStrings = 0; keyMRU.QueryValue(cStrings, TEXT(".Count")); // Read each string and add it to the combo box for (DWORD i = 0; i < cStrings; ++i) { TCHAR szInt[16]; CString strMRUItem; LoadRegString(keyMRU, _itot(i, szInt, 10), strMRUItem); strMRUItem.TrimLeft(); strMRUItem.TrimRight(); if (!strMRUItem.IsEmpty()) m_comboSendChat.InsertString(i, strMRUItem); } } } void CPagePlayers::SavePlayerListColumnOrderToRegistry() { // Open/create the registry key CRegKey key; key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI); // Get the current column ordering int vecOrder[c_cColumns]; for (int iCol = 0; iCol < c_cColumns; ++iCol) vecOrder[iCol] = iCol; m_listPlayers.GetColumnOrderArray(vecOrder, c_cColumns); // Format a comma-delimited string of the column ordering CString strColumnOrder; for (int i = 0; i < c_cColumns; ++i) { if (i) strColumnOrder += ","; TCHAR szNum[16]; strColumnOrder += _itot(vecOrder[i], szNum, 10); } // Save to the registry key.SetValue(strColumnOrder, TEXT("PlayerListColumnOrder")); } void CPagePlayers::SavePlayerListColumnWidthsToRegistry() { // Open/create the registry key CRegKey key; key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI); // Format a comma-delimited string of the column widths CString strColumnWidths; for (int i = 0; i < c_cColumns; ++i) { if (i) strColumnWidths += ","; TCHAR szNum[16]; strColumnWidths += _itot(m_listPlayers.GetColumnWidth(i), szNum, 10); } // Save to the registry key.SetValue(strColumnWidths, TEXT("PlayerListColumnWidths")); } void CPagePlayers::SaveSendChatMRUToRegistry() { // Open/create the registry key CRegKey key; if (ERROR_SUCCESS != key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI)) return; // SendChatMRU CRegKey keyMRU; if (ERROR_SUCCESS != keyMRU.Create(key, TEXT("SendChatMRU"))) return; // Write the count of strings int cStrings = min(m_comboSendChat.GetCount(), c_cMaxChatsInRegistry); keyMRU.SetValue(cStrings, TEXT(".Count")); // Write each string for (int i = 0; i < cStrings; ++i) { TCHAR szInt[16]; CString strMRUItem; m_comboSendChat.GetLBText(i, strMRUItem); keyMRU.SetValue(strMRUItem, _itot(i, szInt, 10)); } } void CPagePlayers::UpdateUI(bool bUpdateData) { // Update data members from fields, if specified if (bUpdateData) UpdateData(); // Determine if a game is in progress or not bool bGameInProgress = NULL != GetSheet()->GetGame(); // Get the number of players that are selected UINT cSelectedItems = m_listPlayers.GetSelectedCount(); // Enable/disable the controls as needed m_staticSendChat.EnableWindow(bGameInProgress && cSelectedItems); m_comboSendChat.EnableWindow(bGameInProgress && cSelectedItems); m_btnBootPlayers.EnableWindow(bGameInProgress && cSelectedItems); } void CPagePlayers::SendChat() { CWaitCursor wait; // Update data members from fields UpdateData(); // Get the number of players that are selected UINT cSelectedItems = m_listPlayers.GetSelectedCount(); if (!cSelectedItems) return; // Send the chat message to the selected users m_strSendChat.TrimLeft(); m_strSendChat.TrimRight(); if (!m_strSendChat.IsEmpty()) { // Look for the text in the MRU list int iFound = m_comboSendChat.FindStringExact(-1, m_strSendChat); if (iFound >= 0) m_comboSendChat.DeleteString(iFound); // Insert the string at the top of the combo box list m_comboSendChat.InsertString(0, m_strSendChat); // Limit the number of chats in the MRU combo int cStrings; do { cStrings = m_comboSendChat.GetCount(); if (cStrings > c_cMaxChatsInRegistry) { m_comboSendChat.DeleteString(cStrings - 1); } } while (cStrings > c_cMaxChatsInRegistry); // Send to the whole game, if all players are selected CComBSTR bstrSendChat(m_strSendChat); if (m_listPlayers.GetItemCount() == static_cast(cSelectedItems)) { GetSheet()->GetGame()->SendChat(bstrSendChat, -1); } else { // Loop through each selected user POSITION it = m_listPlayers.GetFirstSelectedItemPosition(); while (it) { // Get the next item int iIndex = m_listPlayers.GetNextSelectedItem(it); _ASSERTE(-1 != iIndex); DWORD dwItemData = m_listPlayers.GetItemData(iIndex); // Interpret the item's lParam IAdminShip* pShip = reinterpret_cast(dwItemData); _ASSERTE(pShip); // Send the chat to the ship pShip->SendChat(bstrSendChat, -1); } } // Clear the string m_strSendChat.Empty(); UpdateData(false); // Update the MRU list SaveSendChatMRUToRegistry(); } } void CPagePlayers::PopulatePlayersList() { CWaitCursor wait; LPCSTR pszContext = "retrieving collection of players in game"; // Clear the contents of the list m_listPlayers.DeleteAllItems(); // Do nothing else if there is no game in progress if (NULL == GetSheet()->GetGame()) return; // Get the collection of users in the game IAdminUsersPtr spUsers; HRESULT hr = GetSheet()->GetGame()->get_Users(&spUsers); if (FAILED(hr)) { GetSheet()->HandleError(hr, pszContext, true); return; } // Get the enumerator object from the collection IUnknownPtr spEnumUnk; if (FAILED(hr = spUsers->get__NewEnum(&spEnumUnk))) { GetSheet()->HandleError(hr, pszContext, true); return; } IEnumVARIANTPtr spEnum(spEnumUnk); if (NULL == spEnum) { GetSheet()->HandleError(E_NOINTERFACE, pszContext, true); return; } // Iterate through each player from the enumerator int iIndex = 0; CComVariant players[32]; do { // Fetch the next block of players from the enumerator ULONG cFetched; if (FAILED(hr = spEnum->Next(sizeofArray(players), players, &cFetched))) { GetSheet()->HandleError(hr, pszContext, true); return; } // Add each player to the list for (ULONG i = 0; i < cFetched; ++i) { // Convert the VARIANT to IDispatch, if not already VARTYPE vt = V_VT(&players[i]); if (VT_DISPATCH != vt && VT_UNKNOWN != vt) { GetSheet()->HandleError(DISP_E_TYPEMISMATCH, pszContext, true); return; } // Ensure that the IDispatch supports IAdminUser IAdminUserPtr spUser(V_DISPATCH(&players[i])); if (NULL == spUser) { GetSheet()->HandleError(E_NOINTERFACE, pszContext, true); return; } // Clear the VARIANT in the array players[i].Clear(); // Get the ship object of the user IAdminShipPtr spShip; if (FAILED(hr = spUser->get_Ship(&spShip))) { GetSheet()->HandleError(hr, pszContext, true); return; } // Get the interesting properties of the User CComBSTR bstrName, bstrTeam, bstrSector; // Model Name spShip->get_Name(&bstrName); // Team IAGCTeamPtr spTeam; spShip->get_Team(&spTeam); if (NULL != spTeam) spTeam->get_Name(&bstrTeam); // Sector IAGCSectorPtr spSector; spShip->get_Sector(&spSector); if (NULL != spSector) spSector->get_Name(&bstrSector); // Add the ship to the list USES_CONVERSION; m_listPlayers.InsertItem(iIndex, OLE2CT(bstrName)); m_listPlayers.SetItemText(iIndex, c_iColumnTeam, OLE2CT(bstrTeam)); m_listPlayers.SetItemText(iIndex, c_iColumnSector, OLE2CT(bstrSector)); m_listPlayers.SetItemData(iIndex, reinterpret_cast(spShip.Detach())); ++iIndex; } } while (S_FALSE != hr); } void CPagePlayers::AddPlayer(IAGCEvent* pEvent) { CWaitCursor wait; LPCSTR pszContext = "adding new player to the list"; HRESULT hr; // Get the interesting properties of the event CComBSTR bstrName; pEvent->get_SubjectName(&bstrName); long idPlayer = -1; pEvent->get_SubjectID(&idPlayer); // Name must not be empty _ASSERTE(bstrName.Length()); // Name must not already be in list USES_CONVERSION; LV_FINDINFO lvfi = {LVFI_STRING, OLE2CT(bstrName)}; int iIndex = m_listPlayers.FindItem(&lvfi); _ASSERTE(-1 == iIndex); // Get the IAdminUser for the specified user IAdminUserPtr spUser; // if (FAILED(hr = GetSheet()->GetServer()->get_LookupUser( // static_cast(idPlayer), &spUser))) if (FAILED(hr = GetSheet()->GetServer()->get_FindUser(bstrName, &spUser))) { GetSheet()->HandleError(hr, pszContext, true); return; } // Get the ship object of the user IAdminShipPtr spShip; if (FAILED(hr = spUser->get_Ship(&spShip))) { GetSheet()->HandleError(hr, pszContext, true); return; } // Add the user to the list iIndex = m_listPlayers.GetItemCount(); m_listPlayers.InsertItem(iIndex, OLE2CT(bstrName)); m_listPlayers.SetItemText(iIndex, c_iColumnTeam, TEXT("")); m_listPlayers.SetItemText(iIndex, c_iColumnSector, TEXT("")); m_listPlayers.SetItemData(iIndex, reinterpret_cast(spShip.Detach())); } void CPagePlayers::RemovePlayer(IAGCEvent* pEvent) { // Get the interesting properties of the event CComBSTR bstrName; pEvent->get_SubjectName(&bstrName); // Name must not be empty _ASSERTE(bstrName.Length()); // Name must already be in list USES_CONVERSION; LV_FINDINFO lvfi = {LVFI_STRING, OLE2CT(bstrName)}; int iIndex = m_listPlayers.FindItem(&lvfi); _ASSERTE(-1 != iIndex); // Remove the item from the list m_listPlayers.DeleteItem(iIndex); } void CPagePlayers::SectorOrTeamChange(IAGCEvent* pEvent, int iColumn, LPCOLESTR pszProperty) { CWaitCursor wait; // Get the interesting properties of the event CComBSTR bstrName, bstrProperty; pEvent->get_SubjectName(&bstrName); CComVariant varNewPropertyName; pEvent->get_Property(&CComVariant(pszProperty), &varNewPropertyName); varNewPropertyName.ChangeType(VT_BSTR); bstrProperty = V_BSTR(&varNewPropertyName); // Name must not be empty _ASSERTE(bstrName.Length()); // Find the list item with the specified name USES_CONVERSION; LV_FINDINFO lvfi = {LVFI_STRING, OLE2CT(bstrName)}; int iIndex = m_listPlayers.FindItem(&lvfi); _ASSERTE(iIndex >= 0); // Change the sub-item of the list item m_listPlayers.SetItemText(iIndex, iColumn, bstrProperty.Length() ? OLE2CT(bstrProperty) : TEXT("")); } void CPagePlayers::TeamInfoChange(IAGCEvent* pEvent) { CWaitCursor wait; // Get the interesting properties of the event CComBSTR bstrTeam, bstrTeamNew; pEvent->get_SubjectName(&bstrTeam); CComVariant varTeamNew; pEvent->get_Property(&CComVariant(L"NewTeamName"), &varTeamNew); varTeamNew.ChangeType(VT_BSTR); CString strTeam(bstrTeam), strTeamNew(V_BSTR(&varTeamNew)); // Name must not be empty _ASSERTE(!strTeam.IsEmpty()); // Loop through each item in the list int cPlayers = m_listPlayers.GetItemCount(); for (int i = 0; i < cPlayers; ++i) { // Get the list item's team name CString str(m_listPlayers.GetItemText(i, c_iColumnTeam)); // Change the team name of this item, if it has the old team name if (str == strTeam) m_listPlayers.SetItemText(i, c_iColumnTeam, strTeamNew); } } ///////////////////////////////////////////////////////////////////////////// // Message Handlers BOOL CPagePlayers::OnInitDialog() { // Register for events of interest GetSheet()->GetSession()->ActivateEvents(EventID_GameCreated, -1); GetSheet()->GetSession()->ActivateEvents(EventID_GameDestroyed, -1); GetSheet()->GetSession()->ActivateEvents(EventID_LoginGame, -1); GetSheet()->GetSession()->ActivateEvents(EventID_LogoutGame, -1); GetSheet()->GetSession()->ActivateEvents(EventID_ShipChangesSectors, -1); GetSheet()->GetSession()->ActivateEvents(EventID_LeaveTeam, -1); GetSheet()->GetSession()->ActivateEvents(EventID_JoinTeam, -1); GetSheet()->GetSession()->ActivateEvents(EventID_TeamInfoChange, -1); // Perform default processing CPropertyPage::OnInitDialog(); // Initialize the AutoSize object m_AutoSizer.SetWindowAndRules(*this, _AutoSizerMap); // Set the list view control extended styles DWORD dwExStyle = LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP; m_listPlayers.SetExtendedStyle(dwExStyle); // Add columns to the list view control m_listPlayers.InsertColumn(c_iColumnName , CString((LPCSTR)IDS_COLUMN_PLAYER)); m_listPlayers.InsertColumn(c_iColumnTeam , CString((LPCSTR)IDS_COLUMN_TEAM )); m_listPlayers.InsertColumn(c_iColumnSector, CString((LPCSTR)IDS_COLUMN_SECTOR)); // Load previous values from registry LoadFromRegistry(); // Update fields from data members UpdateData(false); // Update the UI UpdateUI(); // Populate the list of players PopulatePlayersList(); // Set the focus to the first tabstop control return true; } void CPagePlayers::OnEndDragPlayerList(NMHDR* pNMHDR, LRESULT* pResult) { HD_NOTIFY* phdn = (HD_NOTIFY*)pNMHDR; if (pNMHDR->hwndFrom != m_listPlayers.GetHeaderCtrl()->GetSafeHwnd()) return; // Defer saving the new column ordering for a few seconds KillTimer(c_idTimerReorder); SetTimer(c_idTimerReorder, c_dwDelayReorder, NULL); *pResult = 0; } void CPagePlayers::OnEndTrackPlayerList(NMHDR* pNMHDR, LRESULT* pResult) { HD_NOTIFY* phdn = (HD_NOTIFY*)pNMHDR; if (pNMHDR->hwndFrom != m_listPlayers.GetHeaderCtrl()->GetSafeHwnd()) return; // Defer saving the new column widths until controls have updated KillTimer(c_idTimerResize); SetTimer(c_idTimerResize, c_dwDelayResize, NULL); *pResult = 0; } void CPagePlayers::OnTimer(UINT nIDEvent) { switch (nIDEvent) { case c_idTimerReorder: KillTimer(nIDEvent); SavePlayerListColumnOrderToRegistry(); return; case c_idTimerResize: KillTimer(nIDEvent); SavePlayerListColumnWidthsToRegistry(); return; } // Perform default processing CPropertyPage::OnTimer(nIDEvent); } void CPagePlayers::OnItemChangedPlayerList(NMHDR* pNMHDR, LRESULT* pResult) { // Interpret the message parameters NM_LISTVIEW* pNMLV = reinterpret_cast(pNMHDR); // Update the UI if an item selection has changed if (pNMLV->uChanged & LVIF_STATE) UpdateUI(); // Obligatory result code *pResult = 0; } void CPagePlayers::OnDeleteItemPlayerList(NMHDR* pNMHDR, LRESULT* pResult) { // Interpret the message parameters NM_LISTVIEW* pNMLV = reinterpret_cast(pNMHDR); // Interpret the item's lParam IAdminShip* pShip = reinterpret_cast(pNMLV->lParam); _ASSERTE(pShip); // Release the interface pShip->Release(); // Obligatory result code *pResult = 0; } void CPagePlayers::OnBootPlayers() { HRESULT hr; LPCSTR pszContext = "booting player from the game"; // Get the count of selected players int cSelected = m_listPlayers.GetSelectedCount(); _ASSERTE(cSelected); // Display a confirmation dialog CString strText; if (1 == cSelected) strText.LoadString(IDS_BOOT_SELECTED_ONE); else strText.Format(IDS_BOOT_SELECTED, cSelected); // Display the message box UINT nFlags = MB_ICONQUESTION | MB_YESNO; int nResponse = MessageBox(strText, NULL, nFlags); if (IDYES != nResponse) return; // Loop through each selected user POSITION it = m_listPlayers.GetFirstSelectedItemPosition(); while (it) { // Get the next item int iIndex = m_listPlayers.GetNextSelectedItem(it); _ASSERTE(-1 != iIndex); DWORD dwItemData = m_listPlayers.GetItemData(iIndex); // Interpret the item's lParam IAdminShip* pShip = reinterpret_cast(dwItemData); _ASSERTE(pShip); // Get the User property of the Ship IAdminUserPtr spUser; if (FAILED(hr = pShip->get_User(&spUser))) { GetSheet()->HandleError(hr, pszContext, false); return; } // Boot the player from the game if (FAILED(hr = spUser->Boot())) { GetSheet()->HandleError(hr, pszContext, false); return; } } // Give the focus to the list control m_listPlayers.SetFocus(); // Remove the "Default Button" style m_btnBootPlayers.SetButtonStyle( m_btnBootPlayers.GetButtonStyle() & ~BS_DEFPUSHBUTTON); }