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

             
            函數(shù)名:

             

              SetWindowPos

            頭文件:

              winuser.h

            函數(shù)原型:

              BOOL SetWindowPos
              (
              HWND hWnd, //窗口句柄
              HWND hWndInsertAfter, //排列順序的句柄
              int X, //水平坐標(biāo)
              int Y, //垂直坐標(biāo)
              int cx, //寬
              int cy, //高
              UINT uFlags //窗口定位標(biāo)識
              );

            說明:

              這個函數(shù)能改變窗口的大小、位置和設(shè)置子窗口、彈出窗口或頂層窗口的排列順序。
              返回值:

              BOOL,如果返回值非零表示成功,返回零表示失敗。錯誤信息請參看GetLastError函數(shù)。

            參數(shù)表:

              參數(shù) 類型及說明
              hwnd HWND,欲定位的窗口句柄
              hWndInsertAfter HWND,置于hwnd前面的窗口句柄。這個參數(shù)必須是窗口的句柄或是下面的值之一:    HWND_BOTTOM 將窗口置于其它所有窗口的底部
              HWND_NOTOPMOST 將窗口置于其它所有窗口的頂部,并位于任何最頂部窗口的后面。如果這個窗口非頂部窗口,這個標(biāo)記對該窗口并不產(chǎn)生影響
              HWND_TOP 將窗口置于它所有窗口的頂部
              HWND_TOPMOST 將窗口置于其它所有窗口的頂部,并位于任何最頂部窗口的前面。即使這個窗口不是活動窗口,也維持最頂部狀態(tài)

            x: 
             
              int,指定窗口新的X坐標(biāo)

            Y:  

              int,指定窗口新的Y坐標(biāo)

            cx:  

              int,指定窗口新的寬度

            cy:  

              int,指定窗口新的高度

            wFlags:

              UINT,指定窗口狀態(tài)和位置的標(biāo)記。這個參數(shù)使用下面值的組合: SWP_DRAWFRAME 圍繞窗口畫一個框
              SWP_FRAMECHANGED 發(fā)送一條WM_NCCALCSIZE消息進(jìn)入窗口,即使窗口的大小沒有發(fā)生改變。如果不指定這個參數(shù),消息WM_NCCALCSIZE只有在窗口大小發(fā)生改變時才發(fā)送
              SWP_HIDEWINDOW 隱藏窗口
              SWP_NOACTIVATE 不激活窗口
              SWP_NOCOPYBITS 屏蔽客戶區(qū)域
              SWP_NOMOVE 保持當(dāng)前位置(X和Y參數(shù)將被忽略)
              SWP_NOOWNERZORDER 不改變所有窗口的位置和排列順序
              SWP_NOREDRAW 窗口不自動重畫
              SWP_NOREPOSITION 與SWP_NOOWNERZORDER標(biāo)記相同
              SWP_NOSENDCHANGING 防止這個窗口接受WM_WINDOWPOSCHANGING消息
              SWP_NOSIZE 保持當(dāng)前大小(cx和cy會被忽略)
              SWP_NOZORDER 保持窗口在列表的當(dāng)前位置(hWndInsertAfter將被忽略)
              SWP_SHOWWINDOW 顯示窗口


            備注:

              如果設(shè)置了SWP_SHOWWINDOW或SWP_HIDEWINDOW標(biāo)記,這個窗口不發(fā)生移動或改變大小。窗口成為最頂級窗口后,它的所有子窗口也會進(jìn)入最頂級。一旦將其設(shè)為非最頂級,則它的所有子窗口也會轉(zhuǎn)為非最頂級。

            相關(guān)函數(shù):

              MoveWindow,SetActiveWindow,SetForegroundWindow

            例子:

              //設(shè)置頂層窗口
              SetWindowPos( Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);

              //取消頂層窗口
              SetWindowPos( Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);

            函數(shù)功能:該函數(shù)改變一個子窗口,彈出式窗口式頂層窗口的尺寸,位置和Z序。子窗口,彈出式窗口,及頂層窗口根據(jù)它們在屏幕上出現(xiàn)的順序排序、頂層窗口設(shè)置的級別最高,并且被設(shè)置為Z序的第一個窗口。

                 函數(shù)原型:BOOL SetWindowPos(HWN hWnd,HWND hWndlnsertAfter,int X,int Y,int cx,int cy,UNIT.Flags);

                 參數(shù):

                 hWnd:窗口句柄。

                 hWndlnsertAfter:在z序中的位于被置位的窗口前的窗口句柄。該參數(shù)必須為一個窗口句柄,或下列值之一:

                 HWND_BOTTOM:將窗口置于Z序的底部。如果參數(shù)hWnd標(biāo)識了一個頂層窗口,則窗口失去頂級位置,并且被置在其他窗口的底部。

                 HWND_DOTTOPMOST:將窗口置于所有非頂層窗口之上(即在所有頂層窗口之后)。如果窗口已經(jīng)是非頂層窗口則該標(biāo)志不起作用。

                 HWND_TOP:將窗口置于Z序的頂部。

                 HWND_TOPMOST:將窗口置于所有非頂層窗口之上。即使窗口未被激活窗口也將保持頂級位置。

                 查g看該參數(shù)的使用方法,請看說明部分。

                 x:以客戶坐標(biāo)指定窗口新位置的左邊界。

                 Y:以客戶坐標(biāo)指定窗口新位置的頂邊界。

                 cx:以像素指定窗口的新的寬度。

                 cy:以像素指定窗口的新的高度。

                 uFlags:窗口尺寸和定位的標(biāo)志。該參數(shù)可以是下列值的組合:

                 SWP_ASNCWINDOWPOS:如果調(diào)用進(jìn)程不擁有窗口,系統(tǒng)會向擁有窗口的線程發(fā)出需求。這就防止調(diào)用線程在其他線程處理需求的時候發(fā)生死鎖。

                 SWP_DEFERERASE:防止產(chǎn)生WM_SYNCPAINT消息。

                 SWP_DRAWFRAME:在窗口周圍畫一個邊框(定義在窗口類描述中)。

                 SWP_FRAMECHANGED:給窗口發(fā)送WM_NCCALCSIZE消息,即使窗口尺寸沒有改變也會發(fā)送該消息。如果未指定這個標(biāo)志,只有在改變了窗口尺寸時才發(fā)送WM_NCCALCSIZE。

                 SWP_HIDEWINDOW;隱藏窗口。

                 SWP_NOACTIVATE:不激活窗口。如果未設(shè)置標(biāo)志,則窗口被激活,并被設(shè)置到其他最高級窗口或非最高級組的頂部(根據(jù)參數(shù)hWndlnsertAfter設(shè)置)。

                 SWP_NOCOPYBITS:清除客戶區(qū)的所有內(nèi)容。如果未設(shè)置該標(biāo)志,客戶區(qū)的有效內(nèi)容被保存并且在窗口尺寸更新和重定位后拷貝回客戶區(qū)。

                 SWP_NOMOVE:維持當(dāng)前位置(忽略X和Y參數(shù))。

                 SWP_NOOWNERZORDER:不改變z序中的所有者窗口的位置。

                 SWP_NOREDRAW:不重畫改變的內(nèi)容。如果設(shè)置了這個標(biāo)志,則不發(fā)生任何重畫動作。適用于客戶區(qū)和非客戶區(qū)(包括標(biāo)題欄和滾動條)和任何由于窗回移動而露出的父窗口的所有部分。如果設(shè)置了這個標(biāo)志,應(yīng)用程序必須明確地使窗口無效并區(qū)重畫窗口的任何部分和父窗口需要重畫的部分。

                 SWP_NOREPOSITION;與SWP_NOOWNERZORDER標(biāo)志相同。

                 SWP_NOSENDCHANGING:防止窗口接收WM_WINDOWPOSCHANGING消息。

                 SWP_NOSIZE:維持當(dāng)前尺寸(忽略cx和Cy參數(shù))。

                 SWP_NOZORDER:維持當(dāng)前Z序(忽略hWndlnsertAfter參數(shù))。

                 SWP_SHOWWINDOW:顯示窗口。

                 返回值:如果函數(shù)成功,返回值為非零;如果函數(shù)失敗,返回值為零。若想獲得更多錯誤消息,請調(diào)用GetLastError函數(shù)。

                 備注:如果設(shè)置了SWP_SHOWWINDOW和SWP_HIDEWINDOW標(biāo)志,則窗口不能被移動和改變大小。如果使用SetWindowLoog改變了窗口的某些數(shù)據(jù),則必須調(diào)用函數(shù)SetWindowPos來作真正的改變。使用下列的組合標(biāo)志:SWP_NOMOVEISWP_NOSIZEISWP_FRAMECHANGED。

                 有兩種方法將窗口設(shè)為最頂層窗口:一種是將參數(shù)hWndlnsertAfter設(shè)置為HWND_TOPMOST并確保沒有設(shè)置SWP_NOZORDER標(biāo)志;另一種是設(shè)置窗口在Z序中的位置以使其在其他存在的窗口之上。當(dāng)一個窗口被置為最頂層窗口時,屬于它的所有窗口均為最頂層窗口,而它的所有者的z序并不改變。

                 如果HWND_TOPMOST和HWND_NOTOPMOST標(biāo)志均未指定,即應(yīng)用程序要求窗口在激活的同時改變其在Z序中的位置時,在參數(shù)hWndinsertAfter中指定的值只有在下列條件中才使用:

                 在hWndlnsertAfter參數(shù)中沒有設(shè)定HWND_NOTOPMOST和HWND_TOPMOST標(biāo)志。

                 由hWnd參數(shù)標(biāo)識的窗口不是激活窗口。

                 如果未將一個非激活窗口設(shè)定到z序的頂端,應(yīng)用程序不能激活該窗口。應(yīng)用程序可以無任何限制地改變被激活窗口在Z序中的位置,或激活一個窗口并將其移到最高級窗口的頂部或非最高級窗口的頂部。

                 如果一個頂層窗口被重定位到z序的底部(HWND_BOTTOM)或在任何非最高序的窗口之后,該窗口就不再是最頂層窗口。當(dāng)一個最頂層窗口被置為非最頂級,則它的所有者窗口和所屬者窗口均為非最頂層窗口。

                 一個非最頂端窗口可以擁有一個最頂端窗口,但反之則不可以。任何屬于頂層窗口的窗口(例如一個對話框)本身就被置為頂層窗口,以確保所有被屬窗口都在它們的所有者之上。

                 如果應(yīng)用程序不在前臺,但應(yīng)該位于前臺,就應(yīng)調(diào)用SetForegroundWindow函數(shù)來設(shè)置。

                 Windows CE:如果這是一個可見的頂層窗口,并且未指定SWP_NOACTIVATE標(biāo)志,則這個函數(shù)將激活窗口、如果這是當(dāng)前的激活窗口,并且指定了SWP_NOACTIVATE或SWP_HIDEWINDOW標(biāo)志,則激活另外一個可見的頂層窗口。

                 當(dāng)在這個函數(shù)中的nFlags參數(shù)里指定了SWP_FRAMECHANGED標(biāo)志時,WindowsCE重畫窗口的整個非客戶區(qū),這可能會改變客戶區(qū)的大小。這也是重新計算客戶區(qū)的唯一途徑,也是通過調(diào)用SetwindowLong函數(shù)改變窗口風(fēng)格后通常使用的方法。

                 SetWindowPos將使WM_WINDOWPOSCHANGED消息向窗口發(fā)送,在這個消息中傳遞的標(biāo)志與傳遞給函數(shù)的相同。這個函數(shù)不傳遞其他消息。

                 Windows CE 1.0不支持在hWndlnsertAber參數(shù)中的HWND_TOPMOST和HWND_NOTOPMOST常量。

            posted @ 2009-06-06 18:49 wrh 閱讀(7176) | 評論 (0)編輯 收藏

            目 錄

            一. 視頻捕獲快速入門

            二.基本的捕獲設(shè)置

                      1.設(shè)置捕獲速度:

                      2.設(shè)置終止捕獲

                      3.捕獲的時間限制

            三.關(guān)于捕獲窗口

                      1.創(chuàng)建一個AVICAP捕獲窗口

                      2.將一個捕獲窗口連接至捕獲設(shè)備

                      3. 父窗口與子窗口的交互

                      4.捕獲窗口的狀態(tài)

            四.視頻捕獲驅(qū)動和音頻驅(qū)動

                      1.視頻捕獲驅(qū)動的性能:

                      2.視頻對話框:

                      3.PREVIEW 和 OVERLAY模式:

                      4.視頻格式

                      5.視頻捕獲設(shè)置

                      6.聲頻格式

            五.使用視頻捕獲

                    1.創(chuàng)建捕獲窗口(CREATING A CAPTURE WINDOW)

                    2.連接到捕獲驅(qū)動(CONNECTING TO A CAPTURE DRIVER)

                    3.列舉所有已安裝的捕獲驅(qū)動(ENUMERATING INSTALLED CAPTURE DRIVERS)

                    4.得到捕獲驅(qū)動的性能(OBTAINING THE CAPABILITIES OF A CAPTURE DRIVER)

                    5.得到捕獲窗口的狀態(tài)(OBTAINING THE STATUS OF A CAPTURE WINDOW)

                    6.顯示對話框設(shè)置視頻特征(DISPLAYING DIALOG BOXES TO SET VIDEO CHARACTERISTICS)

                    7.得到和設(shè)置視頻格式(OBTAINING AND SETTING THE VIDEO FORMAT)

                    8. 預(yù)覽視頻(PREVIEWING VIDEO)

                    9.將視頻設(shè)置為OVERLAY模式(ENABLING VIDEO OVERLAY)

                    10.命名捕獲文件(NAMING THE CAPTURE FILE)

                    11.格式化聲頻捕獲(FORMATTING AUDIO CAPTURE)

                    12.改變視頻捕獲設(shè)置(CHANGING A VIDEO CAPTURE SETTING)

                    13.捕獲數(shù)據(jù)(CAPTURING DATA)

                    14.增加一個信息塊(ADDING AN INFORMATION CHUNK)

                    15.在程序中加入一個回調(diào)函數(shù)(ADDING CALLBACK FUNCTIONS TO AN APPLICATION)

                    16.創(chuàng)建一個狀態(tài)回調(diào)函數(shù)(CREATING A STATUS CALLBACK FUNCTION)

                    17.創(chuàng)建一個錯誤回調(diào)函數(shù)( CREATING AN ERROR CALLBACK FUNCTION)

                    18.創(chuàng)建一個框架回調(diào)函數(shù)(CREATING A FRAME CALLBACK FUNCTION)

            六.將四個標(biāo)準(zhǔn)對話框改成函數(shù)調(diào)用形式

                     AUDIOFORMAT對話框

                     VIDEOFORMAT對話框

                     VIDEOSOURCE對話框

                     VIDEO COMPRESSION對話框  

            前 言

                     視頻捕獲是指由專用的視頻采集卡捕獲聲頻和視頻信息,然后將其進(jìn)行數(shù)據(jù)化處理,再經(jīng)過軟件的壓縮進(jìn)行處理,這時就可對這些數(shù)據(jù)進(jìn)行保存、回放、傳輸?shù)雀鞣N操作。

                     Windows專門提供了Video for Windows來對視頻處理進(jìn)行支持,提供的接口可以被大多數(shù)的視頻采集卡支持,并有多種視頻壓縮驅(qū)動供選擇(當(dāng)然視頻壓縮可以自己開發(fā)),采集卡支持?jǐn)z像頭,TV等多種輸入。


            一. 視頻捕獲快速入門

                      視頻捕捉將一個視頻流和音頻流數(shù)字化, 然后存儲在硬盤或其他存儲介質(zhì)上.

                      一個AVICap視窗口句柄描述了聲頻與視頻流的細(xì)節(jié), 這樣就使你的應(yīng)用程序從AVI文件格式, 聲頻視頻緩沖管理, 低層聲頻視頻驅(qū)動訪問等等解脫出來, AVICap為應(yīng)用程序提供了一個靈活的介面, 你可以僅僅使用如下幾行代碼就可以將視頻捕捉加入你的程序:

            hWndC = capCreateCaptureWindow ( "My Own Capture Window",

            WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);

            SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0 /* wIndex */, 0L);

            SendMessage (hWndC, WM_CAP_SEQUENCE, 0, 0L);

                       一個宏其實也是使用SendMessage, 只不過提供給程序一個更易讀的代碼而已, 下面的這些示例就是使用宏的方法將視頻捕捉加入程序:

            hWndC = capCreateCaptureWindow ( "My Own Capture Window",

            WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);

            capDriverConnect (hWndC, 0);

            capCaptureSequence (hWndC);


                      當(dāng)你創(chuàng)建了一個AVICap類的捕捉窗口并將它連接到一個視頻驅(qū)動時, 此捕捉窗口即可以開始捕捉數(shù)據(jù), 你的程序可以簡單的發(fā)送WM_CAP_SEQUENCE消息(或者使用capCaptureSequence宏)來開始捕捉.

                      如果是缺省的設(shè)置, WM_CAP_SEQUENCE會開始捕捉視頻音頻流到CAPTURE.AVI文件中, 直到下面的某一事件發(fā)生為止:

            用戶按下了ESC鍵或者一個鼠標(biāo)鍵

            你的應(yīng)用程序終止或異常中斷捕捉操作

            磁盤已滿


                          在一個應(yīng)用程序里, 你可以發(fā)送WM_CAP_STOP消息來終止捕捉數(shù)據(jù)(或者使用capCaptureStop宏), 你也可以發(fā)送WM_CAP_ABORT消息(或者使用capCaptureAbort宏)來終止.


            二.基本的捕獲設(shè)置

                      基本的捕獲設(shè)置包括:設(shè)置捕獲速度(每秒捕獲多少幀),是否同時捕獲聲頻,捕獲緩沖,允許最大丟失多少幀,是否使用DOS內(nèi)存,以及用鍵盤的哪個鍵或鼠標(biāo)的哪個鍵來終止捕獲等等。這些基本的設(shè)置都可以使用CAPTUREPARAMS結(jié)構(gòu)來描述,你可以使用capCaptureGetSetup宏來得到當(dāng)前的設(shè)置,然后改變此結(jié)構(gòu)的成員變量,再使用capCaptureSetSetup宏設(shè)置新的設(shè)置。

            例如:

            1.設(shè)置捕獲速度:

                       捕捉速度是指捕捉任務(wù)每秒鐘捕獲的幀數(shù), 你可以發(fā)送WM_CAP_GET_SEQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)來得到當(dāng)前的捕捉速度, 當(dāng)前的捕捉速度保存在CAPTUREPARAMS結(jié)構(gòu)的dwRequestMicroSecPerFrame成員變量中, 你可以通過設(shè)置此變量來改變當(dāng)前設(shè)置, 單位是每毫秒連續(xù)的幀數(shù), 你可以發(fā)送WM_CAP_SET_SEQUENCE_SETUP消息(或者使用capCaptureSetSetup宏), dwRequestMicroSecPerFrame的值是66667, 相當(dāng)于每秒15幀.


            2.設(shè)置終止捕獲

                       你可以允許用戶按下某鍵或某組合鍵或者鼠標(biāo)的左右鍵來終止一個捕獲任務(wù), 如果是實時的捕獲, 則捕獲的文件將會被丟棄; 如果是單步捕獲, 在終止之前所捕獲的內(nèi)容將會被保存.

                      你可以通過發(fā)送WM_CAP_GETQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)來得到當(dāng)前的設(shè)置, 當(dāng)前的按鍵設(shè)置保存在CAPTUREPARAMS的vKeyAbort成員中, 當(dāng)前的鼠標(biāo)設(shè)置保存在fAbortLeftMouse和fAbortRightMouse成員中. 你可以設(shè)置新的按鍵或按鍵組合, 或者鼠標(biāo)左右鍵, 當(dāng)你修改的CAPTUREPARAMS后,應(yīng)該發(fā)送WM_CAP_SET_SEQUENCE_SETUP消息來進(jìn)行更新(或者使用capCaptureSetSetup宏). 缺省的按鍵是VK_ESCAPE. 你必須在指定按鍵之前使用RegisterHotKey函數(shù), 鼠標(biāo)缺省的值是fAbortLeftMouse和fAbortRightMouse都為TRUE.


            3.捕獲的時間限制

                       CAPTUREPARAMS結(jié)構(gòu)中的fLimitEnabled指示是否有時間限度, wTimeLimit指示最大的持續(xù)時間, 單位為秒.

                      得到fLimitEnabled和wTimeLimit的值可以發(fā)送WM_CAP_GET_SEQUENCE_SETUP消息(或使用capCatureGetSetup宏), 當(dāng)設(shè)置了這些成員變量后, 應(yīng)該發(fā)送消息WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)來更新CAPTUREPARAMS結(jié)構(gòu).


            三.關(guān)于捕獲窗口

                    在捕獲之前必須創(chuàng)建一個捕獲窗口(capture window),在發(fā)送消息或使用宏的過程中都需要使用此窗口。

            1.創(chuàng)建一個AVICap捕獲窗口

                    你可以使用capCreateCaptureWindow函數(shù)來創(chuàng)建一個AVICap捕獲窗口, 此函數(shù)將會返回一個句柄, 此句柄以后在發(fā)送消息時要用.

                    你可以在一個程序里創(chuàng)建一個或多個捕獲窗口, 然后給每一個窗口連接不同的捕獲設(shè)置.


            2.將一個捕獲窗口連接至捕獲設(shè)備

                       你可以動態(tài)的在一個捕獲窗口與一個捕獲設(shè)備之前連接或斷接, 你可以發(fā)送WM_CAP_DRIVER_CONNECT消息來使一個捕獲窗口與一個捕獲設(shè)備連接或關(guān)聯(lián). 當(dāng)連接上以后, 你就可以通過捕獲窗口向捕獲設(shè)備發(fā)送各種消息.

                    如果你的系統(tǒng)里裝有多個捕獲設(shè)備, 你可以在發(fā)送WM_CAP_DRIVER_CONNECT消息時用wParam參數(shù)指定使用哪一個, 此參數(shù)是登記在SYSTEM.INI文件的[drivers]一節(jié)里的列表中的某一項, 0為第一個.

                      你可以使用capGetDriverDescription函數(shù)來得到已安裝的捕獲設(shè)備的名稱及版本, 這樣你的程序就可以列舉所有已安裝的捕獲設(shè)備和驅(qū)動, 這樣用戶就可以選擇其中的一個來與你的捕獲窗口連接.

                     你可以發(fā)送WM_CAP_DRIVER_GET_NAME消息(或capDriverGetName宏)來得到連接到捕獲窗口的捕獲設(shè)備的名稱, 得到版本發(fā)送WM_CAP_DRIVER_GET_VERSION消息(或capDriverGetVersion宏)

                     你可以發(fā)送WM_CAP_DRIVER_DISCONNECT消息(或capDriverDisconnect宏)來斷接.


            3. 父窗口與子窗口的交互

                       一些象WM_PALETTECHANGED和WM_QUERYNEWPALETTE的系統(tǒng)級消息只能發(fā)送到頂級窗口或OVERLAPPED窗口, 如果一個捕獲窗口是子窗口,就必須通過父窗口轉(zhuǎn)送.

                     同樣的, 如果父窗口的尺寸改變了, 它就需要通知捕獲窗口, 相反地, 如果捕獲窗口的尺寸改變了, 捕獲窗口就需要發(fā)送消息給父窗口, 一個簡單的方法就是始終保持捕獲窗口的尺寸與視頻流的尺寸一致, 并隨時將尺寸的改變通知父窗口.


            4.捕獲窗口的狀態(tài)

                      你可以發(fā)送WM_CAP_GET_STATUS消息(或capGetStatus宏)來得到當(dāng)前捕獲窗口的狀態(tài), 得到的是一個CAPSTATUS結(jié)構(gòu)的拷貝, 它包含圖片的尺寸, 卷軸的當(dāng)前位置, overlay和preview是否已設(shè)置.

                    因為CAPSTATUS信息是動態(tài)的, 你的程序應(yīng)該只要捕獲的視頻流的尺寸或格式可能發(fā)生了改變就應(yīng)該進(jìn)行刷新(例如: 顯示了捕獲設(shè)備的視頻格式以后).

                    改變捕獲窗口的尺寸并不影響實際的捕獲的視頻流的尺寸, 視頻捕獲設(shè)備的格式對話框捕獲頻流的尺寸.


            四.視頻捕獲驅(qū)動和音頻驅(qū)動

            1.視頻捕獲驅(qū)動的性能:

                      你可以通過發(fā)送WM_CAP_DRIVER_GET_CAPS消息(或者capDriverGetCaps宏)來得到當(dāng)前連接的視頻驅(qū)動的硬件性能. 得到的信息保存在CAPDRIVERCAPS結(jié)構(gòu)中.


            2.視頻對話框:

                      每一個視頻驅(qū)動能夠提供四個對話框來控制視頻捕獲和數(shù)字化處理, 定義壓縮品質(zhì)等, 這些對話框都定義在視頻捕獲驅(qū)動中.

                      Video Source對話框用于控制選擇視頻來源, 此對話框列舉了此視頻捕獲卡連接的所有視頻源(典型的例如:SVHS和合成輸入), 并提供了改變色調(diào), 對比度, 飽和度. 如果視頻驅(qū)動支持此對話框, 你就可以顯示并更新它, 使用WM_CAP_DLG_VIDEOSOURCE消息(或capDlgVideoSource宏).

                       Video Format對話框定義視頻幀的尺寸以及精度, 視頻捕獲卡的壓縮設(shè)置. 如果卡支持的話, 可以發(fā)送消息WM_CAP_DLG_VIDEOFORMAT消息或(capDlgVideoFormat宏).

                       Video Display對話框控制在視頻捕獲期間在顯示器上的顯示, 此控制不會影響視頻數(shù)字?jǐn)?shù)據(jù), 但是他們可能會影響數(shù)字信號的表現(xiàn)形式, 例如: 如果捕獲設(shè)備支持overlay, 可能允許改變色調(diào)和飽和度, 關(guān)鍵色彩 或者overlay隊列. 如果卡支持, 你可以發(fā)送WM_CAP_DLG_VIDEODISPLAY消息(或者使用capDlgVideoDisplay宏).

                       Video Compression對話框控制壓縮品質(zhì), 如果卡支持, 發(fā)送消息WM_CAP_DLG_VIDEOCOMPRESSION(或capDlgVideoCompression宏).


            3.Preview 和 Overlay模式:

                             一個視頻捕獲驅(qū)動對進(jìn)入的視頻流有兩種工作模式: Preview模式和overlay模式, 如果一個捕獲驅(qū)動能夠執(zhí)行兩種方法, 用戶可以在其中選擇一種.

                           Preview模式把從捕獲硬件傳來的數(shù)據(jù)送入系統(tǒng)內(nèi)存并使用圖形設(shè)備介面(GDI)將數(shù)字化幀顯示在捕獲窗口內(nèi). 應(yīng)用程序可以在父窗口失去焦點(diǎn)時減緩顯示速度, 當(dāng)重新又得到焦點(diǎn)后加快顯示速度, 此種模式要占用大量CPU時間.

            有三種消息控制Preview操作:

            WM_CAP_SET_PREIVEW消息(capPreview宏)允許或禁止preview模式

            WM_CAP_SET_PREVIEWRATE(capPreviewRate宏)當(dāng)幀在preview模式顯示時設(shè)置速度.

            WM_CAP_SET_SCALE(capPreviewScale宏)允許或禁止preview視頻的縮放比例.

                      當(dāng)preview和scaling同時使用, 捕獲的視頻幀將會根據(jù)捕獲窗口的尺寸自動縮放, 允許preview模式會自動關(guān)閉overlay模式.

                                  overlay模式是一個硬件函數(shù)它將數(shù)據(jù)送入捕獲緩沖區(qū)中因而不占用CPU資源. 你可以發(fā)送消息WM_CAP_SET_OVERLAY(或capOverlay宏)給捕獲窗口來啟用或終止overlay模式, 允許overlay模式會自動禁止preview模式.

                           你同時也可以在preview模式或overlay模式里發(fā)送WM_CAP_SET_SCROLL消息(或capSetScrollPos宏)來設(shè)置視頻幀的客戶區(qū)卷軸位置.


            4.視頻格式

                        你可以通過發(fā)送WM_CAP_GET_VIDEOFORMAT消息(或capGetVideoFormat和capGetVideoFormatSize宏)來得到視頻格式的結(jié)構(gòu)或結(jié)構(gòu)的尺寸. 你可以通過發(fā)送CAP_SET_VIDEOFORMAT消息(或capSetVideoFormat宏)來設(shè)置視頻格式.


            5.視頻捕獲設(shè)置

                       CAPTUREPARMS結(jié)構(gòu)包含了對視頻捕獲流的控制參數(shù), 你可以完成以下這些任務(wù):

            指定幀數(shù)

            指定分配多少視頻緩沖

            允許或禁止聲頻捕獲

            指定捕獲的時間間隔

            指定在捕獲的過程中是否使用MCI設(shè)置(VCR或者videodisc)

            指定終止流的鍵盤或鼠標(biāo)

            specify the type of video averaging applied during capture.


            得到:WM_CAP_GET_SEQUENCE_SETUP消息(或capCaptureGetSetup宏)

            設(shè)置:WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)


            6.聲頻格式

                           你可以通過發(fā)送WM_CAP_GET_AUDIOFORMAT消息(或capGetAudioFormat宏和capGetAudioFormatSize宏)來得到當(dāng)前捕獲音頻數(shù)據(jù)的格式或尺寸格式。缺省的聲頻格式是:單聲道、8位、11kHz PCM。 當(dāng)你使用WM_CAP_GET_AUDIOFORMAT時,總是使用WAVEFORMATEX結(jié)構(gòu)。

                         設(shè)置發(fā)送消息WM_CAP_SET_AUDIOFORMAT消息(或capSetAudioFormat宏),可以傳送WAVEFORMAT,WAVEFORMATEX,PCMWAVEFORMAT結(jié)構(gòu)指針。

            五.使用視頻捕獲

            1.創(chuàng)建捕獲窗口(Creating a Capture Window)

            hWndC = capCreateCaptureWindow (

            (LPSTR) "My Capture Window", // window name if pop-up

            WS_CHILD | WS_VISIBLE, // window style

            0, 0, 160, 120, // window position and dimensions

            (HWND) hwndParent,

            (int) nID /* child ID */);


            2.連接到捕獲驅(qū)動(Connecting to a Capture Driver)

                       下面的例子是將MSVIDEO驅(qū)動連接到句柄為hWndC的捕獲窗口, 然后調(diào)用capDriverDisconnect宏來斷接.

            fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L);

            //

            // Or, use the macro to connect to the MSVIDEO driver:

            // fOK = capDriverConnect(hWndC, 0);

            //

            // Place code to set up and capture video here.

            //

            capDriverDisconnect (hWndC);


            3.列舉所有已安裝的捕獲驅(qū)動(Enumerating Installed Capture Drivers)

                       下面的例子使用capGetDriverDescription函數(shù)得到已安裝的捕獲驅(qū)動的名稱及版本:

            char szDeviceName[80];

            char szDeviceVersion[80];


            for (wIndex = 0; wIndex < 10; wIndex++)

            {

            if (capGetDriverDescription (wIndex, szDeviceName,

            sizeof (szDeviceName), szDeviceVersion,

            sizeof (szDeviceVersion))

            {

            // Append name to list of installed capture drivers

            // and then let the user select a driver to use.

            }

            }


            4.得到捕獲驅(qū)動的性能(Obtaining the Capabilities of a Capture Driver)

                          發(fā)送WM_CAP_DRIVER_GET_CAPS消息可以得到捕獲驅(qū)動的性能,并保存入一個CAPDRIVERCAPS結(jié)構(gòu).每當(dāng)程序連接一個新的捕獲驅(qū)動到一個捕獲窗口時, 就應(yīng)該更新CAPDRIVERCAPS結(jié)構(gòu). 下面的程序舉例說明了如何使用capDriverGetCaps宏來得到捕獲驅(qū)動的性能:


            CAPDRIVERCAPS CapDrvCaps;

            SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,

            sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) &CapDrvCaps);

            // Or, use the macro to retrieve the driver capabilities.

            // capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


            5.得到捕獲窗口的狀態(tài)(Obtaining the Status of a Capture Window)

                             下面的例子使用SetWindowPos函數(shù)使捕獲窗口與進(jìn)來的視頻流尺寸保持一致, 視頻流的基本信息是使用capGetStatus宏得到的, 保存在CAPSTATUS結(jié)構(gòu)中.


            CAPSTATUS CapStatus;

            capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

            SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth,

            CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);


            6.顯示對話框設(shè)置視頻特征(Displaying Dialog Boxes to Set Video Characteristics)

                          每個視頻捕獲卡一般能提供三個不同的對話框用于控制視頻捕獲及數(shù)字化處理. 下面的例子說明如何顯示這些對話框, 在顯示這些對話框之前,使用了capDriverGetCaps宏來檢查CAPDRIVERCAPS結(jié)構(gòu), 以檢測該卡是否有顯示這些對話框:


            CAPDRIVERCAPS CapDrvCaps;

            capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


            // Video source dialog box.

            if (CapDriverCaps.fHasDlgVideoSource)

            capDlgVideoSource(hWndC);


            // Video format dialog box.

            if (CapDriverCaps.fHasDlgVideoFormat)

            {

            capDlgVideoFormat(hWndC);

            // Are there new image dimensions?

            capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

            // If so, notify the parent of a size change.

            }


            // Video display dialog box.

            if (CapDriverCaps.fHasDlgVideoDisplay)

            capDlgVideoDisplay(hWndC);


            7.得到和設(shè)置視頻格式(Obtaining and Setting the Video Format)

                               BITMAPINFO結(jié)構(gòu)的長度既適應(yīng)于標(biāo)準(zhǔn)的也適應(yīng)于壓縮的數(shù)據(jù)格式, 所有程序必須總是詢問此結(jié)構(gòu)的尺寸以便在得到當(dāng)前的視頻格式之前分配內(nèi)存. 下面的例子就是使用capGetVideoFormatSize宏來得到緩沖區(qū)尺寸并調(diào)用capGetVideoFormat宏來得到當(dāng)前的視頻格式.


            LPBITMAPINFO lpbi;

            DWORD dwSize;

            dwSize = capGetVideoFormatSize(hWndC);

            lpbi = GlobalAllocPtr (GHND, dwSize);

            capGetVideoFormat(hWndC, lpbi, dwSize);


            // Access the video format and then free the allocated memory.


                          程序可以使用capSetVideoFormat宏(或WM_CAP_SET_VIDEOFORMAT消息)發(fā)送一個BITMAPINFO頭結(jié)構(gòu)給捕獲窗口, 因為視頻格式是設(shè)備細(xì)節(jié), 你的程序應(yīng)該檢查返回值以便確定此格式是否已被接受.


            8. 預(yù)覽視頻(Previewing Video)

                         下面的例子使用capPreviewRate宏來設(shè)置每66毫秒顯示一幀, 并使用capPreview宏將它放置在捕獲窗口里.


            capPreviewRate(hWndC, 66); // rate, in milliseconds

            capPreview(hWndC, TRUE); // starts preview

            // Preview

            capPreview(hWnd, FALSE); // disables preview


            9.將視頻設(shè)置為overlay模式(Enabling Video Overlay)

                        下面的例子: capDriverGetCaps宏確定此捕獲卡是否有overlay功能, 如果有就使用宏來設(shè)置它


            CAPDRIVERCAPS CapDrvCaps;

            capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


            if (CapDrvCaps.fHasOverlay)

            capOverlay(hWndC, TRUE);


            10.命名捕獲文件(Naming the Capture File)

                         下面的例子: 使用capFileSetCaptureFile宏來指定預(yù)備文件名為:MYCAP.AVI, capFileAlloc宏預(yù)先指定它的大小為5M.


            char szCaptureFile[] = "MYCAP.AVI";

            capFileSetCaptureFile( hWndC, szCaptureFile);

            capFileAlloc( hWndC, (1024L * 1024L * 5));


            11.格式化聲頻捕獲(Formatting Audio Capture)

                         下面的例子使用capSetAudioFormat來設(shè)置聲頻格式為:11kHz, PCM 8位, 立體聲


            WAVEFORMATEX wfex;

            wfex.wFormatTag = WAVE_FORMAT_PCM;

            wfex.nChannels = 2; // Use stereo

            wfex.nSamplesPerSec = 11025;

            wfex.nAvgBytesPerSec = 22050;

            wfex.nBlockAlign = 2;

            wfex.wBitsPerSample = 8;

            wfex.cbSize = 0;


            capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));


            12.改變視頻捕獲設(shè)置(Changing a Video Capture Setting)

                           下面的例子使用capCaptureGetSetup和capCaptureSetSetup宏得將捕獲幀數(shù)從缺省的15幀改成每秒10幀.


            CAPTUREPARMS CaptureParms;

            float FramesPerSec = 10.0;


            capCaptureGetSetup(hWndC, &CaptureParms, sizeof(CAPTUREPARMS));


            CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /FramesPerSec);

            capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));


            13.捕獲數(shù)據(jù)(Capturing Data)

                            下面的例子使用capCaptureSequence宏來開始捕獲視頻并使用capFileSaveAs宏來將捕獲的數(shù)據(jù)拷貝至NEWFILE.AVI文件中.


            char szNewName[] = "NEWFILE.AVI";

            // Set up the capture operation.

            capCaptureSequence(hWndC);

            // Capture.

            capFileSaveAs(hWndC, szNewName);


            14.增加一個信息塊(Adding an Information Chunk)

                           如果你需要在你的程序捕獲的聲頻和視頻數(shù)據(jù)中加入你的其他信息, 你可以創(chuàng)建一個信息塊并將它們插入捕獲文件中, 信息塊可以包含一些典型的信息, 例如:版權(quán)信息,視頻來源, 外部定位信息等. 下面的例子使用capFileSetInfoChunk宏來插入一個信息塊, 里面包含了一個SMPTE的時間代碼.


            // This example assumes the application controls

            // the video source for preroll and postroll.

            CAPINFOCHUNK cic;

            // .

            // .

            // .

            cic.fccInfoID = infotypeSMPTE_TIME;

            cic.lpData = "00:20:30:12";

            cic.cbData = strlen (cic.lpData) + 1;

            capFileSetInfoChunk (hwndC, &cic);


            15.在程序中加入一個回調(diào)函數(shù)(Adding Callback Functions to an Application)

                           一個程序可以為捕獲窗口登記一個回調(diào)函數(shù)以便在以下的這些情況下通知程序.


            狀態(tài)改變

            錯誤發(fā)生

            視頻框架和聲頻緩沖區(qū)變得可用

            程序應(yīng)用在捕獲視頻流的過程中接收


                       下面的例子創(chuàng)建一個捕獲窗口并登記狀態(tài),錯誤,視頻流和框架回調(diào)函數(shù)在消息處理對列中, 也包括了一個終止回調(diào)函數(shù)的說明.


            case WM_CREATE:

            {

            char achDeviceName[80]

            char achDeviceVersion[100]

            char achBuffer[100]

            WORD wDriverCount = 0

            WORD wIndex

            WORD wError

            HMENU hMenu


            // Create a capture window using the capCreateCaptureWindow macro.

            ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",

            WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);


            // Register the error callback function using the

            // capSetCallbackOnError macro.

            capSetCallbackOnError(ghWndCap, fpErrorCallback);


            // Register the status callback function using the

            // capSetCallbackOnStatus macro.

            capSetCallbackOnStatus(ghWndCap, fpStatusCallback);


            // Register the video-stream callback function using the

            // capSetCallbackOnVideoStream macro.

            capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);


            // Register the frame callback function using the

            // capSetCallbackOnFrame macro.

            capSetCallbackOnFrame(ghWndCap, fpFrameCallback);


            // Connect to a capture driver


            break;

            }

            case WM_CLOSE:

            {

            // Use the capSetCallbackOnFrame macro to

            // disable the frame callback. Similar calls exist for the other

            // callback functions.


            capSetCallbackOnFrame(hWndC, NULL);


            break;

            }


            16.創(chuàng)建一個狀態(tài)回調(diào)函數(shù)(Creating a Status Callback Function)

                        下面的例子是創(chuàng)建一個簡單的狀態(tài)回調(diào)函數(shù),登記此回調(diào)函數(shù)使用capSetCallbackOnStatus宏.


            // StatusCallbackProc: status callback function

            // hWnd: capture window handle

            // nID: status code for the current status

            // lpStatusText: status text string for the current status

            //

            LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID,

            LPSTR lpStatusText)

            {

            if (!ghWndMain)

            return FALSE;


            if (nID == 0) { // Clear old status messages.

            SetWindowText(ghWndMain, (LPSTR) gachAppName);

            return (LRESULT) TRUE;

            }

            // Show the status ID and status text...

            wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);


            SetWindowText(ghWndMain, (LPSTR)gachBuffer);

            return (LRESULT) TRUE;

            }


            17.創(chuàng)建一個錯誤回調(diào)函數(shù)( Creating an Error Callback Function)

                         下面的例子是創(chuàng)建一個簡單的錯誤回調(diào)函數(shù),登記此回調(diào)函數(shù)使用capsetCallbackOnError宏:


            // ErrorCallbackProc: error callback function

            // hWnd: capture window handle

            // nErrID: error code for the encountered error

            // lpErrorText: error text string for the encountered error

            //

            LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,

            LPSTR lpErrorText)

            {

            if (!ghWndMain)

            return FALSE;


            if (nErrID == 0) // Starting a new major function.

            return TRUE; // Clear out old errors.


            // Show the error identifier and text.

            wsprintf(gachBuffer, "Error# %d", nErrID);


            MessageBox(hWnd, lpErrorText, gachBuffer,

            MB_OK | MB_ICONEXCLAMATION);


            return (LRESULT) TRUE;

            }


            18.創(chuàng)建一個框架回調(diào)函數(shù)(Creating a Frame Callback Function)

                          登記此回調(diào)函數(shù)使用capSetCallbackOnFrame宏:


            // FrameCallbackProc: frame callback function

            // hWnd: capture window handle

            // lpVHdr: pointer to struct containing captured

            // frame information

            //

            LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)

            {

            if (!ghWndMain)

            return FALSE;


            wsprintf(gachBuffer, "Preview frame# %ld ", gdwFrameNum++);

            SetWindowText(ghWndMain, (LPSTR)gachBuffer);

            return (LRESULT) TRUE

            }


             

            六.將四個標(biāo)準(zhǔn)對話框改成函數(shù)調(diào)用形式

                          系統(tǒng)提供了四個標(biāo)準(zhǔn)的對話框:AudioFormat, VideoFormat, VideoSource, Video Compression,但有時程序希望通過函數(shù)控制它們,而不是使用系統(tǒng)提供的那個單一的對話框,此時就應(yīng)該使用函數(shù)調(diào)用的方法:


            AudioFormat對話框

                        可以通過使用capSetAudioFormat來實現(xiàn),此時要使用WAVEFORMATEX結(jié)構(gòu)。

            例如:改成PCM格式,立體聲,16聲道,12.05kHz,則:

            WAVEFORMATEX audioFormat;

            // 確定寬度

            acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,&dwSize);

            dwSize = max (dwSize, capGetAudioFormatSize (m_hwCapCapturing));

            // 設(shè)置參數(shù)

            audioFormat.wFormatTag = WAVE_FORMAT_PCM;

            audioFormat.nChannels = 2;

            audioFormat.nSamplesPerSec = 120500;

            audioFormat.wBitsPerSample =16;

            audioFormat.nBlockAlign = nBitsPerSample * nChannels / 8;

            audioFormat.nAvgBytesPerSec =

            audioFormat.nBlockAlign * nSamplesPerSec;

            // 更新

            capSetAudioFormat(ghCapWnd,&audioFormat,dwSize);

            VideoFormat對話框

                              可以通過使用capSetVideoFormat來實現(xiàn),此時要使用BITMAPINFOHEADER結(jié)構(gòu)。

            例如:設(shè)置圖片大小為RGB24位歲,大小為230X160

            BITMAPINFOHEADER bi;

            DWORD dwSize,dw;

            bi.biSize = sizeof(BITMAPINFOHEADER);

            bi.biWidth = 320; // 起作用

            bi.biHeight = 160; // 起作用

            bi.biPlanes = 1;

            bi.biBitCount = 24;

            bi.biCompression = BI_RGB;

            bi.biSizeImage = 0;

            bi.biXPelsPerMeter = 176;

            bi.biYPelsPerMeter = 144;

            bi.biClrUsed = 0;

            bi.biClrImportant = 0;

            dwSize = bi.biSize + ((bi.biBitCount > 8 || bi.biClrUsed) ? (bi.biClrUsed * sizeof(PALETTEENTRY)) : (2 ^ bi.biBitCount * sizeof(PALETTEENTRY)));

            dw = capSetVideoFormat(m_hwCapCapturing, &bi, dwSize);

            VideoSource對話框

                            沒有找到現(xiàn)成的方法,但視頻捕獲卡提供的CD里面有一個動態(tài)鏈接庫可以實現(xiàn)。

            Video Compression對話框

                         可以通過使用ICOpen,ICInfo等函數(shù)聯(lián)合起來,得到當(dāng)前系統(tǒng)里面的視頻壓縮驅(qū)動的列表,并可選擇其一,MSDN里面有一個程序示范了此用戶,程序名叫:ICWalk。

            posted @ 2009-06-06 18:31 wrh 閱讀(3123) | 評論 (0)編輯 收藏

            HWND   VFWAPI   capCreateCaptureWindow(  
                  LPCSTR   lpszWindowName,      
                  DWORD   dwStyle,                      
                  int   x,                                      
                  int   y,                                      
                  int   nWidth,                            
                  int   nHeight,                          
                  HWND   hWnd,                              
                  int   nID                                    
              );  
                  Header:   Declared   in   vfw.h.  
                  Import   Library:   Use   vfw32.lib.  
            //////////////////////////////////////////////////////////////////////////////
            調(diào)用capCreateCaptureWindow創(chuàng)建的窗口如何關(guān)閉釋放掉?
            小弟不懂VC,只是調(diào)的API,用完后但不知道如何關(guān)閉掉這個窗口
            網(wǎng)友回復(fù):HWND hWnd = capCreateCaptureWindow(...);

            // 關(guān)閉該窗口
            ::SendMessage(hWnd, WM_CLOSE, 0, 0);

            posted @ 2009-06-06 18:30 wrh 閱讀(2699) | 評論 (1)編輯 收藏
            譯者:徐景周(原作:Alexander Mikula)

            下載本文示例代碼

            想要通過ODBC直接讀、寫Excel表格文件,首先,應(yīng)確保ODBC中已安裝有Excel表格文件的驅(qū)動"MICROSOFT EXCEL DRIVER (*.XLS)"。然后,可根據(jù)下面步驟進(jìn)行:

            1. 在StdAfx.h文件中加入

            #include <afxdb.h>
            #include <odbcinst.h>
            
            2. 通過ODBC直接創(chuàng)建Excel文件并在表中插入數(shù)據(jù)(暫定文件名:Demo.xls)
            //創(chuàng)建并寫入Excel文件
            void CRWExcel::WriteToExcel()
            {
            CDatabase database;
            CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安裝驅(qū)動
            CString sExcelFile = "c:\\demo.xls";                // 要建立的Excel文件
            CString sSql;
            TRY
            {
            // 創(chuàng)建進(jìn)行存取的字符串
            sSql.Format("DRIVER={%s};DSN='''';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",
            sDriver, sExcelFile, sExcelFile);
            // 創(chuàng)建數(shù)據(jù)庫 (既Excel表格文件)
            if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )
            {
            // 創(chuàng)建表結(jié)構(gòu)(姓名、年齡)
            sSql = "CREATE TABLE demo (Name TEXT,Age NUMBER)";
            database.ExecuteSQL(sSql);
            // 插入數(shù)值
            sSql = "INSERT INTO demo (Name,Age) VALUES (''徐景周'',26)";
            database.ExecuteSQL(sSql);
            sSql = "INSERT INTO demo (Name,Age) VALUES (''徐志慧'',22)";
            database.ExecuteSQL(sSql);
            sSql = "INSERT INTO demo (Name,Age) VALUES (''郭徽'',27)";
            database.ExecuteSQL(sSql);
            }
            // 關(guān)閉數(shù)據(jù)庫
            database.Close();
            }
            CATCH_ALL(e)
            {
            TRACE1("Excel驅(qū)動沒有安裝: %s",sDriver);
            }
            END_CATCH_ALL;
            }
            
            3. 通過ODBC直接讀取Excel文件(暫定文件名:Demo.xls)
            // 讀取Excel文件
            void CRWExcel::ReadFromExcel()
            {
            CDatabase database;
            CString sSql;
            CString sItem1, sItem2;
            CString sDriver;
            CString sDsn;
            CString sFile = "Demo.xls"; 			// 將被讀取的Excel文件名
            // 檢索是否安裝有Excel驅(qū)動 "Microsoft Excel Driver (*.xls)"
            sDriver = GetExcelDriver();
            if (sDriver.IsEmpty())
            {
            // 沒有發(fā)現(xiàn)Excel驅(qū)動
            AfxMessageBox("沒有安裝Excel驅(qū)動!");
            return;
            }
            // 創(chuàng)建進(jìn)行存取的字符串
            sDsn.Format("ODBC;DRIVER={%s};DSN='''';DBQ=%s", sDriver, sFile);
            TRY
            {
            // 打開數(shù)據(jù)庫(既Excel文件)
            database.Open(NULL, false, false, sDsn);
            CRecordset recset(&database);
            // 設(shè)置讀取的查詢語句.
            sSql = "SELECT Name, Age "
            "FROM demo "
            "ORDER BY Name ";
            // 執(zhí)行查詢語句
            recset.Open(CRecordset::forwardOnly, sSql, CRecordset::readOnly);
            // 獲取查詢結(jié)果
            while (!recset.IsEOF())
            {
            //讀取Excel內(nèi)部數(shù)值
            recset.GetFieldValue("Name ", sItem1);
            recset.GetFieldValue("Age", sItem2);
            // 移到下一行
            recset.MoveNext();
            }
            // 關(guān)閉數(shù)據(jù)庫
            database.Close();
            }
            CATCH(CDBException, e)
            {
            // 數(shù)據(jù)庫操作產(chǎn)生異常時...
            AfxMessageBox("數(shù)據(jù)庫錯誤: " + e->m_strError);
            }
            END_CATCH;
            }
            
            4. 獲取ODBC中Excel驅(qū)動的函數(shù)
            CString CRWExcel::GetExcelDriver()
            {
            char szBuf[2001];
            WORD cbBufMax = 2000;
            WORD cbBufOut;
            char *pszBuf = szBuf;
            CString sDriver;
            // 獲取已安裝驅(qū)動的名稱(涵數(shù)在odbcinst.h里)
            if (!SQLGetInstalledDrivers(szBuf, cbBufMax, &cbBufOut))
            return "";
            // 檢索已安裝的驅(qū)動是否有Excel...
            do
            {
            if (strstr(pszBuf, "Excel") != 0)
            {
            //發(fā)現(xiàn) !
            sDriver = CString(pszBuf);
            break;
            }
            pszBuf = strchr(pszBuf, ''\0'') + 1;
            }
            while (pszBuf[1] != ''\0'');
            return sDriver;
            }
            
            作者信息:
            姓名:徐景周(未來工作室 Future Studio)
            EMAIL:jingzhou_xu@163.net

            posted @ 2009-05-22 09:22 wrh 閱讀(1257) | 評論 (0)編輯 收藏

            1.CString::IsEmpty

            BOOL IsEmpty( ) const;

            返回值:如果CString 對象的長度為0,則返回非零值;否則返回0。

            說明:此成員函數(shù)用來測試一個CString 對象是否是空的。

            示例:

            下面的例子說明了如何使用CString::IsEmpty。

            // CString::IsEmpty 示例

            CString s;

            ASSERT( s.IsEmpty() );

            請參閱 CString::GetLength

             

            2.CString::Left

            CString Left( int nCount ) const; 

            throw( CMemoryException );

            返回值:返回的字符串是前nCount個字符。

            示例:

            CString s( _T("abcdef") );

            ASSERT( s.Left(2) == _T("ab") );

             

            3.CString::LoadString

            BOOL LoadString( UINT nID );

            throw( CMemoryException );

            返回值:如果加載資源成功則返回非零值;否則返回0。

            nID  一個Windows 字符串資源ID。

            說明: 此成員函數(shù)用來讀取一個由nID 標(biāo)識的Windows 字符串資源,并放入一個已有CString 對象中。

            示例:

            下面的例子說明了如何使用CString::LoadString。

            // CString::LoadString 示例

            #define IDS_FILENOTFOUND 1

            CString s;

            if (! s.LoadString( IDS_FILENOTFOUND ))

             

            4.CString::MakeLower

            void MakeLower( );  //改變字符的小寫

             

            5.CString::MakeReverse

            void MakeReverse( );  //字符倒置

             

            6.CString::MakeUpper

            void MakeUpper( );  //改變字符的大寫

             

            7.CString::Mid CString Mid( int nFirst ) const; CString Mid( int nFirst, int nCount ) const; nCount代表要提取的字符數(shù), nFirst代表要提取的開始索引位置

            示例: CString s( _T("abcdef") ); ASSERT( s.Mid( 2, 3 ) == _T("cde") );

             

            8.CString::ReleaseBuffer

            void ReleaseBuffer( int nNewLength = -1 );

            參數(shù):nNewLength

            此字符串的以字符數(shù)表示的新長度,不計算結(jié)尾的空字符。如果這個字

            符串是以空字符結(jié)尾的,則參數(shù)的缺省值-1 將把CString 的大小設(shè)置為

            字符串的當(dāng)前長度。

            說明:

            使用ReleaseBuffer 來結(jié)束對由GetBuffer 分配的緩沖區(qū)的使用。如果你知道緩

            沖區(qū)中的字符串是以空字符結(jié)尾的,則可以省略nNewLength 參數(shù)。如果字符

            串不是以空字符結(jié)尾的,則可以使用nNewLength 指定字符串的長度。在調(diào)用

            ReleaseBuffer 或其它CString 操作之后,由GetBuffer 返回的地址是無效的。

            示例:

            下面的例子說明了如何使用CString::ReleaseBuffer。

            // CString::ReleaseBuffer 示例

            CString s;

            s = "abc";

            LPTSTR p = s.GetBuffer( 1024 );

            strcpy(p, "abc"); // 直接使用該緩沖區(qū)

            ASSERT( s.GetLength() == 3 ); // 字符串長度 = 3

            s.ReleaseBuffer(); // 釋放多余的內(nèi)存,現(xiàn)在p 無效。

            ASSERT( s.GetLength() == 3 ); // 長度仍然是3

             

            9.CString::Remove

            int CString::Remove ( TCHAR ch );

            返回值:返回從字符串中移走的字符數(shù)。如果字符串沒有改變則返回零。

            參數(shù):ch  要從一個字符串中移走的字符。

            說明:此成員函數(shù)用來將ch 實例從字符串中移走。與這個字符的比較是區(qū)分大小寫

            的。

            示例:

            // 從一個句子中移走小寫字母'c':

            CString str (“This is a test.”);

            int n = str.Remove( 't' );

            ASSERT( n == 2 );

            ASSERT( str ==“This is a es. ” );

             10.CString::Replace

            int Replace( TCHAR chOld, TCHAR chNew );

            int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew );

            返回值:返回被替換的字符數(shù)。如果這個字符串沒有改變則返回零。

            參數(shù):chOld     要被chNew 替換的字符。

            chNew    要用來替換chOld 的字符。

            lpszOld   一個指向字符串的指針,該字符串包含了要被lpszNew 替換的字符。

            LpszNew  一個指向字符串的指針,該字符串包含了要用來替換lpszOld 的字符。

            說明:此成員函數(shù)用一個字符替換另一個字符。函數(shù)的第一個原形在字符串中用chNew

            現(xiàn)場替換chOld。函數(shù)的第二個原形用lpszNew 指定的字符串替換lpszOld 指定

            的子串。

            在替換之后,該字符串有可能增長或縮短;那是因為lpszNew 和lpszOld 的長度

            不需要是相等的。兩種版本形式都進(jìn)行區(qū)分大小寫的匹配。

            示例:

            // 第一個例子,old 和new 具有相同的長度。

            CString strZap( “C - -” );

            int n = strZap.Replace('-', '+' );

            ASSERT( n == 2 );

            ASSERT(strZap == “C++” );

            // 第二個例子,old 和new 具有不同的長度。

            CString strBang( “Everybody likes ice hockey” );

            n = strBang.Replace( “hockey”, “golf” );

            ASSERT( n ==1 );

            n = strBang.Replace ( “likes” , “plays” );

            ASSERT( n == 1 );

            n = strBang.Replace( “ice”, NULL );

            ASSERT( n == 1 );

            ASSERT( strBang == “Everybody plays golg” );

            // 注意,現(xiàn)在在你的句子中有了一個額外的空格。

            // 要移走這個額外的空格,可以將它包括在要被替換的字符串中,例如,“ice ”。

             

            11.CString::ReverseFind

            int ReverseFind( TCHAR ch ) const;

            返回值: 返回此CString 對象中與要求的字符匹配的最后一個字符的索引;如果沒有找

            到需要的字符則返回-1。

            參數(shù): ch  要搜索的字符。

            說明:此成員函數(shù)在此CString 對象中搜索與一個子串匹配的最后一個字符。此函數(shù)

            類似于運(yùn)行時函數(shù)strrchr。

            示例:

            // CString::ReverseFind 示例

            CString s( "abcabc" );

            ASSERT( s.ReverseFind( 'b' ) == 4 );

             

            12.CString::Right

            CString Right( int nCount ) const; 

            throw( CMemoryException );

            返回值: 返回的字符串是最后nCount個字符。

            CString s( _T("abcdef") );

            ASSERT( s.Right(2) == _T("ef") );

             

            13.CString:: SetAt

            void SetAt( int nIndex, TCHAR ch );

             說明:可以把字符串理解為一個數(shù)組,SetAt類似于[].注意nIndex的范圍,如果不合適會有調(diào)試錯誤。 Ch 更替字符, 把nIndex位置上的字符 變成ch

             示例:

            CString s( "abc" );

            s.MakeReverse();

            ASSERT( s == "cba" );

             

            14.CString::TrimLeft

            void TrimLeft( );

            void CString::TrimLeft( TCHAR chTarget );

            說明:如果沒有參數(shù),從左刪除字符(\n\t空格等),至到遇到一個非此類字符. 當(dāng)然你也可以指定刪除那些字符. 如果指定的參數(shù)是字符串,那么遇上其中的一個字符就刪除. \n  換行符 \t  TAB字符

            示例1: CString str = "\n\t a";

            str.TrimLeft();

            str為“a”;

             示例2:

            CString str = "abbcadbabcadb ";

            str.TrimLeft("ab");

            結(jié)果"cadbabcadb "

            str.TrimLeft("ac");

            結(jié)果"bcadbabcadb "

             

            15.CString::TrimRight

            void TrimRight( );

            void CString::TrimRight( TCHAR chTarget );

            void CString::TrimRight( LPCTSTR lpszTargets );

            說明:用法類似于上面。

             

            16.CString::Compare

            int Compare( LPCTSTR lpsz ) const;

            返回值:字符串一樣返回0,小于lpsz  返回-1,大于lpsz  返回1, 區(qū)分大小字符

            示例:

            CString s1( "abc" );

            CString s2( "abd" );

            ASSERT( s1.Compare( s2 ) == -1 );

            ASSERT( s1.Compare( "abe" ) == -1 

            17.CString::CompareNoCase

            int CompareNoCase( LPCTSTR lpsz ) const;

            返回值: 字符串一樣 返回0,小于lpsz  返回-1,大于lpsz  返回1,不區(qū)分大小字符

             

            18.CString::Collate

            int Collate( LPCTSTR lpsz ) const;

            同CString::Compare

             

            19.CString::CollateNoCase

            int CollateNocase( LPCTSTR lpsz ) const;

            同CString::CompareNoCase

             

            20.CString::CString      //構(gòu)造函數(shù)

            CString( );

            CString( const CString& stringSrc ); 

            CString( TCHAR ch, int nRepeat = 1 ); 

            CString( LPCTSTR lpch, int nLength );

            CString( const unsigned char* psz ); 

            CString( LPCWSTR lpsz );

            CString( LPCSTR lpsz );

            示例:

            CString s1;                     

            CString s2( "cat" );              

            CString s3 = s2;                 

            CString s4( s2 + " " + s3 );        

            CString s5( 'x' );                      // s5 = "x"

            CString s6( 'x', 6 );                   // s6 = "xxxxxx"

            CString s7((LPCSTR)ID_FILE_NEW);        // s7 = "Create a new document"

            CString city = "Philadelphia";

             

            21.CString::Delete

            int Delete( int nIndex, int nCount = 1); 

            返回值:是被刪除前的字符串的長度

            nIndex是第一個被刪除的字符,nCount是一次刪除幾個字符。根據(jù)我實驗得出的結(jié)果:當(dāng)nCount>要刪除字符串的最大長度(GetCount() - nIndex)時會出錯,當(dāng)nCount過大,沒有足夠的字符刪除時,此函數(shù)不執(zhí)行。

            示例:

            CString str1,str2,str3;

            char a;

            str1 = "nihao";

            str2 = "nIhao";

            int x;

            // int i=(str1 == str2);      

            str1.Delete(2,3);

            如果nCount(3) > GetCount() – nIndex (5-2)就會執(zhí)行錯誤

             

            22.CString::Empty

            Void Empty( );

            返回值:沒有返回值  清空操作;

            示例:

            CString s( "abc" );

            s.Empty();

            ASSERT( s.GetLength( ) == 0 );

             

            23.CString::Find

            int Find( TCHAR ch ) const;

            int Find( LPCTSTR lpszSub ) const;

            int Find( TCHAR ch, int nStart ) const;

            int Find( LPCTSTR lpszSub, int nStart ) const;

            返回值:  不匹配的話返回 -1;  索引以0 開始; nStar 代表以索引值nStart 的字符開始搜索 ,

            即為包含以索引nStart字符后的字符串.

            示例:

            CString s( "abcdef" );

            ASSERT( s.Find( 'c' ) == 2 );

            ASSERT( s.Find( "de" ) == 3 );

            Cstring str(“The stars are aligned”);

            Ing n = str.Find('e',5);

            ASSERT(n == 12)

             

            24.CString::FindOneOf

            int FindOneOf( LPCTSTR lpszCharSet ) const;

            返回值:  不匹配的話返回 -1;  索引以0 開始

            注意::返回此字符串中第一個在lpszCharSet中也包括字符并且從零開始的索引值

            示例:

            CString s( "abcdef" );

            ASSERT( s.FindOneOf( "xd" ) == 3 ); // 'd' is first match.

             

            25.CString::Format

            void Format( LPCTSTR lpszFormat, ... );

            void Format( UINT nFormatID, ... );

            參數(shù):lpszFormat  一個格式控制字符串

            nFormatID  字符串標(biāo)識符

            示例:

            CString str;

            Str.Format(“%d”,13); 

            此時Str為13

             

            26.CString::GetAt

            TCHAR GetAt( int nIndex ) const;

            返回值:返回標(biāo)號為nIndex的字符,你可以把字符串理解為一個數(shù)組,GetAt類似于[].注意nIndex的范圍,如果不合適會有調(diào)試錯誤。

             

            27.CString::GetBuffer

            LPTSTR GetBuffer( int nMinBufLength );

            返回值:一個指向?qū)ο蟮模ㄒ钥兆址Y(jié)尾的)字符緩沖區(qū)的LPTSTR 指針。

            參數(shù):nMinBufLength

            字符緩沖區(qū)的以字符數(shù)表示的最小容量。這個值不包括一個結(jié)尾的空字符的空間。

            說明:此成員函數(shù)返回一個指向CString 對象的內(nèi)部字符緩沖區(qū)的指針。返回的LPTSTR 不是const,因此可以允許直接修改CString 的內(nèi)容。如果你使用由GetBuffer 返回的指針來改變字符串的內(nèi)容,你必須在使用其它的CString 成員函數(shù)之前調(diào)用ReleaseBuffer 函數(shù)。

            在調(diào)用ReleaseBuffer 之后,由GetBuffer 返回的地址也許就無效了,因為其它的CString 操作可能會導(dǎo)致CString 緩沖區(qū)被重新分配。如果你沒有改變此CString 的長度,則緩沖區(qū)不會被重新分配。當(dāng)此CString 對象被銷毀時,其緩沖區(qū)內(nèi)存將被自動釋放。

            注意:如果你自己知道字符串的長度,則你不應(yīng)該添加結(jié)尾的空字符。但是,當(dāng)你用ReleaseBuffer 來釋放該緩沖區(qū)時,你必須指定最后的字符串長度。如果你添加了結(jié)尾的空字符,你應(yīng)該給ReleaseBuffer 的長度參數(shù)傳遞-1 ,ReleaseBuffer 將對該緩沖區(qū)執(zhí)行strlen 來確定它的長度。

            示例:

            // CString::GetBuffer 例子

            CString s( "abcd" );

            #ifdef _DEBUG

            afxDump << "CString s " << s << "\n";

            #endif

            LPTSTR p = s.GetBuffer( 10 );

            strcpy( p, "Hello" ); // 直接訪問CString 對象。

            s.ReleaseBuffer( );

            #ifdef _DEBUG

            afxDump << "CString s " << s << "\n";

            #endif

             

            28.CString::GetLength

            int GetLength( ) const;

            返回值:返回字符串中的字節(jié)計數(shù)。

            說明:此成員函數(shù)用來獲取這個CString 對象中的字節(jié)計數(shù)。這個計數(shù)不包括結(jié)尾的空字符。

            對于多字節(jié)字符集(MBCS),GetLength 按每一個8 位字符計數(shù);即,在一個多字節(jié)字符中的開始和結(jié)尾字節(jié)被算作兩個字節(jié)。

            示例

            下面的例子說明了如何使用CString::GetLength。

            // CString::GetLength 示例

            CString s( "abcdef" );

            ASSERT( s.GetLength() == 6 );

             

            29.CString::Insert

            int Insert( int nIndex, TCHAR ch ); 

            int Insert( int nIndex, LPCTSTR pstr );

            返回值:返回修改后的長度,nIndex是字符(或字符串)插入后的索引號例子

            示例:

            CString str( “HockeyBest”);

             int n = str.Insert( 6, “is” );

             ASSERT( n == str.GetLength( ) ); 

            printf( “1: %s\n”, ( LPCTSTR ) str );

             n = str.Insert( 6, ' ' ); 

            ASSERT( n == str.GetLength( ) ); 

            printf ( “2: %s\n”, (LPCTSTR) STR );

             n = str.Insert(555, ‘1’);

            ASSERT( n == str.GetLength ( ) );

             printf ( “3: %s\n”, ( LPCTSTR ) str );

            輸出

            1. Hockeyis Best

            2. Hockey is Best

            3. Hockey is Best!

            posted @ 2009-05-22 09:19 wrh 閱讀(48194) | 評論 (0)編輯 收藏
            在開發(fā)軟件的過程里,經(jīng)常需要把數(shù)據(jù)保存到當(dāng)前執(zhí)行文件路徑下面,或者讀取當(dāng)前執(zhí)行文件路徑下的一些配置信息。這時就需要從當(dāng)前模塊里獲取所在的目錄路徑,以便進(jìn)行固定的位置操作文件。要解決這個需求,就需要調(diào)用API函數(shù)GetModuleFileName來獲取模塊所在的路徑。

            函數(shù)GetModuleFileName聲明如下:
            WINBASEAPI
            DWORD
            WINAPI
            GetModuleFileNameA(
                __in_opt HMODULE hModule,
                __out_ecount_part(nSize, return + 1) LPCH lpFilename,
                __in    DWORD nSize
                );
            WINBASEAPI
            DWORD
            WINAPI
            GetModuleFileNameW(
                __in_opt HMODULE hModule,
                __out_ecount_part(nSize, return + 1) LPWCH lpFilename,
                __in    DWORD nSize
                );
            #ifdef UNICODE
            #define GetModuleFileName GetModuleFileNameW
            #else
            #define GetModuleFileName GetModuleFileNameA
            #endif // !UNICODE
            hModule是模塊的句柄,或者設(shè)置為NULL表示當(dāng)前模塊。
            lpFilename是保存路徑的緩沖區(qū)。
            nSize是緩沖區(qū)的大小。

            調(diào)用函數(shù)的例子如下:
            #001 //獲取當(dāng)前程序所在路徑。
            #002  //蔡軍生 2007/12/05 QQ:9073204 深圳
            #003  void TestGetExePath(void)
            #004  {
            #005        //
            #006        const int nBufSize = 512;
            #007        TCHAR chBuf[nBufSize];
            #008        ZeroMemory(chBuf,nBufSize);
            #009
            #010        //獲取當(dāng)前執(zhí)行文件的路徑。
            #011        if (GetModuleFileName(NULL,chBuf,nBufSize))
            #012        {
            #013              //輸出帶文件名稱路徑。
            #014              OutputDebugString(chBuf);
            #015              OutputDebugString(_T("\r\n"));
            #016
            #017              //獲取文件路徑。
            #018              TCHAR* lpStrPath = chBuf;
            #019              PathRemoveFileSpec(lpStrPath);
            #020              OutputDebugString(lpStrPath);
            #021              OutputDebugString(_T("\r\n"));
            #022        }
            #023
            #024  }

            輸出的結(jié)果如下:
            g:\work\windows_api\wincpp2\debug\WinCpp.exe
            g:\work\windows_api\wincpp2\debug
            posted @ 2009-05-22 08:36 wrh 閱讀(459) | 評論 (0)編輯 收藏
            GetModuleFileName是獲得程序當(dāng)前的運(yùn)行目錄
            GetCurrentDirectory獲取當(dāng)前進(jìn)程所有在的目錄

            復(fù)制代碼
            1.  CFileDialog fdlg(true);
            2.  fdlg.DoModal();//////
            3.  TCHAR *pBuffer = new TCHAR[1024];
            4.  ZeroMemory(pBuffer, 1024);
            5.  GetCurrentDirectory(1024, pBuffer);
            6.  MessageBox(pBuffer, L"GetCurrentDirectory");
            7.  ZeroMemory(pBuffer, 1024);
            8.  GetModuleFileName(NULL, pBuffer, 1024);
            9.  MessageBox(pBuffer, L"GetModuleFileName");

            posted @ 2009-05-22 08:26 wrh 閱讀(863) | 評論 (0)編輯 收藏

            下載本文示例代碼

            想要通過ODBC直接讀、寫Excel表格文件,首先,應(yīng)確保ODBC中已安裝有Excel表格文件的驅(qū)動"MICROSOFT EXCEL DRIVER (*.XLS)"。然后,可根據(jù)下面步驟進(jìn)行:

            1. 在StdAfx.h文件中加入:
            #include <afxdb.h>

            #include <odbcinst.h>

            2. 通過ODBC直接創(chuàng)建Excel文件并在表中插入數(shù)據(jù)(暫定文件名:Demo.xls)
            //創(chuàng)建并寫入Excel文件

            void CRWExcel::WriteToExcel()

            {

              CDatabase database;

              CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安裝驅(qū)動

              CString sExcelFile = "c:\\demo.xls";                // 要建立的Excel文件

              CString sSql;

               

              TRY

              {

                // 創(chuàng)建進(jìn)行存取的字符串

                sSql.Format("DRIVER={%s};DSN='''';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",

                            sDriver, sExcelFile, sExcelFile);

             

                // 創(chuàng)建數(shù)據(jù)庫 (既Excel表格文件)

                if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )

                {

                  // 創(chuàng)建表結(jié)構(gòu)(姓名、年齡)

                  sSql = "CREATE TABLE demo (Name TEXT,Age NUMBER)";

                  database.ExecuteSQL(sSql);

             

                  // 插入數(shù)值

                  sSql = "INSERT INTO demo (Name,Age) VALUES (''徐景周'',26)";

                  database.ExecuteSQL(sSql);

             

                  sSql = "INSERT INTO demo (Name,Age) VALUES (''徐志慧'',22)";

                  database.ExecuteSQL(sSql);

             

                  sSql = "INSERT INTO demo (Name,Age) VALUES (''郭徽'',27)";

                  database.ExecuteSQL(sSql);

                }     

             

                // 關(guān)閉數(shù)據(jù)庫

                database.Close();

              }

              CATCH_ALL(e)

              {

                TRACE1("Excel驅(qū)動沒有安裝: %s",sDriver);

              }

              END_CATCH_ALL;

            }

            3. 通過ODBC直接讀取Excel文件(暫定文件名:Demo.xls)
            // 讀取Excel文件

            void CRWExcel::ReadFromExcel()

            {

                CDatabase database;

                CString sSql;

                CString sItem1, sItem2;

                CString sDriver;

                CString sDsn;

                CString sFile = "Demo.xls";    // 將被讀取的Excel文件名

                                                

                // 檢索是否安裝有Excel驅(qū)動 "Microsoft Excel Driver (*.xls)"

                sDriver = GetExcelDriver();

                if (sDriver.IsEmpty())

                {

                    // 沒有發(fā)現(xiàn)Excel驅(qū)動

                    AfxMessageBox("沒有安裝Excel驅(qū)動!");

                    return;

                }

               

                // 創(chuàng)建進(jìn)行存取的字符串

                sDsn.Format("ODBC;DRIVER={%s};DSN='''';DBQ=%s", sDriver, sFile);

             

                TRY

                {

                    // 打開數(shù)據(jù)庫(既Excel文件)

                    database.Open(NULL, false, false, sDsn);

                   

                    CRecordset recset(&database);

             

                    // 設(shè)置讀取的查詢語句.

                    sSql = "SELECT Name, Age "      

                           "FROM demo "                

                           "ORDER BY Name ";

               

                    // 執(zhí)行查詢語句

                    recset.Open(CRecordset::forwardOnly, sSql, CRecordset::readOnly);

             

                    // 獲取查詢結(jié)果

                    while (!recset.IsEOF())

                    {

                        //讀取Excel內(nèi)部數(shù)值

                        recset.GetFieldValue("Name ", sItem1);

                        recset.GetFieldValue("Age", sItem2);

             

                        // 移到下一行

                        recset.MoveNext();

                    }

             

                    // 關(guān)閉數(shù)據(jù)庫

                    database.Close();

                                        

                }

                CATCH(CDBException, e)

                {

                    // 數(shù)據(jù)庫操作產(chǎn)生異常時...

                    AfxMessageBox("數(shù)據(jù)庫錯誤: " + e->m_strError);

                }

                END_CATCH;

            }

            4. 獲取ODBC中Excel驅(qū)動的函數(shù)
            CString CRWExcel::GetExcelDriver()

            {

                char szBuf[2001];

                WORD cbBufMax = 2000;

                WORD cbBufOut;

                char *pszBuf = szBuf;

                CString sDriver;

             

                // 獲取已安裝驅(qū)動的名稱(涵數(shù)在odbcinst.h里)

                if (!SQLGetInstalledDrivers(szBuf, cbBufMax, &cbBufOut))

                    return "";

               

                // 檢索已安裝的驅(qū)動是否有Excel...

                do

                {

                    if (strstr(pszBuf, "Excel") != 0)

                    {

                        //發(fā)現(xiàn) !

                        sDriver = CString(pszBuf);

                        break;

                    }

                    pszBuf = strchr(pszBuf, ''\0'') + 1;

                }

                while (pszBuf[1] != ''\0'');

             

                return sDriver;

            }

            作者信息:
            姓名:徐景周(未來工作室 Future Studio)
            EMAIL:jingzhou_xu@163.net

            本文來自: 乘風(fēng)原創(chuàng)程序(http://www.qqcf.com) 詳細(xì)出處參考:http://study.qqcf.com/web/197/22219.htm

            posted @ 2009-05-21 21:25 wrh 閱讀(874) | 評論 (0)編輯 收藏

            一、 VC 提供的數(shù)據(jù)庫訪問技術(shù)

            ODBC API MFC ODBC DAO OLE DB ADO

            訪問速度:傳統(tǒng)的 ODBC 速度較慢。 OLE DB ADO 都是基于 COM 技術(shù),使用該技術(shù)可以直接訪問數(shù)據(jù)庫的驅(qū)動程序,速度大大提高。

             

            可擴(kuò)展性:通過 OLE DB ActiveX 技術(shù),可以利用 VC 提供的各種組件,控件和第三方提供的組建。從而實現(xiàn)應(yīng)用程序組件化。

             

            訪問不同數(shù)據(jù)源:傳統(tǒng) ODBC 只能訪問關(guān)系數(shù)據(jù)庫。 VC 中提供 OLD DB 技術(shù)可以解決該問題。

            二、 幾種技術(shù)概述

            1、 ODBC API

            提供一個通用接口,為 ORACLE SQLSERVER 都提供了驅(qū)動程序。用戶可以 SQL 語句對數(shù)據(jù)庫進(jìn)行直接的底層功能操作。使用時應(yīng)包含以下頭文件。 ”SQL.H”,”SQLEXT.H”,”SQLTYPES.H”.

            使用步驟如下:

            第一步:分配 ODBC 環(huán)境,初始化一些內(nèi)部結(jié)構(gòu)。完成該步,需要分配一個 SQLHENV 類型的變量在 ODBC 環(huán)境中做句柄使用。

            第二步:為將要使用的每一個數(shù)據(jù)源分配一個連接句柄,有函數(shù) SQLALLocHandle ()完成。

            第三步:使用 SQLConnect ()把連接句柄與數(shù)據(jù)庫連接,可以先通過 SQLSetConnectAttr ()設(shè)置連接屬性。

            第四步:進(jìn)行 SQL 語句操作。操作完就可以斷開與數(shù)據(jù)庫的連接。

            第五步:釋放 ODBC 環(huán)境。

             

            特點(diǎn):功能強(qiáng)大,提供異步操作,事務(wù)處理等高級功能。目前所有關(guān)系數(shù)據(jù)庫都提供了 ODBC 的驅(qū)動程序,使用很廣泛。

            缺點(diǎn):很難訪問對象數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫。

             

            2、 MFC ODBC

             

            為簡化使用 ODBC API VC 提供了 MFC ODBC 類,封裝了 ODBC API

            主要 MFC ODBC 類如下:

            CDatabase 類:一個 CDatabase 對象表示一個到數(shù)據(jù)源的連接,通過它可以操作數(shù)據(jù)源。一般不需要直接使用 CDatabase 對象,因為 CDecordSet 對象可以實現(xiàn)大多數(shù)功能,但在進(jìn)行事務(wù)處理時, CDatabase 就起到關(guān)鍵作用。

            CRecordSet 類:一個 CRecordSet 對象代表一個從數(shù)據(jù)源選擇的一組記錄的集合 ----- 記錄集。記錄集有兩種形式: snapshot dynaset 。前者表示是靜態(tài)視圖。后者表示記錄集與其它用戶對數(shù)據(jù)庫的更新保持同步。

            CRecordView 類:是在空間中顯示數(shù)據(jù)庫記錄的視圖。這種視圖是直接連到一個 CRecordSet 對象的格式視圖。他從一個對話框模版資源創(chuàng)建。并將 CRecordSet 對象的字段顯示在對話框模版的控件里。對象利用 DDX RFX 機(jī)制。使格式上的控件和記錄集的字段之間數(shù)據(jù)移動自動化。

            CDBException 類:由 Cexception 類派生,以 3 個繼承的變量反映對數(shù)據(jù)庫操作時的異常。

             M_nRetCode: ODBC 返回碼。

            M_strError: 字符串,描述造成拋出異常的錯誤原因。

            M_strStateNativeOrigin: 字符串,描述以 ODBC 錯誤碼表示的異常錯誤。

             

            3、 MFC DAO

             

            MFC DAO 是微軟提供的用于訪問 Microsoft Jet 數(shù)據(jù)庫文件( * Mdb )的工具。當(dāng)只需訪問 Access 數(shù)據(jù)庫時用該技術(shù)很方便。

            4、 OLE DB

             

            ODBC 技術(shù)類似, OLE DB 屬于數(shù)據(jù)庫訪問技術(shù)中的底層接口。

            直接使用 OLEDB 需要大量代碼, VC 中提供了 ATL 模版,

            OLEDB 框架定義了應(yīng)用的 3 個基本類。

             

            數(shù)據(jù)提供程序 Data Provider 擁有自己的數(shù)據(jù)并以表格形式顯示數(shù)據(jù)的應(yīng)用程序。

            使用者 Consumers :試用 OLEDB 接口對存儲在數(shù)據(jù)提供程序中對數(shù)據(jù)進(jìn)行控制的應(yīng)用程序。

            服務(wù)提供程序 ServiceProvider :是數(shù)據(jù)提供程序和使用者的組合。

             

            使用 OLE DB 編程時,用戶使用組件對象開發(fā)程序,這些組件包括:

            枚舉器:用于列出可用的數(shù)據(jù)源;

            數(shù)據(jù)源:代表單獨(dú)的數(shù)據(jù)和服務(wù)提供程序,用于創(chuàng)建對話;

            對話:     用于創(chuàng)建事務(wù)和命令;

            事務(wù):     用于將多個操作歸并為單一事務(wù)處理;

            命令:     用于向數(shù)據(jù)源發(fā)送文本命令( SQL ),返回行集;

            錯誤:     用于獲得錯誤信息。

            5、 ADO

             

            ADO 技術(shù)是基于 OLE DB 的訪問接口。繼承了 OLEDB 的優(yōu)點(diǎn),并對 OLEDB 的接口作了封裝,定義了 ADO 對象,使開發(fā)簡化。 ADO 屬于數(shù)據(jù)庫訪問的高層接口。

             

            ADO 在服務(wù)器應(yīng)用方面非常有效,特別是動態(tài)服務(wù)器頁面( ASP )的支持。

             

            ADO 對象結(jié)構(gòu)類似于 OLEDB ,但并不依靠對象層次。大多數(shù)情況用戶只需創(chuàng)建并使用需要的對象。下面的對象類組成了 ADO 接口。

             

            Connection  用于表示與數(shù)據(jù)庫的連接,以及處理一些事務(wù)和命令。

            Command    用于處理傳送給數(shù)據(jù)源的命令。

            Recordset    用于處理數(shù)據(jù)的表格集, 包括獲取和修改數(shù)據(jù)。

            Field            用于表示記錄集中的列信息,包括列值和其他信息。

            Parameter    在傳送給數(shù)據(jù)源的命令之間傳遞數(shù)據(jù)。

            Property      用于操作在 ADO 中使用的其它對象的詳細(xì)屬性。

            Errro           用于獲取可能發(fā)生的詳細(xì)錯誤信息

            posted @ 2009-05-21 21:18 wrh 閱讀(397) | 評論 (0)編輯 收藏
            使用VC編程來操縱Office。你可以實現(xiàn)諸如:Word文件打印、傳送數(shù)據(jù)到Word文檔、發(fā)送E-MAIL、自動產(chǎn)生表格、Excel數(shù)據(jù)統(tǒng)計、圓餅圖,直方圖顯示、自動報表生成、播放幻燈、doc,txt,HTML,rtf文件轉(zhuǎn)換、中文簡繁體轉(zhuǎn)換、拼音或筆畫排序......只要是Office能夠?qū)崿F(xiàn)的功能,都可以在你寫的程序中調(diào)用。仔細(xì)閱讀下面的說明,并下載源文件進(jìn)行參考,你就可以一步一步地掌握這個技術(shù)。祝朋友們學(xué)習(xí)快樂。

              一、概念

              Microsoft 的 Office 產(chǎn)品中,都提供了OLE Automation 自動化程序的接口。如果你使用VB,VBA 和 Script 腳本調(diào)用 Office 功能的話,其實比使用 VC 調(diào)用要簡單的多。比如在 WORD 中,調(diào)出菜單“工具(T)\宏(M)\錄制新宏(R)”,這時候它開始記錄你在 WORD 中任何菜單和鍵盤的操作,把你的操作過程保存起來,以便再次重復(fù)調(diào)用。而保存這些操作的記錄,其實就是使用了 VBA 程序(Visual Basic for Application)。而我們下面要實現(xiàn)的功能,也同樣要參考 VBA 的方法。

              二、結(jié)構(gòu)層次

              為了更有邏輯,更有層次地操作 Office,Microsoft 把應(yīng)用(Application)按邏輯功能劃分為如下的樹形結(jié)構(gòu)

            Application(WORD 為例,只列出一部分)
            Documents(所有的文檔)
            Document(一個文檔)
            ......
              Templates(所有模板)
            Template(一個模板)
            ......
              Windows(所有窗口)
            Window
            Selection
            View
            Selection(編輯對象)
            Font
            Style
            Range
            ......
            ......

              只有了解了邏輯層次,我們才能正確的操縱 Office。舉例來講,如果給出一個VBScript語句是:
            application.ActiveDocument.SaveAs "c:\abc.doc"

              那么,我們就知道了,這個操作的過程是:第一步,取得Application;第二步,從Application中取得ActiveDocument;第三步,調(diào)用 Document 的函數(shù) SaveAs,參數(shù)是一個字符串型的文件名。
            三、基本步驟

              (1)創(chuàng)建(或打開已有的)一個 MFC 的程序工程

              (2)Ctrl+W 執(zhí)行 ClassWizard(本文按照 VC6 操作,例子程序也是在VC6 下編寫測試的)

              (3)Add Class...\From a type Library... 在 Office 目錄中,找到你想使用的類型庫。(我使用的是 Office2000,其Word 的類型庫文件,保存在 C:\Program Files\Microsoft Office\Office\MSWORD9.OLB)根據(jù)你 Office 的版本,可以使用下表列出的類型庫文件

            Office 版本和類型 類型庫文件 Office 版本和類型 類型庫文件
            Access 97 Msacc8.olb PowerPoint 2000 Msppt9.olb
            Jet Database 3.5 DAO350.dll Word 2000 Msword9.olb
            Binder 97 Msbdr8.olb Access 2002 Msacc.olb
            Excel 97 Excel8.olb Excel 2002 Excel.exe
            Graph 97 Graph8.olb Graph 2002 Graph.exe
            Office 97 Mso97.dll Office 2002 MSO.dll
            Outlook 97 Msoutl97.olb Outlook 2002 MSOutl.olb
            PowerPoint 97 Msppt8.olb PowerPoint 2002 MSPpt.olb
            Word 97 Msword8.olb Word 2002 MSWord.olb
            Access 2000 Msacc9.olb Office Access 2003 Msacc.olb
            Jet Database 3.51 DAO360.dll Office Excel 2003 Excel.exe
            Binder 2000 Msbdr9.olb Graph 2003 Graph.exe
            Excel 2000 Excel9.olb Office 2003 MSO.dll
            Graph 2000 Graph9.olb Office Outlook 2003 MSOutl.olb
            Office 2000 Mso9.dll Office PowerPoint 2003 MSPpt.olb
            Outlook 2000 Msoutl9.olb Office Word 2003 MSWord.olb

              (4)選擇類型庫文件后,在彈出的對話窗中繼續(xù)選擇要添加的類。具體選擇什么類,要看你將來在程序中打算調(diào)用什么功能。當(dāng)然,你也可以不用考慮這么多,用鼠標(biāo)和Shift鍵配合,全部選擇也可以。

              (5)初始化COM。方法一,找到App的InitInstance()函數(shù),在其中添加 AfxOleInit()函數(shù)的調(diào)用;方法二,在需要調(diào)用COM功能的地方 CoInitialize(NULL),調(diào)用完畢后 CoUninitialize()。

              (6)在你需要調(diào)用 Office 功能函數(shù)的 cpp 文件中

            #include <atlbase.h> // 為了方便操作 VARIANT 類型變量,使用 CComVariant 模板類
            #include "頭文件.h"
            // 具體的頭文件名,是由裝載類型庫的文件名決定的。(鼠標(biāo)雙點(diǎn)包裝類的文件,就可以看到)
            // 比如使用 msword9.olb類型庫,那么頭文件是 msword9.h

              (7)好了,現(xiàn)在開始寫程序吧。另外要說明的是,步驟3和4,其實也可以使用 #import 方式引入類型庫。

              四、實現(xiàn)技巧

              在書寫調(diào)用 Office 函數(shù)的過程中,最困難的是確定函數(shù)的參數(shù),一般情況下,參數(shù)都是 VARIANT 類型的變量指針。那么到底具體我們應(yīng)該怎么寫那?推薦兩個方法,其一是閱讀有關(guān) VBA 的書籍;其二,是使用 Office 中自帶的“宏”功能。強(qiáng)烈推薦大家使用第二個方法,把你要完成的功能,在 Office 的操作環(huán)境中,用宏錄制下來,然后觀察分析錄制后的函數(shù)和參數(shù),就可以在 VC 中使用了。舉一個例子:

            ActiveDocument.SaveAs FileName:="Hello.doc", FileFormat:=wdFormatDocument _
            , LockComments:=False, Password:="", AddToRecentFiles:=True, _
            WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
            SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
            False

              以上是在 Word 中錄制的一個保存文件的宏,而在 VC 中對應(yīng)的函數(shù)原型為 void _Document::SaveAs(VARIANT* FileName, VARIANT* FileFormat, VARIANT* LockComments,
            VARIANT* Password, VARIANT* AddToRecentFiles, VARIANT* WritePassword,
            VARIANT* ReadOnlyRecommended, VARIANT* EmbedTrueTypeFonts, VARIANT* SaveNativePictureFormat,
            VARIANT* SaveFormsData, VARIANT* SaveAsAOCELetter)

              分析對照后,我們就能看出,參數(shù) FileName 是字符串 VARIANT(VT_BSTR),參數(shù) LockComments 是布爾VARIANT(VT_BOOL),等等。參數(shù) FileFormat := wdFormatDocument 是什么類型那?其實這是一個表示保存的時候指定文件類型的常量,而且顯然是 DWORD 類型VARIANT(VT_I4)。那么常量的數(shù)值又是多少那?很簡單,寫一個宏,調(diào)用函數(shù) MsgBox 顯示一下不就都知道啦?!

              五、步步為營

              特別提示一:編譯執(zhí)行前,一定要先關(guān)閉 KV 實時監(jiān)視病毒的功能(KV 的程序會干擾我們的調(diào)用,瑞星的則沒關(guān)系)。

               特別提示二:在例子程序中,為了表現(xiàn)程序的關(guān)鍵部分,沒有或很少使用了條件判斷。為了實現(xiàn)你程序的健壯性,請自己加上條件判斷和異常處理。

              Step1:如何啟動和關(guān)閉 WORD,及 VARIANT 的最基本的使用方法
              Step2:和 Step1 同樣功能,用 CComVariant 改進(jìn)了 VARIANT 的使用方式
              Step3:在 Step2 的基礎(chǔ)上,新建一個 WORD 文檔,并從程序中傳送一些字符到 WORD
              Step4:在 Step3 的基礎(chǔ)上,保存 WORD 文檔
              Step5:一個小應(yīng)用舉例,把輸入的漢字按照“筆畫”排序
              Step6:一個小應(yīng)用舉例,盜竊正在使用的 WORD 文檔

              以上這6個小程序中,都有詳細(xì)的注釋。大家閱讀后慢慢體會并實驗,你就可以自由地操縱任何一個 Office 啦。

              源代碼下載

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

            導(dǎo)航

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

            統(tǒng)計

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            99久久成人国产精品免费| 亚洲色大成网站www久久九| 久久综合狠狠综合久久综合88| 狠狠色综合网站久久久久久久| 国产午夜精品久久久久免费视 | 久久国产免费观看精品3| 亚洲伊人久久综合中文成人网 | 久久久久亚洲AV成人网人人网站 | 亚洲国产精品一区二区三区久久| 国内精品久久国产大陆| 性欧美大战久久久久久久久 | 国产精品久久久久天天影视| 久久久久亚洲av无码专区喷水| 日本久久久久亚洲中字幕| 日韩精品久久久久久免费| 久久综合国产乱子伦精品免费| 狠狠色丁香久久婷婷综合五月| 久久99亚洲网美利坚合众国| 99久久国产综合精品麻豆| 一级做a爰片久久毛片16| 久久精品二区| 久久久久亚洲精品日久生情| 97精品依人久久久大香线蕉97 | 久久久久国产一区二区三区| 久久夜色撩人精品国产| 久久久久精品国产亚洲AV无码| 亚洲AV无码久久精品色欲| 久久99国产精品久久99果冻传媒| 国产AV影片久久久久久| 一本久久免费视频| 成人国内精品久久久久一区| 久久av免费天堂小草播放| 久久国产欧美日韩精品免费| 久久综合给合久久狠狠狠97色| 久久成人影院精品777| 午夜视频久久久久一区 | 久久精品无码午夜福利理论片| 一本大道加勒比久久综合| 久久人人爽人人爽人人爽| 91麻豆精品国产91久久久久久| 伊人久久大香线蕉成人|