November 01, 2003
Create Binary Behaviors for IE with .NET
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