// SpinnerDesignDlg.cpp : implementation file
//
#include "stdafx.h"
#include "SpinnerDesign.h"
#include "SpinnerDesignDlg.h"
#include "ColourPicker.h"
#include
#include "ObjectStorage.h"
#include "storageStructs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DLGHEIGHT 50
#define GRIDSIZE 10
#define PI 3.141592654
/////////////////////////////////////////////////////////////////////////////
// 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)
//}}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()
/////////////////////////////////////////////////////////////////////////////
// CSpinnerDesignDlg dialog
CSpinnerDesignDlg::CSpinnerDesignDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSpinnerDesignDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSpinnerDesignDlg)
m_scale = 1.0;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSpinnerDesignDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSpinnerDesignDlg)
DDX_Control(pDX, IDC_COMBO2, m_combo2);
DDX_Control(pDX, IDC_COMBO1, m_combo1);
DDX_Text(pDX, IDC_EDIT1, m_scale);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSpinnerDesignDlg, CDialog)
//{{AFX_MSG_MAP(CSpinnerDesignDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
ON_WM_SIZE()
ON_EN_UPDATE(IDC_EDIT1, OnUpdateEdit1)
ON_WM_LBUTTONDOWN()
ON_BN_CLICKED(IDC_CLEAR, OnClear)
ON_BN_CLICKED(IDC_GENERATE, OnGenerate)
ON_BN_CLICKED(IDC_RESCALE, OnRescale)
ON_WM_DRAWITEM()
ON_BN_CLICKED(IDC_TEST, OnTest)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSpinnerDesignDlg message handlers
BOOL CSpinnerDesignDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
// TODO: Add extra initialization here
m_combo1.ReadFromIniSection("Background");
m_combo2.ReadFromIniSection("Foreground");
m_combo1.SetCurSel(0);
m_combo2.SetCurSel(0);
m_rot2d=0;
m_scale=1.;
bTestViewMode = false;
CheckDlgButton(IDC_RADIOPOLY,1);
m_scale = atof(AfxGetApp()->GetProfileString("Settings","Scale","1"));
UpdateData(false);
goImage.LoadBitmap(IDB_BITMAP1);
clrImage.LoadBitmap(IDB_BITMAP2);
SendDlgItemMessage(IDC_RESCALE,BM_SETIMAGE,IMAGE_BITMAP,reinterpret_cast(goImage.GetSafeHandle()));
SendDlgItemMessage(IDC_BUTTON1,BM_SETIMAGE,IMAGE_BITMAP,reinterpret_cast(clrImage.GetSafeHandle()));
SendDlgItemMessage(IDC_BUTTON3,BM_SETIMAGE,IMAGE_BITMAP,reinterpret_cast(clrImage.GetSafeHandle()));
return TRUE; // return TRUE unless you set the focus to a control
}
void CSpinnerDesignDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CSpinnerDesignDlg::DrawGrid(CDC *pDC)
{
CRect rcClient;
GetClientRect(rcClient);
// make the background of the drawable area white.
CBrush cBr(RGB(255,255,255));
pDC->SelectObject(&cBr);
pDC->Rectangle(0,DLGHEIGHT,rcClient.right,rcClient.bottom);
// Draw the big line thru the center markings
rcClient.top=DLGHEIGHT;
CPen cPen(PS_DASHDOT,1,RGB(100,100,100));
pDC->SelectObject(&cPen);
pDC->SetBkMode(TRANSPARENT);
pDC->MoveTo(rcClient.right/2,rcClient.top);
pDC->LineTo(rcClient.right/2,rcClient.bottom);
pDC->MoveTo(rcClient.left,(rcClient.bottom/2)+(rcClient.top/2));
pDC->LineTo(rcClient.right,(rcClient.bottom/2)+(rcClient.top/2));
}
void CSpinnerDesignDlg::DrawItem(CDC *pDC)
{
// intialize the drawing objects and regions.
int offsetdeg = GetDlgItemInt(IDC_EDIT1);
double offsetangle = PI * ((double)offsetdeg / 180.);
CRect rcClient;
GetClientRect(rcClient);
rcClient.top=DLGHEIGHT;
CPoint centre(rcClient.right/2,(rcClient.bottom/2)+(rcClient.top/2));
CPen solidblack(PS_SOLID,0,RGB(0,0,0));
CPen *old = pDC->SelectObject(&solidblack);
CBrush solidbrush(RGB(255,255,255));
CBrush *oldbrush = pDC->SelectObject(&solidbrush);
CRgn rgn;
rgn.CreateRectRgn(0,DLGHEIGHT,rcClient.right,rcClient.bottom);
pDC->SelectClipRgn(&rgn);
// Draw the grid, only clear the screen if were in Test mode.
if(bTestViewMode)
pDC->Rectangle(0,DLGHEIGHT,rcClient.right,rcClient.bottom);
else
DrawGrid(pDC);
// draw all objects Ive stored in my drawing list.
POSITION pos = mylist.GetHeadPosition();
while(pos!=NULL)
{
CObjectStorage *pStore = (CObjectStorage*) mylist.GetNext(pos);
pStore->Draw(pDC,m_scale,m_rot2d,centre);
}
// now put the grid points on last, this will draw the grid on top
// of all objects, which is what we require. But dont draw them in test mode.
if(!bTestViewMode)
{
for(int yPos=DLGHEIGHT;yPosSetPixel(xPos,yPos,RGB(100,100,100));
}
}
}
// put old objects back into dc
pDC->SelectClipRgn(NULL);
pDC->SelectObject(old);
pDC->SelectObject(oldbrush);
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CSpinnerDesignDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CPaintDC dc(this); // device context for painting
DrawItem(&dc);
CRect rcClient; GetClientRect(rcClient);
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSpinnerDesignDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CSpinnerDesignDlg::DrawColourList(LPDRAWITEMSTRUCT lpDraw, CComboBox& wnd)
{
}
void CSpinnerDesignDlg::OnClose()
{
m_combo1.WriteToIniSection("Background");
m_combo2.WriteToIniSection("Foreground");
CString strDouble; strDouble.Format("%f",m_scale);
AfxGetApp()->WriteProfileString("Settings","Scale",strDouble);
ClearItems();
CDialog::OnClose();
}
void CSpinnerDesignDlg::ClearItems()
{
POSITION pos = mylist.GetHeadPosition();
while(pos)
{
delete mylist.GetNext(pos);
}
mylist.RemoveAll();
}
void CSpinnerDesignDlg::OnButton1()
{
CColourPicker pick;
pick.m_comboClr = &m_combo1;
pick.DoModal();
}
void CSpinnerDesignDlg::OnButton3()
{
CColourPicker pick;
pick.m_comboClr = &m_combo2;
pick.DoModal();
}
void CSpinnerDesignDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
CRect rcInvalid; GetClientRect(rcInvalid);
rcInvalid.top=DLGHEIGHT;
InvalidateRect(rcInvalid);
//reset the window size variables here?
}
void CSpinnerDesignDlg::OnUpdateEdit1()
{
}
void CSpinnerDesignDlg::ConvertXYtoTheta(CPoint point,double &ang,double &len)
{
// now correct them to the screen
CRect rcClient;
GetClientRect(rcClient);
rcClient.top=DLGHEIGHT;
CPoint centre(rcClient.right/2,(rcClient.bottom/2)+(rcClient.top/2));
point-=centre;
point.y = -point.y; // y coords are reversed in my model
// (line length) square root of the squares
double xsq = pow((0. - (double)point.x),2);
double ysq = pow((0. - (double)point.y),2);
len = sqrt(xsq + ysq);
len/=m_scale;
// find the angle of the line. (TO THETA)
double xdt = 0. - (double)point.x;
double ydt = 0. - (double)point.y;
ang = atan(xdt/ydt);
// we are on the other side of the circle.
// the above only calculates the position in 180deg
// we find out if its on "the other side" :)
if(ydt>0)
{
ang += PI;
}
ang-=m_rot2d;
}
void CSpinnerDesignDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// correct the coordinates. to grid
point.x = point.x-(point.x % GRIDSIZE);
point.y = point.y-(point.y % GRIDSIZE);
// choose what coordinate type we are currently drawing.
AddToDiagram(point);
// do a forced redraw.
InvalidateRect(NULL,1);
}
void CSpinnerDesignDlg::AddToDiagram(CPoint point)
{
int count=0;
double angle,length;
ConvertXYtoTheta(point,angle,length);
CObjectStorage *pPoly;
if(IsDlgButtonChecked(IDC_RADIOPOLY))
pPoly= new CPolyStorage();
else
pPoly= new CLineStorage();
count=1;
BOOL bStillDrawing = TRUE;
CPoint newPoint(0,0);
CPoint oldpoint;
CPoint oldendPoint;
oldpoint.x = -99999999;
if (this != GetCapture()) SetCapture();
ASSERT(this == GetCapture());
while(bStillDrawing)
{
MSG msg;
VERIFY(::GetMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST));
if (CWnd::GetCapture() != this)
{
break;
}
/// get point, and adjust from screen coords to window coords ///
newPoint = msg.pt;
ScreenToClient(&newPoint);
switch(msg.message)
{
case WM_LBUTTONUP:
if(count>=MAX_POLY)
bStillDrawing=FALSE;
else
{
if((newPoint.x % GRIDSIZE)>(GRIDSIZE/2))
newPoint.x = newPoint.x + (GRIDSIZE-(newPoint.x % GRIDSIZE));
else
newPoint.x = newPoint.x - (newPoint.x % GRIDSIZE);
if((newPoint.y % GRIDSIZE)>(GRIDSIZE/2))
newPoint.y = newPoint.y + (GRIDSIZE-(newPoint.y % GRIDSIZE));
else
newPoint.y = newPoint.y - (newPoint.y % GRIDSIZE);
newPoint.y = newPoint.y - (newPoint.y % GRIDSIZE);
ConvertXYtoTheta(newPoint,angle,length);
pPoly->AddPoint(angle,length);
DrawTracked(point,newPoint);
count++;
point = newPoint;
}
break;
case WM_MOUSEMOVE:
if((newPoint.x % GRIDSIZE)>(GRIDSIZE/2))
newPoint.x = newPoint.x + (GRIDSIZE-(newPoint.x % GRIDSIZE));
else
newPoint.x = newPoint.x - (newPoint.x % GRIDSIZE);
if((newPoint.y % GRIDSIZE)>(GRIDSIZE/2))
newPoint.y = newPoint.y + (GRIDSIZE-(newPoint.y % GRIDSIZE));
else
newPoint.y = newPoint.y - (newPoint.y % GRIDSIZE);
if(-99999999!=oldpoint.x) DrawTracked(oldpoint,oldendPoint);
oldpoint = point;
oldendPoint = newPoint;
DrawTracked(point,newPoint);
break;
case WM_RBUTTONDBLCLK:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
bStillDrawing=FALSE;
case WM_LBUTTONDOWN:
break;
default:
DispatchMessage(&msg);
break;
}
}
// store away as angle length pairs.
ReleaseCapture();
int iPos=m_combo1.GetCurSel();
int bg = m_combo1.GetItemData(iPos);
iPos=m_combo2.GetCurSel();
int fg = m_combo2.GetItemData(iPos);
pPoly->SetFgRGB(fg&0xff, (fg>>8)&0xff, (fg>>16)&0xff);
pPoly->SetBkRGB(bg&0xff, (bg>>8)&0xff, (bg>>16)&0xff);
mylist.AddTail(pPoly);
}
// Draw a tracker type line on the display which if drawn twice
// will "undisplay" itself.
void CSpinnerDesignDlg::DrawTracked(CPoint startPoint,CPoint endPoint)
{
CRgn rgnNew;
CBrush* pBrush = CDC::GetHalftoneBrush();
CDC* pDC = GetDC();
CRect rect(startPoint, endPoint);
rect.NormalizeRect();
int x_delta, y_delta;
/// choose some deltas to make the tracking line look OK in each orientation ///
if (rect.Height() > rect.Width())
{
x_delta = 1;
y_delta = 0;
}
else
{
x_delta = 0;
y_delta = 1;
}
CPoint newPoints[] =
{
CPoint(startPoint.x + x_delta, startPoint.y - y_delta),
CPoint(startPoint.x - x_delta, startPoint.y + y_delta),
CPoint(endPoint.x - x_delta, endPoint.y + y_delta),
CPoint(endPoint.x + x_delta, endPoint.y - y_delta)
};
rgnNew.CreatePolygonRgn(newPoints, 4, ALTERNATE);
pDC->SelectClipRgn(&rgnNew);
pDC->GetClipBox(&rect);
CBrush* pBrushOld = pDC->SelectObject(pBrush);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
/// restore the device context ///
pDC->SelectObject(pBrushOld);
pDC->SelectClipRgn(NULL);
ReleaseDC(pDC);
}
void CSpinnerDesignDlg::OnClear()
{
if(mylist.GetCount()>0)
{
CString str;
str.LoadString(IDS_CLEAR_ARE_YOU_SURE);
if(MessageBox(str,"Are you sure",MB_OKCANCEL|MB_ICONQUESTION)==IDOK)
{
ClearItems();
}
}
else ClearItems();
Invalidate();
}
void CSpinnerDesignDlg::OnGenerate()
{
CFileDialog dlg(FALSE,"JVF");
if(dlg.DoModal()==IDOK)
{
try
{
CFile file(dlg.GetFileName(),CFile::modeCreate|CFile::modeWrite);
StorageHeader hdr;
hdr.magic = 0xfade0ff;
hdr.byReserved=0;
hdr.elements=mylist.GetCount();
hdr.byRed=255;
hdr.byBlue=255;
hdr.byGreen=255;
file.Write(&hdr,sizeof StorageHeader);
POSITION pos = mylist.GetHeadPosition();
while(pos)
{
CObjectStorage *obj = (CObjectStorage*)mylist.GetNext(pos);
obj->OutputCoordinates(&file);
}
file.Close();
}
catch(CFileException *e)
{
char szError[255];
e->GetErrorMessage(szError,sizeof szError);
MessageBox(CString("Problem opening file!\n")+szError);
}
}
}
void CSpinnerDesignDlg::OnRescale()
{
UpdateData();
Invalidate();
}
void CSpinnerDesignDlg::OnTest()
{
// start by settting test=true, store scale and rotation.
bTestViewMode=true;
double scl = m_scale;
double rot = m_rot2d;
// work from rotation of 0 and scale of 0.1 going up in increments.
m_scale=0.1;
for(int i=0;i<360;i++)
{
m_scale+=0.004;
m_rot2d+=0.03;
Sleep(30); // delay between frames
Invalidate();
UpdateWindow();
}
// restore our screen..
m_scale = scl;
m_rot2d = rot;
bTestViewMode=false;
Invalidate();
UpdateWindow();
}
               (
geocities.com/elricsgsx/java)                   (
geocities.com/elricsgsx)