《网络吸管》开发手记
2006-02-04 13:44:55 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈囩磽瀹ュ拑韬€殿喖顭烽幃銏ゅ礂鐏忔牗瀚介梺璇查叄濞佳勭珶婵犲伣锝夘敊閸撗咃紲闂佺粯鍔﹂崜娆撳礉閵堝洨纾界€广儱鎷戦煬顒傗偓娈垮枛椤兘骞冮姀銈呯閻忓繑鐗楃€氫粙姊虹拠鏌ュ弰婵炰匠鍕彾濠电姴浼i敐澶樻晩闁告挆鍜冪床闂備胶绮崝锕傚礈濞嗘挸绀夐柕鍫濇川绾剧晫鈧箍鍎遍幏鎴︾叕椤掑倵鍋撳▓鍨灈妞ゎ厾鍏橀獮鍐閵堝懐顦ч柣蹇撶箲閻楁鈧矮绮欏铏规嫚閺屻儱寮板┑鐐板尃閸曨厾褰炬繝鐢靛Т娴硷綁鏁愭径妯绘櫓闂佸憡鎸嗛崪鍐簥闂傚倷鑳剁划顖炲礉閿曞倸绀堟繛鍡樻尭缁€澶愭煏閸繃宸濈痪鍓ф櫕閳ь剙绠嶉崕閬嶅箯閹达妇鍙曟い鎺戝€甸崑鎾斥枔閸喗鐏堝銈庡幘閸忔﹢鐛崘顔碱潊闁靛牆鎳愰ˇ褔鏌h箛鎾剁闁绘顨堥埀顒佺煯缁瑥顫忛搹瑙勫珰闁哄被鍎卞鏉库攽閻愭澘灏冮柛鏇ㄥ幘瑜扮偓绻濋悽闈浶㈠ù纭风秮閺佹劖寰勫Ο缁樻珦闂備礁鎲¢幐鍡涘椽閸愵亜绨ラ梻鍌氬€峰ù鍥敋閺嶎厼鍨傞幖娣妼缁€鍐煥濠靛棙顥滈柣锕備憾濮婂宕掑▎鎺戝帯濡炪們鍨归敃銈夊煝瀹ュ鍗抽柕蹇曞Х椤斿姊洪幖鐐插姶闁告挻鐟╅幃姗€骞庨懞銉у幐闂佸憡鍔戦崝搴㈡櫠閺囩姷纾奸柍褜鍓熷畷姗€鍩炴径鍝ョ泿闂傚⿴鍋勫ú銈吤归悜鍓垮洭鏁冮埀顒勬箒濠电姴锕ら悧蹇涙偩濞差亝鐓涢悘鐐额嚙婵″ジ鏌嶇憴鍕伌鐎规洖宕埢搴ょ疀閹惧妲楃紓鍌氬€搁崐鐑芥⒔瀹ュ绀夐幖杈剧到閸ㄦ繃銇勯弽顐粶濡楀懘姊洪崨濠冨闁搞劍澹嗙划濠氬箮閼恒儱鈧敻鏌ㄥ┑鍡欏嚬缂併劏妫勯湁闁绘ǹ宕甸悾鐑樻叏婵犲啯銇濇俊顐㈠暙閳藉鈻庨幇顓炩偓鐑芥⒑鐠囨彃顒㈤柣顓у櫍瀹曪繝骞庨懞銉ヤ粧濡炪倖娲嶉崑鎾垛偓瑙勬礀閻栧ジ銆佸Δ浣哥窞閻庯綆鍋呴悵顐⑩攽閻樻剚鍟忛柛锝庡灣瀵板﹪宕滆閸嬫挾绮☉妯绘悙缂佺姵鐓¢弻娑㈠Ψ椤旂厧顫╅梺钘夊暟閸犳牠寮婚敐澶婃闁圭ǹ瀛╅崰鎰版⒑閼姐倕鏋庣紓宥咃躬瀵鈽夐埗鈹惧亾閿曞倸绠f繝闈涙川娴滎亝淇婇悙顏勨偓銈夊礈濞嗘挻鍋嬮柛鈩冪▓閳ь剚妫冨畷姗€顢欓崲澹洤绠圭紒顔煎帨閸嬫捇鎳犻鈧崵顒傜磽閸屾艾鈧娆㈤敓鐘茬獥婵°倕鎳庣粻浼存煙闂傚鍔嶉柛瀣ф櫊閺岋綁骞嬮敐鍡╂缂佺虎鍘搁崑鎾绘⒒娴h櫣甯涢柛鏃€娲滅划鏃堟濞磋櫕鐩畷姗€顢欓崗鍏夹氶梻渚€鈧偛鑻晶顖炴煏閸パ冾伃妤犵偞甯¢獮瀣攽閹邦亞纾婚梺璇叉唉椤骞愭搴g焼濞撴埃鍋撻柛鈺冨仱楠炲鏁傞挊澶夋睏闂備礁婀辩划顖滄暜閳哄倸顕遍柍褜鍓涚槐鎾存媴閻熸澘濮㈤悷婊勫閸嬬喖宕氶幒鎴旀瀻闁规儳鐤囬幗鏇炩攽閻愭潙鐏﹂柣顓у枛閳讳粙顢旈崼鐔哄幍闁荤喐鐟ョ€氼剚鎱ㄩ崶銊d簻闁靛濡囩粻鐐存叏婵犲啯銇濋柡灞芥嚇閹瑩鎳犵捄渚純濠电姭鎷冮崒姘ギ闂佸搫鐬奸崰鏍箹瑜版帩鏁冮柨婵嗘噽閿涙捇姊绘担鐟邦嚋缂佽瀚板畷鎴濃槈閵忕姷鍘撮梺鐟邦嚟婵參宕戦幘缁樻櫜閹煎瓨锚娴滅偓銇勯幘瀵糕姇婵炲懎锕弻锛勪沪閻e睗锝嗙箾绾板彉閭鐐茬箳娴狅箓鎸婃径濠呭帿闂傚倸鍊烽悞锕傛儑瑜版帒纾归柡鍥ュ灩缁犵娀鏌熼柇锕€鏋熸い顐f礋閺岀喖骞嗚閹界姴鈹戦娑欏唉闁哄本鐩獮姗€寮堕幋鐘点偡闂備礁鎲¢幐绋跨暦椤掑嫧鈧棃宕橀鍢壯囨煕閳╁喚娈樺ù鐘虫倐濮婃椽鎳¢妶鍛瘣闂佸搫鎳忛惄顖炲箖妤e啯鍊婚柦妯猴級閵娧勫枑濠㈣埖鍔曠壕濠氭煙閸撗呭笡闁哄懏鐓¢獮鏍垝閻熸澘鈷夐梺璇茬箰缁夌懓顫忛搹鍦<婵☆垵顕ч棄宥呪攽閻愭彃绾ч柨鏇樺灪娣囧﹪鎮界粙璺槹濡炪倖鐗楀銊╂偪閳ь剟姊婚崒姘偓鎼佹偋婵犲嫮鐭欓柟閭﹀枦婵娊鏌ゅù瀣珖缁炬崘妫勯湁闁挎繂鐗婇ˉ澶愭煟閹炬潙濮堥柟渚垮妼铻g紒瀣仢椤鈹戦垾鍐茬骇闁告梹鐟╅悰顔嘉熼崗鐓庣彴闂佽偐鈷堥崜锕€危娴煎瓨鈷掑ù锝嚽归弳閬嶆煙绾板崬浜扮€规洘鍔栫换婵喰掔粙鎸庡枠鐎殿喛鍩栭幆鏃堝箻鐎涙ɑ婢戝┑锛勫亼閸婃牕顫忔繝姘ラ悗锝庝憾閸熷懘鏌曟径娑滅濞存粍绮嶉妵鍕箻鐠鸿桨绮跺┑鈩冨絻椤兘寮婚敐澶嬫櫜闁搞儜鍐ㄧ婵°倗濮烽崑鐐垫暜閿熺姷宓侀悗锝庡枛缁秹鏌嶈閸撶喖骞冨Δ浣虹瘈婵﹩鍘搁幏娲煟閻斿摜鎳冮悗姘煎弮瀹曟洖螖閸涱喚鍘卞┑鈽嗗灥閵嗏偓闁稿鎹囬幃銏ゅ箵閹烘垹闃€婵犵數濮烽弫鍛婃叏閻戣棄鏋侀柛娑橈攻閸欏繘鏌i幋锝嗩棄闁哄绶氶弻娑樷槈濮楀牊鏁鹃梺鍛婄懃缁绘垿濡甸崟顖氱闁告鍋熸禒鑲╃磼閻愵剙鍔ゆい顓犲厴瀵鎮㈤悡搴n槶閻熸粌绻掗弫顔尖槈閵忥紕鍘撻梻浣哥仢椤戝懘鎮橀敃鍌涚厪闁搞儜鍐句純濡ょ姷鍋炵敮鈥崇暦閸楃儐娓婚柟顖嗗本顥$紓鍌氬€搁崐鎼佸磹妞嬪海鐭嗗〒姘e亾閽樻繈姊洪鈧粔鎾几娴g硶鏀介柣妯挎珪閻ㄦ垹鈧鎸风欢姘跺蓟濞戙垹鐒洪柛鎰典簴婵洭姊虹粙鍖″姛闁稿繑锕㈠璇测槈濡攱鏂€闂佺硶鍓濋〃蹇斿閳ь剚淇婇悙顏勨偓鏍ь潖瑜版帒绀夐柡鍥ュ灩閻撴﹢鏌熸潏楣冩闁稿﹤顭烽弻娑㈠Ψ閵忊剝鐝栭柡宥忕節濮婄粯鎷呴崨濠傛殘闂佸湱枪椤兘骞冮悜鑺ユ櫆闁伙絽澶囬弨铏節閻㈤潧孝婵炶绠撳畷鐢稿礃椤旂晫鍘撻梺鍛婄箓鐎氼剟寮抽悢鍏肩叆婵炴垶鐟ч惌鎺撴叏婵犲洨绱伴柕鍥ㄥ姍楠炴帡骞嬪⿰鍐╃€抽梻鍌欑閹诧繝鎮烽妷锔绘闁归棿绀侀悡婵嬫煙閻愵剚鐏遍柛顐邯閺屾盯顢曢妶鍛亖闂佸憡蓱閹倿寮婚敐鍫㈢杸闁哄洨鍋橀幋椋庣磼缂併垹骞栭柣鏍帶閻g兘骞嬮敃鈧粻濠氭偣閸ヮ亜鐨洪柣銈傚亾婵犵數鍋犻幓顏嗗緤娴犲绠熼柨鐔哄Т绾捐銇勯弽顐沪闁抽攱鍨归惀顏堫敇閻愭潙娅f繛瀛樼矊缂嶅﹪骞冪捄琛℃闁哄诞鍐ㄐ曢梻浣虹《閺備線宕戦幘鎰佹富闁靛牆妫楃粭鎺楁煕閻曚礁浜伴柟顖氬暙鐓ゆい蹇撴噽閸樺憡绻涙潏鍓у埌婵犫偓鏉堛劍娅犳い蹇撶墛閻撳啴鎮峰▎蹇擃仼闁诲繑鎸抽弻鐔碱敊閻e本鍣伴悗娈垮枛閻栧ジ鐛€n喗鍋愰弶鍫厛閺佸洭姊婚崒姘偓椋庣矆娴i潻鑰块弶鍫涘妿娴犳岸姊绘担渚敯濠殿喓鍊楅崚鎺撴償閵娿儳顦梺鍦劋椤ㄥ懐鐚惧澶嬬厱妞ゆ劑鍊曢弸搴∶归悩鐑橆仩缂佽鲸鎸婚幏鍛村礈閹绘帒澹嶆俊鐐€栧ú妯荤箾婵犲洤鏋侀柛鎰靛枛绾惧吋绻涢幋鐐跺妤犵偛鐗撳缁樻媴閸涘﹥鍎撳┑鐐茬湴閸ㄨ棄鐣峰┑鍡欐殕闁告洦鍓欓埀顒€鐖奸弻锝呂熼懖鈺佺闂佺粯鎸诲ú鐔煎蓟閻斿吋鍤嬫い鎺嗗亾濠碉紕鍘ч湁婵犲﹤瀚崝銈夋煃鐟欏嫬鐏撮柡浣哥Ч瀹曠喖顢曢埄鍐╃窔闂傚倷鑳舵灙闁挎洏鍎甸幃褔鎮╅懠顒佹濠电娀娼ч鍡涘疾濠靛鐓冪憸婊堝礈閻旂厧鐏抽柨鏇炲€搁柨銈嗕繆閵堝倸浜鹃梺缁樺笒閻忔岸濡甸崟顖氱鐎广儱鐗嗛崢锛勭磽娴e搫孝濠⒀傜矙閸┾偓妞ゆ巻鍋撻柛妯荤矒瀹曟垿骞橀弬銉︽杸闂佺粯枪娴滎剛绮i弮鍫熺厱閻庯綆鍋掑▓鏃堟煃鐟欏嫬鐏存い銏$懅濞戠敻鎮滈悾灞藉冀濠电姷鏁搁崑娑㈠箯閹寸姴绶ら柛顭戝暎閿濆绠涢柡澶庢硶椤斿﹪姊洪悷鏉挎毐缁剧虎鍙冨畷浼村箻鐠囪尙顔嗛梺缁樶缚缁垶宕甸幋锔界厾缂佸娉曟禒娑欐叏閿濆棗濮嶆慨濠傤煼瀹曟帒顫濋钘変壕闁绘垼濮ら崵鍕煠閸濄儲鏆╁ù鐘崇缁绘繈鎮介棃娑楃捕濡炪倖娲﹂崣鍐ㄧ暦濡も偓铻e〒姘煎灠濞堛劌顪冮妶鍡楀闁稿﹥鐗滈埀顒佺濮樸劑鍩€椤掑倹鍤€濠㈢懓锕畷浼村冀瑜夐弸鏃堟煏婵犲繐顩紒鈾€鍋撻梻浣圭湽閸ㄨ棄岣胯閻楀海绱撴担鍝勪壕婵犮垺岣跨划鏃堟偡闁箑娈ㄩ梺鍝勮閸庤京绮婚悽鍛婄厵闁绘垶岣跨粻姗€鏌涢悙鍨毈闁哄矉缍侀幃鈺呮倻濮楀棔鍝楅梺璇茬箰缁诲牓宕濆畝鍕垫晩闊洦绋戝敮閻熸粌顦靛畷鎴﹀箻閼搁潧鏋傞梺鍛婃处閸撴瑧鍠婂鍛斀闁宠棄妫楁禍婵堢磼鐠囨彃鈧潡鏁愰悙鍓佺杸婵炴垶鐟﹂崕顏堟⒑闂堚晛鐦滈柛姗€绠栭弫宥呪堪閸愶絾鏂€闂佸疇妫勫Λ妤呮倶閻樼粯鐓欑痪鏉垮船娴滀即鏌ㄥ┑鍫濅粶妞ゆ挸銈稿畷鍫曞煛閸愯法闂繝鐢靛仩閹活亞绱炴笟鈧棢闁规崘顕х粈澶屸偓骞垮劚椤︿即鎮″▎鎴犵<閻庯綆浜炴禒銏ゆ煛閸℃稐鎲鹃柡宀嬬秮閺佹劙宕惰楠炲螖閻橀潧浠滄い鎴濐樀瀵偊宕橀鑲╁姦濡炪倖甯掗崐缁樼▔瀹ュ應鏀介柣妯虹-椤f煡鏌涚€e墎绉柡灞剧洴婵$兘骞嬪┑鍡樻婵°倗濮村ú顓㈠箖濡ゅ啯鍠嗛柛鏇ㄥ墮绾板秶绱撴担鍓叉Ч闁瑰憡濞婇崹楣冨籍閸繄顦ㄥ銈嗘煥濡插牐顦归柡灞剧洴閸╁嫰宕楅悪鈧禍顏勎涢崟顐悑闁搞儮鏅濋敍婵囩箾鏉堝墽鍒板鐟帮躬瀹曟洟骞囬悧鍫㈠幈闂侀潧枪閸庨亶銆傚畷鍥╃<妞ゆ梻鈷堥崕蹇斻亜閹惧啿鎮戠€垫澘瀚埀顒婄秵娴滄牠宕戦幘缁樼叆閻庯絻鍔嬬花濠氭⒑閻熺増鎯堢紒澶婄埣钘濋柨鏃堟暜閸嬫挸鈻撻崹顔界亪闂佽绻戠换鍫ュ春閻愬搫绠i柨鏇楀亾闁绘搫绻濋弻娑㈠焺閸愮偓鐣兼繛瀵稿閸ㄨ泛顫忓ú顏勫窛濠电姴娴烽崝鍫曟⒑閸涘﹥澶勯柛娆忛鐓ら柛娑橈梗缁诲棝鏌曢崼婵堢闁告帊鍗抽弻娑㈡偆娴e摜浠搁悗瑙勬礃閸旀瑥鐣疯ぐ鎺濇晝闁挎繂鎳庢导搴㈢節绾版ɑ顫婇柛銊﹀▕瀹曘垼顦崇紒鍌氱У閵堬綁宕橀埡浣插亾閸偅鍙忔俊顖滃帶娴滈箖鎮楀鐐

《网络吸管》开发手记
网络确实是个好东西,文章呀,图片呀什么的都很吸引人。每次上网都能满载而归,但是这些资料的收集过程却很麻烦。对于好文章,每次都要复制、粘贴地在记事本和IE之间切换多次才能保存下来,而且说不定什么时候遇到那种怎么复制也复制不下来的防复制网页;对于图片也要点右键,选择“图片另存为”,再点确定才可以,遇到文件重名问题还要重命名。上网的兴致全被打乱了。网上虽然也有“网文快捕”之类的小软件,但是由于不是为自己“量身定做”的,所以用起来也不是很顺手。既然这样,就自己动手做一个吧,“自己动手丰衣足食”嘛!说干就干!
设计思想很简单:监视剪贴板,当发现剪贴板中有新内容时,就根据内容是文字还是图片来决定不同的保存方式。
如何监视剪贴板呢?很自然地想到放一个定时器,每隔一段时间检测一个剪贴板,将剪贴板地内容于上次检测地内容相比较,如果不同,就说明剪贴板的内容有变化。但是这样效率太低了,并且定时器的时间间隔也不好把握,间隔太短会降低系统的效率,而间隔太长就有可能漏掉复制的内容。这让我想起了CPU与外设之间通讯方式中的查询方式,那么有没有一种像CPU与外设之间的中断方式的东西呢?启动MSDN,搜索ClipBoard,呵呵!终于找到了!是什么呢?听我慢慢道来!
为了使应用程序能自动感知剪贴板的变化,windows提供了两个API函数。使用SetClipBoard可以将窗体注册到剪贴板观测链中,然后程序就能响应剪贴板的变化消息。剪贴板观察器是一个显示剪贴板当前内容的窗口。剪贴板观察链是一系列相互独立的剪贴板观察窗口,它们都能够接受当前发送到剪贴板的内容。
SetClipBoard的原型是:
function SetClipBoard(hwndNewViewer:HWND):HWND;
hwndNewViewer为要注册的窗体句柄。如果注册成功,则返回剪贴板观测链中下一个窗体的句柄;如果发生错误或无其他窗体,则返回NULL。
如果剪贴板发生变化,windows会向窗体发送WM_CHANGECCHAIN或WM_DRAWCLIPBOARD消息,观测链中每个窗体都会调用SendMessage将该消息传送给下一个窗体。当应用程序退出时,要利用API函数ChangeClipboardChain将窗体从剪贴板观测链中移去。其原型为:
function ChangeClipboardChain(hWndRemove, hWndNewNext:HWND):boolean;
hWndRemove将要删除的窗口的句柄, hWndNewNext为SetClipBoard返回的窗体的句柄。
这样我们只要在程序中等待剪贴板变化的消息即可。当消息到来时,我们应该怎样得到剪贴板中的内容呢?Delphi的clipbrd.pas单元中定义了一个类TClipboard,它封装了Windows剪贴板,简化了大量复杂的处理过程。我们在程序中可以直接调用全局函数Clipboard,该函数用于返回TClipboard对象实例,使用这个实例对剪贴板进行剪切、复制和粘贴等操作。下面是TClipboard对象的几个常用的方法和属性的简单介绍:
方法:
PRocedure Clear; 清空剪贴板。
function HasFormat(Format: Word): Boolean; 查询剪贴板中是否有指定格式的内容。可以有三种取值:CF_TEXT(文字)、CF_BITMAP(位图)、CF_METAFILEPICT(元文件)。
属性:
AsText:用于读写剪贴板文字内容。
如何给用户保存下来的图片文件命名也是个问题。我们可以设置一个全局整型变量,每当保存一个图片文件时,就令这个变量增加1,将这个整型变量转换成字符串做为文件名。如果指定的文件名已经存在,就要给文件重命名。最简单的办法就是在文件名之前(或之后)加上一个字符串(比如'new'),如果加上这个字符串后还是存在重名的文件呢?这就要用到学编程的人在一开始就学到的一个小技巧:递归。这个问题的解决办法见下面的代码:
procedure SaveToPic(APic: TJPegImage; AFileName: string);
Const PICPLUSSTR = 'new';
begin
if FileExists(AFileName) then
savetopic(ABmp, PICPLUSSTR+AFileName)
else
SaveBmpAsJpg(APic, AFileName);
end;
在实际应用的时候,还应该加上异常处理(如磁盘空间已满,文件名过长等)。图片的保存的基本问题已经解决,我们再来看看文字的保存。为了增强程序的灵活性,我们应该使用用户能方便地将不同地文字保存到不同的文件。继续沿用上面保存图片的方式用数字做文件名吗?当然不可以。一是因为文本文件不像图片那样在资源管理器中可以预览,用户必须打开文件才能知道文件中保存的是什么内容,如果用户想在一大堆“1.txt”、“2.txt”……中找自己想要的内容就太麻烦了;二是因为用户并不要求每次复制下来的内容都保存到单一的文件中,而是要将相关的内容保存到一个文件中。我对这个问题的解决方法是这样的:
用户可以先复制一段文字,然后再按一个热键(比如Ctrl+Alt+S,为什么要选Ctrl+Alt+S做热键呢?后面再说!),这样用户以后复制下的文字就保存到以用户复制的文字做为文件名的文件中。
记得无数位大师说过:“要将用户界面与业务逻辑分开。”好吧,就将上面的东西封装一下,也算是我向OO迈进的第一步吧!(下面之列出了类的部分成员)
TWebPageSaver = class(TObject)
private
FImagePath: string;
FTextPath: string;
FImageCount: Integer;
FTextFileName: string;
procedure SetImagePath(const Value: string);
procedure SetTextPath(const Value: string);
public
function Save: Boolean;//result is whether the content is saved
procedure NewTextFile(AFileName:string);
property ImagePath: string read FImagePath write SetImagePath;
property TextPath: string read FTextPath write SetTextPath;
end;
在用户界面中,当用户按下热键Ctrl+Alt+S时,就调用TWebPageSaver.NewTextFile更改文字保存的文件名FTextFileName;当收到剪贴板变化的消息时就调用TWebPageSaver.Save保存剪贴板中的内容。另外还有ImagePath、TextPath等属性,可以由用户来更改图片、文字的保存路径。
核心代码已经完成,来做一下用户界面吧!仿照着“windows优化大师”我做了界面,左边我用的是TSpeedButton组件,右边是TNotePage组件。当用户点击一个TSpeedButton时,调用TNotePage.ActivePage := '页面的代号'就可以激活相应的配置界面。这个软件需要在后台运行,那么就让它在平时缩小到系统托盘吧!将程序缩小到系统托盘很容易做到,网上有很多这样的示例代码。我手头有一个控件cooltray4.3可以用来实现系统托盘的功能,我就懒得自己再去写代码了。
软件运行一切良好。不过一直令我耿耿于怀的就是网上那种防复制的网页:不管你怎么拖动鼠标,那些文字就是无法被选定。仔细想一想,既然文字能够在IE上显示就一定可以得到它们。在MSDN中找了半天,才找到解决方法。可以通过ShellWindows集合来代表属于shell 的当前打开的窗口的集合,而IE就是属于shell的一个应用程序。用CoShellWindows.Create得到当前打开的shell的接口(IShellWindows),调用接口的Count属性得到当前打开的shell的数量,然后遍历这些窗口,尝试从接口中取出IWebbrowser2接口(通过ShellWindow.Item(I) as IWebbrowser2这样的接口类型转换方式),如果结果不为nil说明这个窗口是IE窗口。之后只要调用IWebBrowser2接口的相应方法即可得到窗口中的文字、URL、标题等内容了。
示例代码如下:
{需要使用mshtml,SHdocvw两个单元}
var
ShellWindow : IShellWindows;
WebBrowser : IWebBrowser2;
I, ShellWindowCount: integer;
HTMLdocument : IHTMLdocument2;
URL, Title, Text:string;
begin
ShellWindow := CoShellWindows.Create;
ShellWindowCount := ShellWindow.Count;
for I := 0 to ShellWindowCount-1 do
begin
WebBrowser := ShellWindow.Item(I) as IWebbrowser2;
if WebBrowser <> nil then
begin
HTMLDocument := WebBrowser.Document as IHtmlDocument2;
URL := URL;
Title := HTMLDocument.title;
Text := HTMLDocument.body.outerText ;
ShowMessage(URL+Title+Text);
end;
end;
ShellWindow := nil;
end;
我们定义一个记录类型:
TWebPageRecord = record
URL: string; file://保存网页的URL
Title: string;//保存网页的标题
Text: string; file://保存网页的文字
end;
然后定义一个TWebPageRecord类型的数组FWebPageRecordArray,大小定位20吧(我想一般人不会打开20个以上的IE吧):
Const MAXPAGECOUNT = 20;
……
FWebPageRecordArray : array [0..MAXPAGECOUNT-1] of TWebPageRecord;
在遍历IE窗口时,向数组中的元素的相应字段复制即可。
对这个复制防复制(好拗口呀:))网页的功能也封装成一个类吧!
type
TWebCracker = class(TObject)
private
FWebPageRecordArray : array [0..MAXPAGECOUNT-1] of TWebPageRecord;
FWebPageCount: Integer;
public
procedure SnapShot;
function GetWebText(AIndex:integer): string;
function GetWebTitle(AIndex:integer): string;
function GetWebURL(AIndex:integer): string;
procedure Clear;
procedure Refresh;
function GetWebPageCount: Integer;
end;
在用户界面中,可以通过调用TWebCracker.SnapShot;来对打开的IE窗口进行遍历,并保存到FWebPageRecordArray这个数组中。通过TWebCracker.GetWebPageCount方法可以得到FWebPageRecordArray中保存的页面的个数,通过GetWebText、GetWebTitle、GetWebURL就可以得到指定页面的文字、标题或是URL。
一切都已经搞定了!爽!
通过编写这个小软件,我是收获颇丰呀!除了学到了上边这些技巧外,我还有一些小的经验,愿意与大家分享:
1、为用户着想,让用户舒服
用户是上帝嘛!以那个Ctrl+Alt+S热键来说吧:一般用户上网都是右手握鼠标,空下来的只有左手。小拇指按Ctrl,大拇指按Alt,食指刚好能按到S键,不费一点力气!
2、 良好的编码习惯
(1)不要出现魔术数
以TWebCracker定义的那个FWebPageRecordArray数组来说:
Const MAXPAGECOUNT = 20;
……
FWebPageRecordArray : array [0..MAXPAGECOUNT-1] of TWebPageRecord;
别人一看MAXPAGECOUNT就知道是什么意思,而如果你写成:
FWebPageRecordArray : array [0..19] of TWebPageRecord;
估计除了你自己没有人能够知道19到底是什么意思。
(2)用sender的方式增强代码的健壮性
procedure TMainfrm.CBAutoRunClick(Sender: TObject);
Const
SIGNINREGISTRY = 'WebSuction';
begin
if (Sender as TCheckBox).Checked then
AddToAutoRun(application.ExeName,SIGNINREGISTRY)
else DelAutoRun(SIGNINREGISTRY);
end;
这样即使Checkbox1改了名字也不怕。
又如:
procedure TMainfrm.N1Click(Sender: TObject);
begin
if (Sender as TMenuItem).Caption = '暂停(&S)' then
begin
(Sender as TMenuItem).Caption := '开始(&R)';
FWebPageSaver.Pause;
end
else
begin
(Sender as TMenuItem).Caption := '暂停(&S)';
FWebPageSaver.ReStart;
end;
end;
(3)不要直接使用Tform2单元的全局Form2变量,那样就破坏了封装性
procedure TMainfrm.SBNextClick(Sender: TObject);
var
LSelectedIndex : integer;
FormDisplay : Tform2;
begin
LSelectedIndex := LBWebPage.ItemIndex;
if LSelectedIndex <> -1 then
begin
FormDisplay := Tform2.Create(self);
FormDisplay.SetContent(FWebCracker.GetWebText(LSelectedIndex));
FormDisplay.Show;
end;
end;
在TForm2中定义 SetContent方法
procedure TWebCrackfrm.SetContent(AText:string);
begin
Memo.Clear;
Memo.Lines.Add(AText);
end;
更多请见:http://lincosoft.go.nease.net/
更多精彩
赞助商链接