716 lines
13 KiB
C++
716 lines
13 KiB
C++
#include "gdiptest.h"
|
|
#include <commctrl.h>
|
|
|
|
|
|
extern const TCHAR* formatExtList =
|
|
_T("CPP files\0*.cpp\0"
|
|
"Java files\0*.Java\0"
|
|
"VML files\0*.vml\0"
|
|
"All files\0*.*\0");
|
|
|
|
extern const TCHAR* defaultFormatExt = _T("cpp");
|
|
|
|
//*******************************************************************
|
|
//
|
|
// TestDraw
|
|
//
|
|
//
|
|
//
|
|
//*******************************************************************
|
|
|
|
VOID TestDraw::AddPoint(HWND hwnd, Point pt)
|
|
{
|
|
if (!curShape)
|
|
{
|
|
// no current shape, create one of appropriate type
|
|
curShape = TestShape::CreateNewShape(shapeType);
|
|
curShape->Initialize(NULL);
|
|
|
|
// save copy of brush & pen in shape
|
|
curShape->SetBrush(curBrush->Clone());
|
|
curShape->SetPen(curPen->Clone());
|
|
}
|
|
else if (curShape->IsComplete())
|
|
{
|
|
TestShape *lastShape = curShape;
|
|
|
|
// add current shape to shape stack
|
|
shapeStack.Push(curShape);
|
|
|
|
// create blank shape of this type
|
|
curShape = TestShape::CreateNewShape(shapeType);
|
|
curShape->Initialize(lastShape);
|
|
|
|
// save copy of brush & pen in shape
|
|
curShape->SetBrush(curBrush->Clone());
|
|
curShape->SetPen(curPen->Clone());
|
|
}
|
|
|
|
curShape->AddPoint(hwnd, pt);
|
|
}
|
|
|
|
BOOL TestDraw::DoneShape(HWND hwnd)
|
|
{
|
|
// we are at regular end point regardless
|
|
if (!curShape->IsComplete())
|
|
{
|
|
// if point can't be treated as an 'end point' then treat
|
|
// it as a regular control point
|
|
curShape->DoneShape(hwnd);
|
|
}
|
|
|
|
return curShape->IsComplete();
|
|
}
|
|
|
|
BOOL TestDraw::EndPoint(HWND hwnd, Point pt)
|
|
{
|
|
AddPoint(hwnd, pt);
|
|
|
|
return DoneShape(hwnd);
|
|
}
|
|
|
|
BOOL TestDraw::RemovePoint(HWND hwnd)
|
|
{
|
|
if (!curShape || (curShape && !curShape->RemovePoint(hwnd)))
|
|
{
|
|
if (shapeStack.GetCount() > 0)
|
|
{
|
|
// the shape is empty, delete it
|
|
delete curShape;
|
|
|
|
curShape = shapeStack.Pop();
|
|
|
|
// !! reset menu option for current shape
|
|
UpdateStatus();
|
|
|
|
return curShape->RemovePoint(hwnd);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID TestDraw::Draw(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rt;
|
|
HDC hdc;
|
|
|
|
// !!! when CopyPixels work, cache the graphics up to the
|
|
// last shape. We blit that, then the new shape begins.
|
|
|
|
// posts a WM_ERASEBKGND message
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
|
|
/////////////////////////////////////////////////////
|
|
// GDI+ code BEGINS
|
|
////////////////////////////////////////////////////
|
|
Graphics *g = new Graphics(hwnd);
|
|
|
|
GetClientRect(hwnd, &rt);
|
|
ERectangle rect(rt.left,
|
|
rt.top,
|
|
rt.right-rt.left,
|
|
rt.bottom-rt.top
|
|
-18); // for status window
|
|
|
|
// set appropriate clip region
|
|
if (useClip)
|
|
{
|
|
Region region(rect);
|
|
region.And(clipRegion);
|
|
g->SetClip(®ion);
|
|
}
|
|
else
|
|
{
|
|
g->SetClip(rect);
|
|
}
|
|
|
|
g->SetRenderingHint(antiAlias);
|
|
|
|
g->SetWorldTransform(worldMatrix);
|
|
|
|
// !!! iterate through stack of shapes.
|
|
|
|
// because of alpha we can't just redraw the last shape,
|
|
// otherwise we will blend alpha with ourself and whatever
|
|
// else is under us. clear the rectangle and redraw all.
|
|
|
|
if (redrawAll)
|
|
{
|
|
INT count = shapeStack.GetCount();
|
|
INT pos;
|
|
|
|
for (pos=0; pos<count; pos++)
|
|
{
|
|
TestShape *shape = shapeStack[pos];
|
|
|
|
if (!shape->GetDisabled())
|
|
{
|
|
// shape must be complete
|
|
ASSERT(shape->IsComplete());
|
|
|
|
shape->DrawShape(g);
|
|
|
|
if (keepControlPoints)
|
|
shape->DrawPoints(g);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (curShape)
|
|
{
|
|
if (curShape->IsComplete())
|
|
{
|
|
curShape->DrawShape(g);
|
|
|
|
if (keepControlPoints)
|
|
goto DrawCurShape;
|
|
}
|
|
else
|
|
{
|
|
DrawCurShape:
|
|
g->SetClip(rect);
|
|
curShape->DrawPoints(g);
|
|
}
|
|
}
|
|
|
|
delete g;
|
|
|
|
////////////////////////////////////////////////////
|
|
// GDI+ code ENDS.
|
|
////////////////////////////////////////////////////
|
|
|
|
UpdateStatus();
|
|
|
|
EndPaint(hwnd, &ps);
|
|
|
|
}
|
|
|
|
VOID TestDraw::SetClipRegion(HWND hwnd)
|
|
{
|
|
|
|
if (!curShape)
|
|
{
|
|
WarningBox(_T("Create at least one shape first!"));
|
|
return;
|
|
}
|
|
|
|
// we want to allow the very last shape to clip
|
|
// so we add it in here to the stack list.
|
|
if (curShape->IsComplete())
|
|
{
|
|
TestShape *lastShape = curShape;
|
|
|
|
// add current shape to shape stack
|
|
shapeStack.Push(curShape);
|
|
|
|
// create blank shape of this type
|
|
curShape = TestShape::CreateNewShape(shapeType);
|
|
curShape->Initialize(lastShape);
|
|
|
|
// save copy of brush & pen in shape
|
|
curShape->SetBrush(curBrush->Clone());
|
|
curShape->SetPen(curPen->Clone());
|
|
}
|
|
|
|
// notice we repeatly initialize even though we only
|
|
// created this once...
|
|
clipShapeRegion->Initialize(&shapeStack, curShape, useClip);
|
|
|
|
if (clipShapeRegion->ChangeSettings(hwnd))
|
|
{
|
|
delete clipRegion;
|
|
clipRegion = clipShapeRegion->GetClipRegion();
|
|
|
|
useClip = clipShapeRegion->GetClipBool();
|
|
|
|
SetMenuCheckCmd(hwnd,
|
|
MenuOtherPosition,
|
|
IDM_USECLIP,
|
|
useClip);
|
|
|
|
// force redraw of all stacked shapes w/new clip region
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
VOID TestDraw::RememberPoint(Point pt)
|
|
{
|
|
remPoint = pt;
|
|
}
|
|
|
|
VOID TestDraw::MoveControlPoint(Point pt)
|
|
{
|
|
// find shape that hits control point.
|
|
|
|
Point *hitpt = NULL;
|
|
|
|
if (curShape)
|
|
{
|
|
if (curShape->MoveControlPoint(remPoint, pt))
|
|
return;
|
|
|
|
INT count = shapeStack.GetCount();
|
|
INT pos;
|
|
|
|
for (pos = count-1; pos>=0; pos--)
|
|
{
|
|
TestShape* shape = shapeStack[pos];
|
|
|
|
if (shape->MoveControlPoint(remPoint, pt))
|
|
return;
|
|
}
|
|
}
|
|
|
|
// nothing moved
|
|
WarningBeep();
|
|
}
|
|
|
|
VOID TestDraw::ChangeBrush(HWND hwnd, INT type)
|
|
{
|
|
TestBrush *newBrush = NULL;
|
|
|
|
if (curBrush && (type == curBrush->GetType()))
|
|
{
|
|
// same brush type
|
|
|
|
// !!! change brush color in middle of drawing?
|
|
|
|
TestBrush* newBrush = curBrush->Clone();
|
|
|
|
if (newBrush->ChangeSettings(hwnd))
|
|
{
|
|
delete curBrush;
|
|
curBrush = newBrush;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// new brush type
|
|
|
|
SetMenuCheckPos(hwnd,
|
|
MenuBrushPosition,
|
|
curBrush->GetType(),
|
|
FALSE);
|
|
|
|
newBrush = TestBrush::CreateNewBrush(type);
|
|
|
|
if (!newBrush)
|
|
{
|
|
return;
|
|
}
|
|
|
|
newBrush->Initialize();
|
|
|
|
// keep or discard changed brush settings
|
|
if (newBrush->ChangeSettings(hwnd))
|
|
{
|
|
delete curBrush;
|
|
curBrush = newBrush;
|
|
// !!! change brush color in middle of drawing
|
|
}
|
|
else
|
|
{
|
|
delete newBrush;
|
|
}
|
|
|
|
SetMenuCheckPos(hwnd,
|
|
MenuBrushPosition,
|
|
curBrush->GetType(),
|
|
TRUE);
|
|
}
|
|
|
|
if (curShape && curShape->GetCount() == 0)
|
|
{
|
|
curShape->SetBrush(curBrush->Clone());
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
VOID TestDraw::ChangePen(HWND hwnd)
|
|
{
|
|
TestPen *newPen = NULL;
|
|
|
|
if (curPen)
|
|
{
|
|
TestPen *newPen = curPen->Clone();
|
|
|
|
if (newPen->ChangeSettings(hwnd))
|
|
{
|
|
delete curPen;
|
|
curPen = newPen;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
newPen = new TestPen();
|
|
newPen->Initialize();
|
|
|
|
// !!! change pen in middle of drawing?
|
|
if (newPen->ChangeSettings(hwnd))
|
|
{
|
|
delete curPen;
|
|
curPen = newPen;
|
|
}
|
|
else
|
|
{
|
|
delete newPen;
|
|
}
|
|
}
|
|
|
|
if (curShape && curShape->GetCount() == 0)
|
|
{
|
|
curShape->SetPen(curPen->Clone());
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
VOID TestDraw::ChangeShape(HWND hwnd, INT type)
|
|
{
|
|
TestShape *shape;
|
|
|
|
shape = TestShape::CreateNewShape(type);
|
|
shape->Initialize(curShape);
|
|
|
|
// save copy of brush & pen in shape
|
|
shape->SetBrush(curBrush->Clone());
|
|
shape->SetPen(curPen->Clone());
|
|
|
|
if (shape->ChangeSettings(hwnd))
|
|
{
|
|
SetMenuCheckPos(hwnd,
|
|
MenuShapePosition,
|
|
shapeType,
|
|
FALSE);
|
|
|
|
shapeType = type;
|
|
|
|
// if shape can be completed, complete it, otherwise
|
|
// destroy the shape.
|
|
|
|
if (curShape)
|
|
{
|
|
if (!curShape->IsComplete())
|
|
{
|
|
curShape->DoneShape(hwnd);
|
|
}
|
|
|
|
if (!curShape->IsComplete() || curShape->IsEmpty())
|
|
{
|
|
delete curShape;
|
|
curShape = NULL;
|
|
}
|
|
}
|
|
|
|
if (curShape)
|
|
shapeStack.Add(curShape);
|
|
|
|
curShape = shape;
|
|
|
|
SetMenuCheckPos(hwnd,
|
|
MenuShapePosition,
|
|
shapeType,
|
|
TRUE);
|
|
|
|
// removing last incomplete shape, redraw the window.
|
|
// OR completed shape, redraw the window
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
else
|
|
{
|
|
delete shape;
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
VOID TestDraw :: UpdateStatus(HWND hwnd)
|
|
{
|
|
if (hwnd)
|
|
{
|
|
|
|
if (hwndStatus)
|
|
{
|
|
// destroy previous window
|
|
DestroyWindow(hwndStatus);
|
|
hwndStatus = NULL;
|
|
}
|
|
|
|
// we only want to destroy this window
|
|
if (hwnd == (HWND)-1)
|
|
return;
|
|
|
|
hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE,
|
|
_T(""),
|
|
hwnd,
|
|
0); // never used?
|
|
}
|
|
|
|
if (hwndStatus)
|
|
{
|
|
TCHAR str[MAX_PATH];
|
|
|
|
_stprintf(&str[0],"[Last shape: %s] [Brush: %s] [Number of Points: %d]",
|
|
shapeList[inverseShapeValue[GetShapeType()]],
|
|
brushList[inverseBrushValue[GetBrushType()]],
|
|
curShape ? curShape->GetCount() : 0);
|
|
|
|
// !! for some reason, DrawStatusText didn't work here...
|
|
// wouldn't it just call SendMessage() ?!?
|
|
|
|
SendMessage(hwndStatus, SB_SETTEXT, 0 | 0, (LPARAM)(LPTSTR)str);
|
|
}
|
|
}
|
|
|
|
VOID TestDraw :: SaveAsFile(HWND hWnd)
|
|
{
|
|
static TCHAR fname[MAX_PATH] = _T("");
|
|
|
|
OPENFILENAME ofn =
|
|
{
|
|
sizeof(OPENFILENAME),
|
|
hWnd,
|
|
0,
|
|
formatExtList,
|
|
NULL,
|
|
0,
|
|
1,
|
|
&fname[0],
|
|
MAX_PATH-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
OFN_PATHMUSTEXIST,
|
|
0,
|
|
0,
|
|
defaultFormatExt,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
if ((GetSaveFileName(&ofn) == TRUE) &&
|
|
fname[0] != '\0')
|
|
{
|
|
OutputFile* outfile = OutputFile::CreateOutputFile(fname);
|
|
|
|
if (outfile)
|
|
{
|
|
outfile->GraphicsProcedure();
|
|
|
|
outfile->BeginIndent();
|
|
|
|
outfile->GraphicsDeclaration();
|
|
|
|
outfile->BlankLine();
|
|
|
|
outfile->SetMatrixDeclaration(_T("g"),
|
|
_T("SetWorldTransform"),
|
|
_T("worldMatrix"),
|
|
worldMatrix);
|
|
|
|
INT count = shapeStack.GetCount();
|
|
|
|
for (INT pos=0; pos<count; pos++)
|
|
{
|
|
TestShape *shape = shapeStack[pos];
|
|
ASSERT(shape->IsComplete());
|
|
|
|
outfile->BlankLine();
|
|
|
|
outfile->BeginIndent();
|
|
|
|
shape->AddToFile(outfile);
|
|
|
|
outfile->EndIndent();
|
|
}
|
|
|
|
if (curShape && curShape->IsComplete())
|
|
{
|
|
outfile->BlankLine();
|
|
|
|
outfile->BeginIndent();
|
|
|
|
curShape->AddToFile(outfile);
|
|
|
|
outfile->EndIndent();
|
|
}
|
|
|
|
outfile->EndIndent();
|
|
|
|
delete outfile;
|
|
|
|
WarningBox(_T("Graphics source code saved."));
|
|
}
|
|
else
|
|
WarningBox(_T("Can't create file for writing."));
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
//*******************************************************************
|
|
//
|
|
// TestGradDraw
|
|
//
|
|
//
|
|
//
|
|
//*******************************************************************
|
|
|
|
VOID TestGradDraw::AddPoint(HWND hwnd, Point pt)
|
|
{
|
|
gradShape->AddPoint(hwnd, pt);
|
|
}
|
|
|
|
BOOL TestGradDraw::DoneShape(HWND hwnd)
|
|
{
|
|
// pop-up dialog box to configure point parameters
|
|
gradShape->DoneShape(hwnd);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL TestGradDraw::EndPoint(HWND hwnd, Point pt)
|
|
{
|
|
return gradShape->EndPoint(hwnd, pt);
|
|
}
|
|
|
|
BOOL TestGradDraw::RemovePoint(HWND hwnd)
|
|
{
|
|
return gradShape->RemovePoint(hwnd);
|
|
}
|
|
|
|
VOID TestGradDraw::Draw(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rt;
|
|
HDC hdc;
|
|
|
|
// !!! when CopyPixels work, cache the graphics up to the
|
|
// last shape. We blit that, then the new shape begins.
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
|
|
/////////////////////////////////////////////////////
|
|
// GDI+ code BEGINS
|
|
////////////////////////////////////////////////////
|
|
Graphics *g = new Graphics(hwnd);
|
|
|
|
GetClientRect(hwnd, &rt);
|
|
ERectangle rect(rt.left,
|
|
rt.top,
|
|
rt.right-rt.left,
|
|
rt.bottom-rt.top);
|
|
g->SetClip(rect);
|
|
|
|
g->SetRenderingHint(TRUE);
|
|
|
|
gradShape->DrawShape(g);
|
|
gradShape->DrawPoints(g);
|
|
|
|
delete g;
|
|
|
|
////////////////////////////////////////////////////
|
|
// GDI+ code ENDS.
|
|
////////////////////////////////////////////////////
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
|
|
VOID TestGradDraw::SetClipRegion(HWND hwnd)
|
|
{
|
|
}
|
|
|
|
VOID TestGradDraw::RememberPoint(Point pt)
|
|
{
|
|
remPoint = pt;
|
|
}
|
|
|
|
VOID TestGradDraw::MoveControlPoint(Point pt)
|
|
{
|
|
if (!gradShape->MoveControlPoint(remPoint, pt))
|
|
WarningBeep();
|
|
}
|
|
|
|
VOID TestGradDraw :: UpdateStatus(HWND hwnd)
|
|
{
|
|
}
|
|
|
|
VOID TestGradDraw :: SaveAsFile(HWND hwnd)
|
|
{
|
|
}
|
|
|
|
BOOL TestGradDraw :: ChangeSettings(HWND hwndParent)
|
|
{
|
|
HWND hWnd;
|
|
MSG msg;
|
|
|
|
HMENU hMenu = LoadMenu(hInst,
|
|
MAKEINTRESOURCE(IDR_GRADBRUSH));
|
|
|
|
hWnd = CreateWindow(
|
|
szWindowClass,
|
|
_T("Gradient Brush Shape"),
|
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
300,
|
|
200,
|
|
(HWND)hwndParent,
|
|
(HMENU)hMenu, // menu handle
|
|
(HINSTANCE)hInst,
|
|
(LPVOID)(static_cast<TestDrawInterface*>(this)));
|
|
|
|
if (!hWnd)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ShowWindow(hWnd, SW_SHOWNORMAL);
|
|
UpdateWindow(hWnd);
|
|
|
|
HACCEL hAccelTable = LoadAccelerators(hInst, (LPCTSTR)IDC_GDIPTEST);
|
|
|
|
// Main message loop:
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
DeleteObject(hAccelTable);
|
|
|
|
return msg.wParam;
|
|
}
|
|
|
|
VOID TestGradDraw::Initialize()
|
|
{
|
|
DebugBreak();
|
|
}
|
|
|
|
VOID TestGradDraw::Initialize(TestGradShape *newGradShape)
|
|
{
|
|
gradShape = newGradShape;
|
|
}
|
|
|
|
VOID TestGradDraw::Reset(HWND hwnd)
|
|
{
|
|
NotImplementedBox();
|
|
}
|
|
|
|
VOID TestGradDraw::Instructions(HWND hwnd)
|
|
{
|
|
NotImplementedBox();
|
|
}
|