﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-cyantree's home</title><link>http://www.cppblog.com/cyantree/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 21 Mar 2010 11:38:38 GMT</lastBuildDate><pubDate>Sun, 21 Mar 2010 11:38:38 GMT</pubDate><ttl>60</ttl><item><title>讨论fltk的qq群</title><link>http://www.cppblog.com/cyantree/archive/2007/01/28/18117.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Sun, 28 Jan 2007 10:43:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2007/01/28/18117.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/18117.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2007/01/28/18117.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/18117.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/18117.html</trackback:ping><description><![CDATA[群号：32425450<br /><br />欢迎对fltk有兴趣的开发人员加入<img src ="http://www.cppblog.com/cyantree/aggbug/18117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2007-01-28 18:43 <a href="http://www.cppblog.com/cyantree/archive/2007/01/28/18117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fltk在windows上的一个小bug</title><link>http://www.cppblog.com/cyantree/archive/2007/01/23/17934.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Tue, 23 Jan 2007 11:43:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2007/01/23/17934.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/17934.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2007/01/23/17934.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/17934.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/17934.html</trackback:ping><description><![CDATA[
  描述：<br />在windows下创建一个resizable window，最大化的时候会出错，窗口的最下方实际上并没有和任务栏靠在一起，而且如果任务栏很高，那更是奇怪，窗口会超出任务栏<br /><br />原因：<br />怀疑实现部分并非是由系统处理，而且自己处理了这个事件，没有去看代码，暂时存疑<br /><br />解决：<br />无。只有找到源代码的实现部分才知道怎么修改了<img src ="http://www.cppblog.com/cyantree/aggbug/17934.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2007-01-23 19:43 <a href="http://www.cppblog.com/cyantree/archive/2007/01/23/17934.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fltk2更新简介</title><link>http://www.cppblog.com/cyantree/archive/2007/01/23/17933.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Tue, 23 Jan 2007 11:42:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2007/01/23/17933.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/17933.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2007/01/23/17933.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/17933.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/17933.html</trackback:ping><description><![CDATA[不久前fltk终于释出可以实用的2.0版本，目前的具体版本是2.0.x-r5556，让我们看看具体的更新和变动<br /><br />首先是字体
的巨大改进，开始支持utf8，所以在linux下汉字无法显示和输入法无法输入的问题已经彻底解决，但同时也带来一些问题，就是在代码内必须使用
utf8的汉字才能正确显示在界面上，但是unicode的编辑器又不是那么好找，再说在windows下开发的话一般都会使用vc，而在vc下输入
unicode是一件有困难的事情，至少我没有找到好的插件，所以需要一个解决办法，那就是<fltk>里的函数，帮助文档里没 有说的很清楚，但是大体上还是可以猜到意思的<br /><br />修
改了class
Browser，变成了一个tree，在1.0中想显示一个grid或者listview一直只能自己处理，现在不用了，这个Browser还算可以，提
供了基本的功能，稍微还有一些扩充，如果想再丰富一些就只有自己继承了，反正fltk的宗旨就是自己动手丰衣足食。<br /><br />Opengl的功能貌似有一些修正，但是我没有用到，而且demo中关于OpenGL的例子还没有提供，所以目前情况未知<br /><br />帮助文档未完善，而且代码中附带的帮助无法使用，所以很多时候还是查1.0的帮助以及看源代码更加有效一些<br /><br />所 有的头文件和类名全部去除了FL_，引入了namespace，好处是类看起来更清楚了，坏处是从1.0的代码升级变得很麻烦。</fltk>头文件从&lt;FL/FL_XXXX.H&gt;变成&lt;fltk/xxxx.h&gt;<fltk><fltk>，全部变成了小写，而且去掉了FL_，同时目录也变成fltk/了，这些细 节稍微用一段时间就会习惯，一开始会造成一些问题，虽然在fltk目录下也保留了一些兼容的头文件，但是建议还是不要用，因为不全，而且迟早要换的， 何必不一步到位？<br /><br />对编译器支持的更全，目前支持vc6,vc.net,devcpp,gcc,Code::Blocks,bc5，基本囊括了流行的C/C++编译器<br /><br />支持整体theme，可以一次性设置当前界面的theme<br /><br />打算引入一个叫cairo的库，具体作用好像是用于矢量运算的，属于第三方的代码，在fltk的站点上关于这个有一个投票，大多数人还是拒绝在fltk中加入外来插件，都觉得应该保持fltk的轻量快速的特征<br /><br />待续.....</fltk></fltk><img src ="http://www.cppblog.com/cyantree/aggbug/17933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2007-01-23 19:42 <a href="http://www.cppblog.com/cyantree/archive/2007/01/23/17933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>class的沼泽地</title><link>http://www.cppblog.com/cyantree/archive/2006/10/19/13885.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Thu, 19 Oct 2006 13:15:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/10/19/13885.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/13885.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/10/19/13885.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/13885.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/13885.html</trackback:ping><description><![CDATA[
    　　先看这个文章，“最小接口”：<br /><a href="http://blog.csdn.net/mfowler/archive/2006/10/19/1340364.aspx" title="http://blog.csdn.net/mfowler/archive/2006/10/19/1340364.aspx" target="_blank">http://blog.csdn.net/mfowler/archive/2006/10/19/1340364.aspx</a><br /><br />　
　Martin
Fowler的确是oo的大师，对类的理解和解析的确很深入，但是我还是想表述一些不同的意见。对于class而言，越强大就会越臃肿，越简单就会越零
碎，这是不可避免的问题。对于一个足够复杂的系统，class简单了不行，太散，最后的组装成本会相对过高，复杂了也不行，复用和维护的成本也很高。而且
这两种都会造成中间层的脂肪过剩，虽然所有讲oo的书都会说过度复杂的中间层不好，但是没有哪本书提出了很好的解决办法，似乎归结到最后就只有依靠开发者
本身了。这种情况其实很是可怕，面对目前的开发现状，很多系统对复用的渴求会越来越明显，但是老系统中到底有多少模块可以无缝移植，只怕没有人能说清楚。
而且随着需求的变化，老系统的维护和升级也越来越成为一个巨大的负担，重写是最常见的最终武器，但这武器所带来的损耗和浪费也是相当惊人的。<br /><br />　
　其实问题的核心是：如何在复杂度和可读性之间寻求最佳的平衡。人的脑容量是有限的和有差异的，不同的开发者对复杂度的衡量标准是不一样的。一个确定的模
块，对某些人而言是容易理解和消化的，但对另外的人而言却复杂的无法吞咽，这是现实问题，并不是通过培训和努力就能消除的。不同的行业和不同的开发方向，
一定会造成不同的理解范围和理解方式，也就造成不同的开发者之间会存在必然的差异。只要这种差异存在，之前所述的问题就一定存在。<br /><br />　　问
题不可怕，可怕的是不敢去面对。真的勇士，敢于直面惨淡的人生;-)
个人看法，胶合层是一定要减肥的，但是如何减是一个问题。对于一个oo构架的系统，胶合层是一定存在的，如何做薄做小是个关键，同时薄和小的标准也是因人
而异的。起码有一点我很肯定，胶合层的复用性是很差的，甚至可以说根本没有复用的可能，那么很简单，一个系统中只创建一个胶合层，尽量将特定的需求和无法
复用的部分整合进来，同时随时做好丢弃的准备，一旦需要开发新系统或者需要升级系统，胶合层就成为第一个被牺牲的对象，如果设计的好，就有可能是唯一需要
丢弃的部分，这样起码可以保证智力投资最大限度的保值。<br /><br />　　模块(class，接口，函数，随便你怎么定义它)的复用性如何，决定了它的
生存时间，也直接反应了开发者的能力，如何确保复用性是个老生常谈的话题了，但我还是要啰嗦两句。复用性好并不代表强大和复杂，为了追求一个万能模块而编
写足够复杂的模块，纯属浪费时间和精力，简单是保证良好复用性的前提，一个复杂的模块是不能指望有多少复用性的。同时，简单并非是简化，一个无法完成分内
工作的模块是残次品，是不能称之为具有复用性的。基于之前的论述，如何算是简单对于不同的开发者而言又是各不相同的，这需要开发者从别人的角度考虑和长时
间的自我衡量，复杂了不行，学习难度太高，简单了不行，会降低模块的灵活性。曾经看过一段话：好的界面就是一眼看过去，需要的功能都在，没有什么复杂的存
在，但是需要深入控制的时候，该有的也都能找的到。挪到我们的问题上，也就差不多是这个意思了。这很难，但就是因为难，也就同时创造了乐趣，做为一个开发
者，当以这种困难为敌手，图穷匕首现，五步溅血.....<br /><br />2006-10-19 18:57<img src ="http://www.cppblog.com/cyantree/aggbug/13885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-10-19 21:15 <a href="http://www.cppblog.com/cyantree/archive/2006/10/19/13885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两个bt聊天</title><link>http://www.cppblog.com/cyantree/archive/2006/07/06/9511.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Thu, 06 Jul 2006 15:20:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/07/06/9511.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/9511.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/07/06/9511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/9511.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/9511.html</trackback:ping><description><![CDATA[
		<p style="text-align: left;">
    伟大的progame 11:30:40<br />我又在看我2年多前的代码 向自己学习 <br />伟大的progame 11:30:50<br />原来我处在一个极端 现在在另一个极端 <br />量大的老鸨 11:32:14<br />我3年前的代码，只能形容为：不忍卒读 <br />量大的老鸨 11:32:43<br />现在的代码，可以很公正的说：垃圾 <br />伟大的progame 11:33:07<br />我原来走标准的三层 com+ businessobject  <br />伟大的progame 11:34:15<br />现在是framework + xml  <br />伟大的progame 11:34:28<br />接下来要中和了 <br />伟大的progame 11:34:31<br />两个都是极端 <br />老渔翁 11:34:57<br />标准的三层是垃圾。 <br />量大的老鸨 11:37:01<br />我以前是标准的万物皆类，一个小小的接口都要用类来包裹一番，结果累的不行 <br />量大的老鸨 11:38:05<br />现在终于幡然悔悟，明白鸟手中无刀，心中有刀的真谛，所谓放下屠刀，立地成佛啊..... <br />伟大的progame 11:38:33<br />你不明白 你没有涉及到复杂多变的业务 <br />量大的老鸨 11:39:30<br />以史为鉴，展望未来，我们的目标是飞花摘叶，皆可伤人，要做到手中无刀，心中也无刀..... <br />  乌鸦 11:39:50<br />粒度看自己把握 <br />量大的老鸨 11:40:05<br />我坚持认为，复杂的需求未必一定带来复杂的实现 <br />老渔翁 11:40:36<br />我一直用成熟的技术，不用最先进的技术。 <br />  乌鸦 11:40:44<br />复杂的实现必带来不稳定 <br />量大的老鸨 11:40:53<br />葵花宝典为什么那么nb？化繁为简，一根绣花针就搞定一切啊 <br />老渔翁 11:40:57<br />这是为什么很多国家不修磁悬浮的原因。 <br />  乌鸦 11:41:10<br />复杂的东西必带来不可靠 <br />量大的老鸨 11:41:46<br />再看独孤九剑，关键就在一个破字 <br />  乌鸦 11:42:02<br />以前是数据库,非要怎么设计 <br />  乌鸦 11:42:15<br />现在是类 <br />  乌鸦 11:42:23<br />然后又是层 <br />量大的老鸨 11:42:34<br />所谓九贱齐出，群处可破..... <br />伟大的progame 11:43:41<br />没说实现要复杂 <br />伟大的progame 11:43:53<br />但是你如何有一个灵活的东西去面对多变的业务呢 <br />伟大的progame 11:44:08<br />最后发现 事实上是很难面对的 <br />量大的老鸨 11:44:09<br />要灵活，就要简单 <br />伟大的progame 11:44:32<br />想一个东西通吃不同的业务是不现实的 <br />  乌鸦 11:44:33<br />很多业务其实实现的代价远远大于维护的代价 <br />  乌鸦 11:44:43<br />所以这个业务实际上是错的 <br />量大的老鸨 11:44:44<br />越内敛，越通用 <br />伟大的progame 11:44:48<br />首选是业务模型的建立 <br />伟大的progame 11:45:01<br />这不比软件架构的设计简单 <br />量大的老鸨 11:45:06<br />所谓浓缩的就是精华 <br />量大的老鸨 11:45:49<br />个人经验：要从人的角度考虑，就可以避免一些不必要的复杂 <br />量大的老鸨 11:46:48<br />几乎所有的windows程序都有搜索，但你看linux的做法，find+grep搞定一切 <br />伟大的progame 11:46:50<br />你不精通业务 再怎么设计 都可能走入死角 <br />量大的老鸨 11:47:17<br />业务为人而存在 <br />伟大的progame 11:47:32<br />业务第一 软件第二 <br />量大的老鸨 11:47:48<br />人第一，业务第二，软件第三 <br />量大的老鸨 11:48:26<br />表认为客户都是笨蛋，其实当你愿意教他的时候，客户会比你想像的聪明 <br />伟大的progame 11:48:49<br />你从每个人的想法出发是错误的 因为即使是一个客户 在它的内部也是有大量的冲突 <br />伟大的progame 11:49:00<br />操作和管理层 市场和售后服务 <br />伟大的progame 11:49:12<br />他们的出发点是不同的 出来的东西是矛盾的 <br />量大的老鸨 11:49:17<br />冲突是一定的，而且一定会造成矛盾的需求 <br />伟大的progame 11:49:26<br />你如果精通业务 有成功案例 <br />伟大的progame 11:49:33<br />那么好办了 这时才可以指导它 <br />量大的老鸨 11:49:50<br />在这个时候，可以给出一个二义性的解决方案，有何不可？ <br />伟大的progame 11:49:58<br />不会因为你的软件多么多么地灵活 多么多么地先进 你才有资格指导它 <br />伟大的progame 11:50:23<br />那么你的软件最后给他们是带来问题 <br />伟大的progame 11:50:27<br />而不是解决问题 <br />量大的老鸨 11:50:37<br />解决问题的核心是解决人 <br />专弹金属的JJ 11:50:43<br />因为人本身，就是一个问题！ <br />量大的老鸨 11:50:44<br />而不是事情 <br />伟大的progame 11:50:53<br />精通业务 成功案例 这是顺利实施的不二法门 <br />伟大的progame 11:51:59<br />其它都是扯蛋 跟客户说技术先进 负载量 可伸缩性 跨平台 节约成本 最后都会因为流程无法顺利走通而完蛋 <br />量大的老鸨 11:52:21<br />我没有做过数据库应用，所以只能从我的经验进行推论，未必正确，但是（我恨这个词），一些原理也许可以通用 <br />伟大的progame 11:52:21<br />老梦你做的是提供功能性的东西  功能有了 就OK了 <br />伟大的progame 11:52:30<br />我做的是业务流程的东西 <br />伟大的progame 11:52:40<br />流程才是最重要的 <br />量大的老鸨 11:52:54<br />流程走不通，可以变通 <br />量大的老鸨 11:53:03<br />变通的基点就是人 <br />伟大的progame 11:53:16<br />客户不是要你拿他来当实验品 <br />量大的老鸨 11:53:23<br />否则就不能转化为最终实现 <br />量大的老鸨 11:53:49<br />客户是上帝，是猪，是畜生 <br />量大的老鸨 11:54:08<br />当一回试验品也没关系 <br />量大的老鸨 11:54:43<br />要敢于摸着mimi找mm <br />量大的老鸨 11:54:58<br />只要爽就可以 <br />伟大的progame 11:55:17<br />所以没办法 只好牺牲几个试验品了 <br />伟大的progame 11:55:25<br />代价就是被客户骂 <br />量大的老鸨 11:55:32<br />没人敢说他的模型是万能的，他的流程是通用的 <br />量大的老鸨 11:56:09<br />如果能做到尽量灵活，也能做到无限接近正确 <br />量大的老鸨 11:56:52<br />写的再多，不如抓住核心 <br />伟大的progame 11:57:21<br />我现在就是想 用底层的东西 能够大大节省开发时间 这样 无需开发通用产品 而是快速开发多个产品  <br />量大的老鸨 11:58:22<br />也许我更粗暴，我想用进程＋灵活的接口方式，提供一劳永逸的模块，将来的事情就是组装 <br />量大的老鸨 11:58:57<br />没有胶合层，拒绝转发 <br />量大的老鸨 11:59:16<br />界面都可以抛弃，只有功能永存 <br />量大的老鸨 12:00:24<br />所谓的框架、模型、接口，最终的目标是功能，如果带来的附加部分远超过实际所需，那么再先进也是废物 <br />量大的老鸨 12:01:05<br />最极端的例子就是java的那些狗屁框架，也不知道是为什么样的脑袋而准备的 <br />量大的老鸨 12:01:43<br />我只要一杯水，却给我送上来一个净水处理工厂</p>
		<p style="text-align: left;"> <br /></p>2006-06-29 http://www.heybrain.com 首发<br /><img src ="http://www.cppblog.com/cyantree/aggbug/9511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-07-06 23:20 <a href="http://www.cppblog.com/cyantree/archive/2006/07/06/9511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跨平台的鼠标移动源代码</title><link>http://www.cppblog.com/cyantree/archive/2006/05/31/7930.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Wed, 31 May 2006 05:22:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/05/31/7930.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/7930.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/05/31/7930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/7930.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/7930.html</trackback:ping><description><![CDATA[
		<div class="textbox-content">
				<p>#include &lt; stdio.h &gt;<br />#include &lt; stdlib.h &gt;<br />#include &lt; string.h &gt;</p>
				<p>#ifdef WIN32<br />#include &lt; windows.h &gt;<br />#else<br />#include &lt; unistd.h &gt;<br />#include &lt; X11/X.h &gt;<br />#include &lt; X11/Xlib.h &gt;<br />#endif</p>
				<p>int main(int argc, char* argv[])<br />{<br />    char sx[10], sy[10];<br />    int x, y;</p>
				<p>    if ( argc &lt; 3 ) return 0;<br />    strcpy(sx, argv[1]);<br />    strcpy(sy, argv[2]);<br />    x = atoi(sx);<br />    y = atoi(sy);</p>
				<p>#ifdef WIN32<br />    SetCursorPos(x, y);<br />#else<br />    Display *dpy;<br />    Window rootwindow;</p>
				<p>    dpy = XOpenDisplay(NULL);<br />    if ( ! dpy ) {<br />        printf("Couldn't open Xdisplay.\n");<br />        exit(1);<br />    }<br />    rootwindow = DefaultRootWindow(dpy);</p>
				<p>    XWarpPointer(dpy, rootwindow, rootwindow, 0, 0, 0, 0, x, y);</p>
				<p>    XCloseDisplay(dpy);<br />#endif<br />    return 0;<br />}</p>
				<p>
						<br />
				</p>
		</div>
<img src ="http://www.cppblog.com/cyantree/aggbug/7930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-05-31 13:22 <a href="http://www.cppblog.com/cyantree/archive/2006/05/31/7930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跨平台的INI处理源代码</title><link>http://www.cppblog.com/cyantree/archive/2006/05/31/7929.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Wed, 31 May 2006 05:20:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/05/31/7929.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/7929.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/05/31/7929.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/7929.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/7929.html</trackback:ping><description><![CDATA[// IniFile.h<br /><br />#ifndef INIFILE_H<br />#define INIFILE_H<br /><br />#include &lt; stdio.h &gt;<br />#include &lt; stdlib.h &gt;<br />#include &lt; string.h &gt;<br /><br />#ifndef OWP_DONT_DEF_FALSE<br />#ifndef FALSE<br />#define FALSE 0<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_TRUE<br />#ifndef TRUE<br />#define TRUE 1<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_BOOL<br />#ifndef BOOL<br />#define BOOL unsigned int<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_CCHR<br />#ifndef CCHR<br />#define CCHR const char<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_UCHR<br />#ifndef UCHR<br />#define UCHR unsigned char<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_UCCHR<br />#ifndef UCCHR<br />#define UCCHR const unsigned char<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_UINT<br />#ifndef UINT<br />#define UINT unsigned int<br />#endif<br />#endif<br /><br />#ifndef OWP_DONT_DEF_WORD<br />#ifndef WORD<br />#define WORD unsigned short<br />#endif<br />#endif<br /><br />#ifdef LINUX /* Remove CR, on unix systems. */<br />#define INI_REMOVE_CR<br />#define DONT_HAVE_STRUPR<br />#endif<br /><br />#define tpNULL       0<br />#define tpSECTION    1<br />#define tpKEYVALUE   2<br />#define tpCOMMENT    3<br /><br />struct ENTRY<br />{<br />   char   Type;<br />   char  *pText;<br />   struct ENTRY *pPrev;<br />   struct ENTRY *pNext;<br />};<br /><br />typedef struct<br />{<br />   struct ENTRY *pSec;<br />   struct ENTRY *pKey;<br />   char          KeyText [128];<br />   char          ValText [128];<br />   char          Comment [255];<br />} EFIND;<br /><br />/* Macros */<br />#define ArePtrValid(Sec,Key,Val) ((Sec!=NULL)&amp;&amp;(Key!=NULL)&amp;&amp;(Val!=NULL))<br /><br />class CIniFile<br />{<br />public:<br />    CIniFile    (void)<br />  {<br />    m_pEntry      = NULL;<br />    m_pCurEntry   = NULL;<br />    m_result [0]  = 0;<br />    m_pIniFile    = NULL;<br />  }<br /><br />  ~CIniFile   (void)<br />  {<br />    FreeAllMem ();<br />  }<br /><br />    BOOL    OpenIniFile (CCHR *pFileName)<br />  {<br />    char   Str [255];<br />    char   *pStr;<br />    struct ENTRY *pEntry;<br />    <br />    FreeAllMem ();<br />    <br />    if (pFileName == NULL)                             { return FALSE; }<br />    if ((m_pIniFile = fopen (pFileName, "r")) == NULL) { return FALSE; }<br />    <br />    while (fgets (Str, 255, m_pIniFile) != NULL) {<br />      pStr = strchr (Str, '\n');<br />      if (pStr != NULL) { *pStr = 0; }<br />      pEntry = MakeNewEntry ();<br />      if (pEntry == NULL) { return FALSE; }<br />      <br />      #ifdef INI_REMOVE_CR<br />      Len = strlen(Str);<br />      if ( Len &gt; 0 ) {<br />        if ( Str[Len-1] == '\r' ) {<br />          Str[Len-1] = '\0';<br />        }<br />      }<br />      #endif<br />      <br />      pEntry-&gt;pText = (char *)malloc (strlen (Str)+1);<br />      if (pEntry-&gt;pText == NULL) {<br />        FreeAllMem ();<br />        return FALSE;<br />      }<br />      strcpy (pEntry-&gt;pText, Str);<br />      pStr = strchr (Str,';');<br />      if (pStr != NULL) { *pStr = 0; } /* Cut all comments */<br />      if ( (strstr (Str, "[") &gt; 0) &amp;&amp; (strstr (Str, "]") &gt; 0) ) /* Is Section */ {<br />        pEntry-&gt;Type = tpSECTION;<br />      } else {<br />        if (strstr (Str, "=") &gt; 0) {<br />          pEntry-&gt;Type = tpKEYVALUE;<br />        } else {<br />          pEntry-&gt;Type = tpCOMMENT;<br />        }<br />      }<br />      m_pCurEntry = pEntry;<br />    }<br />    fclose (m_pIniFile);<br />    m_pIniFile = NULL;<br />    return TRUE;<br />  }<br /><br />    void    CloseIniFile ()<br />  {<br />    FreeAllMem ();<br />    if (m_pIniFile != NULL) {<br />      fclose (m_pIniFile);<br />      m_pIniFile = NULL;<br />    }<br />  }<br /><br />    bool    WriteIniFile (CCHR *pFileName)<br />  {<br />    struct ENTRY *pEntry = m_pEntry;<br />    if (m_pIniFile != NULL) {<br />      fclose (m_pIniFile);<br />    }<br />    if ((m_pIniFile = fopen (pFileName, "wb")) == NULL) {<br />      FreeAllMem ();<br />      return FALSE;<br />    }<br />    <br />    while (pEntry != NULL) {<br />      if (pEntry-&gt;Type != tpNULL) {<br />      #ifdef INI_REMOVE_CR<br />        fprintf (m_pIniFile, "%s\n", pEntry-&gt;pText);<br />      #else<br />        fprintf (m_pIniFile, "%s\r\n", pEntry-&gt;pText);<br />      #endif<br />      }<br />      pEntry = pEntry-&gt;pNext;<br />    }<br />    <br />    fclose (m_pIniFile);<br />    m_pIniFile = NULL;<br />    return TRUE;<br />  }<br />  <br />  bool  DeleteKey (CCHR *pSection, CCHR *pKey)<br />  {<br />    EFIND         List;<br />    struct ENTRY *pPrev;<br />    struct ENTRY *pNext;<br />    <br />    if (FindKey (pSection, pKey, &amp;List) == TRUE) {<br />      pPrev = List.pKey-&gt;pPrev;<br />      pNext = List.pKey-&gt;pNext;<br />      if (pPrev) {<br />        pPrev-&gt;pNext=pNext;<br />      }<br />      if (pNext) {<br />        pNext-&gt;pPrev=pPrev;<br />      }<br />      FreeMem (List.pKey-&gt;pText);<br />      FreeMem (List.pKey);<br />      return TRUE;<br />    }<br />    return FALSE;<br />  }<br /><br />  BOOL    ReadBool    (CCHR *pSection, CCHR *pKey, BOOL   Default)<br />  {<br />    char Val [2] = {"0"};<br />    if (Default != 0) { Val [0] = '1'; }<br />    return (atoi (ReadString (pSection, pKey, Val))?1:0); /* Only allow 0 or 1 */<br />  }<br /><br />    int     ReadInt     (CCHR *pSection, CCHR *pKey, int    Default)<br />  {<br />    char Val [12];<br />    sprintf (Val,"%d", Default);<br />    return (atoi (ReadString (pSection, pKey, Val)));<br />  }<br /><br />    double  ReadDouble  (CCHR *pSection, CCHR *pKey, double Default)<br />  {<br />    double Val;<br />    sprintf (m_result, "%1.10lE", Default);<br />    sscanf (ReadString (pSection, pKey, m_result), "%lE", &amp;Val);<br />    return Val;<br />  }<br /><br />    CCHR    *ReadString (CCHR *pSection, CCHR *pKey, CCHR  *pDefault)<br />  {<br />    EFIND List;<br />    if (ArePtrValid (pSection, pKey, pDefault) == FALSE) { return pDefault; }<br />    if (FindKey  (pSection, pKey, &amp;List) == TRUE) {<br />      strcpy (m_result, List.ValText);<br />      return m_result;<br />    }<br />    return pDefault;<br />  }<br /><br />    void    WriteBool   (CCHR *pSection, CCHR *pKey, bool   Value)<br />  {<br />    char Val [2] = {'0',0};<br />    if (Value != 0) { Val [0] = '1'; }<br />    WriteString (pSection, pKey, Val);<br />  }<br />  <br />    void    WriteInt    (CCHR *pSection, CCHR *pKey, int    Value)<br />  {<br />    char Val [12]; /* 32bit maximum + sign + \0 */<br />    sprintf (Val, "%d", Value);<br />    WriteString (pSection, pKey, Val);<br />  }<br /><br />    void    WriteDouble (CCHR *pSection, CCHR *pKey, double Value)<br />  {<br />    char Val [32]; /* DDDDDDDDDDDDDDD+E308\0 */<br />    sprintf (Val, "%1.10lE", Value);<br />    WriteString (pSection, pKey, Val);<br />  }<br /><br />    void    WriteString (CCHR *pSection, CCHR *pKey, CCHR  *pValue)<br />  {<br />    EFIND List;<br />    char  Str [255];<br />    <br />    if (ArePtrValid (pSection, pKey, pValue) == FALSE) { return; }<br />    if (FindKey  (pSection, pKey, &amp;List) == TRUE) {<br />      sprintf (Str, "%s=%s%s", List.KeyText, pValue, List.Comment);<br />      FreeMem (List.pKey-&gt;pText);<br />      List.pKey-&gt;pText = (char *)malloc (strlen (Str)+1);<br />      strcpy (List.pKey-&gt;pText, Str);<br />    } else {<br />      if ((List.pSec != NULL) &amp;&amp; (List.pKey == NULL)) /* section exist, Key not */ {<br />        AddKey (List.pSec, pKey, pValue);<br />      } else {<br />        AddSectionAndKey (pSection, pKey, pValue);<br />      }<br />    }<br />  }<br /><br />protected:<br />  struct  ENTRY *m_pEntry;<br />  struct  ENTRY *m_pCurEntry;<br />  char    m_result [255];<br />  FILE    *m_pIniFile;<br />  <br />  void    AddKey     (struct ENTRY *pEntry, CCHR *pKey, CCHR *pValue)<br />  {<br />    char Text [255];<br />    sprintf (Text, "%s=%s", pKey, pValue);<br />    AddItemAt (pEntry, tpKEYVALUE, Text);<br />  }<br />  <br />  BOOL    AddItem    (char Type, CCHR *pText)<br />  {<br />    struct ENTRY *pEntry = MakeNewEntry ();<br />    if (pEntry == NULL) { return FALSE; }<br />    pEntry-&gt;Type = Type;<br />    pEntry-&gt;pText = (char*)malloc (strlen (pText) +1);<br />    if (pEntry-&gt;pText == NULL) {<br />      free (pEntry);<br />      return FALSE;<br />    }<br />    strcpy (pEntry-&gt;pText, pText);<br />    pEntry-&gt;pNext   = NULL;<br />    if (m_pCurEntry != NULL) { m_pCurEntry-&gt;pNext = pEntry; }<br />    m_pCurEntry    = pEntry;<br />    return TRUE;<br />  }<br />  <br />  bool    AddItemAt (struct ENTRY *pEntryAt, char Mode, CCHR *pText)<br />  {<br />    struct ENTRY *pNewEntry;<br />    if (pEntryAt == NULL)  { return FALSE; }<br />    pNewEntry = (struct ENTRY*) malloc (sizeof (ENTRY));<br />    if (pNewEntry == NULL) { return FALSE; }<br />    pNewEntry-&gt;pText = (char *) malloc (strlen (pText)+1);<br />    if (pNewEntry-&gt;pText == NULL) {<br />      free (pNewEntry);<br />      return FALSE;<br />    }<br />    strcpy (pNewEntry-&gt;pText, pText);<br />    if (pEntryAt-&gt;pNext == NULL) /* No following nodes. */ {<br />      pEntryAt-&gt;pNext   = pNewEntry;<br />      pNewEntry-&gt;pNext  = NULL;<br />    } else {<br />      pNewEntry-&gt;pNext = pEntryAt-&gt;pNext;<br />      pEntryAt-&gt;pNext  = pNewEntry;<br />    }<br />    pNewEntry-&gt;pPrev = pEntryAt;<br />    pNewEntry-&gt;Type  = Mode;<br />    return TRUE;<br />  }<br />  <br />  void    FreeMem    (void *pPtr)<br />  {<br />    if (pPtr != NULL) { free (pPtr); }<br />  }<br />  <br />  void    FreeAllMem (void)<br />  {<br />    struct ENTRY *pEntry;<br />    struct ENTRY *pNextEntry;<br />    pEntry = m_pEntry;<br />    while (1) {<br />      if (pEntry == NULL) { break; }<br />      pNextEntry = pEntry-&gt;pNext;<br />      FreeMem (pEntry-&gt;pText); /* Frees the pointer if not NULL */<br />      FreeMem (pEntry);<br />      pEntry = pNextEntry;<br />    }<br />    m_pEntry    = NULL;<br />    m_pCurEntry = NULL;<br />  }<br />  <br />  bool    FindKey    (CCHR *pSection, CCHR *pKey, EFIND *pList)<br />  {<br />    char Search [130];<br />    char Found  [130];<br />    char Text   [255];<br />    char *pText;<br />    struct ENTRY *pEntry;<br />    pList-&gt;pSec        = NULL;<br />    pList-&gt;pKey        = NULL;<br />    pEntry = FindSection (pSection);<br />    if (pEntry == NULL) { return FALSE; }<br />    pList-&gt;pSec        = pEntry;<br />    pList-&gt;KeyText[0] = 0;<br />    pList-&gt;ValText[0] = 0;<br />    pList-&gt;Comment[0] = 0;<br />    pEntry = pEntry-&gt;pNext;<br />    if (pEntry == NULL) { return FALSE; }<br />    sprintf (Search, "%s",pKey);<br />    strupr  (Search);<br />    while (pEntry != NULL) {<br />      if ((pEntry-&gt;Type == tpSECTION) || /* Stop after next section or EOF */<br />        (pEntry-&gt;Type == tpNULL   )) {<br />        return FALSE;<br />      }<br />      if (pEntry-&gt;Type == tpKEYVALUE) {<br />        strcpy (Text, pEntry-&gt;pText);<br />        pText = strchr (Text, ';');<br />        if (pText != NULL) {<br />          strcpy (pList-&gt;Comment, pText);<br />          *pText = 0;<br />        }<br />        pText = strchr (Text, '=');<br />        if (pText != NULL) {<br />          *pText = 0;<br />          strcpy (pList-&gt;KeyText, Text);<br />          strcpy (Found, Text);<br />          *pText = '=';<br />          strupr (Found);<br />          /*            printf ("%s,%s\n", Search, Found); */<br />          if (strcmp (Found,Search) == 0) {<br />            strcpy (pList-&gt;ValText, pText+1);<br />            pList-&gt;pKey = pEntry;<br />            return TRUE;<br />          }<br />        }<br />      }<br />      pEntry = pEntry-&gt;pNext;<br />    }<br />    return NULL;<br />  }<br /><br />  bool    AddSectionAndKey (CCHR *pSection, CCHR *pKey, CCHR *pValue)<br />  {<br />    char Text [255];<br />    sprintf (Text, "[%s]", pSection);<br />    if (AddItem (tpSECTION, Text) == FALSE) { return FALSE; }<br />    sprintf (Text, "%s=%s", pKey, pValue);<br />    return AddItem (tpKEYVALUE, Text)? 1 : 0;<br />  }<br />  <br />  struct  ENTRY *MakeNewEntry (void)<br />  {<br />    struct ENTRY *pEntry;<br />    pEntry = (struct ENTRY *)malloc (sizeof (ENTRY));<br />    if (pEntry == NULL) {<br />      FreeAllMem ();<br />      return NULL;<br />    }<br />    if (m_pEntry == NULL) {<br />      m_pEntry = pEntry;<br />    }<br />    pEntry-&gt;Type  = tpNULL;<br />    pEntry-&gt;pPrev = m_pCurEntry;<br />    pEntry-&gt;pNext = NULL;<br />    pEntry-&gt;pText = NULL;<br />    if (m_pCurEntry != NULL) {<br />      m_pCurEntry-&gt;pNext = pEntry;<br />    }<br />    return pEntry;<br />  }<br />  <br />  struct  ENTRY *FindSection (CCHR *pSection)<br />  {<br />    char Sec  [130];<br />    char iSec [130];<br />    struct ENTRY *pEntry;<br />    sprintf (Sec, "[%s]", pSection);<br />    strupr  (Sec);<br />    pEntry = m_pEntry; /* Get a pointer to the first Entry */<br />    while (pEntry != NULL) {<br />      if (pEntry-&gt;Type == tpSECTION) {<br />        strcpy  (iSec, pEntry-&gt;pText);<br />        strupr  (iSec);<br />        if (strcmp (Sec, iSec) == 0) {<br />          return pEntry;<br />        }<br />      }<br />      pEntry = pEntry-&gt;pNext;<br />    }<br />    return NULL;<br />  }<br /><br />  #ifdef DONT_HAVE_STRUPR<br />  /* DONT_HAVE_STRUPR is set when INI_REMOVE_CR is defined */<br />  void strupr( char *str )<br />  {<br />    // We dont check the ptr because the original also dont do it.<br />    while (*str != 0) {<br />      if ( islower( *str ) ) {<br />        *str = toupper( *str );<br />      }<br />      str++;<br />    }<br />  }<br />  #endif<br />  <br />private:<br />};<br /><br />#endif<br /><br />#ifdef INIFILE_TEST_THIS_FILE<br />int main (void)<br />{<br />  CIniFile iFile;<br />  printf ("Hello World\n");<br />  iFile.OpenIniFile  ("Test.Ini");<br />  iFile.WriteString  ("Test", "Name", "Value");<br />  iFile.WriteString  ("Test", "Name", "OverWrittenValue");<br />  iFile.WriteString  ("Test", "Port", "COM1");<br />  iFile.WriteString  ("Test", "User", "James Brown jr.");<br />  iFile.WriteString  ("Configuration", "eDriver", "MBM2.VXD");<br />  iFile.WriteString  ("Configuration", "Wrap", "LPT.VXD");<br />  iFile.WriteInt     ("IO-Port", "Com", 2);<br />  iFile.WriteBool    ("IO-Port", "IsValid", 0);<br />  iFile.WriteDouble  ("TheMoney", "TheMoney", 67892.00241);<br />  iFile.WriteInt     ("Test"    , "ToDelete", 1234);<br />  iFile.WriteIniFile ("Test.Ini");<br />  printf ("Key ToDelete created. Check ini file. Any key to continue");<br />  while (!kbhit());<br />  iFile.OpenIniFile  ("Test.Ini");<br />  iFile.DeleteKey    ("Test"    , "ToDelete");<br />  iFile.WriteIniFile ("Test.Ini");<br />  printf ("[Test] Name = %s\n", iFile.ReadString ("Test", "Name", "NotFound"));<br />  printf ("[Test] Port = %s\n", iFile.ReadString ("Test", "Port", "NotFound"));<br />  printf ("[Test] User = %s\n", iFile.ReadString ("Test", "User", "NotFound"));<br />  printf ("[Configuration] eDriver = %s\n", iFile.ReadString ("Configuration", "eDriver", "NotFound"));<br />  printf ("[Configuration] Wrap = %s\n", iFile.ReadString ("Configuration", "Wrap", "NotFound"));<br />  printf ("[IO-Port] Com = %d\n", iFile.ReadInt ("IO-Port", "Com", 0));<br />  printf ("[IO-Port] IsValid = %d\n", iFile.ReadBool ("IO-Port", "IsValid", 0));<br />  printf ("[TheMoney] TheMoney = %1.10lf\n", iFile.ReadDouble ("TheMoney", "TheMoney", 111));<br />  iFile.CloseIniFile ();<br />  return 0;<br />}<br />#endif<br /><br /><img src ="http://www.cppblog.com/cyantree/aggbug/7929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-05-31 13:20 <a href="http://www.cppblog.com/cyantree/archive/2006/05/31/7929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跨平台的线程代码</title><link>http://www.cppblog.com/cyantree/archive/2006/05/16/7262.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Tue, 16 May 2006 08:46:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/05/16/7262.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/7262.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/05/16/7262.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/7262.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/7262.html</trackback:ping><description><![CDATA[
		<p>				改编自fltk，添加了linux平台下的Sleep实现，只支持Windows和Linux，分别用vc和gcc编译，代码如下：</p>
		<div class="dp-highlighter">
				<table class="dp-c" border="0" cellpadding="0" cellspacing="0">
						<tbody>
								<tr>
										<td class="gutter">1</td>
										<td class="line1">//threads.h, LGPL </td>
								</tr>
								<tr>
										<td class="gutter">2</td>
								</tr>
								<tr>
										<td class="gutter">3</td>
										<td class="line1">#ifndef Threads_H </td>
								</tr>
								<tr>
										<td class="gutter">4</td>
										<td class="line2">#define Threads_H </td>
								</tr>
								<tr>
										<td class="gutter">5</td>
								</tr>
								<tr>
										<td class="gutter">6</td>
										<td class="line2">#ifdef WIN32 </td>
								</tr>
								<tr>
										<td class="gutter">7</td>
								</tr>
								<tr>
										<td class="gutter">8</td>
										<td class="line2">#include &lt; windows.h &gt; </td>
								</tr>
								<tr>
										<td class="gutter">9</td>
										<td class="line1">#include &lt; process.h &gt; </td>
								</tr>
								<tr>
										<td class="gutter">10</td>
								</tr>
								<tr>
										<td class="gutter">11</td>
										<td class="line1">typedef unsigned long Fl_Thread; </td>
								</tr>
								<tr>
										<td class="gutter">12</td>
								</tr>
								<tr>
										<td class="gutter">13</td>
										<td class="line1">static int fl_create_thread(Fl_Thread&amp; t, void *(*f) (void *), void* p)  </td>
								</tr>
								<tr>
										<td class="gutter">14</td>
										<td class="line2">{ </td>
								</tr>
								<tr>
										<td class="gutter">15</td>
										<td class="line1">    return t = (Fl_Thread)_beginthread((void( __cdecl * )( void * ))f, 0, p); </td>
								</tr>
								<tr>
										<td class="gutter">16</td>
										<td class="line2">} </td>
								</tr>
								<tr>
										<td class="gutter">17</td>
								</tr>
								<tr>
										<td class="gutter">18</td>
										<td class="line2">#else </td>
								</tr>
								<tr>
										<td class="gutter">19</td>
								</tr>
								<tr>
										<td class="gutter">20</td>
										<td class="line2">// Use POSIX threading... </td>
								</tr>
								<tr>
										<td class="gutter">21</td>
										<td class="line1">#include &lt; pthread.h &gt; </td>
								</tr>
								<tr>
										<td class="gutter">22</td>
										<td class="line2">#include &lt; unistd.h &gt; </td>
								</tr>
								<tr>
										<td class="gutter">23</td>
								</tr>
								<tr>
										<td class="gutter">24</td>
										<td class="line2">typedef pthread_t Fl_Thread; </td>
								</tr>
								<tr>
										<td class="gutter">25</td>
								</tr>
								<tr>
										<td class="gutter">26</td>
										<td class="line2">static int fl_create_thread(Fl_Thread&amp; t, void *(*f) (void *), void* p)  </td>
								</tr>
								<tr>
										<td class="gutter">27</td>
										<td class="line1">{ </td>
								</tr>
								<tr>
										<td class="gutter">28</td>
										<td class="line2">  return pthread_create((pthread_t*)&amp;t, 0, f, p); </td>
								</tr>
								<tr>
										<td class="gutter">29</td>
										<td class="line1">} </td>
								</tr>
								<tr>
										<td class="gutter">30</td>
								</tr>
								<tr>
										<td class="gutter">31</td>
										<td class="line1">static void Sleep(unsigned long dwMilliseconds) </td>
								</tr>
								<tr>
										<td class="gutter">32</td>
										<td class="line2">{ </td>
								</tr>
								<tr>
										<td class="gutter">33</td>
										<td class="line1">    usleep(dwMilliseconds * 1000); </td>
								</tr>
								<tr>
										<td class="gutter">34</td>
										<td class="line2">} </td>
								</tr>
								<tr>
										<td class="gutter">35</td>
								</tr>
								<tr>
										<td class="gutter">36</td>
										<td class="line2">#endif </td>
								</tr>
								<tr>
										<td class="gutter">37</td>
								</tr>
								<tr>
										<td class="gutter">38</td>
										<td class="line2">#endif // !Threads_h </td>
								</tr>
						</tbody>
				</table>
		</div>
		<p>使用示例：</p>
		<table class="dp-c" border="0" cellpadding="0" cellspacing="0">
				<tbody>
						<tr>
								<td class="gutter">1</td>
								<td class="line1">#include "thread.h" </td>
						</tr>
						<tr>
								<td class="gutter">2</td>
								<td class="line2">... </td>
						</tr>
						<tr>
								<td class="gutter">3</td>
						</tr>
						<tr>
								<td class="gutter">4</td>
								<td class="line2">static Fl_Thread m_thread; // define </td>
						</tr>
						<tr>
								<td class="gutter">5</td>
								<td class="line1">... </td>
						</tr>
						<tr>
								<td class="gutter">6</td>
						</tr>
						<tr>
								<td class="gutter">7</td>
								<td class="line1">// thread create </td>
						</tr>
						<tr>
								<td class="gutter">8</td>
								<td class="line2">fl_create_thread(m_thread, thread_fun, 0); </td>
						</tr>
						<tr>
								<td class="gutter">9</td>
								<td class="line1">... </td>
						</tr>
						<tr>
								<td class="gutter">10</td>
						</tr>
						<tr>
								<td class="gutter">11</td>
								<td class="line1">static void* thread_fun(void *p) </td>
						</tr>
						<tr>
								<td class="gutter">12</td>
								<td class="line2">{ </td>
						</tr>
						<tr>
								<td class="gutter">13</td>
								<td class="line1">    while (1) { </td>
						</tr>
						<tr>
								<td class="gutter">14</td>
								<td class="line2">        ... </td>
						</tr>
						<tr>
								<td class="gutter">15</td>
								<td class="line1">    } </td>
						</tr>
						<tr>
								<td class="gutter">16</td>
						</tr>
						<tr>
								<td class="gutter">17</td>
								<td class="line1">    return 0; </td>
						</tr>
						<tr>
								<td class="gutter">18</td>
								<td class="line2">}</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cppblog.com/cyantree/aggbug/7262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-05-16 16:46 <a href="http://www.cppblog.com/cyantree/archive/2006/05/16/7262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从编译Linux kernel说开来</title><link>http://www.cppblog.com/cyantree/archive/2006/05/10/6890.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Wed, 10 May 2006 13:10:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/05/10/6890.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/6890.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/05/10/6890.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/6890.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/6890.html</trackback:ping><description><![CDATA[
		<p>　　编译内核的概念是linux最帅的地方，windows是不会提供操作系统的源代码的，而linux则不然，操作系统的源代码全部都是公开的。
对于发行版而言，比如rh9,debian,suse等，都提供编译好的kernel供用户使用，但是这样的kernel未必是用户需要的，这时就可以自
己对 kernel的源代码进行编译，然后替换掉原来的kernel。<br /><br />　　其实编译kernel并不恐怖，只是一件很简单的事情，就几条
指令而已。/usr/src/linnux是kernel源代码常用的放置目录，进入此目录，执行make
menuconfig，会出来一个图形界面，里面是kernel的各种配置和选项，把自己喜欢的驱动和配置选上，不需要的去除即可。然后make
dep，这是检查新的配置是否正确和做一些初始化工作。然后就是make
bzImage，这是真正开始编译kernel，bzImage是编译后的kernel文件名，可以为任意名字，只是一般会以bzImage、
zImage或vmlinuz之类为名。如果编译成功会生成一个bzImage文件，这就是kernel了。系统启动最主要的就是调用这个文件，里面包括
了文件系统、硬件驱动、网络基础、内存管理、进程管理等，在/boot下面有一个bzImage或者vmlinuz之类的文件就是原有的kernel，只
要把编译后的kernel文件(bzImage)替换掉就换成新的kernel了，或者用新名字复制到/boot下，再将grub或lilo的配置文件修
改一下，下次启动系统的时候即可使用新的kernel。下面是make
modules，这是编译驱动，或者说叫模块，在linux下驱动可以和kernel编译在一起，也可以编译成单独的模块文件，如果是第一种，
kernel启动的时候就会自动尝试载入驱动，第二种则是需要的时候手工加载驱动，也可以手动卸载。这是windows没有的功能，比如显卡的驱动在
windows下不重新启动系统是无法更新的，但在linux下却可以。比如对显卡做升级动作的时候其实就是在编译module，并卸载旧驱动，加载新驱
动，整个步骤无需重启系统。最后一步，就是make
modules_install，这个步骤是在/lib/modules下面生成一个按照kernel版本号为格式的目录，再将编译好的modules复
制进去。kernel启动的时候会通过这样的路径搜索modules文件，类似windows的system32目录。<br /><br />　　写了这么多，
很多没玩过linux的人看了会很迷糊，但了解一些相关认识还是很有趣的，因为这才是linux好玩的地方，一个随便捏来捏去的操作系统，可以满足某些人
士的变态心理-_-#　windows可以运行的硬件平台很有限，因为不公开，而且尺寸也很大，linux却因为可以自己编译，所以支持几乎所有的硬件平
台，x86,cs51,avr,pda,手机,alpha,大型机等等。同时尺寸还很小，一般编译一个可以运行到shell的系统，只要4、5M的尺寸就
可以搞定。加一个x-window也就30M左右，这在windows是不可想象的。这都是kernel公开，可以手动编译的好处和乐趣....<br /> </p>
		<p>2006-05-10 20:55　（根据聊天纪录修改）</p>
<img src ="http://www.cppblog.com/cyantree/aggbug/6890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-05-10 21:10 <a href="http://www.cppblog.com/cyantree/archive/2006/05/10/6890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FLTK简介</title><link>http://www.cppblog.com/cyantree/archive/2006/04/16/5670.html</link><dc:creator>cyantree</dc:creator><author>cyantree</author><pubDate>Sun, 16 Apr 2006 14:11:00 GMT</pubDate><guid>http://www.cppblog.com/cyantree/archive/2006/04/16/5670.html</guid><wfw:comment>http://www.cppblog.com/cyantree/comments/5670.html</wfw:comment><comments>http://www.cppblog.com/cyantree/archive/2006/04/16/5670.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cppblog.com/cyantree/comments/commentRss/5670.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyantree/services/trackbacks/5670.html</trackback:ping><description><![CDATA[　　FLTK，如同其名字所表达的：The Fast Light Tool
Kit，一个轻量级的GUI开发库。但这轻量级并不代表功能的羸弱，相反，FLTK在具有基本的GUI功能之外，还拥有一些特殊的功能，比如跨平台、内置
OpenGL功能、速度更快、尺寸更小、协议宽松等。当然，缺点也是有的，比如对于复杂的界面构件支持不够，资源支持的不足等。但一个工具如果使用的好，
取其长而去其短，自然可以飞花摘叶皆可伤人;P<br /><br />　
　我选择FLTK
的过程还是比较曲折的，当初做ARM下的GUI开发，选择的GUI库是MiniGUI，一个国内开发的界面库。当时还支持类unix平台，对
Windows的支持尚在开发中。由于需要寻找一些问题的解答，所以经常在其论坛上搜索，从而知道了还有microwindow、nano、
qtembedded等嵌入型GUI开发库，但当时没有太过注意。后来又开始转向WINCE平台的开发，这一搁就是２年。再后来终于要做跨平台的开发，对
具有跨平台的GUI开发库开始注意起来。<br /><br />　　一开始的选择是wxWidgets，但是研究了一段时间后发现不好解决的问题越来越多，终于
放弃。最头疼的就是C++类的事件传递，wxWidgets内部使用的是一个类似MFC的方法，所有传递事件的类全部要从一个根类继承，这样就导致创建的
类和wxWidgets绑定过甚，复用性大大降低，同时由于wxWidgets的目标不仅仅是GUI，造成其包含功能过多，其内部结构非常复杂，虽然是
OpenSource，但要若要修改其代码还是很困难的。综上所述，wxWidgets并不符合我的要求，从而被排除在外。<br /><br />　　之后研究的QT，老牌的跨平台GUI开发库，工具很多，开发也很人性化，qtdesign很像Delphi的界面开发方式，代码带有强烈的linux风格，但是看看附带的库文件又实在让人有些泄气，尺寸大，发布麻烦。所以在试用了一段时间后还是放弃了。<br /><br />　
　在此期间，其实也看到过一些对FLTK的介绍，但大多数对其评价不高，也就没有注意。直到有一次偶然心血来潮，上http:
//www.fltk.org看了一下，发现FLTK
似乎正对我的胃口，这才开始对其进行了深入的研究。经过一段时间的实际开发，个人觉得，对于跨平台和代码简洁而言，FLTK是再适合不过了。<br /><br />　
　FLTK的底层只提供一套完整的画点、画线功能，另外附带了字体的显示功能，但FLTK对字体的支持还很粗糙，尤其对于非英文字符集而言，后面我会详细
说明。在基本的点、线功能基础上，FLTK完全自己实现了一套界面，比如Button、Label、Edit、Tab等，全部都是由基本的点线画出。看到
这，可能你会觉得这实在是属于自己造轮子，吃力不讨好。诚然，如果你只针对一种平台开发，这样的做法不能带来多少好处，还造成学习时间的拉长。但若要针对
多个平台开发，这样做的好处就很明显了。首先是移植容易，只要针对目标平台实现基本的点线功能就可以实现代码的移植，这可能是所有跨平台GUI库中最方便
最直接的方案，目前FTLK支持MacOS、Windows、Linux(x-window)等平台，针对WinCE（主要是unicode的问题）和
plam
的开发正在进行中。其次是保持了界面的一致性，虽然QT、GTK等开发库也具有这种功能，但是他们都需要一套基本库的支持，无法做到系统尺寸的优化，而对
于FLTK而言，这却恰恰是他的优点和长项。最后是代码层次清楚、结构简单，由于大部分的工作就是基于底层的点线功能进行自绘，所有很多代码都是简洁明
了，很少费话。<br /><br />　　底层之上是一套以Fl_开头的类，代表了各种GUI构件，比如Fl_Window、Fl_Button、
Fl_Input等，使用起来很是容易。同时由于上面所说的，所有的界面构件都是画出来的，因此在熟悉了这种方式后，生成自己的构件也是很容易的，反正是
画界面嘛，既然别人能做到，你也能做到，实在不行可以查阅源代码进行学习。这些界面类的共同特点是轻量型、都拥有一个draw()，只要在draw()里
实现自己的绘画动作即可。<br /><br />　　说到界面就不能不说其事件实现方式，对于FLTK而言，使用的是最直接的方法：while(1){}。这也
是很多人批评FLTK原始的一个原因。但仔细想想，其实这是最直接的办法，不管是哪种平台，最终的事件方案不外乎是死循环和中断，中断的确具有很多好处，
但只要while(1)能完成这部分的功能，那又有什么关系呢。每个界面类都有一个handle(int
event)，只要继承这个成员函数，就可以在其中处理自己的事务。是不是很简单？同时由于这样的事件方式，造成FLTK的刷新速度很快，事件反应迅速，
也算是个附带优点了。现在大多数的开发库都是采用OO方式的事件处理方式，但FLTK却采用了最原始的函数指针方式，也算是一个异类，这可能和FLTK的
unix背景有关，无论如何，这种方式还是需要一定的适应时间的，而且这种方式的优缺点也是属于各花入各眼了，不过我本人还是很喜欢这种方式的，谁叫我比
较原始呢#-_-<br /><br />　　FLTK产生于NeXT环境，发展于X-window环境，所以对图形加速的支持必然是选择OpenGL。FLTK
使用Fl_Gl_Window这个类将OpenGL的基本功能囊括其中，只要在Fl_Gl_Window的draw()里glbegin/glend即
可，基本的设置工作FLTK全都做好了，对于我现在的系统要求简直是最适合不过了。<br /><br />　　FLTK基于LGPL，对使用者的要求非常宽松：
Contrary to popular belief, it can be used in commercial software -
even Bill Gates could use
it!　所以开发者不需要担心其项目的隐形问题。但是如果对FLTK进行了卓有成效的修正最好还是能回馈给开发组，所谓我为人人，人人为我嘛。<br /><br />　
　说了一堆的好话，现在开始谈谈FLTK的缺点。首先一条就是对非英文字体特别是中文的支持比较差，甚至是非常差。在Windows平台下还好一点，因为
在
Windows平台下使用的是TextOut函数输出字符串，但是在X-Window环境下就完蛋了，无法正确显示中文，也不能调用输入法进行输入。从这
点来说，FLTK还是只适合一些封闭软件的开发，对于通用软件而言FLTK并非是一个好的选择。但只能在Windows平台下开发中文软件也不是个办法，
要解决中文的显示问题也不难，目前FTLK的稳定版是1.1.7，开发版是2.0，有人针对1.xx版本修改了一个unicode版本，可以很平滑的支持
汉字的显示，但很遗憾，我没有编译成功过，如果谁编译成功了可以给我来个信。2.0已经对非英文的支持进行了专门的开发，但目前还没有release，在
不久的将来应该可以完整的解决这个问题。目前，要么等待，要么就像我这样，用点阵字库瞒天过海。具体方法因为还不够成熟，就不公布了。<br /><br />　　无论如何，FLTK的目标还是针对嵌入式和封闭软件的开发，所以复杂的界面并非其长项，如果想做出花哨复杂的界面，还是用其他GUI库比较好，FLTK并不适合。<br /><br /> 　　综上所述，FLTK的优点和缺点都是非常的突出，如何取舍还是自己决定吧。<br /><br /><br /><br />2006-04-16 22:02<img src ="http://www.cppblog.com/cyantree/aggbug/5670.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyantree/" target="_blank">cyantree</a> 2006-04-16 22:11 <a href="http://www.cppblog.com/cyantree/archive/2006/04/16/5670.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>