Files
Client/Tools/PatchMaker/SettingOptionPage.cpp
LGram16 e067522598 Initial commit: ROW Client source code
Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 16:24:34 +09:00

447 lines
13 KiB
C++

// SettingOptionPage.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "PatchMaker.h"
#include "SettingOptionPage.h"
#include "UtilityFunc.h"
#include "PMSettingConstant.h"
#include ".\settingoptionpage.h"
// CSettingOptionPage 대화 상자입니다.
IMPLEMENT_DYNAMIC(CSettingOptionPage, CPropertyPage)
CSettingOptionPage::CSettingOptionPage(CPMSetting& pmSetting, CPropertySheet& ownerSheet)
: CPropertyPage(CSettingOptionPage::IDD)
, m_dwManualPatchMinVer(100)
, m_OwnerSheet(ownerSheet)
, m_pmSettingOption(pmSetting)
{
}
CSettingOptionPage::~CSettingOptionPage()
{
}
void CSettingOptionPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CB_OPT_PATCH_TYPE, m_cbPatchType);
DDX_Control(pDX, IDC_ED_OPT_OLD_PKG, m_edOldPkgPos);
DDX_Control(pDX, IDC_ED_OPT_NEW_CLIENT, m_edNewClientPos);
DDX_Control(pDX, IDC_ED_OPT_NEW_PKG, m_edNewPkgPos);
DDX_Control(pDX, IDC_ED_OPT_MAX_PKG, m_edMaxPkgSize);
DDX_Control(pDX, IDC_CB_OPT_OLD_PKG_POS, m_cbPkgPos);
DDX_Control(pDX, IDC_ED_OPT_FTP_ADDR, m_edFTPAddr);
DDX_Control(pDX, IDC_ED_OPT_FTP_PORT, m_edFTPPort);
DDX_Control(pDX, IDC_CK_OPT_FTP_PASSIVE, m_bFTPPassive);
DDX_Control(pDX, IDC_ED_OPT_MANUAL_PATCH_FILE, m_edManualPatchFolder);
DDX_Control(pDX, IDC_ED_OPT_MANUAL_SFX_FILE, m_edManualPatchSFXFile);
DDX_Control(pDX, IDC_ED_OPT_MANUAL_MIN_VER, m_edManualPatchMinVer);
DDX_Text(pDX, IDC_ED_OPT_MANUAL_MIN_VER, m_dwManualPatchMinVer);
DDV_MinMaxUInt(pDX, m_dwManualPatchMinVer, 100, 10000);
}
BEGIN_MESSAGE_MAP(CSettingOptionPage, CPropertyPage)
ON_BN_CLICKED(IDC_BTN_OPT_OLD_PKG, OnBnClickedBtnOptOldPkg)
ON_BN_CLICKED(IDC_BTN_OPT_NEW_CLIENT, OnBnClickedBtnOptNewClient)
ON_BN_CLICKED(IDC_BTN_OPT_NEW_PKG, OnBnClickedBtnOptNewPkg)
ON_BN_CLICKED(IDC_BTN_OPT_MANUAL_PATCH_FILE, OnBnClickedBtnOptManualPatchFile)
ON_BN_CLICKED(IDC_BTN_OPT_MANUAL_SFX_FILE, OnBnClickedBtnOptManualSfxFile)
ON_BN_CLICKED(ID_SAVE_SETUP, OnBnClickedSaveSetup)
ON_BN_CLICKED(ID_LOAD_SETUP, OnBnClickedLoadSetup)
ON_REGISTERED_MESSAGE(PMConst::AP_SETTING_ENABLE, OnEnableAutoPatchOption)
ON_REGISTERED_MESSAGE(PMConst::AP_SETTING_DISABLE, OnDisableAutoPatchOption)
ON_REGISTERED_MESSAGE(PMConst::MP_SETTING_ENABLE, OnEnableManualPatchOption)
ON_REGISTERED_MESSAGE(PMConst::MP_SETTING_DISABLE, OnDisableManualPatchOption)
ON_CBN_SELCHANGE(IDC_CB_OPT_OLD_PKG_POS, OnCbnSelchangeCbOptOldPkgPos)
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CSettingOptionPage 메시지 처리기입니다.
inline int AddCBString(CComboBox& combo, CString& tempString, int nIndex, UINT nID)
{
tempString.LoadString(nID);
return combo.InsertString(nIndex, tempString);
}
BOOL CSettingOptionPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
// TODO: 여기에 추가 초기화 작업을 추가합니다.
CString szTmp;
m_cbPatchType.InsertString(0, PMConst::PatchType_Part1);
m_cbPatchType.InsertString(1, PMConst::PatchType_BattleLohan);
m_cbPatchType.InsertString(2, PMConst::PatchType_Part2);
m_cbPatchType.InsertString(3, PMConst::PatchType_Part2Test);
m_cbPatchType.InsertString(4, PMConst::PatchType_Part2Malay);
AddCBString(m_cbPkgPos, szTmp, 0, IDS_CB_FTP);
AddCBString(m_cbPkgPos, szTmp, 1, IDS_CB_LOCAL);
OnCbnSelchangeCbOptOldPkgPos();
return TRUE; // return TRUE unless you set the focus to a control
// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}
void CSettingOptionPage::OnBnClickedBtnOptOldPkg()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
PMUtil::BrowseForFolder(GetSafeHwnd(),
_T("예전 패키지가 있는 폴더를 선택해주세요"), m_edOldPkgPos);
}
void CSettingOptionPage::OnBnClickedBtnOptNewClient()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
PMUtil::BrowseForFolder(GetSafeHwnd(),
_T("깨끗한 클라이언트 파일이 있는 폴더를 선택해주세요"), m_edNewClientPos);
}
void CSettingOptionPage::OnBnClickedBtnOptNewPkg()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
PMUtil::BrowseForFolder(GetSafeHwnd(),
_T("새 패키지 파일이 저장될 루트 폴더를 선택해주세요"), m_edNewPkgPos);
}
void CSettingOptionPage::OnBnClickedBtnOptManualPatchFile()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
PMUtil::BrowseForFolder(GetSafeHwnd(),
_T("수동 패치 파일이 위치한 폴더를 선택해주세요"), m_edManualPatchFolder);
}
void CSettingOptionPage::OnBnClickedBtnOptManualSfxFile()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
CString szFileName;
if (PMUtil::BrowseForExisingFile(this->GetSafeHwnd(),
_T("수동 패치 SFX파일을 선택해주세요"), "SFX File\0*.exe", szFileName))
{
m_edManualPatchSFXFile.SetWindowText(szFileName);
}
}
void CSettingOptionPage::OnBnClickedSaveSetup()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
UpdateSetupData(TRUE);
if (!m_pmSettingOption.SaveSetting())
{
MessageBox(_T("셋업 파일을 저장하기 위해서 여는 데 실패했습니다"),
_T("파일 열기 오류"), MB_OK | MB_ICONEXCLAMATION);
}
}
void CSettingOptionPage::OnBnClickedLoadSetup()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if (m_pmSettingOption.LoadSetting())
{
UpdateSetupData(FALSE);
OnCbnSelchangeCbOptOldPkgPos();
}
else
{
MessageBox(_T("셋업 파일을 불러오기 위해서 여는 데 실패했습니다"),
_T("파일 열기 오류"), MB_OK | MB_ICONEXCLAMATION);
}
}
void SetCBSel(CComboBox& cb, CString& szValue, int nDefaultSel = 0)
{
CString szCBValue;
int nMaxCount = cb.GetCount();
for (int nCount = 0; nCount < nMaxCount; ++nCount)
{
cb.GetLBText(nCount, szCBValue);
if (0 == szValue.CompareNoCase(szCBValue))
{
cb.SetCurSel(nCount);
break;
}
}
if (nCount == nMaxCount)
{
// 찾아봐서 맞는 문자열이 없으면 기본값으로 선택
cb.SetCurSel(nDefaultSel);
}
}
void CSettingOptionPage::UpdateSetupData(bool bSaveAndValidate)
{
CString szValue;
struct KeyValuePair
{
LPCTSTR m_szKey;
CEdit& m_edValue;
};
KeyValuePair keyValueData[] =
{
{ PMConst::AP_OldPkg, m_edOldPkgPos },
{ PMConst::AP_NewClient, m_edNewClientPos },
{ PMConst::AP_NewPkg, m_edNewPkgPos },
{ PMConst::AP_MaxPkg, m_edMaxPkgSize },
{ PMConst::AP_FTPAddr, m_edFTPAddr },
{ PMConst::AP_FTPPort, m_edFTPPort },
{ PMConst::MP_Folder, m_edManualPatchFolder },
{ PMConst::MP_SFXFile, m_edManualPatchSFXFile }
};
const int nMaxData = sizeof(keyValueData) / sizeof(KeyValuePair);
if (!bSaveAndValidate)
{
// 셋업 맵의 데이터를 컨트롤로 저장한다.
for (int nCount = 0; nCount < nMaxData; ++nCount)
{
m_pmSettingOption.GetSettingData(keyValueData[nCount].m_szKey, szValue);
keyValueData[nCount].m_edValue.SetWindowText(szValue);
}
m_pmSettingOption.GetSettingData(PMConst::PatchType, szValue);
SetCBSel(m_cbPatchType, szValue);
m_pmSettingOption.GetSettingData(PMConst::AP_PkgPosType, szValue);
SetCBSel(m_cbPkgPos, szValue);
m_pmSettingOption.GetSettingData(PMConst::AP_FTPPassive, szValue);
m_bFTPPassive.SetCheck(0 == szValue.CompareNoCase(_T("TRUE")) ? BST_CHECKED : BST_UNCHECKED);
m_pmSettingOption.GetSettingData(PMConst::MP_MinVer, szValue);
long nVersion = atol(szValue);
if (nVersion < 100) { nVersion = 100; }
m_dwManualPatchMinVer = nVersion;
// 컨트롤 데이터를 화면에 반영한다.
UpdateData(FALSE);
}
else
{
// 화면 데이터를 컨트롤에 읽어온다.
UpdateData(TRUE);
// 컨트롤의 데이터를 셋업 맵에 저장한다.
for (int nCount = 0; nCount < nMaxData; ++nCount)
{
keyValueData[nCount].m_edValue.GetWindowText(szValue);
m_pmSettingOption.SetSettingData(keyValueData[nCount].m_szKey, szValue);
}
int nCurSel = m_cbPatchType.GetCurSel();
if (CB_ERR != nCurSel)
{
m_cbPatchType.GetLBText(nCurSel, szValue);
m_pmSettingOption.SetSettingData(PMConst::PatchType, szValue);
}
nCurSel = m_cbPkgPos.GetCurSel();
if (CB_ERR != nCurSel)
{
m_cbPkgPos.GetLBText(nCurSel, szValue);
m_pmSettingOption.SetSettingData(PMConst::AP_PkgPosType, szValue);
}
m_pmSettingOption.SetSettingData(PMConst::AP_FTPPassive,
BST_CHECKED == m_bFTPPassive.GetCheck() ? _T("TRUE") : _T("FALSE"));
szValue.Format("%u", m_dwManualPatchMinVer);
m_pmSettingOption.SetSettingData(PMConst::MP_MinVer, szValue);
}
}
bool CSettingOptionPage::IsEmptyOption()
{
if (CB_ERR == m_cbPatchType.GetCurSel() ||
0 == m_edOldPkgPos.GetWindowTextLength() ||
0 == m_edNewClientPos.GetWindowTextLength() ||
0 == m_edNewPkgPos.GetWindowTextLength() ||
0 == m_edMaxPkgSize.GetWindowTextLength() ||
CB_ERR == m_cbPkgPos.GetCurSel() ||
0 == m_edManualPatchFolder.GetWindowTextLength() ||
0 == m_edManualPatchSFXFile.GetWindowTextLength() ||
m_dwManualPatchMinVer < 100 ||
10000 < m_dwManualPatchMinVer)
{
// 빈 항목이 있으면 실패!
return true;
}
CString szPkgPos, szFTPPos((LPCTSTR)IDS_CB_FTP);
m_cbPkgPos.GetLBText(m_cbPkgPos.GetCurSel(), szPkgPos);
if (0 == szPkgPos.CompareNoCase(szFTPPos) &&
(0 == m_edFTPAddr.GetWindowTextLength() ||
0 == m_edFTPPort.GetWindowTextLength()))
{
// FTP를 선택했는데, 주소나 Port가 없으면 실패!
return true;
}
return false;
}
BOOL CSettingOptionPage::OnKillActive()
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
if (this == m_OwnerSheet.GetActivePage())
{
// 페이지를 옮기면 자동으로 저장됨
SendMessage(WM_COMMAND, MAKEWPARAM(ID_SAVE_SETUP, BN_CLICKED));
if (IsEmptyOption())
{
MessageBox(_T("기록하지 않은 설정이 있습니다. 남은 설정을 모두 입력해 주십시오"),
_T("옵션 설정"), MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
}
return CPropertyPage::OnKillActive();
}
BOOL CSettingOptionPage::OnSetActive()
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
SendMessage(WM_COMMAND, MAKEWPARAM(ID_LOAD_SETUP, BN_CLICKED));
return CPropertyPage::OnSetActive();
}
afx_msg LRESULT CSettingOptionPage::OnEnableAutoPatchOption(WPARAM wParam, LPARAM lParam)
{
SetAutoPatchOption(true);
return 0;
}
afx_msg LRESULT CSettingOptionPage::OnDisableAutoPatchOption(WPARAM wParam, LPARAM lParam)
{
SetAutoPatchOption(false);
return 0;
}
afx_msg LRESULT CSettingOptionPage::OnEnableManualPatchOption(WPARAM wParam, LPARAM lParam)
{
SetManualPatchOption(true);
return 0;
}
afx_msg LRESULT CSettingOptionPage::OnDisableManualPatchOption(WPARAM wParam, LPARAM lParam)
{
SetManualPatchOption(false);
return 0;
}
void CSettingOptionPage::SetAutoPatchOption(bool bEnable)
{
UINT nDisableID[] =
{
IDC_BTN_OPT_OLD_PKG,
IDC_BTN_OPT_NEW_CLIENT,
IDC_BTN_OPT_NEW_PKG,
};
PMUtil::EnableDlgItems(*this, nDisableID,
sizeof(nDisableID)/sizeof(UINT), bEnable);
if (bEnable && !theApp.IsManualPatchOperate())
{
// 수동패치가 작동 안할때만 Enable
m_cbPatchType.EnableWindow(TRUE);
}
else
{
m_cbPatchType.EnableWindow(FALSE);
}
m_cbPkgPos.EnableWindow(bEnable);
m_bFTPPassive.EnableWindow(bEnable);
m_edOldPkgPos.SetReadOnly(!bEnable);
m_edMaxPkgSize.SetReadOnly(!bEnable);
m_edFTPAddr.SetReadOnly(!bEnable);
m_edFTPPort.SetReadOnly(!bEnable);
}
void CSettingOptionPage::SetManualPatchOption(bool bEnable)
{
UINT nDisableID[] =
{
IDC_BTN_OPT_MANUAL_PATCH_FILE,
IDC_BTN_OPT_MANUAL_SFX_FILE
};
PMUtil::EnableDlgItems(*this, nDisableID,
sizeof(nDisableID)/sizeof(UINT), bEnable);
if (bEnable && !theApp.IsAutoPatchOperate())
{
// 자동패치가 작동 안할때만 Enable
m_cbPatchType.EnableWindow(TRUE);
}
else
{
m_cbPatchType.EnableWindow(FALSE);
}
m_edManualPatchMinVer.SetReadOnly(!bEnable);
}
void CSettingOptionPage::OnCbnSelchangeCbOptOldPkgPos()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
BOOL bEnableFTP = FALSE;
int nCurSel = m_cbPkgPos.GetCurSel();
if (CB_ERR != nCurSel)
{
CString szFTP((LPCTSTR)IDS_CB_FTP);
CString szCurrentSel;
m_cbPkgPos.GetLBText(nCurSel, szCurrentSel);
if (0 == szCurrentSel.CompareNoCase(szFTP))
{
bEnableFTP = TRUE;
}
}
m_edFTPAddr.EnableWindow(bEnableFTP);
m_edFTPPort.EnableWindow(bEnableFTP);
m_bFTPPassive.EnableWindow(bEnableFTP);
m_edOldPkgPos.SetReadOnly(!bEnableFTP);
}
void CSettingOptionPage::OnDestroy()
{
SendMessage(WM_COMMAND, MAKEWPARAM(ID_SAVE_SETUP, BN_CLICKED));
CPropertyPage::OnDestroy();
}