正文

C#下用GDI绘制城墙线波浪线等线型2007-10-31 11:37:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/tujun/30619.html

分享到:

调用的API:

[DllImport("gdi32.dll", EntryPoint="LineDDA")]
  public static extern int LineDDA (
   int   nXStart,         //   线条起点的X坐标  
       int   nYStart,         //   线条起点的Y坐标  
   int   nXEnd,          //   线条终点的X坐标  
   int   nYEnd,          //   线条终点的Y坐标  
   LineDDAProcHandle  lpLineDDAProc,
   IntPtr lParam
   );
  public delegate void    LineDDAProcHandle(  
   int   X, //   被求值点的X坐标  
   int   Y, //   被求值点的Y坐标  
   ref DrawStruct   lpData );
  private void    LineDDAProc(  
   int   X, //   被求值点的X坐标  
   int   Y, //   被求值点的Y坐标  
   ref DrawStruct   mDrawStruct )//   应用程序定义数据的指针               
  {     
   int modvalue = mDrawStruct.nWidth;
   if((X % modvalue) == 0)
   {
    for(int i=X-modvalue;i<X;i++)
    {
     int YY =  (int)(modvalue * Math.Sin(1 * 3.1415926 * i / modvalue - modvalue));
     LineTo(mDrawStruct.hdc,i,YY/2 + Y);
     //SetPixel(mDrawStruct.hdc,i,YY,mDrawStruct.mColor); 
    }
   }
   //SetPixel(mDrawStruct.hdc,X,YY,mDrawStruct.mColor);  
  }

public enum dwPenStyle
  {
   PS_GEOMETRIC =0x10000,
   PS_COSMETIC = 0

  }
  //publc
  public enum Hatch
  {
   HS_BDIAGONAL,
   HS_CROSS,
   HS_DIAGCROSS,
   HS_FDIAGONAL,
   HS_HORIZONTAL,
   HS_VERTICAL
  }
  public enum Style
  {
   BS_DIBPATTERN,
   BS_DIBPATTERN8X8,
   BS_DIBPATTERNPT,
   BS_HATCHED,
   BS_HOLLOW,
   BS_NULL,
   BS_PATTERN,
   BS_PATTERN8X8,
   BS_SOLID
  }
  [StructLayout(LayoutKind.Sequential)]
   public struct LOGBRUSH
  {
   public Style lbStyle;
   public int crColor;
   public Hatch lbHatch;
  }
 
  public enum PenStyles
  {
   PS_SOLID,
   PS_DASH,
   PS_DOT,
   PS_DASHDOT,
   PS_DASHDOTDOT
  }
  [DllImport("gdi32.dll", EntryPoint="MoveToEx")]
  public static extern int MoveToEx (
   IntPtr hdc,
   int x,
   int y,
   IntPtr lpPoint
   );
  [DllImport("gdi32.dll")]
  private static extern IntPtr CreatePen(PenStyles enPenStyle, int nWidth, int crColor);
  [DllImport("gdi32.dll")]
  private static extern IntPtr ExtCreatePen(
   int dwPenStyle,      // pen style
   int dwWidth,         // pen width
   ref LOGBRUSH lplb,  // brush attributes
   int dwStyleCount,    // length of custom style array
   IntPtr lpStyle   // custom style array
   );
  [DllImport("gdi32.dll")]
  private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject);
  [DllImport("gdi32.dll")]
  protected static extern bool DeleteObject(IntPtr hObject);
  public struct PenStylesStu
  {
   public PenStyles style;
   public override string ToString()
   {
    return style.ToString ();
   }
  }
  //  [DllImport("gdi32.dll", EntryPoint="MoveToEx")]
  //  public static extern int MoveToEx (
  //   IntPtr hdc,
  //   int x,
  //   int y,
  //   ref POINTAPI lpPoint
  //   );
  [StructLayout(LayoutKind.Sequential)]
   public struct POINTAPI
  {
   public int X;
   public int Y;
  }
  [DllImport("gdi32.dll", EntryPoint="LineTo")]
  public static extern int LineTo (
   IntPtr hdc,
   int x,
   int y
   );
  [DllImport("gdi32.dll", EntryPoint="EndPath")]
  public static extern int EndPath (
   IntPtr hdc
   );
  [DllImport("gdi32.dll", EntryPoint="StrokePath")]
  public static extern int StrokePath (
   IntPtr hdc
   );
  [DllImport("gdi32.dll", EntryPoint="BeginPath")]
  public static extern int BeginPath (
   IntPtr hdc
   );
  public struct StyleStu
  {
   public Style style;
   public override string ToString()
   {
    return style.ToString ();
   }
  }
  public const int PS_GEOMETRIC = 0x10000;
  public const int PS_COSMETIC = 0x0;
  public const int PS_ENDCAP_ROUND = 0x0;
  public const int PS_ENDCAP_SQUARE = 0x100;
  public const int PS_ENDCAP_FLAT = 0x200;
  public const int PS_JOIN_BEVEL = 0x1000;
  public const int PS_JOIN_MITER = 0x2000;
  public const int PS_JOIN_ROUND = 0x0;
  public const int PS_SOLID = 0;
  public const int BS_SOLID = 0;
  public const int PS_USERSTYLE = 7;

 

绘制铁路线的代码:

//绘制铁路线
   Graphics g = Graphics.FromHwnd(this.panel1.Handle);//在panle1上绘制
   g.Clear(Color.White);
   IntPtr hdc = g.GetHdc();
   

   ///先绘制直线,比指定宽度大2
   Color c = this.label3.BackColor;    //获取颜色
   int nWidth = (int)this.numericUpDown1.Value;//获取线宽
   LOGBRUSH   lb;
   lb.crColor= GetGDIRGB(c);
   lb.lbHatch = Hatch.HS_BDIAGONAL;
   lb.lbStyle = Style.BS_DIBPATTERN;

   
   IntPtr      hPen, hOldPen;
   nWidth = nWidth + 2;
   hPen = ExtCreatePen(PS_ENDCAP_FLAT| (int)PenStyles.PS_SOLID |
    PS_GEOMETRIC/* |
     iEnd [i] |
     iJoin [i]*/,
    nWidth , ref lb,0,IntPtr.Zero);
   hOldPen = SelectObject(hdc,hPen);
   MoveToEx(hdc,30,50,IntPtr.Zero);
   LineTo(hdc,this.panel1.Width - 60,200);
   SelectObject(hdc,hOldPen);

   DeleteObject(hPen);

   //再绘制白色虚线,用指定的宽度
   c = Color.White;
   lb.crColor= GetGDIRGB(c);
   lb.lbHatch = Hatch.HS_BDIAGONAL;
   lb.lbStyle = Style.BS_DIBPATTERN;


   int[] kkk = new int[]{nWidth * 2,nWidth * 2};
   int newWidth = nWidth - (nWidth/2)+1;
   if(newWidth > nWidth - 2)
    newWidth = nWidth - 2;
   hPen = ExtCreatePen(PS_ENDCAP_FLAT| PS_USERSTYLE | PS_GEOMETRIC/* |
     iEnd [i] |
     iJoin [i]*/,
    newWidth , ref lb,  kkk.Length, Marshal.UnsafeAddrOfPinnedArrayElement(kkk,0));
   hOldPen = SelectObject(hdc,hPen);
   MoveToEx(hdc,30,50,IntPtr.Zero);
   LineTo(hdc,this.panel1.Width - 60,200);
   SelectObject(hdc,hOldPen);

   DeleteObject(hPen);


   g.ReleaseHdc(hdc);
   
   g.Dispose();

//绘制国界线

private void button8_Click(object sender, System.EventArgs e)
  {
   Graphics g = Graphics.FromHwnd(this.panel1.Handle);
   g.Clear(Color.White);
   IntPtr hdc = g.GetHdc();
   
   DrawStruct str = new DrawStruct();
   int nWidth = (int)this.numericUpDown1.Value;
   str.hdc =  hdc;
   Color c = this.label3.BackColor;
   str.mColor = GetGDIRGB(c);
   str.nWidth = nWidth;
   
   

   LOGBRUSH   lb;
   lb.crColor= GetGDIRGB(c);
   lb.lbHatch = Hatch.HS_BDIAGONAL;
   lb.lbStyle = Style.BS_DIBPATTERN;

   
   IntPtr      hPen, hOldPen;
   
   hPen = ExtCreatePen(PS_ENDCAP_FLAT| (int)PenStyles.PS_SOLID |
    PS_GEOMETRIC/* |
     iEnd [i] |
     iJoin [i]*/,
    1 , ref lb,0,IntPtr.Zero);
   hOldPen = SelectObject(hdc,hPen);
   
   //MoveToEx(hdc,10,50,IntPtr.Zero);
   str.oldX = this.panel1.Width -30;
   str.oldY = 50;
   str.nWidth = nWidth;
   IntPtr  ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(str));
   Marshal.StructureToPtr(str,ptr,true);
   MoveToEx(hdc,str.oldX,str.oldY,IntPtr.Zero);
   LineDDA(str.oldX,str.oldY,50,250, new LineDDAProcHandle(LineDDAProc_Guojie),ptr);

   SelectObject(hdc,hOldPen);
   DeleteObject(hPen);
   g.ReleaseHdc(hdc);
   Marshal.DestroyStructure(ptr,typeof(DrawStruct));
   g.Dispose();
  }

/// <summary>
  /// 绘制国界线回调函数
  /// </summary>
  /// <param name="X"></param>
  /// <param name="Y"></param>
  /// <param name="mDrawStruct"></param>
  private void    LineDDAProc_Guojie(  
   int   X, //   被求值点的X坐标  
   int   Y, //   被求值点的Y坐标  
   ref DrawStruct   mDrawStruct )//   应用程序定义数据的指针               
  {     
   int modvalue = mDrawStruct.nWidth;
   double hg = mDrawStruct.nWidth;//方波高度
   //计算2点间距离,粗略计算
   double distance = 0.0;
   double angle = Math.Atan((double)(Y - mDrawStruct.oldY) / (double)(X - mDrawStruct.oldX));//线夹角
   distance = (double)(X - mDrawStruct.oldX)*(X - mDrawStruct.oldX) + (double)(Y - mDrawStruct.oldY)*(Y - mDrawStruct.oldY);
   distance = Math.Abs( Math.Sqrt(distance));

   if(distance > hg *4)
   {
    Point P0 = Point.Empty;
    Point P1 = Point.Empty;
    Point P2 = Point.Empty;
    Point P3 = Point.Empty;
    Point P4 = Point.Empty;

    P0.X = mDrawStruct.oldX;
    P0.Y = mDrawStruct.oldY;

    

    P2.X = (X +  mDrawStruct.oldX) /2;
    P2.Y = (Y +  mDrawStruct.oldY) /2;

    P1.X = (P2.X +  mDrawStruct.oldX) /2;
    P1.Y = (P2.Y +  mDrawStruct.oldY) /2;

    


    P4.X = X;
    P4.Y = Y;

    P3.X =(P4.X +  P2.X)/2;
    P3.Y =(P4.Y +  P2.Y)/2;
    //在P1点绘制一个点
    SetPixel(mDrawStruct.hdc,P1.X,P1.Y,mDrawStruct.mColor); 

    //在P2处绘制一条垂直的长度为hg的线段
    Point P21 = Point.Empty;
    Point P22  =Point.Empty;

    //P2和P21的X差 = P1和P2的Y差 , P2和P21的Y差 = P2和P1的X差
    P21.X = P2.X - (P1.Y - P2.Y) /2;
    P21.Y = P2.Y - (P2.X - P1.X) /2;

    //P2和P22的X差
    P22.X =  P2.X + (P1.Y - P2.Y) /2;
    P22.Y =  P2.Y + (P2.X - P1.X) /2;

    Point P41 = Point.Empty;
    Point P42 = Point.Empty;

    P41.X = P4.X - (P3.Y - P4.Y) /2;
    P41.Y = P4.Y - (P4.X - P3.X) /2;

    //P2和P22的X差
    P42.X =  P4.X + (P3.Y - P4.Y) /2;
    P42.Y =  P4.Y + (P4.X - P3.X) /2;
    
    MoveToEx(mDrawStruct.hdc,P21.X,P21.Y,IntPtr.Zero);
    LineTo(mDrawStruct.hdc,P22.X,P22.Y);
    MoveToEx(mDrawStruct.hdc,P2.X,P2.Y,IntPtr.Zero);
    LineTo(mDrawStruct.hdc,P4.X,P4.Y);
    MoveToEx(mDrawStruct.hdc,P41.X,P41.Y,IntPtr.Zero);
    LineTo(mDrawStruct.hdc,P42.X,P42.Y);


    mDrawStruct.oldX = P4.X;
    mDrawStruct.oldY = P4.Y;
   }
  }

 

///绘制城墙线

/// <summary>
  /// 绘制城墙线
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void button7_Click(object sender, System.EventArgs e)
  {
   Graphics g = Graphics.FromHwnd(this.panel1.Handle);
   g.Clear(Color.White);
   IntPtr hdc = g.GetHdc();
   
   DrawStruct str = new DrawStruct();
   int nWidth = (int)this.numericUpDown1.Value;
   str.hdc =  hdc;
   Color c = this.label3.BackColor;
   str.mColor = GetGDIRGB(c);
   str.nWidth = nWidth;
   
   

   LOGBRUSH   lb;
   lb.crColor= GetGDIRGB(c);
   lb.lbHatch = Hatch.HS_BDIAGONAL;
   lb.lbStyle = Style.BS_DIBPATTERN;

   
   IntPtr      hPen, hOldPen;
   
   hPen = ExtCreatePen(PS_ENDCAP_FLAT| (int)PenStyles.PS_SOLID |
    PS_GEOMETRIC/* |
     iEnd [i] |
     iJoin [i]*/,
    1 , ref lb,0,IntPtr.Zero);
   hOldPen = SelectObject(hdc,hPen);
   
   //MoveToEx(hdc,10,50,IntPtr.Zero);
   str.oldX = this.panel1.Width -30;
   str.oldY = 50;
   str.nWidth = nWidth;
   IntPtr  ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(str));
   Marshal.StructureToPtr(str,ptr,true);
   MoveToEx(hdc,str.oldX,str.oldY,IntPtr.Zero);
   LineDDA(str.oldX,str.oldY,50,50, new LineDDAProcHandle(LineDDAProc_CityWalline),ptr);

   SelectObject(hdc,hOldPen);
   DeleteObject(hPen);
   g.ReleaseHdc(hdc);
   Marshal.DestroyStructure(ptr,typeof(DrawStruct));
   g.Dispose();

  }

 

/// <summary>
  /// 绘制城墙线(方波线)回调函数
  /// </summary>
  /// <param name="X"></param>
  /// <param name="Y"></param>
  /// <param name="mDrawStruct"></param>
  private void    LineDDAProc_CityWalline(  
   int   X, //   被求值点的X坐标  
   int   Y, //   被求值点的Y坐标  
   ref DrawStruct   mDrawStruct )//   应用程序定义数据的指针               
  {     

   {
    double hg = mDrawStruct.nWidth;//方波高度
    //计算2点间距离,粗略计算
    double distance = 0.0;
    double angle = Math.Atan((double)(Y - mDrawStruct.oldY) / (double)(X - mDrawStruct.oldX));//线夹角
    distance = (double)(X - mDrawStruct.oldX)*(X - mDrawStruct.oldX) + (double)(Y - mDrawStruct.oldY)*(Y - mDrawStruct.oldY);
    distance = Math.Abs( Math.Sqrt(distance));


   #region 第二种算法
    if(distance >=hg* 2 )//距离大于2象素
    {
     Point P1 = Point.Empty;
     Point P2 = Point.Empty;
     Point P3 = Point.Empty;
     Point P4 = Point.Empty;
     Point P5 = Point.Empty;
     //p1
     P1.X = mDrawStruct.oldX;
     P1.Y = mDrawStruct.oldY;
     //p5
     P5.X = X;
     P5.Y = Y;
     //p2 P2是起始2个端点的重心
     P2.X =(X + mDrawStruct.oldX) /2;
     P2.Y =(Y + mDrawStruct.oldY) /2;


     //p3 P3和P2的X差 == P2和P5的Y差,P3和P2的Y差 = P2和P5的X差
     P3.X = P2.Y - P5.Y + P2.X;
     P3.Y = P5.X - P2.X + P2.Y;
     //P4 P4和P3的X差 = P5和P2的X差 P4和P3的Y差 = P2和P5的Y差
     P4.X = P5.X - P2.X + P3.X;
     P4.Y = P5.Y - P2.Y + P3.Y;

     //绘制方波线


    // MoveToEx(mDrawStruct.hdc,P1.X,P1.Y,IntPtr.Zero);
     LineTo(mDrawStruct.hdc,P2.X,P2.Y);
     LineTo(mDrawStruct.hdc,P3.X,P3.Y);
     LineTo(mDrawStruct.hdc,P4.X,P4.Y);
     LineTo(mDrawStruct.hdc,P5.X,P5.Y);

     mDrawStruct.oldX = P5.X;
     mDrawStruct.oldY = P5.Y;
    }
    #endregion
    

    //
   }
   
  }

////绘波浪线

/// <summary>
  /// 绘波浪线
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void button6_Click(object sender, System.EventArgs e)
  {
   Graphics g = Graphics.FromHwnd(this.panel1.Handle);
   g.Clear(Color.White);
   IntPtr hdc = g.GetHdc();
   
   DrawStruct str = new DrawStruct();
   str.hdc =  hdc;
   int nWidth = (int)this.numericUpDown1.Value;
   str.nWidth = nWidth;
   Color c = this.label3.BackColor;
   str.mColor = GetGDIRGB(c);

   IntPtr  ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(str));
   Marshal.StructureToPtr(str,ptr,true);
   
//
//   LOGBRUSH   lb;
//   lb.crColor= GetGDIRGB(c);
//   lb.lbHatch = Hatch.HS_BDIAGONAL;
//   lb.lbStyle = Style.BS_DIBPATTERN;
//
//   
//   IntPtr      hPen, hOldPen;
   
//   hPen = ExtCreatePen(PS_ENDCAP_FLAT| (int)PenStyles.PS_SOLID |
//    PS_GEOMETRIC/* |
//     iEnd [i] |
//     iJoin [i]*/,
//    nWidth , ref lb,0,IntPtr.Zero);
//   hOldPen = SelectObject(hdc,hPen);

   MoveToEx(hdc,10,50,IntPtr.Zero);
   LineDDA(10,50,this.panel1.Width - 20,100,new LineDDAProcHandle(LineDDAProc),ptr);

//   SelectObject(hdc,hOldPen);
//   DeleteObject(hPen);
   g.ReleaseHdc(hdc);
   Marshal.DestroyStructure(ptr,typeof(DrawStruct));
   g.Dispose();

  }

阅读(8803) | 评论(2)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册