
先看看下面的实例 这是应朋友之邀编写的查询职业技能鉴定考核的分数的软件。看过我之前的博文的,可知这是借用我之前的网页界面。 这个UI,如果用WinForm的控件来实现,难度很高。 于是另辟蹊径,用Webbrowser控件加载HTML网页来实现软件的UI。 这样做的好处有: 1、用HTML编写UI的难度要低得多,可以利用网上很多现成的UI库实现绚丽的UI。本例就是利用Bootstrap库实现的界面UI。 2、实现前端UI和后台逻辑的分离。前端UI(HTML)只实现界面的绘制(可以简单的对前端数据验证),不需要负责后台逻辑以及数据的验证。 缺点是: 界面实现是通过Webbrowser控件来调用系统内核的IE来实现。则界面的效果和IE的版本息息相关,高版本的IE没什么太大的差异,但是低版本的IE就会出现界面变形的情况。 这样做还要解决前端UI和后台的通信问题,即: 1、前端UI如何调用后台的方法 2、后台如何调用前端UI的方法来刷新页面 下面详细讲解一下 1、前端UI如何调用后台的方法 首先,新建一个类,专门实现后台的逻辑。为了能让前端调用,必须给类添加相应的申明,如下所示: <System.Runtime.InteropServices.ComVisible(True)> Public Class clsQuery Private _Web As WebBrowser Public Sub New(W As WebBrowser) _Web = W _Web.ObjectForScripting = Me End Sub Public Sub Query(ID As String, Subject As String) End Sub End Class 通过申明 <System.Runtime.InteropServices.ComVisible(True)> 使得该类的公用方法能通过Webbrowser控件被调用,就是代码中Query方法 再通过 _Web.ObjectForScripting = Me 把该类和Webbrowser控件绑定,这样前端UI就能调用该类的方法了。 在前端UI的HTML代码中,通过window.external.Query(ID, Subject); 调用后台的逻辑 <script> function Query() { var ID = $('#IDCard').val(); var Subject = $('#Subject').val(); if (ID == '') { alert('请输入身份证号!!!!'); } else { window.external.Query(ID, Subject); } } function CreateTable(T) { $('#ResultTable').html(T); } </script> 2、后台如何调用前端UI的方法来刷新页面 上面的前端UI代码中,函数CreateTable是给后台逻辑调用来刷新前端UI的 在后台代码中用下面的代码调用前端UI的函数来刷新UI。 _Web.Document.InvokeScript("CreateTable", A) 至此,前端UI和后台逻辑的双向通信已经全部打通,实现了UI和逻辑层的分离。 同时,前端UI利用众多的HTML、CSS、JS类库能实现很多绚丽的UI,不怕想不到,就怕做不到。 本文中的后台逻辑就不贴了,无外乎就是获取数据、数据分析、格式化数据而已 多说一句,这个前端UI也可以用WPF实现,只是实现的难度要大很多。毕竟网上现成的WPF的前端UI库不太好找。
在前文 创建基于Bootstrap的下拉菜单的DropDownList的JQuery插件 中,实现了DropDownList的JQuery组件,但是留有遗憾。就是当下拉菜单出现滚动条的时候,滚动条会覆盖菜单右侧的两个圆角。使得下拉菜单左侧有2个圆角,右侧没有,看上去不是很完美。如下图所示: 本文的内容就是如何恢复右侧的圆角 先看看原本的下拉菜单的HTML结构: Snippet官网 Snippet使用实例 <ul class="dropdown-menu dropdown-menu-right" role="menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li class="divider"></li> <li><a href="#">Separated link</a></li> </ul> 从上面的结构可以看出,由ul标签实现下拉菜单的外观(通过引用dropdown-menu样式),由li标签实现菜单项(包括菜单、分隔符、组标题)。来看看ul和li标签对应的CSS: Snippet官网 Snippet使用实例 .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; text-align: left; list-style: none; background-color: #fff; -webkit-background-clip: padding-box; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, .15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); box-shadow: 0 6px 12px rgba(0, 0, 0, .175); } .dropdown-menu > li > a { display: block; padding: 3px 20px; clear: both; font-weight: normal; line-height: 1.42857143; color: #333; white-space: nowrap; } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { color: #262626; text-decoration: none; background-color: #f5f5f5; } 由于a的样式是通过.dropdown-menu > li > a来实现的,故要实现a的外观必须是在含有样式dropdown-menu的ul里面的li的里面的a的。 于是,动了一个念头,在HTML结构里的ul里面的li里再嵌套一个包含样式dropdown-menu的ul,ul里面是li,li里面是a。 但是从上面的CSS可以看出,嵌套在里面的ul也会实现菜单的外观(圆角、投影、浮动等),故在该ul的标签里强制添加style属性,把一些样式强制性的去除(改成inherit,采用默认样式),这些样式包括display、position、top、float、padding、border、border-radius、-webkit-box-shadow、box-shadow。 再说说MaxHeight。本次修改后直接采用CSS的样式max-height,而减少对菜单高度的判断。会有疑问,如果浏览器不支持max-height怎么办?一是不支持max-height的浏览器比较少(IE6等),二是如果浏览器不支持max-height,也就不能很好的支持Bootstrap。故不必考虑浏览器是否支持max-height属性。由于里外有2个ul标签,我们需要对里面的ul标签应用max-height属性,故用UL=Obj.find("ul[style]")语句来找寻里面的ul标签(因为里面的ul含有style属性,而外面的ul没有)。 再说说JQuery的height方法。当调用JQuery的height方法来计算隐藏元素高度时,估计是先会显示元素,然后计算高度,再隐藏元素。这会有两个问题。一是显示再隐藏,速度很快,肉眼看不出,但是浏览器不会说谎,有时浏览器会额外显示滚动条。二是如果该元素的父元素也是隐藏的,则height方法会返回0。 完善版的源代码: Snippet官网 Snippet使用实例 (function($){ jQuery.fn.DropDownList = function(options) { var defaults ={ InputName:"Q", ButtonText:"示例", ReadOnly:true, MaxHeight:-1, onSelect:$.noop(), } var options = $.extend(defaults,options); return this.each(function(){ var o=options; var Obj=$(this); var S="<div class='input-group'>"; S = S + "<input type='text' class='form-control' name='" + o.InputName + "' id='" + o.InputName + "' />"; S = S + "<div class='input-group-btn'>"; S = S + "<button type='button' class='btn btn-default dropdown-toggle' data-toggle='dropdown'>" + o.ButtonText + " <span class='caret'></span></button>"; S = S + "<ul class='dropdown-menu dropdown-menu-right' role='menu' >"; S = S + "<li><ul class='dropdown-menu ' style='display:inherit;position:inherit;top:0;float:inherit;padding:0;border:0px;border-radius:0px;-webkit-box-shadow: inherit;box-shadow: inherit;'>"; var SelText,SelData; if (o.Sections!== undefined) { $.each(o.Sections,function(n,value){ if (n>0) {S=S + "<li class='divider'></li>";} if (value.ItemHeader!==undefined) {S = S + "<li class='dropdown-header'>" + value.ItemHeader + "</li>";} CreateItem(value); }); } else { CreateItem(o); } function CreateItem(Items) { $.each(Items.Items,function(n,Item){ if (Item.ItemData===undefined) {Item.ItemData=Item.ItemText;} S=S + "<li><a href='#' ItemData='" + Item.ItemData + "' >" + Item.ItemText + "</a></li>"; if (Item.Selected==true) {SelText=Item.ItemText;SelData=Item.ItemData;} }); } S =S + "</ul></li></ul></div></div>"; Obj.html(S); var Input=Obj.find("input"); if (SelText!="") {SetData(SelText,SelData);} Obj.find("a").bind("click", function(e) { SetData($(this).html(),$(this).attr("ItemData")); }); if (o.ReadOnly==true) { Input.bind("cut copy paste keydown", function(e) {e.preventDefault();}); } if (o.MaxHeight>0) { var UL=Obj.find("ul[style]"); UL.css({'max-height':o.MaxHeight,'overflow':'auto'}); } function SetData(Text,Data) { Input.val(Text); if (o.onSelect) {o.onSelect(o.InputName,Data);} } }); } })(jQuery); 样张: 这样通过两层的ul实现了下拉菜单,并且滚动条也没有覆盖右侧的两个圆角。较之上个版本,比较完善。
有些简单的单网页,如果利用等高线效果的背景图片,再配合合适的背景色,能达到绚丽的效果。如下图所示: 本文就介绍该等高线效果的背景图片是如何制作的。Follow Me!!!! 1、新建文档,尺寸:1000px*1000px 2、用矩形工具创建一个矩形,尺寸:500px*500px 3、给这个矩形添加杂色(点击:滤镜 > 杂色 > 添加杂色,参数如下图所示) 4、复制这个图层3次,调整这4个矩形到四角上(位置分别是(0,0),(500,0),(0,500),(500,500)) 5、将这四个图层合并到一个图层,并给它添加高斯模糊(点击:滤镜 > 模糊 > 高斯模糊),参数如下: 6、点击:滤镜 > 风格化 > 查找边缘,仔细看看,能看到等高线的雏形了。 7、点击:图层 > 新建调整图层 > 色阶。在弹出的对话框上勾选“使用前一图层创建剪贴蒙版”。 在其后出现的对话框,有三个通道可选。可依次选择红、绿、蓝三个通道,参数依照下图所示,可以得到三个效果图,从中挑一个最满意的 下面的图是红色通道: 下面的图是绿色通道: 下面的图是蓝色通道: 可以看出,在图的边缘有线聚集的情况,这不适合做背景(背景要平铺,边缘要顺和),故还得再处理一下(我选的是绿色通道的那张图) 8、将色阶图层和原图层选中并右键选择转换为智能对象,然后栅格化该图层。用矩形选框工具新建矩形选区,调整选区为(250,250,500,500) 9、按Ctrl + Shift + I反选选区,并删除多余部分。可以看出剩下的矩形上边和下边是线条对应的、左边和右边是线条对应的。 10、调整画布大小为500px*500培训,使之正好是整个图像 11、点击:图像 > 调整 > 阈值,调整合适的参数: 至此,等高线背景图就基本制作完成了。我们可以通过魔棒工具(把参数栏上的“连续”前的勾去掉),把白色背景去掉,再利用颜色叠加的图层样式,改变线条的颜色(建议用浅灰色,为了演示方便,我改成红色) 把上面的图片(线条改为浅灰色,)作为网页的背景图片,再配合合适的背景色,能达到绚丽的效果。 再把自己的作品推荐一下:http://bertin.duapp.com/,利用百度开发者平台,只是不太稳定,经常会有503错误。背景图就是一个等高线效果图,再配合蓝色,效果惊艳。
问题描述: 甲乙两人比赛投篮。约定甲先投篮,每人投篮投进一球,则继续投球,若投失一球,则换人投球。初始积分为1分,甲每投进一球,积分加1分;乙每投进1球,积分减1分。若积分达到N分(N>1),甲获胜;若积分减至0分,乙获胜。假定甲投进的概率为P1(0<P1<1),乙投进的概率为P2(0<P2<1)。那么这场投篮比赛,甲获胜的概率P为多少? 很显然的,甲获胜的概率P是和P1、P2、N相关的。 P1越大,P越大 P2越大,P越小 N越大,P越小 不失一般性,假设P1=0.7,P2=0.3,N=4,求甲获胜的概率P 解法一:大数量模拟法(10000000次) 在前文 算法题——投篮比赛获胜的概率 中介绍的就是这种方法。 用计算机模拟10000000次比赛的过程,统计甲获胜的次数。然后甲获胜的次数比上总次数接近甲获胜的概率。 一共模拟了10批次的比赛,每批次模拟10000000次比赛的过程(P1=0.7,P2=0.3,N=4) 第1批次,甲获胜8282467次 第2批次,甲获胜8282839次 第3批次,甲获胜8283808次 第4批次,甲获胜8281636次 第5批次,甲获胜8282652次 第6批次,甲获胜8283432次 第7批次,甲获胜8281948次 第8批次,甲获胜8284125次 第9批次,甲获胜8284626次 第10批次,甲获胜8283720次 平均10个批次,平均甲获胜8283125次。那么甲获胜的概率大约是82.83125% 解法二:矩阵法 解法一是建立在大量的模拟上,所得的数据离理论值还是有一定的偏差的(模拟的次数越多,偏差值越小)。那么,本方法就是从理论上来计算甲获胜的概率P的。 分析该问题,可以得出整个问题存在8个状态(状态的个数和N有关,状态的个数为2N个) 分别是 积分0分,乙获胜 积分1分,乙要投篮;积分1分,甲要投篮 积分2分,乙要投篮;积分2分,甲要投篮 积分3分,乙要投篮;积分3分,甲要投篮 积分4分,甲获胜 这8个状态之间的关系可以用下图表示(为了后文表述方便,给这8个状态起了名字,分别是S1、S2、S3、……、S7、S8) 如图,比赛初始是在S1状态,比赛结束在S7(甲获胜)或S8(乙获胜)状态,状态之间有转换箭头。 例如:当前是S3状态(积分3,甲投篮),那么下一个状态可能是S6(甲投失,换成积分3,乙投篮的状态)或者是S7(甲投进,积分4,甲获胜的状态)。再比如当前是S6状态(积分3,乙投篮),那么下一个状态可能是S5(乙投进,换成积分2,乙投篮的状态)或者是S3(乙投失,换成积分3,甲投篮的状态) 用A1、A2、A3、A4、A5、A6、A7、A8表示某次投篮后,各个状态所占的比重。那么再投篮一次后,各个状态的所占比重计算如下(等号左边是新的比重,等号右边是原来的比重): A1=A4(1-P2) A2=A1P1+A5(1-P2) A3=A2P1+A6(1-P2) A4=A5P2+A1(1-P1) A5=A6P2+A2(1-P1) A6=A3(1-P1) A7=A3P1+A7 A8=A4P2+A8 可以把上面的计算式子转换为矩阵的形式 令向量Ti=(A1、A2、A3、A4、A5、A6、A7、A8)表示第i次(i=0时表示初始状态)投篮各状态所占比重的向量,则 Ti+1=Ti×A 其中,A为8*8的矩阵,如下图所示 因为 T1=T0×A T2=T1×A=T0×A×A=T0×A2 T3=T2×A=T0×A2×A=T0×A3 …… TM=T0×AM 实际上,本题中的甲获胜的概率就是当M趋向于无穷时,TM的A7分量。同时,TM的A8分量表示乙获胜的概率 把上面的矩阵A分成四个小矩阵Q1、Q2、Q3、Q4,如下图所示: 由于TM=T0×AM,故在这儿分析AM 由于矩阵I-Q1可逆,则上述的表达式可以简化为 Q1M-1+Q1M-2+…+Q1+I=(Q1M-1+Q1M-2+…+Q1+I)(I-Q1)(I-Q1)-1 =(Q1M-1+Q1M-2+…+Q1+I-Q1M-Q1M-1-…-Q1)(I-Q1)-1 =(I-Q1M)(I-Q1)-1 于是矩阵AM就简化成如下形式 对于矩阵Q1来说。由于是非负矩阵,根据G. Frobenius可知,它的谱半径ρ满足不等式,r≤ρ≤R。其中r表示G1矩阵中所有行和值(一行所有元素加起来的值)的最小值,R表示G1矩阵中所有行和值最大值。可知R=1,r=MIN(1-P1,1-P2) 而在李华所著的《非负矩阵谱半径的一个新估计》中,将谱半径的范围缩小 得到如下的不等式 r≤ρ≤R-(1-P2)(R-r)/R 由此可以得知Q1的谱半径ρ<1 而利用谱半径的性质可知,当谱半径ρ<1时,矩阵Q1的M次方趋向于0矩阵 于是本问题就得出了结论,令T为TM中M趋向无穷大时的向量,A*为AM中M趋向无穷大时的矩阵。可知 T=T0×A* 本题中P1=0.7,P2=0.3,T0=(1,0,0,0,0,0,0,0) 矩阵A和矩阵A*分别为 于是 T=T0×A*=(0,0,0,0,0,0,0.828302342,0.171697658) 甲获胜的概率是82.8302342%,乙获胜的概率是17.1697658% 和方法一的结论比较(82.83125%),还是非常接近的。也间接说明了方法一的可行性。 本方法从理论的角度给出了问题的解。本示例中,P1=0.7,P2=0.3,N=4 本方法的计算难点就是求(I-Q1)-1,这是一个消耗大量计算时间的过程。Q1是一个2N-2*2N-2的稀疏矩阵,I-Q1也是一个2N-2*2N-2的稀疏矩阵,求它的逆矩阵是非常耗时的 可以在本方法的理论基础上,给出简化的计算方法,也就是接下来讲的迭代法 解法三:迭代法 迭代法的理论基础在解法二上 依次计算向量T1、T2、……、TM等等 若TM+1-TM≈0(若每个分量小于10-9,我们就认为两个向量相等), 还是以上面的示例为例(P1=0.7,P2=0.3,N=4) T1=(0,0.7,0,0.3,0,0,0,0) T2=(0.21,0,0.49,0,0.21,0,0,0.09) T3=(0,0.294,0,0.126,0,0.147,0.343,0.09) T4=(0.0882,0,0.3087,0,0.1323,0,0.343,0.1278) T5=(0,0.15435,0,0.06615,0,0.09261,0.55909,0.1278) T6=(0.046305,0,0.172872,0,0.074088,0,0.55909,0.147645) T7=(0,0.0842751,0,0.0361179,0,0.0518616,0.6801004,0.147645) T8=(0.02528253,0,0.09529569,0,0.04084101,0,0.6801004,0.15848037) T9=(0,0.046286478,0,0.019837062,0,0.028588707,0.746807383,0.15848037) T10=(0.013885943,0,0.05241263,0,0.022462556,0,0.746807383,0.164431489) T11=(0,0.025443949,0,0.01090455,0,0.015723789,0.783496224,0.164431489) T12=(0.007633185,0,0.028817417,0,0.012350321,0,0.783496224,0.167702854) T13=(0,0.013988454,0,0.005995052,0,0.008645225,0.803668415,0.167702854) T14=(0.004196536,0,0.015843576,0,0.006790104,0,0.803668415,0.169501369) …… T71=(0,4.08706E-10,0,1.7516E-10,0,2.52594E-10,0.828302342,0.171697657) T72=(1.22612E-10,0,4.6291E-10,0,1.9839E-10,0,0.828302342,0.171697658) T72≈T71,故可以认为T=(0,0,0,0,0,0,0.828302342,0.171697658) 也就是甲获胜的概率是82.8302342%,乙获胜的概率是17.1697658% 本方法相比解法二,计算上来得简单,仅仅通过迭代计算(加加乘乘),就计算出最后的结果。相比求矩阵的逆来说,要简单的多。
本系列文章目录: SharpDX之Direct2D教程I——简单示例和Color(颜色) 绘制位图是绘制操作的不可缺少的一部分。在Direct2D中绘制位图,必须先利用WIC组件将位图加载到内存中,再绘制到RenderTarget中去 在SharpDX中绘制位图,分成两个部分: 利用WIC在SharpDX中加载位图,生成Bitmap对象 利用RenderTarget对象的DrawBitmap方法把Bitmap对象绘制到RenderTarget中去 利用WIC在SharpDX中加载位图文件 利用WIC在SharpDX中绘制位图文件的核心内容就是把位图文件转换为Bitmap对象。它的操作过程如下: 1、创建WIC的ImagingFactory类。 2、根据位图文件创建BitmapDecoder对象(实际上调用系统解码器解析位图文件)。 BitmapDecoder对象有1个属性和1个函数 FrameCount属性:只读属性,说明该位图对象包含的帧数。一般gif文件能包含多个帧,其余格式的一般只有1个帧 GetFrame函数:返回指定帧对象。参数index是整形,说明是第几帧(从0开始)。返回的是BitmapFrameDecode对象 3、利用BitmapDecoder对象的GetFrame函数,返回指定帧的BitmapFrameDecode对象。(参数index一般是0,返回第1帧) 一般情况下,到此就可以了。但是,位图格式有很多,你可能不是很确定你的位图格式是否兼容SharpDX的Bitmap对象。因此,比较好的做法是继续下面的步骤,将位图格式转换为兼容SharpDX的Bitmap对象 4、创建FormatConverter对象。该对象负责进行格式转换。 5、调用FormatConverter对象的Initialize方法,进行格式转换。 6、最后,利用Bitmap对象的FromWicBitmap函数将之前的FormatConverter对象转换为SharpDX的Bitmap对象 和Windows API Code Pack 1.1中的Direct2D略有不同的是,BitmapFrameDecode对象和FormatConverter对象都继承BitmapSource对象,省去了一个转换的过程 下面是代码 Protected Function LoadBitmap(Render As D2D.RenderTarget, File As String, FrameIndex As Integer) As D2D.Bitmap Dim Decoder As New WIC.BitmapDecoder(_ImagingFactory, File, DX.IO.NativeFileAccess.Read, WIC.DecodeOptions.CacheOnLoad) If FrameIndex > Decoder.FrameCount - 1 OrElse FrameIndex < 0 Then FrameIndex = 0 Dim Source As WIC.BitmapFrameDecode = Decoder.GetFrame(FrameIndex) Dim Converter As New WIC.FormatConverter(_ImagingFactory) Converter.Initialize(Source, WIC.PixelFormat.Format32bppPBGRA) Return D2D.Bitmap.FromWicBitmap(Render, Converter) End Function 利用RenderTarget对象的DrawBitmap方法把Bitmap对象绘制到RenderTarget中去 下面是DrawBitmap方法的原型定义: Public Sub DrawBitmap(bitmap As D2D.Bitmap, destinationRectangle As DX.RectangleF, opacity As Single, interpolationMode As D2D.BitmapInterpolationMode, sourceRectangle As DX.RectangleF) Public Sub DrawBitmap(bitmap As D2D.Bitmap, opacity As Single, interpolationMode As D2D.BitmapInterpolationMode) Public Sub DrawBitmap(bitmap As D2D.Bitmap, destinationRectangle As DX.RectangleF, opacity As Single, interpolationMode As D2D.BitmapInterpolationMode) Public Sub DrawBitmap(bitmap As D2D.Bitmap, opacity As Single, interpolationMode As D2D.BitmapInterpolationMode, sourceRectangle As DX.RectangleF) 参数的意义如下: bitmap:要绘制的Bitmap对象 destinationRectangle:绘制在RenderTarget对象上的目标范围。缺省是在RenderTarget对象的左上角,宽高是Bitmap对象的宽高 opacity:不透明度 interpolationMode:图像缩放时的插值算法,是个枚举 sourceRectangle:要绘制的源目标范围。缺省是Bitmap对象的整个范围 下面是示例代码 Public Class clsSharpDXLoadBitmap Inherits clsSharpDXSampleBase Protected _ImagingFactory As WIC.ImagingFactory Public Shadows Sub CreateDeviceResource(Target As Control) MyBase.CreateDeviceResource(Target) _ImagingFactory = New WIC.ImagingFactory End Sub Public Function LoadBitmap(File As String, Optional FrameIndex As Integer = 0) As D2D.Bitmap Return LoadBitmap(_RenderTarget, File, FrameIndex) End Function Protected Function LoadBitmap(Render As D2D.RenderTarget, File As String, FrameIndex As Integer) As D2D.Bitmap Dim Decoder As New WIC.BitmapDecoder(_ImagingFactory, File, DX.IO.NativeFileAccess.Read, WIC.DecodeOptions.CacheOnLoad) If FrameIndex > Decoder.FrameCount - 1 OrElse FrameIndex < 0 Then FrameIndex = 0 Dim Source As WIC.BitmapFrameDecode = Decoder.GetFrame(FrameIndex) Dim Converter As New WIC.FormatConverter(_ImagingFactory) Converter.Initialize(Source, WIC.PixelFormat.Format32bppPBGRA) Return D2D.Bitmap.FromWicBitmap(Render, Converter) End Function Public Shadows Sub Render() With _RenderTarget .BeginDraw() .Clear(DX.Color.Honeydew.ToColor4) Dim B As D2D.Bitmap = LoadBitmap("216.png") .DrawBitmap(B, 1, SharpDX.Direct2D1.BitmapInterpolationMode.NearestNeighbor, New DX.RectangleF(0, 0, 260, 260)) .EndDraw() End With End Sub End Class 利用WIC保存图片 WIC既能负责图片的解码,也能负责图片的编码。我们也可以利用WIC编码图片。 在调试的时候出了问题,先看看下面两段代码 Public Class Class1 Public Shared Sub Test() Dim wicFactory As WIC.ImagingFactory = New WIC.ImagingFactory Dim F As String = "333.png" If (File.Exists(F)) Then File.Delete(F) Dim spStream As WIC.WICStream = New WIC.WICStream(wicFactory, F, NativeFileAccess.Write) Dim spBitmapEncoder As WIC.PngBitmapEncoder = New WIC.PngBitmapEncoder(wicFactory) spBitmapEncoder.Initialize(spStream) End Sub End Class 上面的代码是用VB2010写的,仅仅写到PngBitmapEncoder对象的Initialize方法。 再看看下面这段代码,用的是C# 2010写的 class Class1 { public static void test() { ImagingFactory wicFactory = new ImagingFactory(); string F = "333.png"; if (File.Exists(F)) File.Delete(F); WICStream stream = new WICStream(wicFactory, F, NativeFileAccess.Write); PngBitmapEncoder encoder = new PngBitmapEncoder(wicFactory); encoder.Initialize(stream); } } 可以看出,两段代码没什么不同(仅仅是语法上的不同而已),但是VB2010的代码在执行到Initialize时总是报错(内部错误),而C#2010在执行到Initialize方法很顺利的完成了。两段代码引用的是同一个动态库SharpDX的2.5.0的库。 我解释不出是什么原因,只能归结于SharpDX自身的原因了。 不过,我发现一个问题,写在这儿,给大家一个参考,也许谁能给出解决方案。(或者是我的设置有问题?) 在VB2010中,PngBitmapEncoder类的初始方法只能看到两个,New(Object)和New(IntPtr) 在C#2010中,PngBitmapEncoder类的初始方法能看到六个,除了上面的两个,还多了很多 打开SharpDX.Direct2D1.xml中也看到PngBitmapEncoder对象的初始方法有六个 难道SharpDX真的不能很好的运用于VB2010中么? 最后贴一段SharpDX中自带示例中的WIC保存图片的代码 using System; using System.IO; using SharpDX; using SharpDX.Direct2D1; using SharpDX.DXGI; using SharpDX.IO; using SharpDX.WIC; using AlphaMode = SharpDX.Direct2D1.AlphaMode; using Bitmap = SharpDX.WIC.Bitmap; using PixelFormat = SharpDX.Direct2D1.PixelFormat; namespace RenderToWicApp { internal static class Program { private static void Main() { var wicFactory = new ImagingFactory(); var d2dFactory = new SharpDX.Direct2D1.Factory(); string filename = "output.png"; const int width = 512; const int height = 512; var rectangleGeometry = new RoundedRectangleGeometry(d2dFactory, new RoundedRectangle() { RadiusX = 32, RadiusY = 32, Rect = new RectangleF(128, 128, width - 128 * 2, height-128 * 2) }); var wicBitmap = new Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad); var renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new PixelFormat(Format.Unknown, AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT); var d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties); var solidColorBrush = new SolidColorBrush(d2dRenderTarget, Color.White); d2dRenderTarget.BeginDraw(); d2dRenderTarget.Clear(Color.Black); d2dRenderTarget.FillGeometry(rectangleGeometry, solidColorBrush, null); d2dRenderTarget.EndDraw(); if (File.Exists(filename)) File.Delete(filename); var stream = new WICStream(wicFactory, filename, NativeFileAccess.Write); var encoder = new PngBitmapEncoder(wicFactory); encoder.Initialize(stream); var bitmapFrameEncode = new BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(width, height); var pixelFormatGuid = SharpDX.WIC.PixelFormat.FormatDontCare; bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid); bitmapFrameEncode.WriteSource(wicBitmap); bitmapFrameEncode.Commit(); encoder.Commit(); bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); System.Diagnostics.Process.Start(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory,filename))); } } }