Back to Creating the Projects
Basic Modifications to GUI Code
Select files from the Solution Explorer file tree and make the following modifications
Gui.cpp
Modify dialog creation in InitInstance() to
BOOL CGUIApp::InitInstance()
{
...
CGUIDlg* dlg = new CGUIDlg();
m_pMainWnd = dlg;
dlg->Create( IDD_GUI_DIALOG );
return TRUE;
}
GuiDlg.h
Modify the Dialog definition to include
class CGUIDlg : public CDialog
{
...
protected:
...
LRESULT DefWindowProc( UINT message, WPARAM wParam, LPARAM );
afx_msg void OnClose();
public:
~CGUIDlg();
...
};
GuiDlg.cpp
Modify the Dialog file to include
#include <projectheader.hpp>
#include <Process1Process_includes.hpp>
#include <GUI/Win32/CPP/Include/Win32_Process.hpp>
Comment out or remove
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
Add Close to message map
BEGIN_MESSAGE_MAP(CGUIDlg, CDialog)
...
ON_WM_CLOSE()
END_MESSAGE_MAP()
Add dialog registration and process startup to OnInitDialog()
BOOL CGUIDlg::OnInitDialog()
{
...
// TODO: Add extra initialization here
::CLIP::SetCallbackWindow( this->GetSafeHwnd(), this );
Process1Process* process = new Process1Process();
process->Startup();
return TRUE;
}
Add overrides for dialog functions
LRESULT CGUIDlg::DefWindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
CLIP::ProcessPumpMessage( message, wParam, lParam );
return CDialog::DefWindowProc( message, wParam, lParam );
}
void CGUIDlg::OnClose()
{
ClpExit(0);
CDialog::OnClose();
}
CGUIDlg::~CGUIDlg()
{
// we will add things here later
}
GUI Dialogs
You can either create your own dialogs
The Start Button will be used to start the application running. Whilst the X will be used to exit the application.
or copy the files GUI.rc, resource.h, OutputDialog.h and OutputDialog.cpp into the project (you will probably need to exit VisualStudio and delete the GUI.APS file).
The Output dialog is used for display of the data and includes a ViewerPixmap (CPixmap.h, CPixmap.cpp, CViewerPixmap.h, CViewerPixmap.cpp) for the display, counters for calculating frame rates and a couple of functions for Initializing and setting the pixmap.
NB. Both dialogs include frame rate counters (processing frames and displayed frames which are reduced by REDUCTION:1 as we wish to see how the processing performs without being constrained by the graphics). This frame counter code could be emitted without loss of functionality and is shown in magenta.
OutputDialog.h
#include "CViewerPixmap.h"
class COutputDialog : publicCDialog
{
...
public:
// access to pixmap
unsigned char* GetPixelData();
void UpdatePixelData();
unsigned int GetPixmapSize();
protected:
...
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg void OnClose();
private:
// create pixmap
void Initialise();
private:
CViewerPixmap* mViewerPixmap;
// frame counters
LARGE_INTEGER mFrequency;
LARGE_INTEGER mPreviousCount;
float mClockPeriodMicroSec;
bool mFirstTime;
};
OutputDialog.cpp
#include <ProjectHeader.hpp>
...
COutputDialog::COutputDialog( CWnd* pParent )
: CDialog( COutputDialog::IDD, pParent )
{
// initialise the frame rate counters
mFirstTime = true;
QueryPerformanceFrequency( &mFrequency );
mClockPeriodMicroSec = 1000000.0f / (float) mFrequency.QuadPart;
}
COutputDialog::~COutputDialog()
{
// delete the pixmap
delete mViewerPixmap;
}
BEGIN_MESSAGE_MAP(COutputDlg, CDialog)
ON_WM_CLOSE()
ON_WM_PAINT()
END_MESSAGE_MAP()
BOOL COutputDialog::OnInitDialog()
{
CDialog::OnInitDialog();
Initialise();
return TRUE;
}
void COutputDlg::OnClose()
{
ClpExit(0);
CDialog::OnClose();
}
void COutputDialog::OnPaint()
{
// update the frame rate counters
if ( !mFirstTime )
{
LARGE_INTEGER CurrentCount;
QueryPerformanceCounter( &CurrentCount );
float TimeTakenMicroSec = ( CurrentCount.QuadPart - mPreviousCount.QuadPart ) * mClockPeriodMicroSec;
mPreviousCount = CurrentCount;
float AverageFrameRate = 1.0f / ( TimeTakenMicroSec * 0.000001f );
CString Text;
Text.Format( " FPS = %.1f", AverageFrameRate );
SetWindowText( Text );
}
else
{
mFirstTime = false;
QueryPerformanceCounter(&mPreviousCount);
}
// update the pixmap
mViewerPixmap->Update();
CDialog::OnPaint();
}
void COutputDialog::Initialise()
{
// Create the pixmap
mViewerPixmap = new CViewerPixmap( this->GetDC()->GetSafeHdc(), GRID_SIZE, GRID_SIZE );
}
unsigned char* COutputDialog::GetPixelData()
{
return mViewerPixmap->GetBitmapData();
}
void COutputDialog::UpdatePixelData()
{
mViewerPixmap->CommitBitmapData();
}
unsigned int COutputDialog::GetPixmapSize()
{
return 0; // we will populate this later
}
The main GUI now needs to be updated to: interface to the Output dialog; add its own frame rate counters and provide callbacks for the Start Button
GuiDlg.h
#include "OutputDialog.h"
class CGUIDlg : public CDialog
{
...
public:
CButton StartBtn;
protected:
// start button callback
afx_msg void OnBnClickedButton1();
public:
// initialise frame counters
void Initialise();
// Output interface
void UpdatePixels( char* Pixmap, unsigned int FrameCount );
private:
COutputDialog* mOutputDlg;
// frame counters
LARGE_INTEGER mFrequency;
LARGE_INTEGER mPreviousCount;
float mClockPeriodMicroSec;
float mTotalTimeTakenMicroSec;
unsigned int mPreviousFrameCount;
unsigned int mTotalFrameCount;
unsigned int mTimeSampleCount;
bool mFirstTime;
};
GuiDlg.cpp
...
void CGUIDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, StartBtn);
}
BEGIN_MESSAGE_MAP(CGUIDlg, CDialog)
...
ON_BN_CLICKED(IDC_BUTTON1, &CGUIDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
BOOL CGUIDlg::OnInitDialog()
{
...
Initialise();
// TODO: Add extra initialization here
...
}
...
void CGUIDlg::Initialise()
{
CRect Rect;
// position this dialog
this->SetWindowPos( NULL, 0,0,0,0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW );
this->GetClientRect( &Rect );
this->ClientToScreen( &Rect );
// create output dialog
mOutputDlg = new COutputDialog( this );
mOutputDlg->Create( IDD_OUTPUT_DIALOG, this );
// position/size output dialog
mOutputDlg->SetWindowPos( NULL, Rect.right + 5, 0, GRID_SIZE + 6, GRID_SIZE + 32, SWP_NOZORDER | SWP_SHOWWINDOW );
// initialise frame counters
mFirstTime = true;
QueryPerformanceFrequency(&mFrequency);
mClockPeriodMicroSec = 1000000.0f / (float)mFrequency.QuadPart;
}
void CGUIDlg::OnBnClickedButton1()
{
// start pressed - tell CLIP to start
// TDB in Final GUI Modifications
}
void CGUIDlg::UpdatePixels( char* Pixmap, unsigned int FrameCount )
{
// update frame counters
if ( !mFirstTime )
{
LARGE_INTEGER CurrentCount;
QueryPerformanceCounter(&CurrentCount);
mTotalTimeTakenMicroSec += ( CurrentCount.QuadPart - mPreviousCount.QuadPart ) * mClockPeriodMicroSec;
mPreviousCount = CurrentCount;
++mTimeSampleCount;
mTotalFrameCount += ( FrameCount - mPreviousFrameCount );
mPreviousFrameCount = FrameCount;
float AverageFrameRate = (float)mTotalFrameCount / ( mTotalTimeTakenMicroSec * 0.000001f );
CString Text;
Text.Format( " FPS = %.1f", AverageFrameRate );
SetWindowText( Text );
if ( mTimeSampleCount == TIME_SAMPLE_COUNT )
{
mTotalTimeTakenMicroSec = 0.0f;
mTimeSampleCount = 0;
mTotalFrameCount = 0;
}
}
else
{
mFirstTime = false;
QueryPerformanceCounter(&mPreviousCount);
mPreviousFrameCount = FrameCount;
mTotalTimeTakenMicroSec = 0.0f;
mTimeSampleCount = 0;
mTotalFrameCount = 0;
}
// draw pixels and refresh the display
memcpy( mOutputDlg->GetPixelData(), Pixmap, mOutputDlg->GetPixmapSize() );
mOutputDlg->UpdatePixelData();
mOutputDlg->PostMessage( WM_PAINT );
}
The constant value 'GRID_SIZE' can be defined in the project header file by opening the file from the Solution Explorer Window and adding the following code
FDTD/Header Files/ProjectHeader.hpp
...
// TODO: Reference any additional headers or defines you need
#define GRID_SIZE 1024
#endif
The actual grid size could be modified for a finer/larger grid. However, many calculations later in the code will assume it is a power of 2.