|
2008年5月6日
#
1.为什么下水道的盖子是圆的?
2.中国有多少辆汽车?
3.将汽车钥匙插入车门,向哪个方向旋转就可以打开车锁?
4.如果你要去掉中国的34个省(含自治区、直辖市和港澳特区及台湾省)中的任何一个,你会去掉哪一个,为什么?
5.多少个加油站才能满足中国的所有汽车?
6.想象你站在镜子前,请问,为什么镜子中的影象可以颠倒左右,却不能颠倒上下?
7.为什么在任何旅馆里,你打开热水,热水都会瞬间倾泻而出?
8.你怎样将Excel的用法解释给你的奶奶听?
9.你怎样重新改进和设计一个ATM银行自动取款机?
10.如果你不得不重新学习一种新的计算机语言,你打算怎样着手来开始?
11.如果你的生涯规划中打算在5年内受到奖励,那获取该项奖励的动机是什么?观众是谁?
12.如果微软告诉你,我们打算投资五百万美元来启动你的投资计划,你将开始什么样商业计划?为什么?
13.如果你能够将全世界的电脑厂商集合在一个办公室里,然后告诉他们将被强迫做一件事,那件事将是什么?
2008年4月26日
#
这两天花了点时间把这个图表整了下,可以支持多数据子项绘制了,描述信息也得到了修正和加强,已经可以正式在项目中用了。
当然,数据源的绑定有点限制,必须是DataTable,这个还不是很通用。数据列要有要求,Y轴DataColumn要求是数值类型,X轴DataColumn要求是DataTime,而且为了图片美观,目前是写死的(单位:天),但相信需要用的人是可以修改搞定的。
Dopod P800 实现效果如下:
调用方式示例:
Jrong.DBChart dbChart1 = new Jrong.DBChart();
this. dbChart1.Location = new System.Drawing.Point(12, 12);
this.dbChart1.Size = new System.Drawing.Size(240, 268);
this.dbChart1.Name = "dbChart1";
this.Controls.Add(this.dbChart1);
----------------------------------------------------------------
this.dbChart1.Items.Clear();
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("罗湖区", Color.Gold, 2, "xzqhfdm like '03%'"));
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("福田区", Color.Maroon, 2, "xzqhfdm like '04%'"));
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("南山区", Color.Green, 2, "xzqhfdm like '05%'"));
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("宝安区", Color.Blue, 2, "xzqhfdm like '06%'"));
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("龙岗区", Color.Aqua, 2, "xzqhfdm like '07%'"));
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("盐田区", Color.DarkBlue, 2, "xzqhfdm like '08%'"));
this.dbChart1.Items.Add(new Jrong.DBChart.DBChartItem("光明新区", Color.Red, 2, "xzqhfdm like '02%'"));
----------------------------------------------------------------
this.dbChart1.X_Column = "sj";
this.dbChart1.Y_Column = "gyycount";
----------------------------------------------------------------
DataTable table = new DataTable();
table.Columns.Add("xzqhfdm", typeof(string));
table.Columns.Add("sj", typeof(DateTime));
table.Columns.Add("gyycount", typeof(int));
/* 添加 table 行值 */
----------------------------------------------------------------
this.dbChart1.IsUseDBTime = false; // 自定义起始时间,因为从数据库查询到的结果可能缺少某些天的值
this.dbChart1.StartTime = this.dateTimePicker_Start.Value.Date;
this.dbChart1.EndTime = this.dateTimePicker_End.Value.Date;
----------------------------------------------------------------
this.dbChart1.DataSource = table; // 关键是这一句,会直接导致图片的刷新,当然,不会马上执行
OK,大功告成,在运行上述代码后DBChart就会在OnPaint事件里生成统计图片了,如果不想显示,可以直接通过 DBChart.Image 获取图片,本人在WebService上通过该控件获取图片成功。
最后,当然是最实际的,源码下载:DBChart.rar
2008年4月24日
#
SELECT a.username,a.machine,a.program,a.sid,a.serial#, a.status,c.piece,c.sql_text
from v$session a,v$process b, v$sqltext c
WHERE b.spid='ORCL' AND b.addr=a.paddr AND a.sql_address=c.address(+)
order BY c.piece
我们就可以把得到的这个sql分析一下,看一下它的执行计划是否走索引,对其优化避免全表扫描,以减少IO等待,从而加快语句的执行速度。提示:我在做优化sql时,经常碰到使用in的语句,这时我们一定要用exists把它给换掉,因为Oracle在处理In时是按Or的方式做的,即使使用了索引也会很慢。
比如:
SELECT col1,col2,col3
FROM table1 a
WHERE a.col1 not in (SELECT col1 FROM table2)
可以换成:
SELECT col1,col2,col3
FROM table1 a
WHERE not exists (SELECT 'x' FROM table2 b WHERE a.col1=b.col1)
4、另一个有用的脚本:查找前十条性能差的sql。
SELECT * FROM (select PARSING_USER_ID,EXECUTIONS,SORTS,
COMMAND_TYPE,DISK_READS,sql_text FROM v$sqlarea
order BY disk_reads DESC )where ROWNUM<10 ;
二、迅速发现Oracle Server的性能问题的成因,我们可以求助于v$session_wait这个视图,看系统的这些session在等什么,使用了多少的IO。以下是我提供的参考脚本:
脚本说明:查看占io较大的正在运行的session。
SELECT se.sid,se.serial#,pr.SPID,se.username,se.status,
se.terminal,se.program,se.MODULE,、se.sql_address,st.event,st.
p1text,si.physical_reads, si.block_changes
FROM v$session se,v$session_wait st, v$sess_io si,v$process pr
WHERE st.sid=se.sid AND st. sid=si.sid AND se.PADDR=pr.ADDR AND se.sid>6 AND st. wait_time=0 AND st.event NOT LIKE '%SQL%'
ORDER BY physical_reads DESC
对检索出的结果的几点说明:
1、我是按每个正在等待的session已经发生的物理读排的序,因为它与实际的IO相关。
2、你可以看一下这些等待的进程都在忙什么,语句是否合理?
Select sql_address from v$session where sid=;
Select * from v$sqltext where address=; 字串7
执行以上两个语句便可以得到这个session的语句。你也以用alter system kill session 'sid,serial#';把这个session杀掉。
3、应观注一下event这列,这是我们调优的关键一列,下面对常出现的event做以简要的说明:
a、buffer busy waits,free buffer waits这两个参数所标识是dbwr是否够用的问题,与IO很大相关的,当v$session_wait中的free buffer wait的条目很小或没有的时侯,说明你的系统的dbwr进程决对够用,不用调整;free buffer wait的条目很多,你的系统感觉起来一定很慢,这时说明你的dbwr已经不够用了,它产生的wio已经成为你的数据库性能的瓶颈,这时的解决办法如下:
a.1增加写进程,同时要调整db_block_lru_latches参数。
示例:修改或添加如下两个参数
db_writer_processes=4
db_block_lru_latches=8
a、2开异步IO,IBM这方面简单得多,hp则麻烦一些,可以与Hp工程师联系。
b、db file sequential read,指的是顺序读,即全表扫描,这也是我们应该尽量减少的部分,解决方法就是使用索引、sql调优,同时可以增大db_file_multiblock_read_count这个参数。
oracle 可以在 v$sqlarea (v$sqltext)查询到已经和正在运行的sql
可以在v$open_cursor 中查到正open状态的cursor
可以通过 v$session join to v$sql 查到正在running 的session和sql
oracle可以提供给用户查看和诊断的信息远比你所能想象的多,对比oracle来说, mssql简直就是一个黑匣子
2008年4月23日
#
最近在做一个手机浏览器的客户端,最初以为一个浏览器的客户端不用考虑太多的内存使用,结果做完才发现在高端的手机上运行没有任何问题,在低端的手机上不是响应速度过慢,就是内存溢出。所以就开始对代码进行优化,在这个过程总结一些自己的经验,希望对有困惑的朋友有所帮助,有好的办法也希望大家共同探讨,zxhwolfe@hotmail.com
以下内容有些是自己实践所得,有些是参考高人经验或书本上的经验,如有不正确请立即指正;如果侵犯了他人版权请高台贵手,借鉴您的经验不是用于商业,只是希望大家共同进步请不要追究呵呵。
在写程序初期由于是面向midp2.0的手机而且不是游戏的开发,所以没有对性能方面做太多的考虑,大胆的使用了很多vector数组(使用起来方便:))等等,而且程序写的也是随心所欲,似乎不是在手机上开发j2me的东西。结果让我大跌眼镜,没办法只能重新优化,这期间可想而知浪费了很多时间,也使开发效率降低到了最低。说到这,只有一句话奉劝大家,不管你是开发什么样手机程序,一定要把性能放在第一位,不要重蹈我的覆辙。
我的几个vector存放的是链接的内容,文本框的内容,图片的内容和普通文本的内容,每个vector中包含的其他信息还有它所占的行数,它的位置和它的标志。我用线程控制paint(只要目的是实现持续按键的机制),这样的话,每次重绘都要把所有内容重新画到屏幕上,而且还要对当前焦点进行重绘。在重绘的过程中每一次都要遍历一遍几乎所有的vector然后重绘,这样肯定是浪费资源。结果也一样,在稍微低端一点手机上响应明显的慢。优化这样程序,我首先想到的就是把vector用别的方法替换掉,正常的性能使用是字符串-〉一维数组-〉二维数组->vector。一维数组肯定是替代不了我的vector了,那只能是使用二维数组了。费了好大劲把vector转换位二维数组,发现性能上并没有提升多少。大概只节省了20k左右的内存,只能再想别的办法。这里简单说下在手机上获得当前内存和剩余内存的方式:
long tempMin = 1000000;
long temp = Runtime.getRuntime().freeMemory();
if (tempMin > temp) {
tempMin = temp;
}
g.drawString("total = " + Runtime.getRuntime().totalMemory(), 10, 10, 0);
g.drawString("frees = " + temp, 10, 10 + lineHeight, 0);
g.drawString("hiegh = " + tempMin, 10, 10 + 2 * lineHeight, 0);
把这些东西画到你的画布上,在真机上运行的时候方便你查看内存的使用率。(每种机器的内存最大值是不同的)。
而且可以查看内存峰值。当然你也可以使用wtk自带的内存和方法查看器来判断。相关内容参考我的另外2篇文章:
J2ME性能优化之--方法和内存的评测:
/Article/Class2/200603/1650.html
J2ME性能优化之—优化方法探讨:
/Article/Class2/200603/1658.html
既然转换vector不能解决问题,那就继续优化。内存的主要使用看来是在每次重画的时候产生的,这样就要减少每次重画的内容,我采取的方式是把所有固定要重画的东西用双缓冲的方式画到一张图片上,这样只有初始化的时候才去遍历数组,经过一次的遍历把所有内容画到一张图片上,然后每一次的重画都是在重画一张图片。经过这样的处理性能上有了很大的提升。高兴还为时尚早,nokia的低端机器没有问题了,结果在moto的机器上出了问题,根本就不能初始化,也就是说创建那张图片的时候就应用程序错误了。继续查找原因,结果发现是因为moto的机器不支持创建一张那么大图片。也就是说你创建一张大图的时候,在moto的机器上根本就不能申请到内存。找到原因后,把大图分割为两个比较小的图,ok没有问题了。当然至于moto支持创建多大的图片可能每种机器不同吧,只能在需要的时候自己测试了。对于浏览器,一张分割为两张需要做些代码的处理。实际上为了性能的更加优化可以把一张大图分割为多张小图,每张小图的大小可以根据屏幕的几倍大小确定也可以根据机型固定。初始化的时候也可以先初始化一部分图。因人而异。
至此,程序的主要瓶颈已经找到,并且解决。正应了一句话,程序是花80%的时间在执行20%的代码。也就是说我们要把主要精力放在那20%的代码的优化上,但实际中我发现对另外80%代码的优化也很重要,主要是一些编程细节上的处理。在细节的代码书写上多注意些也有利于程序性能的提升。关于细节上觉得以下几个方面对程序性能的提升很有帮助。
首先系统垃圾回收的利用:关于堆内存(heap)与栈内存(stack)我们知道,heap存放的是对象实例与变量;而stack存放的是静态方法。堆内存在JVM启动的时候被创建,堆内存中所存储的对象可以被JVM自动回收。在这里,要手动把不用对象置为null,特别是较大的对象,如果不用一定要记得置为空。比如说较大的数组,vector或者是image对象。(切忌)在这里,浏览器中页面图片的读取我是采用的是后台读取,即先显示文字部分,而后后台读取页面中的图片,读取完成后再一起重新显示。重新显示的时候要重新构建那个双缓冲图片,而我当时就忘记了把原来创建的那个双缓冲图片置为null了,走了很多弯路才解决问题。所以要切忌至少把大的对象置空,不要指望垃圾回收。
其次是static的使用:静态变量在程序运行期间内存空间对所有该类的对象实例而言是共享的,即只在内存中保存一份拷贝,这样节约了不比要的内存开销。但是static生命周期较长,而且不容易被垃圾回收机制所回收,所以要合理运用,不要适得其反。建议在全部具备下列条件的情况下尽量使用静态变量:
1),变量所包含的对象体积较大,占用内存较多。
2),变量所包含的对象生命周期较长。
3),变量所包含的对象数据稳定。
4),该类的对象实例有对该变量所包含的对象的共享需求。
在我的程序中对静态变量的优化后,使程序占用内存量至少提升了5k-10k。所以也不容忽视。
还有就是String类相关的东西:1。字符串累加的时候一定要用StringBuffer的append方法,不要使用+操作符连接两个字符串。差别很大。而且在循环或某些重复执行的动作中不要去创建String对象,因为String对象是要用StringBuffer对象来处理的,一个String对象应该是产生了3个对象(大概是这样:))。
2,字符串length()方法来取得字符串长度的时候不要把length放到循环中,可以在循环外面对其取值。(包括vector的size方法)。特别是循环次数多的时候,尽量把length放到循环外面。
int size = xmlVector.size();
for (int i = 2; i < size; i++) {
。。。
}
在程序中我曾经误写了这样一句:if(i=5){...},编译器没有报错,而且结果好像是把i的值改变了,没有记清,大家有兴趣可以测验下。书写上尽量认真,否则查找bug的时候可能会折腾死人的。
关于优化方面也就能想起这些来了,如果还有对大家有用的东西我再补充吧,希望大家多提宝贵意见。共同进步嘛。
对代码进行优化的最简单办法就是首先不要调用这些代码。这并不是说要删除这些代码,也许可以用其他办法来调用它们(后者事实减少对它的调用)。游戏的主循环是游戏运行的最主要做的事情,应该更多地考虑是否可以不用或减少对属于这个区域内的代码的调用。在前一片文章中介绍了方法和内存评测工具的使用,但它们只能帮助我们找出究竟是哪段代码降低了程序的运行速度,下面的内容是参考了其他资料整理出来的优化代码的方法。
代码优化的技术大致分为两个主要方面:高级优化,从使用的整体算法和结构出发进行的优化;低级优化,集中于孤立的代码片断(通常为方法中的代码)的优化。下面分别讨论两方面的优化:
一,高级优化
1, 感觉到就是真实
对于电影来说,我们通过摄像头看到的都是完美的,而在拍摄现场我们看到的却是木头,泡沫和胶带。所以对于电影来说,感觉到就是真实。
游戏也一样,只需要处理游戏需要的东西。在游戏开发的各个方面这都是实用的。把精力集中在使游戏有趣和完美运行的问题上,始终只做需要做的而丢弃其他的部分。
2, 不要创建对象
减少对象创建的总数量和频率,结果能够大大地提高游戏的性能。还必须小心在不经意的情况下产生String对象。
例如:graphics.drawString( 0,0,”Score:” +score );
这一句代码会在每次被调用的时候产生一个新的String对象,在这里就是每一桢画面显示时都会产生新的String对象。因此最好是只是在分数改变的时候才构造这个String。
3, 绘制屏幕
通常,在对游戏完成大量的优化工作以后,收获的将是一个大量时间耗费在屏幕绘图上的游戏。这是因为一个游戏的主要时耗大都集中在绘制图像的工作上(或其他的一些基本的绘图调用)。因此,如果一开始就可以避免绘制工作,那将是对游戏的很好的优化。
还有就是要减少屏幕绘制,循环检测屏幕图像是否在某个部分发生了改变,如果没有,就不要对那部分的屏幕进行更新。另一个方法就是增加绘制图像的尺寸来减少单独的绘制调用的次数。
4, 算法
最好的,也是使用最多的高级优化是对游戏的算法方面。
二,低级优化
1, 提前绘制复杂图像
我们已经知道,使用LCDUI绘制图像是很慢的,因此最好是能够避免这种绘制。其中的一个方法就是用一个预生成图像来减少复杂图像的绘制。进一步来讲,举例:将所有的游戏状态信息整合到一个面板中(得分,生命数,能量值等),然后对这些信息进行一次性同时更新。
2, 保持类和内存之间的平衡
产生新的类会增加JAR包文件的大小,因此应该尽量避免。有的时候增加了额外类的开销可能节省了额外的内存开销,这也是值得的。
3, 复杂值的预计算
节省运算的一个好方法就是对数值进行预运算,从而无需再调用大开销的计算方法。一个很好的例子就是:主窗口画布的高度和宽度就是很好的 缓存对象。例如:可以调用getHeight方法和getWidth方法一次,然后将它们的结果缓存起来,而不是在每一次绘图中都调用这两种方法。
4, 使用数组
在任何时候,只要可能,都应该使用数组而不是Vector,因为数组的运行速度更快。通常面临的唯一问题是,如果最初分配的数组空间不够大,将需要对数组的大小进行扩充。这可以做到,但它需要对整个数组进行重建。例如:
Public final static int[ ] expandArray(int [] oldArray, int expandBy)
{
int [ ] newArray = new int [oldArray.length + expandBy];
System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
Return newArray;
}
任何时候,都应该尽量使用一维数组。访问二维数组变量的速度只有访问一维数组变量的一半。当然,仍然可以访问二维数组的对象,只是需要加入一点点计算。例如,与其使用这条语句:
world[y][x] = 0;
不如下面这条语句运行的快:
world[y*tilesWide + x] = 0;
这条语句通过行列的位置将数值转换成一维值,实现了对数组同一元素的访问。
5, 不要使用数组
呵呵,尽管数组的访问比Vector快,但仍然比直接访问变量要慢,因此如果可能就应该删除对数组的访问,或者为一些常用方法中的数组寻求其他能提高性能的办法。
6, 使用快速方法
并不是所有Java调用的方法在性能上都是相同的,方法声明方式的不同对性能会会产生很多的影响。可以使用的最快的方法类型是静态方法,因此应该尽可能多地将代码置于静态调用方法中。运行速度仅次于静态方法的是声明为final的方法。运行最慢的两种方法是在接口中定义的方法和用关键字synchronized声明的方法,必须尽可能地避免使用这些类型的方法。
7, 其他优化
1)异常处理非常缓慢,不要为一半的游戏逻辑使用异常,只用它们来报告真正的错误状态。
2)使用switch表达式比使用if条件语句块的速度要快。
3)尽可能避免使用String对象进行运算,使用StringBuffer。
4)内嵌类的运行很慢,尽可能避免使用。
5)在完成一个引用的使用后将它设为null。
6)不要浪费时间来将一个对象初始化为null或0,java虚拟机会替我们完成这样的初始化
7)多思考新方法,这会使我们的大脑运转的更快。
8)如果可能,尽量使用static,它们运行都很快。它同时适用于方法和域,这条规则就是,如果它可以是静态的,那么就把它声明为静态的。
9)避免类型转换。
10)程序优化的时候要有所取舍,要多捉摸了。大家有什么好的建议?一起来壮大吧。
共同探讨:zxhwolfe@hotmail.com
附:关于j2me程序的调试
使用eclipseME+WTK2.1进行J2ME应用程序调试(debug)-- 引用mingjava的帖子。
选择windows->preferences->java->debug 不要选择suspend execution的前面两个选项,在debuger timeout选项中 第一个时间至少设置为15000ms 这样就可以调试了。
2008年4月21日
#
漫漫长夜,闲来无事,绘制一图,有好事者可以效仿之。
最终运行平台:Dopod P800,效果良好,速度也快。
代码下载: ChartDemo.rar
如果有更好的建议或意见,欢迎拍砖。
2008年4月17日
#
今天,微软发布了其免费游戏开发工具的最新正式版“XNA Game Studio 2.0”,可以更轻松地开发Windows和Xbox 360游戏;同时微软还放出了相应的分发支持包“XNA Framework Redistributable 2.0”,用以执行游戏。
微软称,借助经过优化的跨平台.NET游戏库,业余和专业游戏开发人员都能轻松掌握XNA Game Studio 2.0,并为Windows PC和Xbox 360主机开发各种视频游戏。
XNA Game Studio 2.0在性能上将有大幅提升,并带来了不少新功能,如拓展支持Visual Studio 2005、支持网络和多人游戏制作、加入XNA Game Studio设备中心、简化与Xbox 360的连接、改进内容流程体验,等等。
XNA Game Studio 2.0支持Windows XP SP2和Windows Vista系统,硬件需求与Visual Studio 2005相同,另外还要一块支持DX9.0c、SM2.0的显卡。如果使用微软跨平台音频创作工具XACT,则还需安装.NET Framework 1.1。
XNA Game Studio程序本身是免费的,发布创作的PC游戏也没有限制,但如果想发布Xbox 360游戏,就要加入XNA Creators Club俱乐部,年费99美元,试用4个月49美元。
XNA Framework Redistributable 2.0提供了必要的运行时组件,用于在Windows上执行由XNA Game Studio 2.0开发的游戏。新版改进了一些功能,也增加了一些新特性。
点击下载XNA Game Studio 2.0(98.6MB)
点击下载XNA Framework Redistributable 2.0(2.1MB)
两个重要网站:http://www.xna.com/ 和 http://www.xnadev.cn/
2008年4月2日
#
你是否曾有如此困扰?想将甲电脑制作的文件拿到乙电脑列印,但问题是乙电脑无法开启该档,或缺乏所需字型,偏偏又不便于乙电脑安装所需软体或字型。即使可以,也颇费周章。因为也许你只要列印这么一次而已,或乙电脑有系统即时还原功能等等,小软体还好,大软体就十分不便。
也许你会先转换成PDF档来列印,这的确可解决问题,但并非是最佳的解决之道(或说不是唯一的解决之道),因为PDF档与原档难以完全一致(有时候),且列印出来的效果也不如预期(有时候)。但你可以有更好的选择(或说另一个选择)。
解决之道,就是将文件列印成PRN文件。
列印成PRN文件有几个注意事项:
一、应用软体列印成PRN文件时,会根据选择的打印机的“驱动程序语言”来构成PRN文件的“语言”,以制作出PRN文件,因此选择的打印机最好就是实际打印时的打印机。因为不同厂牌的打印机,其“驱动程序语言”可能不同,而同厂牌、不同型号的打印机,也可能会有些许不同,PRN文件的构成“语言”与实际打印机所接受的“驱动程序语言”不一致就无法成功列印,所以要在甲电脑安装乙电脑打印机的驱动程序。
二、列印时在列印对话方块勾选“输出至文件”,如果软体未提供此功能,则将此打印机连接埠改成“FILE:(在磁碟建立文件)”即可。
如此一来,你应该可以顺利地列印出PRN文件了。
下一步就是将此PRN文件置于乙电脑上,PRN文件通常是比较大的,但这应该不是问题。
接下来的问题是PRN文件如何列印至打印机,比较方便的方法,就是用SendFileToPrinter这个仅27KB的免安装小工具。(还有一种方法是利用Windows本身的cmd命令行)。如图示,运行此工具,或将PRN文件拖曳到SendFileToPrinter里,然后选择正确的打印机列印,列印结果将呈现完美的一致性。
※DownloadSendToPrinterv1.00(15Kzipfile)-lastupdated2/8/2000

不再需要大费周章地安装许多东西,只要安装SendFileToPrinter就够了,这也比安装AcrobatReader(或其他软体)更有效率。安装打印机驱动程序来列印PRN文件,也比安装Acrobat(或其他软体)来列印PDF档快速而经济。但更重要的是品质。
这个方法也可以解决同一份文件档在不同电脑开启时所产生的版面不一致的问题,假如你只是为了要在不同的电脑列印的话。
有此需求的人可能不多,但愿能帮助有此需求的人。
以上所述若有错误,敬请不吝指教,感谢!
【注1:prn文件】
Windows提供了一项非常实用的打印到文件功能,即用户在执行打印操作时不直接将数据发送到打印机中进行打印,而是采用专用的*.PRN文件形式保存到硬盘上。.prn文件是并不是一个固定的格式,实际上是由打印机的打印命令组成的,因此,不同的打印机驱动产生的文件不同。这个文件一般无法阅读或转换为其他格式。
【注2:打印prn文件】
对于本地打印机,可以进入cmd命令行,copyabc.prnlpt1/b或copyabc.prnprn/b进行打印。而对于网络打印机(好象又有2种,一是装在其他计算机上,一是打印机有独立IP),此方式则不能直接运用。网上有些解决办法,但xbeta未测试成功(我的打印机有独立IP)。建议用本文中的小工具。
2008年3月29日
#
2008年3月21日
#
今天无聊翻代码,翻出来一个以前写的C#截屏的函数...拿出来和大家共享一下.
这段代码是参照网上一段截屏的C++代码改写的.只不过把API都声明了一下而已.
声明的各API也附后.以供参照.如有问题欢迎指出.(Appledotnet@hotmail.com)
///
/// 截取部分屏幕
///
/// 左上角
/// 右下角
/// 是否全屏幕
/// 返回值Bitmap
public static Bitmap GetPartScreen(Point P1,Point P2,bool Full)
{
IntPtr hscrdc,hmemdc;
IntPtr hbitmap,holdbitmap;
int nx,ny,nx2,ny2;
nx=ny=nx2=ny2=0;
int nwidth, nheight;
int xscrn, yscrn;
hscrdc = CreateDC("DISPLAY", null, null, 0);//创建DC句柄
hmemdc = CreateCompatibleDC(hscrdc);//创建一个内存DC
xscrn = GetDeviceCaps(hscrdc, GetDeviceCapsIndex.HORZRES);//获取屏幕宽度
yscrn = GetDeviceCaps(hscrdc, GetDeviceCapsIndex.VERTRES);//获取屏幕高度
if(Full)//如果是截取整个屏幕
{
nx = 0;
ny = 0;
nx2 = xscrn;
ny2 = yscrn;
}
else
{
nx = P1.X;
ny = P1.Y;
nx2 =P2.X;
ny2 =P2.Y;
//检查数值合法性
if(nx<0)nx = 0;
if(ny<0)ny = 0;
if(nx2>xscrn)nx2 = xscrn;
if(ny2>yscrn)ny2 = yscrn;
}
nwidth = nx2 - nx;//截取范围的宽度
nheight = ny2 - ny;//截取范围的高度
hbitmap = CreateCompatibleBitmap(hscrdc, nwidth, nheight);//从内存DC复制到hbitmap句柄
holdbitmap = SelectObject(hmemdc, hbitmap);
BitBlt(hmemdc, 0, 0, nwidth, nheight,hscrdc, nx, ny,(UInt32)0xcc0020);
hbitmap = SelectObject(hmemdc, holdbitmap);
DeleteDC(hscrdc);//删除用过的对象
DeleteDC(hmemdc);//删除用过的对象
return Bitmap.FromHbitmap(hbitmap);//用Bitmap.FromHbitmap从hbitmap返回Bitmap
}
所用到的API声明:
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDC(
string lpszDriver, // driver name
string lpszDevice, // device name
string lpszOutput, // not used; should be NULL
Int64 lpInitData // optional printer data
);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(
IntPtr hdc // handle to DC
);
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(
IntPtr hdc, // handle to DC
GetDeviceCapsIndex nIndex // index of capability
);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(
IntPtr hdc, // handle to DC
int nWidth, // width of bitmap, in pixels
int nHeight // height of bitmap, in pixels
);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(
IntPtr hdc, // handle to DC
IntPtr hgdiobj // handle to object
);
[DllImport("gdi32.dll")]
public static extern int BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
UInt32 dwRop // raster operation code
);
[DllImport("gdi32.dll")]
public static extern int DeleteDC(
IntPtr hdc // handle to DC
);
|