#include "stdafx.h"
#include "AllSrvUI.h"
#include "AllSrvUISheet.h"
#include "DlgChatPreferences.h"
#include "PageChat.h"
#include "AdminPageThreadWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CPageChat, CPropertyPage)
BEGIN_AUTO_SIZER_MAP(_AutoSizerMap)
AUTO_SIZER_ENTRY(IDC_CHAT_LIST_CLEAR , LeftRight, 0, Right, NoRefresh)
AUTO_SIZER_ENTRY(IDC_CHAT_LIST_CLEAR , TopBottom, 0, Bottom, NoRefresh)
AUTO_SIZER_ENTRY(IDC_CHAT_PREFERENCES , 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_SEND_CHAT_ALL_GAMES, LeftRight, 0, Right, NoRefresh)
AUTO_SIZER_ENTRY(IDC_SEND_CHAT_ALL_GAMES, TopBottom, 0, Bottom, NoRefresh)
AUTO_SIZER_ENTRY(IDC_CHAT_LIST , Right, 0, Right, NoRefresh)
AUTO_SIZER_ENTRY(IDC_CHAT_LIST , Bottom, 0, Bottom, NoRefresh)
END_AUTO_SIZER_MAP()
BEGIN_MESSAGE_MAP(CPageChat, CPropertyPage)
ON_NOTIFY(HDN_ENDDRAG, 0, OnEndDragChatList)
ON_NOTIFY(HDN_ENDTRACK, 0, OnEndTrackChatList)
ON_BN_CLICKED(IDC_CHAT_PREFERENCES, OnChatPreferences)
ON_BN_CLICKED(IDC_CHAT_LIST_CLEAR, OnChatListClear)
ON_WM_DESTROY()
ON_WM_TIMER()
ON_BN_CLICKED(IDC_SEND_CHAT_ALL_GAMES, OnSendChatAllGames)
END_MESSAGE_MAP()
CPageChat::CPageChat() :
CPropertyPage(CPageChat::IDD),
m_Prefs(this),
m_bAdminPageActivated(false),
m_bChatActivated(false),
m_pthAdminPageMsg(NULL),
m_pthAdminPageRun(NULL),
m_pWndAdminPageMsgThread(NULL),
m_pWndAdminPageRunThread(NULL)
{
m_strSendChat = _T("");
m_bSendChatAllGames = FALSE;
HRESULT hr = m_spStrings.CreateInstance("TCObj.Strings");
if (FAILED(hr))
GetSheet()->HandleError(hr, "creating TCObj.Strings helper object", true);
}
void CPageChat::OnEvent(IAGCEvent* pEvent)
{
AGCEventID eEvent;
if (FAILED(pEvent->get_ID(&eEvent)))
return;
switch (eEvent)
{
case EventID_GameCreated:
case EventID_GameDestroyed:
{
UpdateUI();
break;
}
case EventID_ChatMessage:
case EventID_AdminPage:
{
bool bAdminAlert = EventID_AdminPage == eEvent;
CComVariant varGameID;
if (FAILED(pEvent->get_Property(&CComVariant(L"GameID"), &varGameID)))
return;
if (VT_BSTR != V_VT(&varGameID) || 0 != _wcsicmp(V_BSTR(&varGameID), L"TEST"))
{
varGameID.ChangeType(VT_I4);
if (!GetSheet()->GetGame())
return;
AGCGameID idGame = 0;
if (FAILED(GetSheet()->GetGame()->get_GameID(&idGame)))
return;
if (idGame != V_I4(&varGameID))
return;
}
if (!bAdminAlert || m_Prefs.m_bAdminChatList)
{
CComBSTR bstrSender, bstrTarget, bstrMessage;
if (FAILED(pEvent->get_SubjectName(&bstrSender)))
return;
CComVariant varTarget, varMessage;
if (FAILED(pEvent->get_Property(&CComVariant(L"Target"), &varTarget)))
return;
if (FAILED(pEvent->get_Property(&CComVariant(L"Message"), &varMessage)))
return;
varTarget.ChangeType(VT_BSTR);
bstrTarget = V_BSTR(&varTarget);
varMessage.ChangeType(VT_BSTR);
bstrMessage = V_BSTR(&varMessage);
int cItems = m_listChat.GetItemCount();
int nLastPlus = m_listChat.GetTopIndex() + m_listChat.GetCountPerPage();
bool bLastWasVisible = nLastPlus >= cItems;
USES_CONVERSION;
int iIndex = cItems;
m_listChat.InsertItem(iIndex, OLE2CT(bstrSender));
m_listChat.SetItemText(iIndex, c_iColumnTarget, OLE2CT(bstrTarget));
m_listChat.SetItemText(iIndex, c_iColumnMessage, OLE2CT(bstrMessage));
if (bLastWasVisible)
m_listChat.EnsureVisible(iIndex, false);
}
TrimExcessChats();
if (bAdminAlert)
{
if (m_Prefs.m_bAdminMessageBox)
m_pWndAdminPageMsgThread->PostAdminPageMsg(pEvent);
if (m_Prefs.m_bAdminRun)
m_pWndAdminPageRunThread->PostAdminPageRun(pEvent);
}
break;
}
}
}
BOOL CPageChat::OnSetActive()
{
LoadFromRegistry();
UpdateUI();
return CPropertyPage::OnSetActive();
}
BOOL CPageChat::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYDOWN == pMsg->message)
{
if (VK_RETURN == pMsg->wParam)
{
if (&m_comboSendChat == GetFocus() ||
&m_comboSendChat == GetFocus()->GetParent())
{
SendChat();
return true;
}
}
}
return CPropertyPage::PreTranslateMessage(pMsg);
}
void CPageChat::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SEND_CHAT_ALL_GAMES, m_btnSendChatAllGames);
DDX_Control(pDX, IDC_CHAT_LIST, m_listChat);
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_Check(pDX, IDC_SEND_CHAT_ALL_GAMES, m_bSendChatAllGames);
}
LRESULT CPageChat::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lr;
if (m_AutoSizer.ProcessMessage(message, wParam, lParam, &lr))
return lr;
return CPropertyPage::WindowProc(message, wParam, lParam);
}
void CPageChat::LoadFromRegistry()
{
m_Prefs.LoadFromRegistry();
CRegKey key;
key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
CComBSTR bstrColumnOrder;
LoadRegString(key, TEXT("ChatListColumnOrder"), 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_listChat.SetColumnOrderArray(c_cColumns, vecOrder);
}
CComBSTR bstrColumnWidths;
LoadRegString(key, TEXT("ChatListColumnWidths"), 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_listChat.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_listChat.GetColumn(i, &lvc);
int cx = m_listChat.GetStringWidth(CString(szColumn) + TEXT(" "));
m_listChat.SetColumnWidth(i, cx);
}
}
m_comboSendChat.ResetContent();
CRegKey keyMRU;
if (ERROR_SUCCESS == keyMRU.Create(key, TEXT("SendChatMRU")))
{
DWORD cStrings = 0;
keyMRU.QueryValue(cStrings, TEXT(".Count"));
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);
}
}
DWORD dwSendChatAllGames = 0;
key.QueryValue(dwSendChatAllGames, TEXT("SendChatAllGames"));
m_bSendChatAllGames = !!dwSendChatAllGames;
}
void CPageChat::SaveChatListColumnOrderToRegistry()
{
CRegKey key;
key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
int vecOrder[c_cColumns];
for (int iCol = 0; iCol < c_cColumns; ++iCol)
vecOrder[iCol] = iCol;
m_listChat.GetColumnOrderArray(vecOrder, c_cColumns);
CString strColumnOrder;
for (int i = 0; i < c_cColumns; ++i)
{
if (i)
strColumnOrder += ",";
TCHAR szNum[16];
strColumnOrder += _itot(vecOrder[i], szNum, 10);
}
key.SetValue(strColumnOrder, TEXT("ChatListColumnOrder"));
}
void CPageChat::SaveChatListColumnWidthsToRegistry()
{
CRegKey key;
key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
CHeaderCtrl* pHeader = m_listChat.GetHeaderCtrl();
CString strColumnWidths;
for (int i = 0; i < c_cColumns; ++i)
{
HDITEM hdi = {HDI_WIDTH};
pHeader->GetItem(i, &hdi);
if (i)
strColumnWidths += ",";
TCHAR szNum[16];
strColumnWidths += _itot(hdi.cxy, szNum, 10);
}
key.SetValue(strColumnWidths, TEXT("ChatListColumnWidths"));
}
void CPageChat::SaveSendChatMRUToRegistry()
{
CRegKey key;
if (ERROR_SUCCESS != key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI))
return;
CRegKey keyMRU;
if (ERROR_SUCCESS != keyMRU.Create(key, TEXT("SendChatMRU")))
return;
int cStrings = min(m_comboSendChat.GetCount(), c_cMaxChatsInRegistry);
keyMRU.SetValue(cStrings, TEXT(".Count"));
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 CPageChat::SaveSendChatAllGames()
{
CRegKey key;
if (ERROR_SUCCESS != key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI))
return;
DWORD dwSendChatAllGames = m_bSendChatAllGames;
key.SetValue(dwSendChatAllGames, TEXT("SendChatAllGames"));
}
void CPageChat::TrimExcessChats()
{
if (m_Prefs.m_dwChatListLimit)
{
int cExcess = m_listChat.GetItemCount() - m_Prefs.m_dwChatListLimit;
if (cExcess > 0)
{
m_listChat.SetRedraw(false);
while (cExcess--)
m_listChat.DeleteItem(0);
m_listChat.SetRedraw(true);
m_listChat.Invalidate();
}
}
}
void CPageChat::UpdateActivateAdminPage()
{
bool bAdminPageMonitored = m_Prefs.IsAdminPageMonitored();
if (!m_bAdminPageActivated != !bAdminPageMonitored)
{
if (bAdminPageMonitored)
GetSheet()->GetSession()->ActivateEvents(EventID_AdminPage, -1);
else
GetSheet()->GetSession()->DeactivateEvents(EventID_AdminPage, -1);
m_bAdminPageActivated = bAdminPageMonitored;
}
}
void CPageChat::UpdateActivateChatMessage()
{
bool bChatMonitored = m_Prefs.IsChatMonitored();
if (!m_bChatActivated != !bChatMonitored)
{
if (bChatMonitored)
GetSheet()->GetSession()->ActivateEvents(EventID_ChatMessage, -1);
else
GetSheet()->GetSession()->DeactivateEvents(EventID_ChatMessage, -1);
m_bChatActivated = bChatMonitored;
}
}
void CPageChat::UpdateUI(bool bUpdateData)
{
if (bUpdateData)
UpdateData();
bool bGameInProgress = NULL != GetSheet()->GetGame();
m_staticSendChat.EnableWindow(bGameInProgress);
m_comboSendChat.EnableWindow(bGameInProgress);
}
void CPageChat::SendChat()
{
UpdateData();
m_strSendChat.TrimLeft();
m_strSendChat.TrimRight();
if (!m_strSendChat.IsEmpty())
{
int iFound = m_comboSendChat.FindStringExact(-1, m_strSendChat);
if (iFound >= 0)
m_comboSendChat.DeleteString(iFound);
m_comboSendChat.InsertString(0, m_strSendChat);
int cStrings;
do
{
cStrings = m_comboSendChat.GetCount();
if (cStrings > c_cMaxChatsInRegistry)
{
m_comboSendChat.DeleteString(cStrings - 1);
}
} while (cStrings > c_cMaxChatsInRegistry);
CComBSTR bstrText(m_strSendChat);
if (m_bSendChatAllGames && GetSheet()->IsServerInMultiMode())
GetSheet()->GetServer()->SendMsg(bstrText);
else
GetSheet()->GetGame()->SendChat(bstrText, -1);
m_strSendChat.Empty();
UpdateData(false);
SaveSendChatMRUToRegistry();
}
}
UINT CPageChat::AdminPageMsgThreadThunk(void* pvParam)
{
CoInitialize(NULL);
CPageChat* pThis = reinterpret_cast<CPageChat*>(pvParam);
pThis->AdminPageMsgThreadProc();
CoUninitialize();
return 0;
}
UINT CPageChat::AdminPageRunThreadThunk(void* pvParam)
{
CoInitialize(NULL);
CPageChat* pThis = reinterpret_cast<CPageChat*>(pvParam);
pThis->AdminPageRunThreadProc();
CoUninitialize();
return 0;
}
void CPageChat::AdminPageMsgThreadProc()
{
HWND hwnd = GetSafeHwnd();
CAdminPageThreadWnd wnd;
wnd.Create();
m_pWndAdminPageMsgThread = &wnd;
m_evtAdminPageMsgThreadStartup.SetEvent();
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
m_pWndAdminPageMsgThread = NULL;
}
void CPageChat::AdminPageRunThreadProc()
{
HWND hwnd = GetSafeHwnd();
CAdminPageThreadWnd wnd;
wnd.Create(m_Prefs.m_strShortcutPath);
m_pWndAdminPageRunThread = &wnd;
m_evtAdminPageRunThreadStartup.SetEvent();
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
m_pWndAdminPageRunThread = NULL;
}
BOOL CPageChat::OnInitDialog()
{
GetSheet()->GetSession()->ActivateEvents(EventID_GameDestroyed, -1);
CPropertyPage::OnInitDialog();
m_AutoSizer.SetWindowAndRules(*this, _AutoSizerMap);
bool bMultiMode = GetSheet()->IsServerInMultiMode();
m_btnSendChatAllGames.ShowWindow(bMultiMode ? SW_SHOW : SW_HIDE);
m_btnSendChatAllGames.EnableWindow(bMultiMode);
m_pthAdminPageMsg = AfxBeginThread(AdminPageMsgThreadThunk, this,
THREAD_PRIORITY_NORMAL, 4096);
m_pthAdminPageRun = AfxBeginThread(AdminPageRunThreadThunk, this,
THREAD_PRIORITY_NORMAL, 4096);
_ASSERTE(m_pthAdminPageMsg);
_ASSERTE(m_pthAdminPageRun);
HANDLE phEvents[] =
{
m_evtAdminPageMsgThreadStartup,
m_evtAdminPageRunThreadStartup,
};
const DWORD c_cEvents = sizeofArray(phEvents);
WaitForMultipleObjects(c_cEvents, phEvents, true, INFINITE);
DWORD dwExStyle = LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP;
m_listChat.SetExtendedStyle(dwExStyle);
m_listChat.InsertColumn(0, CString((LPCSTR)IDS_COLUMN_SENDER ));
m_listChat.InsertColumn(1, CString((LPCSTR)IDS_COLUMN_TARGET ));
m_listChat.InsertColumn(2, CString((LPCSTR)IDS_COLUMN_MESSAGE));
LoadFromRegistry();
UpdateActivateAdminPage();
UpdateActivateChatMessage();
UpdateData(false);
UpdateUI();
m_comboSendChat.SetFocus();
return false;
}
void CPageChat::OnEndDragChatList(NMHDR* pNMHDR, LRESULT* pResult)
{
HD_NOTIFY* phdn = (HD_NOTIFY*)pNMHDR;
if (pNMHDR->hwndFrom != m_listChat.GetHeaderCtrl()->GetSafeHwnd())
return;
KillTimer(c_idTimerReorder);
SetTimer(c_idTimerReorder, c_dwDelayReorder, NULL);
*pResult = 0;
}
void CPageChat::OnEndTrackChatList(NMHDR* pNMHDR, LRESULT* pResult)
{
HD_NOTIFY* phdn = (HD_NOTIFY*)pNMHDR;
if (pNMHDR->hwndFrom != m_listChat.GetHeaderCtrl()->GetSafeHwnd())
return;
KillTimer(c_idTimerResize);
SetTimer(c_idTimerResize, c_dwDelayResize, NULL);
*pResult = 0;
}
void CPageChat::OnChatPreferences()
{
int nResponse = m_Prefs.DoModal();
if (IDCANCEL == nResponse)
return;
TrimExcessChats();
UpdateActivateAdminPage();
UpdateActivateChatMessage();
}
void CPageChat::OnChatListClear()
{
m_listChat.SetRedraw(false);
m_listChat.DeleteAllItems();
m_listChat.SetRedraw(true);
m_listChat.Invalidate();
}
void CPageChat::OnDestroy()
{
HANDLE phObjects[] =
{
m_pthAdminPageMsg->m_hThread,
m_pthAdminPageRun->m_hThread,
};
const DWORD c_cObjects = sizeofArray(phObjects);
m_pthAdminPageMsg->PostThreadMessage(WM_QUIT, 0, 0);
m_pthAdminPageRun->PostThreadMessage(WM_QUIT, 0, 0);
const DWORD c_dwTimeout = 5000;
WaitForMultipleObjects(c_cObjects, phObjects, true, c_dwTimeout);
CPropertyPage::OnDestroy();
}
void CPageChat::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case c_idTimerReorder:
KillTimer(nIDEvent);
SaveChatListColumnOrderToRegistry();
return;
case c_idTimerResize:
KillTimer(nIDEvent);
SaveChatListColumnWidthsToRegistry();
return;
}
CPropertyPage::OnTimer(nIDEvent);
}
void CPageChat::OnSendChatAllGames()
{
UpdateData();
SaveSendChatAllGames();
}