linecurve.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 482 行
CPP
482 行
//-----------------------------------------------------------------------------------//
// 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 : linecurve.cpp //
// Description: Line/curve demo program, Chapter 8 //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define _WIN32_WINNT 0x0500
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include "..\..\include\win.h"
#include "..\..\include\Canvas.h"
#include "..\..\include\Status.h"
#include "..\..\include\FrameWnd.h"
#include "..\..\include\Affine.h"
#include "..\..\include\Pen.h"
#include "..\..\include\curve.h"
#include "..\..\include\BezierCurve.h"
#include "Resource.h"
class KMyCanvas : public KCanvas
{
virtual void OnDraw(HDC hDC, const RECT * rcPaint);
virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
int m_test;
int m_lastx;
int m_lasty;
void SetTest(int test);
void DrawCrossHair(HDC hDC, bool on);
void TestDrawMode(HDC hDC);
void TestWidthCap(HDC hDC);
void TestDCPen(HDC hDC);
void TestPenStyle(HDC hDC);
void TestCosmetic(HDC hDC);
void TestGeometricWidth(HDC hDC);
void TestGeometricStyle(HDC hDC);
void TestLine1(HDC hDC);
void TestLine2(HDC hDC);
void TestBezier(HDC hDC);
void BezierDemo(HDC hDC);
void DragBezier(HDC hDC, int x, bool on);
void TestBezierPen(HDC hDC);
void TestArc(HDC hDC);
void ArcToBezier(HDC hDC);
void AngleArcToBezier(HDC hDC);
void TestPath(HDC hDC);
void TestPathStyleCurve(HDC hDC);
void TestMapPath(HDC hDC);
POINT m_bezier[4];
public:
KMyCanvas()
{
m_test = -1;
m_lastx = -1;
m_lasty = -1;
m_bezier[0].x = 30; m_bezier[0].y = 330;
m_bezier[1].x = 130; m_bezier[1].y = 30;
m_bezier[2].x = 430; m_bezier[2].y = 130;
m_bezier[3].x = 630; m_bezier[3].y = 430;
}
};
void KMyCanvas::SetTest(int test)
{
m_test = test;
HMENU hMain = GetMenu(GetParent(m_hWnd));
TCHAR Temp[MAX_PATH];
_tcscpy(Temp, _T("LineCurve - "));
GetMenuString(hMain, m_test, Temp + _tcslen(Temp),
sizeof(Temp)/sizeof(TCHAR) - _tcslen(Temp), MF_BYCOMMAND);
SetWindowText(GetParent(m_hWnd), Temp);
}
BOOL KMyCanvas::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch ( LOWORD(wParam) )
{
case IDM_TEST_DRAWMODE:
case IDM_TEST_WIDTHCAP:
case IDM_TEST_DCPEN:
case IDM_TEST_PENSTYLE:
case IDM_TEST_COSMETIC:
case IDM_TEST_GEOMETRIC_WIDTH:
case IDM_TEST_GEOMETRIC_STYLE:
case IDM_TEST_LINE1:
case IDM_TEST_LINE2:
case IDM_TEST_BEZIER:
case IDM_TEST_BEZIERDEMO:
case IDM_TEST_BEZIERPEN:
case IDM_TEST_ARC:
case IDM_TEST_ARCBEZIER:
case IDM_TEST_ANGLEARCBEZIER:
case IDM_TEST_PATH:
case IDM_TEST_PATHSTYLECURVE:
case IDM_TEST_MAPPATH:
SetTest( LOWORD(wParam) );
InvalidateRect(m_hWnd, NULL, TRUE);
return TRUE;
case IDM_FILE_EXIT:
DestroyWindow(GetParent(m_hWnd));
return TRUE;
}
return FALSE; // not processed
}
void KMyCanvas::DrawCrossHair(HDC hDC, bool on)
{
if ( (m_lastx<0) || (m_lasty<0) )
return;
if ( m_test == IDM_TEST_BEZIER )
DragBezier(hDC, m_lastx, on);
else
{
RECT rect;
GetClientRect(m_hWnd, & rect);
SetROP2(hDC, R2_XORPEN);
KPen pen(PS_DOT, 0, RGB(0, 0, 0xFF), hDC);
Line(hDC, rect.left, m_lasty, rect.right, m_lasty);
Line(hDC, m_lastx, rect.top, m_lastx, rect.bottom);
}
}
LRESULT KMyCanvas::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lr;
switch( uMsg )
{
case WM_CREATE:
m_hWnd = hWnd;
SetTest(IDM_TEST_DRAWMODE);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
// SetLastError(0);
// HRGN hrgnClip = CreateRectRgn(0,0,0,0);
// GetUpdateRgn(m_hWnd,hrgnClip,FALSE);
// HDC hdc = GetDCEx(m_hWnd,NULL,DCX_VALIDATE|DCX_INTERSECTUPDATE);
HDC hDC = BeginPaint(m_hWnd, &ps);
// DrawCrossHair(hDC);
OnDraw(hDC, &ps.rcPaint);
DrawCrossHair(hDC, true);
EndPaint(m_hWnd, &ps);
}
return 0;
case WM_MOUSEMOVE:
{
HDC hDC = GetDC(hWnd);
DrawCrossHair(hDC, false);
m_lastx = LOWORD(lParam); m_lasty = HIWORD(lParam);
DrawCrossHair(hDC, true);
ReleaseDC(hWnd, hDC);
TCHAR temp[32];
wsprintf(temp, _T("(%d, %d)"), m_lastx, m_lasty);
m_pStatus->SetText(0, temp);
}
return 0;
default:
lr = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return lr;
}
const TCHAR * R2_Names[] =
{
"R2_BLACK",
"R2_NOTMERGEPEN",
"R2_MASKNOTPEN",
"R2_NOTCOPYPEN",
"R2_MASKPENNOT",
"R2_NOT",
"R2_XORPEN",
"R2_NOTMASKPEN",
"R2_MASKPEN",
"R2_NOTXORPEN",
"R2_NOP",
"R2_MERGENOTPEN",
"R2_COPYPEN",
"R2_MERGEPENNOT",
"R2_MERGEPEN",
"R2_WHITE"
};
void KMyCanvas::TestDrawMode(HDC hDC)
{
for (int c=0; c<20; c++)
{
RECT rect = { c*20+40, 30, c*20+58, 400 };
HBRUSH hBrush = CreateSolidBrush(PALETTEINDEX(c));
FillRect(hDC, & rect, hBrush);
DeleteObject(hBrush);
}
KPen pen(PS_SOLID, 0, RGB(0xFF, 0, 0), hDC);
for (int r=R2_BLACK; r<=R2_WHITE; r++)
{
SetROP2(hDC, r);
for (int i=0; i<18; i++)
{
Label(hDC, 440, r*22+20, R2_Names[r-R2_BLACK]);
Line(hDC, 30, r*22+20+i, 430, r*22+20+i);
}
}
}
void ZoomPixel(HDC hDC, int x0, int y0, int x1, int y1)
{
COLORREF c = GetPixel(hDC, x0, y0);
HBRUSH hBrush = CreateSolidBrush(c);
SelectObject(hDC, hBrush);
Rectangle(hDC, x1, y1, x1+11, y1+11);
SelectObject(hDC, GetStockObject(WHITE_BRUSH));
DeleteObject(hBrush);
}
void KMyCanvas::TestWidthCap(HDC hDC)
{
char temp[6];
KPen green(PS_SOLID, 0, RGB(0, 0xFF, 0));
for (int i=0; i<12; i++)
{
KPen pen (PS_DOT, i, RGB(0, 0, 0xFF));
int x0 = 40 + (i/2)*110;
int x1 = x0 + 64;
int y0 = 30 + (i & 1) * 200;
// thick line
Line(hDC, x0, y0, x1, y0, pen.m_hPen);
// Center line
Line(hDC, x0, y0, x1, y0, green.m_hPen);
wsprintf(temp, "w=%d", i);
Label(hDC, 40+x0-5*12, 90 + y0 -5*12-17, temp);
// copy zoomed line
for (int y=-5; y<6; y++)
for (int x=-5; x<3; x++)
ZoomPixel(hDC, x0+x, y0+y, 40+x0+x*12, 90 + y0 + y*12);
Line(hDC, x0, y0, x1, y0, pen.m_hPen);
}
}
void KMyCanvas::TestDCPen(HDC hDC)
{
Label(hDC, 10, 0, _T("Use DC_PEN to simulate gradient fill"));
SelectObject(hDC, GetStockObject(DC_PEN));
for (int i=0; i<128; i++)
{
SetDCPenColor(hDC, RGB(i, 255-i, 128+i));
Line(hDC, 40, i+40, 150, i+40);
}
SelectObject(hDC, GetStockObject(BLACK_PEN));
// Test DeleteObject on stock object
BOOL rslt = DeleteObject(GetStockObject(DC_PEN));
}
const LPCTSTR mess_PenStyle [] =
{
_T("PS_SOLID"),
_T("PS_DASH"),
_T("PS_DOT"),
_T("PS_DASHDOT"),
_T("PS_DASHDOTDOT"),
_T("PS_NULL"),
_T("PS_INSIDEFRAME"),
_T("PS_USERSTYLE"),
_T("PS_ALTERNATE")
};
void KMyCanvas::TestPenStyle(HDC hDC)
{
// Pen style
for (int i = PS_SOLID; i<=PS_INSIDEFRAME; i++)
{
Label(hDC, 10, i*20+10, mess_PenStyle[i]);
SetBkColor(hDC, RGB(0, 0xFF, 0));
SetBkMode(hDC, OPAQUE);
{
KPen Pen(i, 1, RGB(0x00, 0x00, 0xFF), hDC);
Line(hDC, 150, i*20 + 17, 180, i*20 + 17);
}
SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
// copy to zoomed display
for (int x=150; x<180; x++)
ZoomPixel(hDC, x, i*20 + 17,
200 + (x-150)*12, i*20 + 12);
}
}
void KMyCanvas::TestCosmetic(HDC hDC)
{
const LOGBRUSH logbrush = { BS_SOLID, RGB(0, 0, 0xFF), 0 };
// SetMapMode(hDC, MM_ANISOTROPIC);
// SetViewportExtEx(hDC, 2, 2, NULL);
for (int i = PS_SOLID; i<=PS_ALTERNATE; i++)
{
HPEN hPen;
const DWORD cycle[4] = { 4, 3, 2, 1 };
if ( i==PS_USERSTYLE )
hPen = ExtCreatePen(PS_COSMETIC | i, 1, & logbrush, 4, cycle);
else
hPen = ExtCreatePen(PS_COSMETIC | i, 1, & logbrush, 0, NULL);
Label(hDC, 10, i*20+10, mess_PenStyle[i]);
if ( hPen )
{
SelectObject(hDC, hPen);
SetBkColor(hDC, RGB(0, 0xFF, 0));
SetBkMode(hDC, OPAQUE);
// SetROP2(hDC, R2_XORPEN);
// draw style line
Line(hDC, 150, i*20 + 17, 180, i*20 + 17);
SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
SelectObject(hDC, GetStockObject(BLACK_PEN));
DeleteObject(hPen);
// copy to zoomed display
for (int x=150; x<180; x++)
ZoomPixel(hDC, x, i*20 + 17,
200 + (x-150)*12, i*20 + 12);
}
}
}
void KMyCanvas::TestGeometricWidth(HDC hDC)
{
const LOGBRUSH logbrush = { BS_SOLID, RGB(0, 0xFF, 0), 0 };
int save = SaveDC(hDC);
HPEN hGreen = CreatePen(PS_SOLID, 0, RGB(0, 0xFF, 0));
SetBkColor(hDC, RGB(0, 0xFF, 0));
SetBkMode(hDC, OPAQUE);
// Geometric line width under transformation
HPEN hPen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT, 61, & logbrush, 0, NULL);
KAffine affine;
POINT p[6] = { 0, 0, 200, 0, -00, -30, 200, -30, 200, 30, 0, 30 };
affine.Rotate(30, 0, 0);
affine.Translate(100, -200);
SelectObject(hDC, hPen);
SetMapMode(hDC, MM_ANISOTROPIC);
SetViewportExtEx(hDC, 1, -1, NULL);
SetGraphicsMode(hDC, GM_ADVANCED);
SetWorldTransform(hDC, & affine.m_xm);
LPtoDP(hDC, p, 6);
Line(hDC, 0, 0, 200, 0);
SelectObject(hDC, GetStockObject(BLACK_PEN));
DeleteObject(hPen);
ModifyWorldTransform(hDC, NULL, MWT_IDENTITY);
SetGraphicsMode(hDC, GM_COMPATIBLE);
SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
SetTextAlign(hDC, TA_LEFT);
SetViewportExtEx(hDC, 1, 1, NULL);
Line(hDC, p[0].x, p[0].y, 20, 200);
Label(hDC, 20, 200, "(x0,y0)");
Line(hDC, p[1].x, p[1].y, 300, 80);
Label(hDC, 300, 80, "(x1,y1)");
Line(hDC, p[5].x, p[5].y, 20, 120);
Label(hDC, 20, 120, "(x0-dx,y0+dy)");
Line(hDC, p[4].x, p[4].y, 260, 40);
Label(hDC, 260, 40, "(x1-dx,y1+dy)");
Line(hDC, p[3].x, p[3].y, 300, 160);
Label(hDC, 300, 160, "(x1+dx,y1-dy)");
Line(hDC, p[2].x, p[2].y, 130, 250);
Label(hDC, 130, 250, "(x0+dx,y0-dy)");
Label(hDC, 20, 20, "dx = pen_width * sin(
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?