FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
Dobbs M-Dev
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
November 01, 2003

Create Binary Behaviors for IE with .NET

(Page 4 of 4)
Create Binary Behaviors for IE with .NET

Listing 2 Implementing IHTMLPainter


01234567890123456789012345678901234567890123456789012345678901234567890123456789
namespace BinBehaviors
{
  [
  ComVisible(true),
  ClassInterface(ClassInterfaceType.AutoDispatch),
  Guid("70F8ECDA-3869-4586-958E-0914547E9984"),
  ProgId("BinBehaviors.line")
  ]
  public class Line : mshtml2.IElementBehavior, mshtml2.IHTMLPainter
  {

    //   .


    // IHTMLPainter method.
    void mshtml2.IHTMLPainter.Draw(tagRECT rcBounds, tagRECT rcUpdate, 
                  int lDrawFlags, System.IntPtr hdc, System.IntPtr 				pvDrawObject)
    {
      if (this.bitmap != null)
      {
        Graphics g = Graphics.FromHdc(hdc);
        g.CompositingMode = CompositingMode.SourceOver;

        // Apply any scaling, etc. to the output.
        mshtml._HTML_PAINT_DRAW_INFO info;
        this.paintsite.GetDrawInfo(
          (int) _HTML_PAINT_DRAW_INFO_FLAGS.HTMLPAINT_DRAWINFO_XFORM | 
(int) _HTML_PAINT_DRAW_INFO_FLAGS.HTMLPAINT_DRAWINFO_UPDATEREGION,
          out info);
        Matrix xform = new System.Drawing.Drawing2D.Matrix(
          info.xform.eM11, info.xform.eM12,
          info.xform.eM21, info.xform.eM22,
          info.xform.eDx - rcBounds.left, info.xform.eDy - rcBounds.top);
        g.Transform = xform;

        // Update clipping region.
        Region clip = new Region();
        if (info.hrgnUpdate != System.IntPtr.Zero)
        {
          Region updateclip = Region.FromHrgn(info.hrgnUpdate);
          clip.Intersect(updateclip);
          clip.Translate(rcBounds.left, rcBounds.top);
        }
        g.SetClip(clip, CombineMode.Replace);

        g.DrawImage(this.bitmap,
          rcUpdate.left, rcUpdate.top,
          new Rectangle(rcUpdate.left - rcBounds.left,  
          rcUpdate.top - rcBounds.top, rcUpdate.right - rcUpdate.left, 
          rcUpdate.bottom - rcUpdate.top),
          GraphicsUnit.Pixel);

        g.Dispose();
      }

    }

    // IHTMLPainter method.
    void mshtml2.IHTMLPainter.onresize(tagSIZE size)
    {
      DoLineDraw();
    }

    // IHTMLPainter method.
    void mshtml2.IHTMLPainter.GetPainterInfo(out _HTML_PAINTER_INFO pInfo)
    {
      pInfo.lFlags = (int) (_HTML_PAINTER.HTMLPAINTER_TRANSPARENT | 
        _HTML_PAINTER.HTMLPAINTER_NOPHYSICALCLIP
        | _HTML_PAINTER.HTMLPAINTER_SUPPORTS_XFORM); 
          // Possibly also: | _HTML_PAINTER.HTMLPAINTER_HITTEST.

      pInfo.lZOrder = (int) _HTML_PAINT_ZORDER.HTMLPAINT_ZORDER_REPLACE_ALL;
      pInfo.iidDrawObject = Guid.Empty; // No drawing object; using GDI+.
      pInfo.rcExpand.left = pInfo.rcExpand.right = 
      pInfo.rcExpand.top = pInfo.rcExpand.bottom = 0;
    }

    // IHTMLPainter method.
    // Not called unless pInfo.lFlags 
    // included _HTML_PAINTER.HTMLPAINTER_HITTEST.
    void mshtml2.IHTMLPainter.HitTestPoint(
      tagPOINT pt, out int pbHit, out int plPartID)
    {
      pbHit = 0;
      plPartID = 0;
    }

    /// <summary>
    /// Prepare bitmap image to be drawn.
    /// </summary>
    private void Compose()
    {
      // The element origin is at top left always. 
      // This bitmap drawing is relative to the origin.
      int width = Math.Abs(point2.X - point1.X);
      int height = Math.Abs(point2.Y - point1.Y);

      // The end points relative to the rectangle enclosing the line:
      int x1, y1, x2, y2;
      if (point2.X < point1.X)
      {
        x1 = point1.X - point2.X;
        x2 = 0;
      }
      else
      {
        x1 = 0;
        x2 = point2.X - point1.X;
      }
      if (point2.Y < point1.Y)
      {
        y1 = point1.Y - point2.Y;
        y2 = 0;
      }
      else
      {
        y1 = 0;
        y2 = point2.Y - point1.Y;
      }

      // Element/bitmap is offset left by penwidth to give room 
      // for line, so line x1, x2 start at +penwidth.
      x1 += this.xoffset;
      x2 += this.xoffset;

      y1 += this.yoffset;
      y2 += this.yoffset;

      // IMPORTANT: Free the bitmap by force or 
      // else large bitmaps remain allocated.
      // GC permits increasing amounts of 
      // memory to be left allocated between each
      // successive collection, until physical RAM is consumed.
      if (this.bitmap != null)
        this.bitmap.Dispose();

      if (width == 0 && height == 0) // Skip bitmap if zero; invalid size.
        return;

      // Add room to bitmap to correspond to element size and to avoid clipping.
      width += 2*this.xoffset;
      height += 2*this.yoffset;

      this.bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

      Graphics g = Graphics.FromImage(this.bitmap);

      g.CompositingMode = CompositingMode.SourceOver;
      
      g.DrawLine(new Pen(pencolor, penwidth), x1, y1, x2, y2);
      g.Dispose();
    }

    /// <summary>
    /// Construct the drawing on its bitmap and adjust the containing element.
    /// </summary>
    private void DoLineDraw()
    {
      Compose();
      UpdateElement();
      // Invalidate so entire element must be redrawn.
      this.paintsite.InvalidateRegion(IntPtr.Zero);
    }

    /// <summary>
    /// Update element position and dimensions to fit the drawing.
    /// </summary>
    private void UpdateElement()
    {
      // Position line element at min of point1 and point2 coords.
      this.element.style.left = Math.Min(point1.X, point2.X) - this.xoffset;
      this.element.style.top = Math.Min(point1.Y, point2.Y) - this.yoffset;

      this.element.style.width = 
        Math.Abs(point2.X - point1.X) + 2*this.xoffset;
      this.element.style.height = 
        Math.Abs(point2.Y - point1.Y) + 2*this.yoffset;
    }

  }

}

Previous Page | 1 | 2 | 3 | 4
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK