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

📄 viewport.cpp

📁 swain-0.5.2.zip的源代码,比较好用,希望大家喜欢.
💻 CPP
字号:
/*
This file is part of SWAIN (http://sourceforge.net/projects/swain).
Copyright (C) 2006  Daniel Lindstr鰉 and Daniel Nilsson

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA  02110-1301, USA.
*/
#include "StdAfx.h"
#include "ViewPort.h"

ViewPort::ViewPort(HWND hwnd){
	my_hwnd = hwnd;
	if(!(screen = GetDC(hwnd))){
		throw "could not get hDC";
	}
	createBackbuffer();

	canvas = NULL;
	zoom = 1;
	pan.x = 0; pan.y = 0;
	overzoom = 1.0;
	pen_standard = CreatePen(PS_SOLID, 1, RGB(0,0,0));
	SelectObject(backbuf, pen_standard);
}

ViewPort::~ViewPort(void){
	destroyBackbuffer();
	DeleteDC(screen);
}

void ViewPort::createBackbuffer(void) {
	RECT rc;
	if(!(backbuf = CreateCompatibleDC(screen))){
		throw "could not create backbuffer";
	}

	GetClientRect(my_hwnd, &rc);
	width = rc.right-rc.left;
	height = rc.bottom-rc.top;

	backbuf_bitmap = CreateCompatibleBitmap(screen, width, height);
	SelectObject(backbuf, backbuf_bitmap);
	SetStretchBltMode(backbuf, COLORONCOLOR);
}

void ViewPort::destroyBackbuffer(void) {
	DeleteObject(backbuf_bitmap);
	DeleteDC(backbuf);
}

void ViewPort::screenResized(void) {
	destroyBackbuffer();
	createBackbuffer();
	setZoomPan(zoom, &pan);
	redraw();
}

void ViewPort::flip(void){
	BitBlt(screen, 0, 0, width, height, backbuf, 0, 0, SRCCOPY);
}


void ViewPort::flip(FRECT *frect){
	int x = f2x(frect->left);
	int y = f2y(frect->top);
	int w = f2x(frect->right) - x + 1;
	int h = f2y(frect->bottom) - y + 1;
	BitBlt(screen, x, y, w, h, backbuf, x, y, SRCCOPY);
}

void ViewPort::clearRect(FRECT *rect) {
	RECT rc;
	rc.left = f2x(rect->left);
	rc.top = f2y(rect->top);
	rc.right = f2x(rect->right);
	rc.bottom = f2y(rect->bottom);
	FillRect(backbuf, &rc, (HBRUSH) GetStockObject(WHITE_BRUSH));
}

void ViewPort::drawPolyLine(FPOINT *points, int count){
	this->drawPolyLine(points, count, RGB(0, 0, 0));
}

void ViewPort::drawPolyLine(FPOINT *points, int count, COLORREF color){
	HPEN old, pen = CreatePen(PS_SOLID, 2, color);
	POINT *p = new POINT[count];
	for(int i=0; i<count; i++){
		p[i].x = f2x(points[i].x);
		p[i].y = f2y(points[i].y);
	}
	old = (HPEN)SelectObject(backbuf, pen);
	Polyline(backbuf, p, count);
	SelectObject(backbuf, old);
	delete(p);
	DeleteObject(pen);
}

void ViewPort::drawRectangle(float left, float top, float right, float bottom, COLORREF color, int style){
	HPEN old, pen = CreatePen(style, 1, color);
	old = (HPEN)SelectObject(backbuf, pen);
	RECT rc;
	rc.left = f2x(left);
	rc.top = f2y(top);
	rc.right = f2x(right);
	rc.bottom = f2y(bottom);
	DrawFocusRect(backbuf, &rc);
	SelectObject(backbuf, old);
	DeleteObject(pen);
}

void ViewPort::drawPolygon(FPOINT *points, int count){
	POINT *p = new POINT[count];
	for(int i=0; i<count; i++){
		p[i].x = f2x(points[i].x);
		p[i].y = f2y(points[i].y);
	}
	SelectObject(backbuf, pen_standard);
	Polygon(backbuf, p, count);
	delete(p);
}

void ViewPort::drawBitmap(Bitmap *bitmap, FRECT *dest, RECT *source){
	HDC hdc = bitmap->getHDC();
	StretchBlt(backbuf, f2x(dest->left), f2y(dest->top), f2x(dest->right)-f2x(dest->left),
				f2y(dest->bottom)-f2y(dest->top),
				bitmap->getHDC(), source->left, source->top, source->right-source->left, source->bottom-source->top, SRCCOPY);
}

void ViewPort::mouseDown(POINT *p){
	FPOINT fp;
	fp.x = x2f(p->x);
	fp.y = y2f(p->y);
	if(!canvas)
		throw "no canvas availible";
	this->canvas->mouseDown(&fp);
}

void ViewPort::mouseUp(POINT *p){
	FPOINT fp;
	fp.x = x2f(p->x);
	fp.y = y2f(p->y);
	if(!canvas)
		throw "no canvas availible";
	this->canvas->mouseUp(&fp);
}

void ViewPort::mouseDragged(POINT *p){
	FPOINT fp;
	fp.x = x2f(p->x);
	fp.y = y2f(p->y);
	if(!canvas)
		throw "no canvas availible";
	this->canvas->mouseDragged(&fp);
}

void ViewPort::redraw(void) {
	RECT rc = { 0, 0, width, height };
	redraw(&rc);
}

void ViewPort::redraw(RECT *rect){
	FRECT frect;
	frect.left = x2f(rect->left);
	frect.top = y2f(rect->top);
	frect.right = x2f(rect->right + 1);
	frect.bottom = y2f(rect->bottom + 1);
	HRGN rgn = CreateRectRgnIndirect(rect);
	SelectClipRgn(backbuf, rgn);
	canvas->redraw(&frect);
	SelectClipRgn(backbuf, NULL);
	DeleteObject(rgn);
}

void ViewPort::invalidate(FRECT *frect) {
	RECT rect;
	rect.left = f2x(frect->left);
	rect.top = f2y(frect->top);
	rect.right = f2x(frect->right);
	rect.bottom = f2y(frect->bottom);
	InvalidateRect(my_hwnd, &rect, FALSE);
}

void ViewPort::invalidate(void){
	RECT rect;
	rect.left = 0;
	rect.top = 0;
	rect.right = width;
	rect.bottom = height;
	InvalidateRect(my_hwnd, &rect, FALSE);
}

void ViewPort::alignRect(FRECT *frect) {
	frect->left = x2f(f2x(frect->left));
	frect->top = y2f(f2y(frect->top));
	frect->right = x2f(f2x(frect->right) + 1);
	frect->bottom = y2f(f2y(frect->bottom) + 1);
}

// Some GDI functions such as "polygon" draws outside the bounds by one pixel.
// This function adjusts a bounding rectangle to compensate for this.
void ViewPort::expandBoundsHack(FRECT *frect) {
	frect->right += x2f(1) - x2f(0);
	frect->bottom += y2f(1) - y2f(0);
	frect->left -= x2f(1) - x2f(0);
	frect->top -= y2f(1) - y2f(0);
}

float ViewPort::getMaxZoom(void) {
	FRECT fext;
	RECT ext;
	canvas->getExtents(&fext, &ext);
	float cw = fext.right - fext.left;	// width of canvas in float coords
	float ch = fext.bottom - fext.top;	// height of canvas in float coords
	int cpw = ext.right - ext.left;
	int cph = ext.bottom - ext.top;
	return overzoom * max (cpw / (ZOOMFACTOR * cw),
						   cph / (ZOOMFACTOR * ch));
}

float ViewPort::getMinZoom(void) {
	FRECT fext;
	canvas->getExtents(&fext, NULL);
	float cw = fext.right - fext.left;	// width of canvas in float coords
	float ch = fext.bottom - fext.top;	// height of canvas in float coords
	return max((float)width / (ZOOMFACTOR * cw),
			   (float)height / (ZOOMFACTOR * ch));
}

void ViewPort::setZoomPan(float z, FPOINT *p){
	// Adjust the zoom...
	if (z > getMaxZoom()) {
		z = getMaxZoom();
	}
	if (z < getMinZoom()) {
		z = getMinZoom();
	}
	float vpw = P2F(z, 0, width);		// width of viewport in float coords
	float vph = P2F(z, 0, height);		// height of viewport in float coords
	FRECT fext;
	canvas->getExtents(&fext, NULL);
	// Don't pan outside canvas...
	if(p->x < fext.left)
		p->x = fext.left;
	if(p->y < fext.top)
		p->y = fext.top;
	if((p->x + vpw) > fext.right)
		p->x = fext.right - vpw;
	if((p->y + vph) > fext.bottom)
		p->y = fext.bottom - vph;
	this->zoom = z;
	this->pan.x = p->x;
	this->pan.y = p->y;
	this->invalidate();
}

float ViewPort::getZoom(void){
	return zoom;
}

void ViewPort::getPan(FPOINT *p){
	*p = pan;
}

void ViewPort::setOverzoom(float f) {
	overzoom = f;
}

void ViewPort::drawDot(int x, int y){
	DWORD color = RGB(255, 255, 255);
	SetPixel(backbuf, x, y, color);
}


void ViewPort::setCanvas(Canvas *canvas){
	this->canvas = canvas;
}


void ViewPort::getBounds(FRECT *rect){
	rect->left = x2f(0);
	rect->right = x2f(width);
	rect->top = y2f(0);
	rect->bottom = y2f(height);
}


void ViewPort::setBounds(FRECT *rect){
	float zoom = (float)width/((rect->right - rect->left)*ZOOMFACTOR);
	zoom += (float)height/((rect->bottom - rect->top)*ZOOMFACTOR);
	zoom /= 2;
	zoom = max(getMinZoom(), min(zoom, getMaxZoom()));

	FPOINT offset;
	offset.x = (rect->left + rect->right) / 2 - P2F(zoom, 0, width/2);
	offset.y = (rect->top + rect->bottom) / 2 - P2F(zoom, 0, height/2);

	this->setZoomPan(zoom, &offset);

}

⌨️ 快捷键说明

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