|
|
// fedit.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "fedit.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#include "FEditDoc.h"
#include "FEditView.h"
#ifdef TRY_AUTOSETUP
#include "AutoSetupDlg.h"
#endif
#include <stdio.h>
#include <math.h>
#include "..\..\..\dxsdk\samples\multimedia\common\include\DXUtil.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
/////////////////////////////////////////////////////////////////////////////
// CFEditApp
BEGIN_MESSAGE_MAP(CFEditApp, CWinApp) //{{AFX_MSG_MAP(CFEditApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout) ON_COMMAND(ID_FILE_OPEN, OnFileOpen) //}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) // Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFEditApp construction
CFEditApp::CFEditApp() { // TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CFEditApp object
CFEditApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CFEditApp initialization
BOOL CFEditApp::InitInstance() { AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// Change the registry key under which our settings are stored.
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(7); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_FEDITTYPE, RUNTIME_CLASS(CFEditDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CFEditView)); AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame;
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
// Enable DDE Execute open
EnableShellOpen(); RegisterShellFileTypes(TRUE);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo)) return FALSE;
// setup if needed
#ifdef TRY_AUTOSETUP
{ CAutoSetupDlg dlg; if (!dlg.IsSetup()) { dlg.DoModal(); if (!dlg.WasSuccessful()) { ErrorBox(IDS_APP_NO_SETUP); return FALSE; } } } #endif
// The main window has been initialized, so show and update it.
pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow();
return TRUE; }
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog { public: CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected: //{{AFX_MSG(CAboutDlg)
// No message handlers
//}}AFX_MSG
DECLARE_MESSAGE_MAP() };
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// App command to run the dialog
void CFEditApp::OnAppAbout() { CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd(); if (pMainFrame != NULL) pMainFrame->Stop(); CAboutDlg aboutDlg; aboutDlg.DoModal(); }
/////////////////////////////////////////////////////////////////////////////
// CFEditApp message handlers
void MyTrace(const TCHAR *lpszMessage) { CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd(); if (pMainFrame == NULL) return; pMainFrame->OutputString(lpszMessage); }
/////////////////////////////////////////////////////////////////////////////
// CFEditApp OnFileOpen
//
void CFEditApp::OnFileOpen() { static TCHAR strFileName[MAX_PATH] = TEXT(""); static TCHAR strPath[MAX_PATH] = TEXT(""); HWND hWnd = AfxGetMainWnd()->m_hWnd;
// Setup the OPENFILENAME structure
OPENFILENAME ofn = { sizeof(OPENFILENAME), hWnd, NULL, TEXT("FEdit Files\0*.ffe\0All Files\0*.*\0\0"), NULL, 0, 1, strFileName, MAX_PATH, NULL, 0, strPath, TEXT("Open FEdit File"), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, 0, TEXT(".ffe"), 0, NULL, NULL };
// Get the default media path (something like C:\MSSDK\SAMPLES\MULTIMEDIA\DINPUT\MEDIA)
if( TEXT('\0') == strPath[0] ) _tcscpy( strPath, DXUtil_GetDXSDKMediaPath() );
// Display the OpenFileName dialog. Then, try to load the specified file
if (GetOpenFileName( &ofn ) != 0) { //open file
OpenDocumentFile(strFileName); //and save the path for next time
strcpy( strPath, strFileName ); char* strLastSlash = strrchr( strPath, TEXT('\\' )); strLastSlash[0] = TEXT('\0'); } }
/////////////////////////////////////////////////////////////////////////////
// FEdit Helper Functions
//
DWORD ScaleDurationFromCEffect(ULONG from) { if (CEFFECT_DURATIONSCALE == DI_SECONDS) return (DWORD)from; else return (DWORD)MulDiv(int(from), DI_SECONDS, CEFFECT_DURATIONSCALE); }
ULONG ScaleDurationToCEffect(DWORD to) { if (CEFFECT_DURATIONSCALE == DI_SECONDS) return (ULONG)to; else return (ULONG)MulDiv(int(to), CEFFECT_DURATIONSCALE, DI_SECONDS); }
BOOL GetEffectInfo(CEffect *pEffect, EFFECTINFO *pei) { static struct EIBYGUID { const GUID *pguid; EFFECTINFO ei; } eibyguid[] = { { &GUID_ConstantForce, { FALSE, FALSE, ET_CONSTANT } }, { &GUID_RampForce, { FALSE, FALSE, ET_RAMP } }, // periodics
{ &GUID_Square, { TRUE, FALSE, ET_SQUARE } }, { &GUID_Sine, { TRUE, FALSE, ET_SINE} }, { &GUID_Triangle, { TRUE, FALSE, ET_TRIANGLE} }, { &GUID_SawtoothUp, { TRUE, FALSE, ET_SAWUP } }, { &GUID_SawtoothDown, { TRUE, FALSE, ET_SAWDOWN } }, // conditions
{ &GUID_Spring, { FALSE, TRUE, ET_SPRING } }, { &GUID_Friction, { FALSE, TRUE, ET_FRICTION } }, { &GUID_Damper, { FALSE, TRUE, ET_DAMPER } }, { &GUID_Inertia, { FALSE, TRUE, ET_INERTIA } } }; const int guids = sizeof(eibyguid) / sizeof(EIBYGUID);
pei->bPeriodic = FALSE; pei->nType = ET_UNKNOWN;
ASSERT(pEffect != NULL && pei != NULL); if (pEffect == NULL || pei == NULL) return FALSE;
GUID *pguid = pEffect->GetEffectGuid(); ASSERT(pguid != NULL); if (pguid == NULL) return FALSE;
for (int i = 0; i < guids; i++) if (IsEqualGUID(*pguid, *(eibyguid[i].pguid))) { *pei = eibyguid[i].ei; // TODO: get actual num of axes and condition structures
pei->nAxes = pEffect->GetNumActiveAxes(); pei->nConditions = pei->nAxes; return TRUE; }
return FALSE; }
int CFEditApp::ExitInstance() { return CWinApp::ExitInstance(); }
///////////////////////////////////////////
// Allocates and loads a resource string.
// Returns it or NULL if unsuccessful.
//
TCHAR *AllocLoadString(UINT strid) { // allocate
const int STRING_LENGTHS = 1024; TCHAR *str = (TCHAR *)malloc(STRING_LENGTHS * sizeof(TCHAR));
// use if allocated succesfully
if (str != NULL) { // load the string, or free and null if we can't
if (LoadString(AfxGetInstanceHandle(), strid, str, STRING_LENGTHS) == NULL) { free(str); str = NULL; } }
return str; }
/////////////////////////////////////////////////////////
// Shows a message box with the specified error string.
// (automatically handles getting and freeing string.)
//
static TCHAR g_tmp[1024]; void ErrorBox(UINT strid, ...) { // alloc 'n load
TCHAR *errmsg = AllocLoadString(strid);
// format
va_list args; va_start(args, strid); { char szDfs[1024]={0}; if (errmsg == NULL) strcpy(szDfs,TEXT("(couldn't load error string)")); else strcpy(szDfs,errmsg); // make a local copy of format string
#ifdef WIN95
char *psz = NULL; while (psz = strstr(szDfs,"%p")) // find each %p
*(psz+1) = 'x'; // replace each %p with %x
#ifndef _UNICODE
vsprintf (g_tmp, szDfs, args); // use the local format string
#else
vswprintf (g_tmp, szDfs, args); // use the local format string
#endif //#ifndef _UNICODE
} #else
#ifndef _UNICODE
vsprintf (g_tmp, szDfs, args); #else
vswprintf (g_tmp, szDfs, args); #endif //#ifndef _UNICODE
} #endif //#ifdef WIN95
va_end(args); free(errmsg); errmsg = _tcsdup(g_tmp);
// Show error
AfxMessageBox(errmsg ? errmsg : TEXT("(couldn't form error message)"), MB_OK | MB_ICONSTOP);
// free which ever strings loaded
if (NULL != errmsg) free(errmsg); }
/////////////////////////////////////////////////////////
// Shows a message box based on GetLastError().
//
void LastErrorBox(UINT strid, ...) { va_list args; LPVOID lpMsgBuf = NULL; TCHAR *errmsg = ((strid != NULL) ? AllocLoadString(strid) : NULL);
if (errmsg != NULL) { va_start(args, strid); #ifdef WIN95
{ char *psz = NULL; char szDfs[1024]={0}; strcpy(szDfs,errmsg); // make a local copy of format string
while (psz = strstr(szDfs,"%p")) // find each %p
*(psz+1) = 'x'; // replace each %p with %x
#ifndef _UNICODE
vsprintf (g_tmp, szDfs, args); // use the local format string
#else
vswprintf (g_tmp, szDfs, args); // use the local format string
#endif
} #else
{ #ifndef _UNICODE
vsprintf (g_tmp, errmsg, args); #else
vswprintf (g_tmp, errmsg, args); #endif
} #endif
va_end(args); free(errmsg); errmsg = _tcsdup(g_tmp); }
// format an error message from GetLastError().
DWORD result = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
if (0 == result) { ErrorBox(NULL); } else { // format
CString msg; if (errmsg != NULL) msg.Format(TEXT("%s\n\nLast System Error:\n\t%s"), errmsg, (LPCTSTR)lpMsgBuf); else msg.Format(TEXT("Last System Error:\n\t%s"), (LPCTSTR)lpMsgBuf);
// show the message we just formatted
AfxMessageBox(msg, MB_OK | MB_ICONSTOP); }
// free whichever strings were allocated
if (NULL != errmsg) free(errmsg); if (NULL != lpMsgBuf) LocalFree(lpMsgBuf); }
BOOL GetEffectSustainAndOffset(CEffect *pEffect, int &sustain, int &offset) { ASSERT(pEffect != NULL); if (pEffect == NULL) return FALSE;
EFFECTINFO ei; VERIFY(GetEffectInfo(pEffect, &ei));
if (ei.bCondition || ei.nType == ET_UNKNOWN) { ASSERT(0); return FALSE; }
void *param = pEffect->GetParam(); ASSERT(param != NULL); if (param == NULL) return FALSE;
if (ei.bPeriodic) { sustain = int(((DIPERIODIC *)param)->dwMagnitude); offset = int(((DIPERIODIC *)param)->lOffset); return TRUE; }
switch (ei.nType) { case ET_CONSTANT: sustain = abs(int(((DICONSTANTFORCE *)param)->lMagnitude)); offset = 0; return TRUE;
case ET_RAMP: sustain = abs(int(((DIRAMPFORCE *)param)->lStart) - int(((DIRAMPFORCE *)param)->lEnd)) / 2; offset = (int(((DIRAMPFORCE *)param)->lStart) + int(((DIRAMPFORCE *)param)->lEnd)) / 2; return TRUE;
default: ASSERT(0); return FALSE; } }
BOOL IsValidInteger(const CString &s, int min, int max) { if (s.IsEmpty()) return FALSE;
int i = atoi(s); if (i == 0) { int l = s.GetLength(); for (int c = 0; c < l; c++) if (s[c] != '0') return FALSE; }
if (i < min || i > max) return FALSE;
return TRUE; }
|