关于作者

用户名:vondon
笔名:冯唐
地区: 失败-成功
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



朋友的博客,渊博的朋友

颓废者.clinch's Blog

为了空间数据事业

志图博客 IS空间站

热爱VC++的朋友们

文学※文人

天涯文宛 吴颖

java编程

java编程好爱者的田地

数据库方面的星星

网络营销

最新动态

喜爱的文章

Google搜索引擎

搜集天地之精华为我所用
Google

WWW soln

美图欣赏

我的相册

访问统计:
文章个数:218
评论个数:157
留言条数:51




Powered by BlogDriver 2.1

不经历风雨怎能见彩虹

 

有事您说话

hotmail:vondon_flq@hotmail.com

gmail:vondonster@gmail.com

如果有需要请加我MSN,QQ,我的理想是做个自由职业者。

专业处理和电脑有关系的一切事务,图片广告,false制作3DMAX制作设计,数据库管理,网络安全,主机维护,调试各种网络产品。制作各种个人,企业,组织,团体,政府网站。编写一些符合某些特殊要求的小应用程序。价格面议或QQ联系。 主页:http://www.wandianhong.cn

文章

吉姆·克莱默的“二十五条股市投资规则”
规则1:牛也赚,熊也赚,猪被宰
  “对于交易者来说,知道何时应该离场是基本的生存常识。”在素有“绞肉机”之称的华尔街,这是世代相传的警句。如果说“股市有风险,入市需谨慎”,那离场就要坚决,否则只能任人宰割。


  规则2:缴点税没关系
  “不要妄图用‘长期持有’来避免频繁进出造成的税负。不是所有的股票都值得长期持有,账面上的浮赢可能稍纵即逝,甚至眨眼工夫就变成浮亏。”
  美国人炒股,如果平仓时有赢利就得缴上一笔不菲的“资本利得税”,而享受国家税收优惠的中国股民暂时还不必考虑纳税成本。国情不同,但道理相通。这条规则也可以总结成“适时平仓,落袋为安”,特别是原本就打算炒炒短线的股票,千万不要而幻想着多拿一天还会赚得更多。


  规则3:何必一步到位
  “建仓的时候不要一次买够,平仓的时候也不要一次都卖了。分几步走才能赶上更好的价位。”
  没人能预知下秒钟的价格,多给自己几次机会。


  规则4:发掘价值被低估的股票,别碰基本面出问题的公司
  “华尔街不退货,买错了股只能自认倒霉。”
  如果用中国的股票做例子,4月底国家统计局推迟发布一季度经济数据导致沪指下挫200点,可以算做“因外部因素导致价值被低估”,而“杭萧钢构”则绝对是基本面出了问题。但克莱默自己也承认,面对一只跳水的股票,有时候很难鉴别它是“价值被低估”还是基本面出了大问题。股民只能自己擦亮眼睛去判断了。


  规则5:控制风险,分散投资
  “你唯一需要做的就是控制风险,至于赚钱这件事,它会照顾好自己。”
  “别把鸡蛋放在一个篮子里”,地球人都知道。但克莱默说,他经常分析新股民的持仓,发现很多人不知不觉就买了一篮子类似的股票。“他们还自以为同时持有太阳微系统、微软和EMC(注:三家都是IT行业的著名公司,但分属系统开发、软件和存储等不同领域)就算是分散投资!控制风险是你投资生涯中唯一要做的事情,而控制风险就要时时刻刻想到分散原则。”


  规则6:认真完成家庭作业
  “他们口口声声说懂得研究的重要性,但他们的真实态度就像小学生对待家庭作业一样!我们的确应当像监督孩子完成作业一样,督促自己去看财报,看股评,看所有你能找到的资料。而‘那么多的资料,实在是没时间看’以及‘听说不错,买进来看看吧’这是两个最要不得的态度。”

  规则7:处乱不惊
  “当人们涌向‘太平门’的时候,你最好保持冷静。总有一个更好的离场时机,记住。”
  克莱默甚至建议在别人纷纷抛售的时候,不妨反其道行之——买入。不过,这要更像是高手的剑走偏锋,对于普通股民来说,能在恐慌中保存镇静,有条不紊地离场已经很难得了。


  规则8:买蓝筹总是值得的
  “就像我们买东西讲究品牌一样。蓝筹的确贵了些,但是你买到的是信誉。”
  这一条看上去似乎不无道理,但正如另一位股评家指出的:你能保证这个“蓝筹”不是第
  二个安然?而具体到中国的
  国情,20年的改革开放,18年
  的股市,尚不足以锻造出可
  以“养老”的优质股票。


  规则9:不要试图维持所有的头寸
  “当市场走坏的时候,留几只你最中意的股票,至于其他的,最好的解决办法就是忍痛割爱。”
  集中资金背水一战,才有可能多挽回一些损失。战线拉得越长,弹尽粮绝的一刻来得越早。


  规则10:烂公司并不意味着会被收购
  “并购题材实在是太诱惑了,以至于人们不惜在一些烂公司身上赌博。”
  看来爆炒ST并不是中国股市特有的现象。克莱默坚信,只有那些股价便宜而基本面良好的公司才有可能被并购,如果基本面不好,再便宜的股价也不会被并购。他自己就在北电网络上栽了大跟头。当北电的股价因为巨亏而暴跌的时候,他还安慰自己说:都这么便宜了,北电很有希望被别的大公司收购啦。最后,他终于醒悟过来,收购或许终有一天会发生,但自己恐怕等不到那一天了。


  规则11:你记不住那么多的名字
  “我最多持有25只股票,买进一只,就必须卖出一只。”
  这个规则看上去和“分散投资”有些冲突。其实克莱默强调的是选股时要“少而精”,而分散投资是说“不要把持仓集中在一个板块”。一个行业选一只,而你可以同时投资四五个行业。


  规则12:现金是给赢家准备的
  “如果你对市场的感觉不好,或者犹豫不决,那最好还是持币待购。”
  不要害怕错过机会,正如巴菲特所说,只需要几次正确的投资就足以让你富有一生。


  规则13:无怨无悔
  “不要说‘我本该早点买’,‘我要是晚点卖’,‘我本可以’……”这些“屁话”不会让你挽回哪怕一分钱的损失,只会破坏你作出正确决策所必须的平和心态。


  规则14:时刻准备着
  “股价何时要回调是很难预测的,所以,时刻准备着吧。”
  市场有涨就有跌,有跌就有涨。患得患失是投资的大忌。


  规则15:眼睛不要只盯着股票
  “别忘了还有债券!”
  在自己的投资组合放一些债券品种。因为股市跌的时候往往就是债券涨的时候。


  规则16:留着赚钱的卖掉赔钱的。错!
  “先狠狠心卖掉赔钱的。冷静一天。如果你还是喜欢它,再买进来好了。可我敢保证,你不会再买了。”
  仔细想想,有哪个股民没干过这样的蠢事?克莱默说,甚至一些专业的基金经理,在面对赎回压力时,同样会卖掉赚钱的头寸——这意味着“赢利”,去贴补亏钱的——留在手里意味着或许还有翻本的机会。我们难道真的如此难以接受赔钱的事实吗?


  规则17:不要抱有任何希望
  “每次听到有人说‘这该死的股票,希望它下周能回到我开仓的价格,这样我就能解套了’,我就禁不住想扇那人的耳光。”
  “现价5元-买入价10元+10份希望=赢利”这样的公式从来都不成立。“希望和祈祷属于宗教,理智属于投资。站在股市的门口,放弃你所有的希望!”希望有时是支撑一个人活下去的唯一理由,而在股市里,翻本的希望是支撑你继续赔钱的主要原因。在这一点上,克莱默显示出职业投资人“冷血”的一面,但这样的冷血是必须的。


  规则18:保持灵活性
  “市场的本质是变化的,不要总是老眼光看新情况。”
  在这里,克莱默恐怕是在为股评家的善变和自相矛盾开脱。但在诡异的证券市场上,又何妨做个“墙头草”?不要用你的“信念”或者“希望”去对抗市场的变化。


  规则19:高管都溜了,你还在这干吗?
  “没有哪个公司的高管会真的因为‘个人原因’而突然辞职。”
  三十六计——走为上!


  规则20:放弃价值投资,罪过罪过
  “因为种种原因,总有一些公司的股价在一个阶段滑落到净值附近,而公司本身的经营状况并没有恶化。但大部分投资人似乎都没有耐心等待股价的回升。”
  价值投资似乎总是在股市不好的时候才被提及。股市一派繁荣的时候,更多人是奔着块钱去的,投机才更有魅力。


  规则21:不要轻信你从电视上听来的东西
  “你在电视上听到的股评或许是对的,但仅限于‘或许’。”
  在这一点上,中国股民有过深刻教训,而作为电视主持人的克莱默先生也展示了自己的真诚。


  规则22:看到预告,等30天再做决定
  “遵循这个原则的确让我错过了一些机会。但是,更多时候,我感到庆幸。”
  虽然美国股市的信息披露原则近乎苛刻,但业绩变脸的事情同样时有发生,而中国股民更是深受其害。


  规则23:小心被华尔街“忽悠”了
  “那些躲在股票背后的分析师和公司,可以推动股票非正常地上涨。”
  一个股评家说出这样的话,让人颇感意外。但面对投资机构的营销机器,的确,任何投资人都要倍加小心。


  规则24:自圆其说
  “及时修正错误决策的一个有效方法就是:向其他人解释你为什么要买这只股票。”
  越来越多的人坐在电脑前,独自完成投资决策,我们只需说服自己就可以了。但是,如果有人问起,你确定自己能说服对方吗?不能自圆其说的决定,出问题的概率更大。


  规则25:大牛市总是有的
  “每次结束电视节目之前,我总会说这句话。我会找出个牛市给你看。因为我坚信。”股评家的广告。但借他之言,恭祝每个读者早日发财!

- 作者: 冯唐 2007年05月16日, 星期三 14:1  回复(0) |  引用(0) 加入博采

短信群发器也被列为打击对象了
      在原始的社会里我们没有通信设备。人们就靠着口头传达,旗语,灯语,火把,烟火等来传递信息。
现代社会里我们有了广播,电话,电报,传真,手机,电脑,网络等新型的通信设备。这些设备的时候使人们的生活节奏加快了。人与人交流也加速了。手机在现代生活中的位置变的越来越重要了。对于我们这些贫苦大众来说,手机短信是最合适我们用来交流使用的。它的费用不是很高。交流起来也比较随意。可以是单向的也可以是双向的,大家都可以参与的。在交流的时候我们遇到了这样一个问题,如何使一条信息传播的更快。一些聪明的人就想到了群发。效果很明显。本来是一次告诉一个人,现在却一次告诉了很多人。但是新的问题有出现了,一些广告,垃圾信息,非法信息,危害国家安全的信息等也通过这一途径迅速的传播开了。国家的一些个“专家”想出了一个奇妙的办法。禁止群发。群发器被扼杀了。做这些软件,硬件的公司如何生存下去呢。我想禁止群发器根本不是办法。应该在源头上堵,直接把移动,联通,电信,网通等靠通信盈利的公司关闭了。这样我们不就不会受到垃圾的毒害了。然后关闭所有的网站,关闭所有的网络公司,这些都是垃圾的传播者和制造者。关闭一切和信息有关的,包括(即使通信软件,信息媒体)。让我们回到那个原始的,没有垃圾信息传播的社会中吧。
     

- 作者: 冯唐 2007年02月26日, 星期一 17:00  回复(1) |  引用(0) 加入博采

时间的概念
一秒等于1000毫秒,等于10的15次方皮秒.
10的18次方 |艾[可萨] | E
10的15次方 |拍[它] | P
10的12次方 |太[拉] | T
10的 9次方 |吉[咖] | G
10的 6次方 | 兆 | M
10的 3次方 | 千 | k
10的 2次方 | 百 | h
10的 1次方 | 十 | da
10的-1次方 | 分 | d
10的-2次方 | 厘 | c
10的-3次方 | 毫 | m
10的-6次方 | 微 | μ
10的-9次方 |纳[诺] | n
10的-12次方 |皮[可] | p
10的-15次方 |飞[母托] | f
10的-18次方 |阿[托] | a
时间单位的档案
编辑: 李瑛
撰文/David Labrader [崔琳琳/译 曾少立/校]
时间的单位可以从极小到极大,下面的描述是想传达一种超大时间跨度的感受。
一渺秒(十亿分之一秒的十亿分之一)
科学家是用渺秒来对瞬时事件进行计时的。
研究人员已经用稳定的高速激光产生了仅持续250渺秒的光脉冲。尽管这一时间间隔短得无法想像,但是和普朗克常数相比还是很长的。普朗克常数大约为10-43秒,被认为是可能持续的最短时间。
一飞秒(十亿分之一秒的百万分之一)
一个分子里的一个原子完成一次典型振动需要10到100飞秒。完成快速化学反应通常需要数百飞秒。光与视网膜上色素的相互作用(产生视觉的过程)约需200飞秒。
一皮秒(十亿分之一秒的千分之一)
最快晶体管的运行以皮秒计。一种高能加速器产生的罕见亚原子粒子b夸克在衰变之前可存在1皮秒。室温下水分子间氢键的平均存在时间是3皮秒。
一纳秒(十亿分之一秒)
光在真空中一纳秒仅传播30厘米(不足一个步长)。个人电脑的微处理器执行一道指令(如将两数相加)约需2至4纳秒。另一种罕见的亚原子粒子K介子的存在时间为12纳秒。
一微秒(百万分之一秒)
光在这个时间里可以传播300米,大约是3个足球场的长度,但是海平面上的声波只能传播1/3毫米。高速的商业频闪仪闪烁一次大约持续1微秒。一筒炸药在它的引信烧完之后大约24微秒开始爆炸。
一毫秒(千分之一秒)
典型照相机的最短曝光时间为一毫秒。一只家蝇每三毫秒扇一次翅膀;蜜蜂则每五毫秒扇一次。由于月亮绕地球的轨道逐渐变宽,它绕一圈所需的时间每年长两毫秒。在计算机科学中,10毫秒的间隔称为一个jiffy。
十分之一秒
寓言中常说的“一眨眼”的时间就是十分之一秒。人类的耳朵需要十分之一秒的时间来分辨发声回声。远离太阳系飞行的飞行器旅行者1号,每十分之一秒飞离太阳约两公里。蜂雀在这个时间里可以拍打7次翅膀。为A到中C定调的调音叉振动4次。
一秒
健 康人的心跳大约持续一秒。美国人平均每一秒吃掉350块比萨饼。地球每一秒绕太阳旋转30公里,而与此同时太阳在银河系中穿行274公里。一秒钟不足以使 月光到达地球(需1.3秒)。传统意义上,一秒是24分之一天的60分之一的60分之一,但是科学家给出了一个更精确的定义:铯133原子基态超精细能阶 跃迁的9 192 631 770个周期所持续的时间,称为一秒。

- 作者: 冯唐 2007年01月19日, 星期五 17:26  回复(0) |  引用(0) 加入博采

日期操作常用代码

http://blog.csdn.net/qdzx2008/archive/2005/10/01/493751.aspx


using System;

namespace My.Utils {
 /// <summary>
 /// 日期操作常用工具
 /// </summary>
 public class DateUtils {
  public DateUtils() {
  }

   &160;    /// <summary>
        /// 比较日期的年份差
        /// </summary>
        /// <param name="start">开始日期</param>
        /// <returns>与当前日期的年份差</returns>
        public static int DiffYear (string start) {
            return DiffYear(Convert.ToDateTime(start));
        }

        /// <summary>
        /// 比较日期的年份差
        /// </summary>
        /// <param name="start">开始日期</param>
        /// <param name="end">结束日期</param>
        /// <returns>年份差</returns>
        public static int DiffYear (string start, string end) {
            return DiffYear(Convert.ToDateTime(start), Convert.ToDateTime(end));
        }
       
        /// <summary>
        /// 比较日期的年份差
        /// </summary>
        /// <param name="start">开始日期</param>
        /// <returns>与当前日期的年份差</returns>
        public static int DiffYear (DateTime start) {
            return (DiffYear(start, DateTime.Now));
        }

        /// <summary>
        /// 比较两个日期的年份差
        /// </summary>
        /// <param name="start">开始日期</param>
        /// <param name="end">结束日期</param>
        /// <returns>年份差</returns>
        public static int DiffYear (DateTime start, DateTime end) {
            return (end.Year - start.Year);
        }

        /// <summary>
        /// 格式化当天日期(yyyy-MM-dd)
        /// </summary>
        /// <returns>格式化后的日期字符串</returns>
        public static string DateFormat () {
            return DateFormat(DateTime.Now);
        }

        /// <summary>
        /// 格式化日期(yyyy-MM-dd)
        /// </summary>
        /// <param name="date">待格式化的日期</param>
        /// <returns>格式化后的日期字符串</returns>
        public static string DateFormat (string date) {
            return DateFormat(Convert.ToDateTime(date));
        }

        /// <summary>
        /// 格式化日期
        /// </summary>
        /// <param name="date">待格式化的日期</param>
        /// <param name="format">格式化串</param>
        /// <returns>格式化后的日期字符串</returns>
        public static string DateFormat (string date, string format) {
            return DateFormat(Convert.ToDateTime(date), format);
        }

        /// <summary>
        /// 格式化日期(yyyy-MM-dd)
        /// </summary>
        /// <param name="date">待格式化的日期</param>
        /// <returns>格式化后的日期字符串</returns>
        public static string DateFormat (DateTime date) {
            return DateFormat(date, "yyyy-MM-dd");
        }

        /// <summary>
        /// 格式化日期
        /// </summary>
        /// <param name="date">待格式化的日期</param>
        /// <param name="format">格式化串</param>
        /// <returns>格式化后的日期字符串</returns>
        public static string DateFormat (DateTime date, string format) {
            return date.ToString(format);
        }

        /// <summary>
        /// 格式化日期时间
        /// </summary>
        /// <param name="datetime">待格式化的日期时间</param>
        /// <returns>格式化后的日期时间字符串</returns>
        public static string DateTimeFormat (DateTime datetime) {
            return DateTimeFormat(datetime, "yyyy-MM-dd HH:mm");
        }

        /// <summary>
        /// 格式化日期时间
        /// </summary>
        /// <param name="datetime">待格式化的日期时间</param>
        /// <param name="format">格式化串</param>
        /// <returns>格式化后的日期时间字符串</returns>
        public static string DateTimeFormat (DateTime datetime, string format {
            return datetime.ToString(format);
        }
 }
}

- 作者: 冯唐 2007年01月19日, 星期五 14:41  回复(1) |  引用(0) 加入博采

三叉神经痛

在我国10月10日-17日第二个疼痛周之际,记者针对记者针对难治性三叉神经痛的病因与预防问题,访问了天津医科大学第二医院疼痛科主任郑宝森教授。

有人感觉脸部有短暂、或阵发性、闪电样剧痛,严重时不能说话、不能吃饭、刷牙,连洗脸、剃须。这到底是什么病呢?这可能是得了三叉神经疼。据文献报告,三叉神经痛发病年龄从10-90岁,最多人群为40岁以上的中老年人。男女比例为2:3,发病率为千分之二左右。

三叉神经为脑神经之最大支,负责面部主要的感觉神经,伴行咀嚼肌的运动神经。躯体感觉纤维大部分起源于三叉神经节。三叉神经节位于颞骨岩部尖端的三叉神经压迹处,由节的前外缘分出3 大支:(1)眼神经:是感觉神经,最小的,向前穿入海绵窦外侧壁,居滑车神经下方,继经眶上裂入眶。(2)上颌神经:较大,亦为感觉神经,向前穿入海绵窦 外侧壁下部,继水平向前,经圆孔出颅腔进入翼腭窝,再由眶下裂入眶,续为眶下神经。(3)下颌神经:最大,为混合神经,经卵圆孔至颞下窝,分出耳颞神经、 颧面神经、颧颞神经、颊神经、下牙槽神经和舌神经。

三叉神经痛属于一种神经痛,是 以反复发作的单侧面部电击样疼痛为特点。人群中的发病率约10万分之4。多见与老年人,通常的患病年龄为50-60岁,也可以发生于年轻人。典型发作形式 为:疼痛突然发作,疼痛性质剧烈,通常为电击样、针刺样或撕咬样;疼痛过程短暂,一般为数秒至一分钟,个别者可持续数分钟至一小时;疼痛发作为间断性,发 作间期可为数日甚至数十年,伴随病程发展,疼痛发作会日趋频繁,发作间期越来越短。最常见的是疼痛位于面下部和牙龈,以至好多患者误认为是牙病而拔牙治 疗。轻刺激面部的一些特定部位、咀嚼、大声说话、甚冷空气刺激都可以诱发疼痛。一旦患病就很难有自行痊愈的可能。

三 叉神经痛分为两类型,(1)继发性三叉神经痛是指可以检查到明确病因的三叉神经痛。例如,颅内桥脑小脑角等部位发生的肿瘤,先天血管畸形,多发硬化症等。 (2)原发性三叉神经痛是指无法找到明确发病原因的三叉神经痛。这类三叉神经痛经过一段时间针灸、中药、封闭等简单治疗无效或者反复的患者,要及时到疼痛 科就诊。

根据病史及临床表现不难做出诊断,有疼痛发作不典型或伴有异常神经系统体 征者应考虑为继发性三叉神经痛必要时可行颅底CT、头CT或MRI检查。至今该病发病机制不清楚。比较流行的说法是血管压迫学说。三叉神经的外面有一种神 经组织叫髓鞘,当有异常血管长期压迫神经时,髓鞘破坏,造成神经短路,正常的感觉通过短路进入中枢神经系统,而产生异常的痛觉。当气候变化或温度变化比较 明显时三叉神经痛的发病率会明显升高。

三 叉神经痛治疗方法,包括:药物治疗:如口服卡马西平。中医药治疗:口服中药,针灸,局部贴敷中药。对轻度的三叉神经痛效果很好。对于中度三叉神经痛患者需 要药物和外周神经阻滞(封闭)治疗。对严重三叉神经痛患者需要外科治疗:神经撕脱、神经切断、射频治疗、后颅凹开颅微血管减压术。最近疼痛科医生研究出的 超选择微创介入治疗三叉神经痛,是一种最新的治疗技术,利用超选择技术能够准确阻断三叉神经的痛觉细胞,不损伤感觉和运动神经细胞,对难治性三叉神经痛具 有更加安全有效的独到之处。

三叉神经痛病人日常生活中应注意以下事项:

      1、 利用疼痛发作后的间歇期,清洁颜面、口腔,保持个人卫生,避免其他疾病发生。
      2、 用温水洗脸和刷牙、避免冷水刺激。
      3、 注意气候变化,避免风吹、和寒冷气候对颜面部的刺激。外出时戴口罩或头巾。
      4、 戒烟、酒,少吃辛辣食物,避免化学刺激诱发疼痛。
      5、 吃质软、易嚼食物,避免硬物刺激
      6、 尽可能避免诱发疼痛的机械动作。
      7、 保持乐观情绪,避免急噪、焦虑等情绪诱发疼痛。

      病人在我院治疗康复后应注意以下事项:

      1、 患侧面部治疗后感觉障碍,请勿做局部冷敷、热敷或热疗,以免冻伤或烫
      2、 治疗后部分患者角膜反射减弱,应遵医嘱出院后继续点眼药水,风沙天外出时可戴眼镜,避免异物进入眼睛,保护角膜。如有角膜充血、水肿现象,请及时到眼科就医,以防发生角膜炎。
      3、 治疗后病人患侧面部麻木,感觉障碍,易造成口唇、口腔粘膜的烫伤、咬伤或由异物引起机械性损伤及误吸等。所以注意不要食用带骨、带刺或过热的食物,进食后口腔往往滞留食物应饭后漱口,保持口腔清洁。

      三叉神经痛病人的心理调节

      三叉神经痛是医学界公认的神经系统中最痛苦、最顽固、治疗最困难的一种疾病,有“不死的癌症”之称。疾病不仅给病人带来了肉体上的痛苦,而且给病人带来了 精神上的折磨。病人终日处于畏惧疼痛发作的恐惧中,有的病人因此萌发轻生念头。因此,作为医务工作者我们首先要引导病人正确认识疾病、树立战胜病魔的信 心。
随着科学技术和医疗科技的发展,许多不治之症将迎刃而解。我院“颅底卵圆孔定位装置和方法”的发明和定位药物注射治疗方法的诞生,即是对广大三叉神经痛患 者的一大贡献,是以最小的损伤、最安全的方式治愈顽症的新方法,是医学发展的大势所趋。广大病人应充分认识到这一点,积极治疗,投身到与疾病的顽强抗争 中。
我们在对已康复的病人的随访中发现,许多病人仍表现为:性格孤僻、多疑,担心病情复发,对微小的面部异常感觉非常敏感,仍有戴口罩和头巾的习惯,闭门不 出,怕风、怕凉等。这都表明疾病的阴影并没有散去,给病人带来的心理创痛并没有康复。有这类情况的病人应该接受医生的开导,通过从事适当的运动、从事健康 的爱好或把精力多用于家务、工作等方面,调整心态,逐渐树立起乐观向上的生活信心。

    &160; 总之,三叉神经痛病人应重视和积极做好自身的心理调节。在饮食和起居上象健康人一样生活。世界是美丽的,生活是美好的,让我们携手创造健康、美好的明天。

三叉神经痛的治疗常识

      由于三叉神经痛的病因学和病理学至今还不清楚,所以,治疗的目的应是长期镇痛。镇痛的方法至今仍是多种多样。可大概分为无创和有创治疗方法。无创治疗方法 包括药物治疗、中医中药针灸疗法、理疗等。适用于病程短、疼痛较轻的患者。也可作为有创治疗方法的补充治疗。有创治疗方法包括手术疗法、注射疗法和射频热 凝疗法。
      一、一般疗法

      (一) 药物疗法

      1.卡马西平(carbamazepine) 开始每日2次,以后可每日3次。每日0.2~0.6g,分2~3次服用,每日极量1.2g。服药24~48h后即有镇痛效果。
      2.苯妥英钠(sodium phenytoin) 别名大仑丁(dilantin),为白色粉末,无臭,味微苦。易溶于水,几乎不溶于乙醚或氯仿,在空气中易潮解。

      (二)中药治疗

      祖国医学认为,三叉神经痛属“头痛”、“偏头痛”、“面痛”等范畴。古医书中有“首风”、“脑风”、“头风”等名称记载,如《素问.风论》:“首风之状, 头面多汗恶风,当先风1日则病甚,头痛不可以出内。”有些三叉神经痛患者,经服用中药后可收到一定的治疗效果,可使疼痛发作停止或减轻。有的临床医师采用 内服中药治疗三叉神经痛,取得了一定的效果。中医对于本病主张辨证施治,根据不同的类型,给与针对性的治疗。
对于风邪外袭型,主张治宜活血化瘀,祛风止痛。可采用加味吴茱萸汤(党参、川芎各25g,吴茱萸、白芷、天麻各18g,干姜、薄荷、防风各12g,丹参、 香附各20g,赤芍15g,钩藤30g,细辛3g),或可采用白附子10g,僵蚕10g,天麻10g,防风10g,白芷10g,细辛10g,胆南星 10g,地龙10g,川芎10g,全蝎3g。
对于肝火上炎型,采用滋阴潜阳,降火熄风。可采用全蝎5g,蜈蚣2条,僵蚕、地龙、川芎、牛膝、生地、白芍、白术各15g,制川乌10g,白芷、天麻、制 半夏各10g,细辛4g,钩藤20g,石决明30g(先煎)。也可采用白僵蚕、蔓荆子、炒没药、龙胆草、白蒺藜各9g,白芷12g,白芍、生地黄各 15g,石决明(先煎)30g,全蝎6g,甘草3g。

      (三)针灸治疗

      1.普通针刺疗法 针灸治疗在临床上应用方便,安全快捷,副作用小。主穴:风池、翳风、下关、手三里、合谷。配穴:第1支疼痛者加太阳,阳白,捞竹,头维。第2、3支疼痛者 加太阳、四白、下关、听 会、地仓、承浆、迎香。行重刺激法,并留针,也可用电刺激治疗机作电针治疗。
2.针刺三叉神经周围支 针刺眶上孔,眶下孔、后上齿槽孔及颏孔,直接针刺三叉神经周围支,待出现同侧分支的分布区疼痛及麻胀反应,而获迅速的镇痛效果。所持针刺手法,系提插捻转 强刺激,不论阴阳补泻,对初针患者采用卧位,手法宜轻,以免引起晕针,或产生惧怕情绪。

      二、三叉神经周围支封闭疗法

      三叉神经周围支封闭是临床治疗三叉神经痛的常用方法。注射的部位主要是三叉神经分支通过的骨孔,如眶上孔、眶下孔、下齿槽孔、颏孔、翼腭孔等。所用药物包 括无水乙醇、苯酚溶液、多柔比星、链霉素等。三叉神经周围支封闭治疗止痛范围局限,其效果与操作者的技术水平和患者的病情程度也关系密切,因此,多数病人 在半年至2年内复发。
三叉神经周围支阻滞根据注射部位分为:眶上神经阻滞术,眶下神经阻滞术,后上齿槽神经阻滞术,上颌神经阻滞术,颏神经阻滞,下齿糟神经阻滞和下颌神经阻滞术。

      三、半月神经节阻滞疗法

      概述
      采用半月神经节阻滞治疗三叉神经痛目前己在国内外广泛使用,多年来,这一注射疗法已被证明是有效的,它的确能恒久地治愈三叉神经痛。但因其注射技术较难掌 握,主要是穿刺操作的准确性难以把握,因此,治疗效果随着各人的技术不同而大有出入。经卵圆孔刺入颅腔内的半月神经节,注入甘油、无水乙醇、苯酚溶液、多 柔比星、阿霉素等神经毁损药物,以阻滞三叉神经第2、3支甚至全部的三支,可获得长时间的阻滞效果。用于治疗顽固性三叉神经痛、颌面部癌痛及带状疱疹后遗 痛。
治疗适应证 1、本注射疗法适用于一切较严重而顽固的三叉神经痛患者,尤其是具有开颅手术禁忌的老弱及慢性病患者。2、三叉神经痛同时累及第2、3支,1、2支或全部 3支,并经各周围支阻滞无效者。3、顽固的面部带状疱疹后三叉神经痛。
并发症 半月神经节阻滞可能引起的一些并发症,大多是由于穿刺(无仪器定位的徒手穿刺)方向不准或进针过深损伤附近的血管、脑神经和组织,或乙醇(我院使用安全性 高的药物——医用高纯度甘油)剂量较大并流入蛛网膜下隙引起损害。并发症的发生率是非常低的。半月神经节阻滞的并发症经过努力大多可以避免。

      并发症主要有:阻滞范围内感觉丧失或异常;眩晕综合征;咀嚼困难 ;脑神经损害;.同侧角膜炎、角膜溃疡等。
注射疗法和开颅手术的关系是可以互相补充的。手术治疗三叉神经痛近年来已很少。适用于开颅手术的患者,都应先行注射治疗,凡行开颅手术未能成功者,或手术 治疗效果不好,或手术后复发的患者,注射疗法也可收到很好的效果。

      四、射频热凝疗法

      概述
      射频热凝疗法是利用高温作用于神经节、神经干和神经根等部位,使其蛋白质凝固变性,从而阻断神经冲动的传导。目前,射频热凝疗法在临床较广泛,热凝术的治 疗效果良好,但并发症较多,目前尚无死亡的病例报道。虽然复发率较高,由于操作方便,可重复实施,最终达到镇痛的目的。

      不良反应及并发症
      1、操作中疼痛 本方法需取得患者配合。治疗前应讲清楚,在局部麻醉下施行此种治疗具有一定的痛苦,必须取得患者的理解和配合,并注意从60℃开始缓慢加热,可减少突然高温所带来的痛苦。
      2、颅内出血 半月神经节内侧邻近海绵窦和颈内动脉,穿刺不慎或进入卵圆孔过深易损伤而出血,严重者可形成颅内血肿。(仪器定位穿刺可完全避免)
      3、脑神经损害 如面部轻瘫等。
      4、颅内感染 严格无菌操作可防止颅内继发感染。特别需要注意防止反复穿刺时穿刺针穿破颊黏膜将口腔内细菌带入颅内。
      5、带状疱疹 可在手术后数日出现在患区,其机理尚不清楚。局部可涂甲紫或可的松软膏,数日即可愈合。
      6、角膜炎 半月神经节热凝术的一个较为严重的并发症即是角膜反射消失,严重者可引起麻痹性角膜炎,最终可导致患者失明。操作过程中要注意控制加热的温度和时间,并随 时查看角膜反射的变化。已发生角膜反射丧失者,要嘱患者带眼镜,使用眼膏保护角膜,防止角膜炎。有的角膜反射消失后需数个月才逐渐恢复。
      7、 面部感觉障碍 大多数患者治疗后可有不同程度的面部感觉障碍。在Menzel总结的315例中,治疗后大约93.1%患者面部有不同程度的麻木感或烧灼感。
      因此,在治疗前,患者及家属有权向主治医生了解治疗可能可能产生的副作用。

      五、周围神经撕脱术

      有的专家认为供养三叉神经的动脉发生硬化、缺血,以致神经纤维营养代谢紊而发生变性。远心端神经周围纤维组织增生对血管的压迫使血供进一步减少,加重神 经变性,导致神经纤维脱髓鞘而发生“短路串电”现象。因此,在临床上出现了周围神经撕脱术,进行该手术时,应尽可能多地向近心端撕脱,以防止手术后三叉神 经痛复发。由于该方法对多支痛或深部痛三叉神经痛的治疗捉襟见肘,效果不佳,因此应用不多。

      六、半月神经节球囊压迫法

      球囊压迫法是国际上八十年年代开始用于治疗三叉神经痛的技术。患者采用全身麻醉、气管插管和控制呼吸。由于穿刺操作者的熟练程度不同,麻醉时间在20分钟 ~160分钟。所以要求麻醉随时终止,患者尽快清醒。在X线屏幕下进行半月神经节穿刺术。将有针芯的14号穿刺针经面部皮肤穿刺。穿刺针停在卵圆孔,并拔 出针芯,经穿刺针将Fogarty球囊放入半月神经节。用注射器接球囊外的导管接头,注入1~2ml液体,使球囊胀大,形成大约为1×1.5cm的梨形囊 (X线屏幕下所见),并维持数分钟。在压迫结束后抽出液体,胀大的球囊复原。把球囊与穿刺针一起拔出,压迫穿刺点止血。整个操作过程均在X线屏幕下进行。 手术成功率在90%左右,但半年后复发再次治疗有效,远期效果待观察。

      七、三叉神经根微血管减压术

      自从Dandy 1934年首先提出血管压迫三叉神经根能导致三叉神经痛的论点以后,一些临床资料也表明血管压迫三叉神经是三叉神经痛的原因之一。许多学者因此采用神经血管减压术治疗三叉神经痛。
      (一) 常用方法
      目前治疗三叉神经痛常用的开颅手术有:经颅中窝三叉神经感觉根切断术、三叉神经脊束切断术、三叉神经根解压术和颅后窝三叉神经根微血管解压术。
      (二)手术操作技术
      常规消毒后,采用2%利多卡因作耳后标记线内浸润麻醉或全麻。沿标记线作切口,用颅骨钻紧靠乙状窦后缘钻开一直径大约为2cm大的骨窗(将骨屑收集备 用)。在手术显微镜下将小脑向后上方轻轻牵开,用2~3mm宽带吸引管的微型脑压板由此放入达三叉神经根部,自神经出脑桥处向远端探查血管压迫及其他病灶 情况。在神经与血管之间夹放一块自体小肌片。将受血管压迫的神经包绕起来与血管隔开。此时嘱患者自己用手撞击扳机点及做平时易诱发疼痛的某些动作,若无疼 痛则达到减压目的。逐层缝合关闭切口。
      (三)影响手术效果主观满意度的因素
      三叉神经痛行显微血管减压治疗,虽长期疗效各报道不一,但仍可作为一种可行方法应用。以往远期疗效随访多偏重客观因素,缺乏了解患者对治疗效果的主观满意 度,而后者对于从整体判断三叉神经显微血管减压效果也是重要的。影响主观满意度的一些因素包括:
      1、三叉神经痛是一个给患者带来极大痛苦,而各种治疗方法又均无十分理想效果的一种疾患。因而随访中发现,尽管客观上患者手术后疼痛未彻底消失,留有轻微 疼痛或疼痛复发,但疼痛程度轻,又改变了手术前疼痛不能为药物所控制的状况,或伴有轻度并发症者,主观上患者仍对本手术的效果表示满意。对于这种客观和主 观上不一致性,患者自我对比手术前那种难以忍受的疼痛与手术后的情况,得出正确的选择是可以理解的,这也为采用显微血管减压术治疗三叉神经痛增强了信心。 随访中患者较高的满意度表明,此手术仍不失为三叉神经痛治疗的较好方法。
      2、 手术后早期治愈率并不可靠。随访中发现,手术后疼痛未缓解或未完全缓解者大多数表示不满意。这些患者均为开展显微血管减压手术早期的病例。近年来由于注重 了受累血管的识别,尤其是那些无名小动脉与三叉神经相交叉或在脑干处相接触,或多根侵犯血管存在或动脉环隐蔽的情况,对静脉压迫电凝切断,也采用完全切开 神经周围增厚的蛛网膜,以伸直三叉神经根的方法,皆获得了满意的效果。
      3、在显微血管减压手术后,尽管疼痛缓解,如果仍遗留有面部感觉障碍或听力障碍等并发症,患者是不会满意的。行血管减压不仅仅为了缓解疼痛,还必须注意保 留神经功能,这是有别于三叉神经痛其他外科方法的重要一点。

      八、伽玛刀治疗三叉神经痛

      伽玛刀问世30多年来,已成为立体定向放射外科领域最重要的手段。伽玛刀镇痛的原理就是将伽玛射线聚焦于预选的与疼痛有关的脑部神经核团或痛觉传导通路 上,一次大剂量照射毁损痛觉的传导通路、阻断痛觉的传导而达到镇痛的效果。应用伽玛刀治疗三叉神经痛也取得了一定疗效。
      应用伽玛刀治疗是先通过影像学定位,计算出三叉神经根的三维坐标,再将聚焦的伽玛射线会聚在靶点,治疗医师通过对剂量大小的控制,可阻断痛觉的传导。治疗 过程简单,患者痛苦小,易于接受。但一次治疗费用昂贵,约在2万元左右。根据从事伽玛刀工作的业内专家透露,伽玛刀治疗三叉神经痛的成功率在60%左右, 且有复发可能。来我院治疗的病人中就有很多做过伽玛刀治疗没有治愈的,其中新加坡病人杜某就是例证之一。
      根据目前的经验,适合伽玛刀治疗的条件为:
      ①其他治疗无效的顽固型带状疱疹后三叉神经痛
      ②诊断为继发性三叉神经痛,经影像学检查颅内有较小的肿瘤或血管畸形,可应用伽玛刀治疗其原发病变。一般随原发病变的好转,疼痛也会缓解。

三叉神经痛的病因

      三叉神经痛分为原发性三叉神经痛和继发性三叉神经痛,人们常说的三叉神经痛是指原发性三叉神经痛。

      一、原发性三叉神经痛的病因

      过去认为原发性三叉神经痛并无特殊病理改变。近年来对三叉神经痛的病因有了进一步的认识,大致归纳为以下两种原因:
      ⑴中枢性病因
      三叉神经痛的阵发性提示一种感觉性癫痫样的放电,放电部位可能在三叉神经脊束核内或中枢其它部位。三叉神经痛的突然发作、持续时间短暂、有扳机点、抗癫痫 治疗有效、加之在疼痛发作时中脑处记录到局灶性癫痫样放电均支持中枢性病因学说。但此学说难以解释临床所见的许多现象。
      ⑵周围性病因
      即病因在半月节到桥脑之间的后根部分,文献报告多倾向于周围病变,有以下学说:①机械性压迫或牵拉三叉神经根,主要是临近的血管压迫三叉神经根。②动脉硬 化引起三叉神经的供血不足。③多发性硬化或自发性脱髓鞘疾病。④家族性三叉神经痛。多数临床资料表明血管压迫三叉神经根是原发性三叉神经痛的主要病因。

      总之,目前国内外医学界对原发性三叉神经痛的病因尚无一致意见,因此,临床治疗方案难以针对病因来确立。现有治疗方法多是以缓解症状、消除疼痛即所谓的对症治疗为目的。

      二、继发性三叉神经痛的病因

      继发性三叉神经痛,在临床上较少见,主要为颅内和颅底骨的肿瘤、血管畸形、蛛网膜粘连增厚、多发性硬化等原因导致的三叉神经痛。继发性三叉神经痛的病因可 通过辅助检查,如:颅底X线照片、脑血管造影 、脑室造影、CT或核磁共振检查来发现原发病灶。明确病因,以助诊断,针对原因进行处理。

- 作者: 冯唐 2007年01月15日, 星期一 20:48  回复(7) |  引用(0) 加入博采

原始的xcopy命令,解决你的拷贝备份问题
C:\Documents and Settings\Administrator>xcopy /?
复制文件和目录树。

XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
                           [/C] [/I] [/Q] [/F] [/L] [/H] [/R] [/T] [/U]
                           [/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z]
                           [/EXCLUDE:file1[+file2][+file3]...]

  source       指定要复制的文件。
  destination  指定新文件的位置和/或名称。
  /A           只复制有存档属性集的文件,
               但不改变属性。
  /M           只复制有存档属性集的文件,
               并关闭存档属性。
  /D:m-d-y     复制在指定日期或指定日期以后改变的文件。
               如果没有提供日期,只复制那些源时间
               比目标时间新的文件。
  /EXCLUDE:file1[+file2][+file3]...
               指定含有字符串的文件列表。如果有任何
               字符串与要被复制的文件的绝对路径
               相符,那个文件将不会得到复制。
               例如,指定如 \obj\ 或 .obj 的字符串会排除
               目录 obj 下面的所有文件或带有
               .obj 扩展名的文件。
  /P           创建每个目标文件前提示。
  /S           复制目录和子目录,除了空的。
  /E           复制目录和子目录,包括空的。
               与 /S /E 相同。可以用来修改 /T。
  /V           验证每个新文件。
  /W           提示您在复制前按键。
  /C           即使有错误,也继续复制。
  /I           如果目标不存在,又在复制一个以上的文件,
               则假定目标一定是一个目录。
  /Q           复制时不显示文件名。
  /F           复制时显示完整的源和目标文件名。
  /L           显示要复制的文件。
  /H           也复制隐藏和系统文件。
  /R           改写只读文件。
  /T           创建目录结构,但不复制文件。不
               包括空目录或子目录。/T /E 包括
               空目录和子目录。
  /U           只复制已经存在于目标中的文件。
  /K           复制属性。一般的 Xcopy 会重设只读属性。
  /N           用生成的短名复制。
  /O           复制文件所有权和 ACL 信息。
  /X           复制文件审核设置(隐含 /O)。
  /Y           禁止提示以确认改写一个
               现存目标文件。
  /-Y          导致提示以确认改写一个
               现存目标文件。
  /Z           用重新启动模式复制网络文件。

命令选项 /Y 可以预先在 COPYCMD 环境变量中设置。
这可能被命令行上的 /-Y 改写。

C:\Documents and Settings\Administrator>
Microsoft Windows 2000 [Version 5.00.2195]
(C) 版权所有 1985-2000 Microsoft Corp.

C:\Documents and Settings\Administrator>start /?
启动另一个窗口运行指定的程序或命令。

START ["title"] [/Dpath] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
      [/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
      [/WAIT] [/B] [command/program]
      [parameters]

    "title"     在窗口标题栏中显示的标题。
    path        起始目录
    B           在不创建新窗口的情况下开始应用程序。 除非
                启动 ^C 处理,否则该应用程序会忽略 ^C 处理;
                 ^Break 是唯一可以中断该应用程序的方式
    I           新环境是传递给 cmd.exe 的原始环境,
                而不是当前环境
    MIN         开始时窗口最小化
    MAX         开始时窗口最大化
    SEPARATE    在分开的空间内开始 16 位 Windows 程序
    SHARED      在分共享的空间内开始 16 位 Windows 程序
    LOW         在 IDLE 优先级类别开始应用程序
    NORMAL      在 NORMAL 优级类别开始应用程序
    HIGH        在 HIGH 优先级类别开始应用程序
    REALTIME    在 REALTIME 优先级类别开始应用程序
    ABOVENORMAL 在 ABOVENORMAL 优先级类别开始应用程序
    BELOWNORMAL 在 BELOWNORMAL 优先级类别开始应用程序
    WAIT        启动应用程序并等候它结束
    command/program
                如果是内部 cmd 命令或批文件,那么该命令处理器是
                用 /K 命令选项运行 cmd.exe 的。这表示该窗口在命令运行
                后仍然存在。

                如果不是内部 cmd 命令或批文件,则是一个程序,并
                作为窗口应用程序或控制台应用程序运行。

    parameters  这些为传送到命令/程序的参数


如果命令扩展名被启用,通过命令行或 START 命令的外部命令
调用会如下改变:

将文件名作为命令键入,非可执行文件    可以通过文件关联调用。
    (例如, WORD.DOC 会调用跟 .DOC 文件扩展名关联的应用程序)。
    关于如何从命令脚本内部创建这些关联,请参阅 ASSOC 和
     FTYPE 命令。

执行的应用程序是 32-位 GUI 应用程序时,CMD.EXE 不等应用
    程序终止就返回命令提示。如果在命令脚本内执行,该新行为
    则不会发生。

如果执行的命令行的第一个符号是不带扩展名或路径修饰符的
    字符串 "CMD","CMD" 会被COMSPEC 变量的数值所替换。这
    防止从当前目录抓出 CMD.EXE。

如果执行的命令行的第一个符号没有扩展名,CMD.EXE 会使用
    PATHEXT 环境变量的数值来决定要以什么顺序寻找哪些扩展
    名。PATHEXT 变量的默认值是:

        .COM;.EXE;.BAT;.CMD

    请注意,该语法跟 PATH 变量的一样,分号隔开不同的元素。

查找可执行文件时,如果没有相配的扩展名,看一看该名称是否
与目录名相配。如果确实如此,START 会在那个路径上调用
Explorer。如果从命令行执行,则等同于对那个路径作 CD /D。

C:\Documents and Settings\Administrator>

- 作者: 冯唐 2007年01月4日, 星期四 10:05  回复(0) |  引用(0) 加入博采

12月14日是我侄女的生日
真想见一下我的侄女。还有几天就放假了

- 作者: 冯唐 2006年12月23日, 星期六 19:22  回复(0) |  引用(0) 加入博采

Oracle导入程序Imp的使用详解
摘要:引用 http://okone96.itpub.net/post/9033/196742 引用 http://blogger.org.cn/blog/more.asp?name=RandomRen&id=16872 查看全文

- 作者: 冯唐 2006年11月23日, 星期四 15:15  回复(0) |  引用(0) 加入博采

心跳线的制作方法
摘要:一头是568A的,一头是568B的就可以了 网线的做法友好多种的,局域网就是将单独的微机或终端,利用网络相互连接起来,遵循一定的协议,进行信息交换,实现资源共享。网线常用的有:双绞线、同轴电缆、光纤等。双绞线可按其是否外加金属网丝套的屏蔽层而区分为屏蔽双绞线(STP)和非屏蔽双绞线(UTP)。从性价比和可维护性出发,大多数局域网使用非屏蔽双绞线(UTP- Unshielded Twisted pair) 作为布线的传输介质来组网。 查看全文

- 作者: 冯唐 2006年10月7日, 星期六 14:53  回复(0) |  引用(0) 加入博采

已锁定
此日志的浏览权限已被作者锁定,请同作者联系,发送短消息,如果你的身份符合作者的要求,点击此处可以进行浏览

- 作者: 冯唐 2006年10月6日, 星期五 12:07  回复(0) |  引用(0) 加入博采

laszlo安装
摘要:openlaszlo(开源拉兹罗)是一个新兴开源RIA架构,尽管他不如现在的Ajax那么火爆,也不如Flex那么 根正苗红,但是他的独特之处是别的开发平台所不具备的。具体特性,整理如下: * 多种运行时目标选择,不只是swf,而且还有dhtml,将来会考虑在移动设备等其他硬件上运行 laslzo应用。 查看全文

- 作者: 冯唐 2006年10月6日, 星期五 11:56  回复(0) |  引用(0) 加入博采

MySQL字符集及MySQL编码转换
今天找到这篇文章,里面提到从latin1到UTF8的MySQL编码转换。收藏一下,最近要将所有的数据库都转一次,一直错误的使用latin1,再不转以后麻烦大了。

出处:未知

个人建议,数据库字符集尽量使用utf8(utf-8),以使你的数据能很顺利的实现迁移,因为utf8字符集是目前最适合于实现多种不同字符集之间的转换的字符集,尽管你在命令行工具上无法正确查看数据库中的内容,我依然强烈建议使用utf8作为默认字符集.
接下来是完整的一个例子:
1.创建数据库表

  1. mysql>CREATE DATABASE IF NOT EXISTS my_db default charset utf8 COLLATE utf8_general_ci;

#注意后面这句话 “COLLATE utf8_general_ci“,大致意思是在排序时根据utf8编码格式来排序
#那么在这个数据库下创建的所有数据表的默认字符集都会是utf8了

  1. mysql>create table my_table (name varchar(20) not null default '')type=myisam default charset utf8;

#这句话就是创建一个表了,制定默认字符集为utf8

2.写数据
通过php直接插入数据:

  1. <?php
  2. mysql_connect('localhost','user','password');
  3. mysql_select_db('my_db');
  4.  
  5. //请注意,这步很关键,如果没有这步,所有的数据读写都会不正确的
  6. //它的作用是设置本次数据库联接过程中,数据传输的默认字符集
  7. mysql_query("set names utf8;");
  8.  
  9. //必须将gb2312(本地编码)转换成utf-8,也可以使用iconv()函数
  10. mysql_query(mb_convet_encoding("insert into my_table values('测试');", "utf-8", "gb2312"));
  11. ?>

通过页面提交插入数据:

  1. <?php
  2. //输出本页编码为utf-8
  3. header("content-type:text/html; charset=utf-8");

  4. mysql_connect('localhost','user','password');
  5. mysql_select_db('my_db');

  6. if(isset($_REQUEST['name'))
  7. {
  8. //由于上面已经指定本页字符集为utf-8了,因此无需转换编码
  9. mysql_query(sprintf("insert into my_table values('%s');", $_REQUEST['name']));
  10. }

  11. $q = mysql_query("select * from my_table");
  12. while($r = mysql_fetch_row($q))
  13. {
  14. print_r($r);
  15. }
  16. ?>

  17. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  18. <form action="" method="post">
  19. <input type="text" name="name" value="">
  20. <input type="submit" value='submit'>
  21. </form>

自此,使用utf8字符集的完整的例子结束了.
如果你想使用gb2312编码,那么建议你使用latin1作为数据表的默认字符集,这样就能直接用中文在命令行工具中插入数据,并且可以直接显示出来.而不要使用gb2312或者gbk等字符集,如果担心查询排序等问题,可以使用binary属性约束,例如:

  1. create table my_table ( name varchar(20) binary not null default '')type=myisam default charset latin1;

附:旧数据升级办法
以原来的字符集为latin1为例,升级成为utf8的字符集。原来的表: old_table (default charset=latin1),新表:new_table(default charset=utf8)。
第一步:导出旧数据

  1. mysqldump --default-character-set=latin1 -hlocalhost -uroot -B my_db --tables old_table > old.sql

第二步:转换编码

  1. iconv -t utf-8 -f gb2312 -c old.sql > new.sql

在这里,假定原来的数据默认是gb2312编码。
第三步:导入
修改old.sql,增加一条sql语句: “SET NAMES utf8;“,保存。

  1. mysql -hlocalhost -uroot my_db < new.sql

大功告成!

- 作者: 冯唐 2006年09月29日, 星期五 17:55  回复(0) |  引用(0) 加入博采

WebWork入门教程--创建你第一个WebWork action
摘要:本文,摘录了Manning出版社出版,Patrick Lightbody 和 Jason Carreira所著《WebWork in Action》中关于怎样创建WebWork action和它的视图以及将两者柔和在一起的部分。 查看全文

- 作者: 冯唐 2006年08月26日, 星期六 16:15  回复(0) |  引用(2) 加入博采

通过JDBC连接oracle数据库的十大技巧
摘要:Java数据库连接(JDBC)API是一系列能够让Java编程人员访问数据库的接口,各个开发商的接口并不完全相同。在使用多年的Oracle公司的JDBC后,我积累了许多技巧,这些技巧能够使我们更好地发挥系统的性能和实现更多的功能。 查看全文

- 作者: 冯唐 2006年08月21日, 星期一 19:45  回复(0) |  引用(2) 加入博采

google搜索原理论文的中文版
摘要:这篇文章中,我们介绍了google,它是一个大型的搜索引擎(of a large-scale search engine)的原型,搜索引擎在超文本中应用广泛。Google的设计能够高效地抓网页并建立索引,它的查询结果比其它现有系统都高明。这个原型的全文和超连接的数据库至少包含24‘000‘000个网页。我们可以从 http://google.stanford.edu/ 下载。 查看全文

- 作者: 冯唐 2006年08月21日, 星期一 10:36  回复(1) |  引用(2) 加入博采

Openlaszlo 开发技术简介
摘要:主要内容 什么是Openlaszlo Openlaszlo与RIA Openlaszlo案例 LZX语言特色 现状与展望 什么是Openlaszlo 一个开源的RIA开发平台 一种客户端编程语言 一个产品化的web2.0解决方案 一种面向未来的web应用技术 查看全文

- 作者: 冯唐 2006年08月20日, 星期日 11:32  回复(1) |  引用(0) 加入博采

天下没有免费的午餐
以前帮助过很多网友。因为他们那时很无助,因为他们那时很需要你去帮助,因为我也有需要别人帮助的时候,但是我发现了这样一件怪事,就是当你帮助别人的时候,他会答应你很多的实现不了的东西。当然我也不会认真听。可是当你真的那个时候需要他来帮你的时候他去不知道消失到了何处,就像是蒸发了一样。
然而,那些帮助过我的人我很希望他们能用的上我,但是他们不会来找我帮忙,难道他们认为我也是这样的人。让我感到很无奈。所以想到了一个大家都不会吃亏的办法,那就是交换。当你有需要的时候首先问一下对方需要什么,如果你能为他提供,那么你们就可以交换了。这不是一种交易,不需要价值的等同。只是表示一下公平,让每个人的心里都得到一种平衡。

- 作者: 冯唐 2006年08月17日, 星期四 17:39  回复(4) |  引用(2) 加入博采

oracle 切换归档方式
首先用一个用户的身份去登陆,
然后
connect 超级用户(sys)/密码(password) as sysdba;
shutdown immediate;
startup mount;
(startup restrict open)
Alter database archivelog;
Archive log list;
Archive log start;
startup;
完成。

   在rac下,更改归档模式不像单机或主/备模式下那么容易更改,主要是因为cluster_database参数的缘故。通过将 cluster_database参数从true改为false,可以顺利用更改单机归档模式的方式来更改归档设置。更改完毕后,再将 cluster_database参数改回true即可。至于归档日志,可以通过nfs共享来保存两边共有的归档日志,当然也可以用rman直接各自备各 个节点的归档日志,当需要恢复时,再将归档日志合并即可。     1、关闭运行中的数据库

    # su - oracle

    $sqlplus /nolog

    sql>connect /as sysdba

    sql>shutdown immediate

    2、导出现有数据库的spfile文件

    如果没有spfile,可以先创建spfile

    sql>create spfile from pfile;

    然后导出spfile

    sql>create pfile='/oracle/pfile.ora' from spfile; //将pfile创建到/oracle目录下

    3、修改/oracle/pfile.ora文件

    更改cluster_database参数为false。同时可以添加自动归档参数log_archive_start=true,如下:

    *.log_archive_start=true

    *.cluster_database=false

    *.log_archive_dest='LOCATION=/oracle/archivelog' //将归档日志存放到/oracle/archivelog文件系统下,便于管理

    *.log_archive_format=%t_%s.dbf

    4、导入已修改的spfile

    在数据库关闭状态下:

    sql>create spfile from pfile='/oracle/pfile.ora';

    5、启动数据库到加载状态(mount)

    $sqlplus /nolog

    sql>connect /as sysdba

    sql>startup mount

    6、更改数据库运行模式为归档模式

    $sqlplus /nolog

   sql>connect /as sysdba

    sql>startup mount

    sql>alter database archivelog; //更改为归档模式

    sql>alter database open; //将数据库打开

    sql>archive log list; //检查数据库归档参数是否已经正确更改

    7、将cluster_database参数更改回true

    首先关闭数据库

    $sqlplus /nolog

    sql>connect /as sysdba

    sql>shutdown immediate

    sql>create spfile from pfile='/oracle/pfile01.ora'; //将现有spfile导出

    修改/oracle/pfile01.ora,将cluster_database参数更改为true;

    8、导入新修改的pfile01.ora文件

    $sqlplus /nolog

    sql>connect /as sysdba

    sql>create spfile from pfile='/oracle/pfile01.ora';

    sql>startup //正常启动数据库

    Oracle 9i RAC 归档方式修改方法:

    1. change the cluster_server=false in a instance

    2.shutdown both instances;

    3.change proper parameter about archivelog mode.
   
    4.startup mount the instance from set 1.

    5.login db as sysdba and alter database archivelog;

    6.shutdown instance and change parameter cluster_server=true

    7.start both instance;

    一般的修改方法.

    关闭数据库,备份已有的数据

    改变数据库的运行方式是对数据库的重要改动,所以要对数据库做备份,对可能出现的问题作出保护。

    启动Instance ,Mount数据库但不打开数据库,来改变归档方式

    sqldba lmode=y(svrmgrl)

    sqldba>connect internal

    sqldba>startup mount

    sqldba>alter database archivelog;

    使能自动存档

    在初始化文件init*.ora(一般放ORACLE根目录的下层目录dbs下)加参数:

    log_archive_start=true

    指定存档的重做登录文件名和存放的位置

    同样是在初始化文件init*.ora中加入下面的参数:

    log_archive_format=%S.arc

    log_archive_dest=/arch12/arch (arch12 是日志文件存放的目录)

    关闭数据库,重新启动数据库,归档方式转换完成。

- 作者: 冯唐 2006年08月16日, 星期三 21:23  回复(0) |  引用(2) 加入博采

中国贫富标准线

超级大富豪:年收入在5000万以上

大富豪:年收入在1000—5000万

富豪:年收入在300—1000万之间

富人:年收入在100—300万之间

高产者:年收入在30—100万之间

中产者:年收入在15—30万之间

低产者:年收入在8—15万之间

穷 人:年收入在3—8万之间

很穷的人:年收入在1—3万之间

非常穷的穷人:年收入在5千—1万之间

穷得没衣服穿的人:年收入在1千—5千之间

穷得求生不得求死不能的穷人:年收入在100 —1000元之间

穷得几乎要死的穷人:年收入在30—100元之间

死路一条的穷人:年收入在30元以下

- 作者: 冯唐 2006年08月16日, 星期三 14:15  回复(1) |  引用(2) 加入博采

windows 操作系统 的序列号
Windows XP Professional SP2 VOL 官方简体中文正式版[592MB][ISO]
CD-KEY: XP8BF-F8HPF-PY6BX-K24PJ-TWT6M
4.15日 序列号更新N组 通过官方正版验证
CM3HY-26VYW-6JRYC-X66GX-JVY2D 
DP7CM-PD6MC-6BKXT-M8JJ6-RPXGJ 
F4297-RCWJP-P482C-YY23Y-XH8W3 
HH7VV-6P3G9-82TWK-QKJJ3-MXR96 
HCQ9D-TVCWX-X9QRG-J4B2Y-GR2TT
新增俩组:
QC986-27D34-6M3TY-JJXP9-TBGMD
MRX3F-47B9T-2487J-KWKMF-RPWBY
Windows 2003下载
CD-KEY:
FFK3M-T96TB-C4HW9-GQKRJ-HV67M
FF38J-F4HVH-PRPR7-KK3MK-CPFDY
HB232-TMYVR-M3QTG-QHH4P-TBH3Y
JGDM7-R99DD-CJ9YP-F46R4-V8RDY
CMG77-7YBB6-T8K4W-Q9QBM-HDBQY
JJQRD-DKYHG-PJ43Q-JGKF3-47QHM
HQKK3-4XWQQ-74G97-HVDWX-HKCMB
JMQC9-VRYQX-48BTD-FVYGW-PC2MB
DQ22C-DW8VT-PFCP3-P9RJT-32JYB
JCQ6P-3GYX6-28P8W-R33W6-2CFDY
GTF72-G2P29-7QBW2-YVT3P-B94DY
D29K4-KG3B8-F7HGK-8VGTT-783HM
HJPRJ-44YRR-8KG28-7KMT9-76H3Y

- 作者: 冯唐 2006年08月10日, 星期四 14:15  回复(0) |  引用(2) 加入博采

七夕情人节祝福有情人终成眷属
【七】色云彩漫天开
【夕】照余辉踏浪来
【情】怀依旧景物改
【人】在天涯心何在
【节】竹摇响相思曲
【祝】福随风任飘絮
【福】寿安康求天庇
【有】缘自然他乡遇
【情】到深处无怨尤
【人】事沧桑却何求
【终】老一世随性修
【成】败到头且自由
【眷】恋往事已烟云
【属】意何处但任恁 

- 作者: 冯唐 2006年07月31日, 星期一 09:38  回复(0) |  引用(2) 加入博采

VC常用开发技巧总结
从网络上获取的,感觉不错,先保留下来.

(1) 如何通过代码获得应用程序主窗口的 指针?
主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。
AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED)
//使程序最大化.


(2) 确定应用程序的路径
Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。
Example:
TCHAR
exeFullPath[MAX_PATH] // MAX_PATH在API中定义了吧,好象是
128
GetModuleFileName(NULL,exeFullPath,MAX_PATH)




(3) 如何在程序中获得其他程序的 图标?
两种方法:
(1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,
(2) SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性, 类型等.
Example(1):
在程序窗口左上角显示 NotePad图标.
void CSampleView:
OnDraw(CDC * pDC)
{
if( :: SHGetFileInfo(_T("c:\\pwin95\\notepad.exe"),0,
&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
{
pDC ->DrawIcon(10,10,stFileInfo.hIcon)
}
}
Example(2):同样功能,Use ExtractIcon Function
void CSampleView:: OnDraw(CDC *pDC)
{
HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
("NotePad.exe"),0)
if (hIcon &&hIcon!=(HICON)-1)
pDC->DrawIcon(10,10,hIcon)
}
说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点.


(4) 获得各种目录信息
Windows目录: Use "GetWindowsDirectory"
Windows下的system目录: Use "GetSystemDirectory"
temp目录: Use "GetTempPath"
当前目录: Use "GetCurrentDirectory"

请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区后两个相反.



(5) 如何自定义消息
1) 手工定义消息,可以这么写
#define WM_MY_MESSAGE(WM_USER+100),
MS 推荐的至少是 WM_USER+100

(2)写消息处理函数,用
WPARAM,LPARAM返回LRESULT.
LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)

{
temp目录: Use "GetTempPath"
//加入你的处理函数 irectory"
}

(6) 如何改变窗口的图标?
向窗口发送 WM_SECTION消息。
Example:
HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON)
ASSERT(hIcon)
AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)


(7) 如何改变窗口的缺省风格?
重载 CWnd:: PreCreateWindow 并修改CreateSTRUCT结构来指定窗口风格和其他创建信息.
Example: Delete "Max" Button and Set original
Window's Position and Size

BOOL CMainFrame:: PreCreateWindow
(CreateSTRUCT &cs)
{
cs.style &=~WS_MAXINIZEMOX

cs.x=cs.y=0
cs.cx=GetSystemMetrics(SM_CXSCREEN/2)
cs.cy=GetSystemMetrics(SM_CYSCREEN/2)

return CMDIFramewnd ::PreCreateWindow(cs)
}

(8) 如何将窗口居中显示?
Call Function CWnd::
Center Windows

Example(1):
Center Window( ) //Relative to it's parent
// Relative
to Screen
Example(2):
Center Window(CWnd:: GetDesktopWindow( ))
//Relative to
Application's MainWindow
AfxGetMainWnd( ) ->
Center Window( )


(9) 如何让窗口和 MDI窗口一启动就最大化和最小化?
先说窗口。
在 InitStance 函数中设定 m_nCmdShow的取值.
m_nCmdShow=SW_SHOWMAXMIZED //最大化
m_nCmdShow=SW_SHOWMINMIZED //最小化
m_nCmdShow=SW_SHOWNORMAL //正常方式

MDI窗口:
如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE

如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。

(10) 如何限制窗口的大小?
也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:
(11) 如何使窗口不可见?
很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow控制.

(12) 如何创建一个字回绕的CEditView
重 载CWnd : : PreCreateWindow和修改CreateSTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL 风格位, 由于CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要修改cs . style。

BOOL CSampleEDitView : : PreCreateWindow (CreateSTRUCT&cs)
{
//First call basse class function .
BOOL bResutl =CEditView : : PreCreateWindow (cs)

// Now specify the new window style .
cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL)
return bResult
}


(13) 如何使程序保持极小状态?
这么办: 在恢复程序窗体大小时,Windows会发送WM_QUERY-OPEN消息,用 ClassWizard设置成员函数
OnQueryOpen() ,add following code:

Bool CMainFrame:: OnQueryOpen( )
{
Return false
}

(14) 移动窗口
调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口的大小。
//Move window to positoin 100 , 100 of its parent window .
SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)

(15) 通用控件的显示窗口
MFC 提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件, CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。

(16) 重置窗口的大小
调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可用CWnd : : MoveWindow 但必须指定窗口的位置。
// Get the size of the window .
Crect reWindow
GetWindowRect (reWindow )

//Make the window twice as wide and twice as tall .
SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,

reWindow . Height () * 2,
SWP_NOMOVE |SWP_NOZORDER )

(17) 如何单击除了窗口标题栏以外的区域使窗口移动
当 窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于 对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。
UINT CSampleDialog : : OnNcHitTest (Cpoint point )
{
UINT nHitTest =Cdialog: : OnNcHitTest (point )
return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest
}

上述技术有两点不利之处,
其一是在窗口的客户区域双击时,窗口将极大;
其二, 它不适合包含几个视窗的主框窗口。
还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。
void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point
)
{
CView : : OnLButtonDow (nFlags , pont )

//Fool frame window into thinking somene clicked
on
its caption bar .
GetParentFrame ( ) —> PostMessage (
WM_NCLBUTTONDOWN ,
HTCAPTION , MAKELPARAM (poitn .x , point .y) )

}
该技术也适用于对话框和基于对的应用程序,只是不必调用
CWnd: :GetParentFrame 。
void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )
{
Cdialog : : OnLButtonDow (nFlags, goint )
//Fool dialog into thinking simeone clicked on its
caption bar .
PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x
, point. y
) )
}

(18) 如何改变视窗的背景颜色
Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。
//Paint area that needs to be erased.
BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)
{
// Create a pruple brush.
CBrush Brush (RGB (128 , 0 , 128) )

// Select the brush into the device context .
CBrush* pOldBrush = pDC—>SelcetObject (&brush)

// Get the area that needs to be erased .
CRect reClip
pDC—>GetCilpBox (&rcClip)
//Paint the area.
pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )

//Unselect brush out of device context .
pDC—>SelectObject (pOldBrush )

// Return nonzero to half fruther processing .
return TRUE
}

(19) 如何改变窗口标题
调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。
//Set title for application's main frame window .
AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )

//Set title for View's MDI child frame window .
GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")
)

//Set title for dialog's push button control.
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )
如 果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在 WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。
AfxSetWindowText的实现如下:
voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )
{
itn nNewLen= Istrlen (Ipaznew)
TCHAR szOld [256]
//fast check to see if text really changes (reduces
flash in the
controls )
if (nNewLen >_contof (szOld)
|| : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen
|| Istrcmp (szOld , IpszNew)! = 0
{
//change it
: : SetWindowText(hWndCtrl , IpszNew )
}
}

(20) 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。
BOOL CMainFrame : : PreCreateWindow (CreateSTRUCT&cs)
{
//Turn off FWS_ADDTOTITLE in main frame .
cs.styel & = ~FWS_ADDTOTITLE  
return CMDIFrameWnd : : PreCreateWindow (cs )
}
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南

(21) 如何获取有关窗口正在处理的当前消息的信息
调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。
viod CMainFrame : : OnCommmonMenuHandler ( )
{
//Display selected menu item in debug window .
TRACE ("Menu item %u was selected . \n" ,

(22) 如何在代码中获取工具条和状态条的指针
缺 省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_TOOLBAR)

(23) 如何使能和禁止工具条的工具提示
如 果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用 CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
{
ASSERT_VALID (m_wndToolBar)

DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

else
dwStyle & = ~CBRS_TOOLTIPS

m_wndToolBar.SetBarStyle (dwStyle )
}

(24) 如何创建一个不规则形状的窗口
可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。
给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。
Class CRoundDlg : public CDialog
{

private :
Crgn m_rgn : // window region

}
修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口:
BOOL CRoundDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//Get size of dialog .
CRect rcDialog
GetClientRect (rcDialog )

// Create region and assign to window .
m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )
SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )

return TRUE
}

通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。
voik CRoundDlg : : OnPaint ( )
{
CPaintDC de (this) // device context for painting
.
//draw ellipse with out any border
dc. SelecStockObject (NULL_PEN)
//get the RGB colour components of the sphere color
COLORREF color= RGB( 0 , 0 , 255)
BYTE byRed =GetRValue (color)
BYTE byGreen = GetGValue (color)
BYTE byBlue = GetBValue (color)

// get the size of the view window
Crect rect
GetClientRect (rect)

// get minimun number of units
int nUnits =min (rect.right , rect.bottom )

//calculate he horiaontal and vertical step size
float fltStepHorz = (float) rect.right /nUnits
float fltStepVert = (float) rect.bottom /nUnits


int nEllipse = nUnits/3 // calculate how many to
draw
int nIndex
// current ellipse that is being draw

CBrush brush
/ bursh used for ellipse fill color
CBrush *pBrushOld // previous
brush that was selected into dc
//draw ellipse , gradually moving towards upper-right
corner
for (nIndex = 0 nIndes < + nEllipse nIndes++)
{
//creat solid brush
brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).
( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)
/nEllipse ) ) )

//select brush into dc
pBrushOld= dc .SelectObject (&brhsh)

//draw ellipse
dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,
rect. right -( (int) fltStepHorz * nIndex )+ 1,
rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)

//delete the brush
brush.DelecteObject ( )
}
}

最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。
UINT CRoundDlg : : OnNchitTest (Cpoint point )
{
//Let user move window by clickign anywhere on thewindow .
UINT nHitTest = CDialog : : OnNcHitTest (point)
rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest

}

(25) 如何获取应用程序的 实例句柄?
应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄.
Example: HANDLE hInstance=AfxGetInstanceHandle()

(26) 如何编程结束应用程序?
这是个很简单又是编程中经常要遇到的问题.
向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据.
Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)

还可以创建一个自定义的函数 Terminate Window
void Terminate Window(LPCSTR pCaption)
{
CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)

if (pWnd)

pWnd ->SendMessage(WM_CLOSE)
}

说 明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。

(27) 如何创建和使用无模式对话框
MFC 将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用 ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。
void CSampleDialog : : OnOK ( )
{
// Retrieve and validate dialog data .
if (! UpdateData (TRUE) )
{
// the UpdateData rountine
will set focus to correct item TRACEO (" UpdateData failed during dialog termination .\n")
return
}

//Call DestroyWindow instead of EndDialog .
DestroyWindow ( )
}

void CSampleDialog : : OnCancel ( )
{
//Call DestroyWindow instead of EndDialog .
DestroyWindow ( )
}

其 次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返 回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。
void CSampleDialog : : PostNcDestroy ( )
{
// Declete the C++ object that represents this dialog.
delete this

最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回,
void CMainFrame : : OnSampleDialog ( )
{
//Allocate a modeless dialog object .
CSampleDilog * pDialog =new CSampleDialog
ASSERT_VALID (pDialog) Destroy ( )

//Create the modeless dialog . represents this dialog.
BOOL bResult = pDialog —> Creste (IDD_IDALOG)
ASSERT (bResult )
}



(28) 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。
BOOL CMainFrame : : PreCreateWindow (CreateSTRUCT&cs)
{
//Turn off FWS_ADDTOTITLE in main frame .
cs.styel & = ~FWS_ADDTOTITLE  
return CMDIFrameWnd : : PreCreateWindow (cs )
}
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。

(29) 如何在代码中获取工具条和状态条的指针
缺 省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_TOOLBAR)


(30) 怎样加载其他的应用程序?
三个SDK函数 winexec, shellexecute,createprocess可以使用。
WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。

ShellExecute 较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:\temp\1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦.

ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:\\temp"),SW_SHOWMAXMIZED)

CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:
STARTUPINFO stinfo
//启动窗口的信息
PROCESSINFO procinfo //进程的信息

CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,
NORMAL_PRIORITY_

CLASS,NULL,NULL, &stinfo,&procinfo)

(31) 如何在代码中获取工具条和状态条的指针
缺 省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

(32) 如何使能和禁止工具条的工具提示
如 果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用 CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
{
ASSERT_VALID (m_wndToolBar)

DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

else
dwStyle & = ~CBRS_TOOLTIPS

m_wndToolBar.SetBarStyle (dwStyle )
}

//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_TOOLBAR)

(33) 如何设置工具条标题
工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,例子如下:
int CMainFrame : : OnCreate (LPCreateSTRUCT lpCreateStruct )
{

// Set the caption of the toolbar .
m_wndToolBar.SetWindowText (_T "Standdard")

(34) 如何使窗口始终在最前方?
BringWindowToTop(Handle)
SetWindowPos函数,指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的风格

Example:
void ToggleTopMost(
CWnd *pWnd)
{
ASSERT_VALID(pWnd)

pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?

&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)
}

(35) 如何在对话框中显示一个位图
这要归功于Win 32先进的静态控件和a href="http://www.microsoft.com/" target="_blank">Microsoft的资源编辑器,在对话框中显示位图是很容易的, 只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。

(36) 如何改变对话或窗体视窗的背景颜色
调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。
BOOL CSampleApp : : InitInstance ( )
{


//use blue dialog with yellow text .
SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 ,255 , 0 ) )


}

需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。

首先,给对话基类增加一人成员变量
CBursh :class CMyFormView : public CFormView
{


private :
CBrush m_ brush // background brush


}

其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
CMyFormView : : CMyFormView ( )
{
// Initialize background brush .
m_brush .CreateSolidBrush (RGB ( 0, 0, 255) )
}

最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。
HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor
)

{
// Determine if drawing a dialog box . If we are, return +handle to
//our own background brush . Otherwise let windows handle it .
if (nCtlColor = = CTLCOLOR _ DLG )
return (HBRUSH) m_brush.GetSafeHandle ( )
return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor
)
}

(37) 如何获取一个对话控件的指针
有两种方法。其一,调用CWnd: : GetDlgItem,获取一个CWnd*指针调用成员函数。下例调用GetDlgItem,将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl : : SetPos 函数:
BOOL CSampleDialog : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//Get pointer to spin button .
CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem(IDC_SPIN)
ASSERT _ VALID (pSpin)
//Set spin button's default position .
pSpin —> SetPos (10)

return TRUE
}

其 二, 可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签,然后选择Add Variable …按钮。如果在对话资源编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对话。


(38) 如何禁止和使能控件
控件也是窗口,所以可以调用CWnd : : EnableWindow使能和禁止控件。
//Disable button controls .
m_wndOK.EnableWindow (FALSE )
m_wndApply.EnableWindow (FALSE )


(39) 如何改变控件的字体
由于控件是也是窗口,用户可以调用CWnd: : SetFont指定新字体。该函数用一个Cfont指针,要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字体改为8点Arial字体:
//Declare font object in class declaration (.H file ).
private : Cfont m_font
// Set font in class implementation (.Cpp file ). Note m_wndButton is a
//member variable added by ClassWizard.DDX routines hook the member
//variable to a dialog button contrlo.
BOOL CSampleDialog : : OnInitDialog ( )
{

//Create an 8-point Arial font
m_font . CreateFont (MulDiv (8 , -pDC
—> GetDeviceCaps(LOGPIXELSY) ,72). 0 , 0 , 0 , FW_NORMAL , 0 , 0,0, ANSI_CHARSER, OUT_STROKE_PRECIS ,

CLIP_STROKE _PRECIS , DRAFT _QUALITY
VARIABLE_PITCH |FF_SWISS, _T("Arial") )

//Set font for push button .
m_wndButton . SetFont (&m _font )


}

(40) 如何在OLE控件中使用OLE_COLOR数据类型
诸 如COleControl : : GetFortColor和COleControl : : GetBackColor等函数返回OLE _COLOR数据类型的颜色,而GDI对象诸如笔和刷子使用的是COLORREF数据类型,调用COleControl : : TranslateColor可以很容易地将OLE_COLOR类型改为COLORREF类型。下例创建了一个当前背景颜色的刷子:

void CSampleControl : : OnDraw (CDC* pdc
const Crect& rcBounds , const Crect& rcInvalid
)
{
//Create a brush of the cuttent background color.
CBrush brushBack (TranslateColor (GetBackColor () ) )

//Paint the background using the current backgroundcolor .
pdc—> FilllRect (rcBounds , &brushBack)

//other drawign commands


}

(41) 在不使用通用文件打开对话的情况下如何显示一个文件列表
调用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox,Windows 将自动地向列表框或组合框填充可用的驱动器名或者指定目录中的文件,下例将Windows目录中的文件填充在组合框中:
BOOL CSampleDig : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )
TCHAR szPath [MAX_PATH] = {"c:\\windows"}
int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE |DDL_READONLY|DDL_HIDDEN| DDL_SYSTEM|DDL_ARCHIVE)
return TRUE
}

(42) 为什么旋转按钮控件看起来倒转
需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围,旋转按钮控件的缺省上限为0,缺省下限为100,这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为0到100:
BOOL CAboutDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//set the lower and upper limit of the spin button
m_wndSpin . SetRange ( 0 ,100 )

return TRUE
}

Visual C++ 4.0 Print对话中的Copise旋转按钮控件也有同样的问题:按下Up按钮时拷贝的数目减少,而按下Down 按钮时拷贝的数目增加。

(43) 为什么旋转按钮控件不能自动地更新它下面的编辑控件
如果使用旋转按钮的autu buddy特性, 则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab order菜单项(或者按下Crtl+D)可以设置对话的标签顺序。

(44) 如何用位图显示下压按钮
Windows 95按钮有几处新的创建风格,尤其是BS_BITMAP和BS_ICON,要想具有位图按钮,创建按钮和调用CButton : : SetBitmap或CButton : : SetIcon时要指定BS_BITMAP或BS_ICON风格。

首先,设置按钮的图标属性。然后,当对话初始化时调用CButton: : SetIcon。注意:下例用图标代替位图,使用位图时要小心,因为不知道背景所有的颜色——并非每个人都使用浅灰色。

BOOL CSampleDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//set the images for the push buttons .
BOOL CSampleDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//set the images for the push buttons .
m_wndButton1.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION1))
m_wndButton2.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION2))
m_wndButton3.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION3))

return TRUE
}


(45) 如何一个创建三态下压按钮
可以使用新的BS_PUSHBUTTON 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。

(46) 如何动态创建控件
分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件:
//In class declaration (.H file ).
private : CButton* m _pButton

//In class implementation (.cpp file ) .
m_pButton =new CButton
ASSERT_VALID (m_pButton)
m_pButton —>Create (_T ("Button Title ") , WS_CHILD |WS_VISIBLE |BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )

(47) 如何限制编辑框中的准许字符
如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志,该标志限制 编辑控件只按收数字字符。如果用户需要复杂的编辑控件,可以使用Microsoft 的屏蔽编辑控件,它是一个很有用的OLE定制控件。
如 果希望不使用OLE 定制控件自己处理字符,可以派生一个CEdit类并处理WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用ClassWizard建立一 个 CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : SubclassDlgItem .

//In your dialog class declaration (.H file )
private : CMyEdit m_wndEdit // Instance of your new edit conrol .

//In you dialog class implementation (.CPP file )
BOOL CSampleDialog : : OnInitDialog ( )
{


//Subclass the edit lontrod .
m_wndEdit .SubclassDlgItem (IDC_EDIT,this)


}

使用ClassWizard处理WM_CHAR消息,计算nChar参量并决定所执行的操作,用户可以确定是否修改、传送字符。下例说明了如何显示字母字符,如果字符是字母字符,则调用CWnd OnChar,否则不调用OnChar.
//Only display alphabetic dharacters .
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
{
//Determine if nChar is an alphabetic character.
if (: : IsCharAlpha ( ( TCHAR) nChar ) )
CEdit : : OnChar (nChar, nRepCnt , nFlags )
}

如 果要修改字符,则不能仅仅简单地用修改过的nChar调用CEdit: : OnChar,然后CEdit: : OnChar调用CWnd: : Default获取原来的wParam 和lParam 的值,这样是不行的。要修改一个字符,需要首先修改nChar,然后用修改过的nChar调用CWnd: : DefWindowProc。下例说明了如何将字符转变为大写:
//Make all characters uppercase
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
{
//Make sure character is uppercase .
if (: : IsCharAlpha ( .( TCHAR) nChar)
nChar=: : CharUpper(nChar )

//Bypass default OnChar processing and directly call
//default window proc.
DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))
}



2005-06-01 18:11



feng_shen2002

论 坛 ID:16332
注册日期: 2005-06-01
性  别: ?
来  自:
发贴数量: 5
会员积分: 570
头  衔: 编程爱好者

在线情况: 续:


(48) 如何改变控件的颜色
有 两种方法。其一,可以在父类中指定控件的颜色,或者利用MFC4.0新的消息反射在控件类中指定颜色。 当控件需要重新着色时,工作框调用父窗口(通常是对话框)的CWnd: : OnCrtlColor,可以在父窗口类中重置该函数并指定控件的新的绘画属性。例如,下述代码将对话中的所有编辑控件文本颜色改为红色:
HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)

{
HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor )

//Draw red text for all edit controls .
if (nCtlColor= = CTLCOLOR_EDIT )
pDC —> SetTextColor (RGB (255, 0 , 0 , ) )

return hbr
}

然 而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息 反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。

首先,使用ClassWizard 创建一个CListBox 的派生类并为该类添加下述数据成员。
class CMyListBox publilc CListBox
{

private
COLORREF m_clrFor // foreground color
COLORREF m_clrBack //background color
Cbrush m_brush //background brush

}
其次,在类的构造函数中,初始化数据中。
CMyListBox : : CMyListBox ()
{
//Initialize data members .
m_clrFore =RGB (255 , 255 , 0) //yellow text
m_clrBack=RGB (0 , 0 , 255) // blue background
m_brush . CreateSolidBrush (m _clrBack )
}

最后,使用ClassWizard处理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新的绘画属性。
HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )
{
pDC—>SetTextColor (m_clrFore)
pDC—>SetBkColor (m_clrBack)

return (HBRUSH) m_brush.GetSafeHandle ()
}
现在,控件可以自己决定如何绘画,与父窗口无关。

(49) 当向列表框中添加多个项时如何防止闪烁
调 用CWnd::SetRedraw 清除重画标志可以禁止CListBox(或者窗口)重画。当向列表框添加几个项时,用户可以清除重画标志,然后添加项,最后恢复重画标志。为确保重画列表 框的新项,调用SetRedraw (TRUE) 之后调用CWnd::Invalidate。

//Disable redrawing.
pListBox->SetRedraw (FALSE)

//Fill in the list box gere
//Enable drwing and make sure list box is redrawn.
pListBox->SetRedraw (TRUE)
pListBox->Invalidate ()

(50) 如何向编辑控件中添加文本
由于没有CEdit:: AppendText函数,用户只好自己做此项工作。调用CEdit:: SetSel移动到编辑控件末尾,然后调用CEdit:: ReplaceSel添加文本。下例是AppendText 的一种实现方法:

void CMyEdit:: AppendText (LPCSTR pText)
{
int nLen=GetWindowTextLength ()
SetFocus ()
SetSel (nLen, nLen)

ReplaceSel (pText)
}

(51) 如何访问预定义的GDI对象
可以通过调用CDC:: SlectStockObject使用Windows的几个预定义的对象,诸如刷子、笔以及字体。下例使用了Windows预定义的笔和刷子GDI对象在视窗中画一个椭圆。
//Draw ellipse using stock black pen and gray brush.
void CSampleView:: OnDraw (CDC* pDC)
{
//Determine size of view.
CRect rcView
GetClientRect (rcView)

//Use stock black pen and stock gray brush to draw ellipse.
pDC->SelectStockObject (BLACK_PEN)
pDC->SelectStockObject (GRAY_BRUSH)
//Draw the ellipse.
pDC->Ellipse (reView)
}

也可以调用新的SDK函数GetSysColorBrush获取一个系统颜色刷子,下例用背景色在视窗中画一个椭圆:
void CsampleView:: OnDraw (CDC* pDC)
{
//Determine size of view.
CRect rcView
GetClientRect (rcView)

//Use background color for tooltips brush.
CBrush * pOrgBrush=pDC->SelectObject ( CBrush ::FromHandle( ::GetSysColorBrush (COLOR_INFOBK)))

//Draw the ellipse.
pDC->Ellipse (rcView)

//Restore original brush.
pDC->SelectObject (pOrgBrush)
}

(52) 如何获取GDI对象的属性信息
可以调用GDIObject:: GetObject。这个函数将指定图表设备的消息写入到缓冲区。下例创建了几个有用的辅助函数。
//Determine if font is bold.
BOOL IsFontBold (const CFont&font)
{
LOGFONT stFont
font.GetObject (sizeof (LOGFONT), &stFont)
return (stFont.lfBold)? TRUE: FALSE
}

//Return the size of a bitmap.
CSize GetBitmapSize (const CBitmap&bitmap)
{
BITMAP stBitmap
bitmap.GetObject (sizeof (BITMAP), &stBitmap)
return CSize (stBitmap.bmWidth, stBitmap.bmHeight)
}

//Create a pen with the same color as a brush.
BOOL CreatePenFromBrush (Cpen&pen, cost Cbrush&brush)
{
LOGBRUSH stBrush
brush.Getobject (sizeof (LOGBRUSH), &stBrush)
return pen. Createpen (PS_SOLID, 0, stBrush.ibColor)
}

(53) 如何实现一个橡皮区矩形
CRectTracker是一个很有用的类,可以通过调用CRectTracker::TrackRubberBand 响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。
下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。

首先,在文件档中声明一个CRectTracker数据成员:
class CSampleView : Public CView
{

public :
CrectTracker m_tracker

}

其次,在文档类的构造函数中初始化CRectTracker 对象:
CSampleDoc:: CSampleDOC ()
{
//Initialize tracker position, size and style.
m_tracker.m_rect.SetRect (0, 0, 10, 10)
m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine
}

然后,在OnDraw函数中画椭圆和踪迹矩形:
void CSampleView:: OnDraw (CDC* pDC)
{
CSampleDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)

//Select blue brush into device context.
CBrush brush (RGB (0, 0, 255))
CBrush* pOldBrush=pDC->SelectObject (&brush)

//draw ellipse in tracking rectangle.
Crect rcEllipse
pDoc->m_tracker.GetTrueRect (rcEllipse)
pDC->Ellipse (rcEllipse)

//Draw tracking rectangle.
pDoc->m_tracker.Draw (pDC)
//Select blue brush out of device context.
pDC->Selectobject (pOldBrush)
}

最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。
void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
{
//Get pointer to document.
CSampleDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)

//If clicked on ellipse, drag or resize it.Otherwise create a
//rubber-band rectangle nd create a new ellipse.
BOOL bResult=pDoc->m_trcker.HitTest (point)!= CRectTracker::hitNothing

//Tracker rectangle changed so update views.
if (bResult)
{
pDoc->m_tracker.Track (this,point,TRue)
pDoc->SetModifiedFlag ()
pDoc->UpdateAllViews (NULL)
}

else
pDoc->m-tracker.TrackRubberBand(this,point,TRUE)
CView:: onLButtonDown (nFlags,point)
}

(54) 如何更新翻转背景颜色的文本
调 用CDC:: SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变, 这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新文本。黑色串在红色串之后,但由于设置了 背景模式仍然可见。

void CSampleView:: OnDraw (CDC* pDC)
{
//Determint size of view.
CRect rcView
GetClientRect (rcVieew)

//Create sample string to display.
CString str (_T ("Awesome Shadow Text..."))
//Set the background mode to transparent.
pDC->SetBKMode (TRANSPARENT)

//Draw black shadow text.
rcView.OffsetRect (1, 1)
pDc->SetTextColor (RGB (0, 0, 0))
pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

//Draw red text.
rcView.OffsetRect (-1,-1)
pDc->SetTextColor (RGB (255, 0, 0))
pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

}

(55) 如何创建一个具有特定点大小的字体
可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度:

int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72)
下例创建了一个8点的Apial字体:

CClientDC dc (AqfxGetMainWnd ())

m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF-SWISS,_T("Arial"))

(56) 如何计算一个串的大小
函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字体选进设备上下文中是很重 要的,否则计算高度和宽度时将依据系统字体,由此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小,按钮的大小由按钮的 字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。

LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)
{
//Pass message to window procedure.
LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr(), m_hWnd, GetCurrentMessage() ->message,wParam,lParam)
//Get title of push button.
CString strTitle
GetWindowText (strTitle)

//Select current font into device context.
CDC* pDC=GetDc ()
CFont*pFont=GetFont ()
CFont*pOldFont=pDC->SelectObject (pFont)

//Calculate size of title.
CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength())

//Adjust the button's size based on its title.
//Add a 5-pixel border around the button.
SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE)
//Clean up.
pDC->SelectFont (pOldFont)
ReleaseDC (pDC)

return bResult
}


(57) 如何显示旋转文本
只 要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的ifEscapement 成员指定了文本行和x轴的角度,角度的单位是十分之一度而不是度,例如,ifEscapement为450表示字体旋转45度。为确保所有的字体沿坐标系 统的同一方向旋转,一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14点Arial 字体每间隔15度画一个串。
void CSampleView:: OnDraw (CDC* pDC)
{
//Determine the size of the window.
CRect rcClient
GetClientRect (rcClient)

//Create sample string.
CString str (_T ("Wheeee...I am rotating!"))
//Draw transparent, red text.
pDC->SetBkMode (TRANSPARENT)
pDC->SetTextColor (RGB (255,0,0))
CFont font
//font object
LOGFONT stFont //font definition
//Set font attributes that will not change.
memset (&stFont, 0, sizeof (LOGFONT))
stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps(LOGPIXELSY), 72)
stFont.ifWeight=FW_NORMAL
stFont.ifClipPrecision=LCIP_LH_ANGLES
strcpy (stFont.lfFaceName, "Arial")

//Draw text at 15degree intervals.
for (int nAngle=0 nAngle<3600 nAngle+=150)
{
//Specify new angle.
stFont.lfEscapement=nAngle

//Create and select font into dc.
font.CreateFontIndirect(&stfont)
CFont* pOldFont=pDC ->SelectObject(&font)

//Draw the text.
pDC->SelectObject(pOldFont)
font.DelectObjext()
}
}


(58) 如何正确显示包含标签字符的串
调 用GDI文本绘画函数时需要展开标签字符,这可以通过调用CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS标志来完成。TabbedTextOut函数允许指定标签位的数组,下例指定每20设备单位展开一个标 签:

void CSampleView:: OnDraw (CDC* pDC)
{
CTestDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoC)

CString str
str.Format (_T ("Cathy\tNorman\tOliver"))
int nTabStop=20 //tabs are every 20 pixels
pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10)
}

(59) 如何快速地格式化一个CString对象
调用CString:: Format,该函数和printf函数具有相同的参数,下例说明了如何使用Format函数:

//Get size of window.
CRect rcWindow
GetWindowRect (rcWindow)
//Format message string.
CString strMessage
strMessage.Format (_T ("Window Size (%d, %d)"),

rcWindow.Width (), rcWindow.Height ())

//Display the message.
MessageBox (strmessage)

(60) 串太长时如何在其末尾显示一个省略号
调用CDC:: DrawText并指定DT_END_ELLIPSIS标志,这样就可以用小略号取代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息,指定DT_END_ELLIPSIS标志并省略号取代串中间的字符。

void CSampleView:: OnDraw (CDC* pDC)
{
CTestDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)

//Add ellpsis to end of string if it does not fit
pDC->Drawtext (CString ("This is a long string"), CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS)

//Add ellpsis to middle of string if it does not fit
pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath, CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS)
}


(61) 为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态
需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_Update_COMMAND_UI或者ON_COMMAND的菜单项。

//Disable MFC from automatically disabling menu items.
m_bAuoMenuEnable=FALSE
//Now enable the menu item.
CMenu* pMenu=GetMenu ()
ASSERT_VALID (pMenu)

pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)


(62) 如何给系统菜单添加一个菜单项
给系统菜单添加一个菜单项需要进行下述三个步骤:
首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000;
其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的
int CMainFrame:: OnCreate (LPCreateSTRUCT lpCreateStruct)
{

//Make sure system menu item is in the right range.
ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM)
ASSERT (IDM-MYSYSITEM<0xF000)

//Get pointer to system menu.
CMenu* pSysmenu=GetSystemmenu (FALSE)
ASSERT_VALID (pSysMenu)
//Add a separator and our menu item to system menu.
CString StrMenuItem (_T ("New menu item"))
pSysMenu->Appendmenu (MF_SEPARATOR)
pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem)


}

现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理WM_SYSCOMMAND消息并检测用户菜单的nID参数:
void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
{
//Determine if our system menu item was selected.
if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
{
//TODO-process system menu item
}

else
CMDIFrameWnd ::OnSysCommand (nID, lParam)
}
最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。

(63) 如何确定顶层菜单所占据的菜单行数
这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。

int CMainFrame:: GetMenuRows ()
{
CRect rcFrame,rcClient
GetWindowRect (rcFrame)
GetClientRect (rcClient)
return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU)
}

(64) 在用户环境中如何确定系统显示元素的颜色
调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。

void CMiniFrameWnd:: OnNcPaint ()
{

dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT))



(65) 如何查询和设置系统参数
在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。

//Create a font that is used for icon titles.
LOGFONT stFont
∶: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE)
m_font.CreateFontIndirect (&stFont)

//Change the wallpaper to leaves.bmp.
∶ : SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (" forest.bmp"), SPIF_UpdateINIFILE)


(66) 如何确定当前屏幕分辨率
调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标题大小、边界大小以及滚动条大小等等。

//Initialize CSize object with screen size.
CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN))


(67) 如何使用一个预定义的Windows光标
调用CWinApp:: LoadStandardCursor并传送光标标识符。
BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd,
UINT nHitTest, UINT
message)
{
//Display wait cursor if busy.
if (m_bBusy)
{
SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT))
return TRUE
}

return CDialog:: OnSetCursor (pWnd. nHitTest,message)
}

(68) 如何检索原先的Task Manager应用程序使用的任务列表
原 先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner可以确定 窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。

void GetTadkList (CListBox&list)
{
CString strCaption
//Caption of window.

list.ResetContent ()
//Clear list box.

//Get first Window in window list.
ASSERT_VALID (AfxGetMainWnd ())
CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST)

//Walk window list.
while (pWnd)
{
// I window visible, has a caption, and does not have an owner?
if (pWnd ->IsWindowVisible()
&& pWnd ->GetWindowTextLength ()
&&! pWnd ->GetOwner ())
{

//Add caption o window to list box.

pWnd ->GetWindowText (strCaption)

list.AddString (strCaption)
}
//Get next window in window list.
pWnd=pWnd ->GetWindow(GW_HWNDNEXT)
}
}

(69) 如何确定Windows和Windows系统目录
有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory,下例说明了如何使用这两个函数:

TCHAR szDir [MAX_PATH]
//Get the full path of the windows directory.
∶ : GetWindowsDirectory (szDir, MAX_PATH)
TRACE ("Windows directory %s\n", szDir)
//Get the full path of the windows system directory.
∶ : GetSystemDirectory (szDir, MAX_PATH)
TRACE ("Windows system directory %s\n", szDir)

(70) 在哪儿创建临文件
调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。


//get unique temporary file.
CString strFile
GetUniqueTempName (strFile)
TRY
{
//Create file and write data.Note that file is closed
//in the destructor of the CFile object.
CFile file (strFile,CFile ::modeCreate | CFile:: modeWrite)

//write data
}

CATCH (CFileException, e)
{
//error opening file
}
END_CATCH


Void GetuniqueTempName (CString& strTempName)
{
//Get the temporary files directory.
TCHAR szTempPath [MAX_PATH]
DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)
ASSERT (dwResult)

//Create a unique temporary file.
TCHAR szTempFile [MAX_PATH]
UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile)
ASSERT (nResult)

strTempName=szTempFile
}

(71) 我怎样才能建立一个等待光标?
调 用 BeginWaitCursor 函 数 来 启 动 等 待 光 标,调 用 EndWaitCursor 函 数 来 结 束 等 待 光 标。要 注 意,二 者 都 要 调 用 app 的 成 员 函 数,如 下 所 示:

AfxGetApp()->BeginWaitCursor();
// 要做的事
AfxGetApp()->EndWaitCursor();

(72) 我在MDI框架中有个 form 视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?
调 用 OnCloseDocument 函 数。

(73) 如何访问桌面窗口
静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。

void CFrameWnd::BeginModalState ()
{

//first count all windows that need to be disabled
UINT nCount=0
HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)
while (hWnd!=NULL)
{
if (:: IsWindowEnabled (hwnd)
&& CWnd::FromHandlePermanent (hWnd)!=NULL
&& AfxIsDescendant (pParent->m_hWnd, hWnd)
&& :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
{
++nCount
}
hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)
}


(74) 什么是COLORREF? 我该怎样用它?
COLORREF 是 一 个 32-bit 整 型 数 值,它 代 表 了 一 种 颜 色。你 可 以 使 用 RGB 函 数 来 初 始 化 COLORREF。例 如:

COLORREF color = RGB(0, 255, 0);
RGB 函 数 接 收 三 个 0-255 数 值,一 个 代 表 红 色, 一 个 代 表 绿 色, 一 个 代 表 蓝 色。在 上 面的 例 子 中, 红 色 和 蓝 色 值 都 为 0,所 以 在 该 颜 色 中 没 有 红 色 和 蓝 色。绿 色 为 最 大 值 255。所 以 该 颜 色 为 绿 色。0,0,0 为 黑 色,255,255,255 为 白 色。

另 一 种 初 始 化 COLORREF 的 方 法 如 下 所 示:

CColorDialog colorDialog;
COLORREF color;

if( colorDialog.DoModal() == IDOK )
{
color = colorDialog.GetColor();
}
这 段 代 码 使 用 了 MFC 中 的 颜 色 对 话 框,它 需 要 文 件。


(75) AppWizard所产生的STDAFX文件是干什么用的?
它 主 要 是 协 助 产 生 预 编 译 头 文 件 的。通 常 你 是 不 需 要 修 改 它 的。

(76) 我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。为什么会这么糟?
CDWordArray 是 很 好 用 的,只 是 因 为 你 没 有 指 定 数 组 的最大尺寸。因 此,当 你 添 加 新 元 素 时,该 类 会 从 堆 中 重 新 分 配 空 间。不 幸 的 是,该 类 会 在 每 次 插 入 新 元 素 时 都 为 数 组 重 新 分 配 空 间。如 果 你 向 它 添 加 了 很 多 新 元 素,所 有 这 些 分 配 和 复 制 数 组 的 操 作 会 就 会 使 它 变 慢。解 决 该 问 题 的 方 法 是,你 可 以 使 用 SetSize 函 数 的 第 二 个 参 数 来 改 变 这 种 重 新 分 配 的 频 率。例 如,如 果 你 把 该 参 数 设 置 为 500,则 每 次 数 组 空 间 超 出 时 它 重 新 分 配 并 添 加 500 个 新 空 间,而 不 是 1 个。这 样 一 来,你 就 可 以 不 用 重 新 分 配 而 添 加 了 另 外 499 个 元 素 空 间,这 也 会 大 大 提 高 程 序 的 运 行 速 度。


(77) 我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?
在 视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。GetParentFrame 会 返 回 一 指 向 一 保 存 有 该 视 的 框 架 窗 口 的 指 针。然 后 调 用 在 框 架 窗 口 上 调 用 MoveWindow。

(78) 在我的程序的某些部分,我可以调用 MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?
MessageBox 函 数 来 自 CWnd 类,所 以 你 只 能 在 从 CWnd 继 承 的 类 ( 如 CView ) 中 调 用 它。但 是,MFC 也 提 供 了 AfxMessageBox 函 数,你 可 以 在 任 何 地 方 调 用 它。


(79) 我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿?
把 该 变 量 放 到 该 应 用 程 序 类 的 头 文 件 中 的 attribute 处。然 后,在 程 序 的 任 何 地 方,你 都 可 以 用 下 面 的 方 法 来 访 问 该 变 量:

CMyApp *app = (CMyApp *)AfxGetApp();
app->MyGlobalVariable = ...

(80) 我听说MFC可以发现内存漏洞,我怎样使用该特性?
如 果 你 在 Debug 菜 单 中 的 Go 选 项 ( 不 是 Project 菜 单 中 的 Execute 选 项 ) 来 运 行 你 的 应 用 程 序,MFC 应 该 在 程 序 终 止 时 报 告 内 存 漏 洞。如 果 没 有,那 么 试 试 运 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 组 中 ),并 启 动 跟 踪。然 后 返 回 应 用 程 序。

(81) 我怎样才能在我的应用程序中循环浏览已经打开的文档?
使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。


(82)才能在我的应用程序中循环浏览已经打开的视?
使 用 CDocument 中 未 公 开 的 GetFirstViewPosition() 和 GetNextView() 函 数。

(83)数PreCreateWindow是干什么用的?
PreCreateWindow 允 许 你 在 调 用 CreateWindow 之 前 来 改 变 窗 口 属 性。

(84)该怎样防止MFC在窗口标题栏上把文档名预置成应用程序名?
在 PreCreateWindow 函 数 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 样 式:

cs.style &= ~FWS_PREFIXTITLE;


(85) 我应该怎样防止MFC在窗口标题栏上添加文档名?
在 PreCreateWindow 函 数 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 样 式:

cs.style &= ~FWS_ADDTOTITLE ;


(86) 我应该如何改变视窗口的大小?
因 为 视 窗 口 实 际 上 是 框 架 窗 口 的 子 窗 口,所 以 你 必 须 改 变 框 架 窗 口 的 大 小,而 不 是 改 变 视 窗 口。使 用 CView 类 中 的 GetParentFrame() 函 数 获 得 指 向 框 架 窗 口 的 指 针,然 后 调 用 MoveWindow() 函 数 来 改 变 框 架 的 大 小。这 会 使 变 尺 寸 的 视 充 满 框 架 窗 口。

(87) 我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?
把“delete this”加 到 PostNcDestroy 中。这 主 要 用 在 需 要 自 动 删 除 对 象 的 场 合。


(88) 为什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?
OnNcDestroy 只 被 已 建 立 的 窗 口 调 用。如 果 建 立 窗 口 失 败 ( 如 PreCreateWindow ),则 没 有 窗 口 处 来 发 送 WM_NCDESTROY 消 息。PostNcDestroy 是 在 对 象 窗 口 被 完 全 删 除,在 OnNcDestroy 后,甚 至 在 窗 口 建 立 失 败 之 后 调 用 的。


(89) File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值?
在 应 用 程 序 类 的 InitInstance 函 数 中 对 LoadStdProfileSettings 的 调 用 中。该 调 用 接 受 一 个 参 数 ( 在 缺 省 情 况 下 如 果 没 有 传 递 值 则 为 4 )。MRU 文 件 名 是 从 INI 文 件 中 调 用 的。如 果 你 有 带 有 ID_FILE_MRU_FILE1 的 ID 的 菜 单 选 项,它 会 为 调 入 的 MRU 列 表 所 替 换。如 果 你 改 变 传 递 给 LoadStdProfileSettings 的 数 值 ( 最 大 为 16 ),则 你 就 改 变 了 所 装 如 文 件 名 的 最 大 值。

(90) 我在菜单中添加了新的项。但是,当我选该项时,在状态栏上没有出现任何提示信息。为什么?
打 开 资 源 文 件 中 的 菜 单 模 板。打 开 新 菜 单 选 项 的 属 性 对 话 框。在 对 话 框 的 底 部 的 Prompt 编 辑 框 中 ,你 可 以 如 下 指 定 状 态 栏 上 的 提 示 信 息 和 工 具 栏 上 的 提 示 信 息 ( 如 果 你 已 经 建 立 的 工 具 栏 按 钮 ):

Status bar string\nFlying tag

(91) 我怎样才能在应用程序的缺省系统菜单中加上一些东西?
系 统 菜 单 与 其 它 菜 单 类 似,你 可 以 添 加 或 删 除 项 目,这 需 要 使 用 CMenu 类 的 成 员 函 数。下 面 的 代 码 在 你 的 系 统 菜 单 后 面 添 加 一 个 新 菜 单 项:

CMenu *sysmenu;
sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
参 见 MFC 帮 助 文 件 中 的 CMenu 类。

(92) 我建立了一个对话框。但是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点?
打 开 资 源 编 辑 器 中 的 对 话 框 模 板。在 Layout 菜单 中 选 择 Tab order 选 项。按 你 的 需 求 单 击 对 话 框 中 的 控 制 来 重 新 排 列 这 些 控 制 的 tab 顺 序。

(93) 我怎样才能使一个窗口具有“always on top”特性?
在 调 用 OnFileNew 后,在 你 的 InitInstance 函 数 中 加 上 下 面 的 代 码:

m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);

(94) 我要为我的form view添加文档模板。我先建立了对话框模板,然后使用ClassWizard建立了基于CFormView的新类,它也是从CDocument继承来 的。我还建立了相应的资源并在InitInstance中添加了新的文档模板。但是,当我试图运行该程序时,出现了Assertion信息。为什么?

form 的 对 话 框 模 板 需 要 些 特 殊 设 置 以 便 可 用 于 CFromView。确 保 这 些 设 置 的 最 简 单 方 法 是 使 用 AppWizard 来 建 立 CFormView 应 用 程 序,并 查 看 AppWizard 所 建 立 的 对 话 框 模 板 所 选 择 的Styles Properties。你 会 发 现 该 对 话 框 模 板 具 有 下 列 样 式:没 有 标 题 栏、不 可 见 和“Child”。把 你 的 form view 的 对 话 框 属 性 变 成 这 样 就 可 以 了。

(95) 我在一对话框中有一列表框,我需要tabbed列表框中的项目。但是,当我处理含有tab字符(用AddString添加的)的列表项时,tab被显示成小黑块而没有展开。哪儿出错了?

在 对 话 框 模 版 中,打 开 列 表 框 的 属 性。确 保 选 择 了“Use Tabstops” 样 式。然 后,确 保 在 对 话 框 类 中 OnInitDialog 函 数 中 调 用 SetTabStops。

(96) 我建立了一个应用程序,并使用了CRecordset类。但是,当我运行该程序时,它试图要访问数据库,并给出“Internal Application Error”对话框。我应该怎样做?

通 常 情 况 下,当 你 的 程 序 中 向 数 据 库 发 送 信 息 的 SQL 语 句 出 现 问 题 时 才 出 现 该 对 话 框。例 如,参 见 下 面 的 例 子:

set.m_strFilter = "(ZipCode = '27111')";
如 果 ZipCode 列 被 定 义 为 字 符 串 时 不 会 出 现 问 题,如 果 定 义 为 long,则 会 出 现“Internal Application Error”对 话 框,这 是 由 于 类 型 不 匹 配 的 缘 故。如 果 你 删 除 27111 的 单 引 号,则 不 会 出 现 问 题。当 你 看 到“Internal Application Error”时,最 好 检 查 一 下 试 图 要 发 送 给 数 据 库 的 SQL 语 句。

(97) 我用ClassWizard建立了一个类。但是,我把名字取错了,我想把它从项目中删除,应该如何做?

在 ClassWizard 对 话 框 关 闭 后,用 文 件 管 理 器 删 除 新 类 的 H 和 CPP 文 件。然 后 打 开 ClassWizard,它 会 提 示 丢 失 了 两 个 文 件,并 询 问 你 该 如 何 做。你 可 以 选 择 从 项 目 中 删 除 这 两 个 问 的 按 钮。


(98) 当我打开应用程序中的窗口时,我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小,但是当我调用GetClientRect时,所得到的尺寸要比所希望的值要小(因为工具栏和窗口边框的缘故)。有其它方法来计算窗口的尺寸吗?

参 见 CWnd::CalcWindowRect。

(99) 我在文档类中设置了一个整型变量。但是,当我试图把该变量写入Serialize函数中的archive文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么?

archive 类 只 重 载 某 些 类 型 的 >> 和 << 操 作 符。“int”类 型 没 有 在 其 中,也 许 是 因 为 int 变 量 在 Windows 3.1 与 Windows NT/95 有 所 不 同 的 缘 故 吧。“long”类 型 得 到 了 支 持,所 以 你 可 以 把 int 类 型 改 成 long 型。参 见 MFC 帮 助 文 件 中 CArchive 类。



(100) 如何控制菜单的大小?
我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help), 我想控制这个菜单的大小(长+高).

方法一:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT.
方法二:查询系统::GetSystemMetric(M_CXMENUSIZE).

/* 你可以通过如下代码来获得文本的大小:
(A)获得被使用的字体 */

NONCLIENTMETRICS ncm;
HFONT hFontMenu;
SIZE size;
size.cy = size.cy = 0;

memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
{
hFontMenu = CreateFontIndirect(&ncm.lfMenuFont);
/*
(B) 获得菜单项的文本: */
char szText[_MAX_PATH];

pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);
/*
然后,获得菜单项文本的高度: */
HFONT hFontOld;
HDC hDC;

hDC = ::GetDC(NULL);
hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);
GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size);
SelectObject(hDC, hFontOld);
::ReleaseDC(NULL, hDC);
}
/*此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度和宽度,通过比较,我发现宽度为4

比较合适。*/


(101) 改变LVIS_SelectED的状态颜色?
我想将CListCtrl项和CTreeCtrl项在LVIS_SelectED状态时的颜色变灰.

方法一:查找函数CustomDraw,它是IE4提供的公共控制,允许有你自己的代码.
方法二:生成一个draw控件,然后在DrawItem中处理文本颜色.

(102) 如何只存储文档的某一部分?
我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数).将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.

(103) 保存工具条菜单有bug吗?


使 用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其 它位置时,下一次启动就会出现在该位置,这是什么原因?你试试这个PToolBar->Create(this,..., ID_MYTOOLBAR);
你的工具条需要包括id,而不是象默认的工具条那样.

(104) Tip of the day的bug

我 创建了一个简单的mdi应用程序,使用.BSF(自定义的文档扩展名)作为它的文档我保存一个foo.bsf文档后,可以在资源管理器中双击该文件打开 mdi应用程序同时打开foo.bsf文档.但当我给mdi应用程序加上a tip of the day组件之后,从资源管理器中双击foo.bsf后,就会给我一个警告:ASSERT(::IsWindow(m_hWnd)),然后mdi应用程序就 死那了.

当从dde启动应用程序(例如:双击相关文档)时,"Tip of the Day"是有bug的.你可以看看函数"ShowTipAtStartup",它在"InitInstance"中调用,可以看到tip of the day作为一个模式对话框显示,在处理其它消息时它一直进行消息循环你可心修改ShowTipAtStartup使其从dde启动时不出现tip of the day.
void CTipOfApp::ShowTipAtStartup(void)
{
// CG: This function added by 'Tip of the Day' component.

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);

if (
cmdInfo.m_bShowSplash &&
cmdInfo.m_nShellCommand != CCommandLineInf:FileDDE
)
{
CTipDlg dlg;
if (dlg.m_bStartup)
dlg.DoModal();
}
}
如果还有其它bug,你可以设定cmdInfo.m_nShellCommand的过滤.

(105) 如何可以让我的程序可以显示在其它的窗口上面?

让用户选择"总是在最上面"最好是在系统菜单里加入一个选项.可以通过修改WM_SYSCOMMAND消息来发送用户的选择.菜单的命令标识(id)会作为一个参数传给OnSysCommand().要定义标识(id),将如下代码加入到CMainFrame.CPP中:

#define WM_ALWAYSONTOP WM_USER + 1
将"总在最上面"的菜单项加入到系统菜单中,将如下代码加入到函数CMainFrame::OnCreate()中:

CMenu* pSysMenu = GetSystemMenu(FALSE);
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, WM_ALWAYSONTOP,
"&Always On Top");
使用ClassWizard,加入对WM_SYSCOMMAND消息的处理,你应该改变消息过滤器,使用系统可以处理这个消息.
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
switch ( nID )
{
case WM_ALWAYSONTOP:

if ( GetExStyle() & WS_EX_TOPMOST )
{
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,
MF_UNCHECKED);
}
else
{
SetWindowPos(&wndTopMost, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED);
}

break;

default:
CFrameWnd::OnSysCommand(nID, lParam);
}
}

(106) 如何控制窗口框架的最大最小尺寸?

要控制一个框架的的最大最小尺寸,你需要做两件事情.在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗口类的限制,因此记住要考虑工具条,卷动条等等的大小.

// 最大最小尺寸的象素点 - 示例
#define MINX 200
#define MINY 300
#define MAXX 300
#define MAXY 400

void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
CRect rectWindow;
GetWindowRect(&rectWindow);

CRect rectClient;
GetClientRect(&rectClient);

// get offset of toolbars, scrollbars, etc.
int nWidthOffset = rectWindow.Width() - rectClient.Width();
int nHeightOffset = rectWindow.Height() - rectClient.Height();

lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;
lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;
lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;
lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset;
}
第二步,在CFrameWnd的继承类的PreCreateWindow函数中去掉WS_MAXIMIZEBOX消息,否则在最大化时你将得不到预料的结果.

BOOL CMyFrameWnd::PreCreateWindow(CreateSTRUCT& cs)
{
cs.style &= ~WS_MAXIMIZEBOX;
return CFrameWnd::PreCreateWindow(cs);
}

(107) 如何改变窗口框架的颜色?

MDI框架的客户区被另一个窗口的框架所覆盖.为了改变客户区的背景色,你需要重画这个客户窗口.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDIClient.给它加上一个成员变量,
#include "MDIClient.h"
class CMainFrame : public CMDIFrameWnd
{
...
protected:
CMDIClient m_wndMDIClient;
}
在CMainFrame中重载CMDIFrameWnd::OnCreateClient
BOOL CMainFrame::OnCreateClient(LPCreateSTRUCT lpcs, CCreateContext* pContext)
{
if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) )
{
m_wndMDIClient.SubclassWindow(m_hWndMDIClient);
return TRUE;
}
else
return FALSE;
}
然后就可以加入对消息WM_ERASEBKGND的处理了.

(108) 如何将应用程序窗口置于屏幕正中?

要将你的应用程序窗口放置在屏幕正中央,只须在MainFrame的OnCreate函数中加入:
CenterWindow( GetDesktopWindow() );


引至http://maocom.com/resources/program/html/200689/9112.htm
想要基于对话框的程序一启动就隐藏到后台吧,ShowWindow是可以的,只不过MFC建立的程序框架里用的是模态对话框,所以 在APP的InitInstance里DoModal()后,程序便阻塞并进入对话框自己的消息循环里,无法调用ShowWindow()。其实参考一下 文档/视框架,将模态对话框改成非模态对话框就可以了。你可以这样做:在APP的源文件中定义一个对话框类的全局变量指针(或静态变量指针)
CYourDlg* pDlg;
删掉InitInstance()里框架自动生成dlg及相关的所有语句,然后用非模态方式创建对话框

pDlg=new CYourDlg();
pDlg->Create(CYourDlg::IDD);
m_pMainWnd = pDlg;

将InitInstance ()的返回值改成TRUE:return TRUE。否则程序一启动就会立即结束。然后打开对话框资源,将对话框资源属性的 more styles里的Visible前的勾去掉,编译,运行就可以了。这时程序一启动就会在后台。可以在任务管理器中看到它。

因为是非模态方式创建,所以退出时要注意自己销毁窗口。

如果不愿这么麻烦,也有一个简单的方法,就是定义一个定时器,在OnInitDialog里启动,然后在OnTimer()里面ShowWindow()即可,然后直接停掉定时器。这个方法的缺点是会看到对话框先闪一下再隐藏。

- 作者: 冯唐 2006年07月26日, 星期三 13:56  回复(0) |  引用(2) 加入博采

巧妙破解Windows XP的登录密码简法
早在2003年第1期《微型计算机》刊登了一篇关于破解Windows XP登录密码的文章,认真说起来这并不是破解,而是通过添加用户以另外一个新用户使用Windows XP,操作也略显繁琐。最近笔者在一些论坛“灌”到了关于Windows XP的掌管密码文件,一个新的破解登录方法无形在头脑中产生。

  首先找一台没有设置密码的Windows XP系统,进入XP系统盘的“\WINDOWS\system32”系统目录,把其中的名为“SPOOLSV.EXE”(50KB)拷贝到"软盘或闪存里(如图1)。


巧妙破解Windows XP的登录密码简法

图1

友情提示:
  如果未在system32文件夹中找到指定文件,则说明当前系统隐藏显示系统文件,在资源管理器中点击菜单“工具→文件夹选项”,在“查看”标签页中撤消“隐藏受保护的操作系统文件(推荐)”复选框,并将“隐藏文件和文件夹”选择为“显示所有文件和文件夹”方式。

  准备好密码文件后,先确认待破解的Windows XP的文件系统(即磁盘系统格式),如果是FAT32,那么只需找一张启动盘,把软盘里的“SPOOLSV.EXE”拷贝到目标XP系统的“\WINDOWS\system32”文件夹覆盖。
  目标XP系统的文件系统是NTFS,如果是还装了能识别NTFS文件系统的其它操作系统(如Windows 2000或Windows Server 2003),直接进入系统进行覆盖。否则的话,可以在纯DOS状态下加载NTFS for DOS工具进行访问覆盖。
   替换文件后,正常方式启动Windows XP,可以不用输入密码直接进入Windows XP桌面已成功破解(多用户的XP系统会选择默认即第一个用户登录)。调出“Windows 任务管理器”工具(快捷键“Ctrl+Shift+Esc”),在“进程”列表中可以查看到“SPOOLSV.EXE”进程(如图2)。

巧妙破解Windows XP的登录密码简法
图2


  请注意,通过此方法会造成XP无法使用休眠关机,切换用户时(快捷键“Win+L”)还会提示输入密码才能返回桌面,请读者们谨慎使用。另外本文只作技巧探讨,千万别用在非法目的,否则后果自负。^)^

- 作者: 冯唐 2006年07月11日, 星期二 15:56  回复(1) |  引用(2) 加入博采

转载:Windows密码与SAM文件问题汇总

Windows密码与SAM文件问题汇总
作者:Andy1990zx 时间:2006-3-30 19:28:34

Windows 2000所在的Winnt\System32\Config下有个SAM文件(即账号密码数据库文件),它保存了Windows 2000中所有的用户名和密码。当你登录的时候系统就会把你键入的用户名和密码。与SAM文件中的加密数据进行校对,如果两者完全符合,则会顺利进入系 统,否则将无法登录,因此我们可以使用删除SAM文件的方法来恢复管理员密码。

用Windows PE(EDR软件)、Bart PE、NTFSDOS等启动,把管理员Administrator账号密码置空,这时你可以用Administrator帐户登录系统,不用输入任何密码,进入系统后再重新设置你的管理员账户密码即可。
把sam考到别的机器上,用LC5破解很快,或者直接把硬盘挂到其他的2K或XP系统下进行这个操作

  需要注意的是:
  A.这方法不能在Windows XP/2003上使用,如果删除SAM文件,会引起系统崩溃。
  B.WindowsNT/2000/XP 中对用户账户的安全管理使用了安全账号管理器(Security AccountManager,SAM)的机制,安全账号管理器对账号的管理是通过安全标识进行的,安全标识在账号创建时就同时创建,一旦账号被删除,安 全标识也同时被删除。安全标识是惟一的,即使是相同的用户名,在每次创建时获得的安全标识都是完全不同的。因此,一旦某个账号被删除,它的安全标识就不再 存在了,即使用相同的用户名重建账号,也会被赋予不同的安全标识,不会保留原未的权限。安全账号管理器的具体表现就是%SystemRoot%\ system32\config\sam文件。SAM文件是WindowsNT/2000/XP的用户账户数据库,所有用户的登录名及口令等相关信息部会 保存在这个文件中。
  C.另外,在Windows XP中,将\WINDOWS\repair\sam文件复制到\WINDOWS\system32\config\目录下覆盖掉原有的文件(如果不放心可以先备份一下原有的SAM文件)Administrator帐号的密码即为空的了
  D.如有可能,建议使用其它方法。
优点:使用简单 缺点:破坏安全标识,不能在Windows XP、Windows 2003 使用,如果用EFS加密,加密破坏,数据丢失。
E.Repair下的sam文件是当初安装XP时产生的

这样操作成功登陆后,如果系统打开了系统还原,可以还原到最新的还原点。

转者注:在网上看到了一堆这样、那样的windows 2000/XP的管理员口令的破解。绝大多数误导大家,看到这篇文章,觉得是说到了点子上:回复管理员口令时,对windows 2000和XP的SAM文件的处理是不同的,2000的SAM文件可以直接改名或删除,管理员的口令就为空了;XP的口令要用%SystemRoot%\ Repair\Sam 文件覆盖(将以前的改名比较保险)才行,删除config下的Sam文件就惨了。

总结了一下,有如下的几个方法:

1. 用各种启动盘(软盘、USB盘、可启动的光盘)启动,使用一些工具直接修改管理员口令,还比较好使,就是要用启动盘。软盘估计大家都没有了,USB盘还必须要一个啥的windows98来做,光盘嘛,还要刻一张,最好还是用RW的,要不有一点浪费。

2. 利用windows xp的安装盘或带命令行方式的安全模式启动xp,钻xp的漏洞来修改。不过这些现在都不太好用了,盖茨也在不断的改进啊,因此,许多人认为按照教程来,就是不成功的原因了。

3. 像什么使用LC4/LC5的方法,如果口令比较复杂,那可有你等的了。

4. 就是上面偶很欣赏的方法,启动起来,直接用一些rename,copy等命令就搞定了。

- 作者: 冯唐 2006年07月11日, 星期二 15:54  回复(0) |  引用(2) 加入博采

WEB服务的规划==>HTTPD安装/应用模块配置==>升级/维护等过程
作者: FrEeBsD  发布日期: 2006-5-27    查看数: 187   出自: http://www.linuxsky.net 从简化安装==>性能调优==>方便维护的角度,讨论WEB服务的规划==>HTTPD安装/应用模块配置==>升级/维护等过程。
让APACHE的升级和PHP 及 RESIN等应用模块的升级完全互不影响。

WEB应用容量规划:根据硬件配置和WEB应用的特点进行WEB服务的规划及一些简单的估算公式;
APACHE安装过程:apache的通用的简化安装选项,方便以后的应用的模块化配置;
修改 HARD_SERVER_LIMIT:
vi /path/to/apache_src/src/include/httpd.h
#define HARD_SERVER_LIMIT 2560 <===将原来的 HARD_SERVER_LIMIT 256 后面加个“0”
apache编译:
/path/to/apache_src/configure --prefix=/another_driver/apache --enable-shared=max --enable-module=most
可选应用模块/工具的安装:php resin mod_gzip mod_expire及各个模块之间的配合;
PHP安装:
/path/to/php_src/configure --with-apxs=/path/to/apache/bin/apxs --enable-track-vars --with-other-modules-you-need
mod_resin安装:
/path/to/resin/src/configure --with-apxs=/path/to/apache/bin/apxs
Mod_gzip安装:
/path/to/apache/bin/apxs -i -a -c mod_gzip.c
工具:cronolog安装:http://www.cronolog.org
升级/维护:看看通用和模块化的安装过程如何简化了日常的升级/维护工作;
按照以上的方法:系统管理员和应用管理员的职责可以清楚的分开,互相独立。
系统安装:系统管理员的职责就是安装系统=>安装好一台DSO模式的APACHE,然后COLON,
应用安装:由应用管理员负责具体应用所需要的模块并设置HTTPD。
系统升级:系统管理员:升级系统/升级APACHE
应用升级:系统管理员:升级应用模块
具体的说明:

WEB应用的容量规划

APACHE主要是一个内存消耗型的服务应用,我个人总结的经验公式:
apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2
apache_max_process = apache_max_process_with_good_perfermance * 1.5

为什么会有一个apache_max_process_with_good_perfermance和apache_max_process呢?原因是在 低负载下系统可以使用更多的内存用于文件系统的缓存,从而进一步提高单个请求的响应速度。在高负载下,系统的单个请求响应速度会慢不少,而超过 apache_max_process,系统会因为开始使用硬盘做虚拟内存交换空间而导致系统崩溃。此外,同样的服务:2G内存的机器的 apache_max_process一般只设置到1G内存的1.7倍,因为APACHE本身会因为管理更多的进程而产生性能下降。

例子1:
一个apache + mod_php的服务器:一个apache进程一般需要4M内存
因此在一个1G内存的机器上:apache_max_process_with_good_perfermance < (1g / 4m) * 2 = 500
apache_max_process = 500 * 1.5 = 750
所以规划你的应用让服务尽量跑在500个APACHE以下,并设置APACHE的软上限在800个。

例子2:
一个apache + mod_resin的服务器: 一个apache进程一般需要2M内存
在一个2G内存的机器上: apache_max_process_with_good_perfermance < (2g / 2m ) * 2 = 2000
因此:apache_max_process = 2000 * 1.5 = 3000

以上估算都是按小文件服务估算的(一个请求一般大小在20k以下)。对于文件下载类型站点,可能还会受其他因素:比如带宽等的影响。

APACHE安装过程

服务器个数的硬上限HARD_SERVER_LIMIT的修改:
在FREEBSD和LINUX等UNIX操作系统下APACHE缺省的最大进程数是256个,需要修改apache_1.3.xx/src/include/httpd.h
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 2560 <===将原来的HARD_SERVER_LIMIT 256 后面加个“0”
#endif
#endif

解释:
APACHE缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,但随着内存成本的急剧下降,现在大型站 点的服务器内存配置一般比当时要高一个数量级不止。所以256个进程的硬限制对于一台1G内存的机器来说是太浪费了,而且APACHE的软上限 max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高APACHE的 HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了(APACHE的软上限的规划请看后 面)。

APACHE的编译:通用的编译选项能使安装过程标准化
./configure --prefix=/another_driver/apache/ --enable-shared=max --enable-module=most

解释:
--prefix=/another_driver/apache/: 一个系统使用寿命最低的一般就是硬盘,因此:将服务数据和系统完全分开,不仅能提高了数据的访问速度,更重要的,大大方便系统升级,备份和恢复。

--shared-module=max:使用动态加载方式会带来5%的性能下降,但和带来的好处相比更本不算什么:比如模块升级方便,系统升级风险降低,安装过程标准化

--enable-module=most:用most可以将一些不常用的module编译进来,比如后面讲到的mod_expire是就不在apache的缺省常用模块中

如果不想build so, 也可以这样:
./configure \
"--with-layout=Apache" \
"--prefix=/path/to/apache" \
"--disable-module=access" \
"--disable-module=actions" \
"--disable-module=autoindex" \
"--disable-module=env" \
"--disable-module=imap" \
"--disable-module=negotiation" \
"--disable-module=setenvif" \
"--disable-module=status" \
"--disable-module=userdir" \
"--disable-module=cgi" \
"--disable-module=include" \
"--disable-module=auth" \
"--disable-module=asis"

但结果会发现,这样编译对服务性能只能有微小的提高(5%左右),但却失去了以后系统升级和模块升级的灵活性,无论是模块还是APACHE本身升级都必须把所有SOURCE加在一起重新编译。

apache的缺省配置文件一般比较大:我们可以使用去掉注释的方法精简一下:然后再进入具体的培植过程能让你更快的定制出你所需要的。
grep -v "#" httpd.conf.default >httpd.conf

需要修改的通用项目有以下几个:

#服务端口,缺省是8080,建议将整个APACHE配置调整好后再将服务端口改到正式服务的端口
Port 8080 => 80

#服务器名:缺省没有
ServerName name.example.com

#最大服务进程数:根据服务容量预测设置
MaxClients 256 => 800

#缺省启动服务后的服务进程数:等服务比较平稳后,按平均负载下的httpd个数设置就可以
StartServers 5 => 200

不要修改:
以前有建议说修改:
MinSpareServers 5 => 100
MaxSpareServers 10 => 200

但从我的经验看来:缺省值已经是非常优化的了,而且让APACHE自己调整进程个数还是比较好的。

特别修改:
在solaris或一些比较容易出现内存泄露的应用上:
MaxRequestsPerChild 0 =>3000

应用模块和工具的安装配置:

由于使用模块动态加载的模式,所以可以方便的通过简单的配置调整来把APACHE定制成你需要的:最好把不常用模块全部清除(无论处于安全还是效率)。
比如:对于静态页面服务器:就什么模块都不加载,对于PHP应用就加上PHP模块,对于JAVA应用就把RESIN模块加载上。而且各种模块的插拔非常简单。


一般说来,可以不需要的模块包括:
#LoadModule env_module libexec/mod_env.so
#LoadModule negotiation_module libexec/mod_negotiation.so
#LoadModule status_module libexec/mod_status.so
#server side include已经过时了
#LoadModule includes_module libexec/mo_include.so
#不需要将没有缺省index文件的目录下所有文件列出
#LoadModule autoindex_module libexec/mod_autoindex.so
#尽量不使用CGI:一直是APACHE安全问题最多的地方
#LoadModule cgi_module libexec/mod_cgi.so
#LoadModule asis_module libexec/mod_asis.so
#LoadModule imap_module libexec/mod_imap.so
#LoadModule action_module libexec/mod_actions.so
#不使用安全校验可以大大提高访问速度
#LoadModule access_module libexec/mod_access.so
#LoadModule auth_module libexec/mod_auth.so
#LoadModule setenvif_module libexec/mod_setenvif.so

最好保留的有:
#用于定制log格式
LoadModule config_log_module libexec/mod_log_config.so
#用于增加文件应用的关联
LoadModule mime_module libexec/mod_mime.so
#用于缺省index文件:index.php等
LoadModule dir_module libexec/mod_dir.so

可用可不用的有:
#比如:需要在~/username/下调试php可以将
LoadModule userdir_module libexec/mod_userdir.so
#比如:需要将以前的URL进行转向或者需要使用CGI script-alias
LoadModule alias_module libexec/mod_alias.so


常用的模块:
最常用的可能就是php和JAVA WEB应用的wrapper,此外,从性能上讲:mod_gzip可以减少40%左右的流量,从而减少机器用于传输的负载,而mod_expires可以 减少10%左右的重复请求,让重复的用户请求CACHE在本地,根本不向服务器发出请求。

建议将所有MODULE的配置都放到

PHP的安装:
/path/to/php_src/configure --with-apxs=/path/to/apache/bin/apxs --with-other-modules-you-need
需要修改的配置:
AddType application/x-httpd-php .php .php3 .any_file_in_php

resin的安装设置:
/path/to/resin/src/configure --with-apxs=/path/to/apache/bin/apxs

一般将具体的resin设置放在另外一个文件中:

CauchoConfigFile /path/to/apache/conf/resin.conf


mod_expires的安装配置:

ExpiresActive on
#所有的.gif文件1个月以后过期
ExpiresByType image/gif "access plus 1 month"
#所有的文件缺省1天以后过期
ExpiresDefault "now plus 1 day"


mod_gzip的安装:
/path/to/apache/bin/apxs -i -a -c mod_gzip.c


mod_gzip和PHP在一起的配置

mod_gzip_on Yes
mod_gzip_minimum_file_size 1000
mod_gzip_maximum_file_size 300000
mod_gzip_item_include file \.htm$
mod_gzip_item_include file \.html$
mod_gzip_item_include file \.php$
mod_gzip_item_include file \.php3$
mod_gzip_item_include mime text/.*
mod_gzip_item_include mime httpd/unix-directory
#不要让mod_gzip和php的session使用同一个临时目录:php_session需要通过php.ini设置session.save_path = /tmp/php_sess
mod_gzip_temp_dir /tmp/mod_gzip
mod_gzip_dechunk Yes
mod_gzip_keep_workfiles No

mod_gzip和mod_php的配合:不要让mod_gzip和mod_php使用同一个临时目录;

mod_gzip和RESIN配合:要让mod_gzip在mod_caucho后LOAD,否则mod_gzip不起作用
...othr modules
AddModule mod_so.c
AddModule mod_caucho.c
#notice: mod_gzip must load after mod_caucho
AddModule mod_gzip.c
AddModule mod_expires.c
...


mod_gzip_on Yes
mod_gzip_dechunk yes
mod_gzip_keep_workfiles No
mod_gzip_minimum_file_size 3000
mod_gzip_maximum_file_size 300000
mod_gzip_item_include file \.html$
mod_gzip_item_include mime text/.*
mod_gzip_item_include mime httpd/unix-directory
mod_gzip_item_include handler 'caucho-request'


日志轮循工具cronolog的安装和设置:cronolog可以非常整齐的将日志按天轮循存储
缺省编译安装到/usr/local/bin/下,只需要将配置改成:

CustomLog "|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log" combined

日志将按天截断并存放在以weekday为目录名的目录下:比如:log/1是周一,log/5是周五, log/0是周日

升级维护:

由于使用标准化的DSO模式安装APACHE,APACHE的HTTPD核心服务和应用模块以及应用模块之间都变的非常灵活,建议将所有独立模块的配置都放在

CONFIGURATIONS..

里,这样配置非常容易通过屏蔽某个模块来进行功能调整:比如:
#AddModule mod_gzip.c
就屏蔽了mod_gzip,其他模块不首任何影响。

安装和维护过程:

系统安装:系统管理员的职责就是安装系统和一个按照DSO模式安装的APACHE,然后COLON。
应用安装:由应用管理员负责具体应用所需要的模块并设置HTTPD。
系统升级:系统管理员:升级系统/升级APACHE
应用升级:应用管理员:升级应用模块:PHP CAUCHO等
系统备份/恢复:如果APACHE不在缺省的系统盘上,只需要将APACHE目录备份就可以了,遇到系统分区的硬件问题直接使用预先准备好的系统COLON,直接将APACHE所在物理盘恢复就行了。
系统管理员:APACHE的最简化安装 OS + APACHE(httpd core only)
应用管理员:应用模块定制   +so
+php
+so
+caucho
+ssl
应用: 纯静态页面服务:
image.example.com
www.example.com bbs.example.com mall.example.com

例子:APACHE和PHP模块的独立升级。

如果APACHE是按照以下方式安装:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
PHP是按照以下方式安装:
./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql

以后单独升级APACHE的时候,仍然是:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
make
su
#/home/apache/bin/apachectl stop
#make install

单独升级php时,仍然是:
./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
make
su
#/home/apache/bin/apachectl stop
#make install

小技巧:

Apache安装后,缺省根目录下没有但很有用的2个文件:

favicon.ico: favicon.ico是一个16x16的站点图标文件,如果浏览器发现有这个文件,在地址栏中会用这个图标替换调浏览器的网页图标。IE6和MOZILLA等主流浏览器都支持这个功能。
robots.txt: 用于告诉搜索引擎的爬虫程序(spider)网站那些页面可以被索引,那些不可以。具体说明请参考:
http://www.robotstxt.org/wc/robots.html
 

参考文档:

Apache
http://httpd.apache.org

php
http://www.php.net

Resin
http://www.caucho.com

mod_gzip
http://www.remotecommunications.com/apache/mod_gzip/

Cronolog
http://www.cronolog.org

mod_expires
http://httpd.apache.org/docs/mod/mod_expires.html

- 作者: 冯唐 2006年07月3日, 星期一 15:11  回复(0) |  引用(2) 加入博采

常用正则表达式
匹配中文字符的正则表达式: [\u4e00-\u9fa5]

匹配双字节字符(包括汉字在内):[^\x00-\xff]

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

匹配首尾空格的正则表达式:(^\s+)|(\s+$)

应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:

String.prototype.trim = function()
{
return this.replace(/(^\s+)|(\s+$)/g, "");
}

利用正则表达式分解和转换IP地址:

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:

function IP2V(ip)
{
re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))

匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

匹配网址URL的正则表达式:
http://([/w-]+/.)+[/w-]+(/[/w- ./?%&=]*)?

利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复]

var s="abacabefgeeii"
var s1=s.replace(/(.).*\1/g,"$1")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2) //结果为:abcefgi

这个方法对于字符顺序有要求的字符串可能不适用。

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

s="
http://www.zhway.com/aaa.html"
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
alert(s)

利用正则表达式限制网页表单里的文本框输入内容:

用 正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,′′)" onbeforepaste="clipboardData.setData(′text′,clipboardData.getData(′text′).replace(/[^\u4E00-\u9FA5]/g,′′))"

用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,′′)" onbeforepaste="clipboardData.setData(′text′,clipboardData.getData(′text′).replace(/[^\uFF00-\uFFFF]/g,′′))"

用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,′′) "onbeforepaste="clipboardData.setData(′text′,clipboardData.getData(′text′).replace(/[^\d]/g,′′))"

用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,′′) "onbeforepaste="clipboardData.setData(′text′,clipboardData.getData(′text′).replace(/[^\d]/g,′′))"


下面是常用的17种正则表达式:

"^\d+$"  //非负整数(正整数 + 0)

"^[0-9]*[1-9][0-9]*$"  //正整数

"^((-\d+)|(0+))$"  //非正整数(负整数 + 0)

"^-[0-9]*[1-9][0-9]*$"  //负整数

"^-?\d+$"    //整数

"^\d+(\.\d+)?$"  //非负浮点数(正浮点数 + 0)

"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"  //正浮点数

"^((-\d+(\.\d+)?)|(0+(\.0+)?))$"  //非正浮点数(负浮点数 + 0)

"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"  //负浮点数

"^(-?\d+)(\.\d+)?$"  //浮点数

"^[A-Za-z]+$"  //由26个英文字母组成的字符串

"^[A-Z]+$"  //由26个英文字母的大写组成的字符串

"^[a-z]+$"  //由26个英文字母的小写组成的字符串

"^[A-Za-z0-9]+$"  //由数字和26个英文字母组成的字符串

"^\w+$"  //由数字、26个英文字母或者下划线组成的字符串

"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"    //email地址

"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$"  //url

提取信息中的网络链接:
(h|H)(r|R)(e|E)(f|F) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?
提取信息中的邮件地址:
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
提取信息中的图片链接:
(s|S)(r|R)(c|C) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?
提取信息中的ip地址:
(\d+)\.(\d+)\.(\d+)\.(\d+)
提取信息中的中国手机号码:
(86)*0*13\d{9}
提取信息中的中国固定电话号码:
(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}
提取信息中的中国电话号码(包括移动和固定电话):
(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}
提取信息中的中国邮政编码:
[1-9]{1}(\d+){5}
提取信息中的中国身份证号码:
\d{18}|\d{15}
提取信息中的整数:
\d+
提取信息中的浮点数(即小数):
(-?\d*)\.?\d+
提取信息中的任何数字 :
(-?\d*)(\.\d+)?
提取信息中的中文字符串:
[\u4e00-\u9fa5]*
提取信息中的双字节字符串 (汉字):
[^\x00-\xff]*
提取信息中的英文字符串:
\w*

 
载 http://zhway.cnblogs.com/archive/2006/03/18/352523.aspx

- 作者: 冯唐 2006年06月23日, 星期五 15:16  回复(0) |  引用(2) 加入博采

如何匹配字符串中的汉字
   

匹配汉字:

Regex r= new Regex(@"[\u4e00-\u9fa5]+");
MatchCollection m=r.Match(yourstring);

-------------------------
如果需要使用正则表达式匹配Unicode字符的话...
这里是几个主要非英文语系字符范围(google上找到的):

2E80~33FFh:中日韩符号区。收容康熙典部首、中日韩辅助部首、注音符号、日本假名、韩文音符,中日韩的符号、标点、带圈或带括符文数字、月份,以及日本的假名组合、单位、年号、月份、日期、时间等。

3400~4DFFh:中日韩认同表意文字扩充A区,总计收容6,582个中日韩汉字。

4E00~9FFFh:中日韩认同表意文字区,总计收容20,902个中日韩汉字。

A000~A4FFh:彝族文字区,收容中国南方彝族文字和字根。

AC00~D7FFh:韩文拼音组合字区,收容以韩文音符拼成的文字。

F900~FAFFh:中日韩兼容表意文字区,总计收容302个中日韩汉字。

FB00~FFFDh:文字表现形式区,收容组合拉丁文字、希伯来文、阿拉伯文、中日韩直式标点、小符号、半角符号、全角符号等。

比如需要匹配所有中日韩非符号字符,那么正则表达式应该是^[\u3400-\u9FFF]+$
理论上没错, 可是我到msn.co.ko随便复制了个韩文下来, 发现根本不对, 诡异
再到msn.co.jp复制了个'お', 也不得行..

然后把范围扩大到^[\u2E80-\u9FFF]+$, 这样倒是都通过了, 这个应该就是匹配中日韩文字的正则表达式了, 包括我們臺灣省還在盲目使用的繁體中文

而关于中文的正则表达式, 应该是^[\u4E00-\u9FFF]+$, 和论坛里常被人提起的^[\u4E00-\u9FA5]+$很接近

需要注意的是论坛里说的^[\u4E00-\u9FA5]+$这是专门用于匹配简体中文的正则表达式, 实际上繁体字也在里面, 我用测试器测试了下'中華人民共和國', 也通过了, 当然, ^[\u4E00-\u9FFF]+$也是一样的结果

载 http://sgsoft.cnblogs.com/archive/2006/04/26/32486.html



- 作者: 冯唐 2006年06月23日, 星期五 15:12  回复(0) |  引用(2) 加入博采

利用集群技术实现 Web 服务器的负载均衡

参考资料:http://www.linuxvirtualserver.org/software/index.html
http://www.chinaunix.net/

集群和负载均衡的概念

集群(Cluster)
所谓集群是指一组独立的计算机系统构成的一个松耦合的多处理器系统,它们之间通过网络实现进程间的通信。应用程序可以通过网络共享内存进行消息传送,实现分布式计算机。

负载均衡(Load Balance)
网络的负载均衡是一种动态均衡技术,通过一些工具实时地分析数据包,掌握网络中的数据流量状况,把任务合理均衡地分配出去。这种技术基于现有网络结构,提供了一种扩展服务器带宽和增加服务器吞吐量的廉价有效的方法,加强了网络数据处理能力,提高了网络的灵活性和可用性。

特点
(1)高可靠性(HA)。利用集群管理软件,当主服务器故障时,备份服务器能够自动接管主服务器的工作,并及时切换过去,以实现对用户的不间断服务。
(2)高性能计算(HP)。即充分利用集群中的每一台计算机的资源,实现复杂运算的并行处理,通常用于科学计算领域,比如基因分析、化学分析等。
(3)负载平衡。即把负载压力根据某种算法合理分配到集群中的每一台计算机上,以减轻主服务器的压力,降低对主服务器的硬件和软件要求。

LVS系统结构与特点
1. Linux Virtual Server:简称LVS。是由中国一个Linux程序员章文嵩博士发起和领导的,基于Linux系统的服务器集群解 决方案,其实现目标是创建一个具有良好的扩展性、高可靠性、高性能和高可用性的体系。许多商业的集群产品,比如RedHat的Piranha、 Turbo Linux公司的Turbo Cluster等,都是基于LVS的核心代码的。
2. 体系结构:使用LVS架设的服务器集群系统从体系结构上看是透明的,最终用户只感觉到一个虚拟服务器。物理服务器之间可以通过高速的LAN或分布在 各地的WAN相连。最前端是负载均衡器,它负责将各种服务请求分发给后面的物理服务器,让整个集群表现得像一个服务于同一IP地址的虚拟服务器。
3. LVS的三种模式工作原理和优缺点: Linux Virtual Server主要是在负载均衡器上实现的,负载均衡器是一台加了 LVS Patch的2.2.x版内核的Linux系统。LVS Patch可以通过重新编译内核的方法加入内核,也可以当作一个动态的模块插入现在的内 核中。
负载均衡器可以运行在以下三种模式下:
(1)Virtual Server via NAT(VS-NAT):用地址翻译实现虚拟服务器。地址转换器有能被外界访问到的合法IP地址,它修改来 自专有网络的流出包的地址。外界看起来包是来自地址转换器本身,当外界包送到转换器时,它能判断出应该将包送到内部网的哪个节点。优点是节省IP地址,能 对内部进行伪装;缺点是效率低,因为返回给请求方的流量经过转换器。
(2)Virtual Server via IP Tunneling (VS-TUN):用IP隧道技术实现虚拟服务器。这种方式是在集群的节点不在 同一个网段时可用的转发机制,是将IP包封装在其他网络流量中的方法。为了安全的考虑,应该使用隧道技术中的VPN,也可使用租用专线。 集群所能提供的 服务是基于TCP/IP的Web服务、Mail服务、News服务、DNS服务、Proxy服务器等等.
(3)Virtual Server via Direct Routing(VS-DR):用直接路由技术实现虚拟服务器。当参与集群的计算机和作为控 制管理的计算机在同一个网段时可以用此法,控制管理的计算机接收到请求包时直接送到参与集群的节点。优点是返回给客户的流量不经过控制主机,速度快开销 少。
以四台服务器为例实现负载均衡:

安装配置LVS
1. 安装前准备:
(1)首先说明,LVS并不要求集群中的服务器规格划一,相反,可以根据服务器的不同配置和负载状况,调整负载分配策略,充分利用集群环境中的每一台服务器。如下表:
Srv Eth0 Eth0:0 Eth1 Eth1:0
vs1 10.0.0.1 10.0.0.2 192.168.10.1 192.168.10.254
vsbak 10.0.0.3 192.168.10.102
real1 192.168.10.100
real2 192.168.10.101
其中,10.0.0.2是允许用户访问的IP。
(2)这4台服务器中,vs1作为虚拟服务器(即负载平衡服务器),负责将用户的访问请求转发到集群内部的real1,real2,然后由real1,real2分别处理。 Client为客户端测试机器,可以为任意操作系统。
(3)所有OS为redhat6.2,其中vs1 和vsbak 的核心是2.2.19, 而且patch过ipvs的包, 所有real server的Subnet mask 都是24位, vs1和vsbak 的10.0.0. 网段是24 位。
2.理解LVS中的相关术语
(1) ipvsadm :ipvsadm是LVS的一个用户界面。在负载均衡器上编译、安装ipvsadm。
(2) 调度算法: LVS的负载均衡器有以下几种调度规则:Round-robin,简称rr;weighted Round-robin,简称 wrr;每个新的连接被轮流指派到每个物理服务器。Least-connected,简称lc;weighted Least-connected,简称 wlc,每个新的连接被分配到负担最小的服务器。
(3) Persistent client connection,简称pcc,(持续的客户端连接,内核2.2.10版以后才支持)。所有来自同一个 IP的客户端将一直连接到同一个物理服务器。超时时间被设置为360秒。Pcc是为https和cookie服务设置的。在这处调度规则下,第一次连接 后,所有以后来自相同客户端的连接(包括来自其它端口)将会发送到相同的物理服务器。但这也会带来一个问题,因为大约有25%的Internet可能具有 相同的IP地址。
(4) Persistent port connection调度算法:在内核2.2.12版以后,pcc功能已从一个调度算法(你可以选择不同的调度 算法:rr、wrr、lc、wlc、pcc)演变成为了一个开关选项(你可以让rr、 wrr、lc、wlc具备pcc的属性)。在设置时,如果你没有选 择调度算法时,ipvsadm将默认为wlc算法。 在Persistent port connection(ppc)算法下,连接的指派是基于端口 的,例如,来自相同终端的80端口与443端口的请求,将被分配到不同的物理服务器上。不幸的是,如果你需要在的网站上采用cookies时将出问题,因 为http是使用80端口,然而cookies需要使用443端口,这种方法下,很可能会出现cookies不正常的情况。
(5)Load Node Feature of Linux Director:让Load balancer 也可以处理users 请求。
(6)IPVS connection synchronization。
(7)ARP Problem of LVS/TUN and LVS/DR:这个问题只在LVS/DR,LVS/TUN 时存在。
3. 配置实例
(1) 需要的软件包和包的安装:
I. piranha-gui-0.412-2*.rpm (GUI接口cluster设定工具);
II. piranha-0.4.12-2*.rpm;
III. ipchains-1.3.9-6lp*.rpm (架设NAT)。
取得套件或mount到光盘,进入RPMS目录进行安装:
# rpm -Uvh piranha*
# rpm -Uvh ipchains*
(2) real server群:
真正提供服务的server(如web server),在NAT形式下是以内部虚拟网域的形式,设定如同一般虚拟网域中Client端使用网域:192.168.10.0/24 架设方式同一般使用虚拟IP之局域网络。
a. 设网卡IP
real1 :192.168.10.100/24
real2 :192.168.10.101/24
b.每台server均将default gateway指向192.168.10.254。 192.168.10.254为该网域唯一对外之信道,设定在virtual server上,使该网域进出均需通过virtual server 。
c.每台server均开启httpd功能供web server服务,可以在各real server上放置不同内容之网页,可由浏览器观察其对各real server读取网页的情形。
d.每台server都开启rstatd、sshd、rwalld、ruser、rsh、rsync,并且从Vserver上面拿到相同的lvs.conf文件。
(3) virtual server:
作用在导引封包的对外主机,专职负责封包的转送,不提供服务,但因为在NAT型式下必须对进出封包进行改写,所以负担亦重。
a.IP设置:
对外eth0:IP:10.0.0.1 eth0:0 :10.0.0.2 
对内eth1:192.168.10.1 eth1:0 :192.168.10.254
NAT形式下仅virtual server有真实IP,real server群则为透过virtual server.
b.设定NAT功能
# echo 1 〉 /proc/sys/net/ipv4/ip_forward
# echo 1 〉 /proc/sys/net/ipv4/ip_always_defrag
# ipchains -P forward MASQ
c.设定piranha 进入X-window中 (也可以直接编辑/etc/lvs.cf )
a).执行面板系统piranha
b).设定“整体配置”(Global Settings) 主LVS服务器主机IP:10.0.0.2, 选定网络地址翻译(预设) NAT路径名称: 192.168.10.254, NAT 路径装置: eth1:0
c).设定虚拟服务器(Virtual Servers) 添加编辑虚拟服务器部分:(Virtual Server)名称:(任意取名);应用: http;协议: tcp;连接:80;地址:10.0..0.2;装置:eth0:0; 重入时间:180 (预设);服务延时:10 (预设);加载 监控工具:ruptime (预设);调度策略:Weighted least-connections; 持续性:0 (预设); 持续性屏蔽: 255.255.255.255 (预设); 按下激活:实时服务器部分:(Real Servers); 添加编辑:名字:(任意取名); 地址: 192.168.10.100; 权重:1 (预设) 按下激活
另一架real server同上,地址:192.168.10.101。
d). 控制/监控(Controls/Monitoring) 控制:piranha功能的激活与停止,上述内容设定完成后即可按开始键激活piranha.监控器:显示ipvsadm设定之routing table内容 可立即更新或定时更新。
(4)备援主机的设定(HA)
单一virtual server的cluster架构virtual server 负担较大,提供另一主机担任备援,可避免virtual server的故障而使对外服务工作终止;备份主机随时处于预备状态与virtual server相互侦测
a.备份主机:
eth0:IP 10.0.0.3
eth1:IP 192.168.10.102 同样需安装piranha,ipvsadm,ipchains等套件
b.开启NAT功能(同上面所述)。
c.在virtual server(10.0.0.2)主机上设定。
a).执行piranha冗余度 ;
b).按下“激活冗余度”;
冗余LVS服务器IP: 10.0.0.3;HEARTBEAT间隔(秒数): 2 (预设)
假定在…秒后进入DEAD状态: 5 (预设); HEARTBEAT连接埠: 539 (预设)
c).按下“套用”;
d).至“控制/监控”页,按下“在当前执行层添加PULSE DEAMON” ,按下“开始”;
e).在监控器按下“自动更新”,这样可由窗口中看到ipvsadm所设定的routing table,并且动态显示real server联机情形,若real server故障,该主机亦会从监视窗口中消失。
d.激活备份主机之pulse daemon (执行# /etc/rc.d/init.d/pulse start)。
至此,HA功能已经激活,备份主机及virtual server由pulse daemon定时相互探询,一但virtual server故障,备份主机立刻激活代替;至virtual server 正常上线后随即将工作交还virtual server。

LVS测试
经过了上面的配置步骤,现在可以测试LVS了,步骤如下:
1. 分别在vs1,real1,real2上运行/etc/lvs/rc.lvs_dr。注意,real1,real2上面的/etc/lvs目录是 vs2输出的。如果您的NFS配置没有成功,也可以把vs1上/etc/lvs/rc.lvs_dr复制到real1,real2上,然后分别运行。确保 real1,real2上面的apache已经启动并且允许telnet。
2. 测试Telnet:从client运行telnet 10.0.0.2, 如果登录后看到如下输出就说明集群已经开始工作了:(假设以guest用户身份登录)
[guest@real1 guest]$——说明已经登录到服务器real1上。
再开启一个telnet窗口,登录后会发现系统提示变为:
[guest@real2 guest]$——说明已经登录到服务器real2上。
3. 测试http:从client运行iexplore http://10.0.0.2
因为在real1 和real2 上面的测试页不同,所以登录几次之后,显示出的页面也会有所不同,这样说明real server 已经在正常工作了。

- 作者: 冯唐 2006年06月8日, 星期四 15:12  回复(0) |  引用(2) 加入博采

Oracle如何配置逻辑备用数据库

1.逻辑备用数据库介绍

  逻辑备用数据库使用主数据库的拷贝创建出来,但是创建出来以后,该备用数据库的物理结构就与主数据库不同了。逻辑备用数据库通过应用SQL语句进行更新。这样就允许用户在任何时候都可以在备用数据库上运行查询和报表了。

  因为逻辑备用数据库使用SQL语句进行与主数据库的同步,所以逻辑备用数据库必须打开。而且,在逻辑备用数据库上,还可以创建其他的索引和物化视图来提高效率。不过逻辑备用数据库在数据类型、表的类型和DDL以及DML上有些限制。

  逻辑备用数据库的优点:

  a、更加有效利用了备用数据库的硬件资源
  b、减小了主数据库的负载,例如将非实时性的查询转移到备用数据库等
  c、可以作为主数据库的备份
2.创建逻辑备用数据库前对主数据库的准备

  在创建逻辑备用数据库的过程中,必须确保在主数据库上做配置所用的用户帐号具有以下数据库角色:
  a、logstdby_administrator角色,用来使用逻辑备用功能
  b、select_catalog_role角色,能够访问所有数据字典视图。

  下面详细说明了创建一个逻辑备用数据库前,必须在主数据库上进行的准备工作。

  2.1 启用forced logging

  将主数据库设置为force logging模式:

SQL>alter database force logging;

  2.2 启用归档,并在本地定义一个归档路径

  确保主数据库设置成归档模式,启用自动归档,并且必须有一个本地的归档路径。

SQL> alter system set log_archive_dest_1='location=D:\oradata\rmantgt\archive mandatory' scope=both;

  2.3 确认log_parallelism初始化参数

  在主数据库上,使用show parameter的命令显示当前log_parallelism初始化参数的值。逻辑备用数据库要求你将该初始化参数设置为1,同时这也是该参数的缺省 值。如果该参数已经是1了,则跳到2.4步骤。否则,设置log_parallelism=1,如下:

SQL>alter system set log_parallelism=1 scope=spfile;

  设置完以后,需要重启数据库以使设置生效。

  2.4 确定所能支持的数据类型和表类型

  在建立逻辑备用数据库前,确保在当前主数据库中的数据类型和表类型都是逻辑备用数据库所能支持的。

  逻辑备用数据库所支持的数据类型有:char、nchar、varchar2和varchar、nvarchar2、number、date、 timestamp、timestamp with time zone、timestamp with local time zone、interval year to month、interval year to second、raw、clob、blob

  逻辑备用数据库不支持的数据类型有:nclob、long、long raw、bfile、rowid、urowid、user-defined types、objec types refs、varrays、nested tables

  逻辑备用数据库不支持的表、sequences和视图有:用户在sys schema里定义的表和sequences、那些含有不支持的数据类型的表、使用了segment compression的表、索引组织表(index-organized tables)

  确定主数据库是否含有不支持的对象,查看dba_logstdby_unsupported视图,该视图列出了逻辑备用数据库所不支持的对象:

SQL> select distinct owner,table_name from dba_logstdby_unsupported order by owner,table_name;

如果主数据库含有不支持的对象,则日志应用服务在逻辑备用数据库上运用重做日志会自动剔除那些不支持的对象。

  如果以下SQL语句在主数据库上运行了的话,那么传到逻辑备用数据库以后,也不会在逻辑备用数据库上运行:ALTER DATABASE、ALTER SESSION、ALTER SNAPSHOT、ALTER SNAPSHOT LOG、ALTER SYSTEM SWITCH LOG、CREATE CONTROL FILE、CREATE DATABASE、CREATE DATABASE LINK、CREATE PFILE FROM SPFILE、CREATE SCHEMA AUTHORIZATION、CREATE SNAPSHOT、CREATE SNAPSHOT LOG、CREATE SPFILE FROM PFILE、CREATE TABLE AS SELECT FROM A CLUSTER TABLE、DROP DATABASE LINK、DROP SNAPSHOT、DROP SNAPSHOT LOG、EXPLAIN、LOCK TABLE、RENAME、SET CONSTRAINTS、SET ROLE、SET TRANSACTION。

  那些在主数据库上修改元数据的pl/sql存储过程也不会在逻辑备用数据库上运行。比如在主数据库上运行了 dbms_mview_refresh,但是传到备用数据库后并不会被应用。唯一的例外是dbms_job包,job元数据会应用到逻辑备用数据库上,但 是jobs本身不会执行。

  2.5 确认主数据库里表的行都可以唯一标识

  由于在逻辑备用数据库里rowid可能不等于主数据库里的rowid,所以必须采取一些机制来保证在主数据库里所更新的行能够对应到备用数据库里相应的行。

  可以采用以下对应方法:主键或唯一索引。

  在主数据库里,无论合适与否,每个表都添加主键或唯一索引。这样就能确保应用SQL操作时可以有效的更新逻辑备用数据库里的数据了。
  采用以下的方法来确保日志应用服务可以唯一的标识表里的行。

  2.5.1 在主数据库里找到那些没有唯一标识的表

  查询dba_logstdbby_not_unique视图,来确定主数据库里那些还没有主键或唯一索引的表。

SQL> select owner,table_name,bad_column from dba_logstdby_not_unique where table_name not in(select table_name from dba_logstdby_unsupported);

  该语句找出的表仍然能够支持,因为supplemental logging在重做日志里添加了唯一标识行的信息。主键或唯一索引的存在与否,能够影响追加的日志(supplemental logging):

  a、如果表有主键或唯一索引,则在supplemental logging的时候,向重做日志添加的信息是最少的。
  b、如果表没有主键或唯一索引,supplemental logging会自动在重做日志里记录所有字段的值。

  2.5.2 添加一个disabled的主键类型的rely的限制(disabled primary key rely constraint)

  如果应用程序确保表里的行是唯一标识的,你可以在表上创建一个disabled主键类型的rely的限制:

SQL>alter table mytab add primary key(id,name) rely disable;

  rely constraint告诉系统确保了所有的行都是唯一的。如果rely constraint所指定的列没有唯一,则在逻辑备用数据库应用SQL时将会失败。最好添加主键或唯一索引,这样在逻辑备用数据库应用SQL语句时也会速度快些。

  2.6 确保启用追加的日志(supplemental logging)

  在创建逻辑备用数据库前,在主数据库上,必须启用supplemental logging。因为oracle只会对那些修改的列生成日志,这对唯一标识那些被修改的行时并不总是足够的,额外的信息(supplemental)必 须被加到重做日志里。这些被加到联机日志里的supplemental信息能够帮助日志应用服务正确的标识逻辑备用数据库里的表和表里的行。

  确定在主数据库上,supplemental logging是否被启用,可以查询v$database,如下:
SQL> select supplemental_log_data_pk,supplemental_log_data_ui from v$database;
 

  如果为NO,则说明supplemental logging没有被启用。如果被启用,则转到2.7,否则如果没有被启用,则采用下面的方法来启用。

  2.6.1 启用supplemental logging

  在主数据库上,执行下面语句以便将主键和唯一索引信息添加到归档日志里:
SQL> alter database add supplemental log data(primary key,unique index) columns;
 

  该语句在主数据库中向重做日志添加了唯一标识行的信息,从而日志应用服务可以在备用数据库里正确的标识相同的行了。

  2.6.2 切换到一个新的重做日志

  在主数据库上,执行以下语句:

SQL> alter system archive log current;

  通过切换到一个新的日志文件,这样,你就可以保证当前重做日志既不含有supplemental日志数据也不含有 nonsupplemental日志数据。逻辑备用数据库不能使用那些既含有supplemental日志数据又含有nonsupplemental日志 数据的重做日志。

  2.6.3 确保启用supplemental logging
SQL> select supplemental_log_data_pk as primaryKey,supplemental_log_data_ui as uniqueIndex from v$database;
 

  如果都为yes则说明启动了。

  如果在一个已经含有物理备用数据库的data guard配置中启用了supplemental logging的话,那么必须在每个物理备用数据库中分别执行alter database add supplemental log data,以便将来在switchover的时候能够正常工作。

  2.7 创建一个可替代的表空间

  如果希望在主数据库和逻辑备用数据库之间进行switchover,你必须在主数据库上创建一个替代表空间,并且将逻辑备用数据库里system表转移到这个替代表空间里。

  逻辑备用数据库使用一组在sys和system schema下的表。这些表缺省创建在system表空间下。这些表可能会增长非常快。通过预先准备一个单独的表空间,然后将这些逻辑备用系统表转移到这 个单独的表空间下,从而避免了这些表将整个system表空间都填满的情况出现。

  在逻辑备用数据库创建时,会向这些逻辑备用系统表填数据。这样,应该在创建逻辑备用数据库前,就将这些表转移到独立的表空间里去。

  创建表空间:
SQL> create tablespace logmnrts datafile 'D:\oradata\rmantgt\logmnrts.dbf' size 25m autoextend on maxsize unlimited;
 

  转移表:

SQL> execute dbms_logmnr_d.set_tablespace('logmnrts');

  如果在备用数据库里的初始化参数standby_file_management设置为true,则前面创建表空间的命令会自动应用到备用数据库上。否则如果没有设置为true,则需要手工在备用数据库上执行。

3.创建逻辑备用数据库

  3.1 确认主数据库的数据文件和联机日志文件

  在主数据库上,查询v$datafile列出所有的逻辑备用数据库所需要的数据文件:

SQL> select name from v$datafile;NAME------------------------------------------------D:\ORADATA\RMANTGT\SYSTEM01.DBFD:\ORADATA\RMANTGT\USERS02.DBFD:\ORADATA\RMANTGT\USERS01.DBFD:\ORADATA\RMANTGT\UNDO02.DBF

  在主数据库上,查询v$logfile列出所有的逻辑备用数据库所需要的日志文件:

SQL> select group#,type,member from v$logfile;   GROUP# TYPE  MEMBER---------- ------- ------------------------------   1 ONLINE  D:\ORADATA\RMANTGT\REDO01.LOG       2 ONLINE  D:\ORADATA\RMANTGT\REDO02.LOG       3 ONLINE  D:\ORADATA\RMANTGT\REDO03.LOG

  3.2 对主数据库生成一份拷贝

  在主数据库上,进行以下步骤,以生成一份主数据库文件的冷拷贝备份。

  第一步 关闭主数据库

SQL> shutdown;

  第二步 拷贝数据文件到临时目录

  使用操作系统命令将3.1所找出来的数据文件拷贝到一个临时目录。拷贝到临时目录是因为主数据库后面还会再次被关闭。

  第三步 重启主数据库

SQL> startup

  第四步 为备用数据库创建一个控制文件的备份拷贝在主数据库上,为备用数据库创建一个控制文件的备份:

SQL> alter database backup controlfile to'D:\oradata\dataguard_logic_tmp\logicdg.ctl';

  第五步 在主数据库上启用限制登录(restrict session)模式

  在主数据库上,启用限制登录模式,这样就不允许其他用户登录进行DDL或DML操作。

SQL> alter system enable restricted session;

  第六步 创建logminer目录

  为了创建逻辑备用数据库,你必须为逻辑备用数据库手工创建目录结构。在主数据库上,采用以下命令创建logminer目录:

SQL> execute dbms_logstdby.build;

  第七步 在主数据库上禁用限制登录(restrict session)模式

SQL> alter system disable restricted session;

  第八步 确定最后归档的日志文件

  为了获得创建逻辑备用数据库的起点,查询v$archived_log视图,确定最后的归档日志,并且在后面创建的过程中,输入该归档日志的名字。

SQL> alter system archive log current;SQL> select name from v$archived_log where (sequence#=(select max(sequence#) from v$archived_log where dictionary_begin='YES' and standby_dest='NO'));NAME---------------------------------------------------------------------------D:\ORADATA\RMANTGT\ARCHIVE\ARC00315.001

  3.3 为备用数据库准备一个初始化参数文件

  在主数据库上通过spfile创建一个传统的文本格式的初始化参数文件。该文本格式的初始化参数文件可以拷贝到备用数据库所在的系统并且可以被手工修改。

SQL> create pfile='D:\oradata\dataguard_logic_tmp\initLogic.ora' from spfile;

  在后面的3.11的时候,还需要修改该文件的参数以对应备用数据库,然后还要将其转换为spfile。

  3.4 从主数据库所在系统向备用数据库所在系统拷贝文件

  在主数据库所在的系统上,使用操作系统命令拷贝以下二进制文件到备用数据库所在的系统。
  a、备份的数据文件(在4.2.2处创建)
  b、备份的日志文件(在4.2.2处创建)
  c、初始化参数文件(在4.2.3处创建)

  3.5 为备用数据库设置初始化参数

  尽管从主数据库处拷贝的初始化参数文件里的参数设置大部分都适用于逻辑备用数据库,但是有些还是需要修改。
  下面的例子显示了为逻辑备用数据库所作的初始化参数修改。被修改的部分用黑体表示。

 1*.aq_tm_processes=1 2*.background_dump_dest='C:\oracle92\ora92\admin\logicdg\bdump' 3*.compatible='9.2.0.0.0' 4*.control_files='D:\oradata\logicdg\LOGICDG.CTL' 5*.core_dump_dest='C:\oracle92\ora92\admin\logicdg\cdump' 6*.standby_archive_dest='D:\oradata\logicdg\standby' 7*.parallel_max_servers=9 8*.db_block_size=8192 9*.db_cache_size=2516582410*.db_domain=''11*.db_file_multiblock_read_count=1612*.db_name='rmantgt'13*.dispatchers='(PROTOCOL=TCP) (SERVICE=ora920XDB)'14*.fast_start_mttr_target=30015*.global_names=TRUE16*.hash_join_enabled=TRUE17*.instance_name='logicdg'18*.java_pool_size=3355443219*.job_queue_processes=1020*.large_pool_size=838860821*.log_archive_dest=''22*.log_archive_dest_1='location=D:\oradata\logicdg\archive mandatory'23*.log_archive_start=TRUE24*.log_parallelism=125*.open_cursors =30026*.pga_aggregate_target=2516582427*.processes=15028*.query_rewrite_enabled ='FALSE'29*.remote_login_passwordfile='EXCLUSIVE'30*.shared_pool_size=5033164831*.sort_area_size =52428832*.star_transformation_enabled='FALSE'33*.timed_statistics=TRUE34*.undo_management ='AUTO'35*.undo_retention=1080036*.undo_tablespace='UNDOTBS2'37*.user_dump_dest ='C:\oracle92\ora92\admin\logicdg\udump'38#如果主数据库和备用数据库在同一台机器上,就需要做以下参数配 置39*.lock_name_space=logicdg

  这里,对上面的设置做一个简单解释:

  a、db_name:不需要修改,与主数据库保持一致。
  b、compatible:不需要修改,与主数据库保持一致。
  c、control_files:说明了备用数据库的控制文件所在的路径。
  d、log_archive_start:不需要修改,与主数据库保持一致。
  e、standby_archive_dest:说明了主数据库向备用数据库传递归档日志的路径。需要主数据库上配置归档路径为备用数据库,这样,主数据库在归档时,会将归档日志文件发送到备用数据库上该参数指定的位置。
  f、log_archive_dest_1:说明备用数据库的归档日志所存放的路径。一旦出现switchover,那么该备用数据库成为主数据库,则该参数指定了联机日志文件的归档路径。
  g、log_parallelism:不需要修改,与主数据库保持一致。
  h、instance_name:如果主数据库和备用数据库在同一台机器上的话,就需要定义该参数并且与主数据库不同。
  i、lock_name_space:指定备用数据库所在的实例名称。该参数与instance_name相同。
  记住,可能还需要修改一些参数,比如background_dump_dest、user_dump_dest等。
  3.6 创建一个windows服务
  如果备用数据库所在机器为windows系统,则需要使用oradim创建windows服务。
  C:\>oradim -new -sid logicdg -startmode manual

  3.7 为主数据库和备用数据库配置监听

  在主数据库和备用数据库上,分别为彼此配置监听器。如果使用了data guard broker,则必须使用TCP/IP协议配置监听器。
  如果数据库在安装oracle介质的时候就自动创建了数据库的话,则不用配置。

  3.8 在备用数据库所在系统启用死亡连接检测

  通过在sqlnet.ora文件里设置sqlnet.expire_time参数来检测死亡连接。比如

  sqlnet.expire_time=2

  3.9 创建Oracle Net连接名

  在主数据库和备用数据库里,分别创建连接到主数据库和备用数据库的tnsnames名称。

  3.10 启动并mount备用数据库

  在备用数据库上,启动并mount备用数据库。

  注意,如果是windows系统,则还需要创建密码文件。

C:\>orapwd file=C:\oracle92\ora92\DATABASE\PWDlogicdg.ORA password=hanson entries=5SQL>startup mount pfile=C:\oracle92\ora92\admin\logicdg\pfile\initLogic.ora

  3.11 在逻辑备用数据库上重命名数据文件

  在逻辑备用数据库上,需要将从主数据库拷贝来的数据文件所在的路径重新命名,因为要告诉控制文件,现在的数据文件所在的路径已经与主数据库中的路径不一致了,需要更改为当前最新的路径。

C:\>orapwd file=C:\oracle92\ora92\DATABASE\PWDlogicdg.ORA password=hanson entries=5SQL>startup mount pfile=C:\oracle92\ora92\admin\logicdg\pfile\initLogic.ora

  3.12 在逻辑备用数据库上重命名联机日志文件

SQL> select member from v$logfile;MEMBER----------------------------------------------------------------------------D:\ORADATA\RMANTGT\REDO01.LOGD:\ORADATA\RMANTGT\REDO02.LOGD:\ORADATA\RMANTGT\REDO03.LOGSQL> alter database rename file 'D:\ORADATA\RMANTGT\REDO01.LOG'to 'D:\oradata\logicdg\redo01.log';Database altered.SQL> alter database rename file 'D:\ORADATA\RMANTGT\REDO02.LOG'to 'D:\oradata\logicdg\redo02.log';Database altered.SQL> alter database rename file 'D:\ORADATA\RMANTGT\REDO03.LOG'to 'D:\oradata\logicdg\redo03.log';Database altered.SQL> select member from v$logfile;MEMBER----------------------------------------------------------------------------D:\ORADATA\LOGICDG\REDO01.LOGD:\ORADATA\LOGICDG\REDO02.LOGD:\ORADATA\LOGICDG\REDO03.LOG

3.13 打开database guard

  为了防止其他用户在逻辑备用数据库上进行DML操作,在逻辑备用数据库上打开database guard。
  SQL>alter database guard all;
  由于使用的控制文件比数据文件要新,所以直接open时会报错,需要进行恢复。
  SQL>recover database using backup controlfile until cancel;
  然后,直接输入cancel结束恢复。
  SQL>alter database open resetlogs;

  3.14 重新设置逻辑备用数据库名

  通过运行oracle的DBNEWID(nid)实用程序,来改变逻辑备用数据库的名称。改变逻辑备用数据库的名称可以防止该逻辑备用数据库与主数据库之间进行交互作用。在运行nid的时候,必须关闭数据库,并启动到mount状态:
  然后,现在可以运行nid来改变数据库名了:
  

C:\>nid target=sys/hanson@dataguard dbname=logicdgDBNEWID: Release 9.2.0.1.0 - ProductionCopyright (c) 1995, 2002, Oracle Corporation.  All rights reserved.Connected to database RMANTGT (DBID=2455129425)Control Files in database:  D:\ORADATA\LOGICDG\LOGICDG.CTLChange database ID and database name RMANTGT to LOGICDG? (Y/[N]) => yProceeding with operationChanging database ID from 2455129425 to 2205596403Changing database name from RMANTGT to LOGICDG  Control File D:\ORADATA\LOGICDG\LOGICDG.CTL - modified  Datafile D:\ORADATA\LOGICDG\SYSTEM01.DBF - dbid changed, wrote new name  Datafile D:\ORADATA\LOGICDG\LOGMNRTS.DBF - dbid changed, wrote new name  Datafile D:\ORADATA\LOGICDG\USERS01.DBF - dbid changed, wrote new name  Datafile D:\ORADATA\LOGICDG\UNDO02.DBF - dbid changed, wrote new name  Control File D:\ORADATA\LOGICDG\LOGICDG.CTL - dbid changed, wrote new nameDatabase name changed to LOGICDG.Modify parameter file and generate a new password file before restarting.Database ID for database LOGICDG changed to 2205596403.All previous backups and archived redo logs for this database are unusable.Shut down database and open with RESETLOGS option.Succesfully changed database name and ID.DBNEWID - Completed succesfully.

  3.15 在初始化参数文件中修改数据库名

  第一步 修改初始化参数文件中的db_name为logicdg。
  第二步 关闭逻辑备用数据库
  SQL>shutdown immediate;
  第三步 根据pfile创建spfile
  SQL> create spfile from pfile='C:\oracle92\ora92\admin\logicdg\pfile\initLogic.ora';
  第四步 重启逻辑备用数据库

SQL>startup mount;SQL>alter database open resetlogs;

  3.16 为逻辑备用数据库创建一个新的临时表空间

  临时数据文件不需要从主数据库拷贝到逻辑备用数据库上。
  第步 确定当前临时数据文件
  在逻辑备用数据库上,执行如下SQL:
  SQL>select * from v$tempfile;
  如果没有记录,则跳到第三步。
  第二步 在逻辑备用数据库上删除临时数据文件
  SQL>alter database tempfile 'tempfilename' drop;
  第三步 在逻辑备用数据库上,添加一个新的临时数据文件
  1、确定临时表空间

  SQL>select tablespace_name from dba_tablespaces where contents='TEMPORARY';

  2、添加一个临时文件

SQL>alter tablespace temp add tempfile 'D:\ORADATA\LOGICDG\temp01.dbf' size 50m reuse;

  注意,这里的temp表空间空间必须足够,否则逻辑备用数据库在运用主数据库传来的归档日志时会出错。

  3.17 注册归档的日志,并启动SQL应用操作

  注册最新的归档日志文件,并应用重做日志里的数据。

  第一步 注册最新的归档日志文件

  将3.2的第八步查到的归档日志文件注册到逻辑备用数据库。

SQL> alter database register logical logfile 'D:\oradata\logicdg\ARC00290.001';

  第二步 在逻辑备用数据库里开始应用重做日志

  SQL> alter database start logical standby apply initial;

  只有在逻辑备用数据库第一次启动应用重做日志时,指定initial选项。以后启动SQL应用按照以下方法:

SQL>alter database stop logical standby apply;SQL>alter database start logical standby apply;

  3.18 使主数据库向备用数据库进行归档

  必须在主数据库上设置,以使得主数据库能够向备用数据库归档。

  第一步 设置定义归档的初始化参数

  在主数据库的log_archive_dest_n和log_archive_dest_state_n参数重设置主数据库向备用数据库的归档。

  下面的例子显示了如何设置这些参数:

  第一步 设置远程归档参数

SQL> alter system set log_archive_dest_2='service=dataguard mandatory' scope=both;SQL> alter system set log_archive_dest_state_2=enable scope=both;

  第二步 启动远程归档

  SQL> alter system archive log current;

  4.确认逻辑备用数据库正常工作 

  一旦你创建了逻辑备用数据库,并启动了日志转移服务,可能你需要确定一下主数据库的修改已经成功转移到备用数据库上了。为了查看归档的日志文件 已经被备用数据库所接收,首先,需要确定在备用数据库下存在归档的日志文件。在主数据库上归档少量的日志文件,然后检查备用数据库。

  第一步 确定归档日志文件在备用数据库上已经注册了

  SQL>select sequence#,first_time,next_time,dict_begin,dict_end from dba_logstdby_log order by sequence#;

  第二步 在主数据库上归档一些日志

  SQL>alter system archive log current;

  第三步 再次查询dba_logstdby_log视图

  SQL>select sequence#,first_time,next_time,dict_begin,dict_end from dba_logstdby_log order by sequence#;

  查看是否有新的归档日志记录。如果有,就说明成功注册到备用数据库了。这些日志现在可以开始被应用了。

  第四步 确定重做日志的已经被正确应用了在逻辑备用数据库上,查询dba_logstdby_status视图确定重做数据已经被正确应用了。

  SQL>select name,value from v$logstdby_stats where name='coordinator state';

  如果结果是initializing,则说明日志应用服务已经准备好应用SQL操作了,但是从重做日志来的数据还没有应用到逻辑备用数据库上。

  逻辑备用数据库如果有很多表,那么初始化的过程会需要几个小时,但是,一旦初始化结束,后面的应用重做日志会快很多。

  第五步 查询v$logstdby视图,确定当前SQL应用活动

  SQL>select type,high_scn,status from v$logstdby;

  一旦在逻辑备用数据库上,coordinator进程开始应用重做日志,v$logstdby视图通过在status显示applying状态表明正在应用重做日志。high_scn会不断增加。

  第六步 检查日志应用服务的进行到的程度

  SQL>select applied_scn,newest_scn from dba_logstdby_progress;
  如果applied_scn与newest_scn相同,这就意味着所有重做日志里的可用数据都被应用了。这些值可以与dba_logstdby_log视图里的first_change#的值做比较,来得知有多少日志信息已经被应用了以及有多少没应用。

- 作者: 冯唐 2006年06月7日, 星期三 15:44  回复(0) |  引用(2) 加入博采

集群系统实现方案详解
一、集群的基本概念
  
  有一种常见的方法可以大幅提高服务器的安全性,这就是集群。
  
  Cluster集群技术可如下定义:一组相互独立的服务器在网络中表现为单一的系统,并以单一系统的模式加以管理。此单一系统为客户工作站提供高可靠性的服务。
  
  大多数模式下,集群中所有的计算机拥有一个共同的名称,集群内任一系统上运行的服务可被所有的网络客户所使用。Cluster必须可以协调管理各分离的组件的错误和失败,并可透明地向Cluster中加入组件。一个Cluster包含多台(至少二台)拥有共享数据存储空间的服务器。任何一台服务器运行一个应用时,应用数据被存储在共享的数据空间内。每台服务器的操作系统和应用程序文件存储在其各自的本地储存空间上。
  
   Cluster内各节点服务器通过一内部局域网相互通讯。当一台节点服务器发生故障时,这台服务器上所运行的应用程序将在另一节点服务器上被自动接管。 当一个应用服务发生故障时,应用服务将被重新启动或被另一台服务器接管。当以上任一故障发生时,客户将能很快连接到新的应用服务上。
  
  二、集群的硬件配置
  
  镜像服务器双机
  
  集群中镜像服务器双机系统是硬件配置最简单和价格最低廉的解决方案,通常镜像服务的硬件配置需要两台服务器,在每台服务器有独立操作系统硬盘和数据存贮硬盘,每台服务器有与客户端相连的网卡,另有一对镜像卡或完成镜像功能的网卡。
  
  镜像服务器具有配置简单,使用方便,价格低廉诸多优点,但由于镜像服务器需要采用网络方式镜像数据,通过镜像软件实现数据的同步,因此需要占用网络服务器的CPU及内存资源,镜像服务器的性能比单一服务器的性能要低一些。
  
   有一些镜像服务器集群系统采用内存镜像的技术,这个技术的优点是所有的应用程序和网络操作系统在两台服务器上镜像同步,当主机出现故障时,备份机可以在 几乎没有感觉的情况下接管所有应用程序。因为两个服务器的内存完全一致,但当系统应用程序带有缺陷从而导致系统宕机时,两台服务器会同步宕机。这也是内存 镜像卡或网卡实现数据同步,在大数据量读写过程中两台服务器在某些状态下会产生数据不同步,因此镜像服务器适合那些预算较少、对集群系统要求不高的用户。
  
  硬件配置范例:
  
  网络服务器 两台
  服务器操作系统硬盘 两块
  服务器数据存贮硬盘 视用户需要确定
  服务器镜像卡(部分软件可使用标准网卡) 两块
  网络服务网卡 两块
  
  三、 双机与磁盘阵列柜
  
   与镜像服务器双机系统相比,双机与磁盘阵列柜互联结构多出了第三方生产的磁盘阵列柜,目前,豪威公司、精业公司等许多公司都生产有磁盘阵列柜,在磁盘阵 列柜中安装有磁盘阵列控制卡,阵列柜可以直接将柜中的硬盘配置成为逻辑盘阵。磁盘阵列柜通过SCSI电缆与服务器上普通SCSI卡相连,系统管理员需直接 在磁盘柜上配置磁盘阵列。
  
  双机与磁盘阵列柜互联结构不采用内存镜像技术,因此需要有一定的切换时间(通常为60——180秒), 它可以有郊的避免由于应用程序自身的缺陷导致系统全部宕机,同时由于所有的数据全部存贮在中置的磁盘阵列柜中,当工作机出现故障时,备份机接替工作机,从 磁盘阵列中读取数据,所以不会产生数据不同步的问题,由于种方案不需要网络镜像同步,因此这种集群方案服务器的性能要比镜像服务器结构高出很多。
  
   双机与磁盘阵列柜互联结构的缺点是在系统当中存在单点错的缺陷,所谓单点错是指当系统中某个部件或某个应用程序出现故障时,导致所有系统全部宕机。在这 个系统中磁盘阵列柜是会导致单点错,当磁盘阵列柜出现逻辑或物理故障时,所有存贮的数据会全部丢失,因此,在选配这种方案时,需要选用一个品质与售后服务 较好的产品。
  
  硬件配置范例:
  
  网络服务器 两台
  服务器操作系统硬盘 两块
  第三方生产的磁盘阵列柜 一台
  磁盘柜专用SCSI电线 两根
  磁盘阵列柜数据存贮硬盘 视用户需求确定
  网络服务网卡 两块
  除此之外,一些厂商还有更优秀的技术的解决方案,比如HP。
  
  四、 HP双机双控容错系统
  
  HP NetServer为双机双控容错系统提供了高品质和高可靠的硬件基础。。
  
  HP双机双控容错系统结合了HP服务器产品的安全可靠性与Cluster技术的优点,相互配合二者的优势。
  
  硬件配置范例:
  
  HP L系统的网络服务器 两台
  服务器操作系统硬盘 两块
  HP硬盘存贮柜(SS/6,RS/8,RS/12) 一台
  磁盘柜专用SCSI集群适配电缆 两根
  磁盘柜数据存贮硬盘 视用户需求确定
  HP集群专用阵列卡 两块
  网络服务网卡 两块
  
  五、 HP光纤通道双机双控集群系统
  
  光纤通道是一种连接标准,可以作为SCSI的一种替代解决方案,光纤技术具有高带宽、抗电磁干扰、传输距离远、质量高、扩展能力强等特性,目前在FC-AL仲裁环路上可接入126个设备。
  
   光纤设备提供了多种增强的连接技术,大大方便了用户使用。服务器系统可以通过光缆远程连接,最大可跨越10公里的距离。它允许镜像配置,这样可以改善系 统的容错能力。服务器系统的规模将更加灵活多变。SCSI每条通道最多可连接15个设备,而光纤仲裁环路最多可以连接126个设备。
  
  光纤集群系统组成:
  
   HP光纤集群系统硬件设备包括有两台HP服务器(需支持光纤卡,目前有LC2000、LH3000、LH4、LH6000、LT6000、 LXr8000、LXR8500)及光纤适配卡,可以使用RS/12FC光纤磁盘阵列柜,需另加一对或两对网卡用于心跳检测和与客户端连接。在配置过程中 还需另外选配光纤卡到光纤存贮设备的光纤电缆。
  
  硬件配置:
  
  HPL系统的网络服务器 两台
  服务器操作系统硬盘 两块
  HP光纤阵列存贮柜(RS/12FC) 一台
  光纤磁盘柜专用光纤电缆 两根
  光纤磁盘柜数据存贮硬盘 视用户需求确定
  HP光纤适配卡 两块
  网络服务网卡 两块
  
  六、集群的软件配置
  
  基于NT平台的集群软件
  
  Microsoft的MSCS,也有许多第三方的专业软件公司开发的集群软件,如豪威的DATAWARE,VINCA公司的STANDBY SERVER,NSI公司的DOUBLE-TAKE。
  
  MS WolfPack的特点
  
  MS WolfPack是MS Cluster server的别称,是微软针对Cluster技术研制开发的双机软件。它集成在NT SERVER上,支持由二台机器组成的双机系统,提供一种高可用且易管理的应用环境。
  
  主要特点:
  
  自动检测和修复服务器或应用程序的错误
  可实现对服务器中应用程序的切换
  可通过TCP/IP连接各种客户端,如MS-DOS、WINDOWS 3.X/9X/NT,Apple Macintosh、UNIX等
  生产主机无需人工干涉即可自动恢复数据并接管任务
  易管理性:
  
  可自动审核服务器和应用程序的工作状态
  可建立高可用性的应用程序、文件共享、打印请求等
  可灵活设置应用程序和数据的恢复策略
  简单操作即可进行应用程序的离线,重新再线,服务器间的迁移。
  目前,WINDOWS 2000 Advanced Server与WINDOWS 2000 DataCenter Server都集成有更先进集群技术。
  
  其它的网络操作系统平台上也有许多集群软件,比如:
  
  基于novell平台的集群软件有Novell HA Server、Novell SFT III
  基于sco UNIX平台的集群软件有Sentinel集群软件
  基于Linux平台的集群软件有TurboCluster
  
  七、集群技术的发展趋势
  
   集群技术随着服务器硬件系统与网络操作系统的发展将会在可用性、高可靠性、系统冗余等方面逐步提高。未来的集群可以依靠集群文件系统实现对系统中的所有 文件、设备和网络资源的全局访问,并且生成一个完整的系统映像。这样,无论应用程序在集群中的哪台服务器上,集群文件系统允许任何用户(远程或本地)都可 以对这个软件进行访问。任何应用程序都可以访问这个集群任何文件。甚至在应用程序从一个节点转移到另一个节点的情况下,无需任何改动,应用程序就可以访问 系统上的文件。
  
  在今天,利用服务器的集群技术,通过周密计划和网络维护,系统破坏的机率是非常小的。所以,企业服务器的稳定必须使用集群技术。

- 作者: 冯唐 2006年06月1日, 星期四 17:17  回复(0) |  引用(2) 加入博采