• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            幽幽
             
            posts - 51,  comments - 28,  trackbacks - 0
             1typedef ULONG (WINAPI *PFNNtUnmapViewOfSection)( IN HANDLE ProcessHandle,IN PVOID BaseAddress );
             2
             3BOOL UnmapViewOfModule ( DWORD dwProcessId, LPVOID lpBaseAddr )
             4{
             5    HMODULE hModule = GetModuleHandle ( L"ntdll.dll" ) ;
             6    if ( hModule == NULL )
             7        hModule = LoadLibrary ( L"ntdll.dll" ) ;
             8
             9    PFNNtUnmapViewOfSection pfnNtUnmapViewOfSection = (PFNNtUnmapViewOfSection)GetProcAddress ( hModule, "NtUnmapViewOfSection" ) ;
            10    
            11    HANDLE hProcess = OpenProcess ( PROCESS_ALL_ACCESS, TRUE, dwProcessId ) ;
            12    ULONG    ret = pfnNtUnmapViewOfSection ( hProcess, lpBaseAddr ) ;
            13    CloseHandle ( hProcess ) ;
            14    return ret ? FALSE : TRUE;
            15}

            16
            17
            posted @ 2009-02-21 22:32 幽幽 閱讀(485) | 評論 (0)編輯 收藏
            本文轉(zhuǎn)自: http://hi.baidu.com/csuhkx/blog/item/267418d3614cf9013bf3cf55.html

            這篇文章是翻譯MSDN上一篇叫《Heap: Pleasures and Pains》的文章的

            Murali R. Krishnan
            Microsoft Corporation

            1999 年 2 月

            摘要: 討論常見的堆性能問題以及如何防范它們。(共 9 頁)

            前言

            您是否是動(dòng)態(tài)分配的 C/C++ 對象忠實(shí)且幸運(yùn)的用戶?您是否在模塊間的往返通信中頻繁地使用了“自動(dòng)化”?您的程序是否因堆分配而運(yùn)行起來很慢?不僅僅您遇到這樣的問題。幾乎所有項(xiàng)目遲早都會(huì)遇到堆問題。大家都想說,“我的代碼真正好,只是堆太慢”。那只是部分正確。更深入理解堆及其用法、以及會(huì)發(fā)生什么問題,是很有用的。

            什么是堆?

            (如果您已經(jīng)知道什么是堆,可以跳到“什么是常見的堆性能問題?”部分)

            在程序中,使用堆來動(dòng)態(tài)分配和釋放對象。在下列情況下,調(diào)用堆操作:

            1. 事先不知道程序所需對象的數(shù)量和大小。

            2. 對象太大而不適合堆棧分配程序。

            堆使用了在運(yùn)行時(shí)分配給代碼和堆棧的內(nèi)存之外的部分內(nèi)存。下圖給出了堆分配程序的不同層。

            GlobalAlloc/GlobalFree:Microsoft Win32 堆調(diào)用,這些調(diào)用直接與每個(gè)進(jìn)程的默認(rèn)堆進(jìn)行對話。

            LocalAlloc/LocalFree:Win32 堆調(diào)用(為了與 Microsoft Windows NT 兼容),這些調(diào)用直接與每個(gè)進(jìn)程的默認(rèn)堆進(jìn)行對話。

            COM 的 IMalloc 分配程序(或 CoTaskMemAlloc / CoTaskMemFree):函數(shù)使用每個(gè)進(jìn)程的默認(rèn)堆。自動(dòng)化程序使用“組件對象模型 (COM)”的分配程序,而申請的程序使用每個(gè)進(jìn)程堆。

            C/C++ 運(yùn)行時(shí) (CRT) 分配程序:提供了 malloc()free() 以及 newdelete 操作符。如 Microsoft Visual Basic 和 Java 等語言也提供了新的操作符并使用垃圾收集來代替堆。CRT 創(chuàng)建自己的私有堆,駐留在 Win32 堆的頂部。

            Windows NT 中,Win32 堆是 Windows NT 運(yùn)行時(shí)分配程序周圍的薄層。所有 API 轉(zhuǎn)發(fā)它們的請求給 NTDLL。

            Windows NT 運(yùn)行時(shí)分配程序提供 Windows NT 內(nèi)的核心堆分配程序。它由具有 128 個(gè)大小從 8 到 1,024 字節(jié)的空閑列表的前端分配程序組成。后端分配程序使用虛擬內(nèi)存來保留和提交頁。

            在圖表的底部是“虛擬內(nèi)存分配程序”,操作系統(tǒng)使用它來保留和提交頁。所有分配程序使用虛擬內(nèi)存進(jìn)行數(shù)據(jù)的存取。

            分配和釋放塊不就那么簡單嗎?為何花費(fèi)這么長時(shí)間?

            堆實(shí)現(xiàn)的注意事項(xiàng)

            傳統(tǒng)上,操作系統(tǒng)和運(yùn)行時(shí)庫是與堆的實(shí)現(xiàn)共存的。在一個(gè)進(jìn)程的開始,操作系統(tǒng)創(chuàng)建一個(gè)默認(rèn)堆,叫做“進(jìn)程堆”。如果沒有其他堆可使用,則塊的分配使用“進(jìn)程堆”。語言運(yùn)行時(shí)也能在進(jìn)程內(nèi)創(chuàng)建單獨(dú)的堆。(例如,C 運(yùn)行時(shí)創(chuàng)建它自己的堆。)除這些專用的堆外,應(yīng)用程序或許多已載入的動(dòng)態(tài)鏈接庫 (DLL) 之一可以創(chuàng)建和使用單獨(dú)的堆。Win32 提供一整套 API 來創(chuàng)建和使用私有堆。有關(guān)堆函數(shù)(英文)的詳盡指導(dǎo),請參見 MSDN。

            當(dāng)應(yīng)用程序或 DLL 創(chuàng)建私有堆時(shí),這些堆存在于進(jìn)程空間,并且在進(jìn)程內(nèi)是可訪問的。從給定堆分配的數(shù)據(jù)將在同一個(gè)堆上釋放。(不能從一個(gè)堆分配而在另一個(gè)堆釋放。)

            在所有虛擬內(nèi)存系統(tǒng)中,堆駐留在操作系統(tǒng)的“虛擬內(nèi)存管理器”的頂部。語言運(yùn)行時(shí)堆也駐留在虛擬內(nèi)存頂部。某些情況下,這些堆是操作系統(tǒng)堆中的層,而語言運(yùn)行時(shí)堆則通過大塊的分配來執(zhí)行自己的內(nèi)存管理。不使用操作系統(tǒng)堆,而使用虛擬內(nèi)存函數(shù)更利于堆的分配和塊的使用。

            典型的堆實(shí)現(xiàn)由前、后端分配程序組成。前端分配程序維持固定大小塊的空閑列表。對于一次分配調(diào)用,堆嘗試從前端列表找到一個(gè)自由塊。如果失敗,堆被迫從后端(保留和提交虛擬內(nèi)存)分配一個(gè)大塊來滿足請求。通用的實(shí)現(xiàn)有每塊分配的開銷,這將耗費(fèi)執(zhí)行周期,也減少了可使用的存儲(chǔ)空間。

            Knowledge Base 文章 Q10758,“用 calloc() 和 malloc() 管理內(nèi)存” (搜索文章編號(hào)), 包含了有關(guān)這些主題的更多背景知識(shí)。另外,有關(guān)堆實(shí)現(xiàn)和設(shè)計(jì)的詳細(xì)討論也可在下列著作中找到:“Dynamic Storage Allocation: A Survey and Critical Review”,作者 Paul R. Wilson、Mark S. Johnstone、Michael Neely 和 David Boles;“International Workshop on Memory Management”, 作者 Kinross, Scotland, UK, 1995 年 9 月(http://www.cs.utexas.edu/users/oops/papers.html)(英文)。

            Windows NT 的實(shí)現(xiàn)(Windows NT 版本 4.0 和更新版本) 使用了 127 個(gè)大小從 8 到 1,024 字節(jié)的 8 字節(jié)對齊塊空閑列表和一個(gè)“大塊”列表。“大塊”列表(空閑列表[0]) 保存大于 1,024 字節(jié)的塊。空閑列表容納了用雙向鏈表鏈接在一起的對象。默認(rèn)情況下,“進(jìn)程堆”執(zhí)行收集操作。(收集是將相鄰空閑塊合并成一個(gè)大塊的操作。)收集耗費(fèi)了額外的周期,但減少了堆塊的內(nèi)部碎片。

            單一全局鎖保護(hù)堆,防止多線程式的使用。(請參見“Server Performance and Scalability Killers”中的第一個(gè)注意事項(xiàng), George Reilly 所著,在 “MSDN Online Web Workshop”上(站點(diǎn):http://msdn.microsoft.com/workshop/server/iis/tencom.asp(英文)。)單一全局鎖本質(zhì)上是用來保護(hù)堆數(shù)據(jù)結(jié)構(gòu),防止跨多線程的隨機(jī)存取。若堆操作太頻繁,單一全局鎖會(huì)對性能有不利的影響。

            什么是常見的堆性能問題?

            以下是您使用堆時(shí)會(huì)遇到的最常見問題:

            • 分配操作造成的速度減慢。光分配就耗費(fèi)很長時(shí)間。最可能導(dǎo)致運(yùn)行速度減慢原因是空閑列表沒有塊,所以運(yùn)行時(shí)分配程序代碼會(huì)耗費(fèi)周期尋找較大的空閑塊,或從后端分配程序分配新塊。

            • 釋放操作造成的速度減慢。釋放操作耗費(fèi)較多周期,主要是啟用了收集操作。收集期間,每個(gè)釋放操作“查找”它的相鄰塊,取出它們并構(gòu)造成較大塊,然后再把此較大塊插入空閑列表。在查找期間,內(nèi)存可能會(huì)隨機(jī)碰到,從而導(dǎo)致高速緩存不能命中,性能降低。

            • 堆競爭造成的速度減慢。當(dāng)兩個(gè)或多個(gè)線程同時(shí)訪問數(shù)據(jù),而且一個(gè)線程繼續(xù)進(jìn)行之前必須等待另一個(gè)線程完成時(shí)就發(fā)生競爭。競爭總是導(dǎo)致麻煩;這也是目前多處理器系統(tǒng)遇到的最大問題。當(dāng)大量使用內(nèi)存塊的應(yīng)用程序或 DLL 以多線程方式運(yùn)行(或運(yùn)行于多處理器系統(tǒng)上)時(shí)將導(dǎo)致速度減慢。單一鎖定的使用—常用的解決方案—意味著使用堆的所有操作是序列化的。當(dāng)?shù)却i定時(shí)序列化會(huì)引起線程切換上下文。可以想象交叉路口閃爍的紅燈處走走停停導(dǎo)致的速度減慢。

              競爭通常會(huì)導(dǎo)致線程和進(jìn)程的上下文切換。上下文切換的開銷是很大的,但開銷更大的是數(shù)據(jù)從處理器高速緩存中丟失,以及后來線程復(fù)活時(shí)的數(shù)據(jù)重建。

            • 堆破壞造成的速度減慢。造成堆破壞的原因是應(yīng)用程序?qū)Χ褖K的不正確使用。通常情形包括釋放已釋放的堆塊或使用已釋放的堆塊,以及塊的越界重寫等明顯問題。(破壞不在本文討論范圍之內(nèi)。有關(guān)內(nèi)存重寫和泄漏等其他細(xì)節(jié),請參見 Microsoft Visual C++(R) 調(diào)試文檔 。)

            • 頻繁的分配和重分配造成的速度減慢。這是使用腳本語言時(shí)非常普遍的現(xiàn)象。如字符串被反復(fù)分配,隨重分配增長和釋放。不要這樣做,如果可能,盡量分配大字符串和使用緩沖區(qū)。另一種方法就是盡量少用連接操作。

            競爭是在分配和釋放操作中導(dǎo)致速度減慢的問題。理想情況下,希望使用沒有競爭和快速分配/釋放的堆。可惜,現(xiàn)在還沒有這樣的通用堆,也許將來會(huì)有。

            在所有的服務(wù)器系統(tǒng)中(如 IIS、MSProxy、DatabaseStacks、網(wǎng)絡(luò)服務(wù)器、 Exchange 和其他), 堆鎖定實(shí)在是個(gè)大瓶頸。處理器數(shù)越多,競爭就越會(huì)惡化。

            盡量減少堆的使用

            現(xiàn)在您明白使用堆時(shí)存在的問題了,難道您不想擁有能解決這些問題的超級魔棒嗎?我可希望有。但沒有魔法能使堆運(yùn)行加快—因此不要期望在產(chǎn)品出貨之前的最后一星期能夠大為改觀。如果提前規(guī)劃堆策略,情況將會(huì)大大好轉(zhuǎn)。調(diào)整使用堆的方法,減少對堆的操作是提高性能的良方。

            如何減少使用堆操作?通過利用數(shù)據(jù)結(jié)構(gòu)內(nèi)的位置可減少堆操作的次數(shù)。請考慮下列實(shí)例:

            struct ObjectA {
                // objectA 的數(shù)據(jù)
            }
            struct ObjectB {
                // objectB 的數(shù)據(jù)
            }
            // 同時(shí)使用 objectA 和 objectB
            //
            // 使用指針
            //
            struct ObjectB {
                struct ObjectA * pObjA;
                // objectB 的數(shù)據(jù)
            }
            //
            // 使用嵌入
            //
            struct ObjectB {
                struct ObjectA pObjA;
                // objectB 的數(shù)據(jù)
            }
            //
            // 集合 – 在另一對象內(nèi)使用 objectA 和 objectB
            //
            struct ObjectX {
                struct ObjectA   objA;
                struct ObjectB   objB;
            }
            
            1. 避免使用指針關(guān)聯(lián)兩個(gè)數(shù)據(jù)結(jié)構(gòu)。如果使用指針關(guān)聯(lián)兩個(gè)數(shù)據(jù)結(jié)構(gòu),前面實(shí)例中的對象 A 和 B 將被分別分配和釋放。這會(huì)增加額外開銷—我們要避免這種做法。

            2. 把帶指針的子對象嵌入父對象。當(dāng)對象中有指針時(shí),則意味著對象中有動(dòng)態(tài)元素(百分之八十)和沒有引用的新位置。嵌入增加了位置從而減少了進(jìn)一步分配/釋放的需求。這將提高應(yīng)用程序的性能。

            3. 合并小對象形成大對象(聚合)。聚合減少分配和釋放的塊的數(shù)量。如果有幾個(gè)開發(fā)者,各自開發(fā)設(shè)計(jì)的不同部分,則最終會(huì)有許多小對象需要合并。集成的挑戰(zhàn)就是要找到正確的聚合邊界。

            4. 內(nèi)聯(lián)緩沖區(qū)能夠滿足百分之八十的需要(aka 80-20 規(guī)則)。個(gè)別情況下,需要內(nèi)存緩沖區(qū)來保存字符串/二進(jìn)制數(shù)據(jù),但事先不知道總字節(jié)數(shù)。估計(jì)并內(nèi)聯(lián)一個(gè)大小能滿足百分之八十需要的緩沖區(qū)。對剩余的百分之二十,可以分配一個(gè)新的緩沖區(qū)和指向這個(gè)緩沖區(qū)的指針。這樣,就減少分配和釋放調(diào)用并增加數(shù)據(jù)的位置空間,從根本上提高代碼的性能。

            5. 在塊中分配對象(塊化)。塊化是以組的方式一次分配多個(gè)對象的方法。如果對列表的項(xiàng)連續(xù)跟蹤,例如對一個(gè) {名稱,值} 對的列表,有兩種選擇:選擇一是為每一個(gè)“名稱-值”對分配一個(gè)節(jié)點(diǎn);選擇二是分配一個(gè)能容納(如五個(gè))“名稱-值”對的結(jié)構(gòu)。例如,一般情況下,如果存儲(chǔ)四對,就可減少節(jié)點(diǎn)的數(shù)量,如果需要額外的空間數(shù)量,則使用附加的鏈表指針。

              塊化是友好的處理器高速緩存,特別是對于 L1-高速緩存,因?yàn)樗峁┝嗽黾拥奈恢?—不用說對于塊分配,很多數(shù)據(jù)塊會(huì)在同一個(gè)虛擬頁中。

            6. 正確使用 _amblksiz。C 運(yùn)行時(shí) (CRT) 有它的自定義前端分配程序,該分配程序從后端(Win32 堆)分配大小為 _amblksiz 的塊。將 _amblksiz 設(shè)置為較高的值能潛在地減少對后端的調(diào)用次數(shù)。這只對廣泛使用 CRT 的程序適用。

            使用上述技術(shù)將獲得的好處會(huì)因?qū)ο箢愋汀⒋笮〖肮ぷ髁慷兴煌5偰茉谛阅芎涂缮s性方面有所收獲。另一方面,代碼會(huì)有點(diǎn)特殊,但如果經(jīng)過深思熟慮,代碼還是很容易管理的。

            其他提高性能的技術(shù)

            下面是一些提高速度的技術(shù):

            1. 使用 Windows NT5 堆

              由于幾個(gè)同事的努力和辛勤工作,1998 年初 Microsoft Windows(R) 2000 中有了幾個(gè)重大改進(jìn):

              • 改進(jìn)了堆代碼內(nèi)的鎖定。堆代碼對每堆一個(gè)鎖。全局鎖保護(hù)堆數(shù)據(jù)結(jié)構(gòu),防止多線程式的使用。但不幸的是,在高通信量的情況下,堆仍受困于全局鎖,導(dǎo)致高競爭和低性能。Windows 2000 中,鎖內(nèi)代碼的臨界區(qū)將競爭的可能性減到最小,從而提高了可伸縮性。

              • 使用 “Lookaside”列表。堆數(shù)據(jù)結(jié)構(gòu)對塊的所有空閑項(xiàng)使用了大小在 8 到 1,024 字節(jié)(以 8-字節(jié)遞增)的快速高速緩存。快速高速緩存最初保護(hù)在全局鎖內(nèi)。現(xiàn)在,使用 lookaside 列表來訪問這些快速高速緩存空閑列表。這些列表不要求鎖定,而是使用 64 位的互鎖操作,因此提高了性能。

              • 內(nèi)部數(shù)據(jù)結(jié)構(gòu)算法也得到改進(jìn)。

              這些改進(jìn)避免了對分配高速緩存的需求,但不排除其他的優(yōu)化。使用 Windows NT5 堆評估您的代碼;它對小于 1,024 字節(jié) (1 KB) 的塊(來自前端分配程序的塊)是最佳的。GlobalAlloc()LocalAlloc() 建立在同一堆上,是存取每個(gè)進(jìn)程堆的通用機(jī)制。如果希望獲得高的局部性能,則使用 Heap(R) API 來存取每個(gè)進(jìn)程堆,或?yàn)榉峙洳僮鲃?chuàng)建自己的堆。如果需要對大塊操作,也可以直接使用 VirtualAlloc() / VirtualFree() 操作。

              上述改進(jìn)已在 Windows 2000 beta 2 和 Windows NT 4.0 SP4 中使用。改進(jìn)后,堆鎖的競爭率顯著降低。這使所有 Win32 堆的直接用戶受益。CRT 堆建立于 Win32 堆的頂部,但它使用自己的小塊堆,因而不能從 Windows NT 改進(jìn)中受益。(Visual C++ 版本 6.0 也有改進(jìn)的堆分配程序。)

            2. 使用分配高速緩存

              分配高速緩存允許高速緩存分配的塊,以便將來重用。這能夠減少對進(jìn)程堆(或全局堆)的分配/釋放調(diào)用的次數(shù),也允許最大限度的重用曾經(jīng)分配的塊。另外,分配高速緩存允許收集統(tǒng)計(jì)信息,以便較好地理解對象在較高層次上的使用。

              典型地,自定義堆分配程序在進(jìn)程堆的頂部實(shí)現(xiàn)。自定義堆分配程序與系統(tǒng)堆的行為很相似。主要的差別是它在進(jìn)程堆的頂部為分配的對象提供高速緩存。高速緩存設(shè)計(jì)成一套固定大小(如 32 字節(jié)、64 字節(jié)、128 字節(jié)等)。這一個(gè)很好的策略,但這種自定義堆分配程序丟失與分配和釋放的對象相關(guān)的“語義信息”。

              與自定義堆分配程序相反,“分配高速緩存”作為每類分配高速緩存來實(shí)現(xiàn)。除能夠提供自定義堆分配程序的所有好處之外,它們還能夠保留大量語義信息。每個(gè)分配高速緩存處理程序與一個(gè)目標(biāo)二進(jìn)制對象關(guān)聯(lián)。它能夠使用一套參數(shù)進(jìn)行初始化,這些參數(shù)表示并發(fā)級別、對象大小和保持在空閑列表中的元素的數(shù)量等。分配高速緩存處理程序?qū)ο缶S持自己的私有空閑實(shí)體池(不超過指定的閥值)并使用私有保護(hù)鎖。合在一起,分配高速緩存和私有鎖減少了與主系統(tǒng)堆的通信量,因而提供了增加的并發(fā)、最大限度的重用和較高的可伸縮性。

              需要使用清理程序來定期檢查所有分配高速緩存處理程序的活動(dòng)情況并回收未用的資源。如果發(fā)現(xiàn)沒有活動(dòng),將釋放分配對象的池,從而提高性能。

              可以審核每個(gè)分配/釋放活動(dòng)。第一級信息包括對象、分配和釋放調(diào)用的總數(shù)。通過查看它們的統(tǒng)計(jì)信息可以得出各個(gè)對象之間的語義關(guān)系。利用以上介紹的許多技術(shù)之一,這種關(guān)系可以用來減少內(nèi)存分配。

              分配高速緩存也起到了調(diào)試助手的作用,幫助您跟蹤沒有完全清除的對象數(shù)量。通過查看動(dòng)態(tài)堆棧返回蹤跡和除沒有清除的對象之外的簽名,甚至能夠找到確切的失敗的調(diào)用者。

            3. MP 堆

              MP 堆是對多處理器友好的分布式分配的程序包,在 Win32 SDK(Windows NT 4.0 和更新版本)中可以得到。最初由 JVert 實(shí)現(xiàn),此處堆抽象建立在 Win32 堆程序包的頂部。MP 堆創(chuàng)建多個(gè) Win32 堆,并試圖將分配調(diào)用分布到不同堆,以減少在所有單一鎖上的競爭。

              本程序包是好的步驟 —一種改進(jìn)的 MP-友好的自定義堆分配程序。但是,它不提供語義信息和缺乏統(tǒng)計(jì)功能。通常將 MP 堆作為 SDK 庫來使用。如果使用這個(gè) SDK 創(chuàng)建可重用組件,您將大大受益。但是,如果在每個(gè) DLL 中建立這個(gè) SDK 庫,將增加工作設(shè)置。

            4. 重新思考算法和數(shù)據(jù)結(jié)構(gòu)

              要在多處理器機(jī)器上伸縮,則算法、實(shí)現(xiàn)、數(shù)據(jù)結(jié)構(gòu)和硬件必須動(dòng)態(tài)伸縮。請看最經(jīng)常分配和釋放的數(shù)據(jù)結(jié)構(gòu)。試問,“我能用不同的數(shù)據(jù)結(jié)構(gòu)完成此工作嗎?”例如,如果在應(yīng)用程序初始化時(shí)加載了只讀項(xiàng)的列表,這個(gè)列表不必是線性鏈接的列表。如果是動(dòng)態(tài)分配的數(shù)組就非常好。動(dòng)態(tài)分配的數(shù)組將減少內(nèi)存中的堆塊和碎片,從而增強(qiáng)性能。

              減少需要的小對象的數(shù)量減少堆分配程序的負(fù)載。例如,我們在服務(wù)器的關(guān)鍵處理路徑上使用五個(gè)不同的對象,每個(gè)對象單獨(dú)分配和釋放。一起高速緩存這些對象,把堆調(diào)用從五個(gè)減少到一個(gè),顯著減少了堆的負(fù)載,特別當(dāng)每秒鐘處理 1,000 個(gè)以上的請求時(shí)。

              如果大量使用“Automation”結(jié)構(gòu),請考慮從主線代碼中刪除“Automation BSTR”,或至少避免重復(fù)的 BSTR 操作。(BSTR 連接導(dǎo)致過多的重分配和分配/釋放操作。)

            摘要

            對所有平臺(tái)往往都存在堆實(shí)現(xiàn),因此有巨大的開銷。每個(gè)單獨(dú)代碼都有特定的要求,但設(shè)計(jì)能采用本文討論的基本理論來減少堆之間的相互作用。

            1. 評價(jià)您的代碼中堆的使用。

            2. 改進(jìn)您的代碼,以使用較少的堆調(diào)用:分析關(guān)鍵路徑和固定數(shù)據(jù)結(jié)構(gòu)。

            3. 在實(shí)現(xiàn)自定義的包裝程序之前使用量化堆調(diào)用成本的方法。

            4. 如果對性能不滿意,請要求 OS 組改進(jìn)堆。更多這類請求意味著對改進(jìn)堆的更多關(guān)注。

            5. 要求 C 運(yùn)行時(shí)組針對 OS 所提供的堆制作小巧的分配包裝程序。隨著 OS 堆的改進(jìn),C 運(yùn)行時(shí)堆調(diào)用的成本將減小。

            6. 操作系統(tǒng)(Windows NT 家族)正在不斷改進(jìn)堆。請隨時(shí)關(guān)注和利用這些改進(jìn)。

            Murali Krishnan 是 Internet Information Server (IIS) 組的首席軟件設(shè)計(jì)工程師。從 1.0 版本開始他就設(shè)計(jì) IIS,并成功發(fā)行了 1.0 版本到 4.0 版本。Murali 組織并領(lǐng)導(dǎo) IIS 性能組三年 (1995-1998), 從一開始就影響 IIS 性能。他擁有威斯康星州 Madison 大學(xué)的 M.S.和印度 Anna 大學(xué)的 B.S.。工作之外,他喜歡閱讀、打排球和家庭烹飪。


            posted @ 2009-02-03 08:49 幽幽 閱讀(495) | 評論 (0)編輯 收藏

            現(xiàn)在是5:14, 外面正在下雨, 喜歡下雨, 因?yàn)槁牭洁栲枧九镜挠曷? 我總能靜下心來,
            是該靜下心來好好想想了, 最近總是很浮躁, 靜不下心來, 是該靜下心來看看書寫寫
            代碼了.....

            posted @ 2009-02-03 05:18 幽幽 閱讀(216) | 評論 (0)編輯 收藏

            導(dǎo)讀:習(xí)慣的力量是驚人的。習(xí)慣能載著你走向成功,也能馱著你滑向失敗。如何選擇,完全取決于你自己。

            1.習(xí)慣的力量:35歲以前養(yǎng)成好習(xí)慣

            你想成功嗎?那就及早培養(yǎng)有利于成功的好習(xí)慣。

            習(xí)慣的力量是驚人的,35歲以前養(yǎng)成的習(xí)慣決定著你是否成功。

            有這樣一個(gè)寓言故事:

            一位沒有繼承人的富豪死后將自己的一大筆遺產(chǎn)贈(zèng)送給遠(yuǎn)房的一位親戚,這位親戚是一個(gè)常年靠乞討為生的乞丐。這名接受遺產(chǎn)的乞丐立即身價(jià)一變,成了百萬富翁。新聞?dòng)浾弑銇聿稍L這名幸運(yùn)的乞丐:"你繼承了遺產(chǎn)之后,你想做的第一件事是什么?"乞丐回答說:"我要買一只好一點(diǎn)的碗和一根結(jié)實(shí)的木棍,這樣我以后出去討飯時(shí)方便一些。"

            可見,習(xí)慣對我們有著絕大的影響,因?yàn)樗且回灥模诓恢挥X中,經(jīng)年累月地影響著我們的行為,影響著我們的效率,左右著我們的成敗。

            一個(gè)人一天的行為中,大約只有5%是屬于非習(xí)慣性的,而剩下的95%的行為都是習(xí)慣性的。即便是打破常規(guī)的創(chuàng)新,最終可以演變成為習(xí)慣性的創(chuàng)新。

            根據(jù)行為心理學(xué)的研究結(jié)果:3周以上的重復(fù)會(huì)形成習(xí)慣;3個(gè)月以上的重復(fù)會(huì)形成穩(wěn)定的習(xí)慣,即同一個(gè)動(dòng)作,重復(fù)3周就會(huì)變成習(xí)慣性動(dòng)作,形成穩(wěn)定的習(xí)慣。

            亞里士多德說:"人的行為總是一再重復(fù)。因此,卓越不是單一的舉動(dòng),而是習(xí)慣。""人的行為總是一再重復(fù)。因此,卓越不是單一的舉動(dòng),而是習(xí)慣。"所以,在實(shí)現(xiàn)成功的過程中,除了要不斷激發(fā)自己的成功欲望,要有信心、有熱情、有意志、有毅力等之外,還應(yīng)該搭上習(xí)慣這一成功的快車,實(shí)現(xiàn)自己的目標(biāo)。

            有個(gè)動(dòng)物學(xué)家做了一個(gè)實(shí)驗(yàn):他將一群跳蚤放入實(shí)驗(yàn)用的大量杯里,上面蓋上一片透明的玻璃。跳蚤習(xí)性愛跳,于是很多跳蚤都撞上了蓋上的玻璃,不斷地發(fā)叮叮冬冬的聲音。過了一陣子,動(dòng)物學(xué)家將玻璃片拿開,發(fā)現(xiàn)竟然所有跳蚤依然在跳,只是都已經(jīng)將跳的高度保持在接近玻璃即止,以避免撞到頭。結(jié)果竟然沒有一只跳蚤能跳出來--依它們的能力不是跳不出來,只是它們已經(jīng)適應(yīng)了環(huán)境。

            后來,那位動(dòng)物學(xué)家就在量杯下放了一個(gè)酒精燈并且點(diǎn)燃了火。不到五分鐘,量杯燒熱了,所有跳蚤自然發(fā)揮求生的本能,每只跳蚤再也不管頭是否會(huì)撞痛(因?yàn)樗鼈円詾檫€有玻璃罩),全部都跳出量杯以外。這個(gè)試驗(yàn)證明,跳蚤會(huì)為了適應(yīng)環(huán)境,不愿改變習(xí)性,寧愿降低才能、封閉潛能去適應(yīng)。

            我想,人類之于環(huán)境也是如此。人類在適應(yīng)外界大環(huán)境中,又創(chuàng)造出適合于自己的小環(huán)境,然后用習(xí)慣把自己困在自己所創(chuàng)造的環(huán)境中。所以,習(xí)慣決定著你的活動(dòng)空間的大小,也決定著你的成敗。養(yǎng)成好習(xí)慣對于你的成功非常重要。

            心理學(xué)巨匠威廉·詹姆士說:"播下一個(gè)行動(dòng),收獲一種習(xí)慣;播下一種習(xí)慣,收獲一種性格;播下一種性格,收獲一種命運(yùn)。"

            2.35歲以前成功必備的9大習(xí)慣

            好習(xí)慣會(huì)使成功不期而至。我認(rèn)為下面9個(gè)好習(xí)慣是成功必備的:

            (1)積極思維的好習(xí)慣

            有位秀才第三次進(jìn)京趕考,住在一個(gè)經(jīng)常住的店里。考試前兩天他做了三個(gè)夢:第一個(gè)夢是夢到自己在墻上種白菜,第二個(gè)夢是下雨天,他戴了斗笠還打著傘,第三個(gè)夢是夢到跟心愛的表妹脫光了衣服躺在一起,但是背靠著背。臨考之際做此夢,似乎有些深意,秀才第二天去找算命的解夢。算命的一聽,連拍大腿說:"你還是回家吧。你想想,高墻上種菜不是白費(fèi)勁嗎?戴斗笠打雨傘不是多此一舉嗎?跟表妹脫光了衣服躺在一張床上,卻背靠背,不是沒戲嗎?"秀才一聽,心灰意冷,回店收拾包裹準(zhǔn)備回家。店老板非常奇怪,問:"不是明天才考試嗎?今天怎么就打道回府了?"秀才如此這般說了一番,店老板樂了:"唉,我也會(huì)解夢的。我倒覺得,你這次一定能考中。你想想,墻上種菜不是高種嗎?戴斗笠打傘不是雙保險(xiǎn)嗎?跟你表妹脫光了背靠背躺在床上,不是說明你翻身的時(shí)候就要到了嗎?"秀才一聽,更有道理,于是精神振奮地參加考試,居然中了個(gè)探花。

            可見,事物本身并不影響人,人們只受到自己對事物看法的影響,人必須改變被動(dòng)的思維習(xí)慣,養(yǎng)成積極的思維習(xí)慣。

            怎樣才算養(yǎng)成了積極思維的習(xí)慣呢?當(dāng)你在實(shí)現(xiàn)目標(biāo)的過程中,面對具體的工作和任務(wù)時(shí),你的大腦里去掉了"不可能"三個(gè)字,而代之以"我怎樣才能"時(shí),可以說你就養(yǎng)成了積極思維的習(xí)慣了。

            (2)高效工作的好習(xí)慣

            一個(gè)人成功的欲望再強(qiáng)烈,也會(huì)被不利于成功的習(xí)慣所撕碎,而溶入平庸的日常生活中。所以說,思想決定行為,行為形成習(xí)慣,習(xí)慣決定性格,性格決定命運(yùn)。你要想成功,就一定要養(yǎng)成高效率的工作習(xí)慣。

            確定你的工作習(xí)慣是否有效率,是否有利于成功,我覺得可以用這個(gè)標(biāo)準(zhǔn)來檢驗(yàn):即在檢省自己工作的時(shí)候,你是否為未完成工作而感到憂慮,即有焦灼感。如果你應(yīng)該做的事情而沒有做,或做而未做完,并經(jīng)常為此而感到焦灼,那就證明你需要改變工作習(xí)慣,找到并養(yǎng)成一種高效率的工作習(xí)慣。

            高效工作從辦公室開始:

            1)了解你每天的精力充沛期。通常人們在早晨9點(diǎn)左右工作效率最高,可以把最困難的工作放到這時(shí)來完成。

            2)每天集中一、兩個(gè)小時(shí)來處理手頭緊急的工作,不接電話、不開會(huì)、不受打擾。這樣可以事半功倍。

            3)立刻回復(fù)重要的郵件,將不重要的丟棄。若任它們積累成堆,反而更費(fèi)時(shí)間。

            4)做個(gè)任務(wù)清單,將所有的項(xiàng)目和約定記在效率手冊中。手頭一定要帶著效率手冊以幫助自己按計(jì)劃行事。一個(gè)人一天的行為中,大約只有5%是屬于非習(xí)慣性的,而剩下的95%的行為都是習(xí)慣性的。

            5)學(xué)會(huì)高效地利用零碎時(shí)間,用來讀點(diǎn)東西或是構(gòu)思一個(gè)文件,不要發(fā)呆或做白日夢。

            6)減少回電話的時(shí)間。如果你需要傳遞的只是一個(gè)信息,不妨發(fā)個(gè)手機(jī)短信。

            7)對可能打來的電話做到心中有數(shù),這樣在你接到所期待的電話后便可迅速找到所需要的各種材料,不必當(dāng)時(shí)亂翻亂找。

            8)學(xué)習(xí)上網(wǎng)高效搜尋的技能,以節(jié)省上網(wǎng)查詢的時(shí)間。把你經(jīng)常要瀏覽的網(wǎng)站收集起來以便隨時(shí)找到。

            9)用國際互聯(lián)網(wǎng)簡化商業(yè)旅行的安排。多數(shù)飯店和航線可以網(wǎng)上查詢和預(yù)訂。

            10)只要情況允許就可委派別人分擔(dān)工作。事必躬親會(huì)使自己疲憊不堪,而且永遠(yuǎn)也做不完。不妨請同事幫忙,或讓助手更努力地投入。

            11)做靈活的日程安排,當(dāng)你需要時(shí)便可以忙中偷閑。例如,在中午加班,然后早一小時(shí)離開辦公室去健身,或是每天工作10個(gè)小時(shí),然后用星期五來赴約會(huì)、看醫(yī)生。

            12)在離開辦公室之前開列次日工作的清單,這樣第二天早晨一來便可以全力以赴。

            計(jì)劃習(xí)慣,就等于計(jì)劃成功。

            凡事制定計(jì)劃有個(gè)名叫約翰·戈達(dá)德的美國人,當(dāng)他15歲的時(shí)候,就把自己一生要做的事情列了一份清單,被稱做"生命清單"。在這份排列有序的清單中,他給自己所要攻克的127個(gè)具體目標(biāo)。比如,探索尼羅河、攀登喜馬拉雅山、讀完莎士比亞的著作、寫一本書等。在44年后,他以超人的毅力和非凡的勇氣,在與命運(yùn)的艱苦抗?fàn)幹校K于按計(jì)劃,一步一步地實(shí)現(xiàn)了106個(gè)目標(biāo),成為一名卓有成就的電影制片人、作家和演說家。

            中國有句老話:"吃不窮,喝不窮,沒有計(jì)劃就受窮。"盡量按照自己的目標(biāo),有計(jì)劃地做事,這樣可以提高工作效率,快速實(shí)現(xiàn)目標(biāo)。

            (3)養(yǎng)成鍛煉身體的好習(xí)慣

            增強(qiáng)保健意識(shí)

            計(jì)劃習(xí)慣,就等于計(jì)劃成功。如果你想成就一番事業(yè),你就必須有一個(gè)健康的身體;要想身體健康,首先要有保健意識(shí)。

            我認(rèn)識(shí)一個(gè)大學(xué)教師,身體一直很健康。早些時(shí)候,我們經(jīng)常在一起玩。在談及各人身體狀況時(shí),他說腎部偶爾有輕微不適的感覺。我們曾勸他去醫(yī)院檢查一下,但他自恃身體健康,不以為意。直至后來感覺比較疼痛,其愛人才強(qiáng)迫他去檢查。診斷結(jié)果是晚期腎癌。雖經(jīng)手術(shù)化療的等治療措施,但終未能保住生命,死時(shí)才39歲。此前,他曾因?qū)W校分房、評職稱不如意,心情一直抑郁,他的病和情緒有關(guān),但如果他保健意識(shí)強(qiáng),及早去檢查,完全有可以進(jìn)行預(yù)防,消患于未萌。保健意識(shí)差,讓他付出了生命的代價(jià)。

            如何落實(shí)保健意識(shí)呢?一是要有生命第一、健康第一的意識(shí),有了這種意識(shí),你就會(huì)善待自己的身體、自己的心理,而不會(huì)隨意糟踏自己的身體。二是要注意掌握一些相關(guān)的知識(shí)。三是要使自己有一個(gè)對身體應(yīng)變機(jī)制:定期去醫(yī)院做身體檢查;身體覺得有不適的地方,應(yīng)及早去醫(yī)院檢查;在有條件的情況下,可以請一個(gè)保健醫(yī)生,給自己的健康提出忠告。

            ▲有計(jì)劃地鍛煉身體

            鍛煉身體的重要性已經(jīng)越來越多地為人們所接受,但我感覺很多人只停留在重視的意識(shí)階段,而缺乏相應(yīng)的行動(dòng)。我認(rèn)為鍛煉既要針對特定工作姿勢所能引發(fā)的相應(yīng)疾病有目的地進(jìn)行,以防止和治療相應(yīng)的疾病,更要把鍛煉當(dāng)作一種樂趣,養(yǎng)成鍛煉的習(xí)慣。

            因?yàn)楣ぷ餍枰医?jīng)常與客戶打交道,并因處理突發(fā)事情四處奔忙,這在一定程度起到了鍛煉身體的作用,同時(shí),我還每周堅(jiān)持游泳一到兩次,以保證有足夠的精力去做工作,去享受生活。

            身體鍛煉,就像努力爭取成功一樣,貴在堅(jiān)持。

            除上述兩點(diǎn)以,注意飲食結(jié)構(gòu),合理膳食,以及注意養(yǎng)成好的衛(wèi)生習(xí)慣等,都是養(yǎng)成健康習(xí)慣的組成部分。

            總之,健康是"革命"的本錢,是成功的保證。健康成就自己。

            (4)不斷學(xué)習(xí)的好習(xí)慣"萬般皆下品,唯有讀書高"的年代已經(jīng)過去了,但是養(yǎng)成讀書的好習(xí)慣則永遠(yuǎn)不會(huì)過時(shí)。

            哈利·杜魯門是美國歷史上著名的總統(tǒng)。他沒有讀過大學(xué),曾經(jīng)營農(nóng)場,后來經(jīng)營一間布店,經(jīng)歷過多次失敗,當(dāng)他最終擔(dān)任政府職務(wù)時(shí),已年過五旬。但他有一個(gè)好習(xí)慣,就是不斷地閱讀。多年的閱讀,使杜魯門的知識(shí)非常淵博。他一卷一卷地讀了《大不列顛百科全書》以及所有查理斯·狄更斯和維克多·雨果的小說。此外,他還讀過威廉·莎士比亞的所有戲劇和十四行詩等。

            杜魯門的廣泛閱讀和由此得到的豐富知識(shí),使他能帶領(lǐng)美國順利度過第二次世界大戰(zhàn)的結(jié)束時(shí)期,并使這個(gè)國家很快進(jìn)入戰(zhàn)后繁榮。他懂得讀書是成為一流領(lǐng)導(dǎo)人的基礎(chǔ)。讀書還使他在面對各種有爭議的、棘手的問題時(shí),能迅速做出正確的決定。例如,在20世紀(jì)50年代他頂住壓力把人們敬愛的戰(zhàn)爭英雄道格拉斯·麥克阿瑟將軍解職。

            他的信條是:"不是所有的讀書人都是一名領(lǐng)袖,然而每一位領(lǐng)袖必須是讀書人。"

            美國前任總統(tǒng)克林頓說:在19世紀(jì)獲得一小塊土地,就是起家的本錢;而21世紀(jì),人們最指望得到的贈(zèng)品,再也不是土地,而聯(lián)邦政府的獎(jiǎng)學(xué)金。因?yàn)樗麄冎溃莆罩R(shí)就是掌握了一把開啟未來大門的鑰匙。"

            每一個(gè)成功者都是有著良好閱讀習(xí)慣的人。世界500家大企業(yè)的CEO至少每個(gè)星期要翻閱大概30份雜志或圖書資訊,一個(gè)月可以翻閱100多本雜志,一年要翻閱1000本以上。

            世界500家大企業(yè)的CEO至少每個(gè)星期要翻閱大概30份雜志或圖書資訊,一個(gè)月可以翻閱100多本雜志,一年要翻閱1000本以上。如果你每天讀15分鐘,你就有可能在一個(gè)月之內(nèi)讀完一本書。一年你就至少讀過12本書了,10年之后,你會(huì)讀過總共120本書!想想看,每天只需要抽出15分鐘時(shí)間,你就可以輕易地讀完120本書,它可以幫助你在生活的各方面變得更加富有。如果你每天花雙倍的時(shí)間,也就是半個(gè)小時(shí)的話,一年就能讀25本書--10年就是250本!

            我覺得,每一個(gè)想在35歲以前成功的人,每個(gè)月至少要讀一本書,兩本雜志。

            (5)謙虛的好習(xí)慣

            一個(gè)人沒有理由不謙虛。相對于人類的知識(shí)來講,任何博學(xué)者都只能是不及格。

            著名科學(xué)家法拉第晚年,國家準(zhǔn)備授予他爵位,以表彰他在物理、化學(xué)方面的杰出貢獻(xiàn),但被他拒絕了。法拉第退休之后,仍然常去實(shí)驗(yàn)室做一些雜事。一天,一位年輕人來實(shí)驗(yàn)室做實(shí)驗(yàn)。他對正在掃地的法拉第說道:"干這活,他們給你的錢一定不少吧?"老人笑笑,說道:"再多一點(diǎn),我也用得著呀。""那你叫什么名字?老頭?""邁克爾·法拉第。"老人淡淡地回答道。年輕人驚呼起來:"哦,天哪!您就是偉大的法拉第先生!""不",法拉第糾正說,"我是平凡的法拉第。"

            謙虛不僅是一種美德,更是是一種人生的智慧,是一種通過貶低自己來保護(hù)自己的計(jì)謀。

            (6)自制的好習(xí)慣

            任何一個(gè)成功者都有著非凡的自制力。

            三國時(shí)期,蜀相諸葛亮親自率領(lǐng)蜀國大軍北伐曹魏,魏國大將司馬懿采取了閉城休戰(zhàn)、不予理睬的態(tài)度對付諸葛亮。他認(rèn)為,蜀軍遠(yuǎn)道來襲,后援補(bǔ)給必定不足,只要拖延時(shí)日,消耗蜀軍的實(shí)力,一定能抓住良機(jī),戰(zhàn)勝敵人。

            諸葛亮深知司馬懿沉默戰(zhàn)術(shù)的利害,幾次派兵到城下罵陣,企圖激怒魏兵,引誘司馬懿出城決戰(zhàn),但司馬懿一直按兵不動(dòng)。諸葛亮于是用激將法,派人給司馬懿送來一件女人衣裳,并修書一封說:"仲達(dá)不敢出戰(zhàn),跟婦女有什么兩樣。你若是個(gè)知恥的男兒,就出來和蜀軍交戰(zhàn),若不然,你就穿上這件女人的衣服。""士可殺不可辱。"這封充滿侮辱輕視的信,雖然激怒了司馬懿,但并沒使老謀深算的司馬懿改變主意,他強(qiáng)壓怒火穩(wěn)住軍心,耐心等待。

            相持了數(shù)月,諸葛亮不幸病逝軍中,蜀軍群龍無首,悄悄退兵,司馬懿不戰(zhàn)而勝。

            抑制不住情緒的人,往往傷人又傷己如果司馬懿不能忍耐一時(shí)之氣,出城應(yīng)戰(zhàn),那么或許歷史將會(huì)重寫。

            現(xiàn)代社會(huì),人們面臨的誘惑越來越多,如果人們?nèi)狈ψ灾屏Γ敲淳蜁?huì)被誘惑牽著鼻子走,偏離成功的軌道。

            (7)幽默的好習(xí)慣

            有人說,男人需要幽默,就像女人需要一個(gè)漂亮的臉蛋一樣重要。

            男人需要幽默,就像女人需要一個(gè)漂亮的臉蛋一樣重要。美國第16任總統(tǒng)林肯長相丑陋,但他從不忌諱這一點(diǎn),相反,他常常詼諧地拿自己的長相開玩笑。在競選總統(tǒng)時(shí),他的對手攻擊他兩面三刀,搞陰謀詭計(jì)。林肯聽了指著自己的臉說:"讓公眾來評判吧。如果我還有另一張臉的話,我會(huì)用現(xiàn)在這一張嗎?"還有一次,一個(gè)反對林肯的議員走到林肯跟前挖苦地問:"聽說總統(tǒng)您是一位成功的自我設(shè)計(jì)者?""不錯(cuò),先生。"林肯點(diǎn)點(diǎn)頭說,"不過我不明白,一個(gè)成功的設(shè)計(jì)者,怎么會(huì)把自己設(shè)計(jì)成這副模樣?"林肯就是這種幽默的方法,多次成功地化解了可能出現(xiàn)的尷尬和難堪場面。

            沒有幽默的男人不一定就差,但懂得幽默的男人一定是一個(gè)優(yōu)秀的人,懂得幽默的女人更是珍稀動(dòng)物。

            (8)微笑的好習(xí)慣

            微笑是大度、從容的表現(xiàn),也是交往的通行證。

            舉世聞名的希爾頓大酒店,其創(chuàng)建人希爾頓在創(chuàng)業(yè)之初,經(jīng)過多年探索,最終發(fā)現(xiàn)了一條簡單、易行、不花本錢的經(jīng)營秘訣--微笑。從此,他要求所有員工:無論飯店本身遭遇到什么困難,希爾頓飯店服務(wù)員臉上的微笑永遠(yuǎn)是屬于顧客的陽光。這束"陽光"最終使希爾頓飯店贏得了全世界一致好評。

            在歐美發(fā)達(dá)國家,人們見面都要點(diǎn)頭微笑,使人們相互之間感到很溫暖。而在中國,如果你在大街上向一個(gè)女士微笑,那么你可能被說成"有病"。向西方人學(xué)習(xí),讓我們致以相互的微笑吧。

            從古至今,敬業(yè)是所有成功人士最重要的品質(zhì)之一。

            (9)敬業(yè)、樂業(yè)的好習(xí)慣

            敬業(yè)是對渴望成功的人對待工作的基本要求,一個(gè)不敬業(yè)的人很難在他所從事的工作中做出成績。

            美國標(biāo)準(zhǔn)石油公司有一個(gè)叫阿基勃特的小職員,開始并沒有引起人們的特別注意。他的敬業(yè)精神特別強(qiáng),處處注意維護(hù)和宣傳企業(yè)的聲譽(yù)。在遠(yuǎn)行住旅館時(shí)總不忘記在自己簽名的下方寫上"每桶四美元的標(biāo)準(zhǔn)石油"字樣,在給親友寫信時(shí),甚至在打收條時(shí)也不例外,簽名后總不忘記寫那幾個(gè)字。為此,同事們都叫他"每桶四美元"。這事被公司的董事長洛克菲勒知道了,他邀請阿基勃特共進(jìn)晚餐,并號(hào)召公司職員向他學(xué)習(xí)。后來,阿基勃特成為標(biāo)準(zhǔn)石油公司的第二任董事長。

            3.35歲以前成功必須戒除的9大惡習(xí)

            壞習(xí)慣使成功寸步難行。

            與建立良好習(xí)慣相應(yīng)的,是克服不良習(xí)慣。不破不立,不改掉不良習(xí)慣,好習(xí)慣是難以建立起來的。

            古希臘的佛里幾亞國王葛第士以非常奇妙的方法,在戰(zhàn)車的軛打了一串結(jié)。他預(yù)言:誰能打開這個(gè)結(jié),就可以征服亞洲。一直到公元前334年還沒有一個(gè)人能將繩結(jié)打開。這時(shí)。亞歷山大率軍入侵小亞細(xì)亞,他來到葛第士繩結(jié)前,不加考慮便拔劍砍斷了它。后來,他果然一舉占領(lǐng)了比希臘大50倍的波斯帝國。

            一個(gè)孩子在山里割草,不小心被毒蛇咬傷了腳。孩子疼痛難忍,而醫(yī)院在遠(yuǎn)處的小鎮(zhèn)上。孩子毫不猶豫地用鐮刀割斷受傷的腳趾,然后忍著巨痛艱難地走到醫(yī)院。雖然缺少了一個(gè)腳趾,但這個(gè)孩子以短暫的疼痛保住了自己的生命。

            改掉壞習(xí)慣,就應(yīng)該有亞歷山大的氣概,就應(yīng)有那個(gè)小孩的果斷和勇敢,徹底改掉壞習(xí)慣,讓好習(xí)慣引領(lǐng)自己走向成功。

            以下這9大惡習(xí)是你必須戒除的:

            1)經(jīng)常性遲到。你上班或開會(huì)經(jīng)常遲到嗎?遲到是造成使老板和同事反感的種子,它傳達(dá)出的信息:你是一個(gè)只考慮自己、缺乏合作精神的人。

            2)拖延。雖然你最終完成了工作,但拖后腿使你顯得不勝任。為什么會(huì)產(chǎn)生延誤呢?如果是因?yàn)槿鄙倥d趣,你就應(yīng)該考慮一下你的擇業(yè);如果是因?yàn)檫^度追求盡善盡美,這毫無疑問會(huì)增多你在工作中的延誤。社會(huì)心理學(xué)專家說:很多愛拖延的人都很害怕冒險(xiǎn)和出錯(cuò),對失敗的恐懼使他們無從下手。

            3)怨天尤人。這幾乎是失敗者共同的標(biāo)簽。一個(gè)想要成功的人在遇到挫折時(shí),應(yīng)該冷靜地對待自己所面臨的問題,分析失敗的原因,進(jìn)而找到解決問題的突破口。

            4)一味取悅他人。一個(gè)真正稱職的員工應(yīng)該對本職工作內(nèi)存在的問題向上級說明并提出相應(yīng)的解決辦法,而不應(yīng)該只是附和上級的決定。對于管理者,應(yīng)該有嚴(yán)明的獎(jiǎng)懲方式,而不應(yīng)該做"好好先生",這樣做雖然暫時(shí)取悅了少數(shù)人,卻會(huì)失去大多數(shù)人的支持。

            5)傳播流言。每個(gè)人都可能會(huì)被別人評論,也會(huì)去評論他人,但如果津津樂道的是關(guān)于某人的流言蜚語,這種議論最好停止。世上沒有不透風(fēng)的墻,你今天傳播的流言,早晚會(huì)被當(dāng)事人知道,又何必去搬石頭砸自己的腳?所以,流言止于智者。

            6)對他人求全責(zé)備、尖酸刻薄。每個(gè)人在工作中都可能有失誤。當(dāng)工作中出現(xiàn)問題時(shí),應(yīng)該協(xié)助去解決,而不應(yīng)該一味求全責(zé)備。特別是在自己無法做到的情況下,讓自己的下屬或別人去達(dá)到這些要求,很容易使人產(chǎn)生反感。長此以往,這種人在公司沒有任何威信而言。

            7)出爾反爾。已經(jīng)確定下來的事情,卻經(jīng)常做變更,就會(huì)讓你的下屬或協(xié)助員工無從下手。你做出的承諾,如果無法兌現(xiàn),會(huì)在大家面前失去信用。這樣的人,難以擔(dān)當(dāng)重任。

            8)傲慢無禮。這樣做并不能顯得你高人一頭,相反會(huì)引起別人的反感。因?yàn)椋魏稳硕疾粫?huì)容忍別人瞧不起自己。傲慢無禮的人難以交到好的朋友。人脈就是財(cái)脈,年輕時(shí)養(yǎng)成這種習(xí)慣的人,相信你很難取得成功。

            9)隨大流。人們可以隨大流,但不可以無主見。如果你習(xí)慣性地隨大流,那你就有可能形成思維定勢,沒有自己的主見,或者既便有,也不敢表達(dá)自己的主見,而沒有主見的人是不會(huì)成功的。( 世界經(jīng)理人)

            沒能發(fā)財(cái)?shù)氖笤?

            1、不明白財(cái)富的定義;不明白成功的鏡像規(guī)律。

            汗,還真不知道什么叫財(cái)富。再怯怯地問一聲:啥叫鏡像啊?

            2、沒有致富的心態(tài)與觀念

            承認(rèn)自己沒有,比如有致富心態(tài)的,看到一個(gè)鋪面門庭若市,他會(huì)想到那里到底賣什么東西這么吸引人,回去自己也搗鼓點(diǎn)賣。而我只是想擠進(jìn)去買點(diǎn)便宜貨。

            3、沒有理財(cái)與致富的規(guī)劃

            又一條沒有。從來沒為自己做過規(guī)劃,劃了也堅(jiān)持不了三個(gè)月。

            4、理財(cái)方式與訓(xùn)練方式不恰當(dāng)

            來論壇之后才學(xué)著理財(cái)。方法正在學(xué)習(xí)中。

            5、大多數(shù)人沒有投資在高報(bào)酬的領(lǐng)域中

            這個(gè)肯定啦,如果有誰知道投資可獲得高報(bào)酬的,除了股票和傳銷,請你馬上告訴我。

            6、沒有用商業(yè)手法控制支出

            這個(gè)我也有。想花錢的時(shí)候就告訴自己先花了再說,不考慮控制。

            7、不善于創(chuàng)造把握理財(cái)與致富的機(jī)會(huì)

            這個(gè)我覺得我沒有,總認(rèn)為是機(jī)會(huì)還沒來,來了我當(dāng)然要抓住。

            8、無創(chuàng)新意識(shí)不知如何決策

            承認(rèn)。確實(shí)不愿意創(chuàng)新。聽了那么多關(guān)于貨幣基金的介紹,可我還是一門心思在儲(chǔ)蓄,因?yàn)閼小⑾勇闊?

            9、未以正確的思考方式解決問題

            不承認(rèn),我一直都在我認(rèn)為正確的道路上行走著。

            10、沒有找到一位理財(cái)與致富向?qū)?

            確實(shí)沒有。不過來理財(cái)生活以后又感覺向?qū)嗔耍悬c(diǎn)暈。(阿里巴巴)

            三種策略讓你賺到100萬

            大多數(shù)年輕人的目標(biāo)是100萬元,而且是愈早實(shí)現(xiàn)愈好。但是根據(jù)網(wǎng)絡(luò)調(diào)查顯示,有七成人認(rèn)為,30歲時(shí)至少應(yīng)該先擁有10萬元存款,但卻只有一成七的人能夠辦到。這就表示有相當(dāng)多的年輕人,連10萬元的目標(biāo)都還沒能達(dá)成,百萬財(cái)富更是一個(gè)遙遠(yuǎn)的夢想。

            于是在社會(huì)上各種致富法紛紛出籠。譬如嫁入豪門、娶個(gè)富家女、每期買彩票,這些方法似乎是最快、但也是最不切實(shí)際的。到底有沒有機(jī)會(huì)靠著自己的努力,提早賺到百萬財(cái)富,答案當(dāng)然是"有",這里有短、中、長期三套戰(zhàn)略,供你參考。

            2年戰(zhàn)略:高杠桿工具才能小兵立大功

            如果想兩年就賺到百萬財(cái)富,最可能實(shí)現(xiàn)夢想的途徑就是利用高杠桿投資工具。雖然風(fēng)險(xiǎn)超高,但是報(bào)酬也高,想要以小搏大、倍數(shù)獲利,就要正確運(yùn)用這種工具。只要你對趨勢敏感,行情不論走多或是走空,都有獲利機(jī)會(huì)。

            高杠桿投資憑借的不是運(yùn)氣,而是精準(zhǔn)判斷盤勢,冷靜面對大盤起落,情緒絕不隨著輸贏起舞。但所謂"高收益高風(fēng)險(xiǎn)",想要兩年就得到暴利,等于是走著鋼索賺錢,因?yàn)槠谪浕蚴沁x擇權(quán)杠桿高,當(dāng)看錯(cuò)趨勢時(shí),幾十萬元很快就輸光出場,是一條風(fēng)險(xiǎn)最高的求財(cái)途徑。因此,先模擬練功并嚴(yán)格控制投資金額,是激進(jìn)主義者最重要的自保之道。

            5年戰(zhàn)略:做老板、當(dāng)top sales

            如果自認(rèn)為用期指或是選擇權(quán)賺大錢,心臟不夠強(qiáng)、武藝不夠高的話,年限不妨放寬一點(diǎn),定5年戰(zhàn)略,也就是努力創(chuàng)業(yè)當(dāng)老板、甚至是加盟總部的老板、或是努力成為業(yè)務(wù)高手。

            什么樣的創(chuàng)業(yè)能夠5年就凈賺百萬元,當(dāng)然是要能引領(lǐng)潮流或是抓住特殊機(jī)遇的創(chuàng)業(yè)。

            程度更高段的賺錢方法則是當(dāng)一群老板的老板,也就是成立加盟連鎖總部,只要能夠研發(fā)出獨(dú)特口味、或是獨(dú)特經(jīng)營模式,而且能夠復(fù)制標(biāo)準(zhǔn)化程序,穩(wěn)定收取加盟店上繳的權(quán)利金。

            當(dāng)然創(chuàng)業(yè)的成本高,學(xué)問也很大。如果不愿意當(dāng)老板,只想繼續(xù)當(dāng)伙計(jì)賺大錢,不妨選擇產(chǎn)品單價(jià)高、抽傭也高、制度完善的業(yè)務(wù)體系,只要用對方法,就可以成為個(gè)中高手

            10年戰(zhàn)略:運(yùn)用多種工具保守理財(cái)

            如果自認(rèn)投資手段不佳,也不適合創(chuàng)業(yè)當(dāng)老板,或是不擅與人打交道,無法成為業(yè)務(wù)高手的話,那么便得回歸正統(tǒng)的理財(cái)管道,將累積財(cái)富的時(shí)間拉長至10年,積極開源、努力儲(chǔ)蓄守成,透過定期儲(chǔ)蓄,或是投資定存概念股,每年賺取股利,或是把錢交給專家理財(cái),透過定期定額基金投資,逐步累積資產(chǎn)。

            更傳統(tǒng)的方式是投資房地產(chǎn),雖然國內(nèi)房地產(chǎn)價(jià)格還有向下修正的空間,但只要選對地段,還是可以找到極具增值潛力的房子,不管是自住或投資,都是一種穩(wěn)健的資產(chǎn)累積方式。

            你是屬于急功近利型的兔子?還是穩(wěn)扎穩(wěn)打型的烏龜?其實(shí)都有適合的致富計(jì)劃,但要再提醒的是,不管選擇哪一種計(jì)劃,想要提前致富,一定要做足功課,懂得深入領(lǐng)受實(shí)踐,百萬財(cái)富將不是遙遠(yuǎn)夢想!(理財(cái)加油站)

             

            posted @ 2008-12-19 08:07 幽幽 閱讀(272) | 評論 (0)編輯 收藏

            彩色圖像轉(zhuǎn)換為黑白圖像時(shí)需要計(jì)算圖像中每像素有效的亮度值,通過匹配像素

            亮度值可以輕松轉(zhuǎn)換為黑白圖像。

            計(jì)算像素有效的亮度值可以使用下面的公式:

            Y=0.3RED+0.59GREEN+0.11Blue

            然后使用 Color.FromArgb(Y,Y,Y) 來把計(jì)算后的值轉(zhuǎn)換

            轉(zhuǎn)換代碼可以使用下面的方法來實(shí)現(xiàn):
            C#

             1public Bitmap ConvertToGrayscale(Bitmap source)
             2
             3{
             4
             5  Bitmap bm = new Bitmap(source.Width,source.Height);
             6
             7  for(int y=0;y<bm.Height;y++)
             8
             9  {
            10
            11    for(int x=0;x<bm.Width;x++)
            12
            13    {
            14
            15      Color c=source.GetPixel(x,y);
            16
            17      int luma = (int)(c.R*0.3 + c.G*0.59+ c.B*0.11);
            18
            19      bm.SetPixel(x,y,Color.FromArgb(luma,luma,luma));
            20
            21    }

            22
            23  }

            24
            25  return bm;
            26
            27}

            VB
             1Public Function ConvertToGrayscale()Function ConvertToGrayscale(ByVal source As Bitmap) as Bitmap
             2
             3  Dim bm as new Bitmap(source.Width,source.Height)
             4
             5  Dim x
             6
             7  Dim y
             8
             9  For y=0 To bm.Height
            10
            11    For x=0 To bm.Width
            12
            13      Dim c as Color = source.GetPixel(x,y)
            14
            15      Dim luma as Integer = CInt(c.R*0.3 + c.G*0.59 + c.B*0.11)
            16
            17      bm.SetPixel(x,y,Color.FromArgb(luma,luma,luma)
            18
            19    Next
            20
            21  Next
            22
            23  Return bm
            24
            25End Function
            posted @ 2008-10-20 13:10 幽幽 閱讀(1012) | 評論 (0)編輯 收藏

            從該DC中得到位圖數(shù)據(jù)


            在DC加載了RGB24位圖,如何從該DC中得到位圖數(shù)據(jù),給些代碼好嗎?
            回復(fù)人: windows_editor(等咱有錢了,每天早上喝兩大碗豆?jié){)
            LONG GetBitmapBits(
              HBITMAP hbmp,      // handle to bitmap
              LONG cbBuffer,     // number of bytes to copy
              LPVOID lpvBits     // buffer to receive bits
            );  //從位圖中取RGB值
            SetBitmapBits 將位圖的數(shù)據(jù)加上頭格式轉(zhuǎn)化為位圖
            回復(fù)人: bluebohe(薄荷) 
            HBITMAP GetSrcBit(HDC hDC,DWORD BitWidth, DWORD BitHeight)
            {
            HDC hBufDC;
            HBITMAP hBitmap, hBitTemp;
            //創(chuàng)建設(shè)備上下文(HDC)
            hBufDC = CreateCompatibleDC(hDC);
            //創(chuàng)建HBITMAP
            hBitmap = CreateCompatibleBitmap(hDC, BitWidth, BitHeight);
            hBitTemp = (HBITMAP) SelectObject(hBufDC, hBitmap);
            //得到位圖緩沖區(qū)
            StretchBlt(hBufDC, 0, 0, BitWidth, BitHeight,
            hDC, 0, 0, BitWidth, BitHeight, SRCCOPY);
            //得到最終的位圖信息
            hBitmap = (HBITMAP) SelectObject(hBufDC, hBitTemp);
            //釋放內(nèi)存
            DeleteObject(hBitTemp);
            ::DeleteDC(hBufDC);
            return hBitmap;
            }
            BOOL SaveBmp(HBITMAP hBitmap, CString FileName)
            {
            //設(shè)備描述表
            HDC hDC;
            //當(dāng)前分辨率下每象素所占字節(jié)數(shù)
            int iBits;
            //位圖中每象素所占字節(jié)數(shù)
            WORD wBitCount;
            //定義調(diào)色板大小, 位圖中像素字節(jié)大小 ,位圖文件大小 , 寫入文件字節(jié)數(shù) 
            DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; 
            //位圖屬性結(jié)構(gòu) 
            BITMAP Bitmap;  
            //位圖文件頭結(jié)構(gòu)
            BITMAPFILEHEADER bmfHdr;  
            //位圖信息頭結(jié)構(gòu) 
            BITMAPINFOHEADER bi;  
            //指向位圖信息頭結(jié)構(gòu)  
            LPBITMAPINFOHEADER lpbi;  
            //定義文件,分配內(nèi)存句柄,調(diào)色板句柄 
            HANDLE fh, hDib, hPal,hOldPal=NULL; 
            //計(jì)算位圖文件每個(gè)像素所占字節(jié)數(shù) 
            hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
            iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
            DeleteDC(hDC); 
            if (iBits <= 1) wBitCount = 1; 
            else if (iBits <= 4)  wBitCount = 4; 
            else if (iBits <= 8)  wBitCount = 8; 
            else   wBitCount = 24; 
            GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
            bi.biSize = sizeof(BITMAPINFOHEADER);
            bi.biWidth = Bitmap.bmWidth;
            bi.biHeight = Bitmap.bmHeight;
            bi.biPlanes = 1;
            bi.biBitCount = wBitCount;
            bi.biCompression = BI_RGB;
            bi.biSizeImage = 0;
            bi.biXPelsPerMeter = 0;
            bi.biYPelsPerMeter = 0;
            bi.biClrImportant = 0;
            bi.biClrUsed = 0;
            dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
            //為位圖內(nèi)容分配內(nèi)存 
            hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); 
            lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
            *lpbi = bi; 

            // 處理調(diào)色板  
            hPal = GetStockObject(DEFAULT_PALETTE); 
            if (hPal) 

            hDC = ::GetDC(NULL); 
            hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
            RealizePalette(hDC); 
            }
            // 獲取該調(diào)色板下新的像素值 
            GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) +dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); 
            //恢復(fù)調(diào)色板  
            if (hOldPal) 

            ::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
            RealizePalette(hDC); 
            ::ReleaseDC(NULL, hDC); 

            //創(chuàng)建位圖文件  
            fh = CreateFile(FileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
            if (fh == INVALID_HANDLE_VALUE)  return FALSE; 
            // 設(shè)置位圖文件頭 
            bmfHdr.bfType = 0x4D42; // "BM" 
            dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;  
            bmfHdr.bfSize = dwDIBSize; 
            bmfHdr.bfReserved1 = 0; 
            bmfHdr.bfReserved2 = 0; 
            bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; 
            // 寫入位圖文件頭 
            WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
            // 寫入位圖文件其余內(nèi)容 
            WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); 
            //清除  
            GlobalUnlock(hDib); 
            GlobalFree(hDib); 
            CloseHandle(fh); 

            return TRUE;
            }


            posted @ 2008-09-28 16:19 幽幽 閱讀(2280) | 評論 (0)編輯 收藏
            轉(zhuǎn)自CSDN

            在所有的預(yù)處理指令中,#Pragma 指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動(dòng)作。#pragma指令對每個(gè)編譯器給出了一個(gè)方法,在保持與C和C++語言完全兼容的情況下,給出主機(jī)或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機(jī)器或操作系統(tǒng)專有的,且對于每個(gè)編譯器都是不同的。
            其格式一般為: #Pragma Para
            其中Para 為參數(shù),下面來看一些常用的參數(shù)。

            (1)message 參數(shù)。 Message 參數(shù)是我最喜歡的一個(gè)參數(shù),它能夠在編譯信息輸出窗
            口中輸出相應(yīng)的信息,這對于源代碼信息的控制是非常重要的。其使用方法為:
            #Pragma message(“消息文本”)
            當(dāng)編譯器遇到這條指令時(shí)就在編譯輸出窗口中將消息文本打印出來。
            當(dāng)我們在程序中定義了許多宏來控制源代碼版本的時(shí)候,我們自己有可能都會(huì)忘記有沒有正確的設(shè)置這些宏,此時(shí)我們可以用這條指令在編譯的時(shí)候就進(jìn)行檢查。假設(shè)我們希望判斷自己有沒有在源代碼的什么地方定義了_X86這個(gè)宏可以用下面的方法
            #ifdef _X86
            #Pragma message(“_X86 macro activated!”)
            #endif
            當(dāng)我們定義了_X86這個(gè)宏以后,應(yīng)用程序在編譯時(shí)就會(huì)在編譯輸出窗口里顯示“_
            X86 macro activated!”。我們就不會(huì)因?yàn)椴挥浀米约憾x的一些特定的宏而抓耳撓腮了


            (2)另一個(gè)使用得比較多的pragma參數(shù)是code_seg。格式如:
            #pragma code_seg( ["section-name"[,"section-class"] ] )
            它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開發(fā)驅(qū)動(dòng)程序的時(shí)候就會(huì)使用到它。

            (3)#pragma once (比較常用)
            只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實(shí)際上在VC6中就已經(jīng)有了,但是考慮到兼容性并沒有太多的使用它。

            (4)#pragma hdrstop表示預(yù)編譯頭文件到此為止,后面的頭文件不進(jìn)行預(yù)編譯。BCB可以預(yù)編譯頭文件以加快鏈接的速度,但如果所有頭文件都進(jìn)行預(yù)編譯又可能占太多磁盤空間,所以使用這個(gè)選項(xiàng)排除一些頭文件。
            有時(shí)單元之間有依賴關(guān)系,比如單元A依賴單元B,所以單元B要先于單元A編譯。你可以用#pragma startup指定編譯優(yōu)先級,如果使用了#pragma package(smart_init) ,BCB就會(huì)根據(jù)優(yōu)先級的大小先后編譯。

            (5)#pragma resource "*.dfm"表示把*.dfm文件中的資源加入工程。*.dfm中包括窗體
            外觀的定義。

            (6)#pragma warning( disable : 4507 34; once : 4385; error : 164 )
            等價(jià)于:
            #pragma warning(disable:4507 34) // 不顯示4507和34號(hào)警告信息
            #pragma warning(once:4385) // 4385號(hào)警告信息僅報(bào)告一次
            #pragma warning(error:164) // 把164號(hào)警告信息作為一個(gè)錯(cuò)誤。
            同時(shí)這個(gè)pragma warning 也支持如下格式:
            #pragma warning( push [ ,n ] )
            #pragma warning( pop )
            這里n代表一個(gè)警告等級(1---4)。
            #pragma warning( push )保存所有警告信息的現(xiàn)有的警告狀態(tài)。
            #pragma warning( push, n)保存所有警告信息的現(xiàn)有的警告狀態(tài),并且把全局警告
            等級設(shè)定為n。
            #pragma warning( pop )向棧中彈出最后一個(gè)警告信息,在入棧和出棧之間所作的
            一切改動(dòng)取消。例如:
            #pragma warning( push )
            #pragma warning( disable : 4705 )
            #pragma warning( disable : 4706 )
            #pragma warning( disable : 4707 )
            //.......
            #pragma warning( pop )
            在這段代碼的最后,重新保存所有的警告信息(包括4705,4706和4707)。
            (7)pragma comment(...)
            該指令將一個(gè)注釋記錄放入一個(gè)對象文件或可執(zhí)行文件中。
            常用的lib關(guān)鍵字,可以幫我們連入一個(gè)庫文件。


            posted @ 2008-08-19 11:01 幽幽 閱讀(297) | 評論 (0)編輯 收藏
            一種給窗口添加陰影的方法
            華南理工大學(xué)微軟技術(shù)俱樂部

            因?yàn)樽约汉芟矚g那些界面做得很漂亮的軟件或者使用各種美化界面的軟件,如avedesk,samurize等等。其中美化界面的一個(gè)重要的方面就是給窗口添加上陰影。雖然OS X已經(jīng)原生的支持窗口陰影,但是windows要到Longhorn才開始支持原生的窗口陰影。現(xiàn)在如果想實(shí)現(xiàn)窗口陰影,一般都會(huì)借助第三方的軟件,例如windowFX或者YzShadow。其中YzShadow是一個(gè)免費(fèi)軟件,我自己也在使用。但是這個(gè)軟件有個(gè)弱點(diǎn),就是無法為Layered Window添加陰影。而我自己編寫的一個(gè)簡易便條程序Stickies(功能類似OneNote,但是功能簡單,小巧。)就是運(yùn)用了Layered Window來作為軟件的界面,于是便自己嘗試添加窗口陰影。以下便是添加陰影的方法,寫下來與大家討論一下。

            我的程序是在Visual Studio.NET 2003下編寫的MFC應(yīng)用程序。我為了實(shí)現(xiàn)窗口陰影創(chuàng)建了一個(gè)Shadow的類。首先我們看看各類之間的關(guān)系:



            1. Class ShadowCastingWindow
            該類是一個(gè)應(yīng)用程序的窗口,它會(huì)在桌面上投射下陰影。這個(gè)類是從CWnd繼承而來。
            ShadowCastingWindow成員變量:
            m_Alpha
            保存該窗口的透明度值。

            ShadowCastingWindow成員函數(shù):
            BOOL ShadowCastingWindow::CreateWindow( CString wndName, CWnd * pParentWnd )
            {
            BOOL tmp = CWnd::CreateEx( WS_EX_TOOLWINDOW|WS_EX_LAYERED
            , …
            , WS_POPUP|WS_VISIBLE
            , … );
            m_Shadow.CreateShadow( this, m_Alpha );
            }

            該函數(shù)用于創(chuàng)建應(yīng)用程序的窗口并創(chuàng)建陰影。請留意CreateEx中窗口屬性WS_EX_...和WS_...的取值,這使得該應(yīng)用程序的窗口是一個(gè)沒有標(biāo)題欄的Layered Windows。是否有標(biāo)題欄對于下文Shadow類中求遮擋窗口的大小會(huì)有所不同,這必須通過一個(gè)判斷邏輯或者根據(jù)程序的應(yīng)用不同編寫好代碼。對于Layered Windows會(huì)有兩種刷新模式,一種就是傳統(tǒng)的消息機(jī)制,就是操作系統(tǒng)自動(dòng)地在適當(dāng)?shù)臅r(shí)候發(fā)送WM_PAINT的消息給應(yīng)用程序窗口,應(yīng)用程序窗口則相應(yīng)該消息,對窗口進(jìn)行刷新;另一種方式則是在Windows2000以后才支持的UpdateLayeredWindow的機(jī)制,在這種機(jī)制下,應(yīng)用程序不再處理WM_PAINT消息,所有的刷新均由用戶在內(nèi)存中的一個(gè)繪圖上下文中繪制好圖像之后再通過UpdateLayeredWindow繪制到屏幕上,只要經(jīng)過一次繪制,窗口的圖像便會(huì)保存在一塊預(yù)訂好的內(nèi)存區(qū)域內(nèi),如果窗口的圖像沒有改變那么操作系統(tǒng)便會(huì)自動(dòng)地處理刷新。

            void ShadowCastingWindow::OnSizing(UINT fwSide, LPRECT pRect)
            {
            CWnd::OnSizing(fwSide, pRect);
            m_Shadow.OnShadowCastingWndNewSize(pRect->right - pRect->left, pRect->bottom - pRect->top);
            }

            void ShadowCastingWindow::OnSize(UINT nType, int cx, int cy)
            {
            CWnd::OnSize(nType, cx, cy);
            m_Shadow.OnShadowCastingWndNewSize(cx,cy);
            }

            void ShadowCastingWindow::OnMoving(UINT fwSide, LPRECT pRect)
            {
            CWnd::OnMoving(fwSide, pRect);
            m_Shadow.OnShadowCastingWndNewPos(pRect->left, pRect->top );
            }

            void ShadowCastingWindow::OnMove(int x, int y)
            {
            CWnd::OnMove(x, y);
            m_Shadow.OnShadowCastingWndNewPos(x, y );
            }

            這四個(gè)事件函數(shù)都是處理應(yīng)用程序窗口大小或者位置變化的。只需要在其中調(diào)用Shadow類中相應(yīng)的處理函數(shù)即可,Shadow便會(huì)自動(dòng)地更改大小或者移動(dòng)位置。可能有人會(huì)問為什么需要顯式地調(diào)整Shadow的位置和大小?因?yàn)閺南挛目梢钥吹絊hadow其實(shí)也是一個(gè)Layered Window,沒有父窗口,所以操作系統(tǒng)不可以自動(dòng)地保持兩者的相對位置。

            void ShadowCastingWindow::SetOpacity( int alpha )
            {
            m_Alpha = alpha;
            m_Shadow.SetAlpha( alpha );
            SetLayeredWindowAttributes( 0, (BYTE)m_Alpha, LWA_ALPHA );
            Invalidate();
            }

            處理應(yīng)用程序窗口透明度變化的函數(shù),其中調(diào)用了陰影Shadow對于透明度變化的處理函數(shù)。并刷新應(yīng)用程序窗口。

            2. Class Shadow
            該類繼承與CWnd類。
            Shadow成員變量:
            CWnd * m_pShadowCastingWindow;
            指向父窗口—需要投射陰影的窗口的指針。
            int m_Alpha;
            當(dāng)前陰影的透明度。
            int m_DeltaTop;
            int m_DeltaLeft;
            int m_DeltaRight;
            int m_DeltaButtom;
            用于表示陰影的尺寸。計(jì)算方法如下:


            Shadow成員函數(shù):
            BOOL Shadow::CreateShadow(CWnd * pShadowCastingWnd, int alpha )
            {
            //根據(jù)投射陰影的窗口的尺寸和各參數(shù)計(jì)算出陰影的尺寸。
            CRect rect;
            pShadowCastingWnd->GetWindowRect(&rect);
            rect.top += m_DeltaTop;
            rect.left -= m_DeltaLeft;
            rect.right += m_DeltaRight;
            rect.bottom += m_DeltaButtom;
            m_Alpha = alpha;
            BOOL tmp = CWnd::CreateEx( WS_EX_TOOLWINDOW|WS_EX_LAYERED
            ,…
            , WS_POPUP|WS_VISIBLE
            , rect
            , …);

            m_IsCreated = true;
            CustomizedPaint();
            return tmp;
            }

            創(chuàng)建陰影,由于陰影必須是沒有標(biāo)題欄的,而且因?yàn)橐L制半透明的像素所以必須使用Layered Window。

            void Shadow::CustomizedPaint(void)
            {
            if ( !m_IsCreated )
            return;

            BLENDFUNCTION blendPixelFunction= {AC_SRC_OVER, 0, m_Alpha, AC_SRC_ALPHA};
            POINT ptWindowScreenPosition = {rect.left, rect.top};
            POINT ptSrc = {0, 0};
            SIZE szWindow = {rect.Width(), rect.Height()};

            CDC * dcScreen = GetDesktopWindow()->GetDC();
            CDC dcMemory;
            dcMemory.CreateCompatibleDC( dcScreen );

            //-----------------------------------
            //把要繪制的內(nèi)容繪制在dcMemory里。對于Shadow需要把投射陰影窗口所覆蓋的區(qū)
            //域剪裁掉
            //-----------------------------------

            UpdateLayeredWindow( dcScreen, &ptWindowScreenPosition, &szWindow, &dcMemory, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA);

            GetDesktopWindow()->ReleaseDC(dcScreen);
            dcMemory.DeleteDC();
            }
            根據(jù)不同程序需要加上適當(dāng)?shù)睦L制流程。比如可以通過畫一個(gè)長方形來表示陰影,這個(gè)效果自然就比較差;也可以利用一些在Photoshop中處理好的陰影圖片把它做適當(dāng)?shù)拇笮≌{(diào)整作為窗口的陰影這樣更容易做出陰影邊緣柔化的效果。這個(gè)CustomizedPaint只需要在窗口的內(nèi)容被改變的時(shí)候才需要重新調(diào)用,其他時(shí)候系統(tǒng)會(huì)自動(dòng)管理已經(jīng)繪制的圖像,用它來刷新窗口,而不需要重新繪制。

            BOOL Shadow::PreCreateWindow(CREATESTRUCT& cs)
            {
            cs.style &= ~WS_BORDER;
            cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
            ::LoadCursor( NULL, IDC_CURSOR ), NULL, NULL);
            return CWnd::PreCreateWindow(cs);
            }
            通過修改默認(rèn)的cs.lpszClass使得窗口不再自動(dòng)重畫背景。

            void Shadow::OnShadowCastingWndNewSize( int x, int y )
            {
            if ( !m_IsCreated )
            return;
            SetWindowPos( m_pShadowCastingWindow,0,0,x+m_DeltaLeft+m_DeltaRight,y-m_DeltaTop+m_DeltaButtom, SWP_NOMOVE );
            CustomizedPaint();
            }

            提供該投射陰影的窗口的接口函數(shù),當(dāng)投射陰影的窗口大小改變的時(shí)候便調(diào)用這個(gè)函數(shù)把新的窗口位置傳給Shadow,Shadow便會(huì)改變自己的大小,并重繪窗口。

            void Shadow::OnShadowCastingWndNewPos( int x, int y )
            {
            if ( !m_IsCreated )
            return;
            SetWindowPos( m_pShadowCastingWindow, x-m_DeltaLeft, y+m_DeltaTop, 0, 0, SWP_NOSIZE );
            }

            提供該投射陰影的窗口的接口函數(shù),當(dāng)投射陰影的窗口位置改變的時(shí)候便調(diào)用這個(gè)函數(shù)把新的窗口位置傳給Shadow,Shadow便會(huì)改變自己的位置。注意了,這里并不需要重繪窗口,因?yàn)榇翱诘膬?nèi)容并沒有改變。

            void Shadow::SetAlpha( int alpha )
            {
            m_Alpha = alpha;
            CustomizedPaint();
            }

            提供該投射陰影的窗口的接口函數(shù),當(dāng)投射陰影的窗口的透明度改變的時(shí)候便調(diào)用這個(gè)函數(shù)把新透明度傳給Shadow,Shadow便會(huì)改變自己的透明度,并重繪窗口。

            下面給出一個(gè)我自己寫的程序的效果圖:

            3. 結(jié)論:

            上面就簡單地介紹了一個(gè)繪制窗口陰影的方法。這種方法基本上可以適用于各種類型的窗口,其中需要注意一下幾點(diǎn):

            1. 在于Shadow::CreateShadow中如何正確取得投射陰影窗口m_pShadowCastingWindow的大小然后計(jì)算出陰影窗口的大小。

            2. Shadow::CustomizedPaint中如何更高效的繪制陰影,例如剪裁掉投射陰影窗口遮擋住的窗口內(nèi)容,避免繪制時(shí)出現(xiàn)閃爍。同時(shí)如何正確使用好UpdateLayeredWindow這個(gè)系統(tǒng)調(diào)用會(huì)是實(shí)現(xiàn)繪制陰影的關(guān)鍵。當(dāng)然在當(dāng)前的設(shè)計(jì)下,我們可以在CustomizePaint中繪制任何的東西,而不一定是陰影。? 大家可以在這里發(fā)揮想象力,讓窗口更加絢麗多彩。

            其實(shí)這個(gè)程序只要讓他通過鉤子函數(shù)與特定的Win32API掛鉤,完全可以寫出一個(gè)可以給系統(tǒng)中所有窗口加上陰影效果的小軟件。大家不妨試試。如果做出來了,記得給我一份。

            注:文章中的代碼都是示意性的,都是通過我自己寫的程序刪減后得到,未必能通過測試。旨在說明一些關(guān)鍵步驟需要注意的地方。如果問題歡迎email討論。


            posted @ 2008-08-17 12:18 幽幽 閱讀(5436) | 評論 (3)編輯 收藏

            這篇文章翻譯至MSDN2005,給自己學(xué)習(xí),也給所有覺得它有用的人,文中難免有翻譯不到位或者錯(cuò)誤的地方,望高手指正。譯者:歐昊川(轉(zhuǎn)載麻煩注明出處及譯者)

            2008年5月4日

            這個(gè)概述討論了窗口的一些特性,如窗口類型、狀態(tài)、大小及位置。

            1、窗口類型(WindowStyles)
            這一節(jié)描述層疊窗口、彈出窗口、子窗口、分層窗口、僅處理消息的窗口這五種類型。

            1.1層疊窗口(OverlappedWindows)
            層疊窗口是一個(gè)具有標(biāo)題欄、邊框和客戶區(qū)的頂層窗口;也就是說它適合做為應(yīng)用程序主窗口。它也可以具有一個(gè)系統(tǒng)菜單,最小和最大化按鈕,以及滾動(dòng)條。一個(gè)層疊窗口被典型地用于包含所有上述組件的應(yīng)用程序主窗口。

            通過在CreateWindowEx中指定WS_OVERLAPPED或者WS_OVERLAPPEDWINDOW樣式,一個(gè)應(yīng)用程序就能創(chuàng)建一個(gè)層疊窗口。假如你使用第一個(gè)樣式,那么創(chuàng)建的窗口就具有一個(gè)標(biāo)題欄和邊框;假如你使用第二個(gè),那么窗口就具有一個(gè)標(biāo)題欄,可以調(diào)整大小的邊框,系統(tǒng)菜單,以及最大最小化按鈕。

            1.2彈出窗口(Pop-upWindows)
            彈出窗口是一個(gè)非凡的層疊窗口,它被用于顯示在應(yīng)用程序主窗口之外的對話框,消息框以及其他臨時(shí)窗口。標(biāo)題欄對彈出窗口來說是可選的;除此之外,彈出窗口跟具有WS_OVERLAPPED樣式的層疊窗口一樣。

            你可以通過在CreateWindowEx中指定WS_POPUP樣式來創(chuàng)建一個(gè)彈出窗口。假如要使用標(biāo)題欄,就加入WS_CAPTION樣式。使用WS_POPUPWINDOW樣式來創(chuàng)建一個(gè)含有邊框和系統(tǒng)菜單的彈出窗口。WS_CAPTION樣式必須與WS_POPUPWINDOW樣式一起使用才能使系統(tǒng)菜單可見。

            1.3子窗口(ChildWindows)
            子窗口具有WS_CHILD樣式并且它被限制在其父窗口的客戶區(qū)中。應(yīng)用程序典型地使用子窗口來把其父窗口的客戶區(qū)劃分成幾個(gè)功能區(qū)域。你可以通過在CreateWindowEx中指定WS_CHILD樣式來創(chuàng)建子窗口。

            子窗口必須具有一個(gè)父窗口。父窗口可以是一個(gè)層疊窗口,彈出窗口,或者另外一個(gè)子窗口。你可以在CreateWindowEx中指定父窗口。假如你在CreateWindowEx中指定了WS_CHILD樣式但是沒有指定父窗口,那么系統(tǒng)不會(huì)創(chuàng)建這個(gè)子窗口。

            子窗口只具有一個(gè)客戶區(qū)而沒有其他特性,除非這些特性被明確的請求。應(yīng)用程序可以為子窗口添加標(biāo)題欄,系統(tǒng)菜單,最小化最大化按鈕,邊框,以及滾動(dòng)條。但是子窗口不能具有自定義菜單。假如應(yīng)用程序指定了一個(gè)自定義菜單句柄,那么無論是在它注冊這個(gè)子窗口類還是創(chuàng)建這個(gè)子窗口時(shí),這個(gè)菜單句柄都被忽略。假如沒有指定邊框樣式,系統(tǒng)將創(chuàng)建一個(gè)無邊框窗口。應(yīng)用程序可以使用無邊框的子窗口來劃分父窗口的客戶區(qū)假如想保持這種劃分對用戶是不可見的話。

            下面一節(jié)討論窗口的布置、裁剪、與父窗口的關(guān)系、消息四個(gè)主題。

            1.4窗口布置(Positioning)
            系統(tǒng)總是相對于父窗口客戶區(qū)的左上角來放置子窗口。子窗口的任何部分都不會(huì)出現(xiàn)在其父窗口的邊框之外。假如應(yīng)用程序創(chuàng)建一個(gè)比父窗口大的子窗口,或者移動(dòng)子窗口使得一個(gè)或者所有子窗口超出了父窗口的邊框,那么系統(tǒng)會(huì)裁剪子窗口,即在父窗口邊框之外的部分不被顯示。對父窗口產(chǎn)生影響的行為同樣會(huì)影響子窗口,這些行為如下:

             

            posted @ 2008-08-16 13:38 幽幽 閱讀(1175) | 評論 (0)編輯 收藏

            OLE拖放實(shí)現(xiàn)

            MFC本身的CView類是支持拖放操作的,通過研究CView類的源碼,大體知道它的實(shí)現(xiàn)原理是這樣的:CView類中有一個(gè)COleDropTarget類的對象,在視圖窗口初始化時(shí),調(diào)用COleDropTarget類成員函數(shù)Register(),以此在系統(tǒng)中注冊該視圖窗口為拖放接收窗口。當(dāng)進(jìn)行拖放操作的鼠標(biāo)指針處于視圖窗口范圍內(nèi)時(shí),COleDropTarge類會(huì)做出反應(yīng),它的OnDragEnterOnDragOverOnDropExOnDrop等成員函數(shù)被依次調(diào)用,這些函數(shù)默認(rèn)均是調(diào)用與其相對應(yīng)的CView類成員函數(shù)OnDragEnterOnDragOverOnDropExOnDrop等,程序員只需重載這些CView類成員函數(shù),即可對拖動(dòng)的過程及結(jié)果進(jìn)行控制。

            因?yàn)?font face=Tahoma>COleDropTarget默認(rèn)只對CView提供支持,所以如果要讓其他的窗口支持拖放,我們必須同時(shí)對要支持拖放的窗口類和COleDropTarget類進(jìn)行派生。把對拖放操作具體進(jìn)行處理的代碼封裝成派生窗口類的成員函數(shù),然后重載COleDropTarget中對應(yīng)的五個(gè)虛函數(shù),當(dāng)它接收到拖放動(dòng)作時(shí),調(diào)用窗口派生類的處理函數(shù)即可。但這里有一個(gè)問題,就是我們怎么知道何時(shí)調(diào)用派生類的處理函數(shù)呢?答案是運(yùn)用RTTI技術(shù)。如果COleDropTarget派生類收到的窗口指針類型,就是我們派生的窗口類,那么就調(diào)用它的處理函數(shù),否則調(diào)用基類進(jìn)行處理。

            首先生成一個(gè)對話框工程,添加二個(gè)新類。

            第一個(gè)類名為CListCtrlEx,父類為CListCtrl。添加完畢后,在CListCtrlEx的定義頭文件中加入DECLARE_DYNAMIC(CListCtrlEx),在其實(shí)現(xiàn)文件中加入IMPLEMENT_DYNAMIC(CListCtrlEx,CListCtrl),這樣就對CListCtrlEx類添加了RTTI運(yùn)行期類型識(shí)別(Run Time Type Information)支持。

            第二個(gè)類名為COleDropTargetEx,父類為COleDataTarget

            CListCtrlEx中添加COleDropTargetEx類的對象,并添加下列公有虛函數(shù)的聲明:

                   virtual BOOL Initialize();

                   virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);

                   virtual DROPEFFECT OnDropEx(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, DROPEFFECT dropList, CPoint point);

                   virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);

                   virtual void OnDragLeave(CWnd* pWnd);

            Initialize函數(shù)用于注冊CListCtrlEx成為拖放接收窗口;

            OnDragOver在拖放鼠標(biāo)進(jìn)入窗口時(shí)被調(diào)用。此函數(shù)的返回值決定了后續(xù)的動(dòng)作的類型:如果返回DROPEFFECT_MOVE,則產(chǎn)生一個(gè)剪切動(dòng)作;如果返回DROPEFFECT_COPY,則產(chǎn)生一個(gè)復(fù)制動(dòng)作,如果返回DROPEFFECT_NONE,則不會(huì)產(chǎn)生拖放動(dòng)作,因?yàn)?font face=Tahoma>OnDropExOnDrop函數(shù)將不會(huì)被調(diào)用(OnDragLeave函數(shù)仍會(huì)被調(diào)用)。

            OnDropEx函數(shù)會(huì)在OnDrop函數(shù)之前調(diào)用,如果OnDropEx函數(shù)沒有對拖放動(dòng)作進(jìn)行處理,則應(yīng)用程序框架會(huì)接著調(diào)用OnDrop函數(shù)進(jìn)行處理。所以必須要在派生類中重載OnDropEx函數(shù)——即使什么動(dòng)作都都沒有做——否則我們的OnDrop函數(shù)將不會(huì)被執(zhí)行到,因?yàn)闆]有重載的話,將會(huì)調(diào)用基類的OnDropEx函數(shù),而基類的OnDropEx函數(shù)對拖放是進(jìn)行了處理的——盡管不是我們所想要的動(dòng)作。當(dāng)然你也可以把對拖放進(jìn)行處理的動(dòng)作放在OnDropEx中——那樣就不需要重載OnDrop了。

            OnDragLeave函數(shù)會(huì)在鼠標(biāo)離開窗口時(shí)被調(diào)用,在此可以進(jìn)行一些簡單的清理工作。譬如在OnDragEnter或者OnDragOver函數(shù)中,我們改變了光標(biāo)的形態(tài),那么此時(shí)我們就應(yīng)該把光標(biāo)恢復(fù)過來。

            這些函數(shù)中最重要的是OnDrop函數(shù),拖放動(dòng)作將在此進(jìn)行處理,它的全部源碼如下:

            BOOL CListCtrlEx::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)

            {

                   UINT              nFileCount = 0;

                   HDROP           hDropFiles = NULL;

                   HGLOBAL        hMemData = NULL;

             

                   AfxMessageBox("OnDrop");

                   if(pDataObject->IsDataAvailable(CF_HDROP))

                   {

                          hMemData = pDataObject->GetGlobalData(CF_HDROP);

                          hDropFiles = (HDROP)GlobalLock((HGLOBAL)hMemData); //鎖定內(nèi)存塊

                          if(hDropFiles != NULL)

                          {

                                 char chTemp[_MAX_PATH+1] = {0};

                                 nFileCount = DragQueryFile(hDropFiles, 0xFFFFFFFF, NULL, 0);

                                 for(UINT nCur=0; nCur<nFileCount; ++nCur) //遍歷取得每個(gè)文件名

                                 {

                                        ZeroMemory(chTemp, _MAX_PATH+1);

                            DragQueryFile(hDropFiles, nCur, (LPTSTR)chTemp, _MAX_PATH+1);

                                        AddAllFiles(chTemp);

                                 }

                          }

                          GlobalUnlock(hMemData);

                          return TRUE;

                   }

                   else

                   {

                          return FALSE;

                   }

            }

            在第二個(gè)類COleDropTarget中添加如下對應(yīng)的函數(shù):

                virtual DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);

                virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);

                   virtual DROPEFFECT OnDropEx(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, DROPEFFECT dropList, CPoint point);

                   virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);

                   virtual void OnDragLeave(CWnd* pWnd);

            它們的動(dòng)作都差不多:先用RTTI判斷窗口指針pWnd的類型,如果是CListCtrlEx,則調(diào)用CListCtrlEx中對應(yīng)的處理函數(shù),否則調(diào)用基類的處理函數(shù)。以OnDrop為例:

            BOOL COleDropTargetEx::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)

            {

                   CListCtrlEx*     pListCtrlEx = NULL;

                  

                   ASSERT_VALID(this);

                   ASSERT(IsWindow(pWnd->m_hWnd));

                  

                   if(pWnd->IsKindOf(RUNTIME_CLASS(CListCtrlEx)))

                   {

                          pListCtrlEx = (CListCtrlEx*)pWnd;

                          return pListCtrlEx->OnDrop(pWnd, pDataObject, dropEffect, point);

                   }

                   else

                   {

                          return COleDropTarget::OnDrop(pWnd, pDataObject, dropEffect, point);    

                   }

            }

             

            //倒霉的64K限制,只能再截?cái)嗔耍海?br>

            至此,我們成功地為CListCtrlEx添加了文件拖入操作的支持。一個(gè)完整的拖放操作,還包括拖出動(dòng)作,所以必須要為該類再添加拖出操作,即,將列表中的某一項(xiàng)或者多項(xiàng)拖出成為一個(gè)文件。這就需要用到另一個(gè)類:COleDataSource。具體步驟如下:

            CListCtrlEx中加入一個(gè)COleDataSource的實(shí)例,并映射列表框的LVN_BEGINDRAG消息處理函數(shù),在此我們添加拖出操作的代碼。

            實(shí)現(xiàn)拖出非常簡單,只需要依次調(diào)用COleDataSource的三個(gè)函數(shù)即可:Empty用于清空原先對象中緩存的數(shù)據(jù),CacheGlobalData用來緩存數(shù)據(jù)以進(jìn)行拖放操作,最后調(diào)用DoDragDrop啟動(dòng)本次拖放操作。

            但在調(diào)用之前,必須要做一些準(zhǔn)備工作。主要的任務(wù)就是創(chuàng)建一個(gè)DROPFILES結(jié)構(gòu)體,并拷貝要拖放的文件名到結(jié)構(gòu)體后的內(nèi)存中。DROPFILES結(jié)構(gòu)體定義了CF_HDROP剪貼板格式,緊跟它后面的是一系列被拖放文件的路徑名。它的定義如下:

            typedef struct _DROPFILES

            {

                DWORD     pFiles;  //文件名起始地址

                POINT      pt;     //鼠標(biāo)放下的位置,坐標(biāo)由fNC成員指定

                BOOL        fNC;    //TRUE表示適用屏幕坐標(biāo)系,否則使用客戶坐標(biāo)系

                BOOL        fWide;  //文件名字符串是否使用寬字符

            } DROPFILES, FAR* LPDROPFILES;

            拖放之前的準(zhǔn)備動(dòng)作的代碼如下:

            uBufferSize = sizeof(DROPFILES) + uBufferSize + 1;

                hMemData = GlobalAlloc(GPTR,uBufferSize);

                ASSERT(hMemData != NULL);

                  

                   lpDropFiles = (LPDROPFILES)GlobalLock(hMemData); //鎖定之,并設(shè)置相關(guān)成員

                   ASSERT(lpDropFiles != NULL);

                   lpDropFiles->pFiles = sizeof(DROPFILES);

            #ifdef _UNICODE

                   lpDropFiles->fWide = TRUE;

            #else

                   lpDropFiles->fWide = FALSE;

            #endif

             

                   //把選中的所有文件名依次復(fù)制到DROPFILES結(jié)構(gòu)體后面(全局內(nèi)存中)

                   pItemPos = strSelectedList.GetHeadPosition();

                   pszStart = (char*)((LPBYTE)lpDropFiles + sizeof(DROPFILES));

                   while(pItemPos != NULL)

                   {

                          lstrcpy(pszStart, (LPCTSTR)strSelectedList.GetNext(pItemPos));

                    pszStart = strchr(pszStart,'\0') + 1; //下次的起始位置是上一次結(jié)尾+1

                   }

            準(zhǔn)備完畢之后就可以進(jìn)行拖放了,拖放動(dòng)作有DoDragDrop函數(shù)觸發(fā),其原型如下:

            DROPEFFECT DoDragDrop(

            DWORD dwEffects = DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK, LPCRECT lpRectStartDrag = NULL,

            COleDropSource* pDropSource = NULL

            );

            這里,dwEffects指定了允許施加于本COleDataSource實(shí)例之上的動(dòng)作集:剪切、復(fù)制或無動(dòng)作。

                lpRectStartDrag指示拖放操作真正開始的矩形,如果鼠標(biāo)沒有移出該矩形,則拖放操作視作放棄處理。如果本成員設(shè)為NULL,則該起始矩形將為一個(gè)像素大小。

                pDropSource表明拖放所使用的COleDataSource對象。

            而該函數(shù)的返回值,則表明本次拖放操作所實(shí)際產(chǎn)生的效果,至于具體產(chǎn)生何種效果,則由系統(tǒng)決定。譬如在拖放時(shí)按住Shift鍵,將產(chǎn)生剪切效果;按住Ctrl鍵,將產(chǎn)生復(fù)制效果,等等。

            拖放的代碼如下:

                   m_oleDataSource.Empty();

                   m_oleDataSource.CacheGlobalData(CF_HDROP, hMemData);

                   DropResult = m_oleDataSource.DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY);

            最后一點(diǎn)要注意的是,在Windows NT 4.0以上的系統(tǒng)中,即使實(shí)際產(chǎn)生的是DROPEFFECT_MOVE動(dòng)作,DoDragDrop函數(shù)也只返回DROPEFFECT_NONE。產(chǎn)生這個(gè)問題的原因在于,Windows NT 4.0Shell會(huì)直接移動(dòng)文件本身來對移動(dòng)操作進(jìn)行優(yōu)化。返回值DROPEFFECT_MOVE最初的含義,就是通知執(zhí)行拖放操作的應(yīng)用程序去刪除原位置上的文件。但是因?yàn)?font face=Tahoma>Shell已經(jīng)替應(yīng)用程序完成了這個(gè)(刪除)動(dòng)作,所以,函數(shù)返回DROPEFFECT_NONE。要想知道文件是否真的被移動(dòng)了也很簡單,只要在函數(shù)返回之后檢查一下原位置上的文件是否存在就可以了。

            Windows 9x系列的操作系統(tǒng)也會(huì)對移動(dòng)進(jìn)行同樣的優(yōu)化動(dòng)作,但是它不會(huì)返回DROPEFFECT_NONE來代替DROPEFFECT_MOVE。詳細(xì)的解釋參見MS知識(shí)庫Q182219

            posted @ 2008-08-14 19:19 幽幽 閱讀(3200) | 評論 (0)編輯 收藏
            僅列出標(biāo)題
            共6頁: 1 2 3 4 5 6 

            <2008年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(6)

            隨筆分類(35)

            隨筆檔案(51)

            文章分類(3)

            文章檔案(3)

            相冊

            我的鏈接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久国产劲爆AV内射—百度| 91久久精品电影| 亚洲狠狠婷婷综合久久久久 | 国产成人精品久久亚洲| 蜜桃麻豆www久久国产精品| 久久久久亚洲AV片无码下载蜜桃| 精品国产乱码久久久久久郑州公司 | 久久精品国产99久久香蕉| 久久久www免费人成精品| 久久99国产精品久久| 久久亚洲精品国产精品婷婷 | 久久国产精品99精品国产| 欧美日韩成人精品久久久免费看| 久久精品国产亚洲av日韩| 午夜精品久久久久9999高清| 久久青草国产手机看片福利盒子| 亚洲美日韩Av中文字幕无码久久久妻妇| 久久国产色AV免费观看| 久久精品桃花综合| 国产ww久久久久久久久久| 国产精品福利一区二区久久| 亚洲国产精品无码久久一线| 一级女性全黄久久生活片免费 | 精品久久久久中文字| 91精品国产高清久久久久久io | 四虎国产精品免费久久久| 乱亲女H秽乱长久久久| 少妇无套内谢久久久久| 青青热久久国产久精品 | 久久久精品波多野结衣| 久久成人国产精品二三区| 看久久久久久a级毛片| 色欲久久久天天天综合网| 久久精品国产亚洲AV香蕉| 伊人久久大香线蕉综合网站| 中文字幕久久亚洲一区| 欧美伊人久久大香线蕉综合 | 国产一级持黄大片99久久| 久久r热这里有精品视频| 国产国产成人久久精品| 无码任你躁久久久久久久|