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

            用SkinMagic工具包創(chuàng)建換皮膚程序
            作者:北京林業(yè)大學(xué) 李少杰

            下載本文示例工程

            代碼運(yùn)行效果圖如下:




            以前看到瑞星和金山詞霸有換皮膚功能,很是羨慕,自己也想做個(gè)換皮膚的程序,但畢竟自己能力有限,以前在此處看到一篇介紹換皮膚功能的文章,但只能應(yīng)用在對(duì)話框程序上。我也試過像BCGCBar這樣的大型軟件,給我的感覺是軟件老是出問題,應(yīng)用起來也很復(fù)雜。在年前我就看到本站有SkinMagic軟件包,但當(dāng)時(shí)不知怎么用,發(fā)了貼子也沒人回答。可能是很少有人用的緣故吧,本站也未更新此軟件包。偶然的一次機(jī)會(huì),讓我知道了怎樣來用它,
            而且編譯出來的軟件體積很小,所以在這里向大家介紹一下,希望對(duì)大家有些幫助。
            如何使用:
            ① 新建工程后,將SkinMagic包中的SkinMagicLib.h、SkinMagicLib.lib、DETOURS.lib拷貝到所在文件夾下,點(diǎn)擊Project->Add To Project->Files,包含到工程中。
            ② 在Resource View中點(diǎn)擊Import 菜單引入幾個(gè)Skin二進(jìn)制文件放在相同的“SKINMAGIC”文件夾下,分別給起一個(gè)名字(見源程序)。
            ③ 在stdafx.h中加入#include "SkinMagicLib.h"
            ④ 在此處添加如下內(nèi)容

            if (!ProcessShellCommand(cmdInfo))
            return FALSE;
            /////////////////////////////////////////////////////////////////////////////////////////
            VERIFY( 1 == InitSkinMagicLib( AfxGetInstanceHandle(), "Demo" ,NULL,NULL ) );//初始化類庫
            VERIFY( 1 == LoadSkinFromResource( AfxGetInstanceHandle()  , "KROMO" ,"SKINMAGIC") );//從資源中加載皮膚
            VERIFY( 1 == SetWindowSkin( m_pMainWnd->m_hWnd , "MainFrame" ));
            VERIFY( 1 == SetDialogSkin( "Dialog" ) );
            ((CMainFrame*)m_pMainWnd)->m_bSkinned = TRUE;
            ((CMainFrame*)m_pMainWnd)->m_nIndex = 0;
            ////////////////////////////////////////////////////////////////////////////////////////////
            m_pMainWnd->ShowWindow(SW_SHOW);
            m_pMainWnd->UpdateWindow();
            
            ⑤ 在MainFrame中加入換皮膚菜單,及相應(yīng)的函數(shù),在函數(shù)中加載皮膚。
            void CMainFrame::OnDevior()
            {
            LoadSkinFromResource( AfxGetInstanceHandle()  , "DEVIOR" ,"SKINMAGIC") ;
            }
            
            到此為止,完美的換皮膚程序就出來了。
            posted @ 2009-05-21 09:32 wrh 閱讀(273) | 評(píng)論 (0)編輯 收藏

            文章導(dǎo)讀:  [準(zhǔn)備工作]  1、將SkinMagicTrial.dll放置在調(diào)試目錄  2、設(shè)置庫文件目錄,在項(xiàng)目[連接器]的[附加依賴項(xiàng)]中加入庫SkinMagicTrial.lib  3、在項(xiàng)目的stdafx.h文件中加入頭文件 #include "SkinMagicLib.h"  [創(chuàng)建過程]  1、初始化SkinMagic庫: 

              [準(zhǔn)備工作]

              1、將SkinMagicTrial.dll放置在調(diào)試目錄

              2、設(shè)置庫文件目錄,在項(xiàng)目[連接器]的[附加依賴項(xiàng)]中加入庫SkinMagicTrial.lib

              3、在項(xiàng)目的stdafx.h文件中加入頭文件 #include "SkinMagicLib.h"

              [創(chuàng)建過程]

              1、初始化SkinMagic庫:

              要使用SkinMagic,這一步必不可少。在應(yīng)用程序類的InitInstance()函數(shù)中行加入如下代碼(粗體部分):

              CWinApp::InitInstance();

              VERIFY( 1 == InitSkinMagicLib(AfxGetInstanceHandle(), NULL ,

              NULL, NULL ));

              說明:

              int InitSkinMagicLib( //初始化SkinMagic工具庫
              HINSTANCE hInstance, //應(yīng)用程序句柄
              char* szApplication , //皮膚文件中定義的應(yīng)用程序名,置為NULL即可
              char* szRegCode, //SkinMagic的使用注冊(cè)碼。若無置為NULL
              char* szReserved2 //保留位,為NULL
              );

              2、調(diào)入皮膚文件:

              皮膚的調(diào)用有兩種方法,一是直接從皮膚文件中調(diào)用,另一種方法是從資源文件中調(diào)用,分別說明如下:

              1)從皮膚文件中調(diào)用皮膚:緊接上句,加入如下代碼

              VERIFY( 1 == LoadSkinFile("corona.smf"));

              2)從資源文件中調(diào)用皮膚:

              VERIFY(1 == LoadSkinFromResource(NULL,"FUTURA","skin"));

              說明:

            int LoadSkinFromResource(
              HMODULE hModule, //包含皮膚文件的模塊句柄,若NULL表面在本模塊中
             char* lpSkinName , //皮膚資源的名稱
              char* lpType); //資源的類型

              3、為窗口添加皮膚:

              1)為標(biāo)準(zhǔn)窗口(擁有標(biāo)題欄、系統(tǒng)菜單、可變大小等特征,比如文檔/視圖結(jié)構(gòu)和有菜單的對(duì)話框)添加皮膚,通常用于主窗口。在應(yīng)用程序類的InitInstance()函數(shù)的底部加入如下代碼:

              VERIFY( 1 == SetWindowSkin( m_pMainWnd->m_hWnd , "MainFrame" ));

              m_pMainWnd->ShowWindow(SW_SHOW);

              m_pMainWnd->UpdateWindow();

              說明:

              int SetWindowSkin(
              HWND hWnd, //要使用皮膚的窗口句柄
              char* lpSkinName //為skinFrameWnd對(duì)象指定的名稱
              );

              2)為對(duì)話框添加皮膚

              在對(duì)話框顯示之前調(diào)用,通常在應(yīng)用程序初始化函數(shù)中調(diào)用

              VERIFY( 1 == SetWindowSkin( m_pMainWnd->m_hWnd , "MainFrame" ));

              VERIFY( 1 == SetDialogSkin( "Dialog" ) );

              m_pMainWnd->ShowWindow(SW_SHOW);

              m_pMainWnd->UpdateWindow();

              說明:

              int SetDialogSkin(
              char* lpSkinName //為skinFrameWnd對(duì)象指定的名稱
              );
              使用該函數(shù)后,以后程序創(chuàng)建的對(duì)話框都將使用該皮膚,但對(duì)話框大小不可變。
            3)為單個(gè)對(duì)話框窗口添加皮膚,例如在對(duì)話框視圖中:重載對(duì)話框視圖的創(chuàng)建函數(shù)OnCreate,加入如下代碼:

              VERIFY( 1 == SetSingleDialogSkin( m_hWnd, "Dialog" ) );

              EnableWindowScrollbarSkin( m_hWnd , SB_BOTH );

              說明:

              int SetSingleDialogSkin(
              HWND hWnd, //要使用皮膚的窗口句柄
              char* lpSkinName //為skinFrameWnd對(duì)象指定的名稱
              );
              int EnableWindowScrollbarSkin( //為滾動(dòng)條添加皮膚
              HWND hWnd, //要使用皮膚的窗口句柄
              int* fnBar //要使用皮膚的滾動(dòng)條,SB_BOTH表明是橫豎都是用皮膚
              );

              4、釋放SkinMagic資源
             
              重載應(yīng)用程序的ExitInstance()函數(shù),添加如下代碼:

              ExitSkinMagicLib();

            posted @ 2009-05-20 20:57 wrh 閱讀(479) | 評(píng)論 (0)編輯 收藏
            如果n <= 0,返回NULL
            如果n == 1,返回"",也就是一個(gè)空串。
            如果成功返回值等于string,也就是獲得的字符串的首地址。
            如果出錯(cuò),或者讀到FILE的結(jié)尾,返回NULL.

            以下是這個(gè)函數(shù)的實(shí)現(xiàn):

            /***
            *fgets.c - get string from a file
            *
            * Copyright (c) Microsoft Corporation. All rights reserved.
            *
            *Purpose:
            * defines fgets() - read a string from a file
            *
            *******************************************************************************/

            #include <cruntime.h>
            #include <stdio.h>
            #include <dbgint.h>
            #include <file2.h>
            #include <internal.h>
            #include <mtdll.h>
            #include <tchar.h>

            /***
            *char *fgets(string, count, stream) - input string from a stream
            *
            *Purpose:
            * get a string, up to count-1 chars or '\n', whichever comes first,
            * append '\0' and put the whole thing into string. the '\n' IS included
            * in the string. if count<=1 no input is requested. if EOF is found
            * immediately, return NULL. if EOF found after chars read, let EOF
            * finish the string as '\n' would.
            *
            *Entry:
            * char *string - pointer to place to store string
            * int count - max characters to place at string (include \0)
            * FILE *stream - stream to read from
            *
            *Exit:
            * returns string with text read from file in it.
            * if count <= 0 return NULL
            * if count == 1 put null string in string
            * returns NULL if error or end-of-file found immediately
            *
            *Exceptions:
            *
            *******************************************************************************/

            _TSCHAR * __cdecl _fgetts (
            _TSCHAR *string,
            int count,
            FILE *str
            )
            {
            REG1 FILE *stream;
            REG2 _TSCHAR *pointer = string;
            _TSCHAR *retval = string;
            int ch;

            _VALIDATE_RETURN(( string != NULL ) || ( count == 0 ), EINVAL, NULL);
            _VALIDATE_RETURN(( count >= 0 ), EINVAL, NULL);
            _VALIDATE_RETURN(( str != NULL ), EINVAL, NULL);

            if (count == 0)
            {
            return NULL;
            }

            /* The C Standard states the input buffer should remain
            unchanged if EOF is encountered immediately. Hence we
            do not blank out the input buffer here */

            /* Init stream pointer */
            stream = str;

            _lock_str(stream);
            __try {

            #ifndef _UNICODE
            _VALIDATE_STREAM_ANSI_SETRET(stream, EINVAL, retval, NULL);
            #endif /* _UNICODE */
            if(retval!=NULL)
            {
            while (--count)
            {
            if ((ch = _fgettc_nolock(stream)) == _TEOF)
            {
            if (pointer == string) {
            retval=NULL;
            goto done;
            }

            break;
            }

            if ((*pointer++ = (_TSCHAR)ch) == _T('\n'))
            break;
            }
            *pointer = _T('\0');
            }


            /* Common return */
            done:

            ; }
            __finally {
            _unlock_str(stream);
            }

            return(retval);
            }
            posted @ 2009-05-20 09:22 wrh 閱讀(769) | 評(píng)論 (0)編輯 收藏
            F1: 幫助 
            Ctrl+O :Open 
            Ctrl+P :Print 
            Ctrl+N :New 
            Ctrl+Shift+F2 :清除所有書簽 
            F2 :上一個(gè)書簽 
            Shift+F2 :上一個(gè)書簽 
            Alt+F2 :編輯書簽 
            Ctrl+F2 :添加/刪除一個(gè)書簽 
            F12 :Goto definition 
            Shift+F12 :Goto reference 
            Ctrl+'Num+' :Displays the next symbol definition or reference 
            Ctrl+'Num-' :Displays the previous symbol definition or reference 
            Ctrl+J/K :尋找上一個(gè)/下一個(gè)預(yù)編譯條件 
            Ctrl+Shift+J/K :尋找上一個(gè)/下一個(gè)預(yù)編譯條件并將這一塊選定 
            Ctrl+End :文檔尾 
            Ctrl+Shift+End :選定從當(dāng)前位置到文檔尾 
            Ctrl+Home :文檔頭 
            Ctrl+Shift+Home :選定從當(dāng)前位置到文檔頭 
            Ctrl+B/Alt+F9 :編輯斷點(diǎn) 
            Alt+F3/Ctrl+F :查找 
            F3 :查找下一個(gè) 
            Shift+F3 :查找上一個(gè) 
            Ctrl+]/Ctrl+E :尋找下一半括弧 
            Ctrl+Shift+] :尋找下一半括弧并選定括弧之間的部分(包括括弧) 
            Ctrl+Shift+E :尋找下一半括弧并選定括弧之間的部分(包括括弧) 
            F4 :尋找下一個(gè)錯(cuò)誤/警告位置 
            Shift+F4 :尋找上一個(gè)錯(cuò)誤/警告位置 
            Shift+Home :選定從當(dāng)前位置到行首 
            Shift+End :選定從當(dāng)前位置到行尾 
            Ctrl+L :剪切當(dāng)前行 
            Ctrl+Shift+L :刪除當(dāng)前行 
            Alt+Shift+T :交換當(dāng)前行和上一行 
            Ctrl+Alt+T :Brings up the completion list box 
            Shift+PageDown :選定從當(dāng)前位置到下一頁當(dāng)前位置 
            Shift+PageUp :選定從當(dāng)前位置到上一頁當(dāng)前位置 
            Ctrl+Shift+Space:顯示函數(shù)參數(shù)的Tooltip 
            Ctrl+Z/Alt+Backspace :Undo 
            Ctrl+Shift+Z/Ctrl+Y :Redo 
            F8 :當(dāng)前位置變成選定區(qū)域的頭/尾(再移動(dòng)光標(biāo)或者點(diǎn)鼠標(biāo)就會(huì)選定) 
            Ctrl+Shift+F8 :當(dāng)前位置變成矩形選定區(qū)域的頭/尾(再移動(dòng)光標(biāo)或者點(diǎn)鼠標(biāo)就會(huì)選定) 
            Alt+F8 :自動(dòng)格式重排 
            Ctrl+G :Goto 
            Ctlr+X/Shift+Del:Cut 
            Ctrl+C/Ctrl+Ins :Copy 
            Ctrl+V/Shift+Ins:Paste 
            Ctrl+U :將選定區(qū)域轉(zhuǎn)換成小寫 
            Ctrl+Shift+U :將選定區(qū)域轉(zhuǎn)換成大寫 
            Ctrl+F8 :當(dāng)前行變成選定區(qū)域的頭/尾(再移動(dòng)上下光標(biāo)或者點(diǎn)鼠標(biāo)就會(huì)選定多行) 
            Ctrl+Shift+L :刪除從當(dāng)前位置到行尾 
            Ctrl+Shift+8 :將所有Tab變成`或者還原 
            Ctrl+T :顯示變量類型 
            Ctrl+↑ :向上滾屏 
            Ctrl+↓ :向下滾屏 
            Ctrl+Del :刪除當(dāng)前單詞的后半截(以光標(biāo)為分割) 
            Ctrl+Backspace :刪除當(dāng)前單詞的前半截(以光標(biāo)為分割) 
            Ctrl+← :移到前一個(gè)單詞 
            Ctrl+→ :移到后一個(gè)單詞 
            Ctrl+Shift+← :選定當(dāng)前位置到前一個(gè)單詞 
            Ctrl+Shift+→ :選定當(dāng)前位置到后一個(gè)單詞 
            Ctrl+Shift+T :將本單詞和上一個(gè)單詞互換
            posted @ 2009-04-24 15:48 wrh 閱讀(267) | 評(píng)論 (0)編輯 收藏
            數(shù)學(xué)函數(shù),所在函數(shù)庫為math.h、stdlib.h、string.h、float.h    
              ----------------------------------------------------------------------------------------------------------  
               
               
              int   abs(int   i)   返回整型參數(shù)i的絕對(duì)值    
              double   cabs(struct   complex   znum)   返回復(fù)數(shù)znum的絕對(duì)值    
              double   fabs(double   x)   返回雙精度參數(shù)x的絕對(duì)值    
              long   labs(long   n)   返回長整型參數(shù)n的絕對(duì)值    
              double   exp(double   x)   返回指數(shù)函數(shù)ex的值    
              double   frexp(double   value,int   *eptr)   返回value=x*2n中x的值,n存貯在eptr中    
              double   ldexp(double   value,int   exp);   返回value*2exp的值    
              double   log(double   x)   返回logex的值    
              double   log10(double   x)   返回log10x的值    
              double   pow(double   x,double   y)   返回xy的值    
              double   pow10(int   p)   返回10p的值    
              double   sqrt(double   x)   返回x的開方    
              double   acos(double   x)   返回x的反余弦cos-1(x)值,x為弧度    
              double   asin(double   x)   返回x的反正弦sin-1(x)值,x為弧度    
              double   atan(double   x)   返回x的反正切tan-1(x)值,x為弧度    
              double   atan2(double   y,double   x)   返回y/x的反正切tan-1(x)值,y的x為弧度    
              double   cos(double   x)   返回x的余弦cos(x)值,x為弧度    
              double   sin(double   x)   返回x的正弦sin(x)值,x為弧度    
              double   tan(double   x)   返回x的正切tan(x)值,x為弧度    
              double   cosh(double   x)   返回x的雙曲余弦cosh(x)值,x為弧度    
              double   sinh(double   x)   返回x的雙曲正弦sinh(x)值,x為弧度    
              double   tanh(double   x)   返回x的雙曲正切tanh(x)值,x為弧度    
              double   hypot(double   x,double   y)   返回直角三角形斜邊的長度(z),   x和y為直角邊的長度,z2=x2+y2    
              double   ceil(double   x)   返回不小于x的最小整數(shù)    
              double   floor(double   x)   返回不大于x的最大整數(shù)    
              void   srand(unsigned   seed)   初始化隨機(jī)數(shù)發(fā)生器    
              int   rand()   產(chǎn)生一個(gè)隨機(jī)數(shù)并返回這個(gè)數(shù)    
              double   poly(double   x,int   n,double   c[])   從參數(shù)產(chǎn)生一個(gè)多項(xiàng)式    
              double   modf(double   value,double   *iptr)   將雙精度數(shù)value分解成尾數(shù)和階    
              double   fmod(double   x,double   y)   返回x/y的余數(shù)    
              double   frexp(double   value,int   *eptr)   將雙精度數(shù)value分成尾數(shù)和階    
              double   atof(char   *nptr)   將字符串nptr轉(zhuǎn)換成浮點(diǎn)數(shù)并返回這個(gè)浮點(diǎn)數(shù)    
              double   atoi(char   *nptr)   將字符串nptr轉(zhuǎn)換成整數(shù)并返回這個(gè)整數(shù)    
              double   atol(char   *nptr)   將字符串nptr轉(zhuǎn)換成長整數(shù)并返回這個(gè)整數(shù)    
              char   *ecvt(double   value,int   ndigit,int   *decpt,int   *sign)    
              將浮點(diǎn)數(shù)value轉(zhuǎn)換成字符串并返回該字符串    
              char   *fcvt(double   value,int   ndigit,int   *decpt,int   *sign)    
              將浮點(diǎn)數(shù)value轉(zhuǎn)換成字符串并返回該字符串    
              char   *gcvt(double   value,int   ndigit,char   *buf)    
              將數(shù)value轉(zhuǎn)換成字符串并存于buf中,并返回buf的指針    
              char   *ultoa(unsigned   long   value,char   *string,int   radix)    
              將無符號(hào)整型數(shù)value轉(zhuǎn)換成字符串并返回該字符串,radix為轉(zhuǎn)換時(shí)所用基數(shù)    
              char   *ltoa(long   value,char   *string,int   radix)    
              將長整型數(shù)value轉(zhuǎn)換成字符串并返回該字符串,radix為轉(zhuǎn)換時(shí)所用基數(shù)    
              char   *itoa(int   value,char   *string,int   radix)    
              將整數(shù)value轉(zhuǎn)換成字符串存入string,radix為轉(zhuǎn)換時(shí)所用基數(shù)    
              double   atof(char   *nptr)   將字符串nptr轉(zhuǎn)換成雙精度數(shù),并返回這個(gè)數(shù),錯(cuò)誤返回0    
              int   atoi(char   *nptr)   將字符串nptr轉(zhuǎn)換成整型數(shù),   并返回這個(gè)數(shù),錯(cuò)誤返回0    
              long   atol(char   *nptr)   將字符串nptr轉(zhuǎn)換成長整型數(shù),并返回這個(gè)數(shù),錯(cuò)誤返回0    
              double   strtod(char   *str,char   **endptr)將字符串str轉(zhuǎn)換成雙精度數(shù),并返回這個(gè)數(shù),    
              long   strtol(char   *str,char   **endptr,int   base)將字符串str轉(zhuǎn)換成長整型數(shù),   并返回這個(gè)數(shù),    
              int   matherr(struct   exception   *e)   用戶修改數(shù)學(xué)錯(cuò)誤返回信息函數(shù)(沒有必要使用)    
              double   _matherr(_mexcep   why,char   *fun,double   *arg1p,   double   *arg2p,double   retval)    
              用戶修改數(shù)學(xué)錯(cuò)誤返回信息函數(shù)(沒有必要使用)    
              unsigned   int   _clear87()   清除浮點(diǎn)狀態(tài)字并返回原來的浮點(diǎn)狀態(tài)    
              void   _fpreset()   重新初使化浮點(diǎn)數(shù)學(xué)程序包    
              unsigned   int   _status87()   返回浮點(diǎn)狀態(tài)字
            posted @ 2009-04-15 10:03 wrh 閱讀(514) | 評(píng)論 (0)編輯 收藏

            在VC++6.0中missing function header (old-style formal list?)解決方法

            該函數(shù)的函數(shù)頭后邊加了分號(hào)

            去掉即可

            例如:void fun();{}就會(huì)出現(xiàn)那種情況

            posted @ 2009-03-27 10:37 wrh 閱讀(2045) | 評(píng)論 (0)編輯 收藏

            VC中沒有現(xiàn)成的函數(shù)來選擇一個(gè)文件夾,但這是經(jīng)常會(huì)用到的,怎么辦?
            自動(dòng)動(dòng)手,豐衣足食!

            使用SHBrowseForFolder,代碼如下:

            #include
              
            int SelFolder(HWND hParent, CString &strFolder)
            {
                strFolder.Empty();
             
                LPMALLOC lpMalloc;
             
                if (::SHGetMalloc(&lpMalloc) != NOERROR) return 0;
             
                char szDisplayName[_MAX_PATH];
                char szBuffer[_MAX_PATH];
                BROWSEINFO browseInfo;
                browseInfo.hwndOwner = hParent;
                browseInfo.pidlRoot = NULL; // set root at Desktop
                browseInfo.pszDisplayName = szDisplayName;
                browseInfo.lpszTitle = "Select a folder";
                browseInfo.ulFlags = BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS;
                browseInfo.lpfn = NULL;
                browseInfo.lParam = 0;
             
                LPITEMIDLIST lpItemIDList;
                if ((lpItemIDList = ::SHBrowseForFolder(&browseInfo)) != NULL)
                {
                    // Get the path of the selected folder from the    item ID list.
                    if (::SHGetPathFromIDList(lpItemIDList, szBuffer))
                    {
                        // At this point, szBuffer contains the path the user chose.
                        if (szBuffer[0] == ´\0´) return 0;
             
                        // We have a path in szBuffer! Return it.
                        strFolder = szBuffer;
                        return 1;
                    }
                    else return 1; // strResult is empty
             
                    lpMalloc->Free(lpItemIDList);
                    lpMalloc->Release();
                }
               
             return 1;
            }

             

            //////調(diào)用:

            void CMusic1Dlg::OnOK()
            {
             // TODO: Add extra validation here
             CString str;

             HWND m_hWnd = GetSafeHwnd();
             
             SelFolder(m_hWnd,str);

             m_list.AddString(str);
            // CDialog::OnOK();
            }

            //------------------------------------------------------------------------------------------------------

            //_________________________________________________________________

            “選擇文件夾”對(duì)話框的封裝


            我們經(jīng)常需要用到“選擇文件夾”對(duì)話框,相應(yīng)的API已經(jīng)很好用,但稍嫌麻煩,所以我專門將其封裝了一下,力求一步到位。

            函數(shù)封裝如下:
            /*****************************************************************
            ** 函數(shù)名:GetPath
            ** 輸 入: 無
            ** 輸 出: CString strPath
            **        strPath非空, 表示用戶選擇的文件夾路徑
            **        strPath為空, 表示用戶點(diǎn)擊了“取消”鍵,取消選擇
            ** 功能描述:顯示“選擇文件夾”對(duì)話框,讓用戶選擇文件夾
            ****************************************************************/

            CString GetPath()
            {
             CString strPath = "";
             BROWSEINFO bInfo;
             ZeroMemory(&bInfo, sizeof(bInfo));
             bInfo.hwndOwner = m_hWnd;
             bInfo.lpszTitle = _T("請(qǐng)選擇路徑: ");
             bInfo.ulFlags = BIF_RETURNONLYFSDIRS;   
             
             LPITEMIDLIST lpDlist; //用來保存返回信息的IDList
             lpDlist = SHBrowseForFolder(&bInfo) ; //顯示選擇對(duì)話框
             if(lpDlist != NULL)  //用戶按了確定按鈕
             {
              TCHAR chPath[255]; //用來存儲(chǔ)路徑的字符串
              SHGetPathFromIDList(lpDlist, chPath);//把項(xiàng)目標(biāo)識(shí)列表轉(zhuǎn)化成字符串
              strPath = chPath; //將TCHAR類型的字符串轉(zhuǎn)換為CString類型的字符串
             }
             return strPath;
            }

            調(diào)用時(shí)只需要用到以下代碼:
            CString strPath = GetPath();
            則strPath為用戶選擇的文件夾路徑。如果用戶點(diǎn)擊了對(duì)話框的取消鍵,則strPath為空字符串("");

            posted @ 2009-03-14 10:02 wrh 閱讀(5226) | 評(píng)論 (1)編輯 收藏
            char   path[MAX_PATH];  
              GetModuleFileName(NULL,path,MAX_PATH);

            GetModuleFileName(   AfxGetInstanceHandle(),szPath,MAX_PATH);


            GetModuleFileNameEx  
              The   GetModuleFileNameEx   function   retrieves   the   fully   qualified   path   for   the   specified   module.    
               
              DWORD   GetModuleFileNameEx(  
                  HANDLE   hProcess,         //   handle   to   the   process  
                  HMODULE   hModule,         //   handle   to   the   module  
                  LPTSTR   lpFilename,     //   buffer   that   receives   the   path  
                  DWORD   nSize                   //   size   of   the   buffer  
              );  
                 
              Parameters  
              hProcess    
              Handle   to   the   process   that   contains   the   module.    
              hModule    
              Handle   to   the   module.    
              lpFilename    
              Pointer   to   the   buffer   that   receives   the   fully   qualified   path   to   the   module.    
              nSize    
              Specifies   the   size,   in   bytes,   of   the   lpFilename   buffer.    
              Return   Value  
              If   the   function   succeeds,   the   return   value   specifies   the   length   of   the   string   copied   to   the   buffer.    
               
              If   the   function   fails,   the   return   value   is   zero.   To   get   extended   error   information,   call   GetLastError.    
               
              See   Also  
              Process   Status   Helper   Overview,   PSAPI   Functions,   EnumProcesses,   GetModuleBaseName     
               
            posted @ 2009-03-14 10:00 wrh 閱讀(1490) | 評(píng)論 (0)編輯 收藏

            文件的打開(fopen函數(shù))

            fopen函數(shù)用來打開一個(gè)文件,其調(diào)用的一般形式為:
            文件指針名=fopen(文件名,使用文件方式);
            其中,
            “文件指針名”必須是被說明為FILE 類型的指針變量;
            “文件名”是被打開文件的文件名;
            “使用文件方式”是指文件的類型和操作要求。
            “文件名”是字符串常量或字符串?dāng)?shù)組。
            例如:
            FILE *fp;
            fp=("file a","r");
            其意義是在當(dāng)前目錄下打開文件file a,只允許進(jìn)行“讀”操作,并使fp指向該文件。
            又如:
            FILE *fphzk
            fphzk=("c:\\hzk16","rb")
            其意義是打開C驅(qū)動(dòng)器磁盤的根目錄下的文件hzk16,這是一個(gè)二進(jìn)制文件,只允許按二進(jìn)制方式進(jìn)行讀操作。兩個(gè)反斜線“\\ ”中的第一個(gè)表示轉(zhuǎn)義字符,第二個(gè)表示根目錄。

            使用文件的方式共有12種,下面給出了它們的符號(hào)和意義。
            文件使用方式 意義
            “rt” 只讀打開一個(gè)文本文件,只允許讀數(shù)據(jù)
            “wt” 只寫打開或建立一個(gè)文本文件,只允許寫數(shù)據(jù)
            “at” 追加打開一個(gè)文本文件,并在文件末尾寫數(shù)據(jù)
            “rb” 只讀打開一個(gè)二進(jìn)制文件,只允許讀數(shù)據(jù)
            “wb” 只寫打開或建立一個(gè)二進(jìn)制文件,只允許寫數(shù)據(jù)
            “ab” 追加打開一個(gè)二進(jìn)制文件,并在文件末尾寫數(shù)據(jù)
            “rt+” 讀寫打開一個(gè)文本文件,允許讀和寫
            “wt+” 讀寫打開或建立一個(gè)文本文件,允許讀寫
            “at+” 讀寫打開一個(gè)文本文件,允許讀,或在文件末追加數(shù)據(jù)
            “rb+” 讀寫打開一個(gè)二進(jìn)制文件,允許讀和寫
            “wb+” 讀寫打開或建立一個(gè)二進(jìn)制文件,允許讀和寫
            “ab+” 讀寫打開一個(gè)二進(jìn)制文件,允許讀,或在文件末追加數(shù)據(jù)

            對(duì)于文件使用方式有以下幾點(diǎn)說明:
            1) 文件使用方式由r,w,a,t,b,+六個(gè)字符拼成,各字符的含義是:
            r(read): 讀
            w(write): 寫
            a(append): 追加
            t(text): 文本文件,可省略不寫
            b(banary): 二進(jìn)制文件
            +: 讀和寫
            2) 凡用“r”打開一個(gè)文件時(shí),該文件必須已經(jīng)存在,且只能從該文件讀出。
            3) 用“w”打開的文件只能向該文件寫入。若打開的文件不存在,則以指定的文件名建立該文件,若打開的文件已經(jīng)存在,則將該文件刪去,重建一個(gè)新文件。
            4) 若要向一個(gè)已存在的文件追加新的信息,只能用“a”方式打開文件。但此時(shí)該文件必須是存在的,否則將會(huì)出錯(cuò)。
            5) 在打開一個(gè)文件時(shí),如果出錯(cuò),fopen將返回一個(gè)空指針值NULL。在程序中可以用這一信息來判別是否完成打開文件的工作,并作相應(yīng)的處理。因此常用以下程序段打開文件:
            6) if((fp=fopen("c:\\hzk16","rb")==NULL)
            {
            printf("\nerror on open c:\\hzk16 file!");
            getch();
            exit(1);
            }

            這段程序的意義是,如果返回的指針為空,表示不能打開C盤根目錄下的hzk16文件,則給出提示信息“error on open c:\ hzk16 file!”,下一行g(shù)etch()的功能是從鍵盤輸入一個(gè)字符,但不在屏幕上顯示。在這里,該行的作用是等待,只有當(dāng)用戶從鍵盤敲任一鍵時(shí),程序才繼續(xù)執(zhí)行,因此用戶可利用這個(gè)等待時(shí)間閱讀出錯(cuò)提示。敲鍵后執(zhí)行exit(1)退出程序。

            7) 把一個(gè)文本文件讀入內(nèi)存時(shí),要將ASCII碼轉(zhuǎn)換成二進(jìn)制碼,而把文件以文本方式寫入磁盤時(shí),也要把二進(jìn)制碼轉(zhuǎn)換成ASCII碼,因此文本文件的讀寫要花費(fèi)較多的轉(zhuǎn)換時(shí)間。對(duì)二進(jìn)制文件的讀寫不存在這種轉(zhuǎn)換。

            8) 標(biāo)準(zhǔn)輸入文件(鍵盤),標(biāo)準(zhǔn)輸出文件(顯示器),標(biāo)準(zhǔn)出錯(cuò)輸出(出錯(cuò)信息)是由系統(tǒng)打開的,可直接使用。

            posted @ 2009-03-13 13:08 wrh 閱讀(9365) | 評(píng)論 (0)編輯 收藏
            隊(duì)列消息和非隊(duì)列消息
               
            從消息的發(fā)送途徑來看,消息可以分成2種:隊(duì)列消息和非隊(duì)列消息。消息隊(duì)列由可以分成系統(tǒng)消息隊(duì)列和線程消息隊(duì)列。系統(tǒng)消息隊(duì)列由Windows維護(hù),線程消息隊(duì)列則由每個(gè)GUI線程自己進(jìn)行維護(hù),為避免給non-GUI現(xiàn)成創(chuàng)建消息隊(duì)列,所有線程產(chǎn)生時(shí)并沒有消息隊(duì)列,僅當(dāng)線程第一次調(diào)用GDI函數(shù)數(shù)系統(tǒng)給線程創(chuàng)建一個(gè)消息隊(duì)列。隊(duì)列消息送到系統(tǒng)消息隊(duì)列,然后到線程消息隊(duì)列;非隊(duì)列消息直接送給目的窗口過程。
                 對(duì)于隊(duì)列消息,最常見的是鼠標(biāo)和鍵盤觸發(fā)的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,還有一些其它的消息,例如:WM_PAINT、WM_TIMER和WM_QUIT。當(dāng)鼠標(biāo)、鍵盤事件被觸發(fā)后,相應(yīng)的鼠標(biāo)或鍵盤驅(qū)動(dòng)程序就會(huì)把這些事件轉(zhuǎn)換成相應(yīng)的消息,然后輸送到系統(tǒng)消息隊(duì)列,由Windows系統(tǒng)去進(jìn)行處理。Windows系統(tǒng)則在適當(dāng)?shù)臅r(shí)機(jī),從系統(tǒng)消息隊(duì)列中取出一個(gè)消息,根據(jù)前面我們所說的MSG消息結(jié)構(gòu)確定消息是要被送往那個(gè)窗口,然后把取出的消息送往創(chuàng)建窗口的線程的相應(yīng)隊(duì)列,下面的事情就該由線程消息隊(duì)列操心了,Windows開始忙自己的事情去了。線程看到自己的消息隊(duì)列中有消息,就從隊(duì)列中取出來,通過操作系統(tǒng)發(fā)送到合適的窗口過程去處理。
                 一般來講,系統(tǒng)總是將消息Post在消息隊(duì)列的末尾。這樣保證窗口以先進(jìn)先出的順序接受消息。然而,WM_PAINT是一個(gè)例外,同一個(gè)窗口的多個(gè) WM_PAINT被合并成一個(gè) WM_PAINT 消息, 合并所有的無效區(qū)域到一個(gè)無效區(qū)域。合并WM_PAIN的目的是為了減少刷新窗口的次數(shù)。
                非隊(duì)列消息將會(huì)繞過系統(tǒng)隊(duì)列和消息隊(duì)列,直接將消息發(fā)送到窗口過程,。系統(tǒng)發(fā)送非隊(duì)列消息通知窗口,系統(tǒng)發(fā)送消息通知窗口。 例如,當(dāng)用戶激活一個(gè)窗口系統(tǒng)發(fā)送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。這些消息通知窗口它被激活了。非隊(duì)列消息也可以由當(dāng)應(yīng)用程序調(diào)用系統(tǒng)函數(shù)產(chǎn)生。例如,當(dāng)程序調(diào)用SetWindowPos系統(tǒng)發(fā)送WM_WINDOWPOSCHANGED消息。一些函數(shù)也發(fā)送非隊(duì)列消息,例如下面我們要談到的函數(shù)。
                
            消息的發(fā)送
                 了解了上面的這些基礎(chǔ)理論之后,我們就可以進(jìn)行一下簡(jiǎn)單的消息發(fā)送與接收。
                 把一個(gè)消息發(fā)送到窗口有3種方式:發(fā)送、寄送和廣播。
                 發(fā)送消息的函數(shù)有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送消息的函數(shù)主要有PostMessage、PostThreadMessage、PostQuitMessage;廣播消息的函數(shù)我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。
                 SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),這個(gè)函數(shù)主要是向一個(gè)或多個(gè)窗口發(fā)送一條消息,一直等到消息被處理之后才會(huì)返回。不過需要注意的是,如果接收消息的窗口是同一個(gè)應(yīng)用程序的一部分,那么這個(gè)窗口的窗口函數(shù)就被作為一個(gè)子程序馬上被調(diào)用;如果接收消息的窗口是被另外的線程所創(chuàng)建的,那么窗口系統(tǒng)就切換到相應(yīng)的線程并且調(diào)用相應(yīng)的窗口函數(shù),這條消息不會(huì)被放進(jìn)目標(biāo)應(yīng)用程序隊(duì)列中。函數(shù)的返回值是由接收消息的窗口的窗口函數(shù)返回,返回的值取決于被發(fā)送的消息。
                 PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),該函數(shù)把一條消息放置到創(chuàng)建hWnd窗口的線程的消息隊(duì)列中,該函數(shù)不等消息被處理就馬上將控制返回。需要注意的是,如果hWnd參數(shù)為HWND_BROADCAST,那么,消息將被寄送給系統(tǒng)中的所有的重疊窗口和彈出窗口,但是子窗口不會(huì)收到該消息;如果hWnd參數(shù)為NULL,則該函數(shù)類似于將dwThreadID參數(shù)設(shè)置成當(dāng)前線程的標(biāo)志來調(diào)用PostThreadMEssage函數(shù)。
              從上面的這2個(gè)具有代表性的函數(shù),我們可以看出消息的發(fā)送方式和寄送方式的區(qū)別所在:被發(fā)送的消息是否會(huì)被立即處理,函數(shù)是否立即返回。被發(fā)送的消息會(huì)被立即處理,處理完畢后函數(shù)才會(huì)返回;被寄送的消息不會(huì)被立即處理,他被放到一個(gè)先進(jìn)先出的隊(duì)列中,一直等到應(yīng)用程序空線的時(shí)候才會(huì)被處理,不過函數(shù)放置消息后立即返回。
              實(shí)際上,發(fā)送消息到一個(gè)窗口處理過程和直接調(diào)用窗口處理過程之間并沒有太大的區(qū)別,他們直接的唯一區(qū)別就在于你可以要求操作系統(tǒng)截獲所有被發(fā)送的消息,但是不能夠截獲對(duì)窗口處理過程的直接調(diào)用。
              以寄送方式發(fā)送的消息通常是與用戶輸入事件相對(duì)應(yīng)的,因?yàn)檫@些事件不是十分緊迫,可以進(jìn)行緩慢的緩沖處理,例如鼠標(biāo)、鍵盤消息會(huì)被寄送,而按鈕等消息則會(huì)被發(fā)送。
              廣播消息用得比較少,BroadcastSystemMessage函數(shù)原型如下:
                  long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);該函數(shù)可以向指定的接收者發(fā)送一條消息,這些接收者可以是應(yīng)用程序、可安裝的驅(qū)動(dòng)程序、網(wǎng)絡(luò)驅(qū)動(dòng)程序、系統(tǒng)級(jí)別的設(shè)備驅(qū)動(dòng)消息和他們的任意組合。需要注意的是,如果dwFlags參數(shù)是BSF_QUERY并且至少一個(gè)接收者返回了BROADCAST_QUERY_DENY,則返回值為0,如果沒有指定BSF_QUERY,則函數(shù)將消息發(fā)送給所有接收者,并且忽略其返回值。

            消息的接收
             
            消息的接收主要有3個(gè)函數(shù):GetMessage、PeekMessage、WaitMessage。
              GetMessage原型如下:BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax);該函數(shù)用來獲取與hWnd參數(shù)所指定的窗口相關(guān)的且wMsgFilterMin和wMsgFilterMax參數(shù)所給出的消息值范圍內(nèi)的消息。需要注意的是,如果hWnd為NULL,則GetMessage獲取屬于調(diào)用該函數(shù)應(yīng)用程序的任一窗口的消息,如果wMsgFilterMin和wMsgFilterMax都是0,則GetMessage就返回所有可得到的消息。函數(shù)獲取之后將刪除消息隊(duì)列中的除WM_PAINT消息之外的其他消息,至于WM_PAINT則只有在其處理之后才被刪除。
               PeekMessage原型如下:BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg);該函數(shù)用于查看應(yīng)用程序的消息隊(duì)列,如果其中有消息就將其放入lpMsg所指的結(jié)構(gòu)中,不過,與GetMessage不同的是,PeekMessage函數(shù)不會(huì)等到有消息放入隊(duì)列時(shí)才返回。同樣,如果hWnd為NULL,則PeekMessage獲取屬于調(diào)用該函數(shù)應(yīng)用程序的任一窗口的消息,如果hWnd=-1,那么函數(shù)只返回把hWnd參數(shù)為NULL的PostAppMessage函數(shù)送去的消息。如果wMsgFilterMin和wMsgFilterMax都是0,則PeekMessage就返回所有可得到的消息。函數(shù)獲取之后將刪除消息隊(duì)列中的除WM_PAINT消息之外的其他消息,至于WM_PAINT則只有在其處理之后才被刪除。
               WaitMessage原型如下:BOOL VaitMessage();當(dāng)一個(gè)應(yīng)用程序無事可做時(shí),該函數(shù)就將控制權(quán)交給另外的應(yīng)用程序,同時(shí)將該應(yīng)用程序掛起,直到一個(gè)新的消息被放入應(yīng)用程序的隊(duì)列之中才返回。

            消息的處理
              接下來我們談一下消息的處理,首先我們來看一下VC中的消息泵:
            while(GetMessage(&msg, NULL, 0, 0))
            {
                   if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
                  {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                   }
            }

               首先,GetMessage從進(jìn)程的主線程的消息隊(duì)列中獲取一個(gè)消息并將它復(fù)制到MSG結(jié)構(gòu),如果隊(duì)列中沒有消息,則GetMessage函數(shù)將等待一個(gè)消息的到來以后才返回。 如果你將一個(gè)窗口句柄作為第二個(gè)參數(shù)傳入GetMessage,那么只有指定窗口的的消息可以從隊(duì)列中獲得。GetMessage也可以從消息隊(duì)列中過濾消息只接受消息隊(duì)列中落在范圍內(nèi)的消息。這時(shí)候就要利用GetMessage/PeekMessage指定一個(gè)消息過濾器。這個(gè)過濾器是一個(gè)消息標(biāo)識(shí)符的范圍或者是一個(gè)窗體句柄,或者兩者同時(shí)指定。當(dāng)應(yīng)用程序要查找一個(gè)后入消息隊(duì)列的消息是很有用。WM_KEYFIRST 和 WM_KEYLAST 常量用于接受所有的鍵盤消息。 WM_MOUSEFIRST 和 WM_MOUSELAST 常量用于接受所有的鼠標(biāo)消息。
             然后TranslateAccelerator判斷該消息是不是一個(gè)按鍵消息并且是一個(gè)加速鍵消息,如果是,則該函數(shù)將把幾個(gè)按鍵消息轉(zhuǎn)換成一個(gè)加速鍵消息傳遞給窗口的回調(diào)函數(shù)。處理了加速鍵之后,函數(shù)TranslateMessage將把兩個(gè)按鍵消息WM_KEYDOWN和WM_KEYUP轉(zhuǎn)換成一個(gè)WM_CHAR,不過需要注意的是,消息WM_KEYDOWN,WM_KEYUP仍然將傳遞給窗口的回調(diào)函數(shù)。    
             處理完之后,DispatchMessage函數(shù)將把此消息發(fā)送給該消息指定的窗口中已設(shè)定的回調(diào)函數(shù)。如果消息是WM_QUIT,則GetMessage返回0,從而退出循環(huán)體。應(yīng)用程序可以使用PostQuitMessage來結(jié)束自己的消息循環(huán)。通常在主窗口的WM_DESTROY消息中調(diào)用。
             下面我們舉一個(gè)常見的小例子來說明這個(gè)消息泵的運(yùn)用:
            if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,WM_KEYLAST, PM_REMOVE))
            {
                      if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)...
            }
              這里我們接受所有的鍵盤消息,所以就用WM_KEYFIRST 和 WM_KEYLAST作為參數(shù)。最后一個(gè)參數(shù)可以是PM_NOREMOVE 或者 PM_REMOVE,表示消息信息是否應(yīng)該從消息隊(duì)列中刪除。                
               所以這段小代碼就是判斷是否按下了Esc鍵,如果是就進(jìn)行處理。

            窗口過程
             窗口過程是一個(gè)用于處理所有發(fā)送到這個(gè)窗口的消息的函數(shù)。任何一個(gè)窗口類都有一個(gè)窗口過程。同一個(gè)類的窗口使用同樣的窗口過程來響應(yīng)消息。 系統(tǒng)發(fā)送消息給窗口過程將消息數(shù)據(jù)作為參數(shù)傳遞給他,消息到來之后,按照消息類型排序進(jìn)行處理,其中的參數(shù)則用來區(qū)分不同的消息,窗口過程使用參數(shù)產(chǎn)生合適行為。
             一個(gè)窗口過程不經(jīng)常忽略消息,如果他不處理,它會(huì)將消息傳回到執(zhí)行默認(rèn)的處理。窗口過程通過調(diào)用DefWindowProc來做這個(gè)處理。窗口過程必須return一個(gè)值作為它的消息處理結(jié)果。大多數(shù)窗口只處理小部分消息和將其他的通過DefWindowProc傳遞給系統(tǒng)做默認(rèn)的處理。窗口過程被所有屬于同一個(gè)類的窗口共享,能為不同的窗口處理消息。下面我們來看一下具體的實(shí)例:

            LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
             int wmId, wmEvent;
             PAINTSTRUCT ps;
             HDC hdc;
             TCHAR szHello[MAX_LOADSTRING];
             LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

             switch (message)
             {
              case WM_COMMAND:
                     wmId    = LOWORD(wParam);
                     wmEvent = HIWORD(wParam);
                     // Parse the menu selections:
                     switch (wmId)
                     {
                      case IDM_ABOUT:
                         DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                         break;
                      case IDM_EXIT:
                         DestroyWindow(hWnd);
                         break;
                      default:
                         return DefWindowProc(hWnd, message, wParam, lParam);
                     }
               break;

              case WM_PAINT:
                     hdc = BeginPaint(hWnd, &ps);
                     // TODO: Add any drawing code here...
                     RECT rt;
                     GetClientRect(hWnd, &rt);
                     DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
                     EndPaint(hWnd, &ps);
                     break;

              case WM_DESTROY:
                     PostQuitMessage(0);
                     break;
              default:
                     return DefWindowProc(hWnd, message, wParam, lParam);
              }
              return 0;
            }

            消息分流器
              通常的窗口過程是通過一個(gè)switch語句來實(shí)現(xiàn)的,這個(gè)事情很煩,有沒有更簡(jiǎn)便的方法呢?有,那就是消息分流器,利用消息分流器,我們可以把switch語句分成更小的函數(shù),每一個(gè)消息都對(duì)應(yīng)一個(gè)小函數(shù),這樣做的好處就是對(duì)消息更容易管理。
              之所以被稱為消息分流器,就是因?yàn)樗梢詫?duì)任何消息進(jìn)行分流。下面我們做一個(gè)函數(shù)就很清楚了:
            void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)
            {
                  switch(id)
                  {
                 case ID_A:
                              if(codeNotify==EN_CHANGE)...
                              break;
                 case ID_B:
                              if(codeNotify==BN_CLICKED)...
                              break;
                         ....
                   }
            }
            然后我們修改一下窗口過程:
            LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
                   switch(message)
                  {
                         HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
                         HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
                       default:
                                return DefWindowProc(hWnd, message, wParam, lParam);
               }
              return 0;
            }
            在WindowsX.h中定義了如下的HANDLE_MSG宏:
               #define HANDLE_MSG(hwnd,msg,fn) \
                         switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));
            實(shí)際上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);將被轉(zhuǎn)換成如下定義:
               #define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn)\
                         ((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);
            好了,事情到了這一步,應(yīng)該一切都明朗了。
            不過,我們發(fā)現(xiàn)在windowsx.h里面還有一個(gè)宏:FORWARD_WM_XXXX,我們還是那WM_COMMAND為例,進(jìn)行分析:
               #define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
                 (void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))
            所以實(shí)際上,F(xiàn)ORWARD_WM_XXXX將消息參數(shù)進(jìn)行了重新構(gòu)造,生成了wParam && lParam,然后調(diào)用了我們定義的函數(shù)。
            好了,事情到這里也算是也段落了,下次我們?cè)诜治鱿⒃贛FC中的處理。

            posted @ 2009-02-21 08:37 wrh 閱讀(435) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共25頁: First 13 14 15 16 17 18 19 20 21 Last 

            導(dǎo)航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計(jì)

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            国产一区二区久久久| 97久久天天综合色天天综合色hd | 国产精品99久久久精品无码| 欧美日韩精品久久久久| 99久久无色码中文字幕| 久久久久免费视频| AV无码久久久久不卡蜜桃| 久久免费视频一区| 久久国产欧美日韩精品| 香蕉久久永久视频| 国内精品久久久久影院优| 色99久久久久高潮综合影院 | 热re99久久精品国产99热| 久久精品国产男包| 一级做a爰片久久毛片人呢| 久久99精品久久久大学生| 久久99精品国产麻豆不卡| 97久久香蕉国产线看观看| 久久久久久曰本AV免费免费| 久久99精品国产99久久6| 久久久久久久99精品免费观看| 久久精品一区二区三区AV| 久久久久亚洲精品中文字幕| 久久精品国产只有精品2020| 国产69精品久久久久9999APGF| 色综合久久中文字幕综合网| 国产精品狼人久久久久影院| 国产69精品久久久久777| 婷婷五月深深久久精品| 久久精品国产亚洲AV久| 无码人妻久久一区二区三区蜜桃 | 亚洲av成人无码久久精品| 综合久久给合久久狠狠狠97色 | 国产精品免费看久久久香蕉| 国产成人精品久久二区二区| 久久久久久久精品妇女99| 日批日出水久久亚洲精品tv| 欧美性猛交xxxx免费看久久久| 久久精品国产欧美日韩| 久久影院久久香蕉国产线看观看| 欧美精品丝袜久久久中文字幕|