附近装电脑系统可以在哪xgao-附近有没有组装电脑的
1.《绝地求生 全军出击》春节试炼版上线,顺应千元大众机主流
2.iphoneX耗电快什么原因
3.求高中作文六篇。急!急!急!
4.Delphi深度探索之PItemIDList的基本概念
《绝地求生 全军出击》春节试炼版上线,顺应千元大众机主流
作者:liugaotian
2017年9月13日凌晨1时,在万众瞩目下,苹果2017秋季新品发布会正式召开。作为本次发布会上的重头戏,新一代iPhone标志性产品“iPhone X”的公布无疑为时下创意匮乏的手机制造业投下了一枚重磅。不料和媒体、手机制造商们的连连惊叹不同,这一次,iPhone X在包括果粉在内的广大手机用户间反倒没能引起像往日iPhone 4S、iPhone 5那样的热烈追捧。究其原因,是因为这一代iPhone不再优秀了吗?
首先,iPhone X继承了iPhone 8所有最好的功能,再者,5.8英寸的OLED、Home键的调整,以及面容识别等功能的加入,让iPhone X在手机市场中毋庸置疑是一款现象级产品。但问题在于,其一,随时间延伸,用户对苹果的新鲜感难免会有所降低;其二,也是最关键的一点,在国内买一部iPhone X的价钱完全可以直接上一台i7,1070Ti的豪华台式机了。所以尽管iPhone X真的很棒,但只有少部分人买得起这款奢侈品。
某网购平台iPhone X售价 看得我肾疼
类似“曲高和寡”的商品在生活中并不是个例。对于游戏业来说,蓝洞公司于17年发行的《绝地求生》在上线初期正是一个曲高和寡的典型。一定程度上,对于国内绝大部分腾讯系玩家来说,从《LOL》、《DNF》等游戏到《绝地求生》的转变,无疑是跨越性的。后者对电脑配置的需求远远超出腾讯系玩家的常用机配置。所以我们看到,很多玩家为了进入高配游戏的世界,动辄5000+大洋换显卡、换CPU,其过程不可谓不艰辛。
Steam上的“ 吃鸡 ”配置要求,开到高配至少要1050Ti
所以,如何在“游戏品质”和“低配”之间达成一种平衡,就成了游戏厂商无法回避的难题。回望17年游戏市场,根据美国数据网站SuperData前不久的发布数据报告显示,腾讯旗下的《英雄联盟》《地下城与勇士》《穿越火线》分列PC游戏收入榜前三甲。诚然这三款游戏无法代表当今游戏业的最高水准,但其令人望而生畏的高额收入还是不得不让人为之惊叹。
而要说到这三款分别发行于09年、05年、07年的国民级游戏之所以能长盛不衰的原因,则不免要提到腾讯旗下社交产品庞大的用户基数。借由自身不俗的流量和早年数款“自研”游戏的资金积累,腾讯从国内一众游戏商中脱颖而出,成为这三款游戏的国内代理商。对于如何将庞大的用户基础转化为游戏玩家,除了亲民的“免费畅玩”运营理念外,游戏本身出色的优化和低配爽玩的特点极大提升了用户适配性。
2017游戏市场收入排行榜,腾讯三雄稳居前三
常言道,风水轮流转。数年的时间,国内游戏的主流趋势从MOBA逐渐转向了“吃鸡”。纵观国内游戏发展史,在很长一段时间内,出于某些不可名状的原因,国内游戏曾出现断层的状况。继PC之后,国内游戏市场越过了主机、掌机等时代,直接进入了手机的天下。而在如今鱼龙混杂的手游市场中,最引人瞩目的一方无疑是腾讯旗下的天美工作室群。
诸如《天天酷跑》《天天飞车》《王者荣耀》等众多脍炙人口的手游佳作均出自天美之手。此外,让人欣慰的是,天美出品的游戏向来都具备“低配爽玩”的特性。上至万元果机iPhone X,下至千元国产安卓机,无关乎机型贵宜,一律能享受到天美游戏中最核心的乐趣。
《王者荣耀》——天美旗下“低配爽玩”的代表作之一
3月9日,天美工作室群制作的正版吃鸡手游《 绝地求生 全军出击 》新版本上线。《绝地求生 全军出击》自身品质自然无需多虑,笔者亲手试玩后也确实印证了这一点。基于此,许多玩家便提出了游戏能否适配全价位机型的疑惑,要知道,游戏之所以被称为正版“吃鸡”,在于它真正做到了在手机端吃鸡的完美展现,其中自然也包括画质。
2月5日,《绝地求生 全军出击》曾开启过一波先遣服技术测试,在当时的技术测试中,《绝地求生 全军出击》公布了一长串测试机型,具体列表如下:点击查看
机型列表部分截图
可以看到,和玩家想象中的不同,在当时的技术测试中,官方公布的机型并不是择优录取,而是覆盖到了几乎所有市面上可以接触到的手机价位。即便是像红米note3这样的国产千元机,依然包含在列。而笔者本次入坑《绝地求生 全军出击》使用的测试机正是一款价格非常平民的安卓“千元机”。令人欣慰的是,“千元机”并没有影响到笔者的试玩体验。
光影效果
捏脸
从笔者的实机截图中可以窥得,《绝地求生 全军出击》的画面表现力非常接近原版“吃鸡”。在春节试炼版中,游戏首先增加了捏脸功能,玩家的五官样貌、肤色与脸部涂装都可以自由搭配。《绝地求生 全军出击》的人物风格更为真实,偏向欧美化。这一点与原作契合度很高。
细分模式
《绝地求生》的成功与新颖的游戏模式密不可分。从游戏设计上看,该类游戏步骤清晰、随机性强。在找点,收集,行走,再收集的常规路径中,插入随时随地就会展开的的遭遇战环节。但《绝地求生》并未创立一种新逻辑,倒不如说是将 射击 、 生存 、战利品收集、动作等诸多系统有机地统一起来。
换句话说,上述这些内容都可以单独深挖。《绝地求生 全军出击》就把经典玩法进一步细分成了狙击精英、冷兵器战斗、绝地训练与神装训练四个部分。有趣的是,它们都是两两对应的极端玩法:狙击精英可供玩家搜刮的都是,冷兵器战斗则是和近战兵器;绝地训练玩的就是跑图能力,神装训练考验的则是同等装备下玩家的真正实力。
这次更新,你可以将其看作是“全军出击”对自身体量的一次合理扩充,毕竟这些玩法其实就像MOD、水友版本一样,满足了差异化玩家的需求。
玩得就是对狙
优化
对游戏的优化与维护是一份持续的工作。有时是向上述内容一样,通过增添游戏玩法,让游戏内容不再单一。有时则是减少游戏中出现的程序性问题、带给玩家更舒畅的游戏体验。
根据官方目前公布的信息,游戏在运动(攀爬、翻越)方面规范碰撞体积,增加攀爬场景,在射击层面加强机瞄与打击感,对场景比如房屋、天气等方面做了极为丰富的优化。
OB与演出
《绝地求生 全军出击》在帧数上的表现同样令人满意。从 跳伞 、开门、舔包,再到跨越、开镜、射击等复杂动作,游戏丝毫没有卡顿的迹象。而当笔者和其他玩家在拐角处撞了一个“惊喜”,极短的时间内,拉准星、调整站姿、开枪射击等一系列连贯性操作十分顺滑。因此,《绝地求 生全军出击》这类游戏在直播、比赛领域同样具备观赏性。
春节试炼版在社交系统里就额外增加了OB主播的选项,我想,和时下流行的抖音、快手类似,意见领袖的存在往往能将玩家中的部分群体集中起来,更容易搭建社区。
维持高水准的前提下,兼具其他“吃鸡”游戏不存在的杰出优化。对于热爱“吃鸡”的玩家来说,《绝地求生 全军出击》的出现便已经是一个利好消息。即使在寒冷的天气里,玩家依然可以窝在被窝里“吃鸡”。除此之外《绝地 求生全军出击》对不等价位机型的全适配,则同样是天美一直以来向下垂直渗透的思路体现。“用心创造快乐”,《绝地求生 全军出击》正是这样一款创造快乐、持续改变适应玩家需求的产品,而非一味追求自我陶醉的奢侈品。
iphoneX耗电快什么原因
iPhoneX是苹果第一次使用了OLED屏,这个屏幕的优缺点都很明显,优点是屏幕很薄,显示效果更出色、非常省电,而缺点是烧屏等。
苹果还在iPhoneX上首次纳入了L形双电池设计,电池容量为2716mAh,这个电池容量对于苹果来说已经不小了。
至于iPhoneX的续航情况,从众多实际测试情况看,没有什么太大的惊喜,一天一充是必然,不过如果苹果想要改善它的续航,那么也是轻而易举的,这不不少用户已经开始在官方论坛恳求苹果这么做了。
事情是这样的,有外媒测试了iPhoneX省电诀窍,屏幕背景用真正的黑色壁纸、打开智能反转颜色和灰度功能,这样一套下来三个小时手机最多可节省近60%的电量,表现很凶残,但这只是应急的。
如果苹果为iPhone X加入夜间模式,那么手机的续航将会更大幅度的提升,不过他们迟迟没有行动,不过最新的消息显示,为了让iPhone X续航表现有明显提升,他们已经在着手实现这样的工作。
在智能手机的零部件中,屏幕是消耗电能最多的。iPhone X屏幕分辨率是2436 X 1125像素,这意味着,它的像素数量比iPhone 8 Plus全屏幕多出来约32%。
更多的像素意味着更高的能耗。能耗的增加不仅仅来自屏幕本身——需要驱动的像素越多,意味着需要的能耗也越多——更高的分辨率,意味着iPhone X必须更“努力地工作”,才能驱动分辨率更高的屏幕。对于显示电路和嵌入在A11仿生芯片中的图形处理单元来说,这意味着更大的工作量。
图形处理单元工作量更大,意味着能耗将会上升,从而对电池续航时间产生负面影响。
显示的内容也会影响电池续航时间
对于iPhone 8和8 Plus配置的LCD屏幕而言,能耗与显示的内容类型无关;对于iPhone X配置的OLED屏幕而言,就不是这么回事了。
这是因为,在OLED屏幕中,每个像素自行发光。如果显示的内容大部分都是黑色的,能耗会相当低,因为会有大量像素被关闭;但如果显示内容主要是白色,能耗就会高得多,因为白色要求红、绿和蓝子像素全部点亮。
在苹果iOS用户界面中,浅色——尤其是白色居多。打开iPhone上的Apple Music、Mail和Messages应用就会发现,应用界面中白色居多。
由于苹果没有重新设计iPhone X用户界面,使之更多地显示为较深的颜色,iPhone X屏幕将被迫经常渲染高能耗的内容,从而增加能耗,缩短电池续航时间。
求高中作文六篇。急!急!急!
1 布拉格的第一场雪
城里的法师告诉穆,只要穆能让布拉格下一场雪,他的父母就会回到他身边。
布拉格,一座空虚的城市,成天飘着纤细的雨,却从不下雪;一座忧郁的城市。穆的法力只能让他周围三平方米飘雪,而布拉格需要几百万个穆才能降雪……
然而,穆的父母在一年前的战争中双双丧身。穆知道,可是那位法师不道……
穆只有一条路好走找到布鲁塞尔的魔法师布尔,然后……打败这个相当于几百万个他的法师……
穆并没有绝望,他背上他的剑开始了一条死亡之路……
当他的剑上沾满了几百个生命的鲜血的时候,他也就到了恶魔宫布尔的家。他拖着剑走了进去,过道的旁边胡乱地堆了些骷髅架子。当他正在吃惊中时,他的面前出现了他的爸爸那位慈祥的父亲用一种别样的眼睛看着他的儿子。穆慢慢地走了过去,越走越近……在刚要与他父亲的手指接触的一刹那,他停住了他的手,他发现了父亲眼中异样的光芒,是一种诡异的绿色。然后,他举起了他的剑,毫不犹豫地刺进了他“父亲“的咽喉。他“父亲“的脸痛苦地扭曲成了一张红色的恶魔铁脸布尔。突然,穆发现那位恶魔布尔已经倒在了他的面前,绿色的眼睛正吃惊地睁着。也就是在这时候,穆感觉自己的身体充满了能量……
穆耗尽了他所有法力来凝固飘飞的雨水,在合眼的刹那他看见了漫天的雪花,犹如精灵一般飞来飞去。
在这个下雪的城市里,躺着一个男孩,他的嘴角还留着稀疏的微笑,眼角挂着晶莹的泪珠,这泪已凝固成坚固的冰晶。
住在孤儿院里的华猛地睁开了眼睛,他发现今天是雪天。
2风中有朵雨做的云
风中有多雨做的云;
我长大了,真的长大了。在父母的唠叨中,在老师的灌输中,在同学的叹息中,在朋友的微笑中,我长大了。抛弃了久经逝去的幼稚、夹杂着青春的欢乐、烦恼,带着心里那朵雨做的晕,我踏上了成长的火车。
我坐在靠窗的地方,以便可以看到外边的风景,外边的时间很精彩,我很想跳下火车,背起不再有烦恼的包袱,去寻找清静免除尘世喧嚣的地方。可我不能,抬头望着车外,天上飘着一朵云……
火车要抵达第一站了,司机让我们下了车,车站上挂着粉色做底、蓝色镶边的几个字――“亲情父母园”。到站了,要找到自己的父母,然后和他们聊聊天,谈谈心,才能离开。我不想去找父母的,正感觉肚子饿了,想去要个面包加小瓶可乐。一摸口袋,钱不够。无奈正要离开,却眼睛一亮,发现了“免费就餐”几个字,就去找waiter。Waiter说只有父母的陪同才能就餐。望了望周围果然是父母陪同孩子们在吃饭的,他们有说有笑,我好不羡慕,心里不免有些失落,突然又看见天上飘着一朵雨做的云。找到父母后,把他们带到就餐的地方,自己美美的享受了一顿“免费的午餐”,却发现父母眼中有种晶莹的东西,我吃了一惊。“难道我们真的没有什么可说吗?”父亲开口了。“不……不是的。”我忙说,“我没有不和你说话啊!”我已经习惯了不和父母交流,也许是代沟太厉害了吧,母亲正和蔼地看着我:“先吃,吃完再说。慢慢吃。”我突然心里难过起来,我做错了吗?“我……”我喊了一声“妈――”卧铺到了她怀里。车长在吹喇叭了,我要上车了,火车又要向前开了。
大约过了5个小时,火车又停了下来,从窗玻璃往外望――咦,好朋友怎么都在?哼,那次惹我的那个阿薇,怎么也在?他在等谁?不理他!车长从喇叭里喊道:“青春友谊区到了,请旅客们下车,20分钟后回来。”我从玻璃窗朝阿茹挥手,她示意我下来,很神秘的冲我一笑。呵呵,我真喜欢青春友谊区啊,处处都显示着青春的活力,可爱极了。阿茹说:“想死你了。”“我也是啊!”我说。“看,那是谁?”我朝着她指的地方望去:“哎,不就是阿薇吗?她还――”我刚说完,想起和她闹别扭的那一天,气不打一处来。“嗨!”她朝我打招呼。“嗨什么嗨?”我自言自语地说。阿如“噗嗤”一声笑了:“她知道错了,还让我转交给你一封信呢。”“信?”“……真对不起你,那天是我不好……”看着看着,我跑过去,拍了阿薇一下,“还是好姐妹。”“嗯!”……火车又要走了,怎么不多停一会儿呢?呵,天上那朵云怎么笑了?
下一站是什么?让我看一下日程表。呀!是“浓浓师生占”!哪个老师会来呢?小学的班主任李老师?现在的刘老师?还是阿兵老师?邱老师?……都想不出来。我们都是怕老师的,全火车的同学都在说:“车长,可不可以不停站?”“不可以。”“可不可以不下车?”“不可以!”哎……都太无奈了。“可不可以不去找老师?”“那你们上车干什么?”是啊,我们上车干什么?难道你不让我们成长?明明是成长列车嘛,想着想着,“浓浓师生占”到了,我们慢悠悠的下了车,都不敢和老师说话。刘老师来了:“快!快过来!”我过去了,没看见其他老师。“他们呀,都太忙了,批作业、出试卷、讲课、写教案、帮助后进生。”“噢。”我应了一声。“好好学习,别老师想着玩,我只请了10分钟的,你先去休息一下,我先走了。”“噢,老师再见!”他们都太忙了,只能和那朵雨做的云说话了。
天快黑了,坐在火车上,黄昏的余辉射进窗来,好像让我和什么告别似的?和什么呢?是烦恼?是忧愁?还是那风中那多雨做的云?
风中有多雨做的云/一朵雨做的云/云在风里伤透了心/不知又将吹向哪儿去
3 春 潮
转眼,春就这么赤裸地站在我面前,我们默默无语。融化的天空下起了绵绵不绝的雨,潮湿,但温和,宛若一个快乐的孩子,倔强地排斥她不想要的,却又真的快乐的像个孩子。冬日,我用得泛滥的一个词就是冻结,而这个春天,果真冻结了我冬日的一切,比如冥想,比如放荡,比如流浪。说到流浪,我确是一直在写流浪,想流浪,念叨着流浪,可我却不知什么才是真正意义上的流浪。我想我是思想上的放逐者,风起,我语,风离,我归。犹如不死的亡灵。思想外的我,只穿黑色或白色,把头压得很低,极快速地穿行于这座我再熟悉不过的小城之中,眼下有的是纷繁下坠却终归禁锢的一潭潭积水以及潭中细软的淤泥,那都是些看似单薄却无底的深沉。很久很久,我都没有嗅到来自于俯仰之间的味道了,于是,也就很久很久的忘却了天蓝如洗,还有我曾经爱到完美又美到破碎的深兰色苍穹。我终于不知所措地开始回忆了。其实,每个人的回忆都会夹杂些许痛楚,可我们却偏爱于回忆,也许只是为了那隐忍不退的丝丝痛楚。我是这样想着,却又惦记起远在江南的哥了,他是个依赖黑夜的人,不知他会不会在闲暇之余抬头望一眼唯一可以与我共享的夜。哥说他讨厌雨,艳羡北方的雪。我说我喜欢雪,因为雪去雨来。他笑一笑,什么也没有说,只是轻轻点点头,又继续埋头苦读,我理解,他在考研。许是春潮作怪,又乱语了这许多许多,在这些本该春深似海的日子里,就本该有许多许多一无所知的梦,抑或思想。而我,不想称自己为孩子却总是这样定位自己,面对我一切该面对的,快乐,以及难过,都简单的像个小孩子。
4 迷雾森林?钻石
真正的音乐,不需要华美的外表,不需要精致的包装,也不需要大红大紫的歌手来演绎。只要有一颗善于聆听,发现的心,便也够了。而BANDARI无疑是最完美的!
——题记
天是那样黑,月亮也被照上了一层薄纱。在失去皎洁月光照射的森林,我孤独地走着,乱冲乱撞,寻着出路。
看,天边开始泛白,太阳出来了。点,线,面,出来了,全都探出了头,柔和的阳光静静地,轻轻地洒落,落下。照到树叶,照到露珠,也照到了我,仓庚开始歌唱,用清脆的歌喉,唤醒这沉睡的森林,也唤醒了我的希望。
清晨的空气中有一股泥土的味道,有点香,有点爽。露水凝在草叶上,花苞上。不时,掉下几滴,摔在地上,碎了,蒸融掉了,一切又恢复到了静谧。顺着,林间的空路,摸索着走着,慢慢地,静静地,不忍破坏这清晨的宁静。四周的树,是那样的高大,他们放弃了优美的虬枝,为了夺取更多了阳光,他们挣者,抢着。年轻的树干上缠着几根已近枯萎的藤,他们却也用这弥留之际,来享受最后的恬静,我不忍打扰便悄悄走了。
路已到头,面前却挡着一座大山,巍峨,却不乏细腻。耸入云中,化在雾里。不时路过的几只飞鸟,更显得这山,高大危耸,这山仿佛透着点灵气。也许,自然中的一切都如此,只不过我从未如此近的聆听自然罢了。
虽然,对这山,这木,这光,这晨,这景不舍留恋。但我仍然在找寻出路,不是我爱自然,只是城市的生活让我失去了在自然中生存的技巧,或者我根本没有勇气独自生活。不过我真得感谢这求生的欲望。在山根搜寻,搜寻出路,却无意间发现了一个山洞,深邃,幽暗。踏进的一刹,整个世界变得黑暗,我却着迷般走着,不知多久,狭长湫隘的山洞,变得宽广,旷达。石笋,钟乳石,被莫名的光线照得,显出异样却美丽的色泽在二侧岩壁上突出,辉映。前面似乎有间大殿似的凹洞,从中闪出昏弱却纯洁的光。
钻石!一颗璀璨的钻石,纯洁无暇,晶莹剔透。我不禁伸出手,去抚摩那人世间的瑰宝,就在指间触到的刹那。一个轻盈婀娜的女子出现在我面前,手指轻轻一点我的额头,我便失去了知觉……
后记:曾经我很喜欢流行音乐,很喜欢嘈杂的迪士高。但是自从我听到了BANDARI之后,我就迷上了这了生活在森林中的乐队,以及他们的音乐。也许任何文字对于音乐都是多余的,但是我只是要记录下我曾经的感动!
5 钻石坐位
主人公:W(主角),X(W的同桌,右,女生),G(W的同桌,左,男生),L(W的后桌),C(L的同桌,X的后桌)环境:不管怎么说都――热地点:那间散发着汗臭的教室,里面只有四个吊扇(更热),53张卓椅。长N米宽的某某班教室。剧情介绍:W不满班主任分配的位置,班主任把W调到了全班同学公认的最佳位置上。那里左边是专门搞笑装酷的第七名G,右边是全班第三的X兼班花,后面则是我办第一,尽职尽责的“老板”L,老板旁边是“蒜哥”数学科代表C。在这种情况之下成绩不太好的W怎么混呢?场景设计:镜头缓缓掠过教室大门,来到中间的那大组的第三,第四。其中在中间一桌椅空空如也,后面“老板”叠的书高出他一头,蒜哥正和班花“打”得热闹,G只有看着他们留口水了。(插放电脑特技:W的帅样,X的美样,G的痴样,L的呆样,C的憨样)第一场:出来乍到(W拿着足球,正在寻找自己的座位)W:(东张西望)oh!我该坐哪儿?can;you;help;me?(旁边的人示意第三中间的那个位子)W:(仰天长啸)什么?!my;god!X:干嘛!进去!(说完站起来,让W进)W:(把球慢慢的放进桌子底下,望望旁边的二位)你们二位干嘛!老盯着我看啊!(一麻头发)我有那么帅吗?G:我是在看你来了我的蟑螂小黑就死了1X:我是在看你包包里头有没有钱!W:你们L:别吵没看见我和蒜哥在比做奥数题吗?G(对L)继续。X:(摇摇手指,对着W说)就你!?还以为远看周润发,近看刘德华,左看周杰伦,右看郭富成。C:我是帅得想自杀,你是丑得想自杀。W:你们!(对X)小小年纪就染头发,卖国求荣啊,汪金魏!(X正待开话)你在说,你这小矮子,侏……(刷!)W:泼妇!记住妇啊!X:你!(一脚)啊!一声回荡在教室……L:别闹!W(愤愤不平的往凳子上一坐)Ouch^^^^^……从此以后W明白了一个真理――人所力量大第二场:侏罗纪公园;(至“出来乍到”以后W深感一人势单力薄,于此他与G连袂出手)G(对X)看过侏罗纪公园吗?X(看都不看他一眼,走了)W:我原来没看过,不过……(眼睛向墙角一斜)G:我也看到了,呵呵C:看什么?(W.X一脚把他揣开,别打望)W:那儿有(为了显示一下自己的渊博,扳着手指开始数)梁龙,三角龙,剑龙,霸王龙……G:对啊!那里是以X为首的霸王龙组成的恐龙队占领了侏罗纪公园。(殊不知X等恐龙以悄然走进)X:你们……G:(微笑着对X等恐龙)有本事你咬啊!X:吃我豆腐!恐……姐妹们,冲啊!G:兄弟们!(做出一副义薄云天状)……逃啊!X:我……(一阵灰尘扬起,朦胧看见一支手在摇……)
6 笑论“风云”――Mr Wu,Ms Sha and Ms Do
No。1――“吴哥”MrWu
;;;;三位“武林高手”中,数吴哥年长,以柔克刚。小个子,中等身材,五官整齐地凑在那圆圆的脸上。他不用暗器(事实上没有),是个相当好的优点。不仅如此,他还信佛,讲究:“救人一命胜造七级浮屠。”顶多就是呦嗬两声,什么掌法什么腿法,他从来不用。他的绝招是――“化力气为浆糊,”用叽叽咕咕的咒语烦死你!
No。2――“沙姐”MsSha
;;;沙姐是位女中豪杰,有任盈盈的霸气,有黄蓉的聪明,只欠缺小龙女的温柔了!(哎,可悲啊!)长长的秀发配上般的体型,再加上“尺规利器”,整个儿一“玉女掌门人”。她的绝招是――“化问号为省略号”,用密密麻麻的符号累死你!
No。3――“董大妹子”MsDong
董大妹子和沙姐不相上下,但沙姐的江湖经验要比她略胜一筹。董大妹子为人和善,不轻易动武,发型最酷,才识和紫薇并驾齐驱,饱读诗书,擅用兵器就是一支笔。她可以“一笔”让天下英雄尽折腰。这一点是无人能及的。她的绝招是――“化无为有,化有为无”可谓刚柔并济,虚实结合,也吸收了吴哥和沙姐的精华贯穿其中,使用自如。用模模糊糊的文字晕死你!
如今,他们三个联手,决定平整江湖。哎!……
谁料,几年后,江湖中又出现了许多风云人物……
7 一片蔚蓝
一片蔚蓝生活中,似乎每一件事我们都会毫不自觉的问一声Why!但这问题真正的答案往往与我们想的毫不相干!――题记1我的脚刚跨入教室,立即就引起了一阵骚动,顺着同学的示意,我抬起了头:“0757,下课后请到语文办公室――Ms?Z”小黑板角落的这行小字映入我的眼帘。“0757?”我十分纳闷,嘴角喃喃的蠕动,反复念叨着这个看似平常的数字。哦!这,这不是我的班序号吗?“0757?我是特务还是间谍?我的名字怎么变成了阿拉伯数字代号了?这是我吗?――一来我做事小心谨慎、“奉公守法”;二来我虽和Ms?Z没有多少交情、也从无过节发生过什么不愉快的事呀!怎么说“请”进办室就“请”进办公室呢?我猜想着,脑海一片混乱……2Ms?Z是我0757和0757所有同班同学的语文老师、班主任。3上课的铃声虽然让我的身体安静下来,心潮却涛声依旧。4铃声响起,宣布了一节化学课的开始。但我既没有陶醉于化学爆炸实验的惊心动魄,更没有心情去欣赏老师声情并茂、手舞足蹈的讲解。我的心中只装有一个大大的问号,为什么?为什么?5我的脑海中不时闪过一张张画面,搜索着这为什么的答案。难道——我的心顿时咯噔一下,把记忆锁在了昨天的一节语文课上:Ms?Z穿着一套黑色的套装和一双高跟鞋。鞋底很高,约摸有七八公分。一头乌黑的微微卷曲的长发披在肩上,脸上抹了一点淡妆,粉底铺得很少,似乎还依稀可见时间和辛劳给她额角
镶嵌的一丝皱纹。虽然,时间和辛劳在额角的刻痕依稀可见。老师还是显得美丽迷人。流露着一位女性‘灵魂工程师’特有的气质。我一激动竟发出了“Howbeautiful!”的赞叹。老师对我微微一笑,迈着猫步款款地走向讲台。高根鞋踩在教室大理石地板上发出一阵清脆的“哒哒……”声。这时教室里极静,“哒哒……”的响声在教室里面回荡,显得异常响亮。我用手拐了拐同桌:“听!‘我哒哒的马啼是美丽的错误……’”我脱口蹦出了郑愁予的《美丽的错误》。同桌会意,贼贼的笑了。我声音虽然压得很低,可还是被Ms?Z听到。她瞥了我一眼,竟坐在了讲台上的凳子上。Ms?Z上课从不坐着。因为,她曾经说过如果老师坐着上课,那是对学生的不尊重。同时,她也强调:希望师生之间要互相尊重。这次她为什么一反常态?我当时不敢想,也没有机会让我多想,因为接下来她坐着上了整整一节课,――难道这一切都是因为我?课后,老师没有说什么?只是静静的离开了教室,这异常的平静,让我更加觉得恐惧,似乎一场风暴就开始了酝酿。5风暴?!我悄悄的抬头又看了看小黑板上的那排小字。“0757”显得特别刺眼。Ms?Z曾经说过:表扬要公平,批评要回避。难道?之所以不用我的名字而用班序号数字代替这也是回避?想到这里我的心猛然一惊。当然这一惊主要是因为心里的畏惧,另外嘛,还有一点小原因:下课铃声响了。6面对将要发生的一切,成了我此时的惟一选择。
8 我的成长故事
一、我出生了
当我被抱出产房时,爸爸妈妈喜极而泣,一滴滴眼泪在我心里留下了深深的烙印。爸爸妈妈总是细心地照料我,使我一次次被感动得大哭小叫。
二、我要读书
在父母的熏陶下,年仅5岁的我越来越强烈地想要读书,每天看见比我大的哥哥姐姐们背着书包来来往往,我总是不由自主地想象着自己读书时的情景。于是,我一次次地请求爸爸妈妈让我上幼儿园读书,可爸爸妈妈总说我现在年纪还小,等我6岁时再去。我心里明白得很:家里离幼儿园很远,而平时爸爸妈妈还要工作,没空接送我,让我这个才5岁的孩子一个人走到学校,父母是怎么也不会允许的。但我还是不肯放弃想读书的念头。爸爸妈妈见我这么喜欢学习,笑容像花儿那样美丽,还时不时地刁难我:“读书可是很累的!”“我不怕累”我坚定地回答。“读书非常苦!”“我也不怕。”“读书是很枯燥的!”“不,不是枯燥,而是快乐!”“到时候你可别后悔呀!”“我决不后悔。”我感到胜利的女神正在向我微笑,因为我看出爸爸妈妈已知道我是真心想读书的,而不是随便说说,和他们开玩笑。终于,爸爸妈妈同意我去上学了。那时,我竟大呼:“读书万岁!”
三、勇敢的我
在我报名的时候,那位慈祥的阿姨看到我感到很惊讶,其实她不说我也猜的出,就是因为我年龄小嘛。第二天,我是由姑父骑车送我的,当时,我高兴极了,嘴里还哼着小曲儿。当我走进自己班级的时候,看见许许多多以前从未见过的小朋友,有的小朋友又哭又闹,可想而知,他们并不爱上学,是父母逼的,和我正好成为对比。在这里生活很轻松,很愉快,而且还能交到许多知心朋友。起初,是由我姑父骑车接送我,可后来他也没空,老师知道后,就开始每天接送我,这让我感到很不好意思。于是从那时侯起我就尝试着每天早早就起床,无论刮风下雨,都是一个人步行上学。有时老师偶然遇见我,总是和蔼地说:“我来送你回家吧!”可我不愿意,她也没有要勉强的意思,我继续一个人孤独的走着。直到有一天,我认识了一位新朋友,她也读幼儿园,而且离我家很近,所以我常与她一起步行去上学。就这样,我们一起走过了两年的风风雨雨。
四、难以捉摸的我
自从我上了小学后,脾气就变得异常古怪,时晴时阴,有时还会来场“大暴雨”。就算是世界上最准确的天气预报台也无法预料。就比如和爸爸妈妈在一起的时候,有时我会调皮地和他们玩耍、打闹;有时我又会变成个乖乖女,他们叫我做什么,我就做什么;有时,我在对某件事的看法与他们不同,他们欺负我人小,不懂事,总说我是错误的,我一气之下,好几次都在夜间离家出走……在学校里,我与我的同桌天天吵、天天闹,可谓“水火不容”,老师咋就把我和他分到了一张课桌上。每到这时,只要有好朋友来找我玩,我马上就会由阴变成晴,和往常一样嘻嘻哈哈的,丝毫看不出有什么不快。“大暴雨”不常下,只偶尔下两场而已。轻则只折断几支笔,重则也不过是撕本子、砸东西。有时回想起来也觉得不可思议,我是怎么啦,是不是中邪了?
LZ这是8篇高中作文 要是不满意的话可以去://.zuowen/gaozhong/上自己找找
Delphi深度探索之PItemIDList的基本概念
PIDL的秘密
从Windows 开始 微软公司为操作系统引入了新的外壳界面 新的外壳从根本上改变了应用程序同操作系统的结合方式 遗憾的是微软公司对于发布同外壳相关的编程信息方面显得很吝啬 可以得到的资料非常少 而且质量也不高 对于Delphi开发者来说 情况就更为严重了 因为几乎所有的Windows API 文档都是针对C/C++程序员的 但是Nothing is impossible 在本文中 我们将开始外壳编程的历险 就让我们从PIDL开始吧
外壳命名空间
新外壳系统中的一个核心概念就是命名空间(namespace) 对于DOS来说 命名空间可以理解为就是整个文件系统 它有着树一样的继承关系 它的树根被称为 根目录
对于Windows x和NT来说 命名空间仍然是树状继承关系的 但它不再一一对应于文件系统了 文件系统变成了一个大的命名空间的一部分 新的命名空间发展了原有的文件夹和文件概念 新的文件夹仍然类似于旧的DOS目录 包含其他的命名空间元素 比如文件夹和外壳对象 而新的外壳对象同旧的DOS文件不同之处在于 所有的系统目录都是文件夹 但并不是所有的文件夹都是目录 所有的文件都是外壳对象 但不是所有的外壳对象都是文件
新的命名空间的树根就是桌面文件夹 这从管理器左边的树视图中就能看到 桌面下包括我的电脑文件夹 其中包括了旧的DOS命名空间 磁盘驱动器 桌面和我的电脑明显不是文件系统的一部分 同样的特殊的文件夹 比如控制面板 打印机 回收站和网络邻居等等都不是原来意义上的文件系统了
但不管外壳的概念如何变化 它必须是可唯一标识的 每个外壳中的文件夹和对象必须有一个唯一的 名字 名字 有两种类型 相对和绝对的 名字 相对 名字 是指相对一个给定的父对象 它是唯一的 比如我叫张三 我哥哥叫张大和张二 那么对于我的父亲来说 我的名字就可以唯一地确定我的身份了 但如何从全国所有名叫张三的同胞中找出我来呢 这就需要绝对的名字了 这时就应该用中国北京某胡同的张大胡子的儿子张三来唯一地确定我了 对于外壳对象来说 相对于根节点的路径就可以用来唯一确定它的绝对 名字
对于老的DOS文件系统 每个文件都有一个唯一确定的路径名 这个路径名就相当于它的绝对名字 它的格式通常就是C:\windows\system\…\ 文件名 而单独的 样式的文件名字则是相对名
对于新的Windows x系统 这种DOS方式的路径名已经不够用了 它无法描述控制面板这类外壳对象的名字 为此微软公司给出了两个新的数据结构 每个元素的相对名字用一个TShItemID记录来标识 当需要时我们可以合并这些记录 从概念上类似于用 \ 连接DOS路径名 而一连串的这些记录就是项目标识符列表(IDL Item Identifier List) 在Delphi中使用TItemIDList来标识它 因为IDL主要是通过指针来进行操作的 因此通常主要使用的是它的指针形式PIDL 在Delphi中定义为PItemIDList PIDL就是在外壳命名空间确定唯一一个元素的通用方法 所有这些Delphi数据结构都定义在ShlObj单元中
同DOS 样式的字符串类型的路径不同的是 PIDL是二进制类型的数据 同时TShItemID 和 TItemIDList 是变长的数据类型 其中TShItemID的定义如下
TShItemID = packed recordcb: Word; // 记录的大小 abID: array[ ] of Byte; // 外壳对象 ID数据 end;
第一个记录成员是cb cb 中应该存放整个TShItemID记录的尺寸 而abID 被定义为只有一个元素的字节数组 但这并不意味着数组中只有一个元素 它可以扩展为cb个元素 另外TItemIDList 定义如下
TItemIDList = packed recordmkid: TShItemID;end;
它只是有一个TShItemID类型的数据成员构成 需要注意的是这种定义方法意味着记录并不仅是一个TShItemID成员 而是一个TShItemID结构的列表 一个挨着一个 最后要使用一个cb为 的TshItemID标识列表的结束 下表中给出了一个TItemIDList的示意图 它由 个TShItemID 记录组成 注意cb 总是比abID的字节大 除了列表结束的标志记录的cb 这是因为cb 应该包含cb成员本身的字节大小 而它正好是
cb abID cb abID cb abID cb abID bytes bytes bytes bytes从表中就可以清楚地知道cb的用途了 它可以被用来作为可靠的路标来遍历一个TItemIDList PItemIDList指针指向TItemIDList记录的第一个字节 除非PItemIDList 为nil 否则列表中至少会有一个TShItemID 然后通过cb的值就可以知道列表中下一个TShItemID的起始位置 如果cb为 就表明列表结束了
下面的代码用PItemIDList作为参数 然后遍历整个TItemIDList 并返回整个列表的尺寸 当需要复制列表时 获得的信息可以用来确定复制所需缓冲区大小
function GetPIDLSize(PIDL: PItemIDList): Integer;varCurrentID: PShItemID;begin// 判断PIDL是否为nil if (PIDL <> nil) thenbegin// 对于终止的标志的cb至少为 Result := SizeOf(CurrentID cb);// 初始化item id 指针并遍历列表直到碰到cb = 才终止// 把碰到的每个cb的值添加到结果中 CurrentID := PShItemID(PIDL);while (CurrentID cb <> ) do beginInc(Result CurrentID cb);Inc(PChar(CurrentID) CurrentID cb);endendelse // 如果PIDL为nil返回 Result := ;end;
如同有相对和绝对路径一样 同样也有相对和绝对的PIDL 一个绝对的PIDL是从命名空间的根节点桌面开始算起的 而相对PIDL通常是从其直接父对象算起的
外壳中的文件夹可以通过一个IShellFolder 接口来进行控制 这个接口提供了许多方法 这些方法的参数通常就是相对PIDL 因为接口本身就代表了父文件夹 而以Sh开头的Shell API函数通常则使用绝对PIDL作为参数 因为它们不是类 无法代表类 因此只能使用绝对PIDL 我们在应用中一定要搞清楚两者的区别
PIDL的内存分配
在实际应用中 PIDL经常是在一个模块中被分配 而在另一个模块中被释放 比如外壳API经常会在函数内部分配并返回一个PIDL 这时我们的程序就要负责在使用后进行释放 这意味着内存的分配和释放必须是语言无关的 也就是说可以用C++写PIDL分配模块 而用Delphi写释放模块
但实际上不同的开发语言的内存管理函数是完全不兼容的 如果使用Delphi的FreeMem 过程来释放一些C语言的Malloc函数分配的内存的话 产生的糟糕后果就是会破坏整个堆 为了解决这一问题 操作系统提供了外壳任务分配器(shell task allocator)来统一外壳内存管理 外壳任务分配器是通过IMalloc 接口实现的 IMalloc实现了一个非常完整的内存分配引擎 它定义在ActiveX单元中 获得一个IMalloc接口实例最简单的办法是使用SHGetMalloc API函数 这个函数定义在ShlObj 单元中 这些声明定义如下
IMalloc = interface(IUnknown)[ { C } ]function Alloc(cb: Longint): Pointer; stdcall;function Realloc(pv: Pointer; cb: Longint):Pointer; stdcall;procedure Free(pv: Pointer); stdcall;function GetSize(pv: Pointer): Longint; stdcall;function DidAlloc(pv: Pointer): Integer; stdcall;procedure HeapMinimize; stdcall;end;function SHGetMalloc(var ppMalloc: IMalloc):HResult; stdcall;
下面是一个使用分配引擎的例子
varAllocator: IMalloc;Buffer: Pointer;begin// 获得IMalloc 接口 SHGetMalloc(Allocator); // 分配 个字节的缓冲区 Buffer := Allocator Alloc( );// 扩展缓冲区为 字节 Buffer := Allocator Realloc(Buffer ); //释放缓冲区 Allocator Free(Buffer);end;
如果不需要IMalloc接口提供的全部功能 而只是想分配或释放内存的话 有两个未经公开的函数SHAlloc 和SHFree封装了对IMalloc接口的调用来分配和释放内存 它们在SHELL DLL中的索引分别为 和 当要想释放一个PIDL时 可以使用ILFree 这个未公开的函数 它的索引值为 三个函数的定义如下
function SHAlloc(BufferSize: ULONG): Pointer; stdcall;procedure SHFree(Buffer: Pointer); stdcall;procedure ILFree(Buffer: PItemIDList); stdcall;
路径和PIDL之间的相互转换
如何将文件系统的路径转化为外壳形式的PIDL呢?微软公司的文档中记载的标准方式是先获得桌面的IShellFolder 接口 然后把要转化的路径名转化为PWideChar 类型的以null结尾的UNICODE字符串 然后作为参数调用桌面的IShellFolder接口的ParseDisplayName 方法才能获得PIDL 实际应用起来太复杂 不过不要紧 有三个未公开的函数可以帮助我们简化这一功能的实现
function SHILCreateFromPath(Path: Pointer;PIDL: PItemIDList; var Attributes: ULONG):HResult; stdcall;function ILCreateFromPath(Path: Pointer):PItemIDList; stdcall;function SHSimpleIDListFromPath(Path: Pointer):PItemIDList; stdcall;
SHILCreateFromPath 函数实际上就是对桌面的IShellFolder接口的ParseDisplayName方法进行简单封装 而ILCreateFromPath函数则是对SHILCreateFromPath调用的简单封装 而SHSimpleIDListFromPath函数则实现了整个过程 它们的索引分别是 和
其中SHSimpleIDListFromPath 相对要快一些 因为它并不校验路径参数的有效性 而SHILCreateFromPath 和ILCreateFromPath 在转化前都要校验路径的有效性 如果提供的路径是无效的 就会返回一个nil
由于SHSimpleIDListFromPath 不校验路径 所以可以从任何路径获得一个PIDL而不会引起错误 但是有时这个函数返回的PIDL不完全正确 比如用它产生的PIDL来调用SHBrowseForFolder 函数显示浏览对话框的时候 偶尔结果显示的名字和图标是不正确的
当想从一个绝对PIDL获得一个文件系统路径时 就相对简单多了 有一个公开的函数SHGetPathFromIDList可以实现这一功能 它定义在ShlObj单元中(有AnsiChar和widechar两个版本)
function SHGetPathFromIDList(PIDL: PItemIDList;Path: PAnsiChar): BOOL; stdcall;function SHGetPathFromIDListW(PIDL: PItemIDList;Path: PWideChar): BOOL; stdcall;
注意 path参数对应的指针应该指向一个可以容纳MAX_PATH+ 个字符的缓冲区 以避免越界读写
显示名称
如果想要获得一个PIDL对应的显示名称 文档中介绍的方法是使用IShellFolder接口的GetDisplayNameOf方法来完成 另外使用SHGetFileInfo API函数也能获得显示名 不过有一个未公开的API调用ILGetDisplayName函数使用起来是最方便的 它实际上就是调用桌面的IShellFolder接口的GetDisplayNameOf 方法 同时调用的标志值为SHGDN_FORPARSING ILGetDisplayName 函数的索引值为 不过这个函数不会返回通常的短显示名 而是返回包含了相应路径的长显示名 如果想得到的是短文件名的话 最好使用SHGetFileInfo函数 下面是函数的定义
function ILGetDisplayName(PIDL: PItemIDList;Name: Pointer): LongBool; stdcall; Windows NT和PWideChar
回头看一下已经定义的未公开的函数就会发现通常字符串类型的变量 并没有定义为Pchar而是定义为Pointer 这是因为对于未公开的函数来说 在Windows x上字符串变量都是PAnsiChar类型的 而在NT上都是PWideChar类型的 没有办法像公开的函数那样可以任选ANSI或UNICODE版本的函数 未公开函数在Windows x上只能使用ANSI版本 在Windows NT 上只能使用UNICODE版本的函数 如果想在所有版本的操作系统上都能正常工作 就必须在运行时检查操作系统类型 SysUtils单元中的Win Platform 全局变量可以用来判断操作系统类型 如果程序是运行在Windows NT上的 在调用前就需要把字符串变量转化为PWideChar 类型 当函数返回时 又需要把返回字符串变回PAnsiChar 这种转化比较麻烦 但这就是使用未公开函数调用的代价
如果想确定两个PIDL是否相同 标准方法是使用IShellFolder接口的CompareIDs 方法 相对的PIDLs 可以用他们父文件夹的IShellFolder接口 而绝对PIDLs的比较必须使用桌面的IShellFolder接口 同样的 系统也提供了未公开的快捷方法 要想确定两个PIDL是否相等 可以使用ILIsEqual 函数 如果想确定一个PIDL是否是另一个PIDL的子对象 可以使用ILIsParent 函数 如果希望判断子对象是否是父对象的最直接的子对象的话 需要设定函数的ImmediateParent 参数为True 下面的就是函数的定义
function ILIsEqual(PIDL : PItemIDList; PIDL : PItemIDList):LongBool; stdcall;function ILIsParent(PIDL : PItemIDList;PIDL : PItemIDList; ImmediateParent: LongBool):LongBool; stdcall;
这两个函数的索引值分别为 和 要注意的是通过二进制的比较是无法判断两个PIDL是否相等的 因为相等的PIDL可能会有不同的二进制结构
解析PIDL
有时 我们会想要分解一个PIDL为单独的ID列表 没有公开的函数可以实现这项功能 很显然 微软公司希望程序员自己实现切割PIDL的功能 的是还是有未公开的函数可以简化开发
如果我们想确定PIDL中所有标识符的尺寸 可以使用ILGetSize 函数 如果想遍历PIDL中每一个项目标识符的话 可以使用ILGetNext 函数 当给定一个PIDL后 函数会返回一个指向列表中下一个项目标识符的指针 如果PIDL为nil或已经指向了列表中的最后一项 函数会返回nil 要想返回列表中最后一项item identifier 可以使用未公开的ILFindLastID函数
一个更专业的查找函数是ILFindChild 给定一个父PIDL和一个子PIDL 它将返回一个指向子PIDL独特部分的指针 比如 如果你把目录 C:\DIR 的PIDL作为父PIDL 而把 C:\DIR\FILE TXT 的PIDL作为子PIDL的话 它会返回一个指针指向代表FILE TXT的子PIDL 如果给定的子PIDL不是父PIDL的子对象 函数返回nil 这些函数的索引值分别为 和 函数定义如下
function ILGetSize(PIDL: PItemIDList): UINT; stdcall;kfunction ILGetNext(PIDL: PItemIDList):PItemIDList; stdcall;function ILFindLastID(PIDL: PItemIDList):PItemIDList; stdcall;function ILFindChild(ParentPIDL: PItemIDList;ChildPIDL: PItemIDList): PItemIDList; stdcall;
复制和合并
有时在进行外壳编程的时候需要制作一个PIDL的拷贝 给定一个已有的PIDL ILClone 函数将会分配并返回一个新的PIDL的克隆 而ILCloneFirst 函数可以从源PIDL中生成一个只包含第一个item identifier的PIDL 如果想获得最后一个item identifier的拷贝 组合使用ILFindLastID和ILCloneFirst函数调用就可以了 对于PIDL的其他部分 就需要不断调用ILGetNext和ILCloneFirst函数了 这两个函数定义如下 其索引值为 和
function ILClone(PIDL: PItemIDList): PItemIDList; stdcall;function ILCloneFirst(PIDL: PItemIDList):PItemIDList; stdcall;
如果想合并两个PIDL 则可以使用ILCombine 函数 给定两个PIDL 它会创建一个包含两个源列表的新的PIDL 如果想把一个单独的item identifier同PIDL合并 可能需要使用ILAppendID 函数 它可以把一个TItemID 记录添加到一个已有的PIDL的开头或结尾 然而同ILCombine不同 原来的PIDL在操作后将被销毁 ILAppendID 函数中的PIDL参数甚至可以为nil 这两个函数的索引值分别为 和 函数定义如下
function ILCombine(PIDL : PItemIDList; PIDL : PItemIDList):PItemIDList; stdcall;function ILAppendID(PIDL: PItemIDList; ItemID: PShItemID;AddToEnd: LongBool): PItemIDList; stdcall;
全局内存克隆
前面已经提到了 为PIDL分配内存需要使用外壳内存分配器 系统中有两个未公开的函数提供了不同的分配和释放内存的方法 它们是ILGlobalClone和ILGlobalFree 函数(索引值为 和 ) 函数定义如下
function ILGlobalClone(PIDL: PItemIDList):PItemIDList; stdcall;procedure ILGlobalFree(PIDL: PItemIDList); stdcall;
在Windows NT中 这两个函数使用缺省进程的堆(由GetProcessHeap得到的) 堆的分配在某些方面比外壳分配器效率更高 而外壳在内部使用全局分配函数可以提高效率
在Windows x 上外壳中的绝大多数内部结构都需要在DLL的所有实例 *** 享 同样PIDL使用的内存也应该是可共享的 ILGlobalClone 使用一个可共享的堆来分配PIDL的内存 使得可以从任何地方存取PIDL的指针
删改
如果想删除整个PIDL 只要使用ILFree 函数就可以了 如果想从列表的末尾删除最后一个item identifier 可以使用ILRemoveLastID 函数
function ILRemoveLastID(PIDL: PItemIDList):LongBool; stdcall;
它的索引值为 要注意的是它并不真的释放任何内存 它只是重置了列表的最后位置 它是唯一一个删除相关操作的函数 如果我们想从PIDL的开始删除一个item identifier 就只能使用ILGetNext 和ILClone 来生成一个从原始PIDL的第二个ID开始的拷贝了 然后使用ILFree删除源PIDL 从列表的中间删除一个ID显然更加麻烦了 但的是在实际中几乎不存在这种需要
深入命名空间
现在我们对PIDL已经有了一定程度的了解了 接下来就是研究如何遍历命名空间 桌面是遍历命名空间的根节点 从桌面开始 可以枚举外壳中的所有对象 在开始遍历命名空间前 需要获得桌面对象的IShellFolder接口 下面的代码演示了如何获得桌面接口
varDesktop: IShellFolder;BeginOleCheck(SHGetDesktopFolder(Desktop));
IShellFolder 可以用来枚举外壳中的内容 设定或取得外壳对象的名字 查询它们的属性并通过界面元素进行交互 下面是一个使用IShellFolder 接口的例子
typeTItemListArray = array of PItemIDList; function GetShellItems(Folder: IShellFolder): TItemListArray;ConstSHCONTF_ALL=SHCONTF_FOLDERSorSHCONTF_NONFOLDERSorSHCONTF_INCLUDEHIDDEN;VarEnumList: IEnumIDList;NewItem: PItemIDList;Dummy: Cardinal;I: Integer;BeginResult := nil;I := ;if Folder EnumObjects( SHCONTF_ALL EnumList) = S_OK thenwhile EnumList Next( NewItem Dummy) = S_OK dobeginInc(I);SetLength(Result I);Result[I ] := NewItem;end;end;
GetShellFolders 函数返回一组相对于父文件夹的PIDL列表 通过EnumObjects方法可以获得PIDL枚举接口 不过最终要负责释放全部结果中的项目
function GetShellObjectName(Folder: IShellFolder;ItemList: PItemIDList): string;VarStrRet: TStrRet;BeginFolder GetDisplayNameOf(ItemList SHGDN_INFOLDER StrRet);case StrRet uType of STRRET_WSTR:BeginResult := WideCharToString(StrRet pOleStr);CoTaskMemFree(StrRet pOleStr);end;STRRET_OFFSET: Result := PChar(Cardinal(ItemList) + StrRet uOffset);STRRET_CSTR: Result := StrRet cStr;end;end;
GetShellObjectName 函数则返回一个相对的PIDL的字符串表达 把这些代码集成起来 就可以编写一个过程来输出指定深度的外壳命名空间的层次关系了
procedure EnumShellNamespace(Strings: TStrings; Depth: Integer;Folder: IShellFolder = nil);procedure AddObjectName(Folder: IShellFolder; ItemList: PItemIDList; Level: Integer);VarS: string;BeginSetLength(S Level * );FillChar(PChar(S)^ Length(S) );Strings Add(S + GetShellObjectName(Folder ItemList));end;procedure EnumItems(Folder: IShellFolder; Level: Integer);varItems: TItemListArray;ItemList: PItemIDList;Flags: Cardinal;SubFolder: IShellFolder;I: Integer;BeginInc(Level);Items := GetShellItems(Folder);Tryfor I := to Length(Items) dobeginItemList := Items[I];AddObjectName(Folder ItemList Level);if Level < Depth thenbeginFlags := GAO_HASSUBFOLDER;OleCheck(Folder GetAttributesOf( ItemList Flags));if Flags and GAO_HASSUBFOLDER = GAO_HASSUBFOLDER thenBeginOleCheck(Folder BindToObject(ItemList nil IID_IShellFolder SubFolder));EnumItems(SubFolder Level);end;end;end;finallyfor I := to Length(Items) doILFree(Items[I]);end;beginStrings BeginUpdate;TryStrings Clear;if Folder = nil thenbeginOleCheck(SHGetDesktopFolder(Folder));AddObjectName(Folder nil );end;if Depth > thenEnumItems(Folder );FinallyStrings EndUpdate;end;end;end
对于Delphi来说 由于其提供了一个非常友好的对象框架 所以这里对IShellFolder的功能进行了封装 实现了一个TShellNode 类 对TShellNode类进行了描述 AbsoluteList 标识节点的绝对PIDL指针Count Items属性中的节点数HasChildren 表示是否有子节点Item 子TShellNode对象Name 节点的显示名称Path 节点对应的系统文件路径Parent 对象的父节点 对桌面来说 这个属性为nilRelativeList 相对PIDL指针ShellFolder 对应于节点的IShellFolder接口Create 创建节点CreateFromList 根据PIDL创建节点CreateFromFolder 由特殊路径创建节点Destroy 析构函数Assign 复制节点信息Clear 释放节点的子对象Initialize 初始化方法
TShellNode被设计成一个基类 可以从它继承更加有用的类来 一些在表 中列出的属性和方法是protected的 需要在继承类中声明为public 衍生类不应该重新定义constructors过程 但可以重载Initialize方法
扩展TShellNode 的类可以添加系统图像列表索引属性 查找能力等等 这完全取决于你的想像力 还有一点是除了桌面外 微软公司还定义了一组CoClasses对象 它们都暴露了IShellFolder 接口 我们也可以从它们出发来遍历命名空间 下面列出这些CoClass的定义和描述 CLSID_NeorkPlaces 网络邻居CLSID_NeorkDomain 网络域CLSID_NeorkServer 网络服务器CLSID_NeorkShare 网络共享CLSID_MyComputer 我的电脑CLSID_Internet 我的网络CLSID_ShellFolder 文件系统的桌面目录CLSID_RecycleBin 回收站CLSID_ControlPanel 控制面板CLSID_Printers 打印机CLSID_MyDocuments 我的文档
举例来说 可以使用下面代码来创建一个简单的打印机选择组合列表框
EnumShellNamespace(ComboBox Items
CreateObject(CLSID_Printers) as IShellFolder); 在例子程序中 我们从TShellNode类又衍生了一个TShellTreeNode 类 添加了图像索引和Strings属性 ImageIndex 属性对应于系统图像列表中的节点的图像索引 Strings 属性则保存着节点的绝对PIDL列表中每一项的显示名称 程序允许我们在绝对和相对PIDL察看模式间切换 下图就是程序中显示的外壳对象树的示意图
例子程序的主要目的是演示如何进行PIDL的操作 在GetItemListStrings过程中 演示了如何使用ILClone ILFindChild ILFree ILGetCount ILIsRoot和ILRemoveLastID等例程
显示属性页
IShellFolder接口不仅提供对外壳内部数据结构的存取 也可以调用界面元素进行交互 例如 使用IShellFolder GetUIObjectOf 方法 可以请求上下文相关菜单 在下面代码中演示了如何操作PIDL来获得IContextMenu 接口 并通过IContextMenu来调用菜单命令 比如显示属性页 调用我的电脑的属性命令显示属性页的示意图下图所示
procedure ShowProperties(Handle: HWND; ItemList: PItemIDList); overload;varDesktop: IShellFolder;Folder: IShellFolder;ParentList: PItemIDList;RelativeList: PItemIDList;ContextMenu: IContextMenu;CommandInfo: TCMInvokeCommandInfo;BeginParentList := ILClone(ItemList);if ParentList <> nil thentryILRemoveLastID(ParentList);OleCheck(SHGetDesktopFolder(Desktop));OleCheck(Desktop BindToObject(ParentList nil IID_IShellFolder Folder));RelativeList := ILFindChild(ParentList ItemList);OleCheck(Folder GetUIObjectOf(Handle RelativeList IID_IContextMenu nil ContextMenu));FillChar(CommandInfo SizeOf(TCMInvokeCommandInfo) # );with CommandInfo dobegincbSize := SizeOf(TCMInvokeCommandInfo);hwnd := Handle;lpVerb := Properties ;nShow := SW_SHOW;end;OleCheck(ContextMenu InvokeCommand(CommandInfo));FinallyILFree(ParentList);end;end;procedure ShowProperties(Handle: HWND; const DisplayName: string); overload;varItemList: PItemIDList;BeginItemList := ILCreateFromPath(PChar(DisplayName));TryShowProperties(Handle ItemList)FinallyILFree(ItemList);end;end;
PIDL的其他用途
IShellFolder并不是使用PIDL的唯一接口 其他像文件快捷方式 外壳扩展等都利用PIDL来扩展或嵌入外壳 Windows还提供了一组公开的使用PIDL的函数 比如调用SHGetSpecialFolderLocation 函数就可以由PIDL获得特色文件夹的相应文件路径 而用SHGetDataFromIDList 函数可以查询文件系统或网络中的PIDL来获得相应属性
结论
lishixinzhi/Article/program/Delphi/201311/24786声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。