[BACK]Return to ChildView.cpp CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / windows / engine2000

File: [local] / OpenXM_contrib2 / windows / engine2000 / ChildView.cpp (download)

Revision 1.6, Thu Aug 20 17:47:53 2015 UTC (8 years, 8 months ago) by ohara
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +74 -53 lines

Add interface to struct canvas.
Now C++ codes do not depend on gmpxx.h

// ChildView.cpp : CChildView クラスの動作の定義を行います。
//

#include "stdafx.h"
#include "ox_plot.h"
#include "ChildView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include <math.h>

extern "C" {
#include "if_canvas.h"

struct pa {
	int length;
	POINT *pos;
};

typedef struct RealVect {
	int len;
	int body[1];
} RealVect;

#define EXP10(a) pow(10.0,a)

extern struct canvas *current_can;
extern POINT start_point,end_point;

	HANDLE hResizeNotify,hResizeNotify_Ack;
	void destroy_canvas(struct canvas *);
	void pline(int *,struct canvas *, HDC);
	void draw_wideframe(struct canvas *, HDC);
	double adjust_scale(double,double);
}
/////////////////////////////////////////////////////////////////////////////
// CChildView

CChildView::CChildView()
{
	can = 0;
}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView,CWnd )
	//{{AFX_MSG_MAP(CChildView)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_COMMAND(ID_OPT_NOAXIS, OnOptNoaxis)
	ON_UPDATE_COMMAND_UI(ID_OPT_NOAXIS, OnUpdateOptNoaxis)
	ON_COMMAND(ID_OPT_PRECISE, OnOptPrecise)
	ON_UPDATE_COMMAND_UI(ID_OPT_PRECISE, OnUpdateOptPrecise)
	ON_COMMAND(ID_OPT_WIDE, OnOptWide)
	ON_UPDATE_COMMAND_UI(ID_OPT_WIDE, OnUpdateOptWide)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CChildView メッセージ ハンドラ

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
	if (!CWnd::PreCreateWindow(cs))
		return FALSE;

	cs.dwExStyle |= WS_EX_CLIENTEDGE;
	cs.style &= ~WS_BORDER;
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);
	return TRUE;
}

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // 描画用のデバイス コンテキスト
	
	// TODO: メッセージ ハンドラのコードをここに追加してください。
	
	// 描画のために CWnd::OnPaint を呼び出してはいけません。
	if ( canvas_is_interactive(can) ) {
		canvas_bitblt(can,dc.m_hDC,0,0);
	} else {
		if ( !canvas_wide(can) ) {
			canvas_bitblt(can,dc.m_hDC,0,0);
			pline(0,can,dc.m_hDC);
		} else
			draw_wideframe(can,dc.m_hDC);
	}
	BringWindowToTop();
}

void CChildView::OnPrint(CDC &dc) 
{
	DOCINFO docinfo;
//	NODE n;
	int width,height,ratio,x,y,step;
	int ch,cw,len,i;

	memset(&docinfo,0,sizeof(DOCINFO));
	docinfo.cbSize = sizeof(DOCINFO);
	docinfo.lpszDocName = "test";
	docinfo.lpszOutput = 0;

	// black pen
	CPen pen(PS_SOLID,0,(COLORREF)0);
	dc.SelectObject(&pen);

	// black brush
	CBrush brush((COLORREF)0);
	dc.SelectObject(&brush);

	// setup
	// isotropic mode 
	dc.SetMapMode(MM_ISOTROPIC);

	// the page size in device pixel
	width = dc.GetDeviceCaps(HORZRES)*9/10;
	height = dc.GetDeviceCaps(VERTRES)*9/10;

	dc.StartDoc(&docinfo);
	dc.StartPage();

	cw = canvas_width(can);
	ch = canvas_height(can);

	if ( canvas_is_interactive(can) ) {

		// We want to associate a rectangle of a fixed size to
		// one bitmap pixel
		// if cw/ch > width/height
		// then match the widths, else match the height
		if ( cw*height > ch*width )
			ratio = width/cw;
		else
			ratio = height/ch;

		// set the logical src bitmap size 
		dc.SetWindowExt(cw*ratio,ch*ratio);

		// set the viewport size and the origine in printer pixel
		dc.SetViewportOrg(width/18,height/18);
		dc.SetViewportExt(width,height);

		step = (ratio+4)/5;
		RealVect **p = (RealVect **)canvas_history(can, &len);
		for(i=0; i<len; i++) {
			RealVect *rv = p[i];
			if ( rv->len == 2 ) {
//				dc.SetPixel(rv->body[0],rv->body[1],0);
				x = rv->body[0]*ratio;
				y = rv->body[1]*ratio;
//				dc.FillRect(CRect(x,y,x+1,y+1),&brush);
//				dc.FillRect(CRect(x-1,y-1,x+1,y+1),&brush);
				dc.FillRect(CRect(x,y,x+step,y+step),&brush);
			} else if ( rv->len == 4 ) {
				dc.MoveTo(rv->body[0]*ratio,rv->body[1]*ratio);
				dc.LineTo(rv->body[2]*ratio,rv->body[3]*ratio);
			}
		}
	} else {
		// set the logical src bitmap size 
		dc.SetWindowExt(cw,ch);

		// set the viewport size and the origine in printer pixel
		dc.SetViewportOrg(width/18,height/18);
		dc.SetViewportExt(width,height);

		if ( canvas_is_plot(can) )
			dc.Polyline(canvas_pa(can)->pos,canvas_pa(can)->length);
		else
			::StretchBlt(dc.m_hDC,0,0,cw,ch,canvas_pix(can),0,0,cw,ch,SRCCOPY);
		PrintAxis(dc);
	}
	dc.EndPage();
	dc.EndDoc();
}

void CChildView::PrintAxis(CDC &dc)
{
#define D 5
#define DEFAULTWIDTH 400
#define DEFAULTHEIGHT 400

	double w,w1,e,n;
	int x0,y0,x,y,xadj,yadj;
	char buf[BUFSIZ];
	double cxmin,cxmax,cymin,cymax;
	int cw,ch;

	cxmin = canvas_xmin(can);
	cxmax = canvas_xmax(can);
	cymin = canvas_ymin(can);
	cymax = canvas_ymax(can);
	cw = canvas_width(can);
	ch = canvas_height(can);

	/* XXX : should be cleaned up */
	if ( canvas_noaxis(can) || (canvas_is_plot(can) && !canvas_pa(can)) 
		 || canvas_is_interactive(can) )
		return;

	xadj = yadj = 0;
	if ( (cxmin < 0) && (cxmax > 0) ) {
		x0 = (int)((cw)*(-cxmin/(cxmax-cxmin)));
		dc.MoveTo(x0,0); dc.LineTo(x0,ch);
	} else if ( cxmin >= 0 )
		x0 = 0;
	else
		x0 = cw-D;
	if ( (cymin < 0) && (cymax > 0) ) {
		y0 = (int)((ch)*(cymax/(cymax-cymin)));
		dc.MoveTo(0,y0); dc.LineTo(cw,y0);
	} else if ( cymin >= 0 )
		y0 = ch;
	else
		y0 = D;
	w = cxmax-cxmin; 
	w1 = w * DEFAULTWIDTH/cw;
	e = adjust_scale(EXP10(floor(log10(w1))),w1);
	for ( n = ceil(cxmin/e); n*e<= cxmax; n++ ) {
		x = (int)(cw*(n*e-cxmin)/w);
		dc.MoveTo(x,y0); dc.LineTo(x,y0-D);
		sprintf(buf,"%g",n*e);
		dc.TextOut(x+2,y0+2,buf,strlen(buf));
	}
	w = cymax-cymin;
	w1 = w * DEFAULTHEIGHT/ch;
	e = adjust_scale(EXP10(floor(log10(w1))),w1);
	for ( n = ceil(cymin/e); n*e<= cymax; n++ ) {
		y = (int)(ch*(1-(n*e-cymin)/w));
		dc.MoveTo(x0,y); dc.LineTo(x0+D,y);
		sprintf(buf,"%g",n*e);
		if ( cxmax <= 0 ) {
			xadj = dc.GetOutputTextExtent(buf,strlen(buf)).cx;
		}
		dc.TextOut(x0+2-xadj,y+2,buf,strlen(buf));
	}
}

static CPoint start,prev;

void CChildView::OnLButtonDown(UINT nFlags, CPoint point) {
	start = point;
	prev = point;
	SetCapture();
	CWnd::OnLButtonDown(nFlags,point);	
}

void CChildView::OnMouseMove(UINT nFlags, CPoint point) {
	if ( nFlags & MK_LBUTTON ) {
		CDC *pDC = GetDC();
		CRect prevrect(start,prev),rect(start,point);
		CSize size(1,1);
	
		pDC->DrawDragRect(&rect,size,&prevrect,size);
		ReleaseDC(pDC);
		prev = point;
	}
	CWnd::OnMouseMove(nFlags,point);	
}

void CChildView::OnLButtonUp(UINT nFlags, CPoint point) {
	CDC *pDC = GetDC();
	CRect rect(start,point);
	CSize size(1,1);

	pDC->DrawDragRect(&rect,size,0,size);
	ReleaseDC(pDC);
	ReleaseCapture();
	start_point = start; end_point = point;
	current_can = can;
	SetEvent(hResizeNotify);
	WaitForSingleObject(hResizeNotify_Ack,(DWORD)-1);

	CWnd::OnLButtonUp(nFlags,point);	
}

void CChildView::DestroyCanvas() {
	destroy_canvas(can);
}

void CChildView::OnOptNoaxis() 
{
	// TODO: この位置にコマンド ハンドラ用のコードを追加してください
	canvas_toggle_noaxis(can);
	RedrawWindow();
}

void CChildView::OnUpdateOptNoaxis(CCmdUI* pCmdUI) 
{
	// TODO: この位置に command update UI ハンドラ用のコードを追加してください
	pCmdUI->SetCheck(canvas_noaxis(can));	
}

void CChildView::OnOptPrecise() 
{
	// TODO: この位置にコマンド ハンドラ用のコードを追加してください
	canvas_toggle_precise(can);
}

void CChildView::OnUpdateOptPrecise(CCmdUI* pCmdUI) 
{
	// TODO: この位置に command update UI ハンドラ用のコードを追加してください
	pCmdUI->SetCheck(canvas_precise(can));	
}

void CChildView::OnOptWide() 
{
	// TODO: この位置にコマンド ハンドラ用のコードを追加してください
	canvas_toggle_wide(can);
	RedrawWindow();
}

void CChildView::OnUpdateOptWide(CCmdUI* pCmdUI) 
{
	// TODO: この位置に command update UI ハンドラ用のコードを追加してください
	pCmdUI->SetCheck(canvas_wide(can));	
}