⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coordinatespace.cpp

📁 Windows 图形编程 书籍
💻 CPP
字号:
//-----------------------------------------------------------------------------------//
//              Windows Graphics Programming: Win32 GDI and DirectDraw               //
//                             ISBN  0-13-086985-6                                   //
//                                                                                   //
//  Written            by  Yuan, Feng                             www.fengyuan.com   //
//  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
//  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
//                                                                                   //
//  FileName   : coordinatespace.cpp			                                     //
//  Description: Coordinate space demo program, Chapter 6                            //
//  Version    : 1.00.000, May 31, 2000                                              //
//-----------------------------------------------------------------------------------//

#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <assert.h>
#include <tchar.h>
#include <math.h>

#include "..\..\include\Affine.h"
#include "..\..\include\win.h"
#include "..\..\include\Canvas.h"
#include "..\..\include\FrameWnd.h"
#include "..\..\include\Status.h"

#include "resource.h"


class KFixedString
{
	int	  m_len;

public:

	TCHAR m_buffer[MAX_PATH];

	KFixedString(void)
	{
		m_buffer[0] = 0;
		m_len       = 0;
	}

	void Add(TCHAR ch)
	{
		m_buffer[m_len++] = ch;
		m_buffer[m_len  ] = 0;
	}

	void Add(PCTSTR pStr)
	{
		_tcscat(m_buffer + m_len, pStr);

		m_len += _tcslen(pStr);
	}

	void Add(int i)
	{
		wsprintf(m_buffer + m_len, "%d ", i);
		m_len = _tcslen(m_buffer);
	}

	void Add(int x, int y)
	{
		wsprintf(m_buffer + m_len, "(%d, %d)", x, y);

		m_len = _tcslen(m_buffer);
	}
};


void DumpMapMode(HDC hDC)
{
	POINT p;
	SIZE  s;
	KFixedString str;

	str.Add( GetMapMode(hDC) );

	str.Add( GetDeviceCaps(hDC, HORZSIZE) );
	str.Add( GetDeviceCaps(hDC, VERTSIZE) );
	
	str.Add( GetDeviceCaps(hDC, HORZRES) );
	str.Add( GetDeviceCaps(hDC, VERTRES) );
	str.Add( GetDeviceCaps(hDC, LOGPIXELSX) );
	str.Add( GetDeviceCaps(hDC, LOGPIXELSY) );

	GetWindowOrgEx(hDC, & p); str.Add(p.x, p.y);
	GetWindowExtEx(hDC, & s); str.Add(s.cx, s.cy);

	GetViewportOrgEx(hDC, & p); str.Add(p.x, p.y);
	GetViewportExtEx(hDC, & s); str.Add(s.cx, s.cy);

	MessageBox(NULL, str.m_buffer, "Map mode", MB_OK);
}


void SetEnglish(HDC hDC)
{
	SetWindowOrgEx(hDC, 5, 5, NULL);
	SetViewportOrgEx(hDC, 10, 10, NULL);

	SetMapMode(hDC, MM_TEXT);
	DumpMapMode(hDC);
	
	SetMapMode(hDC, MM_ISOTROPIC);
	DumpMapMode(hDC);
	
	SetWindowExtEx(hDC, 3, 5, NULL);

	DumpMapMode(hDC);

	SetViewportExtEx(hDC, 5, 3, NULL);

	DumpMapMode(hDC);

	SetMapMode(hDC, MM_ANISOTROPIC);
	BOOL rslt = SetViewportExtEx(hDC, 1, 1, NULL);
	
	DumpMapMode(hDC);

	rslt = SetViewportExtEx(hDC, 0, 0, NULL);
	
	DumpMapMode(hDC);

}


// Demonstrate world transformation using dotted-lines
void Transform_DottedLine(HDC hDC, int width, int height)
{
	KAffine af;

	SetMapMode(hDC, MM_ANISOTROPIC);
	SetWindowExtEx  (hDC, 1, 1,				   NULL); // default
	SetWindowOrgEx  (hDC, 0, 0,				   NULL);
	
	SetViewportExtEx(hDC, 1, -1,			   NULL); // y axis goes up
	SetViewportOrgEx(hDC, width/2, height*3/4, NULL); // 1/2, 3/4

	SetGraphicsMode(hDC, GM_ADVANCED);				  // using world coordinate space	

	for (int i=0; i<=72*5; i++)
	{
		SetWorldTransform(hDC, & af.m_xm);		// set transformation 

		for (int x=0; x<=200; x+=3)				// dotted line
			SetPixel(hDC, x+50, 0, 0);

		af.Translate(5, 5);						// translate

		af.Scale((FLOAT) 0.98, (FLOAT) 0.98);	// scale 0.98
		af.Rotate(5);							// rotate
	}
}


// size x size square in logical coordinate space
void Face(HDC hDC, COLORREF color, int size)
{
	for (int x=0; x<size; x++)
	for (int y=0; y<size; y++)
		SetPixel(hDC, x, y, color);
}


// use three transformations to map square in logical coordinate space to faces of a 3D cube
void Draw_Cube(HDC hDC, int width, int height, int degree)
{
	KAffine af;

	SetMapMode(hDC, MM_ANISOTROPIC);
	SetWindowExtEx  (hDC, 1, 1,				   NULL); // default
	SetWindowOrgEx  (hDC, 0, 0,				   NULL);
	
	SetViewportExtEx(hDC, 1, -1,			   NULL); // y axis goes up
	SetViewportOrgEx(hDC, width/2, height*3/4, NULL); // 1/2, 3/4

	SetGraphicsMode(hDC, GM_ADVANCED);

	const float pi   = (float) 3.1415926;
	const int   size = 150;
	const float dx   = (float) (size * cos(pi*degree/180));
	const float dy   = (float) (size * sin(pi*degree/180));
	
	af.MapTri(0, 0, (float)size, 0, 0, (float)size,   0, 0, dx, dy, 0, (float)size);
	SetWorldTransform(hDC, & af.m_xm);

	Face(hDC, RGB(0xFF, 0, 0), size);

	af.MapTri(0, 0, (float)size, 0, 0, (float)size,   0, 0, -dx, dy, 0, (float)size);
	SetWorldTransform(hDC, & af.m_xm);
	Face(hDC, RGB(0, 0xFF, 0), size);

	af.MapTri(0, 0, (float)size, 0, 0, (float)size,   0, (float)size, dx, size + dy, -dx, size + dy);
	SetWorldTransform(hDC, & af.m_xm);
	Face(hDC, RGB(0, 0, 0xFF), size);
}	



class KRotate
{
	int m_x0, m_y0, m_dx, m_dy;

public:

	int m_ds;
	
	KRotate(int x0, int y0, int x1, int y1)
	{
		m_x0 = x0;
		m_y0 = y0;
		m_dx = x1 - x0;
		m_dy = y1 - y0;
		m_ds = (int) sqrt( m_dx * m_dx + m_dy * m_dy);
	}

	int RotateX(int x, int y)
	{
		return x * m_dx / m_ds - y * m_dy / m_ds;
	}

	int RotateY(int x, int y)
	{
		return x * m_dy / m_ds + y * m_dx / m_ds;
	}
};


// Draw a line with an arrow	
void Arrow(HDC hDC, int x0, int y0, int x1, int y1, int width, int height)
{
	MoveToEx(hDC, x0, y0, NULL);
	LineTo(hDC, x1, y1);

	KRotate rotate(x0, y0, x1, y1);

	POINT arrow[4] = 
	{ 
		x1, y1, 
		
		rotate.RotateX(rotate.m_ds-width,  height) + x0, 
		rotate.RotateY(rotate.m_ds-width,  height) + y0,
		
		rotate.RotateX(rotate.m_ds-width, -height) + x0, 
		rotate.RotateY(rotate.m_ds-width, -height) + y0,
		
		x1, y1
	};

	HGDIOBJ hOld = SelectObject(hDC, GetStockObject(BLACK_BRUSH));
	Polygon(hDC, arrow, 4);
	SelectObject(hDC, hOld);
}


// Convert size in points to device coordinate
void PointToDevice(HDC hDC, SIZE & size)
{
	int dpix = GetDeviceCaps(hDC, LOGPIXELSX);
	int dpiy = GetDeviceCaps(hDC, LOGPIXELSY);

	size.cx = size.cx * dpix / 72;
    size.cy = size.cy * dpiy / 72;
}


// Convert size in device coordinate to logical coordinate
void DeviceToLogical(HDC hDC, SIZE & size)
{
	POINT p[2] = { 0, 0, size.cx, size.cy };

	DPtoLP(hDC, p, 2);

	size.cx = abs(p[1].x - p[0].x);
	size.cy = abs(p[1].y - p[0].y);
}


// Generic algorithm for axes display: width height in device coordinate
void ShowAxes(HDC hDC, int width, int height)
{
	POINT corner[2];

	// display axes for the area [10, 10, width-10, height-10]
	corner[0].x = 10;
	corner[0].y = 10;
	corner[1].x = width - 10;
	corner[1].y = height - 10;

	// covert to logical coordinate
	DPtoLP(hDC, corner, 2);

	// we need to display a 10x2 point arrow, convert to device coordinate, then to logical
	SIZE s = { 10, 2 };
	PointToDevice(hDC, s);
	DeviceToLogical(hDC, s);

	// X-axis
	Arrow(hDC, min(corner[0].x, corner[1].x), 0, 
		       max(corner[0].x, corner[1].x), 0, s.cx, s.cy);

	// Y-axis
	Arrow(hDC, 0, min(corner[0].y, corner[1].y), 
		       0, max(corner[0].y, corner[1].y), s.cx, s.cy);
}


// Decode world transformation and mapping mode
void DecodeTransform(HDC hDC)
{
	POINT windoworg;   GetWindowOrgEx(hDC, & windoworg);
	SIZE  windowext;   GetWindowExtEx(hDC, & windowext);

	POINT viewportorg; GetViewportOrgEx(hDC, & viewportorg);
	SIZE  viewportext; GetViewportExtEx(hDC, & viewportext);

	TCHAR formulax[128];
	TCHAR formulay[128];

	wsprintf(formulax, "x' = (x-%d) %d / %d + %d", windoworg.x, viewportext.cx, windowext.cx, viewportorg.x);
	wsprintf(formulay, "y' = (y-%d) %d / %d + %d", windoworg.y, viewportext.cy, windowext.cy, viewportorg.y);

	POINT p[2] = { 10, 10, 10, 35 };
	DPtoLP(hDC, p, 2);

	TextOut(hDC, p[0].x, p[0].y, formulax, _tcslen(formulax));
	TextOut(hDC, p[1].x, p[1].y, formulay, _tcslen(formulay));
}


// a scene (screen, page) with drawing and message handling
class KScene
{
public:
	virtual  ~KScene()
	{
	}

	virtual void          OnDraw(HDC hDC)                         = 0;
	virtual void          OnMouseMove(int x, int y, TCHAR mess[]) = 0;
	virtual const TCHAR * GetTitle(void)                          = 0;
};


// Mapping mode demostration
class KMapMode : public KScene
{
	HWND m_hWnd;
	int  m_width;
	int  m_height;
	int  m_mapmode;
	int  m_dpix;
	int  m_dpiy;

	// setup a mapping mode with origin in the center
	void Setup(HDC hDC)
	{
		RECT rect;

		GetClientRect(m_hWnd, & rect);
		m_width  = rect.right;
		m_height = rect.bottom;

		SetMapMode(hDC, m_mapmode);

		if ( m_dpix )
		{
			SetViewportExtEx(hDC, GetDeviceCaps(hDC, LOGPIXELSX), GetDeviceCaps(hDC, LOGPIXELSY), NULL);
			  SetWindowExtEx(hDC, m_dpix,                         m_dpiy,						  NULL);
		}

		SetWindowOrgEx(hDC,   0,         0,          NULL);
		SetViewportOrgEx(hDC, m_width/2, m_height/2, NULL);
	}

	// draw axes
	void OnDraw(HDC hDC)
	{
		Setup(hDC);
		
		ShowAxes(hDC, m_width, m_height);
		DecodeTransform(hDC);

		SelectObject(hDC, GetStockObject(NULL_BRUSH));
		Ellipse(hDC, -100, -100, 100, 100);
	}

	// display device coordinate and logical coordinate
	void OnMouseMove(int x, int y, TCHAR mess[])
	{
		POINT p = { x, y };

		wsprintf(mess, _T("Client: %d x %d"), p.x, p.y);

		HDC hDC = GetDC(m_hWnd);

		Setup(hDC);
		DPtoLP(hDC, & p, 1);
		wsprintf(mess + _tcslen(mess), ", Logical: %d x %d", p.x, p.y);

		ReleaseDC(m_hWnd, hDC);
	}

public:
	KMapMode(HWND hWnd, int mapmode, int dpix=0, int dpiy=0)
	{
		m_hWnd    = hWnd;
		m_mapmode = mapmode;
		m_dpix    = dpix;
		m_dpiy    = dpiy;
	}

	const TCHAR * GetTitle(void)
	{
		switch ( m_mapmode )
		{
			case MM_TEXT	   : return _T("MappingMode: MM_TEXT");
			case MM_LOENGLISH  : return _T("MappingMode: MM_LOENGLISH");
			case MM_HIENGLISH  : return _T("MappingMode: MM_HIENGLISH");
			case MM_LOMETRIC   : return _T("MappingMode: MM_LOMETRIC");
			case MM_HIMETRIC   : return _T("MappingMode: MM_HIMETRIC");
			case MM_TWIPS      : return _T("MappingMode: MM_TWIPS");
			case MM_ISOTROPIC  : return _T("MappingMode: MM_ISOTROPIC");
			case MM_ANISOTROPIC: return _T("MappingMode: MM_ANISOTROPIC");
		}

		return NULL;
	}

};



class KMyCanvas : public KCanvas
{
	int      mode;
	KScene * scene;

	void GetWndClassEx(WNDCLASSEX & wc)
	{
		memset(& wc, 0, sizeof(wc));

		wc.cbSize        = sizeof(WNDCLASSEX);
		wc.style         = CS_HREDRAW | CS_VREDRAW;  // repaint when resize
		wc.lpfnWndProc   = WindowProc;
		wc.cbClsExtra    = 0;
		wc.cbWndExtra    = 0;       
		wc.hInstance     = NULL;
		wc.hIcon         = NULL;
		wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
		wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
		wc.lpszMenuName  = NULL;
		wc.lpszClassName = NULL;
		wc.hIconSm       = NULL;
	}

public:
	KMyCanvas()
	{
		mode  = 0;
		scene = NULL;
	}

	virtual void OnDraw(HDC hDC, const RECT * rcPaint)
	{
		if ( scene )
			scene->OnDraw(hDC);
		else
		{
			RECT rect;

			GetClientRect(m_hWnd, & rect);
	
			switch (mode )
			{
				case IDM_VIEW_DOTLINE:
					Transform_DottedLine(hDC, rect.right, rect.bottom);
					break;

				case IDM_VIEW_CUBE30:
					Draw_Cube(hDC, rect.right, rect.bottom, 30);
					break;

				case IDM_VIEW_CUBE45:
					Draw_Cube(hDC, rect.right, rect.bottom, 45);
					break;
			}
		}
	}

	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
	{
		if ( mode != LOWORD(wParam) )
		{
			mode = LOWORD(wParam);
		
			if ( scene )
			{
				delete scene;
				scene = NULL;
			}

			switch ( mode )
			{
				case IDM_VIEW_MMTEXT     :   scene = new KMapMode(m_hWnd, MM_TEXT);        break;
				case IDM_VIEW_MMLOENGLISH:   scene = new KMapMode(m_hWnd, MM_LOENGLISH);   break;
				case IDM_VIEW_MMHIENGLISH:   scene = new KMapMode(m_hWnd, MM_HIENGLISH);   break;
				case IDM_VIEW_MMLOMETRIC:    scene = new KMapMode(m_hWnd, MM_LOMETRIC);    break;
				case IDM_VIEW_MMHIMETRIC:    scene = new KMapMode(m_hWnd, MM_HIMETRIC);    break;
				case IDM_VIEW_MMTWIPS:	     scene = new KMapMode(m_hWnd, MM_TWIPS);       break;
				case IDM_VIEW_MMISOTROPIC:   scene = new KMapMode(m_hWnd, MM_ISOTROPIC, 300, 300);   break;
				case IDM_VIEW_MMANISOTROPIC: scene = new KMapMode(m_hWnd, MM_ANISOTROPIC, 600, 300); break;
			}

			if ( scene )
				m_pStatus->SetText(0, scene->GetTitle());
			
			InvalidateRect(m_hWnd, NULL, TRUE);
		}
		
		return TRUE;
	}

	LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		if ( uMsg==WM_MOUSEMOVE )
		{
			TCHAR temp[64];

			temp[0] = 0;
			if ( scene )
				scene->OnMouseMove(LOWORD(lParam), HIWORD(lParam), temp);

			if ( temp[0] )
				m_pStatus->SetText(1, temp);

			return 0;
		}
		else
			return KCanvas::WndProc(hWnd, uMsg, wParam, lParam);
	}
};

class KMyFrame : public KFrame
{
	void GetWndClassEx(WNDCLASSEX & wc)
	{
		KFrame::GetWndClassEx(wc);
		wc.hIcon  = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_GRAPH));
	}

public:
	KMyFrame(HINSTANCE hInstance, const TBBUTTON * pButtons, int nCount,
			KToolbar * pToolbar, KCanvas * pCanvas, KStatusWindow * pStatus) :
		KFrame(hInstance, pButtons, nCount, pToolbar, pCanvas, pStatus)
	{
	}

};


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nShow)
{
	KMyCanvas		canvas;
	KStatusWindow   status;

	KMyFrame		frame(hInst, NULL, 0, NULL, & canvas, & status);
	
	frame.CreateEx(0, _T("CoorinateSpace"), _T("Coordinate Space"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
		NULL, LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAIN)), hInst);

    frame.ShowWindow(nShow);
    frame.UpdateWindow();
    frame.MessageLoop();

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -