Source code of Windows XP (NT5)
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.

523 lines
12 KiB

  1. // fedit.cpp : Defines the class behaviors for the application.
  2. //
  3. #include "stdafx.h"
  4. #include "fedit.h"
  5. #include "MainFrm.h"
  6. #include "ChildFrm.h"
  7. #include "FEditDoc.h"
  8. #include "FEditView.h"
  9. #ifdef TRY_AUTOSETUP
  10. #include "AutoSetupDlg.h"
  11. #endif
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include "..\..\..\dxsdk\samples\multimedia\common\include\DXUtil.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CFEditApp
  22. BEGIN_MESSAGE_MAP(CFEditApp, CWinApp)
  23. //{{AFX_MSG_MAP(CFEditApp)
  24. ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  25. ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
  26. //}}AFX_MSG_MAP
  27. // Standard file based document commands
  28. ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
  29. // Standard print setup command
  30. ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
  31. END_MESSAGE_MAP()
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CFEditApp construction
  34. CFEditApp::CFEditApp()
  35. {
  36. // TODO: add construction code here,
  37. // Place all significant initialization in InitInstance
  38. }
  39. /////////////////////////////////////////////////////////////////////////////
  40. // The one and only CFEditApp object
  41. CFEditApp theApp;
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CFEditApp initialization
  44. BOOL CFEditApp::InitInstance()
  45. {
  46. AfxEnableControlContainer();
  47. // Standard initialization
  48. // If you are not using these features and wish to reduce the size
  49. // of your final executable, you should remove from the following
  50. // the specific initialization routines you do not need.
  51. #ifdef _AFXDLL
  52. Enable3dControls(); // Call this when using MFC in a shared DLL
  53. #else
  54. Enable3dControlsStatic(); // Call this when linking to MFC statically
  55. #endif
  56. // Change the registry key under which our settings are stored.
  57. // TODO: You should modify this string to be something appropriate
  58. // such as the name of your company or organization.
  59. SetRegistryKey(_T("Local AppWizard-Generated Applications"));
  60. LoadStdProfileSettings(7); // Load standard INI file options (including MRU)
  61. // Register the application's document templates. Document templates
  62. // serve as the connection between documents, frame windows and views.
  63. CMultiDocTemplate* pDocTemplate;
  64. pDocTemplate = new CMultiDocTemplate(
  65. IDR_FEDITTYPE,
  66. RUNTIME_CLASS(CFEditDoc),
  67. RUNTIME_CLASS(CChildFrame), // custom MDI child frame
  68. RUNTIME_CLASS(CFEditView));
  69. AddDocTemplate(pDocTemplate);
  70. // create main MDI Frame window
  71. CMainFrame* pMainFrame = new CMainFrame;
  72. if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
  73. return FALSE;
  74. m_pMainWnd = pMainFrame;
  75. // Enable drag/drop open
  76. m_pMainWnd->DragAcceptFiles();
  77. // Enable DDE Execute open
  78. EnableShellOpen();
  79. RegisterShellFileTypes(TRUE);
  80. // Parse command line for standard shell commands, DDE, file open
  81. CCommandLineInfo cmdInfo;
  82. ParseCommandLine(cmdInfo);
  83. // Dispatch commands specified on the command line
  84. if (!ProcessShellCommand(cmdInfo))
  85. return FALSE;
  86. // setup if needed
  87. #ifdef TRY_AUTOSETUP
  88. {
  89. CAutoSetupDlg dlg;
  90. if (!dlg.IsSetup())
  91. {
  92. dlg.DoModal();
  93. if (!dlg.WasSuccessful())
  94. {
  95. ErrorBox(IDS_APP_NO_SETUP);
  96. return FALSE;
  97. }
  98. }
  99. }
  100. #endif
  101. // The main window has been initialized, so show and update it.
  102. pMainFrame->ShowWindow(m_nCmdShow);
  103. pMainFrame->UpdateWindow();
  104. return TRUE;
  105. }
  106. /////////////////////////////////////////////////////////////////////////////
  107. // CAboutDlg dialog used for App About
  108. class CAboutDlg : public CDialog
  109. {
  110. public:
  111. CAboutDlg();
  112. // Dialog Data
  113. //{{AFX_DATA(CAboutDlg)
  114. enum { IDD = IDD_ABOUTBOX };
  115. //}}AFX_DATA
  116. // ClassWizard generated virtual function overrides
  117. //{{AFX_VIRTUAL(CAboutDlg)
  118. protected:
  119. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  120. //}}AFX_VIRTUAL
  121. // Implementation
  122. protected:
  123. //{{AFX_MSG(CAboutDlg)
  124. // No message handlers
  125. //}}AFX_MSG
  126. DECLARE_MESSAGE_MAP()
  127. };
  128. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  129. {
  130. //{{AFX_DATA_INIT(CAboutDlg)
  131. //}}AFX_DATA_INIT
  132. }
  133. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  134. {
  135. CDialog::DoDataExchange(pDX);
  136. //{{AFX_DATA_MAP(CAboutDlg)
  137. //}}AFX_DATA_MAP
  138. }
  139. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  140. //{{AFX_MSG_MAP(CAboutDlg)
  141. // No message handlers
  142. //}}AFX_MSG_MAP
  143. END_MESSAGE_MAP()
  144. // App command to run the dialog
  145. void CFEditApp::OnAppAbout()
  146. {
  147. CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd();
  148. if (pMainFrame != NULL)
  149. pMainFrame->Stop();
  150. CAboutDlg aboutDlg;
  151. aboutDlg.DoModal();
  152. }
  153. /////////////////////////////////////////////////////////////////////////////
  154. // CFEditApp message handlers
  155. void MyTrace(const TCHAR *lpszMessage)
  156. {
  157. CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd();
  158. if (pMainFrame == NULL)
  159. return;
  160. pMainFrame->OutputString(lpszMessage);
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. // CFEditApp OnFileOpen
  164. //
  165. void CFEditApp::OnFileOpen()
  166. {
  167. static TCHAR strFileName[MAX_PATH] = TEXT("");
  168. static TCHAR strPath[MAX_PATH] = TEXT("");
  169. HWND hWnd = AfxGetMainWnd()->m_hWnd;
  170. // Setup the OPENFILENAME structure
  171. OPENFILENAME ofn = { sizeof(OPENFILENAME), hWnd, NULL,
  172. TEXT("FEdit Files\0*.ffe\0All Files\0*.*\0\0"), NULL,
  173. 0, 1, strFileName, MAX_PATH, NULL, 0, strPath,
  174. TEXT("Open FEdit File"),
  175. OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, 0,
  176. TEXT(".ffe"), 0, NULL, NULL };
  177. // Get the default media path (something like C:\MSSDK\SAMPLES\MULTIMEDIA\DINPUT\MEDIA)
  178. if( TEXT('\0') == strPath[0] )
  179. _tcscpy( strPath, DXUtil_GetDXSDKMediaPath() );
  180. // Display the OpenFileName dialog. Then, try to load the specified file
  181. if (GetOpenFileName( &ofn ) != 0)
  182. {
  183. //open file
  184. OpenDocumentFile(strFileName);
  185. //and save the path for next time
  186. strcpy( strPath, strFileName );
  187. char* strLastSlash = strrchr( strPath, TEXT('\\' ));
  188. strLastSlash[0] = TEXT('\0');
  189. }
  190. }
  191. /////////////////////////////////////////////////////////////////////////////
  192. // FEdit Helper Functions
  193. //
  194. DWORD ScaleDurationFromCEffect(ULONG from)
  195. {
  196. if (CEFFECT_DURATIONSCALE == DI_SECONDS)
  197. return (DWORD)from;
  198. else
  199. return (DWORD)MulDiv(int(from), DI_SECONDS, CEFFECT_DURATIONSCALE);
  200. }
  201. ULONG ScaleDurationToCEffect(DWORD to)
  202. {
  203. if (CEFFECT_DURATIONSCALE == DI_SECONDS)
  204. return (ULONG)to;
  205. else
  206. return (ULONG)MulDiv(int(to), CEFFECT_DURATIONSCALE, DI_SECONDS);
  207. }
  208. BOOL GetEffectInfo(CEffect *pEffect, EFFECTINFO *pei)
  209. {
  210. static struct EIBYGUID {
  211. const GUID *pguid;
  212. EFFECTINFO ei;
  213. } eibyguid[] = {
  214. { &GUID_ConstantForce, { FALSE, FALSE, ET_CONSTANT } },
  215. { &GUID_RampForce, { FALSE, FALSE, ET_RAMP } },
  216. // periodics
  217. { &GUID_Square, { TRUE, FALSE, ET_SQUARE } },
  218. { &GUID_Sine, { TRUE, FALSE, ET_SINE} },
  219. { &GUID_Triangle, { TRUE, FALSE, ET_TRIANGLE} },
  220. { &GUID_SawtoothUp, { TRUE, FALSE, ET_SAWUP } },
  221. { &GUID_SawtoothDown, { TRUE, FALSE, ET_SAWDOWN } },
  222. // conditions
  223. { &GUID_Spring, { FALSE, TRUE, ET_SPRING } },
  224. { &GUID_Friction, { FALSE, TRUE, ET_FRICTION } },
  225. { &GUID_Damper, { FALSE, TRUE, ET_DAMPER } },
  226. { &GUID_Inertia, { FALSE, TRUE, ET_INERTIA } } };
  227. const int guids = sizeof(eibyguid) / sizeof(EIBYGUID);
  228. pei->bPeriodic = FALSE;
  229. pei->nType = ET_UNKNOWN;
  230. ASSERT(pEffect != NULL && pei != NULL);
  231. if (pEffect == NULL || pei == NULL)
  232. return FALSE;
  233. GUID *pguid = pEffect->GetEffectGuid();
  234. ASSERT(pguid != NULL);
  235. if (pguid == NULL)
  236. return FALSE;
  237. for (int i = 0; i < guids; i++)
  238. if (IsEqualGUID(*pguid, *(eibyguid[i].pguid)))
  239. {
  240. *pei = eibyguid[i].ei;
  241. // TODO: get actual num of axes and condition structures
  242. pei->nAxes = pEffect->GetNumActiveAxes();
  243. pei->nConditions = pei->nAxes;
  244. return TRUE;
  245. }
  246. return FALSE;
  247. }
  248. int CFEditApp::ExitInstance()
  249. {
  250. return CWinApp::ExitInstance();
  251. }
  252. ///////////////////////////////////////////
  253. // Allocates and loads a resource string.
  254. // Returns it or NULL if unsuccessful.
  255. //
  256. TCHAR *AllocLoadString(UINT strid)
  257. {
  258. // allocate
  259. const int STRING_LENGTHS = 1024;
  260. TCHAR *str = (TCHAR *)malloc(STRING_LENGTHS * sizeof(TCHAR));
  261. // use if allocated succesfully
  262. if (str != NULL)
  263. {
  264. // load the string, or free and null if we can't
  265. if (LoadString(AfxGetInstanceHandle(), strid, str, STRING_LENGTHS) == NULL)
  266. {
  267. free(str);
  268. str = NULL;
  269. }
  270. }
  271. return str;
  272. }
  273. /////////////////////////////////////////////////////////
  274. // Shows a message box with the specified error string.
  275. // (automatically handles getting and freeing string.)
  276. //
  277. static TCHAR g_tmp[1024];
  278. void ErrorBox(UINT strid, ...)
  279. {
  280. // alloc 'n load
  281. TCHAR *errmsg = AllocLoadString(strid);
  282. // format
  283. va_list args;
  284. va_start(args, strid);
  285. {
  286. char szDfs[1024]={0};
  287. if (errmsg == NULL)
  288. strcpy(szDfs,TEXT("(couldn't load error string)"));
  289. else
  290. strcpy(szDfs,errmsg); // make a local copy of format string
  291. #ifdef WIN95
  292. char *psz = NULL;
  293. while (psz = strstr(szDfs,"%p")) // find each %p
  294. *(psz+1) = 'x'; // replace each %p with %x
  295. #ifndef _UNICODE
  296. vsprintf (g_tmp, szDfs, args); // use the local format string
  297. #else
  298. vswprintf (g_tmp, szDfs, args); // use the local format string
  299. #endif //#ifndef _UNICODE
  300. }
  301. #else
  302. #ifndef _UNICODE
  303. vsprintf (g_tmp, szDfs, args);
  304. #else
  305. vswprintf (g_tmp, szDfs, args);
  306. #endif //#ifndef _UNICODE
  307. }
  308. #endif //#ifdef WIN95
  309. va_end(args);
  310. free(errmsg);
  311. errmsg = _tcsdup(g_tmp);
  312. // Show error
  313. AfxMessageBox(errmsg ? errmsg : TEXT("(couldn't form error message)"), MB_OK | MB_ICONSTOP);
  314. // free which ever strings loaded
  315. if (NULL != errmsg)
  316. free(errmsg);
  317. }
  318. /////////////////////////////////////////////////////////
  319. // Shows a message box based on GetLastError().
  320. //
  321. void LastErrorBox(UINT strid, ...)
  322. {
  323. va_list args;
  324. LPVOID lpMsgBuf = NULL;
  325. TCHAR *errmsg = ((strid != NULL) ? AllocLoadString(strid) : NULL);
  326. if (errmsg != NULL)
  327. {
  328. va_start(args, strid);
  329. #ifdef WIN95
  330. {
  331. char *psz = NULL;
  332. char szDfs[1024]={0};
  333. strcpy(szDfs,errmsg); // make a local copy of format string
  334. while (psz = strstr(szDfs,"%p")) // find each %p
  335. *(psz+1) = 'x'; // replace each %p with %x
  336. #ifndef _UNICODE
  337. vsprintf (g_tmp, szDfs, args); // use the local format string
  338. #else
  339. vswprintf (g_tmp, szDfs, args); // use the local format string
  340. #endif
  341. }
  342. #else
  343. {
  344. #ifndef _UNICODE
  345. vsprintf (g_tmp, errmsg, args);
  346. #else
  347. vswprintf (g_tmp, errmsg, args);
  348. #endif
  349. }
  350. #endif
  351. va_end(args);
  352. free(errmsg);
  353. errmsg = _tcsdup(g_tmp);
  354. }
  355. // format an error message from GetLastError().
  356. DWORD result = FormatMessage(
  357. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  358. FORMAT_MESSAGE_FROM_SYSTEM |
  359. FORMAT_MESSAGE_IGNORE_INSERTS,
  360. NULL,
  361. GetLastError(),
  362. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  363. (LPTSTR) &lpMsgBuf,
  364. 0,
  365. NULL);
  366. if (0 == result)
  367. {
  368. ErrorBox(NULL);
  369. }
  370. else
  371. {
  372. // format
  373. CString msg;
  374. if (errmsg != NULL)
  375. msg.Format(TEXT("%s\n\nLast System Error:\n\t%s"), errmsg, (LPCTSTR)lpMsgBuf);
  376. else
  377. msg.Format(TEXT("Last System Error:\n\t%s"), (LPCTSTR)lpMsgBuf);
  378. // show the message we just formatted
  379. AfxMessageBox(msg, MB_OK | MB_ICONSTOP);
  380. }
  381. // free whichever strings were allocated
  382. if (NULL != errmsg)
  383. free(errmsg);
  384. if (NULL != lpMsgBuf)
  385. LocalFree(lpMsgBuf);
  386. }
  387. BOOL GetEffectSustainAndOffset(CEffect *pEffect, int &sustain, int &offset)
  388. {
  389. ASSERT(pEffect != NULL);
  390. if (pEffect == NULL)
  391. return FALSE;
  392. EFFECTINFO ei;
  393. VERIFY(GetEffectInfo(pEffect, &ei));
  394. if (ei.bCondition || ei.nType == ET_UNKNOWN)
  395. {
  396. ASSERT(0);
  397. return FALSE;
  398. }
  399. void *param = pEffect->GetParam();
  400. ASSERT(param != NULL);
  401. if (param == NULL)
  402. return FALSE;
  403. if (ei.bPeriodic)
  404. {
  405. sustain = int(((DIPERIODIC *)param)->dwMagnitude);
  406. offset = int(((DIPERIODIC *)param)->lOffset);
  407. return TRUE;
  408. }
  409. switch (ei.nType)
  410. {
  411. case ET_CONSTANT:
  412. sustain = abs(int(((DICONSTANTFORCE *)param)->lMagnitude));
  413. offset = 0;
  414. return TRUE;
  415. case ET_RAMP:
  416. sustain = abs(int(((DIRAMPFORCE *)param)->lStart) -
  417. int(((DIRAMPFORCE *)param)->lEnd)) / 2;
  418. offset = (int(((DIRAMPFORCE *)param)->lStart) +
  419. int(((DIRAMPFORCE *)param)->lEnd)) / 2;
  420. return TRUE;
  421. default:
  422. ASSERT(0);
  423. return FALSE;
  424. }
  425. }
  426. BOOL IsValidInteger(const CString &s, int min, int max)
  427. {
  428. if (s.IsEmpty())
  429. return FALSE;
  430. int i = atoi(s);
  431. if (i == 0)
  432. {
  433. int l = s.GetLength();
  434. for (int c = 0; c < l; c++)
  435. if (s[c] != '0')
  436. return FALSE;
  437. }
  438. if (i < min || i > max)
  439. return FALSE;
  440. return TRUE;
  441. }