• <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>

            我住包子山

            this->blog.MoveTo("blog.baozishan.in")

            #

            ATL初學小記

             初學ATL...從頭開始吧


            <B>#include <shlobj.h>
            #include <comdef.h></B>
             
            class ATL_NO_VTABLE CDLLRegShlExt :
              public CComObjectRootEx<CComSingleThreadModel>,
              public CComCoClass<CDLLRegShlExt, &CLSID_DllRegShlExt>,
              <STRIKE>public IDllRegShlExt,</STRIKE>
              <B>public IShellExtInit</B>
            {
              BEGIN_COM_MAP(CDLLRegShlExt)
                <STRIKE>COM_INTERFACE_ENTRY(IDllRegShlExt)</STRIKE>
                <B>COM_INTERFACE_ENTRY(IShellExtInit)</B>
              END_COM_MAP()


            template<
            class ThreadModel
            >
            class CComObjectRootEx : public CComObjectRootBase

            這里CComObjectRootEx是一個ATL的類
            我看來大概是管理Com對象的一個類,是搞計數的吧,一個實現COM的類必須要繼承它的
            它還是個模板類,模板參數是ThreadModel:
            CComSingleThreadModel, CComMultiThreadModel, or CComMultiThreadModelNoCS. You can accept the server's default thread model by setting ThreadModel to CComObjectThreadModel or CComGlobalsThreadModel

            A class that implements a COM server must inherit from CComObjectRootEx or CComObjectRoot.


            template<
            class T,
            const CLSID* pclsid = &CLSID_NULL
            >
            class CComCoClass

            CComCoClass的類應該之前

             


             繼續加一些新的東西 看MSDN Magzine 關于COM的東西,提到一些對于rgs注冊腳本的使用前提
            Way back in the November and December 1999 issues of Microsoft Systems Journal (now known as MSDN®Magazine), I showed how to build a Band Object for Internet Explorer using the Active Template Library (ATL) IRegistrar interface. (Band Objects need to register a special category CATID_DeskBand.) IRegistrar is a really cool tool that lets you write a registration script (.RGS file) to add your registry entries, instead of calling registry functions like RegOpenKey, RegSetValue, and the rest. Figure 1 shows a typical script.

            這一段講IRegistrar接口的作用,hoho

             

            posted @ 2007-05-16 23:03 Gohan 閱讀(368) | 評論 (0)編輯 收藏

            結束與Winpcap的學習,有機會可以學DX

            MFC的問題就是在XP下占內存比較大,我不知道怎么優化,以后有空可以用win32 sdk完成一些事情.
            最近在學關于FTP 協議的一些相關文檔,準備在網絡應用方面再學習一點.
            http://cr.yp.to/ftp.html
            一個ftp協議的介紹...個人覺得很全面

            posted @ 2007-05-14 17:01 Gohan 閱讀(184) | 評論 (0)編輯 收藏

            winpcap學了點

            東西這幾天就能弄個大概了winpcap弄差不多,socket用mfc的就能弄好了。
            mfc程序真的占用內存好多,做好這個以后決定用sdk /c 重寫這個東西

            posted @ 2007-05-05 01:19 Gohan 閱讀(232) | 評論 (0)編輯 收藏

            今天考試結束,學習了解一下winpcap。。

            信號與系統考得很爛,準備了一晚上并不算理想,主要原因是高數計算基礎爛+以及一些常用式沒記住
            有些東西很麻煩,很多東西有文檔什么的記什么嘛

            今天看了點winpcap的文檔
            做了和單純用raw的對比
            發現winpcap得到的包大小跟ipHeader的包頭大小關系很奇怪,不是線形,所以可以解釋為什么raw計算流量根本不準。。。不知道什么原因。。

            來大學還是跟過去一般的懶+貪玩。。。想改掉

            五一把計電算網速的東西弄出來吧。。

            今晚開始不打游戲。。

            posted @ 2007-04-27 22:13 Gohan 閱讀(204) | 評論 (0)編輯 收藏

            這個月開始只學CS了

            開學到現在一直懶洋洋的,早上老睡到10點多12點,落了不少課。
            假期到現在斷續的學winsock,在做網速檢測實現發現用原始套接字raw捕獲消息報得到的數據(包的大?。┖懿粶蚀_,以前用CS寫的那個調用別人的一個Develop Kit 的測速軟件卻還比較準,不知道是為什么??個人直覺判斷是因為那個develop kit用了winpcap,要寫的東西只有先放放了。

            GPCT為了推廣他們的技術辦了個比賽,我和WF同學合作準備把它拿下,CS以前沒怎么學,別的什么的也沒會多少,還是搞搞突擊吧。好好抓住這次鍛煉機會吧

            posted @ 2007-03-31 16:17 Gohan 閱讀(224) | 評論 (0)編輯 收藏

            VC++的Unicode編程


            ??

            VC++的Unicode編程
            來自 vckbase? 我最近在使用VS2005做VC++/MFC方面的制作遇到了一些問題,這篇文章能夠解決很多關于寬字符的周邊。。呵呵,直接貼過來了,雖然很多貼圖是VC6的
            作者:韓耀旭

            下載源代碼

            一、什么是Unicode

              先從ASCII說起,ASCII是用來表示英文字符的一種編碼規范。每個ASCII字符占用1個字節,因此,ASCII編碼可以表示的最大字符數是255(00H—FFH)。其實,英文字符并沒有那么多,一般只用前128個(00H—7FH,最高位為0),其中包括了控制字符、數字、大小寫字母和其它一些符號。而最高位為1的另128個字符(80H—FFH)被稱為“擴展ASCII”,一般用來存放英文的制表符、部分音標字符等等的一些其它符號。
              這種字符編碼規則顯然用來處理英文沒有什么問題。但是面對中文、阿拉伯文等復雜的文字,255個字符顯然不夠用。
            于是,各個國家紛紛制定了自己的文字編碼規范,其中中文的文字編碼規范叫做“GB2312—80”,它是和ASCII兼容的一種編碼規范,其實就是利用擴展ASCII沒有真正標準化這一點,把一個中文字符用兩個擴展ASCII字符來表示,以區分ASCII碼部分。
              但是這個方法有問題,最大的問題就是中文的文字編碼和擴展ASCII碼有重疊。而很多軟件利用擴展ASCII碼的英文制表符來畫表格,這樣的軟件用到中文系統中,這些表格就會被誤認作中文字符,出現亂碼。
              另外,由于各國和各地區都有自己的文字編碼規則,它們互相沖突,這給各國和各地區交換信息帶來了很大的麻煩。
            要真正解決這個問題,不能從擴展ASCII的角度入手,而必須有一個全新的編碼系統,這個系統要可以將中文、法文、德文……等等所有的文字統一起來考慮,為每一個文字都分配一個單獨的編碼。

            于是,Unicode誕生了。

              Unicode也是一種字符編碼方法,它占用兩個字節(0000H—FFFFH),容納65536個字符,這完全可以容納全世界所有語言文字的編碼。
            在Unicode里,所有的字符被一視同仁,漢字不再使用“兩個擴展ASCII”,而是使用“1個Unicode”,也就是說,所有的文字都按一個字符來處理,它們都有一個唯一的Unicode碼。

            二、使用Unicode編碼的好處

              使用Unicode編碼可以使您的工程同時支持多種語言,使您的工程國際化。
              另外,Windows NT是使用Unicode進行開發的,整個系統都是基于Unicode的。如果調用一個API函數并給它傳遞一個ANSI(ASCII字符集以及由此派生并兼容的字符集,如:GB2312,通常稱為ANSI字符集)字符串,那么系統首先要將字符串轉換成Unicode,然后將Unicode字符串傳遞給操作系統。如果希望函數返回ANSI字符串,系統就會首先將Unicode字符串轉換成ANSI字符串,然后將結果返回給您的應用程序。進行這些字符串的轉換需要占用系統的時間和內存。如果用Unicode來開發應用程序,就能夠使您的應用程序更加有效地運行。

            下面例舉幾個字符的編碼以簡單演示ANSI和Unicode的區別:

            字符 ?A ?N ?和
            ANSI碼 ?41H ?4eH ?cdbaH
            Unicode碼 ?0041H ?004eH ?548cH

            三、使用C++進行Unicode編程

              對寬字符的支持其實是ANSI C標準的一部分,用以支持多字節表示一個字符。寬字符和Unicode并不完全等同,Unicode只是寬字符的一種編碼方式。

            1、寬字符的定義

              在ANSI中,一個字符(char)的長度為一個字節(Byte)。使用Unicode時,一個字符占據一個字,C++在wchar.h頭文件中定義了最基本的寬字符類型wchar_t:

            typedef unsigned short wchar_t;

            從這里我們可以清楚地看到,所謂的寬字符就是無符號短整數。

            2、常量寬字符串

              對C++程序員而言,構造字符串常量是一項經常性的工作。那么,如何構造寬字符字符串常量呢?很簡單,只要在字符串常量前加上一個大寫的L就可以了,比如:

            wchar_t *str1=L" Hello";

            這個L非常重要,只有帶上它,編譯器才知道你要將字符串存成一個字符一個字。還要注意,在L和字符串之間不能有空格。

            3、寬字符串庫函數

            為了操作寬字符串,C++專門定義了一套函數,比如求寬字符串長度的函數是

            size_t __cdel wchlen(const wchar_t*);

              為什么要專門定義這些函數呢?最根本的原因是,ANSI下的字符串都是以’\0’來標識字符串尾的(Unicode字符串以“\0\0”結束),許多字符串函數的正確操作均是以此為基礎進行。而我們知道,在寬字符的情況下,一個字符在內存中要占據一個字的空間,這就會使操作ANSI字符的字符串函數無法正確操作。以”Hello”字符串為例,在寬字符下,它的五個字符是:
            0x0048 0x0065 0x006c 0x006c 0x006f
            在內存中,實際的排列是:

            48 00 65 00 6c 00 6c 00 6f 00

              于是,ANSI字符串函數,如strlen,在碰到第一個48后的00時,就會認為字符串到尾了,用strlen對寬字符串求長度的結果就永遠會是1!

            4、用宏實現對ANSI和Unicode通用的編程

              可見,C++有一整套的數據類型和函數實現Unicode編程,也就是說,您完全可以使用C++實現Unicode編程。
            如果我們想要我們的程序有兩個版本:ANSI版本和Unicode版本。當然,編寫兩套代碼分別實現ANSI版本和Unicode版本完全是行得通的。但是,針對ANSI字符和Unicode字符維護兩套代碼是非常麻煩的事情。為了減輕編程的負擔,C++定義了一系列的宏,幫助您實現對ANSI和Unicode的通用編程。
              C++宏實現ANSI和Unicode的通用編程的本質是根據”_UNICODE”(注意,有下劃線)定義與否,這些宏展開為ANSI或Unicode字符(字符串)。

            如下是tchar.h頭文件中部分代碼摘抄:

            #ifdef  _UNICODE
            typedef wchar_t     TCHAR;
            #define __T(x)      L##x
            #define _T(x)       __T(x)
            #else
            #define __T(x)      x
            typedef char            TCHAR;
            #endif 
            
              可見,這些宏根據”_UNICODE” 定義與否,分別展開為ANSI或Unicode字符。 tchar.h頭文件中定義的宏可以分為兩類:

            A、實現字符和常量字符串定義的宏我們只列出兩個最常用的宏:

            未定義_UNICODE(ANSI字符) 定義了_UNICODE(Unicode字符)
            TCHAR?char?wchar_t
            _T(x)?x?L##x

            注意:
              
            “##”是ANSI C標準的預處理語法,它叫做“粘貼符號”,表示將前面的L添加到宏參數上。也就是說,如果我們寫_T(“Hello”),展開后即為L“Hello”

            B、實現字符串函數調用的宏

            C++為字符串函數也定義了一系列宏,同樣,我們只例舉幾個常用的宏:

            未定義_UNICODE(ANSI字符) 定義了_UNICODE(Unicode字符)
            _tcschr?strchr?wcschr
            _tcscmp?strcmp?wcscmp
            _tcslen?strlen?wcslen

            四、使用Win32 API進行Unicode編程

            Win32 API中定義了一些自己的字符數據類型。這些數據類型的定義在winnt.h頭文件中。例如:

            typedef char CHAR; 
            typedef unsigned short WCHAR;    // wc,   16-bit UNICODE character 
            typedef CONST CHAR *LPCSTR, *PCSTR; 
            
            Win32 API在winnt.h頭文件中定義了一些實現字符和常量字符串的宏進行ANSI/Unicode通用編程。同樣,只例舉幾個最常用的:
            #ifdef  UNICODE 
            typedef WCHAR TCHAR, *PTCHAR;
            typedef LPWSTR LPTCH, PTCH;
            typedef LPWSTR PTSTR, LPTSTR;
            typedef LPCWSTR LPCTSTR;
            #define __TEXT(quote) L##quote      // r_winnt
            #else   /* UNICODE */               // r_winnt
            typedef char TCHAR, *PTCHAR;
            typedef LPSTR LPTCH, PTCH;
            typedef LPSTR PTSTR, LPTSTR;
            typedef LPCSTR LPCTSTR;
            #define __TEXT(quote) quote         // r_winnt
            #endif /* UNICODE */                // r_winnt
            
              從以上頭文件可以看出,winnt.h根據是否定義了UNICODE(沒有下劃線),進行條件編譯。
               Win32 API也定義了一套字符串函數,它們根據是否定義了“UNICODE”分別展開為ANSI和Unicode字符串函數。如:lstrlen。API的字符串操作函數和C++的操作函數可以實現相同的功能,所以,如果需要的話,建議您盡可能使用C++的字符串函數,沒必要去花太多精力再去學習API的這些東西。
              也許您從來沒有注意到,Win32 API實際上有兩個版本。一個版本接受MBCS字符串,另一個接受Unicode字符串。例如:其實根本沒有SetWindowText()這個API函數,相反,有SetWindowTextA()和SetWindowTextW()。后綴A表明這是MBCS函數,后綴W表示這是Unicode版本的函數。這些API函數的頭文件在winuser.h中聲明,下面例舉winuser.h中的SetWindowText()函數的聲明部分:
            #ifdef UNICODE
            #define SetWindowText  SetWindowTextW
            #else
            #define SetWindowText  SetWindowTextA
            #endif // !UNICODE
            
              可見,API函數根據定義UNICODE與否決定指向Unicode版本還是MBCS版本。
              細心的讀者可能已經注意到了UNICODE和_UNICODE的區別,前者沒有下劃線,專門用于Windows頭文件;后者有一個前綴下劃線,專門用于C運行時頭文件。換句話說,也就是在ANSI C++語言里面根據_UNICODE(有下劃線)定義與否,各宏分別展開為Unicode或ANSI字符,在Windows里面根據UNICODE(無下劃線)定義與否,各宏分別展開為Unicode或ANSI字符。
              在后面我們將會看到,實際使用中我們不加嚴格區分,同時定義_UNICODE和UNICODE,以實現UNICODE版本編程。

            五、VC++6.0中編寫Unicode編碼的應用程序

              VC++ 6.0支持Unicode編程,但默認的是ANSI,所以開發人員只需要稍微改變一下編寫代碼的習慣便可以輕松編寫支持UNICODE的應用程序。
              使用VC++ 6.0進行Unicode編程主要做以下幾項工作:

            1、為工程添加UNICODE和_UNICODE預處理選項。

              具體步驟:打開[工程]->[設置…]對話框,如圖1所示,在C/C++標簽對話框的“預處理程序定義”中去除_MBCS,加上_UNICODE,UNICODE。(注意中間用逗號隔開)改動后如圖2:


            圖一


            圖二

              在沒有定義UNICODE和_UNICODE時,所有函數和類型都默認使用ANSI的版本;在定義了UNICODE和_UNICODE之后,所有的MFC類和Windows API都變成了寬字節版本了。

            2、設置程序入口點

              因為MFC應用程序有針對Unicode專用的程序入口點,我們要設置entry point。否則就會出現連接錯誤。
              設置entry point的方法是:打開[工程]->[設置…]對話框,在Link頁的Output類別的Entry Point里填上wWinMainCRTStartup。


            圖三

            3、使用ANSI/Unicode通用數據類型

              微軟提供了一些ANSI和Unicode兼容的通用數據類型,我們最常用的數據類型有_T ,TCHAR,LPTSTR,LPCTSTR。
              順便說一下,LPCTSTR和const TCHAR*是完全等同的。其中L表示long指針,這是為了兼容Windows 3.1等16位操作系統遺留下來的,在Win32 中以及其它的32位操作系統中,long指針和near指針及far修飾符都是為了兼容的作用,沒有實際意義。P(pointer)表示這是一個指針;C(const)表示是一個常量;T(_T宏)表示兼容ANSI和Unicode,STR(string)表示這個變量是一個字符串。綜上可以看出,LPCTSTR表示一個指向常固定地址的可以根據一些宏定義改變語義的字符串。比如:

            TCHAR* szText=_T(“Hello!”);
            TCHAR szText[]=_T(“I Love You”);
            LPCTSTR lpszText=_T(“大家好!”);
            
            使用函數中的參數最好也要有變化,比如:
            MessageBox(_T(“你好”));

              其實,在上面的語句中,即使您不加_T宏,MessageBox函數也會自動把“你好”字符串進行強制轉換。但我還是推薦您使用_T宏,以表示您有Unicode編碼意識。

            4、修改字符串運算問題

              一些字符串操作函數需要獲取字符串的字符數(sizeof(szBuffer)/sizeof(TCHAR)),而另一些函數可能需要獲取字符串的字節數sizeof(szBuffer)。您應該注意該問題并仔細分析字符串操作函數,以確定能夠得到正確的結果。
            ANSI操作函數以str開頭,如strcpy(),strcat(),strlen();
            Unicode操作函數以wcs開頭,如wcscpy,wcscpy(),wcslen();
            ANSI/Unicode操作函數以_tcs開頭 _tcscpy(C運行期庫);
            ANSI/Unicode操作函數以lstr開頭 lstrcpy(Windows函數);
            考慮ANSI和Unicode的兼容,我們需要使用以_tcs開頭或lstr開頭的通用字符串操作函數。

            六、舉個Unicode編程的例子

            第一步:
              打開VC++6.0,新建基于對話框的工程Unicode,主對話框IDD_UNICODE_DIALOG中加入一個按鈕控件,雙擊該控件并添加該控件的響應函數:

            void CUnicodeDlg::OnButton1() 
            {
            	TCHAR* str1=_T("ANSI和UNICODE編碼試驗");
            	m_disp=str1;
            	UpdateData(FALSE);
            }
            
              添加靜態文本框IDC_DISP,使用ClassWizard給該控件添加CString類型變量m_disp。使用默認ANSI編碼環境編譯該工程,生成Unicode.exe。

            第二步:
              打開“控制面板”,單擊“日期、時間、語言和區域設置”選項,在“日期、時間、語言和區域設置”窗口中繼續單擊“區域和語言選項”選項,彈出“區域和語言選項”對話框。在該對話框中,單擊“高級”標簽,將“非Unicode的程序的語言”選項改為“日語”,單擊“應用”按鈕,如圖四:


            圖四

            彈出的對話框單擊“是”,重新啟動計算機使設置生效。
            運行Unicode.exe程序并單擊“Button1”按鈕,看,靜態文本框出現了亂碼。

            第三步:
              改為Unicode編碼環境編譯該工程,生成Unicode.exe。再次運行Unicode.exe程序并單擊“Button1”按鈕。看到Unicode編碼的優勢了吧。

            就說這些吧,祝您好運。




            最新評論 [發表評論][文章投稿] 查看所有評論 推薦給好友 打印

            還有那個轉換函數沒有說,記得有個參數是表示區域碼的
            ??中文是936?日語932,記得要用,測的時候中日英下面都跑一下,不是單單改內碼跑,最好是在各自語言版本的操作系統下面跑。 ( iv3ljf 發表于 2007-2-1 12:27:00)
            ?
            樓主說的沒多大用,關鍵的Unicode在98下的問題沒有說
            Dll和EXE在98下使用Unicode的問題沒有說

            等于沒說 ( sheds 發表于 2007-1-4 20:18:00)
            ?
            好文章,謝謝。最近正為這個苦惱呢 ( freewind2000 發表于 2007-1-3 22:14:00)
            ?
            .......................................................
            More...


            版權所有 ? 2006 VC知識庫?

            posted @ 2007-03-11 10:16 Gohan 閱讀(834) | 評論 (0)編輯 收藏

            [一篇VC小文章]VC++制作一個最小化最小托盤的8步驟(Minimize your app to systray in 8 easy steps)翻譯完

            Minimize your app to systray in 8 easy steps

            By Yasar Arslan. From codeproject




            這篇文章內容比較基礎,最近看到覺得有用,順便翻譯一下
            有空可以寫一個自己的TrayIcon類,化簡這些原始的操作。

            Introduction

            這篇文章解析了 Shell_NotifyIcon 這個函數用法--用來建立你自己的應用程序的系統托盤圖標.
            這篇文章給了基本的縮小到托盤的操作過程并讓你從中了解.
            這篇文章提供8個簡單的步驟讓你成功的實現在你的程序中建立系統托盤圖標.
            源代碼提供了一個基于對話框的演示程序.

            Tray Icons

            為了用托盤圖標你需要用一個shell函數 :)

            BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid );
            

            The dwMessage?可選的參數包括 the NIM_ADD,NIM_DELETE and NIM_MODIFY功能分別是添加刪除以及修改圖標于系統圖標.

            PNOTIFYICONDATA 結構包括這些系統需要處理的任務圖標狀態區域消息等信息.
            typedef??struct _NOTIFYICONDATA {
            ??? DWORD cbSize;
            ??? HWND hWnd;
            ??? UINT uID;
            ??? UINT uFlags;
            ??? UINT uCallbackMessage;
            ??? HICON hIcon;
            ??? #if (_WIN32_IE < 0x0500)
            ??????? TCHAR szTip[64];
            ??? #else
            ??????? TCHAR szTip[128];
            ??? #endif??? #if (_WIN32_IE >= 0x0500)
            ??????? DWORD dwState;
            ??????? DWORD dwStateMask;
            ??????? TCHAR szInfo[256];
            ??????? union {
            ??????????? UINT? uTimeout;
            ??????????? UINT? uVersion;
            ??????? } DUMMYUNIONNAME;
            ??????? TCHAR szInfoTitle[64];
            ??????? DWORD dwInfoFlags;
            ??? #endif??? #if (_WIN32_IE >= 0x600)
            ??????? GUID guidItem;
            ??? #endif
            } NOTIFYICONDATA, *PNOTIFYICONDATA;

            *Note:?更完全的信息可以去參考MSDN

            Creating the Application

            Create a new VC++ dialog based project and call it TrayMin.
            創建一個名叫TrayMin的基于對話框的VC++工程

            Step: 1

            自定義消息于 TrayMinDlg.h 頭文件.

            				#define WM_TRAY_MESSAGE (WM_USER + 1)
            		

            The WM_USER 常量用來幫助用戶定義自己的消息被用來建立個人的窗口類, 定義時通常用這種格式 WM_USER+X,?這里 X 是一個整形變量.

            *更詳細的看MSDN

            Step: 2

            現在在Now add the DECLARE_MESSAGE_MAP() 之前添加下面的用戶函數吧( TrayMinDlg.h file)?? afx_msg void OnTrayNotify(WPARAM wParam, LPARAM lParam);
            ?


            當添加一個圖標到托盤時這有一個圖標的回調消息,注意到 NOTIFYICONDATA 結構中有uCallbackMessage成員是回調消息識別的關鍵,它會被傳給NIM_ADD(我們之后將會見到更詳細的)。當添加托盤圖標這個事件發生時,系統發送一個回調函數到由hWnd成員對象指定的窗口過程(winproc),wParam 參數可以用來被識別究竟發生了什么操作。lParam參數存放發生事件相關的鼠標或者鍵盤消息。舉個例子,當一個鼠標指針指向一個托盤圖標,lParam將包括WM_MOUSEMOVE

            Step: 3


            現在添加下面的這行在消息宏中(MessageMap)在TrayMinDlg.cpp

            ON_MESSAGE(WM_TRAY_MESSAGE,OnTrayNotify)
            ?

            現在應該是這樣的.

                BEGIN_MESSAGE_MAP(CTrayMinDlg, CDialog)
                  //{{AFX_MSG_MAP(CTrayMinDlg)
                  ON_WM_SYSCOMMAND()
                  ON_WM_PAINT()
                  ON_WM_QUERYDRAGICON()
                  ON_MESSAGE(WM_TRAY_MESSAGE ,OnTrayNotify)
                  //}}AFX_MSG_MAP
                END_MESSAGE_MAP()
            
              

            Step: 4

            現在在TrayMinDlg.cpp 定義OnTrayNotify函數,不要忘記在函數頭部添加afx_msg。

              afx_msg void CTrayMinDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam)
              {
                UINT uID; 
                UINT uMsg; 
             
                uID = (UINT) wParam;
                uMsg = (UINT) lParam; 
             
              
                if (uID != 1)
                  return;
              
                CPoint pt;  
              
              
                switch (uMsg ) 
                { 
            
                case WM_LBUTTONDOWN:
                  GetCursorPos(&pt);
                  ClientToScreen(&pt);
                  OnTrayLButtonDown(pt);
                  break;
              
                case WM_RBUTTONDOWN:
                case WM_CONTEXTMENU:
                  GetCursorPos(&pt);
                  OnTrayRButtonDown(pt);
                  break;
            
                } 
                return; 
              }
              

            Step: 5

            現在在TrayMinDlg類添加兩個成員函數來相應鼠標事件。

            實現鼠標左鍵單擊的相應

            • 函數類型:void ?
            • 函數聲明:?OnTrayLButtonDown(CPoint pt)

            實現鼠標右鍵單擊的相應

            • 函數類型: void
            • 函數聲明: OnTrayRButtonDown(CPoint pt)

            OnTrayLButtonDown(CPoint pt)的定義如下.

            				void CTrayMinDlg::OnTrayLButtonDown(CPoint pt)
                {  
                  MessageBox("You have clicked Left mouse Button ");
                }
              

            The Declaration of OnTrayRButtonDown(CPoint pt) is as following.

            				void CTrayMinDlg::OnTrayRButtonDown(CPoint pt)
                {  
                  //m_menu is the member of CTrayMinDlg as CMenu m_menu;
                  m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_BOTTOMALIGN|
                   TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this);      
                }
              

            Step: 6

            Add two member variable to the CTrayMinDlg.
            為CTrayMinDlg添加兩個成員變量

            • Variable Type: NOTIFYICONDATA
            • Variable Name: m_TrayData;
            • Variable Type: CMenu
            • Variable Name: m_menu;


            現在添加菜單資源

            Step: 7

            現在畫一個最小化的按鈕在對話框設計中
            并且添加這個按鈕的執行函數
            void CShellDlg::OnMinimize() 
              {
                m_TrayData.cbSize = sizeof(NOTIFYICONDATA);
                //Size of this structure, in bytes. 
                
                
                m_TrayData.hWnd  = this->m_hWnd;
                //Handle to the window that receives notification //messages associated with an icon in the taskbar //status area. The Shell uses hWnd and uID to //identify which icon to operate on when //Shell_NotifyIcon is invoked. 
              
                m_TrayData.uID = 1;
                //Application-defined identifier of the taskbar icon.//The Shell uses hWnd and uID to identify which icon //to operate on when Shell_NotifyIcon is invoked. You// can have multiple icons associated with a single //hWnd by assigning each a different uID. 
            
                m_TrayData.uCallbackMessage  = WM_TRAY_MESSAGE;
                //Application-defined message identifier. The system //uses this identifier to send notifications to the //window identified in hWnd. These notifications are //sent when a mouse event occurs in the bounding //rectangle of the icon, or when the icon is selected //or activated with the keyboard. The wParam parameter //of the message contains the identifier of the taskbar //icon in which the event occurred. The lParam parameter //holds the mouse or keyboard message associated with the// event. For example, when the pointer moves over a //taskbar icon, lParam is set to WM_MOUSEMOVE. 
                
            
            
                m_TrayData.hIcon = this->m_hIcon;
                //Handle to the icon to be added, modified, or deleted
                
                strcpy(m_TrayData.szTip,"My Icon");
                //Pointer to a null-terminated string with the text //for a standard ToolTip. It can have a maximum of 64 //characters including the terminating NULL. 
                
                
                m_TrayData.uFlags = NIF_ICON|NIF_MESSAGE;
                //Flags that indicate which of the other members contain 
                valid data.  
              
            
                BOOL bSuccess = FALSE;
                BOOL BSus = FALSE;
            
                BSus = m_menu.LoadMenu(IDR_MENU1);
                if(!(BSus))
                  MessageBox("Unabled to Loa menu");
            
                bSuccess = Shell_NotifyIcon(NIM_ADD,&m_TrayData);
            
                if(!(bSuccess))
                  MessageBox("Unable to Set Tary Icon");
                else
                {
                  this->ShowWindow(SW_MINIMIZE);
                  this->ShowWindow(SW_HIDE);
            
                }
              }
              
              

            Step: 8


            在退出菜單的執行函數寫下如下

            Shell_NotifyIcon(NIM_DELETE,&m_TrayData);
            ? DestroyWindow();


            現在可以運行程序,并且嘗試最小化按鈕的使用(他會最小化導系統托盤)。
            現在盡情發揮,完善這些步驟,完成自己的系統托盤圖標吧!

            Yasar Arslan

            posted @ 2007-03-06 19:06 Gohan 閱讀(1880) | 評論 (0)編輯 收藏

            翻譯一篇文章Introduction to Multi-threaded Code 多線程編程的一些代碼 已經全譯好了

            Someone recently asked me what I recommend for synchronizing worker threads and I suggested setting an event. This person's response was that you could not do that since worker threads do not support a message pump (UI threads are required to support messages). The confusion here is that events and messages are different animals under windows.

            我忘記了我從哪里copy的這些例子代碼,他們可是非常簡單而有趣的。如果有人知道這些代碼的作者,我一定要好好感謝你和這位作者。

            注意這里有很多對于沒有提及的MFC的支持。像_beginthread(一個C運行時庫調用)的API可以在MFC應用程序中替換成AfxBeginThread

            無同步(No Synchronization)

            這第一個例子描述了兩個互不同步的線程。進程中的首要線程--主函數循環,輸出全局整形數組的內容。還有一個線程“Thread”不停的給數組每個元素+1。
            ?The thread called "Thread" continuously populates the global array of integers.

            				  #include <process.h>
            				  #include <stdio.h>
            				int a[ 5 ];
              
              void Thread( void* pParams )
              { int i, num = 0;
              
                while ( 1 )
                { 
                   for ( i = 0; i < 5; i++ ) a[ i ] = num;
                   num++;
                }
              }
              
              int main( void )
              { 
                 _beginthread( Thread, 0, NULL );
              
                 while( 1 )
                    printf("%d %d %d %d %d\n", 
                           a[ 0 ], a[ 1 ], a[ 2 ],
                           a[ 3 ], a[ 4 ] );
              
               return0;
              }
            

            注意這個例子的輸出,紅色的數處在一個主線程搶先于Thread工作過程中執行的打印動作

            81751652 81751652 81751651 81751651 81751651
            81751652 81751652 81751651 81751651 81751651
            83348630 83348630 83348630 83348629 83348629
            83348630 83348630 83348630 83348629 83348629
            83348630 83348630 83348630 83348629 83348629

            ?

            關鍵區域/臨界區域 對象(Critical Section Objects)

            如果你想讓主線程等待Thread線程處理好全局數組再做打印,一種解決方法是使用關鍵區域對象。
            關鍵區域對象提供同步于使用互斥器(Mutex)對象很相似, 除了關鍵區域對象之能在一個進程內發揮效用。Event, mutex,?以及 semaphore?對象也可以用在單進程的應用程序中, 但是關鍵區域對象提供一個相對快捷更加高效的同步機制. 就像互斥器一樣, 一個關鍵區域對象只能同時被一個線程擁有, 這個關鍵區域能夠在同時發生的數據存取時保護共享資源. 獲取關鍵區域的先后順序不定,可是不用太擔心,系統對于每一個線程都是平等的。

            ???  
              CRITICAL_SECTION cs;
              int a[ 5 ];
              
              void Thread( void* pParams )
              {
                int i, num = 0;
              
                while ( TRUE )
                {
                   EnterCriticalSection( &cs );
                   for ( i = 0; i < 5; i++ ) a[ i ] = num;
                   LeaveCriticalSection( &cs );
                   num++;
                }
              }
              
              int main( void )
            { InitializeCriticalSection( &cs ); _beginthread( Thread, 0, NULL ); while( TRUE ) { EnterCriticalSection( &cs ); printf( "%d %d %d %d %d\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] ); LeaveCriticalSection( &cs ); } return 0; }

            If you are running Windows 9x/NT/2000, you can run this program by clicking here.

            互斥器(Mutex Objects)

            一個互斥器是一個信號狀態的同步對象,當它不屬于任何一個線程時就用信號來體現,當被擁有時他的信號狀態就為None. 同一時刻只有一個線程可以擁有互斥器, 互斥器這個名字來自于他們對于并列的線程存取共享資源時表現出的行為。舉個例子,避免兩個線程同時寫入一個共享內存,每一個線程當需要執行存取共享資源的代碼時首先等待直到自己獲得擁有權. 在存取共享資源之后,線程釋放對互斥器的擁有權。

            兩個或以上的進程可以調用CreateMutex 來建立同樣名字的互斥器. 實際上第一個進程建立的這個互斥器, 隨后的進程只是得到了那個存在的互斥器的句柄. 這能使多進程共用一個互斥器, 當然用戶應該有確保建立互斥器的進程首先啟動的責任. 使用這種技術,你應該將這個 bInitialOwner標記設置成FALSE; 否則, 它可以因不同的進程最初擁有它而帶來困難.

            多進程可以有同一個mutex對象的句柄, 讓mutex對象能夠用于多進程間同步. 下面的對象共享機制是適用的:

            • 一個子進程通過CreateProcess?函數被建立,當CreateMutex的lpMutexAttributes?參數給予相應的mutex對象指針它可以繼承到一個mutex對象的句柄.
            • 一個進程可以在DuplicateHandle 函數中指定一個mutex對象句柄來建立一個句柄的拷貝由其他進程使用.
            • 一個繼承可以指定一個mutex的名字通過 CreateMutex 函數得到這個mutex對象的句柄.

            總的來說, 如果你想要進行線程同步,臨界區域更高效些.

            				#include <windows.h>
            				#include <process.h>
            				#include <stdio.h>
              
              HANDLE hMutex;
              int a[ 5 ];
              
              void Thread( void* pParams )
              { 
                 int i, num = 0;
              
                 while ( TRUE )
                 { 
                    WaitForSingleObject( hMutex, INFINITE );
                    for ( i = 0; i < 5; i++ ) a[ i ] = num;
                    ReleaseMutex( hMutex );
                    num++;
                 }
              }
              
              int main( void )
              {
                 hMutex = CreateMutex( NULL, FALSE, NULL );
                 _beginthread( Thread, 0, NULL );
              
                 while( TRUE )
            { WaitForSingleObject( hMutex, INFINITE ); printf( "%d %d %d %d %d\n", a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] ); ReleaseMutex( hMutex ); } return0; }

            If you are running Windows 9x/NT/2000, you can run this program by clicking here.

            Event Objects事件對象

            若我們想要強制第二線程在主線程完成全局數組的內容輸出時執行該如何?這樣的話每行的輸出就只是遞增1。

            一個事件對象也是一個可以通過SetEvent or PulseEvent 函數設置像信號般的狀態的同步對象. 下面是兩種類型的事件對象.

            Object Description
            Manual-reset event
            手動激發對象
            只有使用ResetEvent 函數才可以將其設置為無激發狀態. 當它在激發狀態時, 它會激發所有正在等待的線程, 執行對相同 event對象的線程會立即從wait函數返回.
            Auto-reset event
            自動激發對象
            一個只相應一個線程的wait函數的事件對象(當這個對象是激發狀態),wait函數返回同時事件對象自動變成無激發狀態?,當沒有線程執行wait事件對象仍然是激發狀態.

            event object的用處就在于它可以在它發生時向等待著的線程發出信號標志從而使其wait結束.?舉個例子, 在overlapped I/O 操作時, 當異步操作完成時系統設置了那個由程序員指定(specified)的事件對象為信號狀態. A 一個單一線程可以指定許多不同的事件對象在許多同時發生的overlapped 操作運作, 調用一個多對象的wait函數可以當任意一個event object激發時結束等待.

            在一個線程中可使用 CreateEvent 函數建立一個event object. 在這個線程中指定這個event object 的特性是manual-reset?或者 auto-reset . 在這個線程中也可以命名一個event object. 其他進程中的線程也可以使用 OpenEvent 通過event object的名字打開一個現存event object . 另外關于mutex, event, semaphore, 以及 timer objects的其他信息, 就參考《Interprocess Synchronization》的文章.

            一個線程能夠用 PulseEvent?函數設置一個event?object 為信號狀態而后激發當前適當數量的wait線程,之后切換為無信號狀態 .?對于一個manual-reset event object, 所有的等待線程被返回(release). 對于一個auto-reset event object, 這個函數只能釋放一個等待的線程, 即使有更多線程在等待. 如果沒有線程在函數調用時等待, PulseEvent 只是簡單的將事件狀態設為無信號并且返回(個人注釋,這應該是跟setevent最不相同的地方?。?

            Collapse
            				  #include <windows.h>
            				  #include <process.h>
            				  #include <stdio.h>
              
              HANDLE hEvent1, hEvent2;
              int a[ 5 ];
              
              void Thread( void* pParams )
              {
                 int i, num = 0;
            
                 while ( TRUE )
                 {
                    WaitForSingleObject( hEvent2, INFINITE );
                    for ( i = 0; i < 5; i++ ) a[ i ] = num;
                    SetEvent( hEvent1 );
                    num++;
                 }
              }
              
              int main( void )
              {
                 hEvent1 = CreateEvent( NULL, FALSE, TRUE, NULL );
                 hEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL );
              
                 _beginthread( Thread, 0, NULL );
              
                 while( TRUE )
                 { 
                    WaitForSingleObject( hEvent1, INFINITE );
                    printf( "%d %d %d %d %d\n", 
                            a[ 0 ], a[ 1 ], a[ 2 ],
                            a[ 3 ], a[ 4 ] );
                    SetEvent( hEvent2 );
                 }
                 return0;
              }
            

            If you are running Windows 9x/NT/2000, you can run this program by clicking here.

            Summary of Synchronization Objects

            The MSDN News for July/August 1998 has a front page article on Synchronization Objects. The following table is from that article:

            Name Relative speed Cross process Resource counting Supported platforms
            Critical Section Fast No No (exclusive access) 9x/NT/CE
            Mutex Slow Yes No (exclusive access) 9x/NT/CE
            Semaphore Slow Yes Automatic 9x/NT
            Event Slow Yes Yes 9x/NT/CE
            Metered Section Fast Yes Automatic 9x/NT/CE

            by?William T. Block


            from codeproject

            謝謝回復的補充 ~~,上面拼錯了個詞,改過。。譯完了

            posted @ 2007-02-16 14:06 Gohan 閱讀(985) | 評論 (1)編輯 收藏

            These days work..

            玩太閣立志傳比較墮落。。。
            這兩天學做了幾個Win Socket幾個demo,有點心得,在win32做網絡編程基本了解,現在想知道怎么能做一個支持斷點續傳的下載軟件。
            那幾個計劃還在醞釀。
            電子制作還是一無所知。。

            hostent *hp;
            sockaddr_in server;

            下面這句話還是太生猛
            server.sin_addr.s_addr=*((ULONG *)hp->h_addr);

            容我再學深入一點再說

            posted @ 2007-02-06 21:56 Gohan 閱讀(217) | 評論 (1)編輯 收藏

            繼續在這寫些隨筆吧

            之前很長一段時間沒來,各方面的原因,最主要是因為登陸密碼重置后我沒有及時得到。
            這個學期完成了,好幾門科目過的很險。。。
            很多東西還沒學成。。
            放棄netbios的學習,那本書太讓我失望,直接開學WinSock。。
            讓一切繼續

            posted @ 2007-02-02 17:07 Gohan 閱讀(255) | 評論 (0)編輯 收藏

            僅列出標題
            共16頁: First 8 9 10 11 12 13 14 15 16 
            久久久久人妻一区二区三区| 久久亚洲中文字幕精品有坂深雪| 久久亚洲精品视频| 久久久国产精品网站| 久久久WWW成人免费毛片| 久久久久亚洲国产| 久久se精品一区精品二区| 久久免费观看视频| 精品久久无码中文字幕| 久久最新免费视频| www.久久99| 国产69精品久久久久APP下载 | 国产福利电影一区二区三区,免费久久久久久久精 | 久久99九九国产免费看小说| 久久综合88熟人妻| 久久中文字幕无码专区 | 久久99精品久久久久久9蜜桃| 人妻无码精品久久亚瑟影视 | 品成人欧美大片久久国产欧美| 久久亚洲精品国产亚洲老地址| 青青青青久久精品国产h| 嫩草伊人久久精品少妇AV| 一本久久精品一区二区| 国产伊人久久| 国产精品gz久久久| 99久久久精品| 精品蜜臀久久久久99网站| 亚洲国产精品无码久久久蜜芽 | 91麻豆精品国产91久久久久久| 久久亚洲AV成人出白浆无码国产| 亚洲午夜福利精品久久| 久久e热在这里只有国产中文精品99| 99久久这里只有精品| 国产精品久久成人影院| 国内精品人妻无码久久久影院| 亚洲国产精品久久电影欧美| 久久91精品国产91久| 亚洲成色WWW久久网站| 99精品久久久久久久婷婷| 久久精品国产亚洲av麻豆图片| 久久精品一区二区三区AV|