#include "gdiptest.h" #include 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; posGetDisabled()) { // 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; posIsComplete()); 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(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(); }