Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Graphics.DrawRectangle draws rectangles one pixel too big [modified]

Graphics.DrawRectangle draws rectangles one pixel too big [modified]

Scheduled Pinned Locked Moved Clever Code
graphicshelpcsharp
4 Posts 4 Posters 11 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    The_Mega_ZZTer
    wrote on last edited by
    #1

    If you pass it a pen with a width of 1. This is very annoying and very easy to see. Override the OnPaint function of a control class and put:

    Dim x As New Rectangle(5, 5, 100, 100)
    e.Graphics.FillRectangle(Brushes.Red, x)

    Dim y As New Pen(Color.Black)
    y.Alignment = Drawing2D.PenAlignment.Inset
    y.DashStyle = Drawing2D.DashStyle.Dot
    e.Graphics.DrawRectangle(y, x)

    Inset alignment ensures (should ensure!) the drawn pen will draw inside our filled rectangle. This isn't required (the bug occurs regardless of what Alignment or DashStyle) but it helps us see that the Pen is properly drawing when we crank up the Pen's width (try it). The DashStyle allows us to see the underlying red rectangle boundary clearly. If you run this code snippet you'll see the problem... the DrawRectangle is one pixel too big in width and height! I think it might be a .NET bug... IIRC in GDI rectangles are purposefully drawn one pixel bigger than the rectangle you pass in but .NET seems to counteract this rule, at least in all cases but this. Fortunately, easy workaround:

    Private Sub DrawRectangleFix(ByVal g As Graphics, ByVal p As Pen, ByVal r As Rectangle)
    If p.Width = 1 Then
    r.Width -= 1
    r.Height -= 1
    End If
    g.DrawRectangle(p, r)
    End Sub

    modified on Saturday, July 25, 2009 3:58 PM

    N S D 3 Replies Last reply
    0
    • T The_Mega_ZZTer

      If you pass it a pen with a width of 1. This is very annoying and very easy to see. Override the OnPaint function of a control class and put:

      Dim x As New Rectangle(5, 5, 100, 100)
      e.Graphics.FillRectangle(Brushes.Red, x)

      Dim y As New Pen(Color.Black)
      y.Alignment = Drawing2D.PenAlignment.Inset
      y.DashStyle = Drawing2D.DashStyle.Dot
      e.Graphics.DrawRectangle(y, x)

      Inset alignment ensures (should ensure!) the drawn pen will draw inside our filled rectangle. This isn't required (the bug occurs regardless of what Alignment or DashStyle) but it helps us see that the Pen is properly drawing when we crank up the Pen's width (try it). The DashStyle allows us to see the underlying red rectangle boundary clearly. If you run this code snippet you'll see the problem... the DrawRectangle is one pixel too big in width and height! I think it might be a .NET bug... IIRC in GDI rectangles are purposefully drawn one pixel bigger than the rectangle you pass in but .NET seems to counteract this rule, at least in all cases but this. Fortunately, easy workaround:

      Private Sub DrawRectangleFix(ByVal g As Graphics, ByVal p As Pen, ByVal r As Rectangle)
      If p.Width = 1 Then
      r.Width -= 1
      r.Height -= 1
      End If
      g.DrawRectangle(p, r)
      End Sub

      modified on Saturday, July 25, 2009 3:58 PM

      N Offline
      N Offline
      NormDroid
      wrote on last edited by
      #2

      Not a bug, but by design. GDI+ and GDI maybe behave differently as they are 2 completely different designs, APIs, implementations.

      Software Kinetics (requires SL3 beta) - Moving software

      1 Reply Last reply
      0
      • T The_Mega_ZZTer

        If you pass it a pen with a width of 1. This is very annoying and very easy to see. Override the OnPaint function of a control class and put:

        Dim x As New Rectangle(5, 5, 100, 100)
        e.Graphics.FillRectangle(Brushes.Red, x)

        Dim y As New Pen(Color.Black)
        y.Alignment = Drawing2D.PenAlignment.Inset
        y.DashStyle = Drawing2D.DashStyle.Dot
        e.Graphics.DrawRectangle(y, x)

        Inset alignment ensures (should ensure!) the drawn pen will draw inside our filled rectangle. This isn't required (the bug occurs regardless of what Alignment or DashStyle) but it helps us see that the Pen is properly drawing when we crank up the Pen's width (try it). The DashStyle allows us to see the underlying red rectangle boundary clearly. If you run this code snippet you'll see the problem... the DrawRectangle is one pixel too big in width and height! I think it might be a .NET bug... IIRC in GDI rectangles are purposefully drawn one pixel bigger than the rectangle you pass in but .NET seems to counteract this rule, at least in all cases but this. Fortunately, easy workaround:

        Private Sub DrawRectangleFix(ByVal g As Graphics, ByVal p As Pen, ByVal r As Rectangle)
        If p.Width = 1 Then
        r.Width -= 1
        r.Height -= 1
        End If
        g.DrawRectangle(p, r)
        End Sub

        modified on Saturday, July 25, 2009 3:58 PM

        S Offline
        S Offline
        supercat9
        wrote on last edited by
        #3

        Back in the days of Inside Macintosh, Apple explained in simple but explicit terms that (1) screen coordinates actually represented the spaces between pixels, and (2) with the exception of lone lines, pixels, and polygons, all screen operations took place entirely within the specified region. So a rectangle from (0,0)-(8,8) drawn with a 2-pixel border would have a 4x4 empty area in the middle. Things are a bit mushier in the PC world, which seems to take its drawing model from Postscript (including the poorly conceived miter limit behavior(*)). There are times it is useful to define lines by their center, but it makes fitting things within a pixel region a little more difficult. (*) I sometimes wish I could go back in time and fix the definition of miter limit to the way it should be: an angle which is sufficiently acute that the miter limit would be exceeded should be drawn with a bevel whose distance from the centerpoint is equal to the stroke width times the miter limit. Thus, angles which were too acute would stick out as much as those which were at the miter limit, rather than sticking out less than even a rounded join. OTOH, I did discover a useful trick: to draw angle ABC nicely, compute a point D such that BD is very short and is perpendicular to the bisector of the angle, then draw ABDC. That will yield an appearance between that of bevel and miter joins, without ugliness at acute angles.

        1 Reply Last reply
        0
        • T The_Mega_ZZTer

          If you pass it a pen with a width of 1. This is very annoying and very easy to see. Override the OnPaint function of a control class and put:

          Dim x As New Rectangle(5, 5, 100, 100)
          e.Graphics.FillRectangle(Brushes.Red, x)

          Dim y As New Pen(Color.Black)
          y.Alignment = Drawing2D.PenAlignment.Inset
          y.DashStyle = Drawing2D.DashStyle.Dot
          e.Graphics.DrawRectangle(y, x)

          Inset alignment ensures (should ensure!) the drawn pen will draw inside our filled rectangle. This isn't required (the bug occurs regardless of what Alignment or DashStyle) but it helps us see that the Pen is properly drawing when we crank up the Pen's width (try it). The DashStyle allows us to see the underlying red rectangle boundary clearly. If you run this code snippet you'll see the problem... the DrawRectangle is one pixel too big in width and height! I think it might be a .NET bug... IIRC in GDI rectangles are purposefully drawn one pixel bigger than the rectangle you pass in but .NET seems to counteract this rule, at least in all cases but this. Fortunately, easy workaround:

          Private Sub DrawRectangleFix(ByVal g As Graphics, ByVal p As Pen, ByVal r As Rectangle)
          If p.Width = 1 Then
          r.Width -= 1
          r.Height -= 1
          End If
          g.DrawRectangle(p, r)
          End Sub

          modified on Saturday, July 25, 2009 3:58 PM

          D Offline
          D Offline
          Daniel L Kelly
          wrote on last edited by
          #4

          Actually, I think the line drawing function is working perfectly. The FillRectangle function actually fills a rectangle defined as (top,left,right-1,bottom-1). The MSDN documentation doesnt clearly state that for FillRectangle, but it does for FillRect (and FillRectangle probably just makes a direct call to FillRect ) Check out the docs to FillRect here:

          http://msdn.microsoft.com/en-us/library/aa932720.aspx

          The important part being:

          This function fills the rectangle's left and top borders, but excludes the right and bottom borders.

          If it makes you feel better, I've been programming for windows SDK since 1987, and I still forget that from time to time. It's annoying. I disagree with Microsoft's decision process on that one. Dan K

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups