已有程序能完成画线,矩形,弧等功能(原程序运行正常),因还要求绕不对称逻辑坐标(x:-300,500;y:-200,400)原点旋转和对称等,所以我在OnDraw()里加了一个这样的坐标系,因为ONLBUTTON()所得坐标是相对于物理坐标系,所以在其中做了一个坐标变换但是结果却运行不正常,现把画LINE的关键代码列下,请帮我看看,如果谁有时间,我想把整个工程发给你看看,谢谢!另:1。我对二维坐标系的变换还是无法弄清,有没有人可以解释一下。 2。想寻找VC伙伴,有问题了可以交流一下,.
// draw1vw.cpp : implementation of the CDraw1View class
//#include "stdafx.h"
#include "draw1.h"#include "draw1doc.h"
#include "draw1vw.h"class CDraw1View : public CView
{
protected: // create from serialization only
CDraw1View();
DECLARE_DYNCREATE(CDraw1View)
enum Shapes { Line, Arc, Chord, Circle, Ellipse,  Pie, Rect, Square };
enum Actions { None, Outline, Draw };

// Attributes
public:
CDraw1Doc* GetDocument();
COLORREF rgbColor;
Shapes nShape;
Actions nAction;
int nLineStyle;
int nFillStyle;
POINT ptNew;
RECT rFrame;
// CDraw1ViewCDraw1View::CDraw1View()
{
// TODO: add construction code here
nAction = None;
nShape = Line;
rgbColor = 0x00000000;
nLineStyle = PS_SOLID;
nFillStyle = -1;
}CDraw1View::~CDraw1View()
{
}/////////////////////////////////////////////////////////////////////////////
// CDraw1View drawingvoid CDraw1View::OnDraw(CDC* pDC)
{
CDraw1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
    
CRect   cRect;
CPen *pOldPen,cNewPen(PS_SOLID, 5, 0x02ff0000);
int OldDC;         OldDC=pDC->SaveDC();
pDC->SetMapMode(MM_ISOTROPIC);   加的坐标系
pDC->SetWindowExt(800,600); AfxGetMainWnd()->GetClientRect(cRect);
         pDC->SetViewportExt(cRect.Width(),-cRect.Height());

pDC->SetViewportOrg(cRect.Width()*3/8,cRect.Height()*4/6);
      
pOldPen=pDC->SelectObject(&cNewPen);
pDC->MoveTo( -300, 0);                 画坐标系
pDC->TextOut(-300, 0, "-300");
pDC->LineTo(500,0);
pDC->TextOut(500, 10, "500");         pDC->MoveTo( 0, 400);
pDC->TextOut(0, 400, "400");
pDC->LineTo(0,-200);
pDC->TextOut(0, -150, "-200");
pDC->TextOut(0, 0, "0"); switch( nAction )
{
case Outline:    //not OnLButtomUp,ButtomDown and move
if( nShape == Line )
DrawDotLine( pDC );

rFrame.right = ptNew.x;
rFrame.bottom = ptNew.y;
pDC->DPtoLP(&rFrame);    rFrame取的是相对于DP if( nShape == Line )
DrawDotLine( pDC ); // erase new line
else
DrawOutline( pDC ); // erase new frame
break; case Draw:
if( nShape == Line )
DrawDotLine(pDC ); // erase   prior line); // erase prior frame

nAction = None;
break;
}
// TODO: add draw code for native data here
}
void CDraw1View::DrawDotLine( CDC *pDC )
{
CPen cPen;
pDC->MoveTo( rFrame.left, rFrame.top ); pDC->SetROP2( R2_XORPEN );
cPen.CreatePen( PS_DOT, 1, RGB(0,0,0) );
pDC->SelectObject( &cPen );
pDC->LineTo( rFrame.right, rFrame.bottom );
   
}/////////////////////////////////////////////////////////////////////////////
// CDraw1View printing// CDraw1View message handlersvoid CDraw1View::OnMouseMove(UINT nFlags, CPoint point) 
{
if( nAction == Outline )
{
ptNew=point;                      关于物理坐标的点
Invalidate( FALSE );
}
}void CDraw1View::OnLButtonDown(UINT nFlags, CPoint point) 
{
nAction = Outline;

rFrame.left = point.x;   //DP
rFrame.right = point.x;
rFrame.top = point.y;
rFrame.bottom = point.y;
ptNew = point;
Invalidate( FALSE );
// CView::OnLButtonDown(nFlags, point);
}void CDraw1View::OnLButtonUp(UINT nFlags, CPoint point) 
{
nAction = Draw;
Invalidate( FALSE );
// CView::OnLButtonUp(nFlags, point);
}

解决方案 »

  1.   

    可以看你的程序吗?
    [email protected]
      

  2.   

    你上面的代码有错误每次OnDraw的时候就调用一次
    pDC->DPtoLP(&rFrame);    //rFrame取的是相对于DP
    将rFrame转换为逻辑坐标, 第一次转换rFrame中记录的确实是设备坐标, 但是以后rFrame中记录的就是逻辑坐标了, 所以rFrame.left, rFrame.top的位置将不对;可以改正如下:
    1. 去掉OnDraw中的pDC->DPtoLP(&rFrame)一行;
    2. 可以如下来写
    void DrawDotLine(CDC *pDC)
    {
             RECT rc = rFrame;    // 拷贝rFrame
    pDC->DPtoLP(&rc);    //转换为逻辑坐标不会改变rFrame中的值

    CPen cPen;
    pDC->MoveTo( rc.left, rc.top ); pDC->SetROP2( R2_XORPEN );
    cPen.CreatePen( PS_DOT, 1, RGB(0,0,0) );
    pDC->SelectObject( &cPen );
    pDC->LineTo( rc.right, rc.bottom );  }3. 另外如果你的OnDraw代码是完整的话, 记得将恢复DC的画笔
    pDC->SelectObject(pOldPen); 要不98下运行可能情况不大妙.
      

  3.   

    snooper1001:按你说的改了,还是有问题;在ONDRAW 里设置的逻辑坐标系对DrawDotLine()有效吗?
      

  4.   

    逻辑坐标系是对DC设置的, 在DrawDotLine()中使用的是同一DC, 当然有效.代码在我这边运行是好的!其实你代码的错误就是: DPtoLP(&rcFrame)将rcFrame的坐标转化为了逻辑坐标, 然后在下一次绘图的时候, rcFrame的left和top没有恢复为设备坐标, 然后又调用DPtoLP(&rcFrame)试图将rcFrame转换为逻辑坐标, 那么rcFrame.left, rcFrame.top肯定是错的, 你在使用你的程序绘图的时候有没有注意到终点始终是对的仅仅是起点不对?注意不要忘记删除:
                       case Outline:    //not OnLButtomUp,ButtomDown and move
    if( nShape == Line )
    DrawDotLine( pDC );

    rFrame.right = ptNew.x;
    rFrame.bottom = ptNew.y;
    **********这一行 pDC->DPtoLP(&rFrame);    rFrame取的是相对于DP
      

  5.   

    To:snooper1001
       十分谢谢你的帮助,后来我发现在OutLine时是对的,但Draw 时不对,把DrawShape( CDC *pDC )按你说的方式改了,就对了,再次感谢你,我如何给你加分?