Files
Client/Server/AdminTool/AdminToolClient/UserCharTreeView.cpp
LGram16 dd97ddec92 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>
2025-11-29 20:17:20 +09:00

439 lines
13 KiB
C++

// CharTreeView.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "AdminToolClient.h"
#include "UserCharTreeView.h"
#include "GlobalFunctions.h"
#include "UserInfoDoc.h"
#include "CharacterDoc.h"
#include "PacketManager.h"
#include "ModifyCharNameDlg.h"
#include "AddBlockUserDlg.h"
#include "GMLogMsgDlg.h"
// CUserCharTreeView
IMPLEMENT_DYNCREATE(CUserCharTreeView, CFormView)
CUserCharTreeView::CUserCharTreeView()
: CFormView(CUserCharTreeView::IDD)
{
m_clrR = rand() % 255;
m_clrG = rand() % 255;
m_clrB = rand() % 255;
m_dwWndKey = 0;
}
CUserCharTreeView::~CUserCharTreeView()
{
m_hImageList.DeleteImageList();
m_imgCharTree.DeleteImageList();
}
void CUserCharTreeView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CHARTREE, m_ctrlCharTree);
}
BEGIN_MESSAGE_MAP(CUserCharTreeView, CFormView)
ON_WM_CONTEXTMENU()
ON_WM_CTLCOLOR()
ON_NOTIFY(NM_DBLCLK, IDC_CHARTREE, OnNMDblclkChartree)
ON_COMMAND(ID_CHAREDITNAME, OnModifyCharName)
ON_NOTIFY(NM_RCLICK, IDC_CHARTREE, OnNMRclickChartree)
ON_COMMAND(ID_ACCOUNT_BLOCK, OnBlockAccount)
ON_COMMAND(ID_BLOCK_CHARACTER, OnBlockCharacter)
ON_COMMAND(ID_DELETE_CHAR, OnDeleteChar)
ON_COMMAND(ID_FORCED_DIS, OnForcedDis)
ON_NOTIFY(TVN_SELCHANGED, IDC_CHARTREE, OnTvnSelchangedChartree)
ON_COMMAND(ID_GMLOGMANAGE_UID, OnGmlogmanageUid)
ON_COMMAND(ID_GMLOGMANAGE_CID, OnGmlogmanageCid)
END_MESSAGE_MAP()
// CUserCharTreeView 진단입니다.
#ifdef _DEBUG
void CUserCharTreeView::AssertValid() const
{
CFormView::AssertValid();
}
void CUserCharTreeView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
#endif //_DEBUG
// CUserCharTreeView 메시지 처리기입니다.
HBRUSH CUserCharTreeView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetBkColor(RGB(0, 0, 0));
pDC->SetTextColor(RGB(255, 255, 255));
if(nCtlColor == CTLCOLOR_DLG)
{
HBRUSH m_hBrush;
m_hBrush = CreateSolidBrush(RGB(m_clrR, m_clrG, m_clrB));
return m_hBrush;
}
else
{
return hbr;
}
}
void CUserCharTreeView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
m_hImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 3, 3);
m_hImageList.Add(AfxGetApp()->LoadIcon(IDI_UID));
m_hImageList.Add(AfxGetApp()->LoadIcon(IDI_SERVER));
m_hImageList.Add(AfxGetApp()->LoadIcon(IDI_CHARACTER));
m_hImageList.Add(AfxGetApp()->LoadIcon(IDI_BLOCK));
m_ctrlCharTree.SetImageList(&m_hImageList, TVSIL_NORMAL);
SetUIString(this->m_hWnd, IDC_CHARTREE_01, "IDC_CHARTREE_01");
}
HTREEITEM CUserCharTreeView::InsertItemEX( HTREEITEM hNode, unsigned char cIcon, CString strText )
{
TV_INSERTSTRUCT tvInsert;
TCHAR szText[256];
_sntprintf(szText, sizeof(szText), _T("%s"), strText);
tvInsert.hParent = hNode;
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.item.pszText = szText;
tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvInsert.item.iImage = cIcon;
tvInsert.item.iSelectedImage = cIcon;
return m_ctrlCharTree.InsertItem(&tvInsert);
}
void CUserCharTreeView::OnContextMenu(CWnd* pWnd, CPoint point)
{
// 트리 노드 단계에 맞는 컨텍스트 메뉴 생성
if (pWnd->GetSafeHwnd() == m_ctrlCharTree.GetSafeHwnd())
{
if (NULL != m_ctrlCharTree.GetSelectedItem())
{
CMenu muTemp, *pContextMenu;
muTemp.LoadMenu(IDR_CONTEXTMENU);
m_stLastBlockInfo.m_cType = BLOCK_INFO::NONE;
if (m_hUIDNode == m_ctrlCharTree.GetSelectedItem())
{
pContextMenu = muTemp.GetSubMenu(0);
pContextMenu->ModifyMenu(0, MF_STRING | MF_BYPOSITION, ID_ACCOUNT_BLOCK, GetLocalString("MENU_016"));
pContextMenu->ModifyMenu(2, MF_STRING | MF_BYPOSITION, ID_FORCED_DIS, GetLocalString("MENU_017"));
pContextMenu->ModifyMenu(4, MF_STRING | MF_BYPOSITION, ID_GMLOGMANAGE_UID, GetLocalString("ADDED_STRING_045"));
pContextMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
}
/*
if (m_hUIDNode == m_ctrlCharTree.GetParentItem( m_ctrlCharTree.GetSelectedItem()))
{
pContextMenu = muTemp.GetSubMenu(1);
pContextMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
}
*/
else if(NULL == m_ctrlCharTree.GetChildItem( m_ctrlCharTree.GetSelectedItem()))
{
pContextMenu = muTemp.GetSubMenu(2);
pContextMenu->ModifyMenu(0, MF_STRING | MF_BYPOSITION, ID_CHAREDITNAME, GetLocalString("MENU_018"));
pContextMenu->ModifyMenu(2, MF_STRING | MF_BYPOSITION, ID_BLOCK_CHARACTER, GetLocalString("MENU_019"));
pContextMenu->ModifyMenu(4, MF_STRING | MF_BYPOSITION, ID_GMLOGMANAGE_CID, GetLocalString("ADDED_STRING_045"));
pContextMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
}
}
}
}
void CUserCharTreeView::UserCharTreeSet()
{
const unsigned char IDX_UID = 0;
const unsigned char IDX_SERVER = 1;
const unsigned char IDX_CHARACTER = 2;
const unsigned char IDX_BLOCK = 3;
CUserInfoDoc* Doc = static_cast<CUserInfoDoc*>(GetDocument());
if (Doc && Doc->m_lpUserInfo)
{
CString report;
CCharacterDoc::CharDocInfo::isListCharIdx::iterator pos = Doc->m_lpUserInfo->m_listTreeInfo.begin();
CCharacterDoc::CharDocInfo::isListCharIdx::iterator end = Doc->m_lpUserInfo->m_listTreeInfo.end();
CCharacterDoc::In_ServerCharacter lpServerCharacter;
m_dwWndKey = Doc->m_lpUserInfo->m_dwDocKey;
// UID 노드 삽입
m_hUIDNode = InsertItemEX(NULL, IDX_UID, _T(""));
for(; pos != end; ++pos)
{
CString szServerGroupName, szCharInfo;
lpServerCharacter = (*pos);
// UID 노드 갱신- 몇번째 슬롯에 캐릭이 있을지 모르니 이렇게라도- _-
unsigned long dwTempUID = lpServerCharacter.CharIdx[0].m_UID;
if(0 == dwTempUID) dwTempUID = lpServerCharacter.CharIdx[1].m_UID;
if(0 == dwTempUID) dwTempUID = lpServerCharacter.CharIdx[2].m_UID;
if(0 == dwTempUID) dwTempUID = lpServerCharacter.CharIdx[3].m_UID;
if(0 == dwTempUID) dwTempUID = lpServerCharacter.CharIdx[4].m_UID;
if (0 != dwTempUID)
{
szServerGroupName.Format(_T("%u ID"), dwTempUID);
m_ctrlCharTree.SetItemText(m_hUIDNode, szServerGroupName);
Doc->SetTitle(szServerGroupName); // 문서 타이틀 바
// 해당 UID가 GM 로그를 가지고 있는지 확인 요청
CPacketMgr::GetInstance()->SendPktGMLogMsg(
PktAdminMgr::PktGMLogMsg::LOG_CONFIRM, lpServerCharacter.dwServerGroup, dwTempUID);
}
// 서버군 노드 삽입 및 갱신
CString strServerName;
CCharacterDoc::GetInstance().GetServerName(lpServerCharacter.dwServerGroup, strServerName);
m_hServerNode = InsertItemEX(m_hUIDNode, IDX_SERVER, strServerName);
// 캐릭터 노드 삽입 및 갱신
for (int slot = 0; slot < (int)lpServerCharacter.dwCharCount; slot++)
{
szCharInfo.Format(_T("%u %s"), lpServerCharacter.CharIdx[slot].m_CID,
lpServerCharacter.CharIdx[slot].m_szCharName );
InsertItemEX(m_hServerNode, IDX_CHARACTER, szCharInfo);
// 해당 CID가 GM 로그를 가지고 있는지 확인 요청
CPacketMgr::GetInstance()->SendPktGMLogMsg(
PktAdminMgr::PktGMLogMsg::LOG_CONFIRM, lpServerCharacter.dwServerGroup,
dwTempUID, lpServerCharacter.CharIdx[slot].m_CID);
}
}
}
}
// 트리의 아이템을 더블 클릭했을 때의 이벤트 처리 함수
void CUserCharTreeView::OnNMDblclkChartree(NMHDR *pNMHDR, LRESULT *pResult)
{
if (SEL_TREEITEM_INFO::CHAR_NODE == m_stSelTreeItemInfo.m_cSelType)
{
CUserInfoDoc* Doc = static_cast<CUserInfoDoc*>(GetDocument());
unsigned int dwDocKey = Doc->m_lpUserInfo->m_dwDocKey;
// dwCID : 현재 트리에서 선택한 CID
// Doc->m_lpUserInfo->m_ModifyCharacter->GetCID() : 에디팅 중인 CID
// 현재 에디팅 중인 캐릭터가 아닐때
if ((CCharacterDoc::CharDocInfo::EMPTY == Doc->m_lpUserInfo->m_cCharacterState)
|| (CCharacterDoc::CharDocInfo::FINISH == Doc->m_lpUserInfo->m_cCharacterState))
{
if (NULL != Doc->m_lpUserInfo->m_ModifyCharacter)
{
CPacketMgr::GetInstance()->SendCloseCharacter(m_stSelTreeItemInfo.m_dwServerGroup,
Doc->m_lpUserInfo->m_ModifyCharacter->GetCID(), dwDocKey);
}
Doc->m_lpUserInfo->m_cCharacterState = CCharacterDoc::CharDocInfo::LOADING;
if (NULL != Doc->m_lpUserInfo)
{
CPacketMgr::GetInstance()->SendSelCharacter(
m_stSelTreeItemInfo.m_szCharName, m_stSelTreeItemInfo.m_dwServerGroup,
Doc->m_lpUserInfo->m_cOldServerGroup,
m_stSelTreeItemInfo.m_dwUID, m_stSelTreeItemInfo.m_dwCID, dwDocKey);
}
else
{
Report(GetLocalString("ADDED_STRING_058"), FAILED);
}
}
else
{
Report(GetLocalString("MSG_0133"), CAUTION);
}
}
*pResult = 0;
}
// 인자로 받은 CID가 블럭된 캐릭터인지 아닌지 판별하는 함수
int CUserCharTreeView::IsBlockedChar(UINT CID)
{
// 블럭된 캐릭인지 아닌지 검사한 후 적절한 아이콘 인덱스를 리턴
return rand() % 5;
}
void CUserCharTreeView::OnModifyCharName()
{
CModifyCharNameDlg dlg(this);
dlg.DoModal( );
}
BOOL CUserCharTreeView::PreTranslateMessage(MSG* pMsg)
{
return CFormView::PreTranslateMessage(pMsg);
}
void CUserCharTreeView::OnNMRclickChartree(NMHDR *pNMHDR, LRESULT *pResult)
{
*pResult = 0;
}
void CUserCharTreeView::OnBlockAccount()
{
if(m_stSelTreeItemInfo.m_cSelType == SEL_TREEITEM_INFO::UID_NODE)
{
CAddBlockUserDlg BlockUserDlg(this);
ZeroMemory(m_stLastBlockInfo.m_szCharacterName, BLOCK_INFO::MAX_NAME);
m_stLastBlockInfo.m_cType = BLOCK_INFO::ACCOUNT;
m_stLastBlockInfo.m_dwUID = m_stSelTreeItemInfo.m_dwUID;
m_stLastBlockInfo.m_dwServerGroup = 10000;
_sntprintf(m_stLastBlockInfo.m_szCharacterName,
BLOCK_INFO::MAX_NAME, m_stSelTreeItemInfo.m_szAccountName);
BlockUserDlg.DoModal();
}
}
void CUserCharTreeView::OnBlockCharacter()
{
if (m_stSelTreeItemInfo.m_cSelType == SEL_TREEITEM_INFO::CHAR_NODE)
{
CAddBlockUserDlg BlockUserDlg(this);
ZeroMemory(m_stLastBlockInfo.m_szCharacterName, BLOCK_INFO::MAX_NAME);
m_stLastBlockInfo.m_cType = BLOCK_INFO::CHARACTER;
m_stLastBlockInfo.m_dwUID = m_stSelTreeItemInfo.m_dwUID;
m_stLastBlockInfo.m_dwServerGroup = m_stSelTreeItemInfo.m_dwServerGroup;
_sntprintf(m_stLastBlockInfo.m_szCharacterName, BLOCK_INFO::MAX_NAME, m_stSelTreeItemInfo.m_szCharName);
BlockUserDlg.DoModal();
}
}
void CUserCharTreeView::OnDeleteChar()
{
/*
if(m_stSelTreeItemInfo.m_cSelType == SEL_TREEITEM_INFO::CHAR_NODE)
{
CPacketMgr::GetInstance()->SendPktDelCharacter(
m_stSelTreeItemInfo.m_dwUID, m_stSelTreeItemInfo.m_dwCID,
m_stSelTreeItemInfo.m_dwServerGroup, m_dwWndKey);
}
*/
}
void CUserCharTreeView::OnForcedDis()
{
if(m_stSelTreeItemInfo.m_cSelType == SEL_TREEITEM_INFO::UID_NODE)
{
CPacketMgr::GetInstance()->SendForcedDis(m_stSelTreeItemInfo.m_dwUID);
}
}
void CUserCharTreeView::OnTvnSelchangedChartree(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
HTREEITEM hCurrentNodeGrade = m_ctrlCharTree.GetSelectedItem();
if (NULL != hCurrentNodeGrade)
{
HTREEITEM hUpperNodeGrade = m_ctrlCharTree.GetParentItem(hCurrentNodeGrade);
HTREEITEM hLowerNodeGrade = m_ctrlCharTree.GetChildItem(hCurrentNodeGrade);
ZeroMemory(m_stSelTreeItemInfo.m_szAccountName, SEL_TREEITEM_INFO::MAX_NAME);
ZeroMemory(m_stSelTreeItemInfo.m_szCharName, SEL_TREEITEM_INFO::MAX_NAME);
if (NULL == hUpperNodeGrade)
{
// UID 노드 선택 : UID, 계정명 얻기
m_stSelTreeItemInfo.m_cSelType = SEL_TREEITEM_INFO::UID_NODE;
CString temp_str = m_ctrlCharTree.GetItemText(hCurrentNodeGrade);
_stscanf(temp_str, _T("%d %s"), &m_stSelTreeItemInfo.m_dwUID, &m_stSelTreeItemInfo.m_szAccountName);
}
else if(NULL == hLowerNodeGrade)
{
// 캐릭터 노드 선택 : UID, 계정명, 서버그룹 인덱스, CID, 캐릭명 얻기
m_stSelTreeItemInfo.m_cSelType = SEL_TREEITEM_INFO::CHAR_NODE;
CString temp_str = m_ctrlCharTree.GetItemText(
m_ctrlCharTree.GetParentItem(m_ctrlCharTree.GetParentItem(hCurrentNodeGrade)));
_stscanf(temp_str, _T("%d %s"), &m_stSelTreeItemInfo.m_dwUID, &m_stSelTreeItemInfo.m_szAccountName);
temp_str = m_ctrlCharTree.GetItemText(m_ctrlCharTree.GetParentItem(hCurrentNodeGrade));
CCharacterDoc::GetInstance().GetServerIndex(temp_str, m_stSelTreeItemInfo.m_dwServerGroup);
temp_str = m_ctrlCharTree.GetItemText(hCurrentNodeGrade);
_stscanf(temp_str, _T("%d %s"), &m_stSelTreeItemInfo.m_dwCID, &m_stSelTreeItemInfo.m_szCharName);
}
else
{
// 서버그룹 노드 선택 : UID, 계정명, 서버그룹 인덱스 얻기
m_stSelTreeItemInfo.m_cSelType = SEL_TREEITEM_INFO::GROUP_NODE;
CString temp_str = m_ctrlCharTree.GetItemText(m_ctrlCharTree.GetParentItem(hCurrentNodeGrade));
_stscanf(temp_str, _T("%d %s"), &m_stSelTreeItemInfo.m_dwUID, &m_stSelTreeItemInfo.m_szAccountName);
temp_str = m_ctrlCharTree.GetItemText(hCurrentNodeGrade);
CCharacterDoc::GetInstance().GetServerIndex(temp_str, m_stSelTreeItemInfo.m_dwServerGroup);
}
}
*pResult = 0;
}
void CUserCharTreeView::OnGmlogmanageUid()
{
if (SEL_TREEITEM_INFO::UID_NODE == m_stSelTreeItemInfo.m_cSelType)
{
CGMLogMsgDlg::DlgOwnerInfo stInfo;
stInfo.m_dwUID = m_stSelTreeItemInfo.m_dwUID;
stInfo.m_dwCID = 0;
stInfo.m_dwServerGroup = m_stSelTreeItemInfo.m_dwServerGroup;
CGMLogMsgDlg dlg(CGMLogMsgDlg::UID_LOG_TYPE, stInfo);
dlg.DoModal();
}
}
void CUserCharTreeView::OnGmlogmanageCid()
{
if (SEL_TREEITEM_INFO::CHAR_NODE == m_stSelTreeItemInfo.m_cSelType)
{
CGMLogMsgDlg::DlgOwnerInfo stInfo;
stInfo.m_dwUID = m_stSelTreeItemInfo.m_dwUID;
stInfo.m_dwCID = m_stSelTreeItemInfo.m_dwCID;
stInfo.m_dwServerGroup = m_stSelTreeItemInfo.m_dwServerGroup;
CGMLogMsgDlg dlg(CGMLogMsgDlg::CID_LOG_TYPE, stInfo);
dlg.DoModal();
}
}