/* * @(#) grmorph.cpp - Graphic morphology program for Windows. * (c) 1996 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: C++ * Tested with: Borland C++ v3.1 * Last modified: 1996-04-29 23:05:00 GMT+04:00 */ // Resource file: grmorph.rc #define WIN31 #define STRICT #include #include #include const int BitMapWidth= 800; const int BitMapHeight= 600; const COLORREF Colors[3][16]= {{0x00FFFFFFl,0x00E0E0E0l,0x00C0C0FFl,0x00C0E0FFl, 0x00E0FFFFl,0x00C0FFC0l,0x00FFFFC0l,0x00FFC0C0l, 0x00FFC0FFl,0x000000C0l,0x000040C0l,0x0000C0C0l, 0x0000C000l,0x00C0C000l,0x00C00000l,0x00C000C0l}, {0x00C0C0C0l,0x00404040l,0x008080FFl,0x0080C0FFl, 0x0080FFFFl,0x0080FF80l,0x00FFFF80l,0x00FF8080l, 0x00FF80FFl,0x00000080l,0x00004080l,0x00008080l, 0x00008000l,0x00808000l,0x00800000l,0x00800080l}, {0x00808080l,0x00000000l,0x000000FFl,0x000080FFl, 0x0000FFFFl,0x0000FF00l,0x00FFFF00l,0x00FF0000l, 0x00FF00FFl,0x00000040l,0x00404080l,0x00004040l, 0x00004000l,0x00404000l,0x00400000l,0x00400040l}}; const int ToolCount= 8; const int MenuCount= 4; const int LineCount= 8; const int IconSize= 32; const int LineBarWidth= LineCount*4+6+(1+2+3+4+5+7+9+12); const int LineWidth[LineCount]= {1,2,3,4,5,7,9,12}; _CLASSDEF(TDrawTool) _CLASSDEF(TPointMask) struct TState { PTDrawTool DrawTool; PTPointMask PointMask; HBITMAP BitMap; RECT Area; int PenSize; COLORREF Foreground,Background; }; typedef TState* PTState; // already _CLASSDEF'ed class TDrawTool { protected: HCURSOR Cursor; HICON Icon; PTState State; HWND Window; HPEN Pen; HBRUSH Brush; HDC DC; public: TDrawTool(LPSTR IconName); virtual ~TDrawTool() { DestroyCursor(Cursor); DestroyIcon(Icon); }; BOOL MouseDown(HWND AWindow,int X,int Y,COLORREF Color,PTState AState); void MouseMove(int X,int Y) { DrawTo(X,Y); }; void MouseUp(); virtual BOOL DrawBegin(int X,int Y) { return (FALSE); }; virtual void DrawTo(int X,int Y) {}; virtual void DrawEnd() {}; virtual void Done(PTState AState) {}; HCURSOR GetCursor() { return Cursor; }; HICON GetIcon() { return Icon; }; }; _CLASSDEF(TPenTool) class TPenTool : public TDrawTool { public: TPenTool(LPSTR IconName) : TDrawTool(IconName) {}; virtual BOOL DrawBegin(int X,int Y); virtual void DrawTo(int X,int Y) { LineTo(DC,X,Y); }; }; _CLASSDEF(TFillTool) class TFillTool : public TDrawTool { public: TFillTool(LPSTR IconName) : TDrawTool(IconName) {}; virtual BOOL DrawBegin(int X,int Y); }; _CLASSDEF(TBoxTool) class TBoxTool : public TDrawTool { protected: BOOL Filled; int X1,Y1,X2,Y2; public: TBoxTool(LPSTR IconName,BOOL AFilled) : TDrawTool(IconName) { Filled=AFilled; }; virtual BOOL DrawBegin(int X,int Y); virtual void DrawTo(int X,int Y); virtual void DrawEnd(); virtual void DrawObject(BOOL Draw) {}; }; _CLASSDEF(TLineTool) class TLineTool : public TBoxTool { public: TLineTool(LPSTR IconName) : TBoxTool(IconName,False) {}; virtual void DrawObject(BOOL) { MoveTo(DC,X1,Y1); LineTo(DC,X2,Y2); }; }; _CLASSDEF(TRectTool) class TRectTool : public TBoxTool { public: TRectTool(LPSTR IconName,BOOL AFilled) : TBoxTool(IconName,AFilled) {}; virtual void DrawObject(BOOL) { Rectangle(DC,X1,Y1,X2,Y2); }; }; _CLASSDEF(TEllipseTool) class TEllipseTool : public TBoxTool { public: TEllipseTool(LPSTR IconName,BOOL AFilled) : TBoxTool(IconName,AFilled) {}; virtual void DrawObject(BOOL) { Ellipse(DC,X1,Y1,X2,Y2); }; }; _CLASSDEF(TSelectTool) class TSelectTool : public TRectTool { private: BOOL Selected; HBITMAP Region; public: TSelectTool(LPSTR IconName) : TRectTool(IconName,FALSE) { Selected=FALSE; }; virtual BOOL DrawBegin(int X,int Y); virtual void DrawEnd(); virtual void DrawObject(BOOL Draw); virtual void Done(PTState AState); void DrawFrame(BOOL Draw); void AdjustFrame(BOOL On); void CreateRegion(); void CopyRegion(); void RestoreRegion(); }; _CLASSDEF(TPalette) class TPalette : public TWindow { private: PTState State; public: TPalette(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; }; virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); void SelectColor(TMessage& Message,COLORREF& Color); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN] { SelectColor(Message,State->Foreground); }; virtual void WMRButtonDown(TMessage& Message)= [WM_FIRST+WM_RBUTTONDOWN] { SelectColor(Message,State->Background); }; }; // already _CLASSDEF'ed class TPointMask { private: BOOL Mask[3][3]; public: TPointMask(); void Invert(int X,int Y); BOOL Get(int X,int Y) { return ((X<-1 || X>1 || Y<-1 || Y>1)? FALSE : Mask[Y+1][X+1]); }; BOOL IsEmpty(); }; _CLASSDEF(TMaskEditor) class TMaskEditor : public TWindow { private: PTState State; public: TMaskEditor(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; }; virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; }; _CLASSDEF(TToolBar) class TToolBar : public TWindow { private: PTState State; PTDrawTool Tools[ToolCount]; public: TToolBar(PTWindowsObject AParent,PTState AState); virtual ~TToolBar(); virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; }; _CLASSDEF(TLineBar) class TLineBar : public TWindow { public: TLineBar(PTWindowsObject AParent,PTState AState); virtual void Paint(HDC PaintDC, PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; private: PTState State; void Notch(HDC PaintDC,int X,int W,int Y,int DY); }; _CLASSDEF(TCanvas) class TCanvas : public TWindow { private: PTState State; BOOL Drawing; public: TCanvas(PTWindowsObject AParent,PTState AState); virtual ~TCanvas() { DeleteObject(State->BitMap); }; virtual LPSTR GetClassName() { return "TCanvas"; }; virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; virtual void WMRButtonDown(TMessage& Message)= [WM_FIRST+WM_RBUTTONDOWN]; virtual void WMLButtonUp(TMessage& Message)= [WM_FIRST+WM_LBUTTONUP]; virtual void WMRButtonUp(TMessage& Message)= [WM_FIRST+WM_RBUTTONUP] { WMLButtonUp(Message); }; virtual void WMMouseMove(TMessage& Message)= [WM_FIRST+WM_MOUSEMOVE]; virtual void WMSetCursor(TMessage& Message)= [WM_FIRST+WM_SETCURSOR] { SetCursor(State->DrawTool->GetCursor()); }; HWND GetCanvasWindow() { return (HWindow); }; void SaveDC(); }; _CLASSDEF(TMenuItem) class TMenuItem { protected: HICON Icon; public: TMenuItem(LPSTR IconName) { Icon=LoadIcon(GetApplicationObject()->hInstance,IconName); }; virtual ~TMenuItem() { DestroyIcon(Icon); }; virtual void Run(PTState State,PTCanvas Canvas) {}; HICON GetIcon() { return Icon; }; }; _CLASSDEF(TClearAll) class TClearAll : public TMenuItem { public: TClearAll(LPSTR IconName) : TMenuItem(IconName) {}; virtual void Run(PTState State,PTCanvas Canvas); }; _CLASSDEF(TClipboardRead) class TClipboardRead : public TMenuItem { public: TClipboardRead(LPSTR IconName) : TMenuItem(IconName) {}; virtual void Run(PTState State,PTCanvas Canvas); }; _CLASSDEF(TMorphOperation) class TMorphOperation : public TMenuItem { private: BOOL Dilation; public: TMorphOperation(LPSTR IconName,BOOL ADilation) : TMenuItem(IconName) { Dilation=ADilation; }; virtual void Run(PTState State,PTCanvas Canvas); void Operate(HDC Dest,HDC Src,RECT R,PTPointMask Mask, COLORREF Paint,COLORREF Tested); }; _CLASSDEF(TMenuBar) class TMenuBar : public TWindow { private: PTState State; PTCanvas Canvas; PTMenuItem Items[MenuCount]; public: TMenuBar(PTWindowsObject AParent,PTState AState,PTCanvas ACanvas); virtual ~TMenuBar(); virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; }; _CLASSDEF(TGraphMorphWin) class TGraphMorphWin : public TWindow { private: TState State; PTPalette Palette; PTToolBar ToolBar; PTLineBar LineBar; PTMenuBar MenuBar; PTMaskEditor MaskEdit; PTCanvas Canvas; public: TGraphMorphWin(PTWindowsObject AParent,LPSTR ATitle); virtual ~TGraphMorphWin(); virtual LPSTR GetClassName() { return "TGraphMorphWin"; }; virtual void GetWindowClass(WNDCLASS& WndClass); virtual void WMSize(TMessage& Message)= [WM_FIRST+WM_SIZE]; }; class TGraphMorphApp : public TApplication { public: TGraphMorphApp(LPSTR name,HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmd,int nCmdShow) : TApplication(name,hInstance,hPrevInstance,lpCmd,nCmdShow) {}; virtual void InitMainWindow(void) { MainWindow=new TGraphMorphWin(NULL,"Graphic Morphology"); }; }; void TMorphOperation::Operate(HDC Dest,HDC Src,RECT R,PTPointMask Mask, COLORREF Paint,COLORREF Tested) { int SX,SY; for (int Y=R.top;YGet(SX,SY) && X+SX>=R.left && X+SX=R.top && Y+SYGetCanvasWindow(),&R); if (State->PointMask->IsEmpty() || State->Area.left>R.right || State->Area.top>R.bottom) return; HDC DC=GetDC(Canvas->GetCanvasWindow()); HDC MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); R.left=State->Area.left; R.top=State->Area.top; if (R.right>State->Area.right) R.right=State->Area.right; if (R.bottom>State->Area.bottom) R.bottom=State->Area.bottom; Operate(DC,MemDC,R,State->PointMask, Dilation? State->Foreground : State->Background, Dilation? State->Foreground : State->Background); BitBlt(MemDC,R.left,R.top,R.right-R.left,R.bottom-R.top, DC,R.left,R.top,SRCCOPY); DeleteDC(MemDC); ReleaseDC(Canvas->GetCanvasWindow(),DC); }; TDrawTool::TDrawTool(LPSTR IconName) { char Temp[32]; _fstrcpy(Temp,IconName); strncat(Temp,"Tool",sizeof(Temp)-1); Icon=LoadIcon(GetApplicationObject()->hInstance,Temp); _fstrcpy(Temp,IconName); strncat(Temp,"Cursor",sizeof(Temp)-1); Cursor=LoadCursor(GetApplicationObject()->hInstance,Temp); }; BOOL TDrawTool::MouseDown(HWND AWindow,int X,int Y,COLORREF Color, PTState AState) { Window=AWindow; State=AState; SetCapture(Window); Pen=CreatePen(PS_SOLID,State->PenSize,Color); Brush=CreateSolidBrush(Color); DC=GetDC(Window); return (DrawBegin(X,Y)); }; void TDrawTool::MouseUp() { DrawEnd(); ReleaseCapture(); DeleteObject(Brush); DeleteObject(Pen); ReleaseDC(Window,DC); }; BOOL TPenTool::DrawBegin(int X,int Y) { SelectObject(DC,Pen); MoveTo(DC,X,Y); return (FALSE); }; BOOL TFillTool::DrawBegin(int X,int Y) { SelectObject(DC,Brush); ExtFloodFill(DC,X,Y,GetPixel(DC,X,Y),FLOODFILLSURFACE); return (FALSE); }; BOOL TBoxTool::DrawBegin(int X,int Y) { X1=X2=X; Y1=Y2=Y; SelectObject(DC,GetStockObject(BLACK_PEN)); SelectObject(DC,GetStockObject(NULL_BRUSH)); SetROP2(DC,R2_NOT); DrawObject(TRUE); return (FALSE); }; void TBoxTool::DrawTo(int X,int Y) { DrawObject(FALSE); X2=X; Y2=Y; DrawObject(TRUE); }; void TBoxTool::DrawEnd() { DrawObject(FALSE); SetROP2(DC,R2_COPYPEN); SelectObject(DC,Pen); if (Filled) SelectObject(DC,Brush); DrawObject(TRUE); }; BOOL TSelectTool::DrawBegin(int X,int Y) { DeleteObject(Pen); Pen=CreatePen(PS_DOT,1,0); DrawFrame(FALSE); X1=X2=X; Y1=Y2=Y; if (Selected && X1>=State->Area.left && X1Area.right && Y1>=State->Area.top && Y1Area.bottom) CreateRegion(); else DrawObject(TRUE); return (Selected); }; void TSelectTool::DrawEnd() { if (Selected && X1>=State->Area.left && X1Area.right && Y1>=State->Area.top && Y1Area.bottom) { DeleteObject(Region); State->Area.left+=X2-X1; State->Area.top+=Y2-Y1; State->Area.right+=X2-X1; State->Area.bottom+=Y2-Y1; DrawFrame(TRUE); Selected=TRUE; } else AdjustFrame(X1!=X2 && Y1!=Y2); }; void TSelectTool::DrawObject(BOOL Draw) { if (Selected && X1>=State->Area.left && X1Area.right && Y1>=State->Area.top && Y1Area.bottom) if (Draw) CopyRegion(); else RestoreRegion(); else TRectTool::DrawObject(Draw); }; void TSelectTool::CreateRegion() { int W=State->Area.right-State->Area.left; int H=State->Area.bottom-State->Area.top; HDC RegionDC=CreateCompatibleDC(DC); Region=CreateCompatibleBitmap(DC,W,H); SelectObject(RegionDC,Region); BitBlt(RegionDC,0,0,W,H,DC,State->Area.left,State->Area.top,SRCCOPY); DeleteDC(RegionDC); PatBlt(DC,State->Area.left,State->Area.top,W,H,WHITENESS); }; void TSelectTool::CopyRegion() { HDC RegionDC=CreateCompatibleDC(DC); SelectObject(RegionDC,Region); BitBlt(DC,State->Area.left+X2-X1,State->Area.top+Y2-Y1, State->Area.right-State->Area.left, State->Area.bottom-State->Area.top,RegionDC,0,0,SRCAND); DeleteDC(RegionDC); }; void TSelectTool::RestoreRegion() { int BegX=State->Area.left+X2-X1; int BegY=State->Area.top+Y2-Y1; HDC MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); BitBlt(DC,BegX,BegY,State->Area.right-State->Area.left, State->Area.bottom-State->Area.top,MemDC,BegX,BegY,SRCCOPY); DeleteDC(MemDC); }; void TSelectTool::DrawFrame(BOOL Draw) { X1=State->Area.left-1; Y1=State->Area.top-1; X2=State->Area.right+1; Y2=State->Area.bottom+1; SelectObject(DC,Pen); SelectObject(DC,GetStockObject(NULL_BRUSH)); SetROP2(DC,R2_XORPEN); if (Selected || Draw) TRectTool::DrawObject(Draw); }; void TSelectTool::AdjustFrame(BOOL On) { State->Area.left=0; State->Area.top=0; State->Area.right=BitMapWidth; State->Area.bottom=BitMapHeight; if (On) { State->Area.left=((X1Area.top=((Y1Area.right=((X1Area.bottom=((Y1BitMap); Pen=CreatePen(PS_DOT,1,0); DrawFrame(FALSE); DeleteObject(Pen); DeleteDC(DC); ReleaseDC(Window,WinDC); InvalidateRect(Window,NULL,TRUE); Selected=FALSE; } }; void TPalette::Paint(HDC PaintDC,PAINTSTRUCT&) { int X,Y,S; HPEN Pen; HBRUSH Brush; RECT R; GetClientRect(HWindow,&R); S=R.bottom/17; for (Y=0;Y<16;Y++) for (X=0;X<3;X++) { Brush=(HBRUSH)SelectObject(PaintDC,CreateSolidBrush(Colors[X][Y])); Rectangle(PaintDC,X*S,Y*S,(X+1)*S+1,(Y+1)*S+1); DeleteObject(SelectObject(PaintDC,Brush)); } SelectObject(PaintDC,GetStockObject(NULL_BRUSH)); Rectangle(PaintDC,0,S*16,R.right,R.bottom); Pen=(HPEN)SelectObject(PaintDC,CreatePen(PS_SOLID,5,State->Background)); Brush=(HBRUSH)SelectObject(PaintDC,CreateSolidBrush(State->Foreground)); Rectangle(PaintDC,3,S*16+3,R.right-3,R.bottom-3); DeleteObject(SelectObject(PaintDC,Brush)); DeleteObject(SelectObject(PaintDC,Pen)); }; void TPalette::SelectColor(TMessage& Message,COLORREF& Color) { int X,Y,S; RECT R; HDC DC=GetDC(HWindow); GetClientRect(HWindow,&R); S=R.bottom/17; X=Message.LP.Lo/S; Y=Message.LP.Hi/S; if ((X<3) && (Y<16)) { Color=GetPixel(DC,X*S+1,Y*S+1); InvalidateRect(HWindow,NULL,FALSE); } ReleaseDC(HWindow,DC); }; TPointMask::TPointMask() { for (int Y=0;Y<3;Y++) for (int X=0;X<3;X++) Mask[Y][X]=FALSE; Mask[0][1]=Mask[2][1]=Mask[1][0]=Mask[1][2]=TRUE; }; void TPointMask::Invert(int X,int Y) { if (X>=-1 && X<=1 && Y>=-1 && Y<=1) Mask[Y+1][X+1]=!Mask[Y+1][X+1]; Mask[1][1]=FALSE; }; BOOL TPointMask::IsEmpty() { for (int Y=0;Y<3;Y++) for (int X=0;X<3;X++) if (Mask[Y][X]) return (FALSE); return (TRUE); }; void TMaskEditor::Paint(HDC PaintDC,PAINTSTRUCT&) { RECT R; HBRUSH Brush; GetClientRect(HWindow,&R); int W=R.right/3; int H=R.bottom/3; SelectObject(PaintDC,GetStockObject(WHITE_BRUSH)); SelectObject(PaintDC,GetStockObject(BLACK_PEN)); Rectangle(PaintDC,0,0,R.right,R.bottom); MoveTo(PaintDC,0,H); LineTo(PaintDC,R.right-1,H); MoveTo(PaintDC,0,R.bottom-H-1); LineTo(PaintDC,R.right-1,R.bottom-H-1); MoveTo(PaintDC,W,0); LineTo(PaintDC,W,R.bottom-1); MoveTo(PaintDC,R.right-W-1,0); LineTo(PaintDC,R.right-W-1,R.bottom-1); MoveTo(PaintDC,W,H); LineTo(PaintDC,R.right-W-1,R.bottom-H-1); MoveTo(PaintDC,R.right-W-1,H); LineTo(PaintDC,W,R.bottom-H-1); SelectObject(PaintDC,GetStockObject(WHITE_PEN)); Brush=(HBRUSH)SelectObject(PaintDC,CreateSolidBrush(RGB(160,0,0))); for (int Y=0;Y<3;Y++) for (int X=0;X<3;X++) if (State->PointMask->Get(X-1,Y-1)) Rectangle(PaintDC,X*W+2,Y*H+2,(X+1)*W-1,(Y+1)*H-1); DeleteObject(SelectObject(PaintDC,Brush)); }; void TMaskEditor::WMLButtonDown(TMessage& Message) { RECT R; GetClientRect(HWindow,&R); int X=Message.LP.Lo*3/R.right; int Y=Message.LP.Hi*3/R.bottom; if (X<3 && Y<3) { State->PointMask->Invert(X-1,Y-1); InvalidateRect(HWindow,NULL,FALSE); } }; TToolBar::TToolBar(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; Tools[0]=new TPenTool("Pen"); Tools[1]=new TLineTool("Line"); Tools[2]=new TFillTool("Fill"); Tools[3]=new TRectTool("Rect",FALSE); Tools[4]=new TRectTool("FillRect",TRUE); Tools[5]=new TEllipseTool("Ellipse",FALSE); Tools[6]=new TEllipseTool("FillEllipse",TRUE); Tools[7]=new TSelectTool("Select"); State->DrawTool=Tools[0]; }; TToolBar::~TToolBar() { State->DrawTool->Done(State); for (int i=0;iGetIcon()); if (Tools[N]==State->DrawTool) { R.top=1; R.left=N*IconSize; R.bottom=R.top+30; R.right=R.left+30; InvertRect(PaintDC,&R); } } }; void TToolBar::WMLButtonDown(TMessage& Message) { int N=Message.LP.Lo/IconSize; if (NDrawTool->Done(State); State->DrawTool=Tools[N]; InvalidateRect(HWindow,NULL,FALSE); } }; TLineBar::TLineBar(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_BORDER | WS_CHILD | WS_VISIBLE; State=AState; }; void TLineBar::Notch(HDC PaintDC,int X,int W,int Y,int DY) { for (int L=3;L>=0;L--) { MoveTo(PaintDC,X+W/2-L,Y); LineTo(PaintDC,X+W/2+L+1,Y); Y+=DY; } }; void TLineBar::Paint(HDC PaintDC,PAINTSTRUCT&) { int I,X,W; RECT R; X=4; for (I=0;IPenSize) { Notch(PaintDC,X,W,0,1); Notch(PaintDC,X,W,29,-1); } X+=W+4; } }; void TLineBar::WMLButtonDown(TMessage& Message) { int I,X,W; X=2; for(I=0;I=X) && (Message.LP.Lo<(X+W+4))) { State->PenSize=W; InvalidateRect(HWindow,NULL,TRUE); return; } X+=W+4; } }; TCanvas::TCanvas(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { HDC DC=GetDC(0); HDC MemDC=CreateCompatibleDC(DC); Attr.Style=WS_BORDER | WS_CHILD | WS_VISIBLE; State=AState; Drawing=FALSE; State->BitMap=CreateCompatibleBitmap(DC,BitMapWidth,BitMapHeight); SelectObject(MemDC,State->BitMap); PatBlt(MemDC,0,0,BitMapWidth,BitMapHeight,WHITENESS); DeleteDC(MemDC); ReleaseDC(0,DC); }; void TCanvas::Paint(HDC PaintDC,PAINTSTRUCT&) { RECT R; HDC MemDC=CreateCompatibleDC(PaintDC); SelectObject(MemDC,State->BitMap); GetClientRect(HWindow,&R); BitBlt(PaintDC,0,0,R.right,R.bottom,MemDC,0,0,SRCCOPY); DeleteDC(MemDC); }; void TCanvas::SaveDC() { RECT R; HDC DC=GetDC(HWindow); HDC MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); GetClientRect(HWindow,&R); BitBlt(MemDC,0,0,R.right,R.bottom,DC,0,0,SRCCOPY); DeleteDC(MemDC); ReleaseDC(HWindow,DC); }; void TCanvas::WMLButtonDown(TMessage& Message) { if (!Drawing) { if (State->DrawTool->MouseDown(HWindow, Message.LP.Lo,Message.LP.Hi,State->Foreground,State)) SaveDC(); State->DrawTool->MouseMove(Message.LP.Lo,Message.LP.Hi); Drawing=TRUE; } }; void TCanvas::WMRButtonDown(TMessage& Message) { if (!Drawing) { if (State->DrawTool->MouseDown(HWindow, Message.LP.Lo,Message.LP.Hi,State->Background,State)) SaveDC(); State->DrawTool->MouseMove(Message.LP.Lo,Message.LP.Hi); Drawing=TRUE; } }; void TCanvas::WMMouseMove(TMessage& Message) { if (Drawing) State->DrawTool->MouseMove(Message.LP.Lo,Message.LP.Hi); }; void TCanvas::WMLButtonUp(TMessage&) { if (Drawing) { State->DrawTool->MouseUp(); Drawing=FALSE; SaveDC(); } }; void TClearAll::Run(PTState State,PTCanvas Canvas) { HDC DC=GetDC(Canvas->GetCanvasWindow()); HDC MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); PatBlt(MemDC,State->Area.left,State->Area.top, State->Area.right-State->Area.left, State->Area.bottom-State->Area.top,WHITENESS); DeleteDC(MemDC); ReleaseDC(Canvas->GetCanvasWindow(),DC); InvalidateRect(Canvas->GetCanvasWindow(),&State->Area,TRUE); }; void TClipboardRead::Run(PTState State,PTCanvas Canvas) { if (OpenClipboard(Canvas->GetCanvasWindow())) { HANDLE Image=GetClipboardData(CF_BITMAP); if (Image) { HDC DC=GetDC(Canvas->GetCanvasWindow()); HDC MemDC=CreateCompatibleDC(DC); HDC MapDC=CreateCompatibleDC(MemDC); SelectObject(MemDC,State->BitMap); SelectObject(MapDC,Image); BitBlt(MemDC,State->Area.left,State->Area.top, State->Area.right-State->Area.left, State->Area.bottom-State->Area.top, MapDC,0,0,SRCCOPY); DeleteDC(MapDC); DeleteDC(MemDC); ReleaseDC(Canvas->GetCanvasWindow(),DC); InvalidateRect(Canvas->GetCanvasWindow(),&State->Area,TRUE); } CloseClipboard(); } }; TMenuBar::TMenuBar(PTWindowsObject AParent,PTState AState,PTCanvas ACanvas) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; Canvas=ACanvas; Items[0]=new TClearAll("ClearAll"); Items[1]=new TClipboardRead("ClipboardRead"); Items[2]=new TMorphOperation("MorphDilation",TRUE); Items[3]=new TMorphOperation("MorphErosion",FALSE); }; TMenuBar::~TMenuBar() { for (int i=0;iGetIcon()); }; void TMenuBar::WMLButtonDown(TMessage& Message) { HCURSOR Cursor; int N=Message.LP.Lo/IconSize; if (NRun(State,Canvas); SetCursor(Cursor); } }; TGraphMorphWin::TGraphMorphWin(PTWindowsObject AParent,LPSTR ATitle) : TWindow(AParent,ATitle) { State.DrawTool=NULL; State.BitMap=0; State.PenSize=LineWidth[3]; State.Background=RGB(255,255,255); State.Foreground=RGB(0,0,0); State.Area.left=State.Area.top=0; State.Area.right=BitMapWidth; State.Area.bottom=BitMapHeight; State.PointMask=new TPointMask(); Canvas=new TCanvas(this,&State); Palette=new TPalette(this,&State); ToolBar=new TToolBar(this,&State); LineBar=new TLineBar(this,&State); MenuBar=new TMenuBar(this,&State,Canvas); MaskEdit=new TMaskEditor(this,&State); }; TGraphMorphWin::~TGraphMorphWin() { delete MaskEdit; delete MenuBar; delete LineBar; delete ToolBar; delete Palette; delete Canvas; delete State.PointMask; }; void TGraphMorphWin::GetWindowClass(WNDCLASS& WndClass) { TWindow::GetWindowClass(WndClass); WndClass.hbrBackground=(HBRUSH)COLOR_APPWORKSPACE+1; WndClass.hIcon=LoadIcon(GetApplication()->hInstance,"ProgramIcon"); }; void TGraphMorphWin::WMSize(TMessage&) { int S; RECT R; GetClientRect(HWindow,&R); S=((R.bottom-8)/17)*3+1; MoveWindow(Palette->HWindow,4,4,S,R.bottom-8,TRUE); MoveWindow(ToolBar->HWindow,S+8,4,ToolCount*IconSize,IconSize,TRUE); MoveWindow(LineBar->HWindow,S+ToolCount*IconSize+14,4, LineBarWidth,IconSize,TRUE); MoveWindow(MenuBar->HWindow,S+ToolCount*IconSize+LineBarWidth+20,4, MenuCount*IconSize,IconSize,TRUE); MoveWindow(MaskEdit->HWindow,S+(ToolCount+MenuCount)*IconSize+ LineBarWidth+30,4,IconSize-1,IconSize-1,TRUE); MoveWindow(Canvas->HWindow,S+8,40,R.right-S-12,R.bottom-44,TRUE); }; int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmd,int nCmdShow) { TGraphMorphApp App("Graph Morpho",hInstance,hPrevInstance,lpCmd,nCmdShow); App.Run(); return (App.Status); }