Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

653 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // RunMapExpertDlg.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "hammer.h"
  12. #include "RunMapExpertDlg.h"
  13. #include "RunMapCfgDlg.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include <tier0/memdbgon.h>
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CRunMapExpertDlg dialog
  18. CRunMapExpertDlg::CRunMapExpertDlg(CWnd* pParent /*=NULL*/)
  19. : CDialog(CRunMapExpertDlg::IDD, pParent)
  20. {
  21. //{{AFX_DATA_INIT(CRunMapExpertDlg)
  22. //}}AFX_DATA_INIT
  23. m_pActiveSequence = NULL;
  24. m_bNoUpdateCmd = FALSE;
  25. m_bSwitchMode = FALSE;
  26. }
  27. void CRunMapExpertDlg::DoDataExchange(CDataExchange* pDX)
  28. {
  29. CDialog::DoDataExchange(pDX);
  30. //{{AFX_DATA_MAP(CRunMapExpertDlg)
  31. DDX_Control(pDX, IDC_USEPROCESSWND, m_cUseProcessWnd);
  32. DDX_Control(pDX, IDC_CONFIGURATIONS, m_cCmdSequences);
  33. DDX_Control(pDX, IDC_MOVEUP, m_cMoveUp);
  34. DDX_Control(pDX, IDC_MOVEDOWN, m_cMoveDown);
  35. DDX_Control(pDX, IDC_ENSUREFN, m_cEnsureFn);
  36. DDX_Control(pDX, IDC_ENSURECHECK, m_cEnsureCheck);
  37. DDX_Control(pDX, IDC_PARAMETERS, m_cParameters);
  38. DDX_Control(pDX, IDC_COMMAND, m_cCommand);
  39. //}}AFX_DATA_MAP
  40. DDX_Control(pDX, IDC_COMMANDLIST, m_cCommandList);
  41. }
  42. // dvs: this is duplicated in OPTBuild.cpp!!
  43. enum
  44. {
  45. id_InsertParmMapFileNoExt = 0x100,
  46. id_InsertParmMapFile,
  47. id_InsertParmMapPath,
  48. id_InsertParmBspDir,
  49. id_InsertParmExeDir,
  50. id_InsertParmGameDir,
  51. id_InsertParmEnd
  52. };
  53. enum
  54. {
  55. id_BrExecutable = 0x150,
  56. id_BrChangeDir,
  57. id_BrCopyFile,
  58. id_BrDelFile,
  59. id_BrRenameFile,
  60. id_BrGameProgram,
  61. id_BrVISProgram,
  62. id_BrBSPProgram,
  63. id_BrLIGHTProgram,
  64. id_BrEnd
  65. };
  66. BEGIN_MESSAGE_MAP(CRunMapExpertDlg, CDialog)
  67. //{{AFX_MSG_MAP(CRunMapExpertDlg)
  68. ON_BN_CLICKED(IDC_BROWSECOMMAND, OnBrowsecommand)
  69. ON_LBN_SELCHANGE(IDC_COMMANDLIST, OnSelchangeCommandlist)
  70. ON_BN_CLICKED(IDC_INSERTPARM, OnInsertparm)
  71. ON_BN_CLICKED(IDC_MOVEDOWN, OnMovedown)
  72. ON_BN_CLICKED(IDC_MOVEUP, OnMoveup)
  73. ON_BN_CLICKED(IDC_NEW, OnNew)
  74. ON_BN_CLICKED(IDC_NORMAL, OnNormal)
  75. ON_BN_CLICKED(IDC_REMOVE, OnRemove)
  76. ON_EN_UPDATE(IDC_COMMAND, OnUpdateCommand)
  77. ON_EN_UPDATE(IDC_PARAMETERS, OnUpdateParameters)
  78. ON_BN_CLICKED(IDC_ENSURECHECK, OnEnsurecheck)
  79. ON_EN_UPDATE(IDC_ENSUREFN, OnUpdateEnsurefn)
  80. ON_CBN_SELCHANGE(IDC_CONFIGURATIONS, OnSelchangeConfigurations)
  81. ON_BN_CLICKED(IDC_EDITCONFIGS, OnEditconfigs)
  82. ON_BN_CLICKED(IDC_USEPROCESSWND, OnUseprocesswnd)
  83. ON_COMMAND_EX_RANGE(id_InsertParmMapFileNoExt, id_InsertParmEnd, HandleInsertParm)
  84. ON_COMMAND_EX_RANGE(id_BrExecutable, id_BrEnd, HandleInsertCommand)
  85. //}}AFX_MSG_MAP
  86. END_MESSAGE_MAP()
  87. /////////////////////////////////////////////////////////////////////////////
  88. // CRunMapExpertDlg message handlers
  89. BOOL CRunMapExpertDlg::HandleInsertCommand(UINT nID)
  90. // insert a parm at the current cursor location into the parameters
  91. // edit control
  92. {
  93. PCCOMMAND pCommand = GetCommandAtIndex(NULL);
  94. if(!pCommand)
  95. return TRUE; // no command
  96. if(nID == id_BrExecutable)
  97. {
  98. CFileDialog dlg(TRUE, "exe", NULL, OFN_HIDEREADONLY |
  99. OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
  100. "Executable Files|*.exe||", this);
  101. if(dlg.DoModal() == IDCANCEL)
  102. return TRUE;
  103. m_cCommand.SetWindowText(dlg.m_ofn.lpstrFile);
  104. pCommand->iSpecialCmd = 0;
  105. }
  106. else
  107. {
  108. pCommand->iSpecialCmd = 0;
  109. switch(nID)
  110. {
  111. case id_BrCopyFile:
  112. pCommand->iSpecialCmd = CCCopyFile;
  113. break;
  114. case id_BrDelFile:
  115. pCommand->iSpecialCmd = CCDelFile;
  116. break;
  117. case id_BrRenameFile:
  118. pCommand->iSpecialCmd = CCRenameFile;
  119. break;
  120. case id_BrChangeDir:
  121. pCommand->iSpecialCmd = CCChangeDir;
  122. break;
  123. case id_BrGameProgram:
  124. m_cCommand.SetWindowText("$game_exe");
  125. break;
  126. case id_BrVISProgram:
  127. m_cCommand.SetWindowText("$vis_exe");
  128. break;
  129. case id_BrLIGHTProgram:
  130. m_cCommand.SetWindowText("$light_exe");
  131. break;
  132. case id_BrBSPProgram:
  133. m_cCommand.SetWindowText("$bsp_exe");
  134. break;
  135. }
  136. if(pCommand->iSpecialCmd)
  137. pCommand->bLongFilenames = TRUE;
  138. OnSelchangeCommandlist();
  139. UpdateCommandWithEditFields(-1);
  140. }
  141. return TRUE;
  142. }
  143. void CRunMapExpertDlg::OnBrowsecommand(void)
  144. {
  145. CMenu menu;
  146. menu.CreatePopupMenu();
  147. menu.AppendMenu(MF_STRING, id_BrExecutable, "Executable");
  148. menu.AppendMenu(MF_STRING, id_BrChangeDir, "Change Directory");
  149. menu.AppendMenu(MF_STRING, id_BrCopyFile, "Copy File");
  150. menu.AppendMenu(MF_STRING, id_BrDelFile, "Delete File");
  151. menu.AppendMenu(MF_STRING, id_BrRenameFile, "Rename File");
  152. menu.AppendMenu(MF_SEPARATOR);
  153. menu.AppendMenu(MF_STRING, id_BrBSPProgram, "BSP program");
  154. menu.AppendMenu(MF_STRING, id_BrVISProgram, "VIS program");
  155. menu.AppendMenu(MF_STRING, id_BrLIGHTProgram, "LIGHT program");
  156. menu.AppendMenu(MF_STRING, id_BrGameProgram, "Game program");
  157. // track menu
  158. CWnd *pButton = GetDlgItem(IDC_BROWSECOMMAND);
  159. CRect r;
  160. pButton->GetWindowRect(r);
  161. menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, r.left, r.bottom, this, NULL);
  162. }
  163. LPCTSTR CRunMapExpertDlg::GetCmdString(PCCOMMAND pCommand)
  164. {
  165. switch(pCommand->iSpecialCmd)
  166. {
  167. case 0:
  168. return pCommand->szRun;
  169. case CCCopyFile:
  170. return "Copy File";
  171. case CCDelFile:
  172. return "Delete File";
  173. case CCRenameFile:
  174. return "Rename File";
  175. case CCChangeDir:
  176. return "Change Directory";
  177. }
  178. return "";
  179. }
  180. void CRunMapExpertDlg::OnSelchangeCommandlist()
  181. {
  182. int iIndex = -1;
  183. // change the selection in the command list - update the command
  184. // and parameters edit boxes
  185. PCCOMMAND pCommand = GetCommandAtIndex(&iIndex);
  186. // enable/disable controls
  187. BOOL bEnable = pCommand ? TRUE : FALSE;
  188. int iEnableCmds[] =
  189. {
  190. // edit fields:
  191. IDC_COMMAND,
  192. IDC_PARAMETERS,
  193. IDC_ENSUREFN,
  194. // checkboxes/buttons:
  195. IDC_ENSURECHECK,
  196. IDC_USEPROCESSWND,
  197. IDC_INSERTPARM,
  198. IDC_BROWSECOMMAND,
  199. -1
  200. };
  201. m_bNoUpdateCmd = TRUE;
  202. for(int i = 0; iEnableCmds[i] != -1; i++)
  203. {
  204. CWnd *pWnd = GetDlgItem(iEnableCmds[i]);
  205. pWnd->EnableWindow(bEnable);
  206. if(bEnable == FALSE)
  207. {
  208. // ensure fields are cleared if we're disabling them
  209. if(i < 3)
  210. pWnd->SetWindowText("");
  211. else
  212. ((CButton*)pWnd)->SetCheck(0);
  213. }
  214. }
  215. m_bNoUpdateCmd = FALSE;
  216. if(!pCommand)
  217. return;
  218. // set moveup/movedown buttons
  219. m_cMoveUp.EnableWindow(iIndex != 0);
  220. m_cMoveDown.EnableWindow(iIndex != m_cCommandList.GetCount() - 1);
  221. m_bNoUpdateCmd = TRUE;
  222. m_cCommand.SetWindowText(GetCmdString(pCommand));
  223. m_cParameters.SetWindowText(pCommand->szParms);
  224. m_cEnsureCheck.SetCheck(pCommand->bEnsureCheck);
  225. m_cEnsureFn.SetWindowText(pCommand->szEnsureFn);
  226. m_cUseProcessWnd.SetCheck(pCommand->bUseProcessWnd);
  227. // don't forget to call this:
  228. OnEnsurecheck();
  229. m_bNoUpdateCmd = FALSE;
  230. }
  231. BOOL CRunMapExpertDlg::HandleInsertParm(UINT nID)
  232. // insert a parm at the current cursor location into the parameters
  233. // edit control
  234. {
  235. LPCTSTR pszInsert;
  236. switch (nID)
  237. {
  238. case id_InsertParmMapFileNoExt:
  239. pszInsert = "$file";
  240. break;
  241. case id_InsertParmMapFile:
  242. pszInsert = "$file.$ext";
  243. break;
  244. case id_InsertParmMapPath:
  245. pszInsert = "$path";
  246. break;
  247. case id_InsertParmExeDir:
  248. pszInsert = "$exedir";
  249. break;
  250. case id_InsertParmBspDir:
  251. pszInsert = "$bspdir";
  252. break;
  253. case id_InsertParmGameDir:
  254. default:
  255. pszInsert = "$gamedir";
  256. break;
  257. }
  258. Assert(pszInsert);
  259. if(!pszInsert)
  260. return TRUE;
  261. m_cParameters.ReplaceSel(pszInsert);
  262. return TRUE;
  263. }
  264. void CRunMapExpertDlg::OnInsertparm(void)
  265. {
  266. // two stages - name/description OR data itself
  267. CMenu menu;
  268. menu.CreatePopupMenu();
  269. menu.AppendMenu(MF_STRING, id_InsertParmMapFileNoExt, "Map Filename (no extension)");
  270. menu.AppendMenu(MF_STRING, id_InsertParmMapFile, "Map Filename (with extension)");
  271. menu.AppendMenu(MF_STRING, id_InsertParmMapPath, "Map Path (no filename)");
  272. menu.AppendMenu(MF_SEPARATOR);
  273. menu.AppendMenu(MF_STRING, id_InsertParmExeDir, "Game Executable Directory");
  274. menu.AppendMenu(MF_STRING, id_InsertParmBspDir, "BSP Directory");
  275. menu.AppendMenu(MF_STRING, id_InsertParmGameDir, "Game Directory");
  276. // track menu
  277. CWnd *pButton = GetDlgItem(IDC_INSERTPARM);
  278. CRect r;
  279. pButton->GetWindowRect(r);
  280. menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, r.left, r.bottom, this, NULL);
  281. }
  282. void CRunMapExpertDlg::DeleteCommand(int iIndex)
  283. {
  284. // kill the command at that index (deletes the dataptr memory too)
  285. PCCOMMAND pCommand = GetCommandAtIndex(&iIndex);
  286. m_cCommandList.DeleteString(iIndex);
  287. if(iIndex >= m_cCommandList.GetCount()-1)
  288. iIndex = m_cCommandList.GetCount()-1;
  289. m_cCommandList.SetCurSel(iIndex);
  290. // selection has "changed"
  291. OnSelchangeCommandlist();
  292. delete pCommand;
  293. }
  294. void CRunMapExpertDlg::AddCommand(int iIndex, PCCOMMAND pCommand)
  295. {
  296. // add a command to the list at the index specified in iIndex (-1 to add
  297. // at end of list.)
  298. CString str;
  299. str.Format("%s %s", GetCmdString(pCommand), pCommand->szParms);
  300. iIndex = m_cCommandList.InsertString(iIndex, str);
  301. m_cCommandList.SetItemDataPtr(iIndex, PVOID(pCommand));
  302. }
  303. void CRunMapExpertDlg::MoveCommand(int iIndex, BOOL bUp)
  304. {
  305. PCCOMMAND pCommand = GetCommandAtIndex(&iIndex);
  306. if(!pCommand)
  307. return;
  308. // keep check state of item in listbox
  309. BOOL bChecked = m_cCommandList.GetCheck(iIndex);
  310. // don't bother with the string - that's made from the command/parms
  311. // struct that the item's dataptr points to
  312. m_cCommandList.DeleteString(iIndex);
  313. int iNewIndex = iIndex + (bUp ? -1 : +1);
  314. AddCommand(iNewIndex, pCommand);
  315. // restore check state saved above
  316. m_cCommandList.SetCheck(iNewIndex, bChecked);
  317. // selection has changed
  318. m_cCommandList.SetCurSel(iNewIndex);
  319. OnSelchangeCommandlist();
  320. }
  321. void CRunMapExpertDlg::OnMovedown()
  322. {
  323. MoveCommand(-1, FALSE);
  324. }
  325. void CRunMapExpertDlg::OnMoveup()
  326. {
  327. MoveCommand(-1, TRUE);
  328. }
  329. void CRunMapExpertDlg::OnNew()
  330. {
  331. // add a command
  332. PCCOMMAND pCommand = new CCOMMAND;
  333. memset(pCommand, 0, sizeof(CCOMMAND));
  334. pCommand->bUseProcessWnd = TRUE;
  335. AddCommand(-1, pCommand);
  336. m_cCommandList.SetCurSel(m_cCommandList.GetCount()-1);
  337. // sleection has changed
  338. OnSelchangeCommandlist();
  339. }
  340. void CRunMapExpertDlg::OnNormal()
  341. {
  342. m_bSwitchMode = TRUE;
  343. SaveCommandsToSequence();
  344. CHammer *pApp = (CHammer*) AfxGetApp();
  345. pApp->SaveSequences();
  346. EndDialog(IDOK);
  347. }
  348. void CRunMapExpertDlg::UpdateCommandWithEditFields(int iIndex)
  349. {
  350. PCCOMMAND pCommand = GetCommandAtIndex(&iIndex);
  351. // update command struct with edit fields:
  352. m_cCommand.GetWindowText(pCommand->szRun, MAX_PATH);
  353. m_cParameters.GetWindowText(pCommand->szParms, MAX_PATH);
  354. m_cEnsureFn.GetWindowText(pCommand->szEnsureFn, MAX_PATH);
  355. pCommand->bUseProcessWnd = m_cUseProcessWnd.GetCheck();
  356. pCommand->bEnsureCheck = m_cEnsureCheck.GetCheck();
  357. // save checked state..
  358. BOOL bCmdChecked = m_cCommandList.GetCheck(iIndex);
  359. // update list by deleting/adding command
  360. m_cCommandList.SetRedraw(FALSE);
  361. m_cCommandList.DeleteString(iIndex);
  362. AddCommand(iIndex, pCommand);
  363. m_cCommandList.SetCurSel(iIndex);
  364. m_cCommandList.SetRedraw(TRUE);
  365. m_cCommandList.Invalidate();
  366. m_cCommandList.SetCheck(iIndex, bCmdChecked);
  367. // DON'T call OnCommandlistSelchange() here
  368. }
  369. PCCOMMAND CRunMapExpertDlg::GetCommandAtIndex(int *piIndex)
  370. {
  371. // make sure we're pointing at something:
  372. int iIndex = -1;
  373. if(piIndex == NULL)
  374. piIndex = &iIndex;
  375. // return the current command structure
  376. if(piIndex[0] == -1)
  377. piIndex[0] = m_cCommandList.GetCurSel();
  378. if(piIndex[0] == LB_ERR)
  379. return NULL;
  380. PCCOMMAND pCommand = PCCOMMAND(m_cCommandList.GetItemDataPtr(piIndex[0]));
  381. return pCommand;
  382. }
  383. void CRunMapExpertDlg::OnRemove()
  384. {
  385. // kill the current command
  386. int iIndex = m_cCommandList.GetCurSel();
  387. if(iIndex == LB_ERR)
  388. return;
  389. DeleteCommand(iIndex);
  390. }
  391. void CRunMapExpertDlg::OnUpdateCommand()
  392. {
  393. if(!m_bNoUpdateCmd)
  394. {
  395. // make sure no special command is contained here ..
  396. // (this is only ever called when the user types
  397. // in the command edit field.)
  398. PCCOMMAND pCommand = GetCommandAtIndex(NULL);
  399. if(pCommand->iSpecialCmd)
  400. {
  401. // clear out command .. set the noupdatecmd
  402. // flag so we don't get into a stack overflow
  403. m_bNoUpdateCmd = TRUE;
  404. m_cCommand.SetWindowText("");
  405. m_bNoUpdateCmd = FALSE;
  406. pCommand->iSpecialCmd = 0;
  407. }
  408. UpdateCommandWithEditFields(-1);
  409. }
  410. }
  411. void CRunMapExpertDlg::OnUpdateParameters()
  412. {
  413. if(!m_bNoUpdateCmd)
  414. UpdateCommandWithEditFields(-1);
  415. }
  416. void CRunMapExpertDlg::OnEnsurecheck()
  417. {
  418. if(!m_bNoUpdateCmd)
  419. UpdateCommandWithEditFields(-1);
  420. // enable/disable edit field
  421. m_cEnsureFn.EnableWindow(m_cEnsureCheck.GetCheck());
  422. }
  423. void CRunMapExpertDlg::OnUpdateEnsurefn()
  424. {
  425. if(!m_bNoUpdateCmd)
  426. UpdateCommandWithEditFields(-1);
  427. }
  428. void CRunMapExpertDlg::OnUseprocesswnd()
  429. {
  430. // update the command here..
  431. PCCOMMAND pCommand = GetCommandAtIndex(NULL);
  432. Assert(pCommand);
  433. pCommand->bUseProcessWnd = m_cUseProcessWnd.GetCheck() ? TRUE : FALSE;
  434. }
  435. void CRunMapExpertDlg::InitSequenceList()
  436. {
  437. // add all the information from the CHammer object into
  438. // the dialog box ..
  439. CHammer *pApp = (CHammer*) AfxGetApp();
  440. m_cCmdSequences.ResetContent();
  441. // add the configurations into the list ..
  442. int iSize = pApp->m_CmdSequences.GetSize();
  443. if(iSize == 0)
  444. {
  445. // add a default configuration
  446. CCommandSequence *pSeq = new CCommandSequence;
  447. strcpy(pSeq->m_szName, "Default");
  448. ((CHammer*)AfxGetApp())->m_CmdSequences.Add(pSeq);
  449. iSize = 1;
  450. }
  451. for(int i = 0; i < iSize; i++)
  452. {
  453. CCommandSequence *pSeq = pApp->m_CmdSequences[i];
  454. int iIndex = m_cCmdSequences.AddString(pSeq->m_szName);
  455. m_cCmdSequences.SetItemDataPtr(iIndex, PVOID(pSeq));
  456. }
  457. m_pActiveSequence = NULL;
  458. m_cCmdSequences.SetCurSel(0);
  459. OnSelchangeConfigurations();
  460. }
  461. BOOL CRunMapExpertDlg::OnInitDialog()
  462. {
  463. CDialog::OnInitDialog();
  464. int iSequence = AfxGetApp()->GetProfileInt("RunMapExpert",
  465. "LastSequence", 0);
  466. InitSequenceList();
  467. m_cCmdSequences.SetCurSel(iSequence);
  468. OnSelchangeConfigurations();
  469. return TRUE;
  470. }
  471. void CRunMapExpertDlg::OnOK()
  472. {
  473. SaveCommandsToSequence();
  474. CHammer *pApp = (CHammer*) AfxGetApp();
  475. pApp->SaveSequences();
  476. CDialog::OnOK();
  477. }
  478. void CRunMapExpertDlg::SaveCommandsToSequence()
  479. {
  480. if(!m_pActiveSequence)
  481. return; // nothing set yet
  482. int nCommands = m_cCommandList.GetCount();
  483. m_pActiveSequence->m_Commands.RemoveAll();
  484. for(int i = 0; i < nCommands; i++)
  485. {
  486. PCCOMMAND pCommand = PCCOMMAND(m_cCommandList.GetItemDataPtr(i));
  487. pCommand->bEnable = m_cCommandList.GetCheck(i);
  488. if (!strcmp(pCommand->szRun, "$game_exe"))
  489. pCommand->bNoWait = TRUE;
  490. m_pActiveSequence->m_Commands.Add(*pCommand);
  491. // free the memory:
  492. delete pCommand;
  493. }
  494. }
  495. void CRunMapExpertDlg::OnSelchangeConfigurations()
  496. {
  497. // save the current command list back into the previously active
  498. // command sequence
  499. SaveCommandsToSequence();
  500. int iSel = m_cCmdSequences.GetCurSel();
  501. if(iSel == LB_ERR) // nothing there
  502. {
  503. m_pActiveSequence = NULL;
  504. return;
  505. }
  506. AfxGetApp()->WriteProfileInt("RunMapExpert", "LastSequence", iSel);
  507. CCommandSequence *pSeq = (CCommandSequence*)
  508. m_cCmdSequences.GetItemDataPtr(iSel);
  509. // delete strings from listbox (dataptrs already deleted
  510. // in SaveCommandsToSequence())
  511. m_cCommandList.ResetContent();
  512. m_pActiveSequence = pSeq;
  513. // add the commands from this sequence into the command listbox ..
  514. CCommandArray &Commands = pSeq->m_Commands;
  515. for(int i = 0; i < Commands.GetSize(); i++)
  516. {
  517. PCCOMMAND pCommand = new CCOMMAND(Commands[i]);
  518. AddCommand(i, pCommand);
  519. m_cCommandList.SetCheck(i, pCommand->bEnable);
  520. }
  521. // set to 0th element in list ..
  522. m_cCommandList.SetCurSel(0);
  523. OnSelchangeCommandlist();
  524. }
  525. void CRunMapExpertDlg::OnEditconfigs()
  526. {
  527. CRunMapCfgDlg dlg;
  528. SaveCommandsToSequence();
  529. if(dlg.DoModal() == IDOK)
  530. InitSequenceList();
  531. }
  532. void CRunMapExpertDlg::OnCancel()
  533. {
  534. SaveCommandsToSequence();
  535. CHammer *pApp = (CHammer*) AfxGetApp();
  536. pApp->SaveSequences();
  537. CDialog::OnCancel();
  538. }