屏幕取詞源碼
A. 英文不好怎樣看英文網頁
google 提供在線翻譯 可以 試試
也可以安裝金山詞霸之類的翻譯軟體
問題補充回答:網路里搜 翻譯軟體 ,多的是!翻譯軟體只能翻譯文字性的東西,軟體是經過編譯打包的怎麼可能被翻譯,如果你要翻譯,也首先要反編譯,拿到它的源碼,再進行!
B. 請教關於用python編寫屏幕取詞的程序問題
1、屏幕取詞技術實現原理與關鍵源碼----
Ubuntu 下可以監視 gtk.Clipboard 來獲取當前選中文字和位置。
我以前嘗試過定時抓取滑鼠附近圖像做 OCR 來取詞,
改成快捷鍵取詞會省一點。
直接獲得文字的懸停取詞比較麻煩。
網頁、XUL 應用程序可以有滑鼠懸停事件。
X11 自己沒有, 不過以前流行中文平台、中文外掛時候 Turbolinux 的中文 X-window 被修改為集成滑鼠懸停取詞翻譯。
Gtk 程序也許你可以在 ATK 層入手,自己改 ATK 和用 LD_LIBRARY_PATH。
windows下很不好做。
普遍用的是HOOK API的方法。
可以參考stardict的取詞模塊。
不過我感覺stardict的取詞模塊也不是太好用(沒金山詞霸的好用),感覺有bug。
似乎以前某版本的金山詞霸可以翻譯圖片中的文字,就是用 OCR
再,金山似乎出過 Linux Qt3 版本,找 Zoomq 幾位在金山的老大索取源碼看看吧
嗯, 金山詞霸確實出過 Linux 版本,
是基於 wine 的,不是原生的 Linux 版本...
linux下就不知道,windows下,應該是做一個api hook,鉤住TextOut,DrawText和DrawTextEx。
要取詞的時候給滑鼠所在的窗口發一個WM_PAINT消息,讓窗口重繪。
當窗口調用TextOut, DrawText或是DrawTextEx進行重繪的時候,你就可以根據傳入的參數知道
窗口想在滑鼠下畫什麼東西了。
C. 有開源的java屏幕取詞程序嗎
這樣問得確不是很正確,語言沒有開不開源的說法,語言只是提供給大家一種寫代碼要遵循的語法,當然這些語法肯定是公開的,不然大家怎麼學呀。
至於用java這個語法寫的代碼是否是開源的,那每個項目都不同,有開源的也有商業的;
如果你想問的是java的基本類庫是否開源,那答案是是的,你安裝完jdk後目錄下會有src.zip,裡面就是源代碼;
D. 推薦一些常用電腦軟體
http://www.seekerbase.com/bbs/dispost.asp?BoardID=36&PostID=8219&Page=0
WinRAR v3.42 簡體中文注冊版 V3.50 Beta 7流行好用的壓縮工具,支持滑鼠拖放及外殼擴展,完美支持 ZIP 檔案,內置程序可以解開 CAB、ARJ、LZH、TAR、GZ、ACE、UUE、BZ2、JAR、ISO 等多種類型的壓縮文件;壓縮率相當高,具有分卷壓縮、製作自解壓文件、加密壓縮等功能
=====下載工具=====
點此下載—FlashGet v1.65 國際版 v1.65 注冊機1.65 注冊碼:fgf- 大名鼎鼎的多任務多線程斷點續傳下載管理器,被譽為國內王牌下載工具。可以說是一個集速度與管理於一身的下載軟體。其最大的特點就在於對下載文件的管理,通過JetCar下載的文件可按樹狀結構分門別類的保存起來,新版本已經支持MMS、RTSP等流媒體文件下載
Net Transport v1.94c提起下載,人們馬上就會想到NetAnts、FlashGet等傳統的下載利器。它們憑借著斷點續傳和多線程下載等實用功能而聞名於世。可是,隨著寬頻的普及就漸漸顯出了疲態。寬頻一話不再滿足於在WEB或者是ftp伺服器上下載文件。流媒體成了他們新的話題。網上廣泛流傳的流媒體下載工具是Stream VCR,可是它只支持單線程下載,使得下載速度大大減慢。Net Transport支持HTTP、FTP、MMS和RSTP協議,除了RSTP協議外,對於其他的協議均能實現多線程的斷點續傳
PUB Downloader v1.6 簡體中文版 所謂PUB就是Public ftp的簡稱,您常在下載文件碰到需要使用PUB Downloader軟體下載時,是不是就沒輒了呢!不要怕!就是使用此軟體來下載一些經過轉換保護的Public ftp伺服器內的文件。使用方法:先將密碼網址復制貼到密鑰輸入欄里,按連線完後點選左上角資料指定下載到何處,再選擇pub里你欲下載的檔案再按play鍵即可
eMule 簡體中文版 0.46a VeryCD Build 0611
eMule 0.45b CN-4 Bulid 159 中文安裝版(中國驢)推薦使用中國驢的Mod eMule是以eDonkey2000網路為基礎的新型P2P文件分享工具,不但提供了所有eDonkey的標准功能,還提供了許多額外的功能,比如支持上榜、證書等,因而受到許多網友的喜愛
KuGoo(酷狗) 2.052 KuGoo是國內最大的P2P音樂共享軟體,擁有超過數億的共享文件資料,深受全球用戶的喜愛,擁有近千萬使用用戶。 最新的V2版本給予用戶更多的人性化功能,實行多源下載,提昇平時的下載速度,經測試,最快可以達到500K/S,更快更高效率的下載搜索的歌曲。國內最先提供在線試聽功能,方便用戶進行選擇性的下載,減少下載不喜歡的歌曲哦。娛樂主頁每天會提供大量最新的娛樂資訊,歐美、中文和日韓的最新大碟,單曲排行下載讓你輕松掌握最前衛的流行動態,充分享受KuGoo和您的精彩娛樂生活。 酷狗具有強大的搜索功能,支持用戶從全球KUGOO用戶中快速檢索所需要的資料,還可以與朋友間相互傳輸影片、游戲、音樂、軟體、圖片。 快速下載功能:KUGOO擁有強大的網路連接功能,支持區域網、外網等各種網路環境,支持斷點續傳,實現超高速下載,。 KuGoo具備了的聊天功能,並且可以與好友共享傳輸文件,讓聊天,音樂,下載變得更加互動,還附帶多功能的播放器。 文件共享讓您可以立即與夥伴之間共同分享自己電腦里的文件、數據、音樂等等。為你建立一個自由、自主、安全的世界區域網。
=====BT工具====
BitTorrent Plus! II 正式版 1.2 一個多點下載且源碼公開的P2P軟體,使用非常方便,就像一個瀏覽器插件。與以往http、FTP、 pub等下載人越多,速度越慢的方式迥然不同,BT下載的特點簡單的說就是:下載的人越多,速度越快。時下BT已經成為網上交流資源最新、最酷的方式
BitComet 0.59 穩定版推薦BT用戶使用,對內網用戶尤其適用 BitComet是基於BitTorrent協議的p2p文件分享免費軟體,支持多任務下載,文件有選擇的下載;磁碟緩存,減小對硬碟的損傷;只需一個監聽埠,方便手工防火牆和NAT/Router配置;在WindowsXP下能自動配置支持Upnp的NAT和XP防火牆,續傳做種免掃描,速度限制等多項實用功能,以及自然方便的使用界面
BitSpirit 比特精靈 多國語言版 3.0.1.090 正式版 比特精靈(BitSpirit)是一款完全免費、高速穩定、功能強大、簡單易用的BT下載軟體。自發布以來以其穩定高速,功能強大,使用人性化的特點,日益受到廣大用戶的青睞
貪婪BT(GreedBT) v2.7.1 多語言版 貪婪BT(ABC)是在 The Shad0w''''''''s Bittorrent experimental S-5.7.6 的基礎上改進而來。The Shad0w''''''''s Bittorrent experimental則是在原始的Bittorrent上改進而來。貪婪BT是應該說是超強的Bittorrent客戶端,單窗口多任務,資源消耗少。ABC是一個非常棒的單窗口BT客戶端,穩定,占內存非常小,速度快
=====中文輸入工具=====
拼音加加 3.11 正式版 3.11 增強版
紫光拼音輸入法增強版 4.0 m3 build 2
微軟拼音輸入法 2003 官方正式增強版
極點中文 v4.4 正式版
龍文輸入平台 v3.93正式版 優秀漢字輸入軟體,五筆、拼音混合輸入,無需切換,自動加詞、反查編碼等功能可以使你輸入效率更高,免費使用
智能陳橋五筆v5.601
=====FTP客戶端工具==
FlashFXP v3.2.0 漢化正式版注冊碼在安裝過程中的許可協議裡面注冊方法請詳見漢化說明 功能強大的FXP/FTP軟體,融合了一些其他優秀FTP軟體的優點,如像CuteFTP一樣可以比較文件夾,支持彩色文字顯示;像BpFTP支持多文件夾選擇文件,能夠緩存文件夾;像LeapFTP一樣的外觀界面,甚至設計思路也差相彷彿。支持文件夾(帶子文件夾)的文件傳送、刪除;支持上傳、下載及第三方文件續傳;可以跳過指定的文件類型,只傳送需要的文件;可以自定義不同文件類型的顯示顏色;可以緩存遠端文件夾列表,支持FTP代理及Socks 3&4;具有避免空閑功能,防止被站點踢出;可以顯示或隱藏「隱藏」屬性的文件、文件夾;支持每個站點使用被動模式等
CuteFTP Pro v7.1.06.07 漢化版漢化包中附帶 BetaMaster 的破解補丁,請自行破解最好的FTP客戶程序之一,如果你是CuteFTP老版本的用戶,你會發現很多有用的新特色。目錄比較,宏目錄上載和下載,遠程文件編輯,以及IE風格的工具條等等,定會令你愛不釋手
FTPRush v1.0 RC6 build 0568 著名的FTP客戶端FTPRush(以前叫UltraFXP)是一個高性能的FTP客戶端, 通過它你可以輕松地上傳下載和FXP(Ftp伺服器之間的文件傳輸),, 完全多線程的構造, 讓你自由自在地存取FTP伺服器的資源, 下面列出一些主要的特性:多站台支持、多IP地址、腳本、FTP 代理、多語言支持、容易使用、多線程內核、自動CRC校驗、快速連接、站台捷徑等等
=====郵件客戶端工具====
Foxmail v5.0.800.0 簡體中文版 國內著名的Internet電子郵件客戶端軟體,支持全部的Internet電子郵件功能。有中文版和英文版。中文版在國內擁有眾多用戶,英文版的用戶遍布全球二十多個國家。真正的多用戶,多帳戶,多POP3支持;郵箱目錄樹結構,可以無限建立子郵件夾和子郵箱;不再是MDI(多文檔)窗口。如寫郵件窗口是獨立的,可視面積更大,切換更方便等
雖說平凡得如路旁一棵草,但生命和個性總是屬於自己的。
【我愛的人名花有主】
【愛我的人慘不忍睹】
【不是在放盪中變壞】
【就是在沉默中變態】
發帖時間:2005-9-3 1:18:49
標題:RE:電腦裝機常用軟體大全
作者:夢醒時分 [編輯] [刪除] [引用] 第[2]樓
DreamMail v3.0.0.5 簡體中文版 DreamMail是一款專業的電子郵件軟體,用於管理和收發電子郵件,支持 Windows 98/ME/NT4/2000/XP/2003 等操作系統。它採用多用戶和多帳號方式來管理電子郵件,支持SMTP、eSMTP、POP3、Hotmail、Yahoo等郵件協議,真正採用多線程高速收發郵件。附帶增強型遠程管理,可以直接查看伺服器上郵件的內容、可以在伺服器上直接刪除郵件;郵件過濾器、黑名單及白名單等組合使用,能有效對付垃圾郵件;DreamMail 能自動檢測破壞性郵件,增強系統安全;另外,DreamMail 還支持特快專遞、語音郵件、匿名發送及群組發送等
Becky! v2.21.03 漢化版Name:crsky Code:6507-3437-f766 eMail:[email protected]
雖說平凡得如路旁一棵草,但生命和個性總是屬於自己的。
【我愛的人名花有主】
【愛我的人慘不忍睹】
【不是在放盪中變壞】
【就是在沉默中變態】
發帖時間:2005-9-3 1:19:00
標題:RE:電腦裝機常用軟體大全
作者:夢醒時分 [編輯] [刪除] [引用] 第[3]樓
=====光碟虛擬刻錄工具==
Daemon Tools v3.47 漢化版 一個非常棒的虛擬光碟機軟體,安裝後不需重起即可使用,它支持PS機格式,支持加密光碟,最大的好處是可以把從網上下載的CUE、ISO、CCD、BWT、MDF等鏡像文件Mount成光碟直接使用,不需要再把他們解開了
Alcohol 120%v1.9.5 Build 2802 這個光碟刻錄軟體的完整解決方案,能完整的模擬原始光碟片,讓你能不必將光碟映像文件刻錄出來便可以使用虛擬光碟機執行虛擬光碟且其效能比實際光碟機更加強大;支持多種映像檔案格式,你可以利用其它軟體所產生的光碟映像文件直接掛載進Alcohol 120%之虛擬光碟機中,便可直接讀取其內容;你也可以直接將CD、DVD或光碟映像文件刻錄至空白 CD-R / CD-RW / DVD-R / DVD-RW / DVD-RAM / DVD+RW 之中,而不必透過其它的刻錄軟體,方便你對光碟及映像文件的管理
WinISO v5.3 簡體中文特別版
UltraISO Media Edition 簡體中文版 7.6.1.1125
注冊碼在安裝過程中的許可協議裡面 7.5.5.1012SN:73BE-8D23-18C6-1D1D 一個類似於WinISO的ISO文件編輯工具,界面友好,方便的雙窗口操作,能製作啟動光碟映像。和WinISO相對比,可能製作啟動光碟鏡像的能力要強,而且網友反映穩定性也好於WinISO
DVDIdle Pro v5.9.3.0 多國語言版 大家經常讓自己的DVD-ROM用於DVD影片播放,從頭到尾勤奮的DVD得不到絲毫的休息,有時候還碰到花碟濫碟,嚴重影響了DVD的壽命....,而DVDIdle可以緩解這一問題,它利用了Smart Read-Ahead技術,將相關資料存儲到硬碟的緩存中,以減輕DVD-ROM的工作負擔,能夠延長DVD-ROM的使用壽命為原來的2-8倍
=====圖像瀏覽工具====
ACDSee PowerPark 7.0 Build 102 V7.0 Build 102漢化補丁注意:這是 ACDSee 7.0 build 102 PowerPack 的簡體中文補丁,適用於 ACDSee 7.0 build 102 PowerPack 版本,也可用於標准版。安裝時建議使用 Trial 模式安裝,漢化後即為破解版,無需激活。 ACDSee是目前最流行的數字圖象處理軟體,它能廣泛應用於圖片的獲取、管理、瀏覽、優化甚至和他人的分享!使用 ACDSee,你可以從數碼相機和掃描儀高效獲取圖片,並進行便捷的查找、組織和預覽,超過 50 種常用多媒體格式被一網打盡!作為最重量級看圖軟體,它能快速、高質量顯示您的圖片,再配以內置的音頻播放器,我們就可以享用它播放出來的精彩幻燈片了。Acdsee 能處理如Mpeg之類常用的視頻文件。此外ACDSee是您最得心應手的圖片編輯工具,輕松處理數碼影像,擁有的功能像去除紅眼、剪切圖像、銳化、浮雕特效、曝光調整、旋轉、鏡像等等,還能進行批量處理哦
ACDSee Classic v2.44 漢化版 高性能的看圖程序,支持 BMP,GIF,JPG,TGA,TIF 等各種常見的圖形文件格式,圖片打開速度極快;ACDSee Classic版本並不包含太多的功能,可以說是一個純粹的看圖軟體,所以要比ACDSee小得多
黃河Flash播放器 v7.63 「黃河Flash播放器」,可以播放各類Flash文件,使用不規則界面,可保存列表文件、打開開列表文件、清空列表,可以自定義列表,自動更新功能、從IE中拖放播放、IE右鍵播放功能等
=====屏幕截圖工具====
HyperSnap-DX v5.63.00 漢化版 提供專業級影像效果,也可讓您輕松地抓取屏幕畫面。支持抓取使用DirectX技術之游戲畫面及DVD視頻,並且採用新的去背景功能讓您將抓取後的圖形去除不必要的背景;預覽功能也可以正確地顯示您的圖列印出來時會是什麼模樣等
TechSmith SnagIt v7.22 v7.22漢化補丁Name:crsk Code:BF3909BC382BB17988 一個強大的屏幕捕捉程序,不僅能捕捉Windows下的屏幕,也能捕捉DOS的,存檔支持的圖形格式也很多;它不僅可以擷取整個畫面,還可以做動態影像擷取,文字擷取等,其功能之強大,讓人無法想像
=====網路瀏覽工具====
Internet Explorer v6.0 Build 2800 簡體中文完全版
MyIE2 v0.9.27.68 豪華版 Maxthon 傲遊瀏覽器 豪華版 1.3.1 Maxthon 是一個高度可定製的強大 Web 瀏覽器. 它基於 Internet Explorer 內核(可能正是您當前使用的默認瀏覽器), 這意味著它的效果和您在 IE 中看到的效果完全相同, 同時它還給您提供如下的額外功能... 多頁面瀏覽界面、滑鼠手勢、超級托拽、隱私保護、廣告獵手、Google Bar 支持、外部工具欄、自定義皮膚在經過一年多的開發, 在 1.0 版本即將發布之際, MyIE2 最終更名為 Maxthon.這樣做的主要原因是我們需要一個更能表現它的強大和不會引起誤會的名稱(不知道大家還記得 MyIE3 事件沒有). 與 MyIE2 一樣, Maxthon 也是免費軟體, 它繼承了 MyIE2 的所有強大功能, 並在易用性和用戶親和力方面著重進行了改善.感謝這些日子的支持. 讓我們做得更好!
GreenBrowser 多語言版 3.1.0730GreenBrowser作為一款IE內核多頁面瀏覽器,不斷匯集各家長處和經驗,並吸取來自用戶的反饋,以及自身獨到的創新設計,力爭實現更實用、更易用、更快捷、更穩定的宗旨。就象名字所言,綠色、免費、免安裝。一用上她,無論是從網頁的瀏覽效率、全方位的滑鼠操作性、用戶定製的多樣化、方便細致的搜索欄、自動執行腳本插件等各種特性中,您都能切實的體驗到她所帶來的網上生活的方便感和貼心感
Mozilla Firefox 1.0.6簡體中文版Mozilla Firefox是一個自由的,開放源碼的瀏覽器,適用於 Windows, Linux 和 MacOS X平台,它體積小速度快,還有其它一些高級特徵,主要特性有:標簽式瀏覽,使上網沖浪更快;可以禁止彈出式窗口;自定製工具欄;擴展管理;更好的搜索特性;快速而方便的側欄.這個版本做了脫胎換骨的更新,代碼更優秀,功能更強大,包括安裝程序,界面和下載管理器都作了改進。精品漢化插件使用方法:點擊 '菜單"--"工具"--''擴展'',把.xpi文件拖進彈出窗口裡,稍後就可以看到Firefox會詢問你是否要安裝這個插件,點擊是即可,重啟瀏覽器
GoSuRF Browser 2005 2.62.508.6225最IN的多頁面瀏覽器!重現最逼真的IE界面,並提供多項貼心功能: 加強對網頁圖片、文字的保存,一拖就存。強大的廣告過濾,可以阻擋彈出窗口和各種廣告條。 超強的網頁病毒保護,能防止惡意代碼的襲擊。穩定的工作,對意外崩潰時進行數據保護。提供方便的在線翻譯和瀏覽代理,沖浪無障礙。 快速准確的分類搜索,輕松獲得訊息
E. 屏幕取詞
「滑鼠屏幕取詞」技術是在電子字典中得到廣泛地應用的,如四通利方和金山詞霸等軟體,這個技術看似簡單,其實在WINDOWS系統中實現卻是非常復雜的,總的來說有兩種實現方式:
第一種:採用截獲對部分GDI的API調用來實現,如TextOut,TextOutA等。
第二種:對每個設備上下文(DC)做一分Copy,並跟蹤所有修改上下文(DC)的操作。
第二種方法更強大,但兼容性不好,而第一種方法使用的截獲WindowsAPI的調用,這項技術的強大可能遠遠超出了您的想像,毫不誇張的說,利用WindowsAPI攔截技術,你可以改造整個操作系統,事實上很多外掛式Windows中文平台就是這么實現的!而這項技術也正是這篇文章的主題。
截WindowsAPI的調用,具體的說來也可以分為兩種方法:
第一種方法通過直接改寫WinAPI 在內存中的映像,嵌入匯編代碼,使之被調用時跳轉到指定的地址運行來截獲;第二種方法則改寫IAT(Import Address Table 輸入地址表),重定向WinAPI函數的調用來實現對WinAPI的截獲。
第一種方法的實現較為繁瑣,而且在Win95、98下面更有難度,這是因為雖然微軟說WIN16的API只是為了兼容性才保留下來,程序員應該盡可能地調用32位的API,實際上根本就不是這樣!WIN 9X內部的大部分32位API經過變換調用了同名的16位API,也就是說我們需要在攔截的函數中嵌入16位匯編代碼!
我們將要介紹的是第二種攔截方法,這種方法在Win95、98和NT下面運行都比較穩定,兼容性較好。由於需要用到關於Windows虛擬內存的管理、打破進程邊界牆、向應用程序的進程空間中注入代碼、PE(Portable Executable)文件格式和IAT(輸入地址表)等較底層的知識,所以我們先對涉及到的這些知識大概地做一個介紹,最後會給出攔截部分的關鍵代碼。
先說Windows虛擬內存的管理。Windows9X給每一個進程分配了4GB的地址空間,對於NT來說,這個數字是2GB,系統保留了2GB到 4GB之間的地址空間禁止進程訪問,而在Win9X中,2GB到4GB這部分虛擬地址空間實際上是由所有的WIN32進程所共享的,這部分地址空間載入了共享Win32 DLL、內存映射文件和VXD、內存管理器和文件系統碼,Win9X中這部分對於每一個進程都是可見的,這也是Win9X操作系統不夠健壯的原因。
Win9X中為16位操作系統保留了0到4MB的地址空間,而在4MB到2GB之間也就是Win32進程私有的地址空間,由於 每個進程的地址空間都是相對獨立的,也就是說,如果程序想截獲其它進程中的API調用,就必須打破進程邊界牆,向其它的進程中注入截獲API調用的代碼,這項工作我們交給鉤子函數(SetWindowsHookEx)來完成,關於如何創建一個包含系統鉤子的動態鏈接庫,《電腦高手雜志》已經有過專題介紹了,這里就不贅述了。
所有系統鉤子的函數必須要在動態庫里,這樣的話,當進程隱式或顯式調用一個動態庫里的函數時,系統會把這個動態庫映射到這個進程的虛擬地址空間里,這使得DLL成為進程的一部分,以這個進程的身份執行,使用這個進程的堆棧,也就是說動態鏈接庫中的代碼被鉤子函數注入了其它GUI進程的地址空間(非GUI進程,鉤子函數就無能為力了),當包含鉤子的DLL注入其它進程後,就可以取得映射到這個進程虛擬內存里的各個模塊(EXE和DLL)的基地址,如:
HMODULE hmole=GetMoleHandle(「Mypro.exe」);
在MFC程序中,我們可以用AfxGetInstanceHandle()函數來得到模塊的基地址。EXE和DLL被映射到虛擬內存空間的什麼地方是由它們的基地址決定的。它們的基地址是在鏈接時由鏈接器決定的。當你新建一個Win32工程時,VC++鏈接器使用預設的基地址0x00400000。可以通過鏈接器的BASE選項改變模塊的基地址。EXE通常被映射到虛擬內存的0x00400000處,DLL也隨之有不同的基地址,通常被映射到不同進程的相同的虛擬地址空間處。
系統將EXE和DLL原封不動映射到虛擬內存空間中,它們在內存中的結構與磁碟上的靜態文件結構是一樣的。即PE (Portable Executable) 文件格式。我們得到了進程模塊的基地址以後,就可以根據PE文件的格式窮舉這個模塊的IMAGE_IMPORT_DESCRIPTOR數組,看看進程空間中是否引入了我們需要截獲的函數所在的動態鏈接庫,比如需要截獲「TextOutA」,就必須檢查「Gdi32.dll」是否被引入了。
說到這里,我們有必要介紹一下PE文件的格式,如右圖,這是PE文件格式的大致框圖,最前面是文件頭,我們不必理會,從PE File Optional Header後面開始,就是文件中各個段的說明,說明後面才是真正的段數據,而實際上我們關心的只有一個段,那就是「.idata」段,這個段中包含了所有的引入函數信息,還有IAT(Import Address Table)的RVA(Relative Virtual Address)地址。
說到這里,截獲WindowsAPI的整個原理就要真相大白了。實際上所有進程對給定的API函數的調用總是通過PE文件的一個地方來轉移的,這就是一個該模塊(可以是EXE或DLL)的「.idata」段中的IAT輸入地址表(Import Address Table)。在那裡有所有本模塊調用的其它DLL的函數名及地址。對其它DLL的函數調用實際上只是跳轉到輸入地址表,由輸入地址表再跳轉到DLL真正的函數入口。
具體來說,我們將通過IMAGE_IMPORT_DESCRIPTOR數組來訪問「.idata」段中引入的DLL的信息,然後通過IMAGE_THUNK_DATA數組來針對一個被引入的DLL訪問該DLL中被引入的每個函數的信息,找到我們需要截獲的函數的跳轉地址,然後改成我們自己的函數的地址……具體的做法在後面的關鍵代碼中會有詳細的講解。
講了這么多原理,現在讓我們回到「滑鼠屏幕取詞」的專題上來。除了API函數的截獲,要實現「滑鼠屏幕取詞」,還需要做一些其它的工作,簡單的說來,可以把一個完整的取詞過程歸納成以下幾個步驟:
1. 安裝滑鼠鉤子,通過鉤子函數獲得滑鼠消息。
使用到的API函數:SetWindowsHookEx
2. 得到滑鼠的當前位置,向滑鼠下的窗口發重畫消息,讓它調用系統函數重畫窗口。
使用到的API函數:WindowFromPoint,ScreenToClient,InvalidateRect
3. 截獲對系統函數的調用,取得參數,也就是我們要取的詞。
對於大多數的Windows應用程序來說,如果要取詞,我們需要截獲的是「Gdi32.dll」中的「TextOutA」函數。
我們先仿照TextOutA函數寫一個自己的MyTextOutA函數,如:
BOOL WINAPI MyTextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString,int cbString)
{
// 這里進行輸出lpszString的處理
// 然後調用正版的TextOutA函數
}
把這個函數放在安裝了鉤子的動態連接庫中,然後調用我們最後給出的HookImportFunction函數來截獲進程對TextOutA函數的調用,跳轉到我們的MyTextOutA函數,完成對輸出字元串的捕捉。
HookImportFunction的用法:
HOOKFUNCDESC hd;
PROC pOrigFuns;
hd.szFunc="TextOutA";
hd.pProc=(PROC)MyTextOutA;
HookImportFunction (AfxGetInstanceHandle(),"gdi32.dll",&hd,pOrigFuns);
下面給出了HookImportFunction的源代碼,相信詳盡的注釋一定不會讓您覺得理解截獲到底是怎麼實現的很難,Ok,Let』s Go:
///////////////////////////////////////////// Begin ///////////////////////////////////////////////////////////////
#include <crtdbg.h>
// 這里定義了一個產生指針的宏
#define MakePtr(cast, ptr, AddValue) (cast)((DWORD)(ptr)+(DWORD)(AddValue))
// 定義了HOOKFUNCDESC結構,我們用這個結構作為參數傳給HookImportFunction函數
typedef struct tag_HOOKFUNCDESC
{
LPCSTR szFunc; // The name of the function to hook.
PROC pProc; // The procere to blast in.
} HOOKFUNCDESC , * LPHOOKFUNCDESC;
// 這個函數監測當前系統是否是WindowNT
BOOL IsNT();
// 這個函數得到hMole -- 即我們需要截獲的函數所在的DLL模塊的引入描述符(import descriptor)
PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hMole, LPCSTR szImportMole);
// 我們的主函數
BOOL HookImportFunction(HMODULE hMole, LPCSTR szImportMole,
LPHOOKFUNCDESC paHookFunc, PROC* paOrigFuncs)
{
/////////////////////// 下面的代碼檢測參數的有效性 ////////////////////////////
_ASSERT(szImportMole);
_ASSERT(!IsBadReadPtr(paHookFunc, sizeof(HOOKFUNCDESC)));
#ifdef _DEBUG
if (paOrigFuncs) _ASSERT(!IsBadWritePtr(paOrigFuncs, sizeof(PROC)));
_ASSERT(paHookFunc.szFunc);
_ASSERT(*paHookFunc.szFunc != '\0');
_ASSERT(!IsBadCodePtr(paHookFunc.pProc));
#endif
if ((szImportMole == NULL) || (IsBadReadPtr(paHookFunc, sizeof(HOOKFUNCDESC))))
{
_ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
// 監測當前模塊是否是在2GB虛擬內存空間之上
// 這部分的地址內存是屬於Win32進程共享的
if (!IsNT() && ((DWORD)hMole >= 0x80000000))
{
_ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
return FALSE;
}
// 清零
if (paOrigFuncs) memset(paOrigFuncs, NULL, sizeof(PROC));
// 調用GetNamedImportDescriptor()函數,來得到hMole -- 即我們需要
// 截獲的函數所在的DLL模塊的引入描述符(import descriptor)
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor(hMole, szImportMole);
if (pImportDesc == NULL)
return FALSE; // 若為空,則模塊未被當前進程所引入
// 從DLL模塊中得到原始的THUNK信息,因為pImportDesc->FirstThunk數組中的原始信息已經
// 在應用程序引入該DLL時覆蓋上了所有的引入信息,所以我們需要通過取得pImportDesc->OriginalFirstThunk
// 指針來訪問引入函數名等信息
PIMAGE_THUNK_DATA pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hMole,
pImportDesc->OriginalFirstThunk);
// 從pImportDesc->FirstThunk得到IMAGE_THUNK_DATA數組的指針,由於這里在DLL被引入時已經填充了
// 所有的引入信息,所以真正的截獲實際上正是在這里進行的
PIMAGE_THUNK_DATA pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hMole, pImportDesc->FirstThunk);
// 窮舉IMAGE_THUNK_DATA數組,尋找我們需要截獲的函數,這是最關鍵的部分!
while (pOrigThunk->u1.Function)
{
// 只尋找那些按函數名而不是序號引入的函數
if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))
{
// 得到引入函數的函數名
PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hMole,
pOrigThunk->u1.AddressOfData);
// 如果函數名以NULL開始,跳過,繼續下一個函數
if ('\0' == pByName->Name[0])
continue;
// bDoHook用來檢查是否截獲成功
BOOL bDoHook = FALSE;
// 檢查是否當前函數是我們需要截獲的函數
if ((paHookFunc.szFunc[0] == pByName->Name[0]) &&
(strcmpi(paHookFunc.szFunc, (char*)pByName->Name) == 0))
{
// 找到了!
if (paHookFunc.pProc)
bDoHook = TRUE;
}
if (bDoHook)
{
// 我們已經找到了所要截獲的函數,那麼就開始動手吧
// 首先要做的是改變這一塊虛擬內存的內存保護狀態,讓我們可以自由存取
MEMORY_BASIC_INFORMATION mbi_thunk;
VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
_ASSERT(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
PAGE_READWRITE, &mbi_thunk.Protect));
// 保存我們所要截獲的函數的正確跳轉地址
if (paOrigFuncs)
paOrigFuncs = (PROC)pRealThunk->u1.Function;
// 將IMAGE_THUNK_DATA數組中的函數跳轉地址改寫為我們自己的函數地址!
// 以後所有進程對這個系統函數的所有調用都將成為對我們自己編寫的函數的調用
pRealThunk->u1.Function = (PDWORD)paHookFunc.pProc;
// 操作完畢!將這一塊虛擬內存改回原來的保護狀態
DWORD dwOldProtect;
_ASSERT(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
mbi_thunk.Protect, &dwOldProtect));
SetLastError(ERROR_SUCCESS);
return TRUE;
}
}
// 訪問IMAGE_THUNK_DATA數組中的下一個元素
pOrigThunk++;
pRealThunk++;
}
return TRUE;
}
// GetNamedImportDescriptor函數的實現
PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hMole, LPCSTR szImportMole)
{
// 檢測參數
_ASSERT(szImportMole);
_ASSERT(hMole);
if ((szImportMole == NULL) || (hMole == NULL))
{
_ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
}
// 得到Dos文件頭
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hMole;
// 檢測是否MZ文件頭
if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) ||
(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE))
{
_ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
}
// 取得PE文件頭
PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
// 檢測是否PE映像文件
if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) ||
(pNTHeader->Signature != IMAGE_NT_SIGNATURE))
{
_ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
}
// 檢查PE文件的引入段(即 .idata section)
if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL;
// 得到引入段(即 .idata section)的指針
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader,
pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
// 窮舉PIMAGE_IMPORT_DESCRIPTOR數組尋找我們需要截獲的函數所在的模塊
while (pImportDesc->Name)
{
PSTR szCurrMod = MakePtr(PSTR, pDOSHeader, pImportDesc->Name);
if (stricmp(szCurrMod, szImportMole) == 0)
break; // 找到!中斷循環
// 下一個元素
pImportDesc++;
}
// 如果沒有找到,說明我們尋找的模塊沒有被當前的進程所引入!
if (pImportDesc->Name == NULL)
return NULL;
// 返回函數所找到的模塊描述符(import descriptor)
return pImportDesc;
}
// IsNT()函數的實現
BOOL IsNT()
{
OSVERSIONINFO stOSVI;
memset(&stOSVI, NULL, sizeof(OSVERSIONINFO));
stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
BOOL bRet = GetVersionEx(&stOSVI);
_ASSERT(TRUE == bRet);
if (FALSE == bRet) return FALSE;
return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId);
}
/////////////////////////////////////////////// End //////////////////////////////////////////////////////////////////////
不知道在之前,有多少朋友嘗試過去實現「滑鼠屏幕取詞」這項充滿了挑戰的技術,也只有嘗試過的朋友才能體會到其間的不易,尤其在探索API函數的截獲時,手頭的幾篇資料沒有一篇是涉及到關鍵代碼的,重要的地方都是一筆代過,MSDN更是顯得蒼白而無力,也不知道除了IMAGE_IMPORT_DESCRIPTOR和IMAGE_THUNK_DATA,微軟還隱藏了多少秘密,好在硬著頭皮還是把它給攻克了,希望這篇文章對大家能有所幫助。
F. 拜求一個VC++/MFC編寫的屏幕取詞的程序,就是像金山詞霸取詞的那種~~用HOOK寫的
1.用detour實現hook。非常的簡單依樣畫葫蘆就可以劫持本進程的api
http://blog.csdn.net/evi10r/article/details/6659354
2.windows核心編程那本書里有進程注入,你可以下載源碼,詳見inject和eject的例子,可以把一個dll注入進一個進程
以前做過的,就這樣就行。但是現在那個工程沒了= =。你hook textout系列函數,然後將消息發回伺服器即可,加油。
G. 關於屏幕取詞代碼問題
屏幕取詞的源代碼
注意下面的代碼在截取多個API的時候會有重入問題,問題在於訪問 ShareMem 的時候沒有使用
任何互斥進行鎖定.
/// 數據定義文件
unit U_Def;
interface
uses
Messages, Windows;
const
WM_MOUSEPT = WM_USER + 1000 + Ord('M') + Ord('P') + Ord('T');
MappingFileName = 'Mapping File By Raphael';
MaxStringLen = 50;
CodeJump = $E9909090;
type
PInt = ^integer;
_ExtTextOutA = function (theDC :HDC; nXStart, nYStart :integer; toOptions
∶ Longint; rect : PRect;
lpStr :PAnsiChar; nCount :integer; Dx : PInteger)
∶BOOL; stdcall;
_PExtTextOutA = ^_ExtTextOutA;
TLongJump = packed record
JmpOp : Cardinal;
Addr : Pointer;
end;
TShareMem = packed record
hProcWnd : HWND; //The main window of the program
hHookWnd : HWND; //The window currently being hooked
hWndPseudo : HWND; //The pseudo window used to repaint the other
window
hProc : THandle; //The process ID of the main program
pMouse : TPoint; //the mouse position
fStrMouseQueue : array [0..MaxStringLen] of Char; //mouse info
nTimePassed : integer; //the time passed since last time's mousemove
bCanSpyNow : Boolean;
bHookExtTextOutA : Boolean;
pOldExtTextOutA : TLongJump;
fStrExtTextOutA : array [0..MaxStringLen] of Char;
end;
PShareMem = ^TShareMem;
implementation
end.
/// HOOK DLL源代碼
library dll_HookMouse;
uses
SysUtils,
Windows,
Classes,
Messages,
Math,
Dialogs,
U_Def in 'U_Def.pas';
{$R *.RES}
var
hMouseHook : HHOOK;
SpyInstalled : Boolean;
fTimerID : Cardinal;
pShMem : PShareMem;
hMappingFile : THandle;
function InstallSpy:Boolean; forward;
function UnWiseSpy:Boolean; forward;
function fExtTextOutA(theDC :HDC; nXStart, nYStart :integer; toOptions : Lon
gint; rect : PRect;
lpStr :PAnsiChar; nCount :Longint; Dx: PInteger):BOOL;
stdcall;
var dwBytes, dwCallingProc : DWORD; 答案補充 pOldExtTextOut : _ExtTextOutA;
hMoleGDI : THandle;
poOri, poDC, poText, poMouse : TPoint;
Size : TSize;
begin
UnWiseSpy;
GetWindowThreadProcessID(pShMem^.hHookWnd, @dwCallingProc);
try
if pShMem^.bCanSpyNow and (dwCallingProc <> pShMem^.hProc) then
begin
dwBytes := Min(nCount, MaxStringLen);
CopyMemory(@(pShMem^.fStrExtTextOutA), lpStr, dwBytes);
//Get lpStr Content
//The following codes for get the right text 答案補充 GetDCOrgEx(theDC, poOri);
// 取得本窗口設備相關坐標原點的全局邏輯坐標
poDC.x := nXStart;
poDC.y := nYStart;
//
LPToDP(theDC, poDC, 1);
//全局邏輯坐標轉化為設備相關坐標
GetCursorPos(poMouse);
poText.x := poDC.x + poOri.x;
poText.y := poDC.y + poOri.y;
if (GetTextAlign(theDC) and TA_UPDATECP) <> 0 then 答案補充 begin
GetCurrentPositionEx(theDC, @poOri);
poText.x := poText.x + poOri.x;
poText.y := poText.y + poOri.y;
end;
GetTextExtentPoint(theDC, lpStr, nCount, Size);
// 取得要輸出的字元串的實際顯示大小
if (poMouse.x >= poText.x) and (poMouse.x <= poText.x + Size.cx) and
(poMouse.y >= poText.y) and (poMouse.y <= poText.y + Size.cy) then
begin
pShMem^.bCanSpyNow := False;
pShMem^.nTimePassed := -1;
end; 答案補充 pShMem^.fStrExtTextOutA[dwBytes] := Chr(0);
FlushViewOfFile(pShMem, 0);
if dwCallingProc <> pShMem^.hProc then
PostMessage(pShMem^.hProcWnd, WM_MOUSEPT, 2, 2);
end;
if (dwCallingProc = pShMem^.hProc) or pShMem^.bHookExtTextOutA then
begin
hMoleGDI := GetMoleHandle(PChar('GDI32'));
@pOldExtTextOut := GetProcAddress(hMoleGDI, PChar('ExtTextOutA')); 答案補充 Result := pOldExtTextOut(theDC, nXStart, nYStart, toOptions, rect, lpS
tr, nCount, Dx);
end else
Result := True;
except
Result := False;
end;
SpyInstalled := True;
InstallSpy;
end;
H. 急,求即時預覽源碼,類似於Google搜索,將滑鼠放在上面,右面出現預覽頁面!
看這個www.yangsh.com 你隨便搜索進入頁面。然後滑鼠落在預覽上面。就跟google差不多了。當然要一模一樣就修改代碼就OK了。 很牛B吧
I. 關於金山詞霸對詞條的獲取方式 它是怎麼實現任何一個顯示出來的詞語都可以捕捉到
詞霸有個插件Xdict32.api,在安裝的時候會加入到被取詞軟體目錄下,能夠截取目標參數信息。
內部編寫的源碼還得去找找,找到了發消息給你
J. 能不能用C#做屏幕取詞有源碼嗎
可以使用Tesseract-OCR