#include "stdafx.h"
#include "AllSrvUI.h"
#include "AllSrvUISheet.h"
#include "DlgAbout.h"
#include "DlgGameSelect.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BEGIN_MESSAGE_MAP(CAllSrvUISheet, CPropertySheet)
ON_WM_SYSCOMMAND()
ON_WM_SIZE()
ON_WM_MOVE()
ON_WM_TIMER()
ON_WM_DESTROY()
ON_WM_CLOSE()
END_MESSAGE_MAP()
CAllSrvUISheet::CAllSrvUISheet(CWnd* pParentWnd, UINT iSelectPage) :
CPropertySheet(AFX_IDS_APP_TITLE, pParentWnd, iSelectPage),
m_dwConnectionCookie(0),
m_bInitDone(false),
m_bMultiMode(false)
{
AddPage(&m_PageConnect);
}
CAllSrvUISheet::~CAllSrvUISheet()
{
if (m_dwConnectionCookie && NULL != m_spcp)
{
m_spcp->Unadvise(m_dwConnectionCookie);
m_dwConnectionCookie = 0;
}
}
BOOL CAllSrvUISheet::Create()
{
static const DWORD dwStyle = WS_VISIBLE | WS_SYSMENU | WS_CAPTION |
WS_THICKFRAME | WS_POPUP | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_MODALFRAME;
if (!CPropertySheet::Create(NULL, dwStyle))
return false;
m_nFlags &= WF_CONTINUEMODAL;
return true;
}
void CAllSrvUISheet::InitSysMenu()
{
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
}
void CAllSrvUISheet::InitIcon()
{
LPCTSTR pszRes = MAKEINTRESOURCE(IDR_MAINFRAME);
HICON hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), pszRes,
IMAGE_ICON, ::GetSystemMetrics(SM_CXICON),
::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
SetIcon(hIcon, true);
HICON hIconSmall = (HICON)::LoadImage(AfxGetResourceHandle(), pszRes,
IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON),
::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
SetIcon(hIconSmall, false);
}
void CAllSrvUISheet::AddChildrenToAutoSizer()
{
CTabCtrl* pwndTab = GetTabControl();
m_AutoSizer.AddRule(*pwndTab, AutoSizer_Follow_Right,
NULL, AutoSizer_Lead_Right, AutoSizer_Refresh_NoRefresh);
m_AutoSizer.AddRule(*pwndTab, AutoSizer_Follow_Bottom,
NULL, AutoSizer_Lead_Bottom, AutoSizer_Refresh_NoRefresh);
m_AutoSizer.AddRule(m_wndStatusBar, AutoSizer_Follow_Right,
NULL, AutoSizer_Lead_Right, AutoSizer_Refresh_NoRefresh);
m_AutoSizer.AddRule(m_wndStatusBar, AutoSizer_Follow_TopBottom,
NULL, AutoSizer_Lead_Bottom, AutoSizer_Refresh_NoRefresh);
CWnd* pwnd = GetWindow(GW_CHILD);
while (pwnd)
{
TCHAR szClass[_MAX_PATH];
GetClassName(*pwnd, szClass, sizeofArray(szClass));
if (0 == _tcsicmp(szClass, "button"))
{
m_AutoSizer.AddRule(*pwnd, AutoSizer_Follow_LeftRight,
NULL, AutoSizer_Lead_Right, AutoSizer_Refresh_NoRefresh);
m_AutoSizer.AddRule(*pwnd, AutoSizer_Follow_TopBottom,
NULL, AutoSizer_Lead_Bottom, AutoSizer_Refresh_NoRefresh);
}
pwnd = pwnd->GetWindow(GW_HWNDNEXT);
}
}
void CAllSrvUISheet::UpdateStatus()
{
if (!GetSession())
return;
UINT idStage = IDS_STAGE_NONE;
if (GetGame())
{
AGCGameStage stage = static_cast<AGCGameStage>(-1);
HRESULT hr = GetGame()->get_GameStage(&stage);
if (FAILED(hr))
{
if (RPC_E_CANTCALLOUT_ININPUTSYNCCALL != hr) DestroyWindow();
return;
}
switch (stage)
{
case AGCGameStage_NotStarted: idStage = IDS_STAGE_NOTSTARTED; break;
case AGCGameStage_Starting : idStage = IDS_STAGE_STARTING ; break;
case AGCGameStage_Started : idStage = IDS_STAGE_STARTED ; break;
case AGCGameStage_Over : idStage = IDS_STAGE_OVER ; break;
case AGCGameStage_Terminate : idStage = IDS_STAGE_TERMINATE ; break;
}
}
else
{
long nProcessID;
HRESULT hr = GetSession()->get_ProcessID(&nProcessID);
if (FAILED(hr))
{
if (RPC_E_CANTCALLOUT_ININPUTSYNCCALL != hr) DestroyWindow();
return;
}
}
CString strStage(MAKEINTRESOURCE(idStage));
m_wndStatusBar.SetText(strStage, 0, 0);
}
HRESULT CAllSrvUISheet::HandleError(HRESULT hr, LPCSTR pszContext, bool bExit)
{
IErrorInfoPtr spei;
::GetErrorInfo(0, &spei);
_com_error e(hr, spei, true);
_bstr_t bstrError(e.Description());
if (!bstrError.length())
bstrError = e.ErrorMessage();
const static TCHAR szFmt[] = TEXT("An error occurred while %hs:\n\n%ls");
int cch = sizeofArray(szFmt) + strlen(pszContext) + bstrError.length();
LPTSTR pszMsg = (LPTSTR)_alloca(cch * sizeof(TCHAR));
_stprintf(pszMsg, szFmt, pszContext, (BSTR)bstrError);
MessageBox(pszMsg, TEXT("Error: Allegiance Game Server"));
if (bExit)
DestroyWindow();
return hr;
}
bool CAllSrvUISheet::SelectGame()
{
CDlgGameSelect dlg(this);
if (IDCANCEL == dlg.DoModal())
return false;
if (dlg.GetSelectedGame() == m_spGame)
return false;
m_spGame = dlg.GetSelectedGame();
SetRedraw(false);
AddPage(&m_PageDummy);
RemovePage(&m_PagePlayers);
RemovePage(&m_PageChat);
RemovePage(&m_PageGameCreate);
AddPage(&m_PageGameCreate);
AddPage(&m_PageChat);
AddPage(&m_PagePlayers);
RemovePage(&m_PageDummy);
int iPageSelected = GetActiveIndex();
for (int iPage = 0; iPage < GetPageCount(); ++iPage)
SetActivePage(iPage);
SetActivePage(iPageSelected);
UpdateStatus();
SetRedraw();
Invalidate();
UpdateWindow();
return true;
}
HRESULT CAllSrvUISheet::CreateGame(bool bLobby,
IAGCGameParameters* pGameParameters)
{
_ASSERTE(NULL != m_spServer);
_ASSERTE(NULL == m_spGame);
CComBSTR bstrLobby;
HRESULT hr = m_spServer->put_PublicLobby(bLobby);
if (FAILED(hr))
{
if (HRESULT_FROM_WIN32(ERROR_CRC) == hr)
return hr;
return HandleError(hr, "setting the LobbyServer property", false);
}
IAdminGamesPtr spGames;
hr = m_spServer->get_Games(&spGames);
if (FAILED(hr))
return HandleError(hr, "retrieving the AdminGames property", false);
hr = spGames->Add(pGameParameters);
if (FAILED(hr))
return HandleError(hr, "creating a new game", false);
hr = spGames->get_Item(&CComVariant(0L), &m_spGame);
UpdateStatus();
return hr;
}
HRESULT CAllSrvUISheet::DestroyGame()
{
_ASSERTE(NULL != m_spGame);
IAdminGamePtr spGame(m_spGame);
m_spGame = NULL;
HRESULT hr = spGame->Kill();
if (FAILED(hr))
HandleError(hr, "destroying game", false);
UpdateStatus();
return hr;
}
HRESULT CAllSrvUISheet::PostConnect(DWORD dwCookie)
{
IGlobalInterfaceTablePtr spGIT;
HRESULT hr = spGIT.CreateInstance(CLSID_StdGlobalInterfaceTable);
if (FAILED(hr))
return HandleError(hr, "creating Global Interface Table", true);
if (FAILED(hr = spGIT->GetInterfaceFromGlobal(dwCookie,
__uuidof(IAdminSession), (void**)&m_spSession)))
return HandleError(hr, "retrieving interface from GIT", true);
hr = spGIT->RevokeInterfaceFromGlobal(dwCookie);
SetTimer(c_StageTimer, c_StageTimeout, NULL);
if (FAILED(hr = m_spSession->get_Server(&m_spServer)))
return HandleError(hr, "retrieving AdminServer property", true);
IAdminGamesPtr spGames;
if (FAILED(hr = m_spServer->get_Games(&spGames)))
return HandleError(hr, "retrieving AdminGames property", true);
long cGames = 0;
if (FAILED(hr = spGames->get_Count(&cGames)))
return HandleError(hr, "retrieving the AdminGames.Count property", true);
m_bMultiMode = cGames > 1;
hr = spGames->get_Item(&CComVariant(0L), &m_spGame);
LPCSTR pszContext = "setting-up the connection point";
IConnectionPointContainerPtr spcpc(m_spSession);
if (NULL == spcpc)
return HandleError(E_NOINTERFACE, pszContext, true);
hr = spcpc->FindConnectionPoint(__uuidof(IAdminSessionEvents), &m_spcp);
if (SUCCEEDED(hr))
{
XEvents* pxEvents = new XEvents(this);
hr = m_spcp->Advise(pxEvents, &m_dwConnectionCookie);
pxEvents->Release(); }
if (FAILED(hr))
return HandleError(hr, pszContext, true);
m_spSession->ActivateEvents(EventID_GameDestroyed, -1);
SetRedraw(false);
AddPage(&m_PageGameCreate);
AddPage(&m_PageChat);
AddPage(&m_PagePlayers);
m_AutoSizer.RemoveRules(m_PageConnect);
RemovePage(&m_PageConnect);
int iPageSelected = GetActiveIndex();
for (int iPage = 0; iPage < GetPageCount(); ++iPage)
SetActivePage(iPage);
SetActivePage(iPageSelected);
UpdateStatus();
SetRedraw();
Invalidate();
UpdateWindow();
return S_OK;
}
void CAllSrvUISheet::OnEvent(IAGCEvent* pEvent)
{
AGCEventID eEvent;
if (FAILED(pEvent->get_ID(&eEvent)))
return;
switch (eEvent)
{
case EventID_GameDestroyed:
{
m_spGame = NULL;
UpdateStatus();
break;
}
}
}
void CAllSrvUISheet::PostNcDestroy()
{
delete this;
}
LRESULT CAllSrvUISheet::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lr;
if (m_AutoSizer.ProcessMessage(message, wParam, lParam, &lr))
return lr;
return CPropertySheet::WindowProc(message, wParam, lParam);
}
BOOL CAllSrvUISheet::OnInitDialog()
{
CPropertySheet::OnInitDialog();
InitSysMenu();
InitIcon();
DWORD dwStyle = WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP;
m_wndStatusBar.Create(dwStyle, CRect(0, 0, 0, 0), this, -1);
CRect rect, rectStatusBar;
GetWindowRect(rect);
m_wndStatusBar.GetWindowRect(rectStatusBar);
rect.bottom += rectStatusBar.Height() + 3;
MoveWindow(rect);
m_wndStatusBar.SendMessage(WM_SIZE);
m_AutoSizer.SetWindowAndRules(*this, NULL);
AddChildrenToAutoSizer();
CRegKey key;
if (SUCCEEDED(key.Open(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI, KEY_READ)))
{
WINDOWPLACEMENT wp;
DWORD dwType;
DWORD cbData = sizeof(wp);
if (ERROR_SUCCESS == ::RegQueryValueEx(key, TEXT("WindowPlacement"), NULL,
&dwType, reinterpret_cast<BYTE*>(&wp), &cbData))
{
if (REG_BINARY == dwType)
{
::SetWindowPlacement(*this, &wp);
}
}
}
m_bInitDone = true;
return true;
}
void CAllSrvUISheet::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CDlgAbout dlgAbout(this);
dlgAbout.DoModal();
return;
}
CPropertySheet::OnSysCommand(nID, lParam);
}
CAllSrvUISheet::XEvents::XEvents(CAllSrvUISheet* pThis) :
m_pThis(pThis),
m_nRefs(1)
{
}
CAllSrvUISheet::XEvents::~XEvents()
{
}
STDMETHODIMP CAllSrvUISheet::XEvents::QueryInterface(REFIID riid, void** ppUnk)
{
if (IID_IUnknown == riid || __uuidof(IAdminSessionEvents) == riid)
{
*ppUnk = this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CAllSrvUISheet::XEvents::AddRef(void)
{
return ++m_nRefs;
}
STDMETHODIMP_(ULONG) CAllSrvUISheet::XEvents::Release(void)
{
ULONG nRefs = --m_nRefs;
if (0 == nRefs)
delete this;
return nRefs;
}
STDMETHODIMP CAllSrvUISheet::XEvents::OnEvent(IAGCEvent* pEvent)
{
m_pThis->OnEvent(pEvent);
m_pThis->m_PageGameCreate.OnEvent(pEvent);
m_pThis->m_PageChat.OnEvent(pEvent);
m_pThis->m_PagePlayers.OnEvent(pEvent);
return S_OK;
}
void CAllSrvUISheet::OnSize(UINT nType, int cx, int cy)
{
CPropertySheet::OnSize(nType, cx, cy);
CPropertyPage* pPage = GetActivePage();
if (pPage)
SetActivePage(pPage);
if (m_bInitDone)
SetTimer(c_SizeTimer, c_SizeTimeout, NULL);
}
void CAllSrvUISheet::OnMove(int x, int y)
{
CPropertySheet::OnMove(x, y);
if (m_bInitDone)
SetTimer(c_SizeTimer, c_SizeTimeout, NULL);
}
void CAllSrvUISheet::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case c_SizeTimer:
{
WINDOWPLACEMENT wp = {sizeof(wp)};
::GetWindowPlacement(*this, &wp);
CRegKey key;
key.Create(HKEY_LOCAL_MACHINE, HKLM_AllSrvUI);
RegSetValueEx(key, TEXT("WindowPlacement"), 0, REG_BINARY,
reinterpret_cast<const BYTE*>(&wp), sizeof(wp));
KillTimer(nIDEvent);
break;
}
case c_StageTimer:
{
UpdateStatus();
break;
}
default:
{
CPropertySheet::OnTimer(nIDEvent);
}
}
}
void CAllSrvUISheet::OnDestroy()
{
for (int i = c_cTimersMin + 1; i < c_cTimersMax; ++i)
KillTimer(i);
CPropertySheet::OnDestroy();
}
void CAllSrvUISheet::OnClose()
{
if (!IsServerInMultiMode() && GetGame())
{
int nType = MB_ICONQUESTION | MB_YESNOCANCEL;
CString strText(MAKEINTRESOURCE(IDS_DESTROY_ON_EXIT));
switch (MessageBox(strText, NULL, nType))
{
case IDCANCEL:
return;
case IDYES:
this->DestroyGame();
break;
case IDNO:
break;
}
}
CPropertySheet::OnClose();
}