Facebook Twitter LinkedIn E-mail
magnify
Home Archive for category "Silverlight"

Vaadin Web应用开发教程(26):UI组件-LoginForm组件

LoginForm组件专门用来接受用户输入用户名和密码,并可以自动记住用户输入的用户名和密码。其基本用法如下:

// A wrapper with a caption for the login form
Panel loginPanel = new Panel("Login");
loginPanel.setWidth("250px");
        
LoginForm login = new LoginForm();
loginPanel.addComponent(login);

LoginForm组件内部实现使用了iframe 和静态HTML支持其功能。 如果你想定制LoginForm的外观可以重载getLoginHtml()方法。
下面介绍如何定制LoginForm组件。

class MyLoginForm extends LoginForm {
    String usernameCaption;
    String passwordCaption;
    String submitCaption;
    
    public MyLoginForm(String usernameCaption,
            String passwordCaption, String submitCaption) {
        this.usernameCaption = usernameCaption;
        this.passwordCaption = passwordCaption;
        this.submitCaption  = submitCaption;
    }

然后重载getLoginHTML()方法:
HTML body 部分包含Form定义,包含在一个iframe 中。form 和button 必需定义对应的javascripts 响应用户点击”submit’

@Override
protected byte[] getLoginHTML() {
    // Application URI needed for submitting form
    String appUri = getApplication().getURL().toString()
            + getWindow().getName() + "/";

    String x, h, b; // XML header, HTML head and body
	
	 x = "<!DOCTYPE html PUBLIC \"-//W3C//DTD "
      + "XHTML 1.0 Transitional//EN\" "
      + "\"http://www.w3.org/TR/xhtml1/"
      + "DTD/xhtml1-transitional.dtd\">\n";
	  
	   h = "<head><script type='text/javascript'>"
      + "var setTarget = function() {"
      + "  var uri = '" + appUri + "loginHandler';"
      + "  var f = document.getElementById('loginf');"
      + "  document.forms[0].action = uri;"
      + "  document.forms[0].username.focus();"
      + "};"
      + ""
      + "var styles = window.parent.document.styleSheets;"
      + "for(var j = 0; j < styles.length; j++) {\n"
      + "  if(styles[j].href) {"
      + "    var stylesheet = document.createElement('link');\n"
      + "    stylesheet.setAttribute('rel', 'stylesheet');\n"
      + "    stylesheet.setAttribute('type', 'text/css');\n"
      + "    stylesheet.setAttribute('href', styles[j].href);\n"
      + "    document.getElementsByTagName('head')[0]"
      + "                .appendChild(stylesheet);\n"
      + "  }"
      + "}\n"
      + "function submitOnEnter(e) {"
      + "  var keycode = e.keyCode || e.which;"
      + "  if (keycode == 13) {document.forms[0].submit();}"
      + "}\n"
      + "</script>"
      + "</head>";
	  
	   b = "<body onload='setTarget();'"
      + "  style='margin:0;padding:0; background:transparent;'"
      + "  class='"
      + ApplicationConnection.GENERATED_BODY_CLASSNAME + "'>"
      + "<div class='v-app v-app-loginpage'"
      + "     style='background:transparent;'>"
      + "<iframe name='logintarget' style='width:0;height:0;"
      + "border:0;margin:0;padding:0;'></iframe>"
      + "<form id='loginf' target='logintarget'"
      + "      onkeypress='submitOnEnter(event)'"
      + "      method='post'>"
      + "<table>"
      + "<tr><td>" + usernameCaption + "</td>"
      + "<td><input class='v-textfield' style='display:block;'"
      + "           type='text' name='username'></td></tr>"
      + "<tr><td>" + passwordCaption + "</td>"
      + "    <td><input class='v-textfield'"
      + "          style='display:block;' type='password'"
      + "          name='password'></td></tr>"
      + "</table>"
      + "<div>"
      + "<div onclick='document.forms[0].submit();'"
      + "     tabindex='0' class='v-button' role='button'>"
      + "<span class='v-button-wrap'>"
      + "<span class='v-button-caption'>"
      + submitCaption + "</span>"
      + "</span></div></div></form></div></body>";
	  
	    return (x + "<html>" + h + b + "</html>").getBytes();
}
  

 

Silverlight 引路蜂二维图形库下载

Silverlight库及例子下载 http://www.guidebee.info/download/silverlight/SilverlightGraphics2DDemo.zip ,库同样可以用于WPF,Windows Phone 7

Install Microsoft Silverlight

  1. Silverlight 引路蜂二维图形库示例:概述
  2. Silverlight 引路蜂二维图形库示例:包定义
  3. Silverlight 引路蜂二维图形库示例:基本知识
  4. Silverlight 引路蜂二维图形库示例:绘制各种几何图形
  5. Silverlight 引路蜂二维图形库示例:颜色
  6. Silverlight 引路蜂二维图形库示例:虚线类型
  7. Silverlight 引路蜂二维图形库示例:线段末端形状(LineCap)
  8. Silverlight 引路蜂二维图形库示例:线段连接类型(LineJoin)
  9. Silverlight 引路蜂二维图形库示例:不同线宽
  10. Silverlight 引路蜂二维图形库示例:椭圆
  11. Silverlight 引路蜂二维图形库示例:多义线和多边形
  12. Silverlight 引路蜂二维图形库示例:路径
  13. Silverlight 引路蜂二维图形库示例:坐标变换
  14. Silverlight 引路蜂二维图形库示例:颜色渐变
  15. Silverlight 引路蜂二维图形库示例:材质画刷
  16. Silverlight 引路蜂二维图形库示例:显示位图
  17. Silverlight 引路蜂二维图形库示例:动画Beziers曲线
  18. Silverlight 引路蜂二维图形库示例:矢量字体
  19. Silverlight 引路蜂二维图形库示例:结束语
 

离线地图下载方法解析

在使用Google Map, Microsoft Map 等在线地图时,常常想知道这些地图在服务器上是如何存放的,目前大部分地图服务器都是将地图以图片存储以提高响应速度。 一般大小为256X256个像素。
如果知道每个图片的URL,自己写个地图下载软件并不困难。从而做成离线地图。
下面程序片段给出了常用地图服务器上地图图片存取的URL计算方法。

using System.Collections.Generic;
using System.Text;
namespace MapTileURL
{
    class Program
    {
        private static Dictionary<string, string> MapTypeURLs = new Dictionary<string, string>
        {
            { "GoogleSatURL", "<a href="http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleMapURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleHybURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleTerURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleChinaURL", "<a href="http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "YahooMapURL", "<a href="http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" },
            { "YahooSatURL", "<a href="http://maps{Y_DIGIT}.yimg.com/ae/ximg?v=1.9&t=a&s=256&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/ae/ximg?v=1.9&t=a&s=256&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" },
            { "YahooInMapURL", "<a href="http://maps.yimg.com/hw/tile?locale=en&imgtype=png&yimgv=1.2&v=4.1&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2">http://maps.yimg.com/hw/tile?locale=en&imgtype=png&yimgv=1.2&v=4.1&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2</a>}" },
            { "YahooInHybURL", "<a href="http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2">http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2</a>}" },
            { "YahooHybURL", "<a href="http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&t=h&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&t=h&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" },
            { "MicrosoftBrMapURL", "<a href="http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4">http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4</a>" },
            { "MicrosoftHybURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z</a>" },
            { "MicrosoftSatURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z</a>" },
            { "MicrosoftMapURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z</a>" },
            { "MicrosoftTerURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z</a>" },
            { "OpenStreetMapURL", "<a href="http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png">http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png</a>" },
            { "OSMARenderURL", "<a href="http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png">http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png</a>" },
            { "OpenAerialMapURL", "<a href="http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM">http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM</a>}" },
            { "OpenCycleMapURL", "<a href="http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png">http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png</a>" }
        };
        readonly static char[] Lookup = new[] { 'q', 't', 'r', 's' };
        public static string GetQuadtreeFromXYZoom(int x, int y, int zoom)
        {
            var quad = new StringBuilder();
            for (int i = 0; i < zoom; i++)
            {
                int rx = x % 2;
                int ry = y % 2;
                x /= 2;
                y /= 2;
                quad.Insert(0, Lookup[rx * 2 + ry]);
            }
            quad.Insert(0, 't');
            return quad.ToString();
        }
        public static string BuildUrl(string tileType, int x,int y,int zoom)
        {
    
            string url = "";
            // Edited by Shustrik - compacted the switch statement
            switch (tileType)
            {
                case "GoogleSat":
                case "GoogleSatH":
                    url = MapTypeURLs["GoogleSatURL"];
                    break;
                case "GoogleMap":
                    url = MapTypeURLs["GoogleMapURL"];
                    break;
                case "GoogleHyb":
                    url = MapTypeURLs["GoogleHybURL"];
                    break;
                case "GoogleTer":
                    url = MapTypeURLs["GoogleTerURL"];
                    break;
                case "GoogleChina":
                    url = MapTypeURLs["GoogleChinaURL"];
                    break;
                case "MicrosoftMap":
                    url = MapTypeURLs["MicrosoftMapURL"];
                    break;
                case "MicrosoftSat":
                    url = MapTypeURLs["MicrosoftSatURL"];
                    break;
                case "MicrosoftHyb":
                    url = MapTypeURLs["MicrosoftHybURL"];
                    break;
                case "MicrosoftTer":
                    url = MapTypeURLs["MicrosoftTerURL"];
                    break;
                case "MicrosoftBrMap":
                    if (zoom <= 10)
                        url =  MapTypeURLs["MicrosoftMapURL"];
                    else
                        url = MapTypeURLs["MicrosoftBrMapURL"];
                    break;
                case "YahooMap":
                    url = MapTypeURLs["YahooMapURL"];
                    break;
                case "YahooSat":
                case "YahooSatH":
                case "YahooSatH2":
                    url = MapTypeURLs["YahooSatURL"];
                    break;
                case "YahooHyb":
                    url = MapTypeURLs["YahooHybURL"];
                    break;
                case "YahooInMap":
                    url = MapTypeURLs["YahooInMapURL"];
                    break;
                case "YahooInHyb":
                    url = MapTypeURLs["YahooInHybURL"];
                    break;
                case "OpenStreetMap":
                    url = MapTypeURLs["OpenStreetMapURL"];
                    break;
                case "OSMARender":
                    url = MapTypeURLs["OSMARenderURL"];
                    break;
                case "OpenAerialMap":
                    url = MapTypeURLs["OpenAerialMapURL"];
                    break;
                case "OpenCycleMap":
                    url = MapTypeURLs["OpenCycleMapURL"];
                    break;
            }
          
            // Edited by Shustrik - added variables for configuration settings other than Google
            string quadcode = "";
            for (int i = (int)zoom - 1; i >= 0; i--)
                quadcode = quadcode + (((((y >> i) & 1) << 1) + ((x >> i) & 1)));
            url = url.Replace("{X}", x.ToString());
            url = url.Replace("{Y}", y.ToString());
            url = url.Replace("{Z}", ((int)zoom).ToString());
            url = url.Replace("{ZOOM}", ((int)zoom).ToString());
            url = url.Replace("{QUAD}", quadcode);
            url = url.Replace("{YAHOO_Y}", (((1 << ((int)zoom)) >> 1) - 1 - y).ToString());
            url = url.Replace("{YAHOO_ZOOM}", ((int)zoom + 1).ToString());
            url = url.Replace("{YAHOO_ZOOM_2}", (17 - (int)zoom + 1).ToString());
            url = url.Replace("{OAM_ZOOM}", (17 - (int)zoom).ToString());
            url = url.Replace("{GOOG_DIGIT}", ((x + y) & 3).ToString());
            url = url.Replace("{GOOG_QUAD}", GetQuadtreeFromXYZoom(x, y, zoom));
            url = url.Replace("{MS_DIGITBR}", ((((y & 1) << 1) + (x & 1)) + 1).ToString());
            url = url.Replace("{MS_DIGIT}", ((((y & 3) << 1) + (x & 1))).ToString());
            url = url.Replace("{Y_DIGIT}", ((x + y + zoom) % 3 +1).ToString());
            url = url.Replace("{GALILEO}", "Galileo".Substring(0, ((3 * x + y) & 7)));
            // support old style {} vars
            url = url.Replace("QQQQ", GetQuadtreeFromXYZoom(x,y,zoom));
            url = url.Replace("XXXX", x.ToString());
            url = url.Replace("YYYY", y.ToString());
            url = url.Replace("ZZZZ", (17 - (int)zoom).ToString());
            url = url.Replace("{OSM_ZOOM}", ((int)zoom).ToString());
            url = url.Replace("{MS_QUADCODE}", quadcode);
            url = url.Replace("*", ((x+y+zoom) %4).ToString());
            return url;
        }
        static void Main(string[] args)
        {
            string url = BuildUrl("GoogleMap", 1, 1, 1);
            //return <a href="http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali">http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali</a>
        }
    }
}

例子中取出 google map ,在 zoom=1 及 x=1,y=1是的图片。
http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali

下载工具  http://www.mapdigit.com/forum/viewthread.php?tid=43&extra=page%3D1 中文说明参见离线地图生成工具结构图离线地图生成工具使用方法

 

Silverlight 引路蜂二维图形库示例:结束语

尽管前面引路蜂二维图形库的例子是以Silverlight为例,但引路蜂二维图形库可以用于Java ME,BlackBerry, LWUIT, Windows Mobile ,Windows Phone, Android, iPhone, Java SE ,Mono 等各个平台,以Silverlight为例是因为Silverlight可以实现在线演示。

Install Microsoft Silverlight

Silverlight库及例子下载 http://www.guidebee.info/download/silverlight/SilverlightGraphics2DDemo.zip

 

Silverlight 引路蜂二维图形库示例:矢量字体

引路蜂二维图形库支持矢量字体,包括中文和英文。对于Silverlight应用,由于访问权限的问题,字库一般需作为资源文件包含在应用中,对于英文字体不是个大问题,而对于中文字库,GB2312字库文件最小也要4M以上,所以尽量是用同一字体。引路蜂二维图形库绘制文字时是采用的矢量字库。也可以对文字内部进行填充。文字方向可以从左到右,从上到下,从右到左。 

字体下载链接如下表:

字体 大小 下载
Arial 34K Download
Courier New 50K Download
Elephant 52K Download
Impact 34K Download
Georgia 53K Download
Rockwell 35K Download
Times New Roman 44K Download
Microsoft Sans Serif 29K Download
Verdana 36K Download
幼圆 5128K Download
新魏 15874K Download
新宋体 5740K Download
行楷 13588K Download
宋体 5740K Download
隶书 7083K Download
仿宋 8104K Download
黑体 6108K Download

 

下例使用行楷显示“引路蜂软件”。 

private void FontDemo()
{
 TextureBrush brush1; 

 BitmapImage img = new BitmapImage();
 img.CreateOptions = BitmapCreateOptions.None;
 string path = "/SilverlightGraphics2DDemo;component/brick.png";
 Stream s = Application.GetResourceStream
      (new Uri(path, UriKind.Relative)).Stream;
 img.SetSource(s);
 WriteableBitmap writeableBitmap = new WriteableBitmap(img);
 brush1 = new TextureBrush(writeableBitmap.Pixels,
      img.PixelWidth, img.PixelHeight);
 Pen pen = new Pen(Color.Blue, 1); 

 path = "/SilverlightGraphics2DDemo;component/xingkai.fon";
 int fontSize = 100;
 s = Application.GetResourceStream
     (new Uri(path, UriKind.Relative)).Stream;
 s.Seek(0, SeekOrigin.Begin);
 //Clear the canvas with white color.
 graphics2D.Clear(Color.White);
 char[] longLine = null; 

 FontEx font = new FontEx(s);
 string guidebee = "引路蜂软件";
 longLine = guidebee.ToCharArray();
 graphics2D.SetPenAndBrush(pen,brush1);
 graphics2D.DrawChars(font, fontSize, longLine, 0, longLine.Length,
  (screenWidth - fontSize) / 2, 20, FontEx.TextDirTb);
 int offset = 20;
 for (int i = 1; i < 4;i++ )
 {
  fontSize=100-i*20;
  offset += fontSize+5;
  graphics2D.DrawChars(font, fontSize, longLine, 0,
   longLine.Length, (screenWidth - fontSize) / 2 - offset,
        20, FontEx.TextDirTb);
  graphics2D.DrawChars(font, fontSize, longLine, 0,
   longLine.Length, (screenWidth - fontSize) / 2 + offset,
   20, FontEx.TextDirTb);
   
 }
}

 

除了外挂字体外,引路蜂二维图形库自带了一个英文字库可以通过FontEx.GetSystemFont()取得。此外上述.fon 字体格式为引路蜂自定义,内部使用SVG来描述字体。和Windows中的字体格式不一致。

 

Silverlight 引路蜂二维图形库示例:动画Beziers曲线

类Path为一条几何路径,可以通过直线,二次曲线,三次曲线来构成任意路径。Path提供了moveTo, lineTo, curveTo, curveToCubic, closePath方法来构成路径。

下面的例子动态显示一条Bezier曲线。

/**
* The animation thread.
*/
Thread _thread;
bool _drawn;
/**
 * The random number generator.
 */
readonly Random _random = new Random();
/**
 * The animated path
 */
readonly Path _path = new Path();
/**
 * Red brush used to fill the path.
 */
readonly SolidBrush _brush = new SolidBrush(Color.Red);
const int Numpts = 6;
readonly int[] _animpts = new int[Numpts * 2];
readonly int[] _deltas = new int[Numpts * 2];

private void Beziers()
{
 Reset(screenWidth, screenHeight);
 _thread = new Thread(RunBeziers);
 _thread.Start();
}

private void RunBeziers()
{

 Thread me = Thread.CurrentThread;

 if (!_drawn)
 {
  lock (this)
  {
   graphics2D.Clear(Color.White);
   graphics2D.Fill(_brush, _path);
   _drawn = true;
  }
 }
 while (_thread == me)
 {
  DrawDemo(screenWidth, screenHeight);
 }
}

/**
* Generates new points for the path.
*/
private void Animate(int[] pts, int[] deltas, int i, int limit)
{
 int newpt = pts[i] + deltas[i];
 if (newpt <= 0)
 {
  newpt = -newpt;
  deltas[i] = (_random.Next() & 0x00000003) + 2;
 }
 else if (newpt >= limit)
 {
  newpt = 2 * limit - newpt;
  deltas[i] = -((_random.Next() & 0x00000003) + 2);
 }
 pts[i] = newpt;
}

/**
* Resets the animation data.
*/
private void Reset(int w, int h)
{
 for (int i = 0; i < _animpts.Length; i += 2)
 {
  _animpts[i + 0] = (_random.Next() & 0x00000003) * w / 2;
  _animpts[i + 1] = (_random.Next() & 0x00000003) * h / 2;
  _deltas[i + 0] = (_random.Next() & 0x00000003) * 6 + 4;
  _deltas[i + 1] = (_random.Next() & 0x00000003) * 6 + 4;
  if (_animpts[i + 0] > w / 2)
  {
   _deltas[i + 0] = -_deltas[i + 0];
  }
  if (_animpts[i + 1] > h / 2)
  {
   _deltas[i + 1] = -_deltas[i + 1];
  }
 }
}

/**
 * Sets the points of the path and draws and fills the path.
 */
private void DrawDemo(int w, int h)
{
 for (int i = 0; i < _animpts.Length; i += 2)
 {
  Animate(_animpts, _deltas, i + 0, w);
  Animate(_animpts, _deltas, i + 1, h);
 }
 //Generates the new pata data.
 _path.Reset();
 int[] ctrlpts = _animpts;
 int len = ctrlpts.Length;
 int prevx = ctrlpts[len - 2];
 int prevy = ctrlpts[len - 1];
 int curx = ctrlpts[0];
 int cury = ctrlpts[1];
 int midx = (curx + prevx) / 2;
 int midy = (cury + prevy) / 2;
 _path.MoveTo(midx, midy);
 for (int i = 2; i <= ctrlpts.Length; i += 2)
 {
  int x1 = (curx + midx) / 2;
  int y1 = (cury + midy) / 2;
  prevx = curx;
  prevy = cury;
  if (i < ctrlpts.Length)
  {
   curx = ctrlpts[i + 0];
   cury = ctrlpts[i + 1];
  }
  else
  {
   curx = ctrlpts[0];
   cury = ctrlpts[1];
  }
  midx = (curx + prevx) / 2;
  midy = (cury + prevy) / 2;
  int x2 = (prevx + midx) / 2;
  int y2 = (prevy + midy) / 2;
  _path.CurveTo(x1, y1, x2, y2, midx, midy);
 }
 _path.ClosePath();
 // clear the clipRect area before production

 graphics2D.Clear(Color.White);
 graphics2D.Fill(_brush, _path);

 RefreshBitmap();

}

其中实时更新图像需要CompositionTarget.Rendering事件来处理。CompositionTarget.Rendering += CompositionTargetRendering;

private void CompositionTargetRendering(object sender, EventArgs e)
{
 bmp.Invalidate();
}