mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-05-08 03:27:58 +03:00
733 lines
16 KiB
C++
733 lines
16 KiB
C++
// gp_statsDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "gp_stats.h"
|
|
#include "gp_statsDlg.h"
|
|
#include "../gpersist.h"
|
|
#include "../../ghttp/ghttp.h"
|
|
#include "../../common/gsAvailable.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// These are controls that are enabled when authenticated,
|
|
// and disabled when not authenticated.
|
|
//////////////////////////////////////////////////////////
|
|
CWnd * ToggleControls[64];
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CGp_statsDlg dialog
|
|
|
|
CGp_statsDlg::CGp_statsDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CGp_statsDlg::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CGp_statsDlg)
|
|
m_email = _T("dan@gamespy.com");
|
|
m_nick = _T("mrpants");
|
|
m_password = _T("mrpants");
|
|
m_profileID = 0;
|
|
m_type = 0;
|
|
m_value = _T("");
|
|
m_newKey = _T("");
|
|
//}}AFX_DATA_INIT
|
|
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
}
|
|
|
|
void CGp_statsDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CGp_statsDlg)
|
|
DDX_Control(pDX, IDC_KEYS, m_keys);
|
|
DDX_Text(pDX, IDC_EMAIL, m_email);
|
|
DDX_Text(pDX, IDC_NICK, m_nick);
|
|
DDX_Text(pDX, IDC_PASSWORD, m_password);
|
|
DDX_Text(pDX, IDC_PROFILE_ID, m_profileID);
|
|
DDX_Radio(pDX, IDC_PRIVATE_RW, m_type);
|
|
DDX_Text(pDX, IDC_VALUE, m_value);
|
|
DDX_Text(pDX, IDC_NEW_KEY, m_newKey);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CGp_statsDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CGp_statsDlg)
|
|
ON_BN_CLICKED(IDC_AUTHENTICATE, OnAuthenticate)
|
|
ON_WM_DESTROY()
|
|
ON_BN_CLICKED(IDC_GET, OnGet)
|
|
ON_BN_CLICKED(IDC_SET, OnSet)
|
|
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
|
ON_LBN_SELCHANGE(IDC_KEYS, OnSelchangeKeys)
|
|
ON_EN_CHANGE(IDC_VALUE, OnChangeValue)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CGp_statsDlg message handlers
|
|
|
|
BOOL CGp_statsDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
// Set the icon for this dialog. The framework does this automatically
|
|
// when the application's main window is not a dialog
|
|
SetIcon(m_hIcon, TRUE); // Set big icon
|
|
SetIcon(m_hIcon, FALSE); // Set small icon
|
|
|
|
// Build the list of toggle controls.
|
|
/////////////////////////////////////
|
|
int num = 0;
|
|
#define ADD_TOGGLE(id) ToggleControls[num++] = this->GetDlgItem(id)
|
|
ADD_TOGGLE(IDC_PRIVATE_RW);
|
|
ADD_TOGGLE(IDC_PRIVATE_RO);
|
|
ADD_TOGGLE(IDC_PUBLIC_RW);
|
|
ADD_TOGGLE(IDC_PUBLIC_RO);
|
|
ADD_TOGGLE(IDC_GET);
|
|
ADD_TOGGLE(IDC_SET);
|
|
ADD_TOGGLE(IDC_VALUE);
|
|
ADD_TOGGLE(IDC_KEYS);
|
|
ADD_TOGGLE(IDC_ADD);
|
|
ADD_TOGGLE(IDC_NEW_KEY);
|
|
ToggleControls[num++] = NULL;
|
|
|
|
// Init data.
|
|
/////////////
|
|
m_authenticated = FALSE;
|
|
m_gp = NULL;
|
|
|
|
// Put ourselves in the unauthenticated stats.
|
|
//////////////////////////////////////////////
|
|
UnAuthenticate();
|
|
|
|
// Init the connection to the stats manager.
|
|
////////////////////////////////////////////
|
|
CheckStatsConnection();
|
|
|
|
// Init GP.
|
|
///////////
|
|
if(gpInitialize(&m_gp, 0, 0, GP_PARTNERID_GAMESPY) != GP_NO_ERROR)
|
|
MessageBox("FAILED TO INITIALIZE GP!!!");
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
}
|
|
|
|
void CGp_statsDlg::OnDestroy()
|
|
{
|
|
CDialog::OnDestroy();
|
|
|
|
ClearKeys();
|
|
|
|
// Close the stats connection.
|
|
//////////////////////////////
|
|
CloseStatsConnection();
|
|
|
|
// Shutdown GP.
|
|
///////////////
|
|
gpDestroy(&m_gp);
|
|
|
|
// Shutdown GHTTP.
|
|
//////////////////
|
|
ghttpCleanup();
|
|
}
|
|
|
|
void CGp_statsDlg::Authenticated()
|
|
{
|
|
m_authenticated = TRUE;
|
|
|
|
// Enable controls.
|
|
///////////////////
|
|
int i;
|
|
for(i = 0 ; ToggleControls[i] ; i++)
|
|
ToggleControls[i]->EnableWindow();
|
|
}
|
|
|
|
void CGp_statsDlg::UnAuthenticate()
|
|
{
|
|
m_authenticated = FALSE;
|
|
m_profileID = 0;
|
|
|
|
// Disable controls.
|
|
////////////////////
|
|
int i;
|
|
for(i = 0 ; ToggleControls[i] ; i++)
|
|
ToggleControls[i]->EnableWindow(FALSE);
|
|
}
|
|
|
|
BOOL CGp_statsDlg::CheckStatsConnection()
|
|
{
|
|
// Are we connected?
|
|
////////////////////
|
|
if(IsStatsConnected())
|
|
return TRUE;
|
|
|
|
// Set the gamename and secret key.
|
|
///////////////////////////////////
|
|
#if 1
|
|
strcpy(gcd_gamename, "gmtest");
|
|
gcd_secret_key[0] = 'H';
|
|
gcd_secret_key[1] = 'A';
|
|
gcd_secret_key[2] = '6';
|
|
gcd_secret_key[3] = 'z';
|
|
gcd_secret_key[4] = 'k';
|
|
gcd_secret_key[5] = 'S';
|
|
gcd_secret_key[7] = '\0';
|
|
#else
|
|
strcpy(gcd_gamename, "excessive");
|
|
gcd_secret_key[0] = 'G';
|
|
gcd_secret_key[1] = 'n';
|
|
gcd_secret_key[2] = '3';
|
|
gcd_secret_key[3] = 'a';
|
|
gcd_secret_key[4] = 'Y';
|
|
gcd_secret_key[5] = '9';
|
|
gcd_secret_key[7] = '\0';
|
|
#endif
|
|
|
|
// check that the game's backend is available
|
|
GSIACResult ac_result;
|
|
GSIStartAvailableCheck(gcd_gamename);
|
|
while((ac_result = GSIAvailableCheckThink()) == GSIACWaiting)
|
|
msleep(5);
|
|
if(ac_result != GSIACAvailable)
|
|
{
|
|
MessageBox("The backend is not available\n");
|
|
return TRUE;
|
|
}
|
|
|
|
// Try to connect.
|
|
//////////////////
|
|
int result = InitStatsConnection(0);
|
|
if(result == GE_NOERROR)
|
|
return TRUE;
|
|
|
|
// Error!
|
|
/////////
|
|
CString message;
|
|
if(result == GE_NOSOCKET)
|
|
message = "Unable to create a socket.";
|
|
else if(result == GE_NODNS)
|
|
message = "Unable to resolve a DNS name.";
|
|
else if(result == GE_NOCONNECT)
|
|
message = "Unable to connect to stats server, or connection lost.";
|
|
else if(result == GE_DATAERROR)
|
|
message = "Bad data from the stats server.";
|
|
else
|
|
message = "Error.";
|
|
MessageBox(message, "Error connecting to the stats server");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CGp_statsDlg::SendPassword()
|
|
{
|
|
// Form the URL for the request.
|
|
////////////////////////////////
|
|
CString URL = "http://gamespyarcade.com/software/reqemail.asp?email=";
|
|
URL += m_email;
|
|
|
|
// Set the wait cursor.
|
|
///////////////////////
|
|
HCURSOR hPrevCursor = GetCursor();
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
// Do the request.
|
|
//////////////////
|
|
ghttpGetFile(URL, GHTTPTrue, NULL, NULL);
|
|
|
|
// Reset the previous cursor.
|
|
/////////////////////////////
|
|
SetCursor(hPrevCursor);
|
|
}
|
|
|
|
void CreateAccountCallback(GPConnection * connection, void * arg_, void * param)
|
|
{
|
|
GPNewUserResponseArg * arg = (GPNewUserResponseArg *)arg_;
|
|
int * pid = (int *)param;
|
|
|
|
// Store the result.
|
|
////////////////////
|
|
if(arg->result == GP_NO_ERROR)
|
|
*pid = arg->profile;
|
|
else
|
|
{
|
|
// If the nick was already in use, just pretend we created it.
|
|
//////////////////////////////////////////////////////////////
|
|
GPErrorCode errorCode;
|
|
gpGetErrorCode(connection, &errorCode);
|
|
if(errorCode == GP_NEWUSER_BAD_NICK)
|
|
*pid = arg->profile;
|
|
else
|
|
*pid = 0;
|
|
}
|
|
}
|
|
|
|
BOOL CGp_statsDlg::CreateAccount()
|
|
{
|
|
int pid;
|
|
int rcode;
|
|
|
|
// Create the account.
|
|
//////////////////////
|
|
GPResult result = gpNewUser(
|
|
&m_gp,
|
|
m_nick,
|
|
NULL,
|
|
m_email,
|
|
m_password,
|
|
NULL,
|
|
GP_BLOCKING,
|
|
CreateAccountCallback,
|
|
&pid);
|
|
if(result != GP_NO_ERROR)
|
|
{
|
|
MessageBox("There was an error creating the account.");
|
|
return FALSE;
|
|
}
|
|
|
|
// Check for success.
|
|
/////////////////////
|
|
if(pid)
|
|
{
|
|
m_profileID = pid;
|
|
return TRUE;
|
|
}
|
|
|
|
// Get the error code.
|
|
//////////////////////
|
|
GPErrorCode errorCode;
|
|
gpGetErrorCode(&m_gp, &errorCode);
|
|
|
|
// Handle the error code.
|
|
/////////////////////////
|
|
if(errorCode == GP_NEWUSER_BAD_PASSWORD)
|
|
{
|
|
rcode = MessageBox(
|
|
"You have entered an incorrect password for this e-mail address\n"
|
|
"Would you like the password sent to the e-mail address?",
|
|
NULL,
|
|
MB_YESNO);
|
|
|
|
// If no, we're done.
|
|
/////////////////////
|
|
if(rcode == IDNO)
|
|
return FALSE;
|
|
|
|
// Send the password.
|
|
/////////////////////
|
|
SendPassword();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// An unknown error code.
|
|
/////////////////////////
|
|
MessageBox("There was an error creating the account.");
|
|
return FALSE;
|
|
}
|
|
|
|
void CheckAccountCallback(GPConnection * connection, void * arg_, void * param)
|
|
{
|
|
GPCheckResponseArg * arg = (GPCheckResponseArg *)arg_;
|
|
int * pid = (int *)param;
|
|
|
|
// Store the result.
|
|
////////////////////
|
|
if(arg->result == GP_NO_ERROR)
|
|
*pid = arg->profile;
|
|
else
|
|
*pid = 0;
|
|
}
|
|
|
|
BOOL CGp_statsDlg::CheckAccount()
|
|
{
|
|
int pid;
|
|
int rcode;
|
|
|
|
// Check for the account.
|
|
/////////////////////////
|
|
GPResult result = gpCheckUser(
|
|
&m_gp,
|
|
m_nick,
|
|
m_email,
|
|
m_password,
|
|
GP_BLOCKING,
|
|
CheckAccountCallback,
|
|
&pid);
|
|
if(result != GP_NO_ERROR)
|
|
{
|
|
MessageBox("There was an error authenticating the account.");
|
|
return FALSE;
|
|
}
|
|
|
|
// Check for success.
|
|
/////////////////////
|
|
if(pid)
|
|
{
|
|
m_profileID = pid;
|
|
return TRUE;
|
|
}
|
|
|
|
// Get the error code.
|
|
//////////////////////
|
|
GPErrorCode errorCode;
|
|
gpGetErrorCode(&m_gp, &errorCode);
|
|
|
|
// Handle the error code.
|
|
/////////////////////////
|
|
if(errorCode == GP_CHECK_BAD_EMAIL)
|
|
{
|
|
// Ask if they want to create the account.
|
|
//////////////////////////////////////////
|
|
rcode = MessageBox(
|
|
"This account does not exist.\n"
|
|
"Would you like to create it?",
|
|
NULL,
|
|
MB_YESNO);
|
|
|
|
// If no, we're done.
|
|
/////////////////////
|
|
if(rcode == IDNO)
|
|
return FALSE;
|
|
|
|
// Create the account.
|
|
//////////////////////
|
|
return CreateAccount();
|
|
}
|
|
else if(errorCode == GP_CHECK_BAD_NICK)
|
|
{
|
|
rcode = MessageBox(
|
|
"There are no profiles under this account with the nick you have entered\n"
|
|
"Would you like to create one?",
|
|
NULL,
|
|
MB_YESNO);
|
|
|
|
// If no, we're done.
|
|
/////////////////////
|
|
if(rcode == IDNO)
|
|
return FALSE;
|
|
|
|
// Create the account.
|
|
//////////////////////
|
|
return CreateAccount();
|
|
}
|
|
else if(errorCode == GP_CHECK_BAD_PASSWORD)
|
|
{
|
|
rcode = MessageBox(
|
|
"You have entered an incorrect password for this e-mail address\n"
|
|
"Would you like the password sent to the e-mail address?",
|
|
NULL,
|
|
MB_YESNO);
|
|
|
|
// If no, we're done.
|
|
/////////////////////
|
|
if(rcode == IDNO)
|
|
return FALSE;
|
|
|
|
// Send the password.
|
|
/////////////////////
|
|
SendPassword();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// An unknown error code.
|
|
/////////////////////////
|
|
MessageBox("There was an error authenticating the account.");
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL statsAuthFinished;
|
|
void StatsAuthenticationCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance)
|
|
{
|
|
int * result = (int *)instance;
|
|
|
|
*result = authenticated;
|
|
|
|
if(authenticated != 1)
|
|
MessageBox(NULL, errmsg, "Error authenticating with the stats backend", MB_OK);
|
|
|
|
statsAuthFinished = TRUE;
|
|
}
|
|
|
|
BOOL CGp_statsDlg::StatsAuthentication()
|
|
{
|
|
char response[33];
|
|
int result;
|
|
|
|
// The auth call.
|
|
/////////////////
|
|
statsAuthFinished = FALSE;
|
|
PreAuthenticatePlayerPM(
|
|
0,
|
|
m_profileID,
|
|
GenerateAuth(GetChallenge(NULL), (char *)(LPCSTR)m_password, response),
|
|
StatsAuthenticationCallback,
|
|
&result);
|
|
|
|
// Wait for it to finish.
|
|
/////////////////////////
|
|
while(!statsAuthFinished)
|
|
if(!PersistThink())
|
|
CheckStatsConnection();
|
|
|
|
return (result == 1);
|
|
}
|
|
|
|
void CGp_statsDlg::OnAuthenticate()
|
|
{
|
|
// Update dialog members.
|
|
/////////////////////////
|
|
UpdateData();
|
|
|
|
// Sanity check args.
|
|
/////////////////////
|
|
if(!m_email.GetLength() || !m_nick.GetLength() || !m_password.GetLength())
|
|
{
|
|
MessageBox("E-mail, nick, and password must not be blank.");
|
|
return;
|
|
}
|
|
|
|
// If we're authenticated, unauthenticate.
|
|
//////////////////////////////////////////
|
|
if(m_authenticated)
|
|
UnAuthenticate();
|
|
|
|
// Check the account.
|
|
/////////////////////
|
|
if(!CheckAccount())
|
|
return;
|
|
|
|
// Do stats authentication.
|
|
///////////////////////////
|
|
if(!StatsAuthentication())
|
|
return;
|
|
|
|
// We're authenticated.
|
|
///////////////////////
|
|
Authenticated();
|
|
|
|
// Update dialog display.
|
|
/////////////////////////
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
persisttype_t TypeConversion(int type)
|
|
{
|
|
if(type == 0)
|
|
return pd_private_rw;
|
|
if(type == 1)
|
|
return pd_private_ro;
|
|
if(type == 2)
|
|
return pd_public_rw;
|
|
return pd_public_ro;
|
|
}
|
|
|
|
BOOL GetKeyValue(LPCSTR src, CString & key, CString & value)
|
|
{
|
|
const char * str;
|
|
const char * keyStart;
|
|
const char * valueStart;
|
|
int keyLen;
|
|
int valueLen;
|
|
|
|
// Check for no input.
|
|
//////////////////////
|
|
if(!src)
|
|
return FALSE;
|
|
|
|
// Check the starting \.
|
|
////////////////////////
|
|
if(src[0] != '\\')
|
|
return FALSE;
|
|
|
|
// Clear the key and value.
|
|
///////////////////////////
|
|
key.Empty();
|
|
value.Empty();
|
|
|
|
// Find the key and value, plus lengths.
|
|
////////////////////////////////////////
|
|
keyStart = (src + 1);
|
|
valueStart = strchr(keyStart, '\\');
|
|
if(!valueStart || (valueStart == keyStart))
|
|
return FALSE;
|
|
keyLen = (valueStart - keyStart);
|
|
valueStart++;
|
|
str = strchr(valueStart, '\\');
|
|
if(str)
|
|
valueLen = (str - valueStart);
|
|
else
|
|
valueLen = strlen(valueStart);
|
|
|
|
// Copy off the key.
|
|
////////////////////
|
|
char * keyStr = key.GetBuffer(keyLen);
|
|
memcpy(keyStr, keyStart, keyLen);
|
|
key.ReleaseBuffer(keyLen);
|
|
|
|
// Copy off the value.
|
|
////////////////////
|
|
char * valueStr = value.GetBuffer(valueLen);
|
|
memcpy(valueStr, valueStart, valueLen);
|
|
value.ReleaseBuffer(valueLen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CGp_statsDlg::ClearKeys()
|
|
{
|
|
int count = m_keys.GetCount();
|
|
int i;
|
|
for(i = 0 ; i < count ; i++)
|
|
delete (CString *)m_keys.GetItemDataPtr(i);
|
|
m_keys.ResetContent();
|
|
}
|
|
|
|
void CGp_statsDlg::GotData(LPCSTR data)
|
|
{
|
|
CString key;
|
|
CString value;
|
|
int nIndex;
|
|
|
|
// Go through the keys/values.
|
|
//////////////////////////////
|
|
while(GetKeyValue(data, key, value))
|
|
{
|
|
// Adjust the data based on the key and value lengths.
|
|
//////////////////////////////////////////////////////
|
|
data += (key.GetLength() + value.GetLength() + 2);
|
|
|
|
// Add the new key/value.
|
|
/////////////////////////
|
|
nIndex = m_keys.AddString(key);
|
|
if(nIndex != -1)
|
|
m_keys.SetItemDataPtr(nIndex, new CString(value));
|
|
}
|
|
}
|
|
|
|
BOOL getDataFinished;
|
|
void GetDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance)
|
|
{
|
|
getDataFinished = TRUE;
|
|
|
|
if(success)
|
|
{
|
|
CGp_statsDlg * dlg = (CGp_statsDlg *)instance;
|
|
dlg->GotData(data);
|
|
}
|
|
}
|
|
|
|
void CGp_statsDlg::OnGet()
|
|
{
|
|
// Update dialog members.
|
|
/////////////////////////
|
|
UpdateData();
|
|
|
|
// Clear the keys and value.
|
|
////////////////////////////
|
|
ClearKeys();
|
|
m_value.Empty();
|
|
|
|
// Make sure we're connected to the stats server.
|
|
/////////////////////////////////////////////////
|
|
if(!CheckStatsConnection())
|
|
return;
|
|
|
|
// Get the data.
|
|
////////////////
|
|
getDataFinished = FALSE;
|
|
GetPersistDataValues(0, m_profileID, TypeConversion(m_type), 0, "", GetDataCallback, this);
|
|
while(!getDataFinished)
|
|
if(!PersistThink())
|
|
CheckStatsConnection();
|
|
|
|
// Update dialog display.
|
|
/////////////////////////
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
BOOL setDataFinished;
|
|
void SetDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance)
|
|
{
|
|
setDataFinished = TRUE;
|
|
}
|
|
|
|
void CGp_statsDlg::OnSet()
|
|
{
|
|
// Update dialog members.
|
|
/////////////////////////
|
|
UpdateData();
|
|
|
|
// Make sure we're connected to the stats server.
|
|
/////////////////////////////////////////////////
|
|
if(!CheckStatsConnection())
|
|
return;
|
|
|
|
// Build the data string.
|
|
/////////////////////////
|
|
int count = m_keys.GetCount();
|
|
int i;
|
|
CString data;
|
|
CString key;
|
|
CString * value;
|
|
for(i = 0 ; i < count ; i++)
|
|
{
|
|
m_keys.GetText(i, key);
|
|
value = (CString *)m_keys.GetItemDataPtr(i);
|
|
|
|
data += '\\';
|
|
data += key;
|
|
data += '\\';
|
|
data += *value;
|
|
}
|
|
|
|
// Set some data.
|
|
/////////////////
|
|
setDataFinished = FALSE;
|
|
SetPersistDataValues(0, m_profileID, TypeConversion(m_type), 0, (char *)(LPCSTR)data, SetDataCallback, this);
|
|
while(!setDataFinished)
|
|
if(!PersistThink())
|
|
CheckStatsConnection();
|
|
}
|
|
|
|
void CGp_statsDlg::OnSelchangeKeys()
|
|
{
|
|
UpdateData();
|
|
|
|
// Get the new key/value.
|
|
/////////////////////////
|
|
int nIndex = m_keys.GetCurSel();
|
|
if(nIndex != -1)
|
|
m_value = *(CString *)m_keys.GetItemDataPtr(nIndex);
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CGp_statsDlg::OnAdd()
|
|
{
|
|
UpdateData();
|
|
|
|
if(m_newKey.IsEmpty())
|
|
return;
|
|
|
|
int nIndex = m_keys.AddString(m_newKey);
|
|
if(nIndex != -1)
|
|
m_keys.SetItemDataPtr(nIndex, new CString);
|
|
|
|
m_newKey.Empty();
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CGp_statsDlg::OnChangeValue()
|
|
{
|
|
UpdateData();
|
|
int nIndex = m_keys.GetCurSel();
|
|
if(nIndex != -1)
|
|
{
|
|
CString * string = (CString *)m_keys.GetItemDataPtr(nIndex);
|
|
*string = m_value;
|
|
}
|
|
}
|