Restructure repository to include all source folders

Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,486 @@
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringToolDlg.h"
#include "ChatServerEventHandler.h"
#include "MonitoringToolSetup.h"
#include "MonitoringToolLog.h"
#include "WhisperDlg.h"
#include "ChattingPage.h"
#include "LoginDlg.h"
#include "GlobalFunc.h"
#include <Log/ServerLog.h>
#include <Stream/Buffer/Buffer.h>
#include <Utility/Setup/ServerSetup.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/ChatToolPacketCmd.h>
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
#include <mmsystem.h>
const char* szChatSection = _T("CHAT_SERVER_CONNECTION");
const unsigned int MAX_CHAT = CMonitoringToolSetup::GetInstance().GetInt(szChatSection, _T("CHAT_SERVER_NUM"));
ClientNet::CChatServerEventHandler::CChatServerEventHandler(unsigned int nServerGroup)
: m_nServerGroup(nServerGroup), m_dwLastPingRecvTime(0)
{
}
bool ClientNet::CChatServerEventHandler::Connect()
{
char szKey[MAX_PATH];
unsigned int nServerGroup;
const char* szIP;
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
for(unsigned int nIndex = 0; nIndex < MAX_CHAT; ++nIndex)
{
_snprintf(szKey, MAX_PATH, "CHAT_SERVER_IP_%02d", nIndex);
szIP = Setup.GetString(szChatSection, szKey);
_snprintf(szKey, MAX_PATH, "CHAT_SERVER_INDEX_%02d", nIndex);
nServerGroup = Setup.GetInt(szChatSection, szKey);
ClientNet::CClientEventHandlerMgr& eventHandlerMgr = theApp.GetEventHandlerMgr();
ClientNet::CChatServerEventHandler* lpEventHandler = new ClientNet::CChatServerEventHandler(nServerGroup);
if (!eventHandlerMgr.Connect(
INET_Addr(szIP, CServerSetup::ChatServerMonitoringToolListen), lpEventHandler))
{
delete lpEventHandler;
return false;
}
}
return true;
}
int ClientNet::CChatServerEventHandler::OnOpen(int iErrorCode)
{
if(0 == iErrorCode)
{
theApp.RegisterChatHandler(m_nServerGroup, this);
INET_Addr& addr = GetPeerAddress();
INFLOG3(g_Log, _T("Connect Session (ChatServer) : DP:0x%p, %s:%d"),
this, addr.get_addr_string(), addr.get_port_in());
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_031"));
}
else
{
ERRLOG1(g_Log, _T("Connect Session Failed (ChatServer): Err- %d"), iErrorCode);
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_032"));
}
m_dwLastPingRecvTime = timeGetTime();
return 0;
}
int ClientNet::CChatServerEventHandler::OnClose()
{
theApp.RemoveChatHandler(m_nServerGroup, this);
INFLOG1(g_Log, _T("Disconnect Session (ChatServer): DP:0x%p"), this);
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_033"));
return 0;
}
int ClientNet::CChatServerEventHandler::OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr)
{
bool bResult = false;
switch(lpPktBase->GetCmd())
{
case ChatToolCMD::Authorize: RecvAuthAck(lpPktBase, peerAddr); break;
case ChatToolCMD::ChatSend: RecvChatData(lpPktBase, peerAddr); break;
case ChatToolCMD::ChatPing: RecvChatPing(lpPktBase, peerAddr); break;
case ChatToolCMD::ChatRequest: RecvChatRequest(lpPktBase, peerAddr); break;
default: break;
}
return 0;
}
/// \brief 채팅서버로 인증 패킷 전송
/// \param szUserID 로그인 계정명
/// \param szPass 로그인 패스워드
/// \return 패킷 전송 처리 성공 여부
bool ClientNet::CChatServerEventHandler::SendAuthPkt(char* szUserID, char* szPass)
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[MAX_PATH];
for(unsigned int nIndex = 0; nIndex < MAX_CHAT; ++nIndex)
{
_snprintf(szKey, MAX_PATH, "CHAT_SERVER_INDEX_%02d", nIndex);
CChatServerEventHandler* lpHandler =
theApp.GetChatServerHandler(Setup.GetInt(szChatSection, szKey, 100));
if(0 != lpHandler)
{
CNetworkMsgBlock* lpMsg =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
sizeof(ChatToolPkt::Authorize), INET_Addr());
if(0 != lpMsg)
{
ChatToolPkt::Authorize* lpAuthorize =
reinterpret_cast<ChatToolPkt::Authorize*>(lpMsg->wr_ptr());
_snprintf(lpAuthorize->m_szUserID, ChatToolPkt::MAX_USER_ID, szUserID);
lpAuthorize->m_szUserID[ChatToolPkt::MAX_USER_ID - 1] = 0;
_snprintf(lpAuthorize->m_szPassword, ChatToolPkt::MAX_PASSWORD, szPass);
lpAuthorize->m_szPassword[ChatToolPkt::MAX_PASSWORD - 1] = 0;
if(lpMsg->WrapCrypt(sizeof(ChatToolPkt::Authorize), ChatToolCMD::Authorize, 0))
{
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
}
else
{
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
}
}
Sleep(1000);
}
else
{
ERRLOG1(g_Log, "Failed get session(ChatServer): Group- %d", Setup.GetInt(szChatSection, szKey, 100));
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_030"));
}
}
return true;
}
/// \brief 인증 패킷 Ack 처리
/// \return 패킷 전송 성공 여부
bool ClientNet::CChatServerEventHandler::RecvAuthAck(PktBase* lpPktBase, INET_Addr& peerAddr)
{
CLoginDlg* lpLoginDlg = static_cast<CLoginDlg*>(theApp.GetRegisteredWindow(IDD_LOGINDLG));
if(NULL != lpLoginDlg)
{
ChatToolPkt::Authorize* lpAuthorize = static_cast<ChatToolPkt::Authorize*>(lpPktBase);
if(1 == lpAuthorize->m_cResult)
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_034"));
theApp.SetAuthorized(true);
CString strLoginedName;
strLoginedName.Format("%s", lpAuthorize->m_szUserID);
theApp.SetLoginedName(strLoginedName);
lpLoginDlg->OnOK();
CChattingPage* lpChatPage =
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
if (NULL != lpChatPage)
{
lpChatPage->SetLoginedNameEdit(strLoginedName);
lpChatPage->CheckDlgButton(IDC_GMLOGINED_CHK, BST_CHECKED);
}
unsigned char szOption[ChatToolPkt::ChatOption::MAX_OPTION];
std::fill_n(szOption, int(ChatToolPkt::ChatOption::MAX_OPTION), 1);
SendChatOptPkt(m_nServerGroup, szOption, ChatToolPkt::ChatOption::MAX_OPTION);
}
else
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_035"));
}
}
return true;
}
/// \brief 채팅 메세지 보내기(외치기, 귓속말등)
/// \param nServerGroup 전송할 서버군
/// \param cChatType 전송할 메세지의 타입
/// \param cTargetType 메세지를 받을 대상 타입
/// \param dwTargetUID 메세지를 받을 대상의 UID
/// \param dwMessageID 메세지의 고유 ID (Ack를 받을때 활용)
/// \param strGMName 메세지를 보내는 GM의 로그인 계정명
/// \param strTargetName 메세지를 받을 대상의 계정명 또는 캐릭터명
/// \param strMsg 메세지 내용
/// \return 패킷 전송 처리 성공 여부
bool ClientNet::CChatServerEventHandler::SendChatReqPkt(unsigned int nServerGroup,
unsigned char cChatType,
unsigned char cTargetType,
unsigned long dwTargetUID,
unsigned long dwMessageID,
const CString& strGMName,
const CString& strTargetName,
const CString& strMsg)
{
if (!theApp.IsAuthorized())
{
return false;
}
CClientEventHandler* lpHandler = theApp.GetChatServerHandler(nServerGroup);
if (0 == lpHandler)
{
return false;
}
unsigned char cMsgLen = static_cast<unsigned char>(strMsg.GetLength());
CNetworkMsgBlock* lpMsg =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
sizeof(ChatToolPkt::ChatRequest) + cMsgLen + 1, INET_Addr());
if(0 != lpMsg)
{
ChatToolPkt::ChatRequest* lpChatReq =
reinterpret_cast<ChatToolPkt::ChatRequest*>(lpMsg->wr_ptr());
memset(lpChatReq, 0, sizeof(ChatToolPkt::ChatRequest));
lpChatReq->m_dwUID = dwTargetUID; // 대상 캐릭터 UID (TargetName이 없을 경우 사용)
lpChatReq->m_cTargetType = cTargetType; // UID / CharName / AccountName 중 하나
lpChatReq->m_dwMessageID = dwMessageID;
lpChatReq->m_cChatType = cChatType;
lpChatReq->m_cChatMsgLen = cMsgLen + 1; // +1 : 널 문자 사이즈
_snprintf(lpChatReq->m_szAdminName, ChatToolPkt::MAX_CHAR_NAME - 1, "%s", strGMName);
lpChatReq->m_szAdminName[ChatToolPkt::MAX_CHAR_NAME - 1] = 0;
_snprintf(lpChatReq->m_szTargetName, ChatToolPkt::MAX_CHAR_NAME - 1, "%s", strTargetName);
lpChatReq->m_szTargetName[ChatToolPkt::MAX_CHAR_NAME - 1] = 0;
memcpy(reinterpret_cast<char*>(lpChatReq + 1), strMsg, cMsgLen);
*(reinterpret_cast<char*>(lpChatReq + 1) + cMsgLen) = 0;
if (lpMsg->WrapCrypt(sizeof(ChatToolPkt::ChatRequest) + lpChatReq->m_cChatMsgLen,
ChatToolCMD::ChatRequest, 0))
{
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
return true;
}
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
}
return true;
}
/// \brief 채팅 관련 데이터 처리
/// \return 패킷 처리 성공 여부
bool ClientNet::CChatServerEventHandler::RecvChatData(PktBase* lpPktBase, INET_Addr& peerAddr)
{
ChatToolPkt::ChatDataSend* lpChatDataSend =
reinterpret_cast<ChatToolPkt::ChatDataSend*>(lpPktBase);
CChattingPage* lpPage =
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
CFilterUserDialog* lpFilter =
static_cast<CFilterUserDialog*>(theApp.GetRegisteredWindow(IDD_FILTERDIALOG));
CGMReportDialog* lpGMReport =
static_cast<CGMReportDialog*>(theApp.GetRegisteredWindow(IDD_GMREPORTDIALOG));
if (NULL != lpPage)
{
if(PktChat::GMREPORT == lpChatDataSend->m_cChatType)
{
if(lpGMReport)
{
lpGMReport->AddMessage(lpChatDataSend);
}
}
else
{
// 여기서 필터링
if(lpFilter)
{
lpFilter->CheckMessage(lpChatDataSend);
}
if (PktChat::WHISPER == lpChatDataSend->m_cChatType)
{
if ((0 == theApp.GetLoginedName().Compare(lpChatDataSend->m_szTargetName))
|| (0 == theApp.GetLoginedName().Compare(lpChatDataSend->m_szSenderName)))
{
CWhisperDlg* lpWhisperDlg = lpPage->GetWhisperDlg(lpChatDataSend->m_dwUID);
if (NULL != lpWhisperDlg)
{
lpWhisperDlg->ParseChatData(lpChatDataSend);
}
else
{
bool bGMSender = false;
// sender 유저가 GM이면
if(0 == theApp.GetLoginedName().Compare(lpChatDataSend->m_szSenderName))
bGMSender = true;
// 두번째 매개변수는 유저가 운영자에게 말을 거는 경우 true
lpPage->ParseChatData(lpChatDataSend, true, bGMSender);
}
}
else
{
lpPage->ParseChatData(lpChatDataSend);
}
}
else
{
lpPage->ParseChatData(lpChatDataSend);
}
}
}
CMonitoringToolLog::GetInstance().WriteChatLog(lpChatDataSend);
return true;
}
/// \brief 모니터링 할 채팅 타입 보내기
/// \param nServerGroup 패킷을 전송할 서버군
/// \param szOption 모니터링할 옵션
/// \param cOptionNum 모니터링 하고자 선택한 타입의 개수
/// \return 패킷 전송 처리 성공 여부
bool ClientNet::CChatServerEventHandler::SendChatOptPkt(unsigned int nServerGroup,
unsigned char* szOption, unsigned char cOptionNum)
{
if (true != theApp.IsAuthorized())
{
return false;
}
cOptionNum = std::min(cOptionNum, unsigned char(ChatToolPkt::ChatOption::MAX_OPTION));
CChatServerEventHandler* lpHandler = theApp.GetChatServerHandler(nServerGroup);
if(0 == lpHandler)
{
ERRLOG1(g_Log, "Failed get session(ChatServer): Group- %u", nServerGroup);
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_030"));
return false;
}
CNetworkMsgBlock* lpMsg =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
sizeof(ChatToolPkt::ChatOption), INET_Addr());
if(0 != lpMsg)
{
ChatToolPkt::ChatOption* lpOption =
reinterpret_cast<ChatToolPkt::ChatOption*>(lpMsg->wr_ptr());
memcpy(lpOption->m_cChatOption, szOption, sizeof(unsigned char) * cOptionNum);
if(lpMsg->WrapCrypt(sizeof(ChatToolPkt::ChatOption), ChatToolCMD::ChangeOption, 0))
{
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
return true;
}
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
}
return true;
}
/// \brief 운영자의 접속 상태 설정
/// \param nServerGroup 상태를 다시 설정할 서버군
/// \param strAdminName 상태를 설정할 운영자의 계정명
/// \param cStatus 로그인 또는 로그아웃 상태
/// \return 패킷 전송 처리 성공 여부
bool ClientNet::CChatServerEventHandler::SendAdminStatus(unsigned int nServerGroup,
const CString& strAdminName, unsigned char cStatus)
{
if(!theApp.IsAuthorized())
{
return false;
}
CChatServerEventHandler* lpHandler = theApp.GetChatServerHandler(nServerGroup);
if(0 == lpHandler)
{
ERRLOG1(g_Log, "Failed get session(ChatServer): Group- %u", nServerGroup);
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_030"));
return false;
}
CNetworkMsgBlock* lpMsg =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(sizeof(ChatToolPkt::ChatAdminStatus), INET_Addr());
if(0 != lpMsg)
{
ChatToolPkt::ChatAdminStatus* lpAdminStatus =
reinterpret_cast<ChatToolPkt::ChatAdminStatus*>(lpMsg->wr_ptr());
strncpy(lpAdminStatus->m_szChatAdminName, strAdminName, ChatToolPkt::MAX_USER_ID);
lpAdminStatus->m_cChangeStatus = cStatus;
if(lpMsg->WrapCrypt(sizeof(ChatToolPkt::ChatAdminStatus), ChatToolCMD::ChatAdminStatus, 0))
{
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpMsg);
return true;
}
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsg);
}
return true;
}
/// \brief 핑 패킷을 마지막으로 받은 시간 갱신
/// \return 패킷 처리 성공 여부
bool ClientNet::CChatServerEventHandler::RecvChatPing(PktBase* lpPktBase, INET_Addr& peerAddr)
{
m_dwLastPingRecvTime = timeGetTime();
return true;
}
/// \brief 채팅 요청에 대한 Ack처리
/// \return 패킷 처리 성공 여부
bool ClientNet::CChatServerEventHandler::RecvChatRequest(PktBase* lpPktBase, INET_Addr& peerAddr)
{
ChatToolPkt::ChatRequest* lpChatRequest =
reinterpret_cast<ChatToolPkt::ChatRequest*>(lpPktBase);
switch (lpChatRequest->GetError())
{
case 0:
{
// 메세지 ID에 매칭되는 창이 띄워져있다면 Ack로 받은 UID를 셋팅해준다.
CChattingPage* lpPage =
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
CWhisperDlg* lpDlg = lpPage->GetAccountDlg(lpChatRequest->m_dwMessageID);
if ((NULL != lpDlg) && (0 == lpDlg->GetKeyUID()))
{
lpDlg->SetKeyUID(lpChatRequest->m_dwUID, lpChatRequest->m_dwCID);
}
}
break;
case ChatToolPkt::ChatRequest::PACKET_ERROR:
// 패킷에 에러가 있는 경우. 어쨌건 Ack는 왔음이요...
break;
case ChatToolPkt::ChatRequest::NONE_CHARACTER:
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_043"));
break;
}
return true;
}

View File

@@ -0,0 +1,50 @@
#ifndef _GAMA_NETWORK_CHATSERVER_EVENT_HANDLER_
#define _GAMA_NETWORK_CHATSERVER_EVENT_HANDLER_
#include <Network/ClientNetwork/ClientEventHandler.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Stream/Buffer/Buffer.h>
/** \namespace ClientNet
클라이언트에서 사용하는 네트웍 관련 클래스가 속한 네임스페이스*/
namespace ClientNet
{
/** \class CChatServerEventHandler
채팅서버와 모니터링 툴간 통신*/
class CChatServerEventHandler : public CClientEventHandler
{
public:
CChatServerEventHandler(unsigned int nServerGroup);
virtual int OnOpen(int iErrorCode);
virtual int OnClose();
static bool Connect();
virtual int OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr);
static bool SendAuthPkt(char* szUserID, char* szPass);
static bool SendChatOptPkt(unsigned int nServerGroup, unsigned char* szOption, unsigned char cOptionNum);
static bool SendChatReqPkt(unsigned int nServerGroup, unsigned char cChatType, unsigned char cTargetType,
unsigned long dwTargetUID, unsigned long dwMessageID, const CString& strGMName, const CString& strTargetName,
const CString& strMsg);
static bool SendAdminStatus(unsigned int nServerGroup, const CString& strAdminName, unsigned char cStatus);
unsigned long GetLastPingRecvTime() { return m_dwLastPingRecvTime; }
private:
bool RecvAuthAck(PktBase* lpPktBase, INET_Addr& peerAddr);
bool RecvChatData(PktBase* lpPktBase, INET_Addr& peerAddr);
bool RecvChatPing(PktBase* lpPktBase, INET_Addr& peerAddr);
bool RecvChatRequest(PktBase* lpPktBase, INET_Addr& peerAddr);
unsigned int m_nServerGroup;
unsigned long m_dwLastPingRecvTime;
};
};
#endif

View File

@@ -0,0 +1,911 @@
// ChattingPage.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringToolDlg.h"
#include "ChattingPage.h"
#include "GlobalFunc.h"
#include "ChatServerEventHandler.h"
#include "MonitoringToolSetup.h"
#include "MonitoringToolLog.h"
#include "MonitoringToolSetup.h"
#include "LoginDlg.h"
#include "WhisperDlg.h"
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <UserManage/UserStatistics.h>
#include <Utility/Setup/ServerSetup.h>
#include <Log/ServerLog.h>
#include ".\chattingpage.h"
// CChattingPage 대화 상자입니다.
IMPLEMENT_DYNAMIC(CChattingPage, CPropertyPage)
CChattingPage::CChattingPage()
: CPropertyPage(CChattingPage::IDD)
, m_bAutoScroll(TRUE)
, m_sChatMessageLines(0)
, m_nMaxGroup(0)
, m_dwAccountDlgID(0)
, m_usLocalLang(0xFFFF)
{
m_lpWhisperDlg = NULL;
theApp.RegisterWindow(IDD_CHATTINGPAGE, static_cast<CWnd*>(this));
}
CChattingPage::~CChattingPage()
{
theApp.RemoveWindow(IDD_CHATTINGPAGE);
}
void CChattingPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CHATMONITOR_LIST, m_ctrlChatMonitorList);
DDX_Control(pDX, IDC_SERVERGROUP_LIST, m_ctrlServerGroupCbList);
DDX_Control(pDX, IDC_CHATTYPE_LIST, m_ctrlChatTypeList);
DDX_Control(pDX, IDC_CONNECTION_LIST, m_ctrlConnectionList);
DDX_Control(pDX, IDC_CHATTYPE_CB, m_ctrlChatTypeCb);
DDX_Control(pDX, IDC_SERVERGROUP_CB, m_ctrlServerGroupCb);
DDX_Check(pDX, IDC_AUTOSCROLL_CHK, m_bAutoScroll);
DDX_Text(pDX, IDC_CHATLINES_EDIT, m_sChatMessageLines);
DDX_Control(pDX, IDC_USERSTAT_LIST, m_ctrlUserStatList);
}
BEGIN_MESSAGE_MAP(CChattingPage, CPropertyPage)
ON_LBN_SELCHANGE(IDC_CHATTYPE_LIST, OnLbnSelchangeOpt)
ON_LBN_SELCHANGE(IDC_SERVERGROUP_LIST, OnLbnSelchangeOpt)
ON_BN_CLICKED(IDC_CHATMSG_SEND_BTN, OnBnClickedChatmsgSendBtn)
ON_BN_CLICKED(IDC_AUTOSCROLL_CHK, OnBnClickedAutoscrollChk)
ON_BN_CLICKED(IDC_DELETECHATMSG_BTN, OnBnClickedDeletechatmsgBtn)
ON_BN_CLICKED(IDC_CHATLOGFLUSH_BTN, OnBnClickedChatlogflushBtn)
ON_BN_CLICKED(IDC_AUTH_MANAGER_BTN, OnBnClickedAuthManagerBtn)
ON_BN_CLICKED(IDC_FLUSH_STATLOG_BTN, OnBnClickedFlushStatlogBtn)
ON_LBN_DBLCLK(IDC_CHATMONITOR_LIST, OnLbnDblclkChatmonitorList)
ON_BN_CLICKED(IDC_CALL_WHISPER_DLG, OnBnClickedCallWhisperDlg)
ON_BN_CLICKED(IDC_GMLOGINED_CHK, OnBnClickedGmloginedChk)
ON_BN_CLICKED(IDC_LANGTYPE_CHK, OnBnClickedLangtypeChk)
ON_WM_SIZE()
END_MESSAGE_MAP()
// CChattingPage 메시지 처리기입니다.
BOOL CChattingPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const unsigned int nMaxZone = Setup.GetInt(_T("ZONE_INFO"), _T("ZONE_NUM"));
m_nMaxGroup = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
unsigned int nMaxChannel = Setup.GetInt(_T("CHANNEL_INFO"), _T("CHANNEL_NUM"));
SetServerListBox(m_ctrlServerGroupCbList);
SetChatTypeListBox(m_ctrlChatTypeList);
SetSendChatTypeCombo(m_ctrlChatTypeCb);
SetServerGroupCombo(m_ctrlServerGroupCb);
for(int nIndex = 0; nIndex < m_ctrlServerGroupCbList.GetCount(); ++nIndex)
m_ctrlServerGroupCbList.SetSel(nIndex);
for(int nIndex = 0; nIndex < m_ctrlChatTypeList.GetCount(); ++nIndex)
m_ctrlChatTypeList.SetSel(nIndex);
char szKey[256];
CString strFormat;
m_strLoginedName = "";
// 동접 정보 리스트 초기화
m_ctrlUserStatList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_FLATSB);
m_ctrlUserStatList.InsertColumn(0, _T("Z:00 C:00"), LVCFMT_CENTER, 73);
for(unsigned int nIndex = 0; nIndex < m_nMaxGroup; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_NAME_%02d", nIndex);
strFormat.Format(_T("%s"), Setup.GetString(_T("SERVER_GROUP_INFO"), szKey, _T("?")));
m_ctrlUserStatList.InsertColumn(nIndex + 1, strFormat, LVCFMT_RIGHT, 61);
}
SetDlgItemText(IDC_STRING001_STATIC, GetMyINIString("LOCAL_STRING", "STRING_001"));
SetDlgItemText(IDC_STRING002_STATIC, GetMyINIString("LOCAL_STRING", "STRING_002"));
SetDlgItemText(IDC_AUTOSCROLL_CHK, GetMyINIString("LOCAL_STRING", "STRING_003"));
SetDlgItemText(IDC_CHATLOGFLUSH_BTN, GetMyINIString("LOCAL_STRING", "STRING_004"));
SetDlgItemText(IDC_DELETECHATMSG_BTN, GetMyINIString("LOCAL_STRING", "STRING_005"));
SetDlgItemText(IDC_STRING006_STATIC, GetMyINIString("LOCAL_STRING", "STRING_006"));
SetDlgItemText(IDC_STRING007_STATIC, GetMyINIString("LOCAL_STRING", "STRING_007"));
SetDlgItemText(IDC_STRING007_STATIC2, GetMyINIString("LOCAL_STRING", "STRING_007"));
SetDlgItemText(IDC_STRING008_STATIC, GetMyINIString("LOCAL_STRING", "STRING_008"));
SetDlgItemText(IDC_STRING008_STATIC2, GetMyINIString("LOCAL_STRING", "STRING_008"));
SetDlgItemText(IDC_STRING009_STATIC, GetMyINIString("LOCAL_STRING", "STRING_009"));
SetDlgItemText(IDC_STRING010_STATIC, GetMyINIString("LOCAL_STRING", "STRING_010"));
SetDlgItemText(IDC_FLUSH_STATLOG_BTN, GetMyINIString("LOCAL_STRING", "STRING_011"));
SetDlgItemText(IDC_STRING012_STATIC, GetMyINIString("LOCAL_STRING", "STRING_012"));
SetDlgItemText(IDC_AUTH_MANAGER_BTN, GetMyINIString("LOCAL_STRING", "STRING_013"));
SetDlgItemText(IDC_STRING016_STATIC, GetMyINIString("LOCAL_STRING", "STRING_016"));
SetDlgItemText(IDC_CHATMSG_SEND_BTN, GetMyINIString("LOCAL_STRING", "STRING_017"));
SetDlgItemText(IDC_CALL_WHISPER_DLG, GetMyINIString("LOCAL_STRING", "STRING_023"));
SetDlgItemText(IDC_LOGINEDNAME_STATIC, GetMyINIString("LOCAL_STRING", "STRING_047"));
SetDlgItemText(IDC_GMLOGINED_CHK, GetMyINIString("LOCAL_STRING", "STRING_048"));
SetDlgItemText(IDC_LANGTYPE_CHK, GetMyINIString("LOCAL_STRING", "STRING_049"));
// 동접로그 파일에 컬럼명 명시
CString strColumnName;
strColumnName.Format(_T("WriteTime\tGroupIndex"));
for (unsigned int nZone = 0; nZone < nMaxZone; ++nZone)
{
_snprintf(szKey, MAX_PATH, _T("ZONE_INDEX_%02d"), nZone);
for (unsigned int nCH = 0; nCH < nMaxChannel; ++nCH)
{
strColumnName.AppendFormat(_T("\tZ:%02d C:%02d"),
Setup.GetInt(_T("ZONE_INFO"), szKey, 100), nCH + 1);
}
}
strColumnName.Append(_T("\r\n"));
CMonitoringToolLog::GetInstance().WriteUserStatLog(strColumnName);
return TRUE;
}
const unsigned short ALLOW_LETTER_NUM = 33;
const char AllowLetters[ALLOW_LETTER_NUM] = {
' ', '`', '~', '!', '@', '#', '$', '%', '^', '&',
'*', '(', ')', '-', '=', '_', '+', '{', '}', '|',
'[', ']', '\\', ';', '\'', ':', '\"', '<', '>', '?',
',', '.', '/'
};
BOOL CChattingPage::CheckCharSet(CHAR* str, int Len)
{
int ACount = 0;
// 영어만 입력가능
for(unsigned short LCount = 0; LCount < Len; LCount++)
{
// 2바이트 검출
if((str[LCount] & 0x80))
return TRUE;
// 영문자 허용
if((str[LCount] >= 'A' && str[LCount] <= 'Z') ||
(str[LCount] >= 'a' && str[LCount] <= 'z'))
{
continue;
}
// 숫자 허용
if(str[LCount] >= '0' && str[LCount] <= '9')
{
continue;
}
// 특수 기호 부분 허용
for(ACount = 0; ACount < ALLOW_LETTER_NUM; ACount++)
{
if(str[LCount] == AllowLetters[ACount])
{
break;
}
}
if(ACount == ALLOW_LETTER_NUM)
{
return TRUE;
}
}
return FALSE;
}
BOOL CChattingPage::CheckAisaLang(unsigned short usLang)
{
switch(usLang)
{
case LANG_JAPANESE: // 일본어
case LANG_KOREAN: // 한국어
case LANG_CHINESE: // 중국어
case LANG_THAI: // 태국어
return TRUE;
}
return FALSE;
}
void CChattingPage::AddLineToChatMonitorList(unsigned char cChatType, unsigned short usLang, char* szMsg, bool bIsCall)
{
CXListBox::Color cBackColor = CXListBox::BackColor;
CXListBox::Color cMessageColor = CXListBox::ChatNormal;
if (false == bIsCall)
{
switch(cChatType)
{
case PktChat::NORMAL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PktChat::PARTY:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatParty;
break;
case PktChat::FRIEND:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatFriend;
break;
case PktChat::GUILD:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatGuild;
break;
case PktChat::CLIENT_LOG:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PktChat::STALL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatStall;
break;
case PktChat::SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatShout;
break;
case PktChat::ADMIN_NORMAL_CHAT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminNormal;
break;
case PktChat::ADMIN_SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case PktChat::WHISPER:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatWhisper;
break;
case PktChat::TRADE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatTrade;
break;
case PktChat::NOTICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNotice;
break;
case PktChat::DICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case PktChat::GMREPORT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::GMReport;
break;
}
}
else
{
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::Call;
}
if (m_ctrlChatMonitorList.GetCount() > 5000)
{
//m_ctrlChatMonitorList.DeleteString(0);
m_ctrlChatMonitorList.ResetContent();
}
#ifdef NO_WHISPER
if(cChatType != PktChat::WHISPER)
#endif
{
m_sChatMessageLines = (unsigned long)m_ctrlChatMonitorList.GetCount();
m_ctrlChatMonitorList.AddLine(cMessageColor, cBackColor, szMsg, m_bAutoScroll);
}
UpdateData(false);
}
/// \brief 채팅패킷을 파싱하여 모니터링 스크린(m_ctrlChatMonitorList)에 출력
/// \param lpChatData 채팅 패킷
/// \param bIsCall 유저가 모니터링툴을 사용중인 유저에게 메세지를 보냈는지 여부
/// \note 모니터링 스크린의 특정라인을 더블클릭하면 대화창이 뜨도록하기 위해 SetItemData로 UID를 셋팅
void CChattingPage::ParseChatData(ChatToolPkt::ChatDataSend* lpChatData, bool bIsCall, bool bGMSender)
{
const int MAX_CHAT_LEN = 1024;
char strChatMsg[MAX_CHAT_LEN];
char strRecvMsg[UCHAR_MAX * 2];
char strRace[4][4] = {"N/A", "H", "A", "N/A"};
SERVER_ID serverID;
serverID.dwID = lpChatData->m_dwServerID;
if (0 != lpChatData)
{
time_t tCurrent = time(NULL);
struct tm tmCurrent = *localtime(&tCurrent);
memcpy(strRecvMsg, reinterpret_cast<char*>(lpChatData + 1), lpChatData->m_cChatMsgLen);
strRecvMsg[lpChatData->m_cChatMsgLen] = 0;
if (PktChat::WHISPER == lpChatData->m_cChatType)
{
/////////////////////////////////////////////////////////////////////////////////////////////
// 지엠한테 귓속말이 오면 강제로 귓속말을 처리하게 한다.
if(bIsCall)
{
unsigned long dwUID = lpChatData->m_dwUID;
unsigned long dwCID = lpChatData->m_dwCID;
CWhisperDlg::WhisperDlgInfo stInfo;
ZeroMemory(&stInfo, sizeof(CWhisperDlg::WhisperDlgInfo));
stInfo.m_nDlgType = CWhisperDlg::WhisperDlgInfo::DLG_TYPE::WHISPER_TYPE_CLK;
stInfo.m_dwUID = dwUID;
stInfo.m_dwCID = dwCID;
stInfo.m_cRace = lpChatData->m_cRace;
strncpy(stInfo.m_szServerName, theApp.GetServerName((unsigned int)serverID.GetGroup()), CWhisperDlg::WhisperDlgInfo::MAX_NAME);
if(!bGMSender)
strncpy(stInfo.m_szCharName, lpChatData->m_szSenderName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
else
strncpy(stInfo.m_szCharName, lpChatData->m_szTargetName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
// 이미 창이 띄워져 있는지 체크
WhisperDlgMap::iterator find = m_WhisperDlgMap.find(dwUID);
if (find != m_WhisperDlgMap.end())
{
(find->second)->SetFocus();
}
else
{
// 새 대화 모달리스 창 생성
m_lpWhisperDlg = new CWhisperDlg(this, stInfo);
m_lpWhisperDlg->Create(IDD_WHISPERDLG,this);
m_lpWhisperDlg->ShowWindow(SW_SHOW);
// 맵에 등록
m_WhisperDlgMap.insert(WhisperDlgMap::value_type(dwUID, m_lpWhisperDlg));
m_lpWhisperDlg->ParseChatData(lpChatData);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d][R:%s] %s : %s (To: %s)",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min, strRace[lpChatData->m_cRace],
lpChatData->m_szSenderName, strRecvMsg, lpChatData->m_szTargetName);
}
else if (PktChat::DICE == lpChatData->m_cChatType)
{
char strID[32];
int iMax, iCur;
sscanf(strRecvMsg, "%s %d %d", strID, &iMax, &iCur);
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d][R:%s] %s 님이 %d 주사위를 굴려 %d 가 나왔습니다.",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min, strRace[lpChatData->m_cRace], strID, iMax, iCur);
}
else
{
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d][R:%s] %s",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min, strRace[lpChatData->m_cRace], strRecvMsg);
}
if(m_usLocalLang != 0xFFFF)
{
if(CheckCharSet(strRecvMsg, strlen(strRecvMsg)) // 멀티바이트 문자이고
&& CheckAisaLang(lpChatData->m_usLang)
&& lpChatData->m_usLang != m_usLocalLang) // 내 컴퓨터의 언어와 동일하지 않으면
{
return;
}
}
AddLineToChatMonitorList(lpChatData->m_cChatType, lpChatData->m_usLang, strChatMsg, bIsCall);
m_ctrlChatMonitorList.SetItemData(m_ctrlChatMonitorList.GetCount() - 1, lpChatData->m_dwUID);
m_CharacterID[lpChatData->m_dwUID] = lpChatData->m_dwCID;
}
}
void CChattingPage::OnLbnSelchangeOpt()
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const char* szSection = _T("SERVER_GROUP_INFO");
char szKey[MAX_PATH];
// 채팅 필터링 옵션에 변화가 생겼을때의 이벤트 처리
// 1. 필터링 옵션 배열 초기화 : 초기값은 기본 옵션 모두 ON!
unsigned char szOption[ChatToolPkt::ChatOption::MAX_OPTION];
std::fill_n(szOption, int(ChatToolPkt::ChatOption::MAX_OPTION), 1);
// 2. 채팅 타입 별 필터링 : 선택되어 있는 옵션만 ON
// (단, 리스트 박스 인덱스는 DO_LISTEN(0)이 빠져 있으므로 패킷에 정의된 옵션 인덱스보다 1이 작음)
for(int nCurIndex = 0; nCurIndex < m_ctrlChatTypeList.GetCount(); ++nCurIndex)
{
if (0 != m_ctrlChatTypeList.GetSel(nCurIndex))
{
szOption[nCurIndex + 1] = 1; // 선택된 인덱스의 옵션 ON
}
else
{
szOption[nCurIndex + 1] = 0; // 선택되지 않은 인덱스의 옵션 OFF
}
}
// 3. 서버군 별 필터링 : 선택된 서버군과 선택되지 않은 서버군의 DO_LISTEN 옵션을 조정하여 전송!
unsigned int nMaxGroup = Setup.GetInt(szSection, "SERVER_GROUP_NUM");
for(unsigned int nIndex = 0; nIndex < nMaxGroup; ++nIndex)
{
_snprintf(szKey, MAX_PATH, _T("SERVER_GROUP_INDEX_%02d"), nIndex);
unsigned int nGroupIndex = Setup.GetInt(szSection, szKey, 100);
int nFind = m_ctrlServerGroupCbList.FindString(-1, theApp.GetServerName(nGroupIndex));
if (0 != m_ctrlServerGroupCbList.GetSel(nFind))
{
szOption[ChatToolPkt::ChatOption::DO_LISTEN] = 1; // 선택된 서버군 DO LISTEN
}
else
{
szOption[ChatToolPkt::ChatOption::DO_LISTEN] = 0; // 선택되지 않은 서버군 DO NOT LISTEN
}
if (NULL != theApp.GetChatServerHandler(nGroupIndex))
{
ClientNet::CChatServerEventHandler::SendChatOptPkt(
nGroupIndex, szOption, ChatToolPkt::ChatOption::MAX_OPTION);
}
}
}
void CChattingPage::OnBnClickedChatmsgSendBtn()
{
if (false == theApp.IsAuthorized())
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_044"));
return;
}
CString strServerName, strChatType, strMsg;
unsigned int nChatType;
// 보내는 메세지
GetDlgItemText(IDC_CHATMSG_EDIT, strMsg);
if(strMsg.GetLength() == 0)
return;
strMsg.Append(_T(" ")); // 맨 뒤 문자 깨지는거 방지 (귀찮;)
// 강제 귓속말 보내기 정보.
if(strncmp("/s ", strMsg.GetString(), 3) == 0)
{
// 강제로 귓말로 날렸다.
CString strGMName;
strGMName = theApp.GetLoginedName(); // GM명
char strTarget[32];
sscanf(strMsg.GetString(), "/s %s ", strTarget);
int Len = (int)strlen(strTarget)+4;
strMsg.Delete(0, Len);
unsigned long dwDlgID = GetAccountDlgID();
bool IsSended = false;
char szKey[256];
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
unsigned int nMaxGroupNum = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
for(int nIndex = 0; nIndex < (int)nMaxGroupNum; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
IsSended = ClientNet::CChatServerEventHandler::SendChatReqPkt(
nServerGroup, PktChat::WHISPER,
ChatToolPkt::TARGET_CHARNAME, 0, 0, strGMName, strTarget, strMsg);
}
if(!IsSended)
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_026"));
return;
}
if (CB_ERR == m_ctrlChatTypeCb.GetCurSel()
|| CB_ERR == m_ctrlServerGroupCb.GetCurSel())
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_025"));
return;
}
// 서버 명
m_ctrlServerGroupCb.GetLBText(m_ctrlServerGroupCb.GetCurSel(), strServerName);
// 채팅 타입
m_ctrlChatTypeCb.GetLBText(m_ctrlChatTypeCb.GetCurSel(), strChatType);
nChatType = GetChatTypeIndex(strChatType);
if (true == ClientNet::CChatServerEventHandler::SendChatReqPkt(
theApp.GetServerIndex(strServerName), nChatType,
ChatToolPkt::TARGET_CHARNAME, 0, 0, theApp.GetLoginedName(), _T(""), strMsg))
{
SetDlgItemText(IDC_CHATMSG_EDIT, _T(""));
}
else
{
// 보내기 실패 에러 메세지
}
}
void CChattingPage::OnBnClickedAutoscrollChk()
{
if(m_bAutoScroll)
{
m_bAutoScroll = FALSE;
}
else
{
m_bAutoScroll = TRUE;
}
}
void CChattingPage::OnBnClickedDeletechatmsgBtn()
{
m_ctrlChatMonitorList.ResetContent();
}
void CChattingPage::OnBnClickedChatlogflushBtn()
{
CMonitoringToolLog::GetInstance().FlushChatLog();
}
void CChattingPage::SetManagerServerConnection()
{
CString strConnection;
if (NULL != theApp.GetManagerHandler())
{
strConnection = GetMyINIString("LOCAL_STRING", "STRING_027");
}
else
{
strConnection = GetMyINIString("LOCAL_STRING", "STRING_028");
}
SetDlgItemText(IDC_MANAGERSERVER_CON_EDIT, strConnection);
}
void CChattingPage::OnBnClickedAuthManagerBtn()
{
CLoginDlg dlg(CLoginDlg::MANAGER_SERVER);
dlg.DoModal();
}
void CChattingPage::SetUserStat()
{
m_ctrlUserStatList.DeleteAllItems();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
unsigned int nMaxGroup = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
unsigned int nMaxZone = Setup.GetInt(_T("ZONE_INFO"), _T("ZONE_NUM"));
unsigned int nMaxChannel = Setup.GetInt(_T("CHANNEL_INFO"), _T("CHANNEL_NUM"));
CString strKey;
CString strUserNum;
CString strRowName;
for (unsigned int nZone = 0; nZone < nMaxZone; ++nZone)
{
for (unsigned int nCH = 0; nCH < nMaxChannel; ++nCH)
{
strKey.Format(_T("ZONE_INDEX_%02d"), nZone);
unsigned int nZoneIndex = Setup.GetInt(_T("ZONE_INFO"), strKey, 100);
strRowName.Format(_T("Z:%02d C:%02d"), nZoneIndex, nCH + 1);
m_ctrlUserStatList.InsertItem((nZone * nMaxChannel) + nCH, strRowName);
for (unsigned int nGroup = 0; nGroup < nMaxGroup; ++nGroup)
{
strKey.Format(_T("SERVER_GROUP_INDEX_%02d"), nGroup);
unsigned int nGroupIndex = Setup.GetInt(_T("SERVER_GROUP_INFO"), strKey, 100);
SERVER_ID serverID;
serverID.dwID = 0;
serverID.sID.ID = nZoneIndex;
serverID.sID.Group = nGroupIndex;
serverID.sID.Type = CServerSetup::GameServer;
serverID.sID.Channel = nCH;
strUserNum.Format(_T("%d"), CUserStatistics::GetInstance().GetUserNum(serverID.dwID));
m_ctrlUserStatList.SetItemText((nZone * nMaxChannel) + nCH, nGroup + 1, strUserNum);
}
}
}
unsigned int nTotalUserNum = 0;
int nRow = m_ctrlUserStatList.GetItemCount();
m_ctrlUserStatList.InsertItem(nRow, _T("SUM"));
for (unsigned int nGroup = 0; nGroup < nMaxGroup; ++nGroup)
{
strKey.Format(_T("SERVER_GROUP_INDEX_%02d"), nGroup);
unsigned int nGroupIndex = Setup.GetInt(_T("SERVER_GROUP_INFO"), strKey, 100);
nTotalUserNum += CUserStatistics::GetInstance().GetGroupUserNum(nGroupIndex);
strUserNum.Format(_T("%d"), CUserStatistics::GetInstance().GetGroupUserNum(nGroupIndex));
m_ctrlUserStatList.SetItemText(nRow, nGroup + 1, strUserNum);
}
SetDlgItemInt(IDC_TOTALUSERNUM_EDIT, nTotalUserNum, TRUE);
}
void CChattingPage::OnBnClickedFlushStatlogBtn()
{
CMonitoringToolLog::GetInstance().FlushStatLog();
}
void CChattingPage::OnLbnDblclkChatmonitorList()
{
if (0 > m_ctrlChatMonitorList.GetCurSel())
{
MessageBox(GetMyINIString("LOCAL_STRING", "STRING_024"));
return;
}
unsigned long dwUID =
static_cast<unsigned long>(m_ctrlChatMonitorList.GetItemData(m_ctrlChatMonitorList.GetCurSel()));
if (0 == dwUID)
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_029"));
return;
}
char szBuffer[256];
m_ctrlChatMonitorList.GetText(m_ctrlChatMonitorList.GetCurSel(), szBuffer);
// 선택한 라인을 파싱하여 필요한 정보 추출
// ex) ServerName [Z:00][00:00][R:00] SenderName : Message (To: TargetName)
char* szServerName = strtok(szBuffer, " ");
strtok(NULL, "]");
strtok(NULL, "]");
char* szRace = strtok(NULL, "]");
char* szSenderName = strtok(NULL, " ");
TrimTab(szServerName, (int)strlen(szServerName)); // \t 정리
if (0 == strcmp(szServerName, "UNKNOWN"))
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_029"));
return;
}
if (0 == szSenderName)
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_029"));
return;
}
CWhisperDlg::WhisperDlgInfo stInfo;
ZeroMemory(&stInfo, sizeof(CWhisperDlg::WhisperDlgInfo));
stInfo.m_nDlgType = CWhisperDlg::WhisperDlgInfo::DLG_TYPE::WHISPER_TYPE_CLK;
stInfo.m_dwUID = dwUID;
stInfo.m_dwCID = m_CharacterID[dwUID];
stInfo.m_cRace = 0;
if(szRace[3] == 'H')
stInfo.m_cRace = 1;
else if(szRace[3] == 'A')
stInfo.m_cRace = 2;
strncpy(stInfo.m_szServerName, szServerName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
strncpy(stInfo.m_szCharName, szSenderName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
// 이미 창이 띄워져 있는지 체크
WhisperDlgMap::iterator find = m_WhisperDlgMap.find(dwUID);
if (find != m_WhisperDlgMap.end())
{
(find->second)->SetFocus();
return;
}
// 새 대화 모달리스 창 생성
m_lpWhisperDlg = new CWhisperDlg(this, stInfo);
m_lpWhisperDlg->Create(IDD_WHISPERDLG,this);
m_lpWhisperDlg->ShowWindow(SW_SHOW);
// 맵에 등록
m_WhisperDlgMap.insert(WhisperDlgMap::value_type(dwUID, m_lpWhisperDlg));
}
char* CChattingPage::TrimTab(char* szBuffer, int nSize)
{
char *temp = new char[nSize];
memset(temp, 0, nSize);
int j = 0;
for (int i=0; i < nSize; i++)
{
if (szBuffer[i] != '\t')
{
temp[j++] = szBuffer[i];
}
}
strcpy(szBuffer, temp);
delete temp;
return szBuffer;
}
void CChattingPage::OnBnClickedCallWhisperDlg()
{
if (false == theApp.IsAuthorized())
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_044"));
return;
}
// 계정또는 UID로 대화 창을 띄울때는 별도의 ID를 임시키로 부여한다.
// Ack로 받는 ID로 창을 찾아 UID를 셋팅하고 사용.
// 이미 창이 띄워져 있는지 체크
WhisperDlgMap::iterator find = m_AccountDlgMap.find(m_dwAccountDlgID);
if (find != m_AccountDlgMap.end())
{
(find->second)->SetFocus();
return;
}
// 새로운 창을 생성하기 전에 ID 증가
++m_dwAccountDlgID;
CWhisperDlg::WhisperDlgInfo stInfo;
ZeroMemory(&stInfo, sizeof(CWhisperDlg::WhisperDlgInfo));
stInfo.m_nDlgType = CWhisperDlg::WhisperDlgInfo::DLG_TYPE::FINDUSER;
stInfo.m_dwUID = 0;
stInfo.m_dwDlgID = m_dwAccountDlgID;
m_lpWhisperDlg = new CWhisperDlg(this, stInfo);
m_lpWhisperDlg->Create(IDD_WHISPERDLG);
m_lpWhisperDlg->ShowWindow(SW_SHOW);
// 맵에 등록
m_AccountDlgMap.insert(WhisperDlgMap::value_type(m_dwAccountDlgID, m_lpWhisperDlg));
}
CWhisperDlg* CChattingPage::GetWhisperDlg(unsigned long dwUID)
{
WhisperDlgMap::iterator find = m_WhisperDlgMap.find(dwUID);
if (find != m_WhisperDlgMap.end())
{
return find->second;
}
else
{
return NULL;
}
}
CWhisperDlg* CChattingPage::GetAccountDlg(unsigned long dwDlgID)
{
WhisperDlgMap::iterator find = m_AccountDlgMap.find(dwDlgID);
if (find != m_AccountDlgMap.end())
{
return find->second;
}
else
{
return NULL;
}
}
BOOL CChattingPage::PreTranslateMessage(MSG* pMsg)
{
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN))
{
if ((pMsg->hwnd == GetDlgItem(IDC_CHATMSG_EDIT)->m_hWnd))
{
OnBnClickedChatmsgSendBtn();
}
}
return CPropertyPage::PreTranslateMessage(pMsg);
}
void CChattingPage::SetLoginedNameEdit(const CString& strLoginedName)
{
m_strLoginedName = strLoginedName;
SetDlgItemText(IDC_LOGINEDNAME_EDIT, strLoginedName);
}
void CChattingPage::OnBnClickedGmloginedChk()
{
if (true == theApp.IsAuthorized())
{
unsigned char cSendType = 0;
if (BST_CHECKED != IsDlgButtonChecked(IDC_GMLOGINED_CHK))
{
cSendType = ChatToolPkt::ChatAdminStatus::LOGOUT;
}
else
{
cSendType = ChatToolPkt::ChatAdminStatus::LOGIN;
}
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[256];
for(int nIndex = 0; nIndex < (int)m_nMaxGroup; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
if (false == ClientNet::CChatServerEventHandler::SendAdminStatus(nServerGroup, 0, cSendType))
{
ERRLOG3(g_Log, "채팅 서버로 운영계정 로그인/아웃 패킷 전송 실패. 그룹: %d, GMName: %s, Type: %d",
nServerGroup, theApp.GetLoginedName(), cSendType);
}
}
}
}
void CChattingPage::OnBnClickedLangtypeChk()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if (true == theApp.IsAuthorized())
{
if (BST_CHECKED != IsDlgButtonChecked(IDC_LANGTYPE_CHK))
{
m_usLocalLang = 0xFFFF;
}
else
{
m_usLocalLang = PRIMARYLANGID(GetSystemDefaultLangID());
}
}
}
BOOL CChattingPage::DestroyWindow()
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[256];
for(int nIndex = 0; nIndex < (int)m_nMaxGroup; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
if (false == ClientNet::CChatServerEventHandler::SendAdminStatus(
nServerGroup, 0, ChatToolPkt::ChatAdminStatus::LOGOUT))
{
ERRLOG2(g_Log, "채팅 서버로 운영계정 로그아웃 패킷 전송 실패. 그룹: %d, GMName: %s",
nServerGroup, theApp.GetLoginedName());
}
}
return CPropertyPage::DestroyWindow();
}
void CChattingPage::OnSize(UINT nType, int cx, int cy)
{
CPropertyPage::OnSize(nType, cx, cy);
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
CRect rect, rectc;
GetClientRect(rect);
if(m_ctrlChatMonitorList.GetSafeHwnd())
{
m_ctrlChatMonitorList.GetWindowRect(rectc);
m_ctrlChatMonitorList.MoveWindow(350, 35, rect.Width()-350, rectc.Height());
}
}

View File

@@ -0,0 +1,91 @@
#pragma once
#include "afxwin.h"
#include "XListBox.h"
#include <Network/Packet/ChatToolPacketCmd.h>
#include "afxcmn.h"
#include <map>
class CWhisperDlg; //메시지창을 모달리스로 띄워서 사용할 것임.
/** \class CChattingPage
CMonitoringSheet에 속한 페이지*/
class CChattingPage : public CPropertyPage
{
DECLARE_DYNAMIC(CChattingPage)
public:
CChattingPage();
virtual ~CChattingPage();
// 대화 상자 데이터입니다.
enum { IDD = IDD_CHATTINGPAGE };
typedef std::map<unsigned long, CWhisperDlg*> WhisperDlgMap;
typedef std::map<unsigned long, unsigned long> CharacterIDDataMap;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
DECLARE_MESSAGE_MAP()
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL DestroyWindow();
private:
CXListBox m_ctrlChatMonitorList;
CListBox m_ctrlChatTypeList;
CListBox m_ctrlServerGroupCbList;
CComboBox m_ctrlChatTypeCb;
CComboBox m_ctrlServerGroupCb;
CString m_strLoginedName;
BOOL m_bAutoScroll;
unsigned long m_sChatMessageLines;
unsigned int m_nMaxGroup;
CWhisperDlg* m_lpWhisperDlg; ///< 1대1 대화창
afx_msg void OnLbnSelchangeOpt();
afx_msg void OnBnClickedChatmsgSendBtn();
afx_msg void OnBnClickedAutoscrollChk();
afx_msg void OnBnClickedDeletechatmsgBtn();
afx_msg void OnBnClickedChatlogflushBtn();
afx_msg void OnBnClickedAuthManagerBtn();
afx_msg void OnBnClickedFlushStatlogBtn();
afx_msg void OnBnClickedCallWhisperDlg();
afx_msg void OnLbnDblclkChatmonitorList();
afx_msg void OnBnClickedGmloginedChk();
public:
unsigned short m_usLocalLang;
unsigned long m_dwAccountDlgID;
CListBox m_ctrlConnectionList; ///< 채팅서버와의 접속상태
CListCtrl m_ctrlUserStatList; ///< 동접 정보
CharacterIDDataMap m_CharacterID;
WhisperDlgMap m_WhisperDlgMap; ///< 1대1 대화창 맵
WhisperDlgMap m_AccountDlgMap; ///< 계정명 또는 UID 대화창 맵
void ParseChatData(ChatToolPkt::ChatDataSend* lpChatData, bool bIsCall = false, bool bGMSender = false);
void AddLineToChatMonitorList(unsigned char cChatType, unsigned short usLang, char* szMsg, bool bIsCall = false);
void SetManagerServerConnection();
void SetUserStat();
unsigned long GetAccountDlgID() { return m_dwAccountDlgID; };
void SetLoginedNameEdit(const CString& strLoginedName);
char* TrimTab(char* szBuffer, int nSize);
CWhisperDlg* GetWhisperDlg(unsigned long dwUID);
CWhisperDlg* GetAccountDlg(unsigned long dwDlgID);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnBnClickedLangtypeChk();
BOOL CheckCharSet(CHAR* str, int Len);
BOOL CheckAisaLang(unsigned short usLang);
};

View File

@@ -0,0 +1,253 @@
// CClipboard Class
// ----------------
// Written by David Terracino <davet@lycosemail.com>
//
// This code is released into the public domain, because
// it's silly easy. If you want to use and expand it, go
// ahead; fine by me. If you do expand this class's
// functionality, please consider sending it back up to
// the MFC Programmer's Sourcebook at www.codeguru.com.
//
// And as always, please give credit where credit is
// due. Don't remove my name from the source.
///////////////////////////////////////////////////////////////////////////////
// Modified by Hans Dietrich hdietrich2@hotmail.com
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Clipboard.h"
///////////////////////////////////////////////////////////////////////////////
// GetText - Retrieves text from the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
//
// Return Values:
// CString - not empty if text was successfully copied from clipboard
//
///////////////////////////////////////////////////////////////////////////////
CString CClipboard::GetText()
{
CString str;
str = _T("");
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed.
if (::OpenClipboard(NULL))
{
// Request a pointer to the text on the clipboard.
HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
// If there was no text on the clipboard, we have
// been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPSTR lpszData = (LPSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
str = lpszData;
// Now, simply unlock the global memory pointer
// and close the clipboard.
::GlobalUnlock(hGlobal);
}
}
::CloseClipboard();
}
return str;
}
///////////////////////////////////////////////////////////////////////////////
// GetText - Retrieves text from the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
// lpszBuffer - pointer to a string where the text is to be put
// nBufSize - allocated length of lpszBuffer
//
// Return Values:
// TRUE - Text was successfully retrieved
// FALSE - No text returned
//
///////////////////////////////////////////////////////////////////////////////
BOOL CClipboard::GetText(LPSTR lpszBuffer, int nBufSize)
{
ASSERT(lpszBuffer);
if (lpszBuffer == NULL)
return FALSE;
if (nBufSize == 0)
return FALSE;
lpszBuffer[0] = 0;
BOOL bSuccess = FALSE;
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed.
if (::OpenClipboard(NULL))
{
// Request a pointer to the text on the clipboard.
HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
// If there was no text on the clipboard, we have
// been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPSTR lpszData = (LPSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
// Now get the size of the text on the clipboard.
DWORD nSize = ::GlobalSize(hGlobal);
// Make sure the text on the clipboard is not longer
// that the buffer that was allocated for it. If it was
// snip the text on the clipboard so that it fits.
if (nSize >= (UINT)nBufSize)
nSize = nBufSize - 1;
// Now, copy the text into the return buffer. Note that
// there will be at least one nul at the end
ZeroMemory(lpszBuffer, nBufSize);
CopyMemory(lpszBuffer, lpszData, nSize);
// Now, simply unlock the global memory pointer
// and close the clipboard.
::GlobalUnlock(hGlobal);
bSuccess = TRUE;
}
}
::CloseClipboard();
}
return bSuccess;
}
///////////////////////////////////////////////////////////////////////////////
// GetTextLength - Retrieves length of text on the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
//
// Return Values:
// > 0 - Text length was successfully returned.
// 0 - No text on the clipboard
//
///////////////////////////////////////////////////////////////////////////////
DWORD CClipboard::GetTextLength()
{
DWORD nSize = 0; // Size of clipboard data
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed.
if (::OpenClipboard(NULL))
{
// Request a pointer to the text on the clipboard.
HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
// If there was no text on the clipboard, we have
// been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPSTR lpszData = (LPSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
// Now get the size of the text on the clipboard.
nSize = ::GlobalSize(hGlobal);
// Now, simply unlock the global memory pointer
// and close the clipboard.
::GlobalUnlock(hGlobal);
}
}
::CloseClipboard();
}
return nSize;
}
///////////////////////////////////////////////////////////////////////////////
// SetText - Places text on the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
// lpszBuffer - pointer to a string to put on the clipboard
//
// Return Values:
// TRUE - Text was successfully copied onto clipboard
// FALSE - Text not copied
//
///////////////////////////////////////////////////////////////////////////////
BOOL CClipboard::SetText(LPCTSTR lpszBuffer)
{
BOOL bSuccess = FALSE;
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed. After opening, empty the clipboard so we
// can put our text on it.
if (::OpenClipboard(NULL))
{
::EmptyClipboard();
// Get the size of the string in the buffer that was
// passed into the function, so we know how much global
// memory to allocate for the string.
int nSize = _tcslen(lpszBuffer);
// Allocate the memory for the string.
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_ZEROINIT, nSize+1);
// If we got any error during the memory allocation,
// we have been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPTSTR lpszData = (LPTSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
// Now, copy the text from the buffer into the allocated
// global memory pointer
_tcscpy(lpszData, lpszBuffer);
// Now, simply unlock the global memory pointer,
// set the clipboard data type and pointer,
// and close the clipboard.
::GlobalUnlock(hGlobal);
::SetClipboardData(CF_TEXT, hGlobal);
bSuccess = TRUE;
}
}
::CloseClipboard();
}
return bSuccess;
}

View File

@@ -0,0 +1,29 @@
// CClipboard Class
// ----------------
// Written by David Terracino <davet@lycosemail.com>
//
// This code is released into the public domain, because
// it's silly easy. If you want to use and expand it, go
// ahead; fine by me. If you do expand this class's
// functionality, please consider sending it back up to
// the MFC Programmer's Sourcebook at www.codeguru.com.
//
// And as always, please give credit where credit is
// due. Don't remove my name from the source.
///////////////////////////////////////////////////////////////////////////////
// Modified by Hans Dietrich hdietrich2@hotmail.com
///////////////////////////////////////////////////////////////////////////////
#ifndef CCLIPBOARD_H
#define CCLIPBOARD_H
class CClipboard
{
public:
static CString GetText();
static BOOL GetText(LPSTR lpszBuffer, int nBufSize);
static DWORD GetTextLength();
static BOOL SetText(LPCTSTR lpszBuffer);
};
#endif

View File

@@ -0,0 +1,315 @@
// ColorPickerCB.cpp
//
// http://www.codeguru.com/combobox//combo_color_picker3.shtml
//
// (c) 1998 James R. Twine
//
// Based On Code That Was Found On www.codeguru.com, And Was
// ?1997 Baldvin Hansson
//
///////////////////////////////////////////////////////////////////////////////
// Modified by Hans Dietrich hdietrich2@hotmail.com
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ColorPickerCB.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// NOTE - following table must be kept in sync with XListBox.cpp
SColorAndName CColorPickerCB::ms_pColors[CCB_MAX_COLORS] =
{
SColorAndName( RGB( 0x00, 0x00, 0x00 ), _T("Black") ),
SColorAndName( RGB( 0xFF, 0xFF, 0xFF ), _T("White") ),
SColorAndName( RGB( 0x80, 0x00, 0x00 ), _T("Maroon") ),
SColorAndName( RGB( 0x00, 0x80, 0x00 ), _T("Green") ),
SColorAndName( RGB( 0x80, 0x80, 0x00 ), _T("Olive") ),
SColorAndName( RGB( 0x00, 0x00, 0x80 ), _T("Navy") ),
SColorAndName( RGB( 0x80, 0x00, 0x80 ), _T("Purple") ),
SColorAndName( RGB( 0x00, 0x80, 0x80 ), _T("Teal") ),
SColorAndName( RGB( 0xC0, 0xC0, 0xC0 ), _T("Silver") ),
SColorAndName( RGB( 0x80, 0x80, 0x80 ), _T("Gray") ),
SColorAndName( RGB( 0xFF, 0x00, 0x00 ), _T("Red") ),
SColorAndName( RGB( 0x00, 0xFF, 0x00 ), _T("Lime") ),
SColorAndName( RGB( 0xFF, 0xFF, 0x00 ), _T("Yellow") ),
SColorAndName( RGB( 0x00, 0x00, 0xFF ), _T("Blue") ),
SColorAndName( RGB( 0xFF, 0x00, 0xFF ), _T("Fuchsia") ),
SColorAndName( RGB( 0x00, 0xFF, 0xFF ), _T("Aqua") )
};
CColorPickerCB::CColorPickerCB()
{
}
CColorPickerCB::~CColorPickerCB()
{
}
BEGIN_MESSAGE_MAP(CColorPickerCB, CComboBox)
//{{AFX_MSG_MAP(CColorPickerCB)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CColorPickerCB message handlers
int CColorPickerCB::OnCreate(LPCREATESTRUCT pCStruct)
{
if (CComboBox::OnCreate(pCStruct) == -1) // If Create Failed
return -1; // Return Failure
Initialize(); // Initialize Contents
SetCurSel(0); // Select First Item By Default
return 0; // Done!
}
void CColorPickerCB::PreSubclassWindow()
{
Initialize(); // Initialize Contents
CComboBox::PreSubclassWindow(); // Subclass Control
SetCurSel(0); // Select First Item By Default
}
void CColorPickerCB::Initialize()
{
int iAddedItem = -1;
ResetContent();
for (int iColor = 0; iColor < CCB_MAX_COLORS; iColor++) // For All Colors
{
iAddedItem = AddString( ms_pColors[iColor].m_cColor); // Set Color Name/Text
if (iAddedItem == CB_ERRSPACE) // If Not Added
break; // Stop
else // If Added Successfully
SetItemData(iAddedItem, ms_pColors[iColor].m_crColor); // Set Color RGB Value
}
}
void CColorPickerCB::DrawItem(LPDRAWITEMSTRUCT pDIStruct)
{
CDC dcContext;
CRect rItemRect(pDIStruct -> rcItem);
CRect rBlockRect(rItemRect);
CRect rTextRect(rBlockRect);
int iColorWidth = (rBlockRect.Width() * 5)/ 12;
int iItem = pDIStruct -> itemID;
int iState = pDIStruct -> itemState;
CBrush brFrameBrush;
COLORREF crColor = 0;
COLORREF crNormal = GetSysColor(COLOR_WINDOW);
COLORREF crSelected = GetSysColor(COLOR_HIGHLIGHT);
COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
if (!dcContext.Attach(pDIStruct -> hDC)) // Attach CDC Object
return; // Stop If Attach Failed
brFrameBrush.CreateStockObject(BLACK_BRUSH); // Create Black Brush
if (iState & ODS_SELECTED) // If Selected
{ // Set Selected Attributes
dcContext.SetTextColor((0x00FFFFFF & ~(crText))); // Set Inverted Text Color (With Mask)
dcContext.SetBkColor(crSelected); // Set BG To Highlight Color
dcContext.FillSolidRect(&rBlockRect, crSelected); // Erase Item
}
else // If Not Selected
{ // Set Standard Attributes
dcContext.SetTextColor(crText); // Set Text Color
dcContext.SetBkColor(crNormal); // Set BG Color
dcContext.FillSolidRect(&rBlockRect, crNormal); // Erase Item
}
if (iState & ODS_FOCUS) // If Item Has The Focus
dcContext.DrawFocusRect(&rItemRect); // Draw Focus Rect
//
// Calculate Text Area
//
rTextRect.left += iColorWidth + 2; // Set Start Of Text
rTextRect.top += 2; // Offset A Bit
//
// Calculate Color Block Area
//
rBlockRect.DeflateRect(CSize(2, 2)); // Reduce Color Block Size
rBlockRect.right = iColorWidth; // Set Width Of Color Block
//
// Draw Color Text And Block
//
if (iItem != -1) // If Not An Empty Item
{
CString sColor;
GetLBText(iItem, sColor); // Get Color Text
if (iState & ODS_DISABLED) // If Disabled
{
crColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
dcContext.SetTextColor(crColor); // Set Text Color
}
else // If Normal
crColor = GetItemData(iItem); // Get Color Value
dcContext.SetBkMode(TRANSPARENT); // Transparent Background
dcContext.TextOut(rTextRect.left, rTextRect.top, sColor); // Draw Color Name
dcContext.FillSolidRect(&rBlockRect, crColor); // Draw Color
dcContext.FrameRect(&rBlockRect, &brFrameBrush); // Draw Frame
}
dcContext.Detach(); // Detach DC From Object
}
COLORREF CColorPickerCB::GetSelectedColorValue()
{
int iSelectedItem = GetCurSel(); // Get Selected Item
if (iSelectedItem == CB_ERR) // If Nothing Selected
return (RGB(0, 0, 0)); // Return Black
return (GetItemData(iSelectedItem)); // Return Selected Color
}
UINT CColorPickerCB::GetSelectedColorIndex()
{
UINT nSelectedItem = GetCurSel(); // Get Selected Item
if (nSelectedItem == CB_ERR) // If Nothing Selected
return 0;
else
return nSelectedItem;
}
CString CColorPickerCB::GetSelectedColorName()
{
int iSelectedItem = GetCurSel(); // Get Selected Item
if (iSelectedItem == CB_ERR) // If Nothing Selected
return (m_sColorName = "afxEmptyString"); // Return Nothing (Not "Black!")
GetLBText(iSelectedItem, m_sColorName); // Store Name Of Color
return m_sColorName; // Return Selected Color Name
}
void CColorPickerCB::SetSelectedColorValue(COLORREF crClr)
{
int iItems = GetCount();
for (int iItem = 0; iItem < iItems; iItem++)
{
if (crClr == GetItemData(iItem)) // If Match Found
SetCurSel(iItem); // Select It
}
}
void CColorPickerCB::SetSelectedColorIndex(UINT nIndex)
{
ASSERT(nIndex >= 0 && nIndex <= 15);
SetCurSel(nIndex);
}
void CColorPickerCB::SetSelectedColorName(LPCTSTR cpColor)
{
int iItems = GetCount();
CString sColorName;
for (int iItem = 0; iItem < iItems; iItem++)
{
GetLBText(iItem, sColorName); // Get Color Name
if (!sColorName.CompareNoCase(cpColor)) // If Match Found
SetCurSel(iItem); // Select It
}
}
BOOL CColorPickerCB::RemoveColor(LPCTSTR cpColor)
{
int iItems = GetCount();
CString sColor;
BOOL bRemoved = FALSE;
for (int iItem = 0; iItem < iItems; iItem++)
{
GetLBText(iItem, sColor); // Get Color Name
if (!sColor.CompareNoCase(cpColor)) // If Match Found
{
DeleteString(iItem); // Remove It
bRemoved = TRUE; // Set Flag
break; // Stop Checking
}
}
return bRemoved; // Done!
}
BOOL CColorPickerCB::RemoveColor(COLORREF crClr)
{
int iItems = GetCount();
BOOL bRemoved = FALSE;
for (int iItem = 0; iItem < iItems; iItem++)
{
if (crClr == GetItemData(iItem)) // If Desired Color Found
{
DeleteString(iItem); // Remove It
bRemoved = TRUE; // Set Flag
break; // Stop Checking
}
}
return bRemoved; // Done!
}
int CColorPickerCB::AddColor(LPCTSTR cpName, COLORREF crColor)
{
int iItem = -1;
iItem = InsertString(-1, cpName); // Insert String
if (iItem != LB_ERR) // If Insert Good
SetItemData(iItem, crColor); // Set Color Value
return iItem; // Done! Return Location
}
void DDX_ColorPicker(CDataExchange* pDX, int nIDC_, COLORREF& crColor)
{
HWND hWndCtrl = pDX->PrepareCtrl(nIDC_);
ASSERT(hWndCtrl);
CColorPickerCB* pPicker = (CColorPickerCB*) CWnd::FromHandle(hWndCtrl);
ASSERT(pPicker);
if (!pDX->m_bSaveAndValidate)
{
pPicker->SetSelectedColorValue(crColor);
}
else
{
crColor = pPicker->GetSelectedColorValue();
}
}
void DDX_ColorPicker(CDataExchange* pDX, int nIDC_, CString& strName)
{
HWND hWndCtrl = pDX->PrepareCtrl(nIDC_);
ASSERT(hWndCtrl);
CColorPickerCB* pPicker = (CColorPickerCB*) CWnd::FromHandle(hWndCtrl);
ASSERT(pPicker);
if (!pDX->m_bSaveAndValidate)
{
pPicker->SetSelectedColorName(strName);
}
else
{
strName = pPicker->GetSelectedColorName();
}
}

View File

@@ -0,0 +1,99 @@
// ColorPickerCB.h
//
// http://www.codeguru.com/combobox//combo_color_picker3.shtml
//
// (c) 1998 James R. Twine
//
// Based On Code That Was Found On www.codeguru.com, And Was
// ?1997 Baldvin Hansson
//
///////////////////////////////////////////////////////////////////////////////
// Modified by Hans Dietrich hdietrich2@hotmail.com
///////////////////////////////////////////////////////////////////////////////
#ifndef COLORPICKERCB_H
#define COLORPICKERCB_H
#define CCB_MAX_COLORS 16 // Colors In List
#define CCB_MAX_COLOR_NAME 16 // Max Chars For Color Name - 1
//
// Internal Structure For Color/Name Storage...
//
struct SColorAndName
{
SColorAndName()
{
ZeroMemory(this, sizeof(SColorAndName)); // Init Structure
};
SColorAndName(COLORREF crColor, LPCTSTR cpColor)
{
ZeroMemory(this, sizeof(SColorAndName)); // Init Structure
m_crColor = crColor; // Set Color RGB Value
_tcsncpy(m_cColor, cpColor, CCB_MAX_COLOR_NAME); // Set Color Name
};
COLORREF m_crColor; // Actual Color RGB Value
TCHAR m_cColor[CCB_MAX_COLOR_NAME]; // Actual Name For Color
};
// Gets/sets color value from/to COLORREF member variable
void DDX_ColorPicker(CDataExchange* pDX_, int nIDC_, COLORREF& crColor_);
// Gets/sets color name from/to CString member variable
void DDX_ColorPicker(CDataExchange* pDX_, int nIDC_, CString& strName_);
class CColorPickerCB : public CComboBox
{
// Construction
public:
CColorPickerCB();
virtual ~CColorPickerCB();
// Attributes
private:
CString m_sColorName; // Name Of Selected Color
private:
void Initialize(void); // Initialize Control/Colors
public:
static
SColorAndName ms_pColors[CCB_MAX_COLORS]; // Array Of Colors And Names
COLORREF GetSelectedColorValue(void); // Get Selected Color Value
UINT GetSelectedColorIndex(void); // Get Selected Color Index
CString GetSelectedColorName( void ); // Get Selected Color Name
void SetSelectedColorValue(COLORREF crClr); // Set Selected Color Value
void SetSelectedColorIndex(UINT nIndex); // Set Selected Color Index
void SetSelectedColorName(LPCTSTR cpColor); // Set Selected Color Name
BOOL RemoveColor(LPCTSTR cpColor); // Remove Color From List
BOOL RemoveColor(COLORREF crClr); // Remove Color From List
int AddColor(LPCTSTR cpNam, COLORREF crClr); // Insert A New Color
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CColorPickerCB)
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
// Implementation
public:
// Generated message map functions
protected:
//{{AFX_MSG(CColorPickerCB)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif //COLORPICKERCB_H

View File

@@ -0,0 +1,202 @@
// FilterUserDialog.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "FilterUserDialog.h"
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <UserManage/UserStatistics.h>
#include <Utility/Setup/ServerSetup.h>
#include <Log/ServerLog.h>
#include ".\filteruserdialog.h"
// CFilterUserDialog 대화 상자입니다.
IMPLEMENT_DYNAMIC(CFilterUserDialog, CDialog)
CFilterUserDialog::CFilterUserDialog(CWnd* pParent /*=NULL*/)
: CDialog(CFilterUserDialog::IDD, pParent)
{
theApp.RegisterWindow(IDD_FILTERDIALOG, static_cast<CWnd*>(this));
}
CFilterUserDialog::~CFilterUserDialog()
{
theApp.RemoveWindow(IDD_FILTERDIALOG);
}
void CFilterUserDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_FILTERLIST, m_FilterList);
}
BEGIN_MESSAGE_MAP(CFilterUserDialog, CDialog)
ON_WM_SIZE()
ON_BN_CLICKED(IDC_SAVEBUTTON, OnBnClickedSavebutton)
ON_BN_CLICKED(IDC_SAVEBUTTON2, OnBnClickedSavebutton2)
ON_BN_CLICKED(IDC_SAVEBUTTON3, OnBnClickedSavebutton3)
END_MESSAGE_MAP()
// CFilterUserDialog 메시지 처리기입니다.
BOOL CFilterUserDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// SetDlgItemText(IDC_SAVEBUTTON, GetMyINIString("LOCAL_STRING", "STRING_021"));
g_StringFilter.Load("Filter.txt");
return TRUE;
}
void CFilterUserDialog::OnOK()
{
ShowWindow(SW_HIDE);
}
void CFilterUserDialog::OnCancel()
{
ShowWindow(SW_HIDE);
}
void CFilterUserDialog::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
if(m_FilterList.GetSafeHwnd())
{
CRect rt;
GetClientRect(rt);
rt.top += 22;
m_FilterList.MoveWindow(rt);
}
}
void CFilterUserDialog::CheckMessage(ChatToolPkt::ChatDataSend* lpChatData)
{
const int MAX_CHAT_LEN = 1024;
char strRecvMsg[UCHAR_MAX * 2];
memcpy(strRecvMsg, reinterpret_cast<char*>(lpChatData + 1), lpChatData->m_cChatMsgLen);
strRecvMsg[lpChatData->m_cChatMsgLen] = 0;
if(!g_StringFilter.Filter(strRecvMsg))
{
char strChatMsg[MAX_CHAT_LEN];
SERVER_ID serverID;
serverID.dwID = lpChatData->m_dwServerID;
time_t tCurrent = time(NULL);
struct tm tmCurrent = *localtime(&tCurrent);
CXListBox::Color cBackColor = CXListBox::BackColor;
CXListBox::Color cMessageColor = CXListBox::ChatNormal;
switch(lpChatData->m_cChatType)
{
case PktChat::NORMAL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PktChat::PARTY:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatParty;
break;
case PktChat::FRIEND:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatFriend;
break;
case PktChat::GUILD:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatGuild;
break;
case PktChat::CLIENT_LOG:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PktChat::STALL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatStall;
break;
case PktChat::SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatShout;
break;
case PktChat::ADMIN_NORMAL_CHAT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminNormal;
break;
case PktChat::ADMIN_SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case PktChat::WHISPER:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatWhisper;
break;
case PktChat::TRADE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatTrade;
break;
case PktChat::NOTICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNotice;
break;
case PktChat::DICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case PktChat::GMREPORT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::GMReport;
break;
}
if (PktChat::WHISPER == lpChatData->m_cChatType)
{
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d] %s : %s (to. %s)",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min,
lpChatData->m_szSenderName, strRecvMsg, lpChatData->m_szTargetName);
}
else
{
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d] %s : %s",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min,
lpChatData->m_szSenderName, strRecvMsg);
}
m_FilterList.AddLine(cMessageColor, cBackColor, strChatMsg, true);
ShowWindow(SW_SHOW);
}
}
void CFilterUserDialog::OnBnClickedSavebutton()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
CString strFilter = _T("Text File (*.txt)|*.txt||");
CFileDialog dlg(FALSE, _T("txt"), _T(""), OFN_HIDEREADONLY|OFN_READONLY, strFilter, this);
if (dlg.DoModal() == IDOK)
{
CFile file(dlg.GetPathName(), CFile::modeWrite|CFile::modeCreate);
CString str;
CString line = _T("\r\n");
int iCount = m_FilterList.GetCount();
for(int i = 0; i < iCount; ++i)
{
m_FilterList.GetText(i, str);
file.Write(str.GetString(), str.GetLength());
file.Write(line.GetString(), line.GetLength());
}
}
}
void CFilterUserDialog::OnBnClickedSavebutton2()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
g_StringFilter.Load("Filter.txt");
}
void CFilterUserDialog::OnBnClickedSavebutton3()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
m_FilterList.ResetContent();
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include "afxwin.h"
#include "XListBox.h"
#include "StringFilter.h"
#include <Network/Packet/ChatToolPacketCmd.h>
// CFilterUserDialog 대화 상자입니다.
class CFilterUserDialog : public CDialog
{
DECLARE_DYNAMIC(CFilterUserDialog)
public:
CFilterUserDialog(CWnd* pParent = NULL); // 표준 생성자입니다.
virtual ~CFilterUserDialog();
// 대화 상자 데이터입니다.
enum { IDD = IDD_FILTERDIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
virtual void OnOK();
virtual void OnCancel();
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CXListBox m_FilterList;
afx_msg void OnSize(UINT nType, int cx, int cy);
void CheckMessage(ChatToolPkt::ChatDataSend* lpChatDatamessage);
afx_msg void OnBnClickedSavebutton();
afx_msg void OnBnClickedSavebutton2();
afx_msg void OnBnClickedSavebutton3();
};

View File

@@ -0,0 +1,133 @@
// GMReportDialog.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "GMReportDialog.h"
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <UserManage/UserStatistics.h>
#include <Utility/Setup/ServerSetup.h>
#include <Log/ServerLog.h>
// CGMReportDialog 대화 상자입니다.
IMPLEMENT_DYNAMIC(CGMReportDialog, CDialog)
CGMReportDialog::CGMReportDialog(CWnd* pParent /*=NULL*/)
: CDialog(CGMReportDialog::IDD, pParent)
{
theApp.RegisterWindow(IDD_GMREPORTDIALOG, static_cast<CWnd*>(this));
}
CGMReportDialog::~CGMReportDialog()
{
theApp.RemoveWindow(IDD_GMREPORTDIALOG);
}
void CGMReportDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_REPORTLIST, m_ReportList);
}
BEGIN_MESSAGE_MAP(CGMReportDialog, CDialog)
ON_WM_SIZE()
ON_BN_CLICKED(IDC_SAVEBUTTON, OnBnClickedSavebutton)
ON_BN_CLICKED(IDC_SAVEBUTTON3, OnBnClickedSavebutton3)
END_MESSAGE_MAP()
// CGMReportDialog 메시지 처리기입니다.
BOOL CGMReportDialog::OnInitDialog()
{
CDialog::OnInitDialog();
return TRUE;
}
void CGMReportDialog::OnOK()
{
ShowWindow(SW_HIDE);
}
void CGMReportDialog::OnCancel()
{
ShowWindow(SW_HIDE);
}
void CGMReportDialog::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
if(m_ReportList.GetSafeHwnd())
{
CRect rt;
GetClientRect(rt);
rt.top += 22;
m_ReportList.MoveWindow(rt);
}
}
void CGMReportDialog::AddMessage(ChatToolPkt::ChatDataSend* lpChatData)
{
const int MAX_CHAT_LEN = 1024;
char strRecvMsg[UCHAR_MAX * 2];
memcpy(strRecvMsg, reinterpret_cast<char*>(lpChatData + 1), lpChatData->m_cChatMsgLen);
strRecvMsg[lpChatData->m_cChatMsgLen] = 0;
char strChatMsg[MAX_CHAT_LEN];
SERVER_ID serverID;
serverID.dwID = lpChatData->m_dwServerID;
time_t tCurrent = time(NULL);
struct tm tmCurrent = *localtime(&tCurrent);
CXListBox::Color cBackColor = CXListBox::BackColor;
CXListBox::Color cMessageColor = CXListBox::GMReport;
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d] %s : %s",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min,
lpChatData->m_szSenderName, strRecvMsg);
m_ReportList.AddLine(cMessageColor, cBackColor, strChatMsg, true);
ShowWindow(SW_SHOW);
}
void CGMReportDialog::OnBnClickedSavebutton()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
CString strFilter = _T("Text File (*.txt)|*.txt||");
CFileDialog dlg(FALSE, _T("txt"), _T(""), OFN_HIDEREADONLY|OFN_READONLY, strFilter, this);
if (dlg.DoModal() == IDOK)
{
CFile file(dlg.GetPathName(), CFile::modeWrite|CFile::modeCreate);
CString str;
CString line = _T("\r\n");
int iCount = m_ReportList.GetCount();
for(int i = 0; i < iCount; ++i)
{
m_ReportList.GetText(i, str);
file.Write(str.GetString(), str.GetLength());
file.Write(line.GetString(), line.GetLength());
}
}
}
void CGMReportDialog::OnBnClickedSavebutton3()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
m_ReportList.ResetContent();
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include "afxwin.h"
#include "XListBox.h"
#include "StringFilter.h"
#include <Network/Packet/ChatToolPacketCmd.h>
// CGMReportDialog 대화 상자입니다.
class CGMReportDialog : public CDialog
{
DECLARE_DYNAMIC(CGMReportDialog)
public:
CGMReportDialog(CWnd* pParent = NULL); // 표준 생성자입니다.
virtual ~CGMReportDialog();
// 대화 상자 데이터입니다.
enum { IDD = IDD_GMREPORTDIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
virtual void OnOK();
virtual void OnCancel();
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CXListBox m_ReportList;
afx_msg void OnSize(UINT nType, int cx, int cy);
void AddMessage(ChatToolPkt::ChatDataSend* lpChatDatamessage);
afx_msg void OnBnClickedSavebutton();
afx_msg void OnBnClickedSavebutton3();
};

View File

@@ -0,0 +1,198 @@
#include "stdafx.h"
#include "GlobalFunc.h"
#include "MonitoringTool.h"
#include "MonitoringToolSetup.h"
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
const int MAX_BUFFER = 256;
const char* szSection1 = _T("SERVER_GROUP_INFO");
const char* szSection2 = _T("CHAT_TYPE_INFO");
/// \brief 인자로 받은 리스트 박스에 셋업파일의 서버그룹명을 셋팅
/// \param ctrlListBox 서버그룹명을 셋팅할 리스트 박스
void SetServerListBox(CListBox& ctrlListBox)
{
ctrlListBox.ResetContent();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[MAX_BUFFER];
unsigned int nServerGroup;
CString strFormat;
int nMaxGroup = Setup.GetInt(szSection1, "SERVER_GROUP_NUM");
for(int nIndex = 0; nIndex < nMaxGroup; ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "SERVER_GROUP_INDEX_%02d", nIndex);
nServerGroup = Setup.GetInt(szSection1, szKey);
strFormat.Format("%s", theApp.GetServerName(nServerGroup));
ctrlListBox.AddString(strFormat);
}
}
/// \brief 인자로 받은 콤보 박스에 셋업파일의 서버그룹명을 셋팅
/// \param ctrlCombo 서버그룹명을 셋팅할 콤보 박스
void SetServerGroupCombo(CComboBox& ctrlCombo)
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[MAX_BUFFER];
unsigned int nServerGroup;
CString strFormat;
int nMaxGroup = Setup.GetInt(szSection1, "SERVER_GROUP_NUM");
for(int nIndex = 0; nIndex < nMaxGroup; ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "SERVER_GROUP_INDEX_%02d", nIndex);
nServerGroup = Setup.GetInt(szSection1, szKey);
strFormat.Format("%s", theApp.GetServerName(nServerGroup));
ctrlCombo.InsertString(nIndex, strFormat);
}
}
/// \brief 인자로 받은 리스트 박스에 셋업파일의 채팅타입을 셋팅
/// \param ctrlListBox 채팅타입을 셋팅할 리스트 박스
void SetChatTypeListBox(CListBox& ctrlListBox)
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
int nMaxChatType = Setup.GetInt(szSection2, "CHAT_TYPE_NUM");
char szKey[MAX_BUFFER];
CString strFormat;
for(int nIndex = 0; nIndex < nMaxChatType; ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "CHAT_TYPE_NAME_%02d", nIndex);
strFormat.Format("%s", Setup.GetString(szSection2, szKey));
ctrlListBox.AddString(strFormat);
}
}
/// \brief 인자로 받은 리스트 박스에 채팅서버 연결상태를 표시
/// \param ctrlListBox 연결상태를 표시할 리스트 박스
void SetConnectionListBox(CListBox& ctrlListBox)
{
if(!ctrlListBox.GetSafeHwnd())
return;
ctrlListBox.ResetContent();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[MAX_BUFFER];
for(unsigned int nIndex = 0; nIndex < Setup.GetInt(szSection1, "SERVER_GROUP_NUM"); ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "SERVER_GROUP_INDEX_%02d", nIndex);
if(0 != theApp.GetChatServerHandler(Setup.GetInt(szSection1, szKey)))
{
ctrlListBox.AddString(_T("OK"));
}
else
{
ctrlListBox.AddString(_T("DIS"));
}
}
}
/// \brief 인자로 받은 콤보 박스에 셋업파일의 채팅타입을 셋팅
/// \param ctrlCombo 채팅타입을 셋팅할 콤보 박스
void SetChatTypeCombo(CComboBox& ctrlCombo)
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
int nMaxChatType = Setup.GetInt(szSection2, "CHAT_TYPE_NUM");
char szKey[MAX_BUFFER];
CString strFormat;
for(int nIndex = 0; nIndex < nMaxChatType; ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "CHAT_TYPE_NAME_%02d", nIndex);
strFormat.Format("%s", Setup.GetString(szSection2, szKey));
ctrlCombo.InsertString(nIndex, strFormat);
}
}
/// \brief 인자로 받은 콤보 박스에 셋업파일의 메시지를 전송할 채팅타입을 셋팅
/// \param ctrlCombo 채팅타입을 셋팅할 콤보 박스
/// \note SetChatTypeCombo 함수와 구분하여 사용하여야 함
void SetSendChatTypeCombo(CComboBox& ctrlCombo)
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
int nMaxGroup = Setup.GetInt(szSection2, "SEND_CHAT_TYPE_NUM");
char szKey[MAX_BUFFER];
CString strFormat;
for(int nIndex = 0; nIndex < nMaxGroup; ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "SEND_CHAT_TYPE_NAME_%02d", nIndex);
strFormat.Format("%s", Setup.GetString(szSection2, szKey));
ctrlCombo.InsertString(nIndex, strFormat);
}
}
/// \brief 인자로 받은 콤보 박스에 GM명을 셋팅
/// \param ctrlCombo GM명을 셋팅할 콤보 박스
/// \note 로그인한 GM명으로 메세지 보내기로 수정한 후 사용하지 않음
void SetGMNameCombo(CComboBox& ctrlCombo)
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const char* szSection = _T("GM_INFO");
int nMaxGM = Setup.GetInt(szSection, "GM_NUM");
char szKey[MAX_BUFFER];
CString strFormat;
for(int nIndex = 0; nIndex < nMaxGM; ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, "GM_NAME_%02d", nIndex);
strFormat.Format("%s", Setup.GetString(szSection, szKey));
ctrlCombo.InsertString(nIndex, strFormat);
}
}
/// \brief 채팅타입명으로 채팅타입 인덱스 얻기
/// \param strTypeName 인덱스를 얻고자 하는 채팅타입명
unsigned int GetChatTypeIndex(CString strTypeName)
{
if(strTypeName == _T("ADMIN_SHOUT")) return PktChat::ADMIN_SHOUT;
if(strTypeName == _T("SHOUT")) return PktChat::SHOUT;
//if(strTypeName == _T("WHISPER")) return PktChat::WHISPER;
return 255; // 존재하지 않는 채팅타입 인덱스
}
/// \brief 섹션명과 키로 ini 셋업 파일에서 셋팅된 값 얻기
/// \param szSection 얻고자하는 값이 속한 섹션명
/// \param szKey 얻고자 하는 값에 매칭되는 키
const char* GetMyINIString(const char* szSection, const char* szKey)
{
const char* szResult = CMonitoringToolSetup::GetInstance().GetString(szSection, szKey, 0);
if(0 == szResult)
{
CString strErr;
strErr.Format("Setup string load failed! - key: %s", szKey);
AfxMessageBox(strErr, MB_ICONSTOP);
return "???";
}
return szResult;
}

View File

@@ -0,0 +1,21 @@
#ifndef _GAMA_NETWORK_MONITORING_TOOL_G_FUNC_H_
#define _GAMA_NETWORK_MONITORING_TOOL_G_FUNC_H_
#include <Utility/Registry/RegFunctions.h>
void SetServerListBox(CListBox& ctrlListBox);
void SetServerGroupCombo(CComboBox& ctrlCombo);
void SetChatTypeListBox(CListBox& ctrlListBox);
void SetChatTypeCombo(CComboBox& ctrlCombo);
void SetSendChatTypeCombo(CComboBox& ctrlCombo);
void SetConnectionListBox(CListBox& ctrlListBox);
void SetGMNameCombo(CComboBox& ctrlCombo);
unsigned int GetChatTypeIndex(CString strTypeName);
const char* GetMyINIString(const char* szSection, const char* szKey);
#endif

View File

@@ -0,0 +1,105 @@
// LoginDlg.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "LoginDlg.h"
#include "ChatServerEventHandler.h"
#include "ManagerServerEventHandler.h"
#include "GlobalFunc.h"
#include <Network/Packet/ChatToolPacketCmd.h>
#include <Network/Packet/ManagePacketCmd.h>
// CLoginDlg 대화 상자입니다.
IMPLEMENT_DYNAMIC(CLoginDlg, CDialog)
CLoginDlg::CLoginDlg(AUTH_TYPE cAuthType, CWnd* pParent /*=NULL*/)
: CDialog(CLoginDlg::IDD, pParent)
, m_cAuthType(cAuthType)
{
theApp.RegisterWindow(IDD_LOGINDLG, static_cast<CWnd*>(this));
}
CLoginDlg::~CLoginDlg()
{
theApp.RemoveWindow(IDD_LOGINDLG);
}
void CLoginDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CLoginDlg, CDialog)
ON_BN_CLICKED(IDC_LOGIN_BTN, OnBnClickedLoginBtn)
END_MESSAGE_MAP()
// CLoginDlg 메시지 처리기입니다.
BOOL CLoginDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CString strWindowTitle = _T("UNKNOWN");
if (CHAT_SERVER == m_cAuthType)
{
strWindowTitle = GetMyINIString("LOCAL_STRING", "STRING_041");;
}
else if(MANAGER_SERVER == m_cAuthType)
{
strWindowTitle = GetMyINIString("LOCAL_STRING", "STRING_042");
}
SetWindowText(strWindowTitle);
return TRUE;
}
/// \brief 인증 성공시 호출하여 다이얼로그 소멸
/// \note 외부 클래스에서 인증성공이 확인되면 호출
void CLoginDlg::OnOK()
{
CDialog::OnOK();
}
void CLoginDlg::OnCancel()
{
CDialog::OnCancel();
}
void CLoginDlg::OnBnClickedLoginBtn()
{
char szID[ChatToolPkt::MAX_USER_ID], szPass[ChatToolPkt::MAX_PASSWORD];
if ((0 != GetDlgItemText(IDC_LOGIN_ID_EDIT, szID, ChatToolPkt::MAX_USER_ID))
&& (0 != GetDlgItemText(IDC_LOGIN_PASS_EDIT, szPass, ChatToolPkt::MAX_PASSWORD)))
{
if (m_cAuthType == CHAT_SERVER)
{
ClientNet::CChatServerEventHandler::SendAuthPkt(szID, szPass);
}
else if(m_cAuthType == MANAGER_SERVER)
{
ClientNet::CManagerServerEventHandler* lpHandler = theApp.GetManagerHandler();
if(0 != lpHandler)
{
ServerManage::UserInfo userInfo;
_tcsncpy(userInfo.szID, szID, ServerManage::UserInfo::ID_LEN);
_tcsncpy(userInfo.szPassword, szPass, ServerManage::UserInfo::PASS_LEN);
ClientNet::CManagerServerEventHandler::SendUserInfo(lpHandler, &userInfo, 1,
ServerManage::CMD::AuthUser, 0);
}
}
}
else
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_036"));
}
}

View File

@@ -0,0 +1,37 @@
#pragma once
/** \class CLoginDlg
채팅서버, 관리서버 인증을 받을때 사용하는 다이얼로그*/
class CLoginDlg : public CDialog
{
DECLARE_DYNAMIC(CLoginDlg)
public:
/// 로그인창의 인증 종류
enum AUTH_TYPE
{
CHAT_SERVER = 0, ///< 채팅서버 인증
MANAGER_SERVER = 1 ///< 관리서버 인증
};
CLoginDlg(AUTH_TYPE cAuthType, CWnd* pParent = NULL); // 표준 생성자입니다.
virtual ~CLoginDlg();
enum { IDD = IDD_LOGINDLG };
virtual void OnOK();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
DECLARE_MESSAGE_MAP()
virtual BOOL OnInitDialog();
virtual void OnCancel();
private:
unsigned char m_cAuthType; ///< 인증 종류 (인증 패킷 전송할때 참조)
afx_msg void OnBnClickedLoginBtn();
};

View File

@@ -0,0 +1,249 @@
#include "stdafx.h"
#include "MonitoringTool.h"
#include "ManagerServerEventHandler.h"
#include "MonitoringToolSetup.h"
#include "LoginDlg.h"
#include "GlobalFunc.h"
#include <Utility/Setup/ServerSetup.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <UserManage/UserStatistics.h>
#include <Log/ServerLog.h>
#include <Utility/Compress/MiniLZO/MiniLZOWrapper.h>
#include <mmsystem.h>
namespace ClientNet
{
CManagerServerEventHandler::CManagerServerEventHandler()
: m_dwLastPingRecvTime(0)
{
}
CManagerServerEventHandler::~CManagerServerEventHandler()
{
}
bool CManagerServerEventHandler::Connect()
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const char* szIP = Setup.GetString(_T("MANAGER_SERVER_CONNECTION"), _T("MANAGER_SERVER_IP"));
CManagerServerEventHandler* lpHandler = new CManagerServerEventHandler;
if (!theApp.GetEventHandlerMgr().Connect(
INET_Addr(szIP, CServerSetup::ManageServerManageToolListen), lpHandler))
{
delete lpHandler;
return false;
}
return true;
}
int CManagerServerEventHandler::OnOpen(int iErrorCode)
{
if(0 == iErrorCode)
{
theApp.RegisterManagerHandler(this);
INET_Addr& addr = GetPeerAddress();
INFLOG3(g_Log, _T("Connect Session (ManagerServer): DP:0x%p, %s:%d"),
this, addr.get_addr_string(), addr.get_port_in());
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_037"));
}
else
{
ERRLOG1(g_Log, _T("Connect Session Failed (ManagerServer): Err- %d"), iErrorCode);
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_038"));
}
m_dwLastPingRecvTime = timeGetTime();
return 0;
}
int CManagerServerEventHandler::OnClose()
{
CWnd* lpWnd = AfxGetMainWnd();
if(0 != lpWnd && !IsCloseCalled())
{
lpWnd->PostMessage(WM_SHOW_MSGBOX, MSGBOX_MANAGER_DISCONNECTED);
}
INFLOG1(g_Log, _T("Disconnect Session (ManagerServer): DP:0x%p"), this);
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_039"));
theApp.RemoveManagerHandler(this);
return 0;
}
int CManagerServerEventHandler::OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr)
{
switch(lpPktBase->GetCmd())
{
case ServerManage::CMD::AuthUser: RecvAuthAck(lpPktBase, peerAddr); break;
case ServerManage::CMD::RelayCommand: RecvUserStatistics(lpPktBase, peerAddr); break;
case ServerManage::CMD::Ping: RecvPing(lpPktBase, peerAddr); break;
}
return 0;
}
/// \brief 관리서버로 부터 동접정보를 받아서 저장
/// \return 패킷 처리 성공 여부
bool CManagerServerEventHandler::RecvUserStatistics(PktBase* lpPktBase, INET_Addr& peerAddr)
{
if(lpPktBase->GetLen() < sizeof(ServerManage::ManageCommand))
{
ERRLOG3(g_Log, _T("DP:0x%p/Cmd:0x%p/Invalid packet size : %d"),
this, lpPktBase->GetCmd(), lpPktBase->GetLen());
}
else if(0 != lpPktBase->GetError())
{
ERRLOG3(g_Log, _T("DP:0x%p/Cmd:0x%p/Err:%d/Get ProcessStatus packet failed"),
this, lpPktBase->GetCmd(), lpPktBase->GetError());
}
else
{
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(!ServerManage::CheckManagePacketLength(lpPktBase))
{
ERRLOG3(g_Log, _T("DP:0x%p/Cmd:0x%p/Invalid packet size : %d"),
this, lpPktBase->GetCmd(), lpPktBase->GetLen());
}
if(sizeof(ServerManage::PktManagePacket) <= lpManageCommand->usDataLen)
{
ServerManage::PktManagePacket* lpPktManagePacket =
reinterpret_cast<ServerManage::PktManagePacket*>(lpManageCommand + 1);
switch(lpPktManagePacket->m_dwSubCommand)
{
case ServerManage::CMD::SubCmd_ServerUserNum:
{
ServerManage::PktManageUserNum* lpPktManageUserNum =
static_cast<ServerManage::PktManageUserNum*>(lpPktManagePacket);
CUserStatistics::GetInstance().SerializeIn(lpManageCommand->dwRunID,
reinterpret_cast<ServerManage::UserNumPair*>(lpPktManageUserNum + 1),
lpPktManageUserNum->m_dwUserInfoNum);
}
break;
}
return true;
}
}
return false;
}
/// \brief 관리서버로 인증패킷 전송
/// \param lpHandler 관리서버 연결 세션
/// \param lpUserInfo 로그인 유저 정보
/// \param cUserInfoNum 유저수(모니터링툴에선 1로 고정)
/// \param cCommand 커맨드
/// \param cError 인증 패킷 전송에 따른 에러코드
/// \return 패킷 전송 처리 성공 여부
bool CManagerServerEventHandler::SendUserInfo(CManagerServerEventHandler* lpHandler,
const ServerManage::UserInfo* lpUserInfo,
unsigned char cUserInfoNum,
unsigned char cCommand,
unsigned char cError)
{
// 다른 유저들에게 자신이 추가되었다는 메시지를 던진다.
CNetworkMsgPool& networkMsgPool = CNetworkMsgPool::GetInstance();
CNetworkMsgBlock* lpBuffer = networkMsgPool.GetNetworkMsgBlock(
sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum, INET_Addr());
CNetworkMsgBlock* lpCompressedBuffer = networkMsgPool.GetNetworkMsgBlock(
CMiniLZO::GetLeastCompressBuffer(sizeof(ServerManage::UserCommand) +
sizeof(ServerManage::UserInfo) * cUserInfoNum), INET_Addr());
if(0 != lpBuffer && 0 != lpCompressedBuffer)
{
ServerManage::UserCommand* lpUserCommand = reinterpret_cast<ServerManage::UserCommand*>(lpBuffer->wr_ptr());
ServerManage::UserInfo* lpFirstUserInfo = reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
ServerManage::UserInfo* lpLastUserInfo = lpFirstUserInfo + cUserInfoNum;
lpUserCommand->cUserInfoNum = cUserInfoNum;
std::copy(lpUserInfo, lpUserInfo + cUserInfoNum, lpFirstUserInfo);
lpBuffer->wr_ptr(sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum);
if(lpCompressedBuffer->WrapCompress(lpBuffer->rd_ptr(), (unsigned short)lpBuffer->length(),
cCommand, 0, cError))
{
networkMsgPool.FreeNetworkMsgBlock(lpBuffer);
theApp.GetEventHandlerMgr().SendPacket(lpHandler, lpCompressedBuffer);
return true;
}
}
networkMsgPool.FreeNetworkMsgBlock(lpBuffer);
networkMsgPool.FreeNetworkMsgBlock(lpCompressedBuffer);
return false;
}
/// \brief 관리서버 인증 Ack
void CManagerServerEventHandler::RecvAuthAck(PktBase* lpPktBase, INET_Addr& peerAddr)
{
CString strErrFormat;
CLoginDlg* lpLoginDlg =
static_cast<CLoginDlg*>(theApp.GetRegisteredWindow(IDD_LOGINDLG));
if(lpPktBase->GetLen() < sizeof(ServerManage::UserCommand))
{
ERRLOG3(g_Log, _T("DP:0x%p/Cmd:0x%p/Invalid packet size : %d"),
this, lpPktBase->GetCmd(), lpPktBase->GetLen());
}
else if(0 != lpPktBase->GetError())
{
switch(lpPktBase->GetError())
{
case ServerManage::AUTHORIZE_FAILED:
strErrFormat = _T("ManagerServer Auth Failed: AUTHORIZE_FAILED");
break;
case ServerManage::CANNOT_AUTHORIZE_NOT_USER:
strErrFormat = _T("ManagerServer Auth Failed: CANNOT_AUTHORIZE_NOT_USER");
break;
case ServerManage::CANNOT_AUTHORIZE_INVALID_PASSWORD:
strErrFormat = _T("ManagerServer Auth Failed: CANNOT_AUTHORIZE_INVALID_PASSWORD");
break;
case ServerManage::CANNOT_AUTHORIZE_INVALID_IPADDRESS:
strErrFormat = _T("ManagerServer Auth Failed: CANNOT_AUTHORIZE_INVALID_IPADDRESS");
break;
case ServerManage::ALREADY_LOGINED:
strErrFormat = _T("ManagerServer Auth Failed: ALREADY_LOGINED");
break;
default:
break;
}
}
else
{
lpLoginDlg->OnOK();
strErrFormat = GetMyINIString("LOCAL_STRING", "STRING_040");
}
theApp.ReportResult(strErrFormat);
}
/// \brief 관리서버에서 마지막으로 핑받은 시각 갱신
void CManagerServerEventHandler::RecvPing(PktBase* lpPktBase, INET_Addr& peerAddr)
{
m_dwLastPingRecvTime = timeGetTime();
}
}

View File

@@ -0,0 +1,42 @@
#ifndef _GAMA_NETWORK_MANAGERSERVER_EVENT_HANDLER_
#define _GAMA_NETWORK_MANAGERSERVER_EVENT_HANDLER_
#include <Network/ClientNetwork/ClientEventHandler.h>
#include <Network/Packet/ManagePacketCmd.h>
namespace ClientNet
{
/** \class CManagerServerEventHandler
관리서버와 모니터링 툴간 통신*/
class CManagerServerEventHandler : public CClientEventHandler
{
public:
CManagerServerEventHandler();
virtual ~CManagerServerEventHandler();
virtual int OnOpen(int iErrorCode);
virtual int OnClose();
static bool Connect();
virtual int OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr);
static bool SendUserInfo(CManagerServerEventHandler* lpHandler,
const ServerManage::UserInfo* lpUserInfo,
unsigned char cUserInfoNum, unsigned char cCommand, unsigned char cError);
unsigned long GetLastPingRecvTime() { return m_dwLastPingRecvTime; }
private:
void RecvAuthAck(PktBase* lpPktBase, INET_Addr& peerAddr);
bool RecvUserStatistics(PktBase* lpPktBase, INET_Addr& peerAddr);
void RecvPing(PktBase* lpPktBase, INET_Addr& peerAddr);
unsigned long m_dwLastPingRecvTime;
};
};
#endif

View File

@@ -0,0 +1,62 @@
// MonitoringSheet.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringSheet.h"
#include ".\monitoringsheet.h"
// CMonitoringSheet
IMPLEMENT_DYNAMIC(CMonitoringSheet, CPropertySheet)
CMonitoringSheet::CMonitoringSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
AddPage(&m_ChattingPage);
}
CMonitoringSheet::CMonitoringSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
AddPage(&m_ChattingPage);
}
CMonitoringSheet::~CMonitoringSheet()
{
}
BEGIN_MESSAGE_MAP(CMonitoringSheet, CPropertySheet)
ON_WM_SIZE()
END_MESSAGE_MAP()
// CMonitoringSheet 메시지 처리기입니다.
BOOL CMonitoringSheet::OnInitDialog()
{
BOOL bResult = CPropertySheet::OnInitDialog();
// 필요없는 버튼 제거
GetDlgItem(IDOK)->ShowWindow(false);
GetDlgItem(IDCANCEL)->ShowWindow(false);
GetDlgItem(IDHELP)->ShowWindow(false);
GetDlgItem(ID_APPLY_NOW)->ShowWindow(false);
return bResult;
}
void CMonitoringSheet::OnSize(UINT nType, int cx, int cy)
{
CPropertySheet::OnSize(nType, cx, cy);
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
if(m_ChattingPage.GetSafeHwnd())
{
CRect rect;
GetClientRect(rect);
m_ChattingPage.MoveWindow(rect);
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "ChattingPage.h"
/** \class CMonitoringSheet
CMonitoringToolDlg에 붙어있는 프로퍼티 시트*/
class CMonitoringSheet : public CPropertySheet
{
DECLARE_DYNAMIC(CMonitoringSheet)
public:
CMonitoringSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
CMonitoringSheet(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
virtual ~CMonitoringSheet();
protected:
DECLARE_MESSAGE_MAP()
virtual BOOL OnInitDialog();
private:
CChattingPage m_ChattingPage; ///< 채팅 모니터링 페이지
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
};

View File

@@ -0,0 +1,264 @@
// MonitoringTool.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringToolSetup.h"
#include "GlobalFunc.h"
#include "ChatServerEventhandler.h"
#include "ChattingPage.h"
#include <Network/ClientNetwork/ClientEventHandler.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Stream/Buffer/Buffer.h>
#include <Log/ServerLog.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMonitoringToolApp
BEGIN_MESSAGE_MAP(CMonitoringToolApp, CWinApp)
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
// CMonitoringToolApp construction
CMonitoringToolApp::CMonitoringToolApp()
: m_DefaultiniFileName(_T("./RylMonitoringToolSetup.ini"))
, m_bIsAuthorized(false)
, m_lpEventHandlerMgr(0)
, m_lpManageServerEventHandler(0)
, m_lpBufferFactory(0)
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CMonitoringToolApp object
CMonitoringToolApp theApp;
// CMonitoringToolApp initialization
BOOL CMonitoringToolApp::InitInstance()
{
m_lpEventHandlerMgr = new ClientNet::CClientEventHandlerMgr;
if(!m_lpEventHandlerMgr) { return FALSE; }
m_lpBufferFactory = new CPoolBufferFactory;
if(!m_lpBufferFactory) { return FALSE; }
InitCommonControls();
CWinApp::InitInstance();
AfxEnableControlContainer();
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
InitServerNameMap();
InitServerIndexMap();
CMonitoringToolDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK) { }
else if (nResponse == IDCANCEL) { }
return FALSE;
}
int CMonitoringToolApp::ExitInstance()
{
delete m_lpEventHandlerMgr;
m_lpEventHandlerMgr = 0;
delete m_lpBufferFactory;
m_lpBufferFactory = 0;
return CWinApp::ExitInstance();
}
/// \brief 서버그룹명 맵 초기화
void CMonitoringToolApp::InitServerNameMap()
{
m_ServerNameMap.clear();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const int MAX_BUFFER = 256;
const char* szSection = _T("SERVER_GROUP_INFO");
char szKey[MAX_BUFFER];
unsigned int nServerGroup;
for(unsigned int nIndex = 0; nIndex < Setup.GetInt(szSection, _T("SERVER_GROUP_NUM")); ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, _T("SERVER_GROUP_INDEX_%02d"), nIndex);
nServerGroup = Setup.GetInt(szSection, szKey, 0xFFFFFFFF);
if(nServerGroup != 0xFFFFFFFF)
{
_snprintf(szKey, MAX_BUFFER, _T("SERVER_GROUP_NAME_%02d"), nIndex);
m_ServerNameMap.insert(ServerNameMap::value_type(nServerGroup, Setup.GetString(szSection, szKey)));
}
}
}
/// \brief 서버그룹명 얻기
/// \param nServerGroup 서버그룹 인덱스
/// \return 서버그룹명
const char* CMonitoringToolApp::GetServerName(unsigned int nServerGroup)
{
ServerNameMap::iterator find = m_ServerNameMap.find(nServerGroup);
if(find != m_ServerNameMap.end())
{
return find->second.c_str();
}
return _T("Tool");
}
/// \brief 서버그룹 인덱스 맵 초기화
void CMonitoringToolApp::InitServerIndexMap()
{
m_ServerIndexMap.clear();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const int MAX_BUFFER = 256;
const char* szSection = _T("SERVER_GROUP_INFO");
char szKey[MAX_BUFFER];
unsigned int nServerGroup;
for(unsigned int nIndex = 0; nIndex < Setup.GetInt(szSection, _T("SERVER_GROUP_NUM")); ++nIndex)
{
_snprintf(szKey, MAX_BUFFER, _T("SERVER_GROUP_INDEX_%02d"), nIndex);
nServerGroup = Setup.GetInt(szSection, szKey, 0xFFFFFFFF);
if(nServerGroup != 0xFFFFFFFF)
{
_snprintf(szKey, MAX_BUFFER, _T("SERVER_GROUP_NAME_%02d"), nIndex);
m_ServerIndexMap.insert(ServerIndexMap::value_type(Setup.GetString(szSection, szKey), nServerGroup));
}
}
}
/// \brief 서버그룹 인덱스 얻기
/// \param strServerName 서버그룹명
/// \return 서버 그룹 인덱스
unsigned int CMonitoringToolApp::GetServerIndex(CString strServerName)
{
ServerIndexMap::iterator find = m_ServerIndexMap.find(strServerName);
if(find != m_ServerIndexMap.end())
{
return find->second;
}
return 100;
}
void CMonitoringToolApp::RegisterManagerHandler(ClientNet::CManagerServerEventHandler* lpHandler)
{
m_lpManageServerEventHandler = lpHandler;
}
void CMonitoringToolApp::RemoveManagerHandler(ClientNet::CManagerServerEventHandler* lpHandler)
{
if(m_lpManageServerEventHandler == lpHandler)
{
m_lpManageServerEventHandler = 0;
}
}
/// \brief 채팅서버 연결 세션 등록
/// \param nServerGroup 채팅서버의 그룹 인덱스
/// \param lpHandler 채팅서버 연결 세션 포인터
void CMonitoringToolApp::RegisterChatHandler(unsigned int nServerGroup,
ClientNet::CChatServerEventHandler* lpHandler)
{
ChatServerHandlerMap::iterator pos = m_ChatHandlerMap.find(nServerGroup);
ChatServerHandlerMap::iterator end = m_ChatHandlerMap.end();
if (pos != end && lpHandler != pos->second)
{
// 이미 존재한다.
pos->second = lpHandler;
}
else
{
m_ChatHandlerMap.insert(ChatServerHandlerMap::value_type(nServerGroup, lpHandler));
}
}
void CMonitoringToolApp::RemoveChatHandler(unsigned int nServerGroup,
ClientNet::CChatServerEventHandler* lpHandler)
{
ChatServerHandlerMap::iterator pos = m_ChatHandlerMap.find(nServerGroup);
ChatServerHandlerMap::iterator end = m_ChatHandlerMap.end();
if (pos != end)
{
m_ChatHandlerMap.erase(pos);
}
}
ClientNet::CChatServerEventHandler* CMonitoringToolApp::GetChatServerHandler(unsigned int nServerGroup)
{
ChatServerHandlerMap::iterator pos = m_ChatHandlerMap.find(nServerGroup);
if (pos != m_ChatHandlerMap.end())
{
return pos->second;
}
return 0;
}
bool CMonitoringToolApp::RegisterWindow(unsigned int nIDD, CWnd* lpWindow)
{
return m_WindowMap.insert(WindowMap::value_type(nIDD, lpWindow)).second;
}
bool CMonitoringToolApp::RemoveWindow(unsigned int nIDD)
{
return 0 != m_WindowMap.erase(nIDD);
}
CWnd* CMonitoringToolApp::GetRegisteredWindow(unsigned int nIDD)
{
WindowMap::iterator find = m_WindowMap.find(nIDD);
if(find != m_WindowMap.end())
{
return find->second;
}
return 0;
}
/// \brief 결과창에 메세지 출력
/// \param szResult 출력할 메세지
void CMonitoringToolApp::ReportResult(const char* szResult)
{
CMonitoringToolDlg* lpDlg =
static_cast<CMonitoringToolDlg*>(theApp.GetRegisteredWindow(IDD_MONITORINGTOOLDLG));
if (NULL != lpDlg)
{
lpDlg->ReportWorkResult(szResult);
}
}

View File

@@ -0,0 +1,112 @@
// MonitoringTool.h : main header file for the PROJECT_NAME application
#pragma once
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
#include "MonitoringToolDlg.h"
#include <map>
#include <string>
/** \mainpage "RylMonitoringTool"
작성일자: 2005-11-10\n
작성자: 임준표\n\n
- RylMonitoringTool: 채팅서버와 연결하여 유저들의 채팅내용을 실시간으로 모니터링\n
※ 간단한 코드의 설명은 생략하였습니다.*/
namespace ClientNet
{
class CManagerServerEventHandler;
class CChatServerEventHandler;
class CClientEventHandlerMgr;
};
class CBufferFactory;
class CCommand;
class CServerLog;
/** \class CMonitoringToolApp
모니터링 툴 메인 클래스*/
class CMonitoringToolApp : public CWinApp
{
public:
CMonitoringToolApp();
virtual BOOL InitInstance();
virtual int ExitInstance();
ClientNet::CClientEventHandlerMgr& GetEventHandlerMgr() { return *m_lpEventHandlerMgr; }
ClientNet::CManagerServerEventHandler* GetManagerHandler() { return m_lpManageServerEventHandler; }
void RegisterManagerHandler(ClientNet::CManagerServerEventHandler* lpHandler);
void RemoveManagerHandler(ClientNet::CManagerServerEventHandler* lpHandler);
ClientNet::CChatServerEventHandler* GetChatServerHandler(unsigned int nServerGroup);
void RegisterChatHandler(unsigned int nServerGroup, ClientNet::CChatServerEventHandler* lpHandler);
void RemoveChatHandler(unsigned int nServerGroup, ClientNet::CChatServerEventHandler* lpHandler);
template<class FnProcess>
bool EnumChatServerHandler(FnProcess fnProcess)
{
ChatServerHandlerMap::iterator pos = m_ChatHandlerMap.begin();
ChatServerHandlerMap::iterator end = m_ChatHandlerMap.end();
for (; pos != end; ++pos)
{
fnProcess(pos->first, pos->second);
}
return true;
}
CWnd* GetRegisteredWindow(unsigned int nIDD);
bool RegisterWindow(unsigned int nIDD, CWnd* lpWindow);
bool RemoveWindow(unsigned int nIDD);
void InitServerNameMap();
void InitServerIndexMap();
const char* GetServerName(unsigned int nServerGroup);
unsigned int GetServerIndex(CString strServerName);
const CString& GetDefaultiniFileName() const { return m_DefaultiniFileName; }
void SetAuthorized(bool bIsAuthorized) { m_bIsAuthorized = bIsAuthorized; }
bool IsAuthorized() { return m_bIsAuthorized; }
void SetLoginedName(const CString& strLoginedName) { m_strLoginedName = strLoginedName; }
const CString& GetLoginedName() { return m_strLoginedName; }
void ReportResult(const char* szResult);
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
private:
bool m_bIsAuthorized;
typedef std::map<unsigned int, ClientNet::CChatServerEventHandler*> ChatServerHandlerMap;
typedef std::map<unsigned int, std::string> ServerNameMap;
typedef std::map<CString, unsigned int> ServerIndexMap;
typedef std::map<unsigned long, CWnd*> WindowMap;
ClientNet::CClientEventHandlerMgr* m_lpEventHandlerMgr;
ClientNet::CManagerServerEventHandler* m_lpManageServerEventHandler; ///< 관리 서버 세션
CBufferFactory* m_lpBufferFactory; ///< 버퍼 Factory
ChatServerHandlerMap m_ChatHandlerMap; ///< Key : 서버 그룹 인덱스 / Value : 채팅서버 세션
WindowMap m_WindowMap;
ServerNameMap m_ServerNameMap; ///< Key : 서버 그룹 인덱스 / Value : 서버 그룹 명
ServerIndexMap m_ServerIndexMap; ///< Key : 서버 그룹 명 / Value : 서버 그룹 인덱스
CString m_DefaultiniFileName;
CString m_strLoginedName;
};
extern CMonitoringToolApp theApp;

View File

@@ -0,0 +1,407 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 한국어 resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_KOR)
#ifdef _WIN32
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
#pragma code_page(949)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
"LANGUAGE 9, 1\r\n"
"#pragma code_page(1252)\r\n"
"#include ""res\\MonitoringTool.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
"#include ""afxres.rc"" // Standard components\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "res\\MonitoringTool.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_CHATTINGPAGE DIALOGEX 0, 0, 559, 411
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
CAPTION "MONITORING"
FONT 9, "MS Shell Dlg", 0, 0, 0x0
BEGIN
LISTBOX IDC_SERVERGROUP_LIST,7,26,73,121,LBS_MULTIPLESEL |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
LISTBOX IDC_CHATTYPE_LIST,101,26,92,121,LBS_MULTIPLESEL |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
CONTROL "",IDC_AUTOSCROLL_CHK,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,366,9,50,8
COMBOBOX IDC_SERVERGROUP_CB,205,364,68,114,CBS_DROPDOWNLIST |
CBS_SORT | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_CHATTYPE_CB,274,364,68,114,CBS_DROPDOWNLIST |
CBS_SORT | WS_VSCROLL | WS_TABSTOP
EDITTEXT IDC_CHATMSG_EDIT,205,378,279,15,ES_AUTOHSCROLL
PUSHBUTTON "",IDC_CHATMSG_SEND_BTN,485,378,66,15
LISTBOX IDC_CHATMONITOR_LIST,200,22,356,319,LBS_OWNERDRAWFIXED |
LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL |
WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,WS_EX_TRANSPARENT
GROUPBOX " ",
IDC_STRING006_STATIC,3,3,194,150,BS_FLAT
LTEXT "",IDC_STRING007_STATIC,11,16,58,8
LTEXT "",IDC_STRING008_STATIC,101,16,74,8
LISTBOX IDC_CONNECTION_LIST,79,26,17,121,LBS_NOINTEGRALHEIGHT |
LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
LTEXT "",IDC_STRING008_STATIC2,274,353,65,8
LTEXT "",IDC_STRING007_STATIC2,205,353,61,8
EDITTEXT IDC_CHATLINES_EDIT,242,7,42,12,ES_CENTER |
ES_AUTOHSCROLL | ES_READONLY
LTEXT " ",IDC_STRING001_STATIC,202,9,36,8
LTEXT "",IDC_STRING002_STATIC,286,9,74,8
PUSHBUTTON "",IDC_DELETECHATMSG_BTN,484,7,71,12,BS_FLAT
PUSHBUTTON "",IDC_CHATLOGFLUSH_BTN,421,7,61,12,BS_FLAT
CONTROL "",IDC_USERSTAT_LIST,"SysListView32",LVS_REPORT |
LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,197,185,127
EDITTEXT IDC_MANAGERSERVER_CON_EDIT,131,168,60,12,ES_CENTER |
ES_AUTOHSCROLL | ES_READONLY
EDITTEXT IDC_TOTALUSERNUM_EDIT,143,326,49,12,ES_CENTER |
ES_AUTOHSCROLL | ES_READONLY
LTEXT "",IDC_STRING012_STATIC,94,328,43,8
GROUPBOX " ",
IDC_STRING009_STATIC,3,160,194,181,BS_FLAT
PUSHBUTTON "",IDC_AUTH_MANAGER_BTN,121,182,71,13,BS_FLAT
LTEXT "",IDC_STRING010_STATIC,35,170,90,8
PUSHBUTTON "",IDC_FLUSH_STATLOG_BTN,58,182,61,13,BS_FLAT
PUSHBUTTON "",IDC_CALL_WHISPER_DLG,344,364,93,12,BS_FLAT
GROUPBOX "",IDC_STATIC,200,345,356,53
GROUPBOX "",IDC_STATIC,4,345,191,53
LTEXT "Static",IDC_LOGINEDNAME_STATIC,9,354,83,8
EDITTEXT IDC_LOGINEDNAME_EDIT,8,367,87,13,ES_CENTER |
ES_AUTOHSCROLL | ES_READONLY
CONTROL "Check1",IDC_GMLOGINED_CHK,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,9,384,85,10
CONTROL "Check1",IDC_LANGTYPE_CHK,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,103,384,85,10
END
IDD_MONITORINGTOOLDLG DIALOGEX 0, 0, 575, 408
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU |
WS_THICKFRAME
EXSTYLE WS_EX_OVERLAPPEDWINDOW | WS_EX_STATICEDGE | WS_EX_APPWINDOW
CAPTION "ROW Monitoring Tool"
FONT 9, "MS Shell Dlg", 0, 0, 0x0
BEGIN
CONTROL "",IDC_SHEETHOLDER_PIC,"Static",SS_BLACKFRAME,3,2,569,
356
PUSHBUTTON "",IDC_AUTH_BTN,458,361,114,14
LISTBOX IDC_REPORT_LIST,101,364,352,39,LBS_HASSTRINGS |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
LTEXT "",IDC_STRING018_STATIC,11,364,84,8
PUSHBUTTON "Filter Dialog",IDC_FILTER_BTN,458,376,114,14
PUSHBUTTON "GMReport Dialog",IDC_REPORT_BTN,458,391,114,14
END
IDD_LOGINDLG DIALOGEX 0, 0, 147, 67
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "User Login"
FONT 9, "MS Shell Dlg", 0, 0, 0x0
BEGIN
EDITTEXT IDC_LOGIN_ID_EDIT,60,7,78,13,ES_AUTOHSCROLL
EDITTEXT IDC_LOGIN_PASS_EDIT,60,27,78,13,ES_PASSWORD |
ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDC_LOGIN_BTN,12,48,50,13
PUSHBUTTON "CANCEL",IDCANCEL,84,48,50,13
LTEXT "ID:",IDC_STATIC,6,11,10,8
LTEXT "PASSWORD:",IDC_STATIC,6,31,40,8
END
IDD_WHISPERDLG DIALOGEX 0, 0, 488, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP |
WS_CAPTION | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
LISTBOX IDC_WHISPER_OUTPUT,4,16,480,246,LBS_MULTIPLESEL |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
CONTROL "Send By UID",IDC_SENDBYUID_CHK,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,84,276,55,10
EDITTEXT IDC_WHISPER_INPUT,4,290,412,32,ES_MULTILINE
PUSHBUTTON "BTN",IDC_WHISPER_SEND,419,290,65,32
LTEXT "Static",IDC_WHISPER_TITLE,83,4,401,8
LTEXT "Static",IDC_WHISPER_TITLE_STATIC,4,4,56,8
LTEXT "Static",IDC_WHISPER_TARGET_STATIC,7,264,130,8
EDITTEXT IDC_WHISPER_TARGET,5,275,75,12,ES_AUTOHSCROLL
EDITTEXT IDC_WHIS_SENDER_EDIT,399,275,85,12,ES_CENTER |
ES_AUTOHSCROLL | ES_READONLY
LTEXT "Static",IDC_WHISPER_LOGINEDNAME_STATIC,399,265,85,8
LTEXT "Static",IDC_PACKET_TIME,151,272,174,8
END
IDD_FILTERDIALOG DIALOGEX 0, 0, 344, 265
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Filter User "
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LISTBOX IDC_FILTERLIST,0,22,337,236,LBS_OWNERDRAWFIXED |
LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL |
WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,WS_EX_TRANSPARENT
PUSHBUTTON "Save",IDC_SAVEBUTTON,0,0,50,14,0,WS_EX_CLIENTEDGE
PUSHBUTTON "FilterReload",IDC_SAVEBUTTON2,287,0,50,14,0,
WS_EX_CLIENTEDGE
PUSHBUTTON "Clear",IDC_SAVEBUTTON3,51,0,50,14,0,WS_EX_CLIENTEDGE
END
IDD_GMREPORTDIALOG DIALOGEX 0, 0, 344, 265
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "GM Report"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LISTBOX IDC_REPORTLIST,0,22,337,236,LBS_OWNERDRAWFIXED |
LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL |
WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,WS_EX_TRANSPARENT
PUSHBUTTON "Save",IDC_SAVEBUTTON,0,0,50,14,0,WS_EX_CLIENTEDGE
PUSHBUTTON "Clear",IDC_SAVEBUTTON3,51,0,50,14,0,WS_EX_CLIENTEDGE
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_CHATTINGPAGE, DIALOG
BEGIN
LEFTMARGIN, 3
RIGHTMARGIN, 556
TOPMARGIN, 3
BOTTOMMARGIN, 408
END
IDD_MONITORINGTOOLDLG, DIALOG
BEGIN
LEFTMARGIN, 3
RIGHTMARGIN, 572
TOPMARGIN, 2
BOTTOMMARGIN, 405
END
IDD_LOGINDLG, DIALOG
BEGIN
LEFTMARGIN, 2
RIGHTMARGIN, 145
TOPMARGIN, 2
BOTTOMMARGIN, 65
END
IDD_WHISPERDLG, DIALOG
BEGIN
LEFTMARGIN, 4
RIGHTMARGIN, 484
TOPMARGIN, 4
BOTTOMMARGIN, 322
END
IDD_FILTERDIALOG, DIALOG
BEGIN
RIGHTMARGIN, 337
BOTTOMMARGIN, 258
END
IDD_GMREPORTDIALOG, DIALOG
BEGIN
RIGHTMARGIN, 337
BOTTOMMARGIN, 258
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_CONTEXTMENU MENU
BEGIN
POPUP "CHATMONITOR"
BEGIN
MENUITEM "Export to File(&E)", ID_CHATMONITOR_EXPORTTOFILE
MENUITEM SEPARATOR
MENUITEM "Select All(&A)", ID_CHATMONITOR_SELECTALL
END
END
#endif // 한국어 resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// 영어(미국) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 224, 45
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "About MonitoringTool"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,11,20,20
LTEXT "MonitoringTool (ver 1010)",IDC_STATIC,40,10,110,8,
SS_NOPREFIX
LTEXT "Copyright (C) 2008 Youxiland.",IDC_STATIC,40,23,119,8
DEFPUSHBUTTON "OK",IDOK,156,9,60,15,WS_GROUP
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 4
RIGHTMARGIN, 220
TOPMARGIN, 4
BOTTOMMARGIN, 41
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,1,0
PRODUCTVERSION 1,0,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "Youxiland"
VALUE "FileDescription", "ROW MonitoringTool"
VALUE "FileVersion", "1.0.1.0"
VALUE "InternalName", "MonitoringTool.exe"
VALUE "LegalCopyright", "(c) Youxiland. All rights reserved."
VALUE "OriginalFilename", "MonitoringTool.exe"
VALUE "ProductName", "MonitoringTool"
VALUE "ProductVersion", "1.0.1.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_ABOUTBOX "&About MonitoringTool..."
END
#endif // 영어(미국) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#pragma code_page(1252)
#include "res\MonitoringTool.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,306 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="RylMonitoringTool"
ProjectGUID="{A58675B7-A73C-4DCD-A533-47684E64275A}"
Keyword="MFCProj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="./;../;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../../RylServerProject/RylGameLibrary;../ManageLibrary"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
TreatWChar_tAsBuiltInType="TRUE"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
SubSystem="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="FALSE"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
AdditionalIncludeDirectories="$(IntDir)"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories="./;../;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../../RylServerProject/RylGameLibrary;../ManageLibrary"
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
MinimalRebuild="FALSE"
RuntimeLibrary="0"
TreatWChar_tAsBuiltInType="TRUE"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/$(ProjectName).exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="FALSE"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
AdditionalIncludeDirectories="$(IntDir)"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Dialog"
Filter="">
<File
RelativePath=".\FilterUserDialog.cpp">
</File>
<File
RelativePath=".\FilterUserDialog.h">
</File>
<File
RelativePath=".\GMReportDialog.cpp">
</File>
<File
RelativePath=".\GMReportDialog.h">
</File>
<File
RelativePath=".\LoginDlg.cpp">
</File>
<File
RelativePath=".\LoginDlg.h">
</File>
<File
RelativePath=".\MonitoringToolDlg.cpp">
</File>
<File
RelativePath=".\MonitoringToolDlg.h">
</File>
<File
RelativePath=".\WhisperDlg.cpp">
</File>
<File
RelativePath=".\WhisperDlg.h">
</File>
</Filter>
<Filter
Name="PropertySheet"
Filter="">
<File
RelativePath=".\MonitoringSheet.cpp">
</File>
<File
RelativePath=".\MonitoringSheet.h">
</File>
<Filter
Name="Page"
Filter="">
<File
RelativePath=".\ChattingPage.cpp">
</File>
<File
RelativePath=".\ChattingPage.h">
</File>
</Filter>
</Filter>
<Filter
Name="resource"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
<File
RelativePath=".\res\MonitoringTool.ico">
</File>
<File
RelativePath=".\MonitoringTool.rc">
</File>
<File
RelativePath=".\res\MonitoringTool.rc2">
</File>
</Filter>
<Filter
Name="CustomControls"
Filter="">
<Filter
Name="XListBox"
Filter="">
<File
RelativePath=".\Clipboard.cpp">
</File>
<File
RelativePath=".\Clipboard.h">
</File>
<File
RelativePath=".\ColorPickerCB.cpp">
</File>
<File
RelativePath=".\ColorPickerCB.h">
</File>
<File
RelativePath=".\XListBox.cpp">
</File>
<File
RelativePath=".\XListBox.h">
</File>
</Filter>
</Filter>
<Filter
Name="Utility"
Filter="">
<File
RelativePath=".\GlobalFunc.cpp">
</File>
<File
RelativePath=".\GlobalFunc.h">
</File>
<File
RelativePath=".\MonitoringToolLog.cpp">
</File>
<File
RelativePath=".\MonitoringToolLog.h">
</File>
<File
RelativePath=".\MonitoringToolSetup.cpp">
</File>
<File
RelativePath=".\MonitoringToolSetup.h">
</File>
<File
RelativePath=".\StringFilter.cpp">
</File>
<File
RelativePath=".\StringFilter.h">
</File>
</Filter>
<Filter
Name="Network"
Filter="">
<File
RelativePath=".\ChatServerEventHandler.cpp">
</File>
<File
RelativePath=".\ChatServerEventHandler.h">
</File>
<File
RelativePath=".\ManagerServerEventHandler.cpp">
</File>
<File
RelativePath=".\ManagerServerEventHandler.h">
</File>
</Filter>
<File
RelativePath=".\MonitoringTool.cpp">
</File>
<File
RelativePath=".\MonitoringTool.h">
</File>
<File
RelativePath=".\res\MonitoringTool.manifest">
</File>
<File
RelativePath=".\ReadMe.txt">
</File>
<File
RelativePath=".\Resource.h">
</File>
<File
RelativePath=".\stdafx.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
<File
RelativePath=".\stdafx.h">
</File>
</Files>
<Globals>
<Global
Name="RESOURCE_FILE"
Value="MonitoringTool.rc"/>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,290 @@
// MonitoringToolDlg.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringToolDlg.h"
#include "LoginDlg.h"
#include "MonitoringSheet.h"
#include "ChatServerEventHandler.h"
#include "ManagerServerEventHandler.h"
#include "GlobalFunc.h"
#include "MonitoringToolLog.h"
#include <Network/ClientNetwork/SessionMgr.h>
#include <mmsystem.h>
#include ".\monitoringtooldlg.h"
static UINT_PTR IID_PROCESS_SOCKET = 1;
static UINT_PTR IID_USERSTAT_CHECK = 2; ///< 동시 접속 유저수 정보 갱신 메세지ID
static UINT_PTR IID_CONNECTION_CHECK = 3; ///< 채팅서버와 관리서버 연결상태 갱신 메세지ID
static UINT_PTR IID_PING_CHECK = 4; ///< 핑 체크 메세지ID
const int MAXIMUM_PING_WAIT_TIME = 1000 * 60 * 2; ///< 최대 핑 체크 주기(2분이상 핑 패킷을 받지 못하면 강제 접속 종료)
class CProcessChaServerHandlerPing
{
public:
CProcessChaServerHandlerPing(unsigned long dwCurrentTime)
: m_dwCurrentTime(dwCurrentTime)
{
}
void operator() (unsigned int nServerID, ClientNet::CChatServerEventHandler* lpHandler)
{
if (MAXIMUM_PING_WAIT_TIME < m_dwCurrentTime - lpHandler->GetLastPingRecvTime())
{
theApp.GetEventHandlerMgr().Close(lpHandler);
}
}
private:
unsigned long m_dwCurrentTime;
};
void CALLBACK Process(HWND hWnd, UINT nMsg, UINT_PTR nTimerID, DWORD dwTime)
{
if(IID_PROCESS_SOCKET == nTimerID)
{
theApp.GetEventHandlerMgr().HandleEvents(1000);
}
else if(IID_CONNECTION_CHECK == nTimerID)
{
CChattingPage* lpChattingPage =
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
if(NULL != lpChattingPage)
{
// 채팅서버 연결 상태 표시
SetConnectionListBox(lpChattingPage->m_ctrlConnectionList);
// 관리서버 연결 상태 표시
lpChattingPage->SetManagerServerConnection();
}
}
else if(IID_PING_CHECK == nTimerID)
{
// 일정 시간동안 Ping이 오지 않으면 접속을 해제한다.
unsigned long dwCurrentTime = timeGetTime();
ClientNet::CManagerServerEventHandler* lpManageServerEventHandler = theApp.GetManagerHandler();
if (0 != lpManageServerEventHandler &&
MAXIMUM_PING_WAIT_TIME < dwCurrentTime - lpManageServerEventHandler->GetLastPingRecvTime())
{
theApp.GetEventHandlerMgr().Close(lpManageServerEventHandler);
}
theApp.EnumChatServerHandler(CProcessChaServerHandlerPing(dwCurrentTime));
}
else if(IID_USERSTAT_CHECK == nTimerID)
{
CChattingPage* lpChattingPage =
static_cast<CChattingPage*>(theApp.GetRegisteredWindow(IDD_CHATTINGPAGE));
if(NULL != lpChattingPage)
{
lpChattingPage->SetUserStat();
CMonitoringToolLog::GetInstance().WriteUserStatLog();
}
}
}
// CMonitoringToolDlg 대화 상자입니다.
IMPLEMENT_DYNAMIC(CMonitoringToolDlg, CDialog)
CMonitoringToolDlg::CMonitoringToolDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMonitoringToolDlg::IDD, pParent)
{
theApp.RegisterWindow(IDD_MONITORINGTOOLDLG, static_cast<CWnd*>(this));
}
CMonitoringToolDlg::~CMonitoringToolDlg()
{
if(NULL != m_pMonitoringSheet)
{
delete m_pMonitoringSheet;
}
if(NULL != m_pFilterUser)
{
delete m_pFilterUser;
}
if(NULL != m_pGMReport)
{
delete m_pGMReport;
}
theApp.RemoveWindow(IDD_MONITORINGTOOLDLG);
}
void CMonitoringToolDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_REPORT_LIST, m_ctrlReportList);
}
BEGIN_MESSAGE_MAP(CMonitoringToolDlg, CDialog)
ON_BN_CLICKED(IDC_AUTH_BTN, OnBnClickedAuthBtn)
ON_MESSAGE(WM_SHOW_MSGBOX, OnShowMessageBox)
ON_WM_SIZE()
ON_WM_SIZING()
ON_BN_CLICKED(IDC_FILTER_BTN, OnBnClickedFilterBtn)
ON_BN_CLICKED(IDC_REPORT_BTN, OnBnClickedReportBtn)
END_MESSAGE_MAP()
// CMonitoringToolDlg 메시지 처리기입니다.
BOOL CMonitoringToolDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetTimer(IID_PROCESS_SOCKET, 200, Process);
SetTimer(IID_USERSTAT_CHECK, 1500, Process);
SetTimer(IID_CONNECTION_CHECK, 1000, Process);
SetTimer(IID_PING_CHECK, 9000, Process);
CWnd* pwndPropSheetHolder = GetDlgItem(IDC_SHEETHOLDER_PIC);
// WS_EX_CONTROLPARENT 속성을 주지 않으면 무한 루프도는 경우가 있음
pwndPropSheetHolder->ModifyStyleEx(0, WS_EX_CONTROLPARENT);
CRect rectPropSheet; pwndPropSheetHolder->GetWindowRect(rectPropSheet);
m_pMonitoringSheet = new CMonitoringSheet(_T("Chatting"), pwndPropSheetHolder);
if(!m_pMonitoringSheet->Create(pwndPropSheetHolder, WS_CHILD | WS_VISIBLE, 0))
{
delete m_pMonitoringSheet;
m_pMonitoringSheet = NULL;
return FALSE;
}
m_pMonitoringSheet->ModifyStyleEx(0, WS_EX_CONTROLPARENT); // 위와 같은 이유
m_pMonitoringSheet->SetWindowPos(NULL, 0, 0, rectPropSheet.Width(), rectPropSheet.Height(),
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
SetDlgItemText(IDC_STRING018_STATIC, GetMyINIString("LOCAL_STRING", "STRING_018"));
SetDlgItemText(IDC_AUTH_BTN, GetMyINIString("LOCAL_STRING", "STRING_019"));
// 관리서버, 채팅서버 연결
ClientNet::CManagerServerEventHandler::Connect();
ClientNet::CChatServerEventHandler::Connect();
m_pFilterUser = new CFilterUserDialog(this);
m_pFilterUser->Create(IDD_FILTERDIALOG);
m_pGMReport = new CGMReportDialog(this);
m_pGMReport->Create(IDD_GMREPORTDIALOG);
return TRUE;
}
void CMonitoringToolDlg::OnBnClickedAuthBtn()
{
CLoginDlg dlg(CLoginDlg::CHAT_SERVER);
dlg.DoModal();
}
void CMonitoringToolDlg::ReportWorkResult(const char* szMsg)
{
m_ctrlReportList.InsertString(m_ctrlReportList.GetCount(), szMsg);
m_ctrlReportList.SetTopIndex(m_ctrlReportList.GetCount() - 4);
}
LRESULT CMonitoringToolDlg::OnShowMessageBox(WPARAM wParam, LPARAM lParam)
{
/*
switch(wParam)
{
case MSGBOX_MANAGER_DISCONNECTED:
// 관리서버와 연결 끊겼을때, 메시지박스 표시 : 관리서버와 연결이 끊겼습니다.
AfxMessageBox(GetMyINIString("LOCAL_STRING", "STRING_020"), MB_OK);z
break;
}
*/
return 0;
}
void CMonitoringToolDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
CRect rect, rectc;
GetClientRect(rect);
CWnd* pwndStatic = GetDlgItem(IDC_STRING018_STATIC);
pwndStatic->GetWindowRect(rectc);
pwndStatic->MoveWindow(rect.left+10, rect.bottom-70, rectc.Width(), rectc.Height());
CWnd* pwndAuth = GetDlgItem(IDC_AUTH_BTN);
pwndAuth->GetWindowRect(rectc);
pwndAuth->MoveWindow(rect.right-rectc.Width()-10, rect.bottom-80, rectc.Width(), rectc.Height());
CWnd* pwndFilter = GetDlgItem(IDC_FILTER_BTN);
pwndFilter->GetWindowRect(rectc);
pwndFilter->MoveWindow(rect.right-rectc.Width()-10, rect.bottom-55, rectc.Width(), rectc.Height());
CWnd* pwndReport = GetDlgItem(IDC_REPORT_BTN);
pwndReport->GetWindowRect(rectc);
pwndReport->MoveWindow(rect.right-rectc.Width()-10, rect.bottom-30, rectc.Width(), rectc.Height());
m_ctrlReportList.GetWindowRect(rectc);
m_ctrlReportList.MoveWindow(rect.left+170, rect.bottom-70, rect.Width()-450, rectc.Height());
CWnd* pwndPropSheetHolder = GetDlgItem(IDC_SHEETHOLDER_PIC);
pwndPropSheetHolder->GetWindowRect(rectc);
pwndPropSheetHolder->MoveWindow(rect.left+10, rect.top+10, rect.Width()-20, rect.Height()-95);
if(m_pMonitoringSheet)
{
pwndPropSheetHolder->GetClientRect(rectc);
m_pMonitoringSheet->MoveWindow(rectc);
}
// m_pMonitoringSheet->SetWindowPos(NULL, 0, 0, rectPropSheet.Width(), rectPropSheet.Height(),
/*
m_pMonitoringSheet = new CMonitoringSheet(_T("Chatting"), pwndPropSheetHolder);
if(!m_pMonitoringSheet->Create(pwndPropSheetHolder, WS_CHILD | WS_VISIBLE, 0))
{
delete m_pMonitoringSheet;
m_pMonitoringSheet = NULL;
return FALSE;
}
m_pMonitoringSheet->ModifyStyleEx(0, WS_EX_CONTROLPARENT); // 위와 같은 이유
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
SetDlgItemText(IDC_STRING018_STATIC, GetMyINIString("LOCAL_STRING", "STRING_018"));
SetDlgItemText(IDC_AUTH_BTN, GetMyINIString("LOCAL_STRING", "STRING_019"));
*/
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
}
void CMonitoringToolDlg::OnBnClickedFilterBtn()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if(m_pFilterUser)
{
if(m_pFilterUser->IsWindowVisible())
m_pFilterUser->ShowWindow(SW_HIDE);
else
m_pFilterUser->ShowWindow(SW_SHOW);
}
}
void CMonitoringToolDlg::OnBnClickedReportBtn()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if(m_pGMReport)
{
if(m_pGMReport->IsWindowVisible())
m_pGMReport->ShowWindow(SW_HIDE);
else
m_pGMReport->ShowWindow(SW_SHOW);
}
}

View File

@@ -0,0 +1,51 @@
#pragma once
#include "afxwin.h"
#include "FilterUserDialog.h"
#include "GMReportDialog.h"
// forword decl.
class CMonitoringSheet;
#define WM_SHOW_MSGBOX (WM_USER + 1)
enum MsgBoxType
{
MSGBOX_MANAGER_DISCONNECTED
};
/** \class CMonitoringToolDlg
모니터링툴 메인 다이얼로그*/
class CMonitoringToolDlg : public CDialog
{
DECLARE_DYNAMIC(CMonitoringToolDlg)
public:
CMonitoringToolDlg(CWnd* pParent = NULL); // 표준 생성자입니다.
virtual ~CMonitoringToolDlg();
// 대화 상자 데이터입니다.
enum { IDD = IDD_MONITORINGTOOLDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
DECLARE_MESSAGE_MAP()
virtual BOOL OnInitDialog();
private:
CListBox m_ctrlReportList; ///< 작업 결과 표시창
afx_msg void OnBnClickedAuthBtn();
afx_msg LRESULT OnShowMessageBox(WPARAM wParam, LPARAM lParam);
public:
CMonitoringSheet* m_pMonitoringSheet;
CFilterUserDialog* m_pFilterUser;
CGMReportDialog* m_pGMReport;
void ReportWorkResult(const char* szMsg);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnBnClickedFilterBtn();
afx_msg void OnBnClickedReportBtn();
};

View File

@@ -0,0 +1,146 @@
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringToolLog.h"
#include "MonitoringToolSetup.h"
#include <Log/ServerLog.h>
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <UserManage/UserStatistics.h>
#include <Utility/Setup/ServerSetup.h>
CServerLog g_ChattingLog("ChatLog", 0);
CServerLog g_UserStatLog("UserStatLog", 0);
CMonitoringToolLog::CMonitoringToolLog()
{
}
CMonitoringToolLog::~CMonitoringToolLog()
{
}
/// \brief 채팅 패킷을 파싱하여 로그로 출력
/// \param lpChatData 채팅 패킷
bool CMonitoringToolLog::WriteChatLog(ChatToolPkt::ChatDataSend* lpChatData)
{
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
SERVER_ID serverID;
serverID.dwID = lpChatData->m_dwServerID;
char strRecvMsg[UCHAR_MAX * 2];
memcpy(strRecvMsg, reinterpret_cast<char*>(lpChatData + 1), lpChatData->m_cChatMsgLen);
strRecvMsg[lpChatData->m_cChatMsgLen] = 0;
if(lpChatData->m_cChatType == PktChat::DICE)
{
g_ChattingLog.Log("[%04d-%02d-%02d %02d:%02d:%02d]"
"[ServerID:0x%08x][Group:%-15s][Zone:%2d][CH:%2d][X:%4d][Z:%4d][UID:%10d][CID:%10d][Type:%2d][S:%-15s][T:%-15s][주사위:%s]\r\n",
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
lpChatData->m_dwServerID, theApp.GetServerName((unsigned int)serverID.GetGroup()), serverID.GetZone(), serverID.GetChannel(),
lpChatData->m_usXPos, lpChatData->m_usZPos, lpChatData->m_dwUID, lpChatData->m_dwCID, lpChatData->m_cChatType + 1,
lpChatData->m_szSenderName, lpChatData->m_szTargetName, strRecvMsg);
}
else
{
g_ChattingLog.Log("[%04d-%02d-%02d %02d:%02d:%02d]"
"[ServerID:0x%08x][Group:%-15s][Zone:%2d][CH:%2d][X:%4d][Z:%4d][UID:%10d][CID:%10d][Type:%2d][S:%-15s][T:%-15s][%s]\r\n",
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
lpChatData->m_dwServerID, theApp.GetServerName((unsigned int)serverID.GetGroup()), serverID.GetZone(), serverID.GetChannel(),
lpChatData->m_usXPos, lpChatData->m_usZPos, lpChatData->m_dwUID, lpChatData->m_dwCID, lpChatData->m_cChatType + 1,
lpChatData->m_szSenderName, lpChatData->m_szTargetName, strRecvMsg);
}
return true;
}
bool CMonitoringToolLog::WriteAdminLog(unsigned char cChatType, unsigned char* szGMName, unsigned char* szUserName, unsigned char* strRecvMsg)
{
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
g_ChattingLog.Log("[%04d-%02d-%02d %02d:%02d:%02d]"
"[ServerID:0x%08x][Group:%-15s][Zone:%2d][CH:%2d][X:%4d][Z:%4d][UID:%10d][CID:%10d][Type:%2d][S:%-15s][T:%-15s][%s]\r\n",
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
0, "Tool", 0, 0, 0, 0, 0, 0, cChatType,
szGMName, szUserName, strRecvMsg);
return true;
}
/// \brief 동시 접속자 정보를 로그로 출력
/// \note 관리서버로부터 동접정보를 전달받음
bool CMonitoringToolLog::WriteUserStatLog()
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const unsigned int nMaxZone = Setup.GetInt(_T("ZONE_INFO"), _T("ZONE_NUM"), 0);
const unsigned int nMaxGroup = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"), 0);
const unsigned int nMaxChannel = Setup.GetInt(_T("CHANNEL_INFO"), _T("CHANNEL_NUM"), 0);
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
char szKey[MAX_PATH];
CString strLog;
for (unsigned int nIndex = 0; nIndex < nMaxGroup; ++nIndex)
{
strLog.AppendFormat(_T("%04d-%02d-%02d %02d:%02d:%02d"),
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
SERVER_ID serverID;
serverID.dwID = 0;
serverID.sID.Type = CServerSetup::GameServer;
_snprintf(szKey, MAX_PATH, _T("SERVER_GROUP_INDEX_%02d"), nIndex);
serverID.sID.Group = Setup.GetInt(_T("SERVER_GROUP_INFO"), szKey, 100);
strLog.AppendFormat(_T("\t%02d"), serverID.GetGroup());
for (unsigned int nIdx = 0; nIdx < nMaxZone; ++nIdx)
{
for (unsigned int nCH = 0; nCH < nMaxChannel; ++nCH)
{
_snprintf(szKey, MAX_PATH, _T("ZONE_INDEX_%02d"), nIdx);
serverID.sID.ID = Setup.GetInt(_T("ZONE_INFO"), szKey, 100);
serverID.sID.Channel = nCH;
strLog.AppendFormat(_T("\t%4d"), CUserStatistics::GetInstance().GetUserNum(serverID.dwID));
}
}
strLog.Append(_T("\r\n"));
g_UserStatLog.Log(strLog);
}
return true;
}
/// \brief 동접로그의 컬럼명을 출력
/// \param strLog 컬럼명(예: WriteTime GroupIndex Z:01 C: 01 Z02: C:01)
/// \note 셋업에따라 컬럼명이 달라지며 로그 출력시 처음 한번만 호출된다.
bool CMonitoringToolLog::WriteUserStatLog(const CString& strLog)
{
g_UserStatLog.Log(strLog);
return true;
}
/// \brief 버퍼에 누적된 채팅로그를 출력
void CMonitoringToolLog::FlushChatLog()
{
g_ChattingLog.Flush();
}
/// \brief 버퍼에 누적된 동접로그를 출력
void CMonitoringToolLog::FlushStatLog()
{
g_UserStatLog.Flush();
}

View File

@@ -0,0 +1,27 @@
#ifndef _GAMA_NETWORK_MONITORING_TOOL_CHAT_LOG_H_
#define _GAMA_NETWORK_MONITORING_TOOL_CHAT_LOG_H_
#include <Pattern/Singleton.h>
#include <Network/Packet/ChatToolPacketCmd.h>
/** \class CMonitoringToolLog
¸ð´ÏÅ͸µ Åø ·Î±× Ŭ·¡½º*/
class CMonitoringToolLog : public CStaticSingleton<CMonitoringToolLog>
{
public:
CMonitoringToolLog();
~CMonitoringToolLog();
bool WriteChatLog(ChatToolPkt::ChatDataSend* lpChatData);
bool WriteAdminLog(unsigned char cChatType, unsigned char* szGMName, unsigned char* szUserName, unsigned char* strRecvMsg);
bool WriteUserStatLog();
bool WriteUserStatLog(const CString& strLog);
void FlushChatLog();
void FlushStatLog();
};
#endif

View File

@@ -0,0 +1,15 @@
#include "stdafx.h"
#include "MonitoringToolSetup.h"
CMonitoringToolSetup::CMonitoringToolSetup(const char* szFileName)
: Registry::CSetupFile(szFileName)
{
}
CMonitoringToolSetup& CMonitoringToolSetup::GetInstance()
{
static CMonitoringToolSetup setup("./RylMonitoringToolSetup.ini");
return setup;
}

View File

@@ -0,0 +1,17 @@
#ifndef _GAMA_NETWORK_MONITORING_TOOL_SETUP_H_
#define _GAMA_NETWORK_MONITORING_TOOL_SETUP_H_
#include <Utility/Registry/RegFunctions.h>
/** \class CMonitoringToolSetup
모니터링 툴 셋업 클래스*/
class CMonitoringToolSetup : public Registry::CSetupFile
{
public:
CMonitoringToolSetup(const char* szFileName);
static CMonitoringToolSetup& GetInstance();
};
#endif

View File

@@ -0,0 +1,94 @@
================================================================================
MICROSOFT FOUNDATION CLASS LIBRARY : MonitoringTool Project Overview
===============================================================================
The application wizard has created this MonitoringTool application for
you. This application not only demonstrates the basics of using the Microsoft
Foundation Classes but is also a starting point for writing your application.
This file contains a summary of what you will find in each of the files that
make up your MonitoringTool application.
MonitoringTool.vcproj
This is the main project file for VC++ projects generated using an application wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
application wizard.
MonitoringTool.h
This is the main header file for the application. It includes other
project specific headers (including Resource.h) and declares the
CMonitoringToolApp application class.
MonitoringTool.cpp
This is the main application source file that contains the application
class CMonitoringToolApp.
MonitoringTool.rc
This is a listing of all of the Microsoft Windows resources that the
program uses. It includes the icons, bitmaps, and cursors that are stored
in the RES subdirectory. This file can be directly edited in Microsoft
Visual C++. Your project resources are in 1033.
res\MonitoringTool.ico
This is an icon file, which is used as the application's icon. This
icon is included by the main resource file MonitoringTool.rc.
res\MonitoringTool.rc2
This file contains resources that are not edited by Microsoft
Visual C++. You should place all resources not editable by
the resource editor in this file.
/////////////////////////////////////////////////////////////////////////////
The application wizard creates one dialog class:
MonitoringToolDlg.h, MonitoringToolDlg.cpp - the dialog
These files contain your CMonitoringToolDlg class. This class defines
the behavior of your application's main dialog. The dialog's template is
in MonitoringTool.rc, which can be edited in Microsoft Visual C++.
/////////////////////////////////////////////////////////////////////////////
Other Features:
ActiveX Controls
The application includes support to use ActiveX controls.
Printing and Print Preview support
The application wizard has generated code to handle the print, print setup, and print preview
commands by calling member functions in the CView class from the MFC library.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named MonitoringTool.pch and a precompiled types file named StdAfx.obj.
Resource.h
This is the standard header file, which defines new resource IDs.
Microsoft Visual C++ reads and updates this file.
MonitoringTool.manifest
Application manifest files are used by Windows XP to describe an applications
dependency on specific versions of Side-by-Side assemblies. The loader uses this
information to load the appropriate assembly from the assembly cache or private
from the application. The Application manifest maybe included for redistribution
as an external .manifest file that is installed in the same folder as the application
executable or it may be included in the executable in the form of a resource.
/////////////////////////////////////////////////////////////////////////////
Other notes:
The application wizard uses "TODO:" to indicate parts of the source code you
should add to or customize.
If your application uses MFC in a shared DLL, and your application is in a
language other than the operating system's current language, you will need
to copy the corresponding localized resources MFC70XXX.DLL from the Microsoft
Visual C++ CD-ROM under the Win\System directory to your computer's system or
system32 directory, and rename it to be MFCLOC.DLL. ("XXX" stands for the
language abbreviation. For example, MFC70DEU.DLL contains resources
translated to German.) If you don't do this, some of the UI elements of
your application will remain in the language of the operating system.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,104 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by MonitoringTool.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_CHATTINGPAGE 103
#define IDD_MONITORINGTOOLDLG 104
#define IDD_LOGINDLG 105
#define IDD_WHISPERDLG 107
#define IDR_MAINFRAME 128
#define IDR_CONTEXTMENU 129
#define IDD_FILTERDIALOG 130
#define IDD_GMREPORTDIALOG 131
#define IDC_SHEETHOLDER_PIC 1001
#define IDC_CHATMONITOR_LIST 1002
#define IDC_CHATTYPE_CB 1004
#define IDC_LOGIN_PASS_EDIT 1006
#define IDC_CHATMSG_SEND_BTN 1006
#define IDC_SERVERGROUP_LIST 1007
#define IDC_CHATTYPE_LIST 1008
#define IDC_SERVERGROUP_CB 1009
#define IDC_CHAT_ADMIN_CB 1010
#define IDC_AUTH_BTN 1011
#define IDC_CHATMSG_SEND_BTN2 1011
#define IDC_LOGIN_ID_EDIT 1012
#define IDC_LOGIN_BTN 1013
#define IDC_FILTER_BTN 1013
#define IDC_REPORT_BTN 1014
#define IDC_CONNECTION_LIST 1015
#define IDC_CHAT_TARGETNAME_EDIT 1016
#define IDC_CHATMSG_EDIT 1017
#define IDC_WHISPER_MSG_EDIT 1018
#define IDC_AUTOSCROLL_CHK 1019
#define IDC_DELETECHATMSG_BTN 1020
#define IDC_CHATLINES_EDIT 1021
#define IDC_CHATLOGFLUSH_BTN 1022
#define IDC_USERSTAT_LIST 1031
#define IDC_MANAGERSERVER_CON_EDIT 1032
#define IDC_TOTALUSERNUM_EDIT 1033
#define IDC_AUTH_MANAGER_BTN 1034
#define IDC_MANAGERSERVER_CON_EDIT2 1035
#define IDC_MANAGERSERVER_AUTH_EDIT 1035
#define IDC_REPORT_LIST 1036
#define IDC_FLUSH_STATLOG_BTN 1036
#define IDC_STRING001_STATIC 1037
#define IDC_STRING002_STATIC 1038
#define IDC_STRING006_STATIC 1039
#define IDC_STRING007_STATIC 1040
#define IDC_STRING008_STATIC 1041
#define IDC_STRING009_STATIC 1042
#define IDC_STRING010_STATIC 1043
#define IDC_STRING012_STATIC 1044
#define IDC_STRING014_STATIC 1045
#define IDC_STRING007_STATIC2 1046
#define IDC_STRING008_STATIC2 1047
#define IDC_STRING015_STATIC 1048
#define IDC_STRING016_STATIC 1049
#define IDC_STRING018_STATIC 1050
#define IDC_LIST1 1052
#define IDC_WHISPER_MSG_LIST 1052
#define IDC_WHISPER_OUTPUT 1052
#define IDC_FILTERLIST 1052
#define IDC_NOTIFY_WHISPER_EDIT 1053
#define IDC_BUTTON1 1054
#define IDC_BTN_TEST_MSGBOX 1054
#define IDC_CALL_WHISPER_DLG 1054
#define IDC_SAVEBUTTON 1054
#define IDC_WHISPER_INPUT 1055
#define IDC_SAVEBUTTON2 1055
#define IDC_WHISPER_TITLE 1056
#define IDC_WHISPER_SEND 1057
#define IDC_WHISPER_GM 1058
#define IDC_SAVEBUTTON3 1058
#define IDC_WHISPER_TARGET 1059
#define IDC_WHISPER_TRGT_TYPE 1060
#define IDC_WHISPER_TARGET_STATIC 1060
#define IDC_WHISPER_TITLE_STATIC 1061
#define IDC_SENDBYUID_CHK 1063
#define IDC_LOGINEDNAME_EDIT 1064
#define IDC_GMLOGINED_CHK 1065
#define IDC_LOGINEDNAME_STATIC 1066
#define IDC_EDIT1 1067
#define IDC_WHIS_SENDER_EDIT 1067
#define IDC_GMLOGINED_CHK2 1067
#define IDC_LANGTYPE_CHK 1067
#define IDC_WHISPER_LOGINEDNAME_STATIC 1068
#define IDC_PACKET_TIME 1069
#define IDC_REPORTLIST 1070
#define ID_CHATMONITOR_SELECTALL 32771
#define ID_CHATMONITOR_COPYTOCLIPBOARD 32772
#define ID_CHATMONITOR_EXPORTTOFILE 32773
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 131
#define _APS_NEXT_COMMAND_VALUE 32774
#define _APS_NEXT_CONTROL_VALUE 1071
#define _APS_NEXT_SYMED_VALUE 108
#endif
#endif

View File

@@ -0,0 +1,84 @@
// StringFilter.cpp: implementation of the CStringFilter class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "StringFilter.h"
#include <string>
CStringFilter g_StringFilter;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CStringFilter::CStringFilter()
{
m_dwStringCount = 0;
m_lpSearched = NULL;
}
CStringFilter::~CStringFilter()
{
}
bool CStringFilter::Filter(char *strTarget)
{
WCHAR strWideTarget[300], strWideString[300];
int nBufferSize = 300;
int nWideTargetLen, nWideStringLen;
unsigned long i;
int j;
MultiByteToWideChar(CP_ACP, 0, strTarget, strlen(strTarget) + 1, strWideTarget, nBufferSize);
nWideTargetLen = wcslen(strWideTarget);
for(i = 0; i < m_dwStringCount; i++)
{
MultiByteToWideChar(CP_ACP, 0, m_strString[i], strlen(m_strString[i]) + 1, strWideString, nBufferSize);
nWideStringLen = wcslen(strWideString);
j = 0;
if(nWideTargetLen >= nWideStringLen)
{
do
{
if(!wcsnicmp(&strWideTarget[j], strWideString, nWideStringLen))
{
m_lpSearched = m_strString[i];
return false;
}
j++;
} while(j <= (nWideTargetLen - nWideStringLen));
}
}
m_lpSearched = NULL;
return true;
}
bool CStringFilter::Load(const char *strScriptFile)
{
FILE* fp = fopen(strScriptFile, "rt");
if(!fp)
return true;
while(true)
{
fgets(m_strString[m_dwStringCount], 15, fp);
int len = strlen(m_strString[m_dwStringCount]);
if(len > 0)
m_strString[m_dwStringCount][len-1] = 0;
if(feof(fp) != 0)
break;
++m_dwStringCount;
}
fclose(fp);
return true;
}

View File

@@ -0,0 +1,26 @@
// StringFilter.h: interface for the CStringFilter class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_STRINGFILTER_H__033A0568_375A_41FD_8370_CEDE222BE28B__INCLUDED_)
#define AFX_STRINGFILTER_H__033A0568_375A_41FD_8370_CEDE222BE28B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CStringFilter
{
public:
bool Load(const char *strScriptFile);
unsigned long m_dwStringCount;
char m_strString[2000][15];
char *m_lpSearched;
bool Filter(char *strTarget);
CStringFilter();
~CStringFilter();
};
extern CStringFilter g_StringFilter;
#endif // !defined(AFX_STRINGFILTER_H__033A0568_375A_41FD_8370_CEDE222BE28B__INCLUDED_)

View File

@@ -0,0 +1,273 @@
// WhisperDlg.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "WhisperDlg.h"
#include "ChattingPage.h"
#include "GlobalFunc.h"
#include "MonitoringToolSetup.h"
#include "ChatServerEventHandler.h"
#include <Log/ServerLog.h>
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
// CWhisperDlg 대화 상자입니다.
IMPLEMENT_DYNAMIC(CWhisperDlg, CDialog)
CWhisperDlg::CWhisperDlg(CWnd* pParent, WhisperDlgInfo stInfo)
: CDialog(CWhisperDlg::IDD, pParent)
, m_strWhisperTitle(_T(""))
{
m_pParent = pParent;
CopyMemory(&m_stWhisperDlgInfo, &stInfo, sizeof(WhisperDlgInfo));
IsWhisperDlgSet = true;
}
CWhisperDlg::CWhisperDlg() : CDialog(CWhisperDlg::IDD)
{
IsWhisperDlgSet = false;
}
CWhisperDlg::~CWhisperDlg()
{
}
void CWhisperDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_WHISPER_OUTPUT, m_ctrlWhisperOutput);
DDX_Text(pDX, IDC_WHISPER_TITLE, m_strWhisperTitle);
DDX_Control(pDX, IDC_SENDBYUID_CHK, m_ctrlSendByUIDChk);
}
BEGIN_MESSAGE_MAP(CWhisperDlg, CDialog)
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_WHISPER_SEND, OnBnClickedWhisperSend)
END_MESSAGE_MAP()
// CWhisperDlg 메시지 처리기입니다.
BOOL CWhisperDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetDlgItemText(IDC_WHISPER_TITLE_STATIC, GetMyINIString("LOCAL_STRING", "STRING_021"));
SetDlgItemText(IDC_WHISPER_TRGT_TYPE, GetMyINIString("LOCAL_STRING", "STRING_022"));
SetDlgItemText(IDC_WHISPER_LOGINEDNAME_STATIC, GetMyINIString("LOCAL_STRING", "STRING_047"));
SetDlgItemText(IDC_WHISPER_SEND, GetMyINIString("LOCAL_STRING", "STRING_017"));
SetDlgItemText(IDC_PACKET_TIME, "");
bool IsEnable = false;
char strRace[4][4] = {"N/A", "H", "A", "N/A"};
if (WhisperDlgInfo::WHISPER_TYPE_CLK == m_stWhisperDlgInfo.m_nDlgType)
{
m_strWhisperTitle.Format("[%s] (UID: %u / CID: %u / Race : %s) %s",
m_stWhisperDlgInfo.m_szServerName, m_stWhisperDlgInfo.m_dwUID, m_stWhisperDlgInfo.m_dwCID, strRace[m_stWhisperDlgInfo.m_cRace],
m_stWhisperDlgInfo.m_szCharName);
SetWindowText(m_stWhisperDlgInfo.m_szCharName);
IsEnable = false;
}
else if (WhisperDlgInfo::FINDUSER == m_stWhisperDlgInfo.m_nDlgType)
{
SetDlgItemText(IDC_WHISPER_TITLE, GetMyINIString("LOCAL_STRING", "STRING_023"));
SetWindowText(GetMyINIString("LOCAL_STRING", "STRING_023"));
IsEnable = true;
}
SetDlgItemText(IDC_WHIS_SENDER_EDIT, theApp.GetLoginedName());
GetDlgItem(IDC_WHISPER_TARGET)->EnableWindow(IsEnable);
GetDlgItem(IDC_SENDBYUID_CHK)->EnableWindow(IsEnable);
UpdateData(false);
return TRUE;
}
void CWhisperDlg::OnBnClickedWhisperSend()
{
CString strServerName, strGMName, strMsg;
strServerName.Format("%s", m_stWhisperDlgInfo.m_szServerName); // 서버 그룹 명
strGMName = theApp.GetLoginedName(); // GM명
GetDlgItemText(IDC_WHISPER_INPUT, strMsg); // 메세지
bool IsSended = false;
if (BST_UNCHECKED == ((CChattingPage*)m_pParent)->IsDlgButtonChecked(IDC_GMLOGINED_CHK))
{
MessageBox(GetMyINIString("LOCAL_STRING", "STRING_046"));
IsSended = false;
}
else
{
// 일반 대화 모드 (리스트박스 더블 클릭)
if ((true == IsWhisperDlgSet) && (WhisperDlgInfo::WHISPER_TYPE_CLK == m_stWhisperDlgInfo.m_nDlgType))
{
IsSended = ClientNet::CChatServerEventHandler::SendChatReqPkt(
theApp.GetServerIndex(strServerName), PktChat::WHISPER,
ChatToolPkt::TARGET_CHARNAME, 0, 0, strGMName, m_stWhisperDlgInfo.m_szCharName, strMsg);
}
// 계정명으로 대화 모드 (직접 계정정보 입력)
else
{
CString strTarget;
GetDlgItemText(IDC_WHISPER_TARGET, strTarget);
char szKey[256];
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
unsigned int nMaxGroupNum = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
for(int nIndex = 0; nIndex < (int)nMaxGroupNum; ++nIndex)
{
unsigned long dwDlgID = ((CChattingPage*)m_pParent)->GetAccountDlgID();
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
if (BST_CHECKED != m_ctrlSendByUIDChk.GetCheck())
{
IsSended = ClientNet::CChatServerEventHandler::SendChatReqPkt(
nServerGroup, PktChat::WHISPER,
ChatToolPkt::TARGET_ACCOUNTNAME, 0, dwDlgID, strGMName, strTarget, strMsg);
// 로그를 모니터링 툴에 남기기 위해서 만든다.
//CMonitoringToolLog::GetInstance().WriteAdminLog(nServerGroup, PktChat::WHISPER, strGMName, strTarget, strMsg);
}
else
{
IsSended = ClientNet::CChatServerEventHandler::SendChatReqPkt(
nServerGroup, PktChat::WHISPER,
ChatToolPkt::TARGET_UID, (unsigned long)atoi(strTarget), dwDlgID, strGMName, _T(""), strMsg);
// 로그를 모니터링 툴에 남기기 위해서 만든다.
//CMonitoringToolLog::GetInstance().WriteAdminLog(nServerGroup, PktChat::WHISPER, strGMName, strTarget, strMsg);
}
}
}
}
if (true == IsSended)
{
SetDlgItemText(IDC_WHISPER_INPUT, _T(""));
GetDlgItem(IDC_WHISPER_TARGET)->EnableWindow(false);
GetDlgItem(IDC_SENDBYUID_CHK)->EnableWindow(false);
}
else
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_026"));
}
}
BOOL CWhisperDlg::PreTranslateMessage(MSG* pMsg)
{
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN))
{
if ((pMsg->hwnd == GetDlgItem(IDC_WHISPER_INPUT)->m_hWnd))
{
OnBnClickedWhisperSend();
}
}
return CDialog::PreTranslateMessage(pMsg);
}
void CWhisperDlg::OnOK()
{
}
void CWhisperDlg::OnClose()
{
DestroyWindow();
}
void CWhisperDlg::OnCancel()
{
DestroyWindow();
}
void CWhisperDlg::PostNcDestroy()
{
if(m_stWhisperDlgInfo.m_nDlgType == WhisperDlgInfo::WHISPER_TYPE_CLK)
{
CChattingPage::WhisperDlgMap::iterator pos1 =
((CChattingPage*)m_pParent)->m_WhisperDlgMap.find(m_stWhisperDlgInfo.m_dwUID);
if (pos1 != ((CChattingPage*)m_pParent)->m_WhisperDlgMap.end())
{
((CChattingPage*)m_pParent)->m_WhisperDlgMap.erase(pos1);
}
}
CChattingPage::WhisperDlgMap::iterator pos2 =
((CChattingPage*)m_pParent)->m_AccountDlgMap.find(m_stWhisperDlgInfo.m_dwDlgID);
if (pos2 != ((CChattingPage*)m_pParent)->m_AccountDlgMap.end())
{
((CChattingPage*)m_pParent)->m_AccountDlgMap.erase(pos2);
}
delete this;
}
/// \brief 채팅패킷을 파싱하여 대화창에 표시
/// \param lpChatData 채팅 패킷
void CWhisperDlg::ParseChatData(ChatToolPkt::ChatDataSend* lpChatData)
{
char strRecvMsg[UCHAR_MAX * 2];
CString strOutput;
char szTime[32];
char szDate[32];
_tzset();
_tstrdate( szDate );
_tstrtime( szTime );
memcpy(strRecvMsg, reinterpret_cast<char*>(lpChatData + 1), lpChatData->m_cChatMsgLen);
strRecvMsg[lpChatData->m_cChatMsgLen] = 0;
strOutput.Format("[%s-%s] %s : %s", szDate, szTime, lpChatData->m_szSenderName, strRecvMsg);
int nIndex = m_ctrlWhisperOutput.AddString(strOutput);
// 자동 스크롤
int nMaxLine = 27; // 1대1 대화창 리스트박스 최대 라인수
if (nIndex >= nMaxLine)
{
m_ctrlWhisperOutput.SetTopIndex(nIndex);
}
strOutput.Format("Time : %s-%s", szDate, szTime);
SetDlgItemText(IDC_PACKET_TIME, strOutput);
}
void CWhisperDlg::SetKeyUID(unsigned long dwUID, unsigned long dwCID)
{
m_stWhisperDlgInfo.m_dwUID = dwUID;
m_stWhisperDlgInfo.m_dwCID = dwCID;
if (NULL == ((CChattingPage*)m_pParent)->GetWhisperDlg(dwUID))
{
((CChattingPage*)m_pParent)->m_WhisperDlgMap.insert(CChattingPage::WhisperDlgMap::value_type(dwUID, this));
CChattingPage::WhisperDlgMap::iterator pos =
((CChattingPage*)m_pParent)->m_AccountDlgMap.find(m_stWhisperDlgInfo.m_dwDlgID);
((CChattingPage*)m_pParent)->m_AccountDlgMap.erase(pos);
CString strTitle;
strTitle.Format("%u", dwUID);
SetWindowText(strTitle);
}
}

View File

@@ -0,0 +1,70 @@
#pragma once
#include "afxwin.h"
#include <Network/Packet/ChatToolPacketCmd.h>
/** \class CWhisperDlg
1대1 대화창. 모니터링 리스트 박스를 더블클릭하거나 계정으로 귓말 보내기를 클릭하면 나타나는 다이얼로그*/
class CWhisperDlg : public CDialog
{
DECLARE_DYNAMIC(CWhisperDlg)
public:
/// 귓속말 대화창 정보
struct WhisperDlgInfo
{
enum SIZE
{
MAX_NAME = 256
};
/// 대화창 타입
enum DLG_TYPE
{
WHISPER_TYPE_CLK = 0, ///< 모니터링 리스트 박스 더블클릭하여 사용하는 대화창
FINDUSER = 1 ///< 직접 계정정보를 입력하는 스타일의 대화창
};
unsigned char m_nDlgType; ///< 대화창 타입
unsigned long m_dwUID; ///< 대화상대의 UID
unsigned long m_dwCID; ///< 대화상대의 CID
unsigned long m_dwDlgID; ///< 대화창의 고유ID
char m_cRace; ///< 종족
char m_szServerName[MAX_NAME]; ///< 대화중인 상대가 있는 서버군
char m_szCharName[MAX_NAME]; ///< 대화 상대의 캐릭명
};
CWhisperDlg(CWnd* pParent, WhisperDlgInfo stInfo); // 표준 생성자입니다.
CWhisperDlg();
virtual ~CWhisperDlg();
enum { IDD = IDD_WHISPERDLG };
protected:
DECLARE_MESSAGE_MAP()
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
virtual void PostNcDestroy();
virtual void OnOK();
virtual void OnCancel();
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
bool IsWhisperDlgSet; ///< 계정으로 찾아서 귓속말 보내는것인지 리스트박스를 클릭해서 귓속말 보내는것인지 체크
CWnd* m_pParent;
private:
CButton m_ctrlSendByUIDChk;
CListBox m_ctrlWhisperOutput; ///< 대화 출력창
CString m_strWhisperTitle; ///< 대화 창 타이틀
WhisperDlgInfo m_stWhisperDlgInfo; ///< 대화상대 정보
afx_msg void OnClose();
afx_msg void OnBnClickedWhisperSend();
public:
void ParseChatData(ChatToolPkt::ChatDataSend* lpChatData);
void SetKeyUID(unsigned long dwUID, unsigned long dwCID);
unsigned long GetKeyUID() { return m_stWhisperDlgInfo.m_dwUID; };
};

View File

@@ -0,0 +1,702 @@
// XListBox.cpp
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
// Notes on use: To use in an MFC project, first create
// a listbox using the standard dialog editor.
// Be sure to mark the listbox as OWNERDRAW
// FIXED, and check the HAS STRINGS box.
// Using Class Wizard, create a variable for
// the listbox. Finally, manually edit the
// dialog's .h file and replace CListBox with
// CXListBox, and #include XListBox.h.
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XListBox.h"
#include "Clipboard.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
// NOTE - following table must be kept in sync with ColorPickerCB.cpp
static COLORREF ColorTable[16] = { RGB( 0, 0, 0), // Black
RGB(255, 255, 255), // White
RGB(255, 255, 255), // ChatNormal
RGB(141, 180, 244), // ChatParty
RGB(255, 255, 255), // ChatFriend
RGB(255, 229, 57), // ChatGuild
RGB(255, 255, 255), // ChatStall
RGB( 53, 218, 193), // ChatShout
RGB(220, 220, 220), // ChatAdminNormal
RGB(255, 128, 64), // ChatAdminShout
RGB(255, 128, 239), // ChatWhisper
RGB(255, 0, 255), // ChatNotice
RGB(204, 128, 255), // ChatTrade
RGB( 38, 255, 38), // Call : 운영자를 부르는 유저의 목소리-_ -a
RGB(255, 0, 255), // GMReport
RGB( 0, 0, 0) }; // BackColor
BEGIN_MESSAGE_MAP(CXListBox, CListBox)
//{{AFX_MSG_MAP(CXListBox)
ON_WM_LBUTTONDBLCLK()
ON_WM_CONTEXTMENU()
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// CXListBox
CXListBox::CXListBox()
{
m_ColorWindow = ::GetSysColor(COLOR_WINDOW);
m_ColorHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
m_ColorWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
m_ColorHighlightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_bColor = TRUE;
m_cxExtent = 0;
m_nTabPosition = 8; // tab stops every 8 columns
m_nSpaceWidth = 7;
m_nContextMenuId = (UINT)-1;
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nTabPosition * m_nSpaceWidth;
}
CXListBox::~CXListBox()
{
}
//////////////////////////////////////////////////////////////////////////////
// MeasureItem
void CXListBox::MeasureItem(LPMEASUREITEMSTRUCT)
{
}
//////////////////////////////////////////////////////////////////////////////
// CompareItem
int CXListBox::CompareItem(LPCOMPAREITEMSTRUCT)
{
return 0;
}
//////////////////////////////////////////////////////////////////////////////
// DrawItem
void CXListBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
COLORREF oldtextcolor, oldbackgroundcolor;
pDC->GetCharWidth((UINT) ' ', (UINT) ' ', &m_nSpaceWidth);
pDC->GetCharWidth((UINT) 'c', (UINT) 'c', &m_nAveCharWidth);
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nAveCharWidth * m_nTabPosition;
// draw focus rectangle when no items in listbox
if (lpDIS->itemID == (UINT)-1)
{
if (lpDIS->itemAction & ODA_FOCUS)
pDC->DrawFocusRect(&lpDIS->rcItem);
return;
}
else
{
int selChange = lpDIS->itemAction & ODA_SELECT;
int focusChange = lpDIS->itemAction & ODA_FOCUS;
int drawEntire = lpDIS->itemAction & ODA_DRAWENTIRE;
if (selChange || drawEntire)
{
BOOL sel = lpDIS->itemState & ODS_SELECTED;
int nLen = CListBox::GetTextLen(lpDIS->itemID);
if (nLen != LB_ERR)
{
char *buf = new char [nLen + 10];
ASSERT(buf);
if (buf && (GetTextWithColor(lpDIS->itemID, (LPSTR)buf) != LB_ERR))
{
// set text color from first character in string -
// NOTE: 1 was added to color index to avoid asserts by CString
int itext = int (buf[0] - 1);
// set background color from second character in string -
// NOTE: 1 was added to color index to avoid asserts by CString
int iback = int (buf[1] - 1);
buf[0] = ' ';
buf[1] = ' ';
COLORREF textcolor = sel ? m_ColorHighlightText : ColorTable[itext];
oldtextcolor = pDC->SetTextColor(textcolor);
COLORREF backgroundcolor = sel ? m_ColorHighlight : ColorTable[iback];
oldbackgroundcolor = pDC->SetBkColor(backgroundcolor);
// fill the rectangle with the background color the fast way
pDC->ExtTextOut(0, 0, ETO_OPAQUE, &lpDIS->rcItem, NULL, 0, NULL);
pDC->TabbedTextOut(lpDIS->rcItem.left, lpDIS->rcItem.top, &buf[2],
(int)strlen(&buf[2]), MAXTABSTOPS, (LPINT)m_nTabStopPositions, 0);
CSize size;
size = pDC->GetOutputTextExtent(&buf[2]);
int nScrollBarWidth = ::GetSystemMetrics(SM_CXVSCROLL);
size.cx += nScrollBarWidth; // in case of vertical scrollbar
int cxExtent = (size.cx > m_cxExtent) ? size.cx : m_cxExtent;
if (cxExtent > m_cxExtent)
{
m_cxExtent = cxExtent;
SetHorizontalExtent(m_cxExtent+(m_cxExtent/32));
}
}
if (buf)
delete [] buf;
}
}
if (focusChange || (drawEntire && (lpDIS->itemState & ODS_FOCUS)))
{
pDC->DrawFocusRect(&lpDIS->rcItem);
}
}
}
//////////////////////////////////////////////////////////////////////////////
// GetTextWithColor - get text string with color bytes
int CXListBox::GetTextWithColor(int nIndex, LPTSTR lpszBuffer) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
ASSERT(lpszBuffer);
lpszBuffer[0] = 0;
return CListBox::GetText(nIndex, lpszBuffer);
}
//////////////////////////////////////////////////////////////////////////////
// GetTextWithColor - get text string with color bytes
void CXListBox::GetTextWithColor(int nIndex, CString& rString) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
rString.Empty();
CListBox::GetText(nIndex, rString);
}
//////////////////////////////////////////////////////////////////////////////
// GetText - for compatibility with CListBox (no color bytes)
int CXListBox::GetText(int nIndex, LPTSTR lpszBuffer) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
ASSERT(lpszBuffer);
lpszBuffer[0] = 0;
int nRet = CListBox::GetText(nIndex, lpszBuffer);
int n = (int)strlen(lpszBuffer);
if (n > 2)
memcpy(&lpszBuffer[0], &lpszBuffer[2], n-1); // copy nul too
return nRet;
}
//////////////////////////////////////////////////////////////////////////////
// GetText - for compatibility with CListBox (no color bytes)
void CXListBox::GetText(int nIndex, CString& rString) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CString str;
str.Empty();
CListBox::GetText(nIndex, str);
if ((!str.IsEmpty()) && (str.GetLength() > 2))
rString = str.Mid(2);
else
rString.Empty();
}
//////////////////////////////////////////////////////////////////////////////
// GetTextLen - for compatibility with CListBox (no color bytes)
int CXListBox::GetTextLen(int nIndex) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
int n = CListBox::GetTextLen(nIndex);
if (n != LB_ERR && n >= 2)
n -= 2;
return n;
}
//////////////////////////////////////////////////////////////////////////////
// SearchString
int CXListBox::SearchString(int nStartAfter, LPCTSTR lpszItem, BOOL bExact) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
// start the search after specified index
int nIndex = nStartAfter + 1;
int nCount = GetCount();
if (nCount == LB_ERR)
return LB_ERR;
// convert string to search for to lower case
CString strItem;
strItem = lpszItem;
strItem.MakeLower();
int nItemSize = strItem.GetLength();
CString strText;
// search until end
for ( ; nIndex < nCount; nIndex++)
{
GetText(nIndex, strText);
strText.MakeLower();
if (!bExact)
strText = strText.Left(nItemSize);
if (strText == strItem)
return nIndex;
}
// if we started at beginning there is no more to do, search failed
if (nStartAfter == -1)
return LB_ERR;
// search until we reach beginning index
for (nIndex = 0; (nIndex <= nStartAfter) && (nIndex < nCount); nIndex++)
{
GetText(nIndex, strText);
strText.MakeLower();
if (!bExact)
strText = strText.Left(nItemSize);
if (strText == strItem)
return nIndex;
}
return LB_ERR;
}
//////////////////////////////////////////////////////////////////////////////
// FindString
int CXListBox::FindString(int nStartAfter, LPCTSTR lpszItem) const
{
return SearchString(nStartAfter, lpszItem, FALSE);
}
//////////////////////////////////////////////////////////////////////////////
// SelectString
int CXListBox::SelectString(int nStartAfter, LPCTSTR lpszItem)
{
int rc = SearchString(nStartAfter, lpszItem, FALSE);
if (rc != LB_ERR)
SetCurSel(rc);
return rc;
}
//////////////////////////////////////////////////////////////////////////////
// FindStringExact
int CXListBox::FindStringExact(int nStartAfter, LPCTSTR lpszItem) const
{
return SearchString(nStartAfter, lpszItem, TRUE);
}
//////////////////////////////////////////////////////////////////////////////
// InsertString - override to add text color
int CXListBox::InsertString(int nIndex, LPCTSTR lpszItem)
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
CString s;
s.Empty();
s = lpszItem;
Color tc = Black; // to force black-only text
Color bc = White;
UINT nColor = (UINT) tc;
ASSERT(nColor < 16);
if (nColor >= 16)
tc = Black;
// don't display \r or \n characters
int i;
while ((i = s.FindOneOf("\r\n")) != -1)
s.SetAt(i, ' ');
// first character in string is color -- add 1 to color
// to avoid asserts by CString class
CString t;
t .Empty();
t += (char) (tc + 1);
t += (char) (bc + 1);
t += s;
// try to insert the string into the listbox
i = CListBox::InsertString(nIndex, t);
return i;
}
//////////////////////////////////////////////////////////////////////////////
// AddString - override to add text color
void CXListBox::AddString(LPCTSTR lpszItem)
{
AddLine(CXListBox::Black, CXListBox::White, lpszItem, true);
}
//////////////////////////////////////////////////////////////////////////////
// AddLine
void CXListBox::AddLine(Color tc, Color bc, LPCTSTR lpszLine, BOOL bAutoScroll)
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CString s;
s.Empty();
s = lpszLine;
if (!m_bColor)
{
tc = Black; // to force black-only text
bc = White;
}
UINT nColor = (UINT) tc;
ASSERT(nColor < 16);
if (nColor >= 16)
tc = Black;
// don't display \r or \n characters
int i;
while ((i = s.FindOneOf("\r\n")) != -1)
s.SetAt(i, ' ');
// first character in string is color -- add 1 to color
// to avoid asserts by CString class
CString t;
t.Empty();
t += (char) (tc + 1);
t += (char) (bc + 1);
t += s;
// try to add the string to the listbox
i = CListBox::AddString(t);
if (i == LB_ERRSPACE)
{
// will get LB_ERRSPACE if listbox is out of memory
int n = GetCount();
if (n == LB_ERR)
return;
if (n < 2)
return;
// try to delete some strings to free up some room --
// don't spend too much time deleting strings, since
// we might be getting a burst of messages
n = (n < 20) ? (n - 1) : 20;
if (n <= 0)
n = 1;
SetRedraw(FALSE);
for (i = 0; i < n; i++)
DeleteString(0);
i = CListBox::AddString(t);
SetRedraw(TRUE);
}
if(bAutoScroll && (i >= 0))
{
SetTopIndex(i);
}
SetCurSel(-1);
}
///////////////////////////////////////////////////////////////////////////////
// Printf
void _cdecl CXListBox::Printf(Color tc, Color bc, UINT nID, LPCTSTR lpszFmt, ...)
{
char buf[1024], fmt[1024];
va_list marker;
// load format string from string resource if
// a resource ID was specified
if (nID)
{
CString s;
if (!s.LoadString(nID))
{
sprintf(s.GetBufferSetLength(80), "Failed to load string resource %u",
nID);
s.ReleaseBuffer(-1);
}
strncpy(fmt, s, sizeof(fmt)-1);
}
else
{
// format string was passed as parameter
strncpy(fmt, lpszFmt, sizeof(fmt)-1);
}
fmt[sizeof(fmt)-1] = 0;
// combine output string and variables
va_start(marker, lpszFmt);
_vsnprintf(buf, sizeof(buf)-1, fmt, marker);
va_end(marker);
buf[sizeof(buf)-1] = 0;
AddLine(tc, bc, buf, true);
}
//////////////////////////////////////////////////////////////////////////////
// EnableColor
void CXListBox::EnableColor (BOOL bEnable)
{
m_bColor = bEnable;
}
//////////////////////////////////////////////////////////////////////////////
// SetTabPosition
void CXListBox::SetTabPosition(int nSpacesPerTab)
{
ASSERT(nSpacesPerTab > 0 && nSpacesPerTab < 11);
m_nTabPosition = nSpacesPerTab;
CDC* pDC = GetDC();
if (pDC)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
pDC->GetCharWidth((UINT) ' ', (UINT) ' ', &m_nSpaceWidth);
pDC->GetCharWidth((UINT) '9', (UINT) '9', &m_nAveCharWidth);
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nAveCharWidth * m_nTabPosition;
ReleaseDC(pDC);
}
}
//////////////////////////////////////////////////////////////////////////////
// GetVisibleLines
int CXListBox::GetVisibleLines()
{
int nCount = 0;
CDC* pDC = GetDC();
if (pDC)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int h = tm.tmHeight + tm.tmInternalLeading;
ReleaseDC(pDC);
CRect rect;
GetClientRect(&rect);
nCount = rect.Height() / h;
}
return nCount;
}
//////////////////////////////////////////////////////////////////////////////
// ResetContent
void CXListBox::ResetContent()
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CListBox::ResetContent();
m_cxExtent = 0;
SetHorizontalExtent(m_cxExtent);
}
//////////////////////////////////////////////////////////////////////////////
// SetFont
void CXListBox::SetFont(CFont *pFont, BOOL bRedraw)
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CListBox::SetFont(pFont, bRedraw);
CDC* pDC = GetDC();
if (pDC)
{
CFont *pOldFont = pDC->SelectObject(pFont);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int h = tm.tmHeight;
SetItemHeight(0, h);
pDC->SelectObject(pOldFont);
pDC->GetCharWidth((UINT) ' ', (UINT) ' ', &m_nSpaceWidth);
pDC->GetCharWidth((UINT) '9', (UINT) '9', &m_nAveCharWidth);
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nAveCharWidth * m_nTabPosition;
ReleaseDC(pDC);
}
m_cxExtent = 0;
}
//////////////////////////////////////////////////////////////////////////////
// OnLButtonDblClk
void CXListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CListBox::OnLButtonDblClk(nFlags, point);
}
//////////////////////////////////////////////////////////////////////////////
// OnContextMenu
void CXListBox::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
if (m_nContextMenuId == -1)
{
TRACE(" no context menu\n");
return;
}
CMenu menu;
if (!menu.LoadMenu(m_nContextMenuId))
{
TRACE(" ERROR failed to load %d\n", m_nContextMenuId);
return;
}
menu.GetSubMenu(0)->TrackPopupMenu(0,
point.x, point.y, this, NULL);
}
//////////////////////////////////////////////////////////////////////////////
// OnEditCopy
void CXListBox::OnEditCopy()
{
CString str;
str.Empty();
int nCount = GetCount();
int nSel = 0;
for (int i = 0; i < nCount; i++)
{
if (GetSel(i) > 0)
{
CString s;
s.Empty();
GetText(i, s);
if (!s.IsEmpty())
{
nSel++;
s.TrimLeft("\r\n");
s.TrimRight("\r\n");
if (s.Find('\n') == -1)
s += "\n";
s.Replace("\t", " ");
str += s;
}
}
}
if (!str.IsEmpty())
CClipboard::SetText(str);
}
//////////////////////////////////////////////////////////////////////////////
// OnEditClear
void CXListBox::OnEditClear()
{
ResetContent();
}
//////////////////////////////////////////////////////////////////////////////
// OnEditSelectAll
void CXListBox::OnEditSelectAll()
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
SelItemRange(TRUE, 0, GetCount()-1);
}
// Add by zun!
BOOL CXListBox::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

View File

@@ -0,0 +1,93 @@
// XListBox.h
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef XLISTBOX_H
#define XLISTBOX_H
///////////////////////////////////////////////////////////////////////////////
// CXListBox class
class CXListBox : public CListBox
{
// Constructors
public:
CXListBox();
~CXListBox();
// Attributes
public:
int m_cxExtent;
int m_nTabPosition;
BOOL m_bColor;
COLORREF m_ColorWindow;
COLORREF m_ColorHighlight;
COLORREF m_ColorWindowText;
COLORREF m_ColorHighlightText;
// NOTE - following list must be kept in sync with ColorPickerCB.cpp
enum Color{ Black, White,
ChatNormal, ChatParty, ChatFriend, ChatGuild, ChatStall, ChatShout,
ChatAdminNormal, ChatAdminShout, ChatWhisper, ChatNotice, ChatTrade, Call, GMReport, BackColor
};
void EnableColor(BOOL bEnable);
// Operations
public:
void AddLine(Color tc, Color bc, LPCTSTR lpszLine, BOOL bAutoScroll = TRUE);
void AddString(LPCTSTR lpszItem);
int FindString(int nStartAfter, LPCTSTR lpszItem) const;
int FindStringExact(int nStartAfter, LPCTSTR lpszItem) const;
int GetText(int nIndex, LPTSTR lpszBuffer) const;
void GetText(int nIndex, CString& rString) const;
int GetTextLen(int nIndex) const;
int GetTextWithColor(int nIndex, LPTSTR lpszBuffer) const;
void GetTextWithColor(int nIndex, CString& rString) const;
int GetVisibleLines();
int InsertString(int nIndex, LPCTSTR lpszItem);
void _cdecl Printf(Color tc, Color bc, UINT nID, LPCTSTR lpszFmt, ...);
virtual void ResetContent();
int SelectString(int nStartAfter, LPCTSTR lpszItem);
void SetContextMenuId(UINT nId) { m_nContextMenuId = nId; }
virtual void SetFont(CFont *pFont, BOOL bRedraw = TRUE);
void SetTabPosition(int nSpacesPerTab);
// Implementation
protected:
int SearchString(int nStartAfter, LPCTSTR lpszItem, BOOL bExact) const;
#define MAXTABSTOPS 100
int m_nTabStopPositions[MAXTABSTOPS];
int m_nSpaceWidth;
int m_nAveCharWidth;
UINT m_nContextMenuId;
virtual int CompareItem (LPCOMPAREITEMSTRUCT lpCIS);
virtual void DrawItem (LPDRAWITEMSTRUCT lpDIS);
virtual void MeasureItem (LPMEASUREITEMSTRUCT lpMIS);
// Generated message map functions
//{{AFX_MSG(CXListBox)
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
afx_msg void OnEditCopy();
afx_msg void OnEditClear();
afx_msg void OnEditSelectAll();
afx_msg BOOL OnEraseBkgnd(CDC* pDC); // Add by zun!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif
///////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Microsoft.Windows.MonitoringTool"
type="win32"
/>
<description>Your app description here</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

View File

@@ -0,0 +1,13 @@
//
// MonitoringTool.RC2 - resources Microsoft Visual C++ does not edit directly
//
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// Add manually edited resources here...
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,7 @@
// stdafx.cpp : source file that includes just the standard includes
// MonitoringTool.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

View File

@@ -0,0 +1,42 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#endif
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later.
#endif
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
// turns off MFC's hiding of some common and often safely ignored warning messages
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxdlgs.h>