VC雕蟲小技集(四)

原文:VC雕蟲小技集(四)
 

VC雕蟲小技集()

何志丹

1, 閱讀程序常常要看此變量在那些地方值改變過

ctrl+f查找太麻煩

將此變量前加const

改變的地方報錯

 :office" />

2, 看一個函數被那些函數調用.

方法:

1,調試狀態下,view->debug window->call Stack

2,class view 的快捷菜單中選擇called by

 

3, 在狀態欄的最左邊顯示時間

static UINT indicators[] =

{

        ID_SEPARATOR,//我們增加的

       ID_SEPARATOR,          

       ID_INDICATOR_CAPS,

       ID_INDICATOR_NUM,

       ID_INDICATOR_SCRL,

};

 

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

      .....       m_wndStatusBar.SetPaneInfo(1,ID_SEPARTOR,SBPS_NORMAL,60);

}

 

//菜單的響應函數

void CMainFrame::OnTest()

{

    CTime t;

       t = CTime::GetCurrentTime();

       CString str = t.Format("%H - %M  -%S");

       m_wndStatusBar.SetPaneText(0,str);

 

}

 

4,模擬鼠標

::SetCursorPos((int)ptMouse->x,(int)ptMouse->y);

::mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);    

::mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);   

::mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);

::mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

 

5,什麼是WORD, DWORD

 typedef unsigned short WORD

 typedef unsigned long  DWORD

 

6,移動控件

 CWnd * pWnd = GetDlgItem(IDC_BUTTON1);

       CRect r;

       pWnd->GetWindowRect(&r);

       r.left +=50;

       r.right += 50;

       pWnd->MoveWindow(r);

 

7, 如何讓對話框中的CEdit響應ENTER鍵回車

GetDlgItem(IDC_EDIT1)->SetWindowText("111/r/n22");

右鍵屬性

sytle -> Multiline選上

最好把want return 也選上

 

8,c語言轉化爲彙編

VC++ provides this feature.

Project->Settings...

C/C++ tab

Category: Choose Listing Files

Listing file type:

select "Assembly with source code"

 

9,如何獲得進程所消耗的CPU時間?

BOOL GetProcessTimes(

  HANDLE hProcess,

  LPFILETIME lpCreationTime,

  LPFILETIME lpExitTime,

  LPFILETIME lpKernelTime,

  LPFILETIME lpUserTime

);

 

10,如何通過擴展名得到該擴展名所對應的圖標?

SHGetFileInfo(path,

              attr,

              &sfi,

              sizeof(SHFILEINFO),

              SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_TYPENAME);

 

 

 

如何在拉着對話框的邊框改變大小時,讓它成比例的變化.就像視頻播放軟件哪樣

處理wm_sizing消息

void CTest 1Dlg::OnSizing(UINT fwSide, LPRECT pRect)

{

  CDialog::OnSizing(fwSide, pRect);

  if((fwSide==WMSZ_BOTTOM) || (fwSide==WMSZ_TOP))

    pRect->right=pRect->left+(pRect->bottom-pRect->top)*2; 

  else

    pRect->bottom=pRect->top+(pRect->right-pRect->left)*0.5; 

}



CNBIE BLOG

VC調試技術小技巧(2)

原文:VC調試技術小技巧(2)
 
#ifndef XTIB_H
#define XTIB_H
// Call SetThreadName(), and then paste this expression into the watch window:
//    (char*)(DW(@TIB+0x14))
 
#pragma pack(1)
 
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
         struct _EXCEPTION_REGISTRATION_RECORD * pNext;
         FARPROC                                                                         pfnHandler;
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
 
typedef struct tagXTIB
{
         PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list
         PVOID      pvStackUserTop;                        // 04h Top of user stack
         PVOID      pvStackUserBase;                       // 08h Base of user stack
 
         union                                                                          // 0Ch (NT/Win95 differences)
         {
                   struct                                                                // Win95 fields
                   {
                            WORD      pvTDB;                                // 0Ch TDB
                            WORD      pvThunkSS;                        // 0Eh SS selector used for thunking to 16 bits
                            DWORD   unknown1;                           // 10h
                   } WIN95;
 
                   struct        // WinNT fields
                   {
                            PVOID SubSystemTib;              // 0Ch
                            ULONG FiberData;                      // 10h
                   } WINNT;
         } TIB_UNION1;
 
         PVOID      pvArbitrary;                                  // 14h Available for application use
         struct _tib *ptibSelf;                             // 18h Linear address of TIB structure
 
         union                                                                          // 1Ch (NT/Win95 differences)
         {
                   struct        // Win95 fields
                   {
                            WORD      TIBFlags;                    // 1Ch
                            WORD      Win16MutexCount;  // 1Eh
                            DWORD   DebugContext;          // 20h
                            DWORD   pCurrentPriority;       // 24h
                            DWORD   pvQueue;                    // 28h Message Queue selector
                   } WIN95;
 
                   struct        // WinNT fields
                   {
                            DWORD unknown1;                           // 1Ch
                            DWORD processID;                   // 20h
                            DWORD threadID;                     // 24h
                            DWORD unknown2;                           // 28h
                   } WINNT;
         } TIB_UNION2;
 
         PVOID*    pvTLSArray;                               // 2Ch Thread Local Storage array
 
         union                                                                          // 30h (NT/Win95 differences)
         {
                   struct        // Win95 fields
                   {
                            PVOID*    pProcess;                    // 30h Pointer to owning process database
                   } WIN95;
         } TIB_UNION3;
 
 
         // Internal function to get the TIB
         /*----------------------------------------------------------------------
         FUNCTION    :   GetTIB
 
         DEs criptION :   Returns pointer to TIB for current thread.
 
         PARAMETERS  :   None.
 
         RETURNS     :   NULL  - A really bad thing
                    !NULL - Pointer to TIB for current thread
         ----------------------------------------------------------------------*/
         static tagXTIB * GetTIB()
         {
                   tagXTIB * pTib;
 
                   __asm
                   {
                            MOV  EAX , FS:[18h]
                            MOV  pTib , EAX
                   }
                   return pTib;
         }
 
         /*----------------------------------------------------------------------
         FUNCTION    :   SetThreadName
 
DEs criptION :   SetThreadName provides a way to "name" your threads so that you can
                    see at a glance which thread is active when you are in the debugger.
                    Calling SetThreadName sets the string pointer parameter into the Thread
                    Information Block (TIB) pvArbitrary field (offset 0x14).  Matt Pietrek
                    discussed the TIB structure in his May 1996 "Under the Hood" column.
                    I included Matt's TIB.h as part of this project if you want to see the
                    rest of the fields in the TIB.
                    pvArbitrary is an unused spot in the TIB that applications can use
                    as they wish.  SetThreadName does the right thing and checks if the
                    pvArbitrary is not 0 and will not write the string pointer to avoid
                    tromping on any other data written there.
                    To view which thread is active in the Watch window, use
                    "(char*)(DW(@TIB+0x14))"  As you swap threads, you can now tell at a
                    glance which thread you are in!
 
         PARAMETERS  :   szName - A pointer to the string which you would like to name the
                    current thread.  You should make the string pointer a
                    constant name.
 
         RETURNS     :   TRUE  - The thread name was set.
                    FALSE - Something else overwrote the pvArbitrary field.
         ----------------------------------------------------------------------*/
         static BOOL SetThreadName(LPCTSTR szName)
         {
                   // Grab the TIB.
                   tagXTIB * pTib = GetTIB();
 
                   // If someone has already written to the arbitrary field, I don't
                   // want to be overwriting it.
                   if (pTib->pvArbitrary != NULL)
                            return FALSE;
 
                   // Nothing's there.  Set the name.
                   pTib->pvArbitrary = (void*)szName;
 
                   return TRUE;
         }
 
         /*----------------------------------------------------------------------
         FUNCTION    :   GetThreadName
 
         DEs criptION :   Returns the string pointer to the name assigned to the
                    current thread.
 
         PARAMETERS  :   None.
 
         RETURNS     :   NULL  - No name was assigned.
                    !NULL - The value at the TIB pvArbitrary offset.  Please
                    note that the pointer could be invalid of if something
                    other than SetThreadName used the pvArbitrary offset.
         ----------------------------------------------------------------------*/
         static LPCTSTR GetThreadName()
         {
                   // Grab the TIB.
                   tagXTIB * pTib = GetTIB();
 
                   return (LPCTSTR)pTib->pvArbitrary;
         }
 
 
} XTIB;
 
#pragma pack()
 
#endif //XTIB_H




CNBIE BLOG

vc調試經驗

原文:vc調試經驗
 

       最經常在csdn上看到關於調試方面的文章,人氣值也挺旺,可是要消化那一大堆文字確實也是不容易的事。在這裏,我也來寫一段!希望對大家有所幫助。

       我們在做vc編程調試時經常遇到需要顯示變量的內容之類的問題,在dos模式下我們簡單使用printf(...)就行了,在windows我們如何顯示變量內容呢?大家肯定有許多方法如:調試時設置斷點,用MessagBox什麼的。我在開始使用vc時,也經常採用這樣的方法來調試,但遇到一些不能用斷點調試的程序時,比如某些繪圖的程序裏需要在ondraw裏計算,就沒辦法了,把變量寫到文件裏吧?太麻煩了,還是看看仔細檢查源代碼吧!

        一個偶然的機會,我終於發現了windows下類似printf的東東了,那就是_RPT。

        大家在自己vc 的源程序里加上_RPT1(0,"i=%d/n",i);到debug模式下運行一下。好了,看到結果了吧!那_RPT1能有幾個參數嗎?不行!哪要有兩個參數怎麼辦?那就用_RPT2吧!其他的就自己試吧!

        [email protected]





CNBIE BLOG

VC調用ACM音頻壓縮編程接口的方法

原文:VC調用ACM音頻壓縮編程接口的方法
 

音 頻 和 視 頻 數 據 是 大 多 數 多 媒 體 應 用 程 序 向 用 戶 提 供 信 息 的 主 要 方 式, 這 些 數 據 一 般 具 有較 高 的 採 樣 速 率, 如 果 不 經 過 壓 縮 的 話, 保 存 它 們 需 要 消 耗 大 量 的 存 貯 空 間, 在 網 絡 上 進 行 傳 輸的 效 率 也 很 低, 因 此 音 頻 視 頻 數 字 壓 縮 編 碼 在 多 媒 體 技 術 中 佔 有 很 重 要 的 地 位。 就 音 頻 數 據 而言, 目 前 常 用 的 壓 縮 方 法 有 很 多 種, 不 同 的 方 法 具 有 不 同 的 壓 縮 比 和 還 原 音 質, 編 碼 的 格 式 和 算法 也 各 不 相 同, 其 中 某 些 壓 縮 算 法 相 當 復 雜, 普 通 程 序 不 可 能 去 實 現 其 編 解 碼 算 法。 所 幸 的 是,與Windows 3.x 相 比,Windows 95/NT 4.0 爲 多 媒 體 應 用 程 序 提 供 了 更 強 的支 持, 引 入 了ACM(Audio Compression Manager, 音 頻 壓 縮 管 理 器) 和VCM(Video Compression Manager, 視 頻 壓 縮 管 理 器), 它 們 負 責 管 理 系 統 中 所 有 音 頻 和 視 頻 編 解 碼 器(Coder-Decoder,簡 稱CODEC, 是 實 現 音 頻 視 頻 數 據 編 解 碼 的 驅 動 程 序), 應 用 程 序 可 以 通 過ACM 或VCM 提 供 的 編 程接 口 調 用 這 些 系 統 中 現 成 的 編 解 碼 器 來 實 現 音 頻 或 視 頻 數 據 的 壓 縮 和 解 壓 縮。95/NT 4.0 系 統自 帶 的 音 頻CODECs 支 持 一 些 早 期 的 音 頻 數 據 壓 縮 標 準, 如ADPCM 等,Internet Explorer 4.0 等應 用 程 序 包 含 的 音 頻CODECs 支 持 一 些 比 較 新 的 壓 縮 標 準, 如MPEG Layer 3 等。 在 控 制 面 板 的 多媒 體 組 件 中 選 擇“ 高 級”, 打 開“ 音 頻 壓 縮 的 編 碼 解 碼 器”, 就 可 列 出 系 統 中 安 裝 的 所 有 音 頻CODECs。本 文 所 要 介 紹 的 就 是ACM 音 頻 壓 縮 接 口 的 編 程 方 法, 所 用 編 程 工 具 爲VC++ 5.0。

獲 取CODECs 的 信 息

---- ACM API msacm.h 中, 外, ACM mmsystem.hmmreg.h 構。 ACM ACM 用, 調 acmGetVersion ACM 息。

---- 前 面 提 到, 在控 制 面 板 中 可 以 查 看 系 統 中CODECs 的 信 息, 而 在 應 用 程 序 中 也 常 常 需 要 知 道 某 種 音 頻CODECs 是否 存 在, 並 獲 取 其 編 解 碼 參 數 等 信 息, 這 一 點 可 以 通 過 調 用 下 面 兩 個 函 數 來 實 現。

---- MMRESULT mmr=acmMetrics(NULL, ACM_METRIC_COUNT_CODECS, &dwCodecs);

---- mmr = acmDriverEnum(CodecsEnumProc, 0, 0);

---- acmMetrics() 函 數 可 以 獲 取 許 多ACM 對 象 的 有 用 信 息, 例 如 向 其 中 傳 遞ACM_METRIC_COUNT_CODECS 可 以 查 詢 系 統 中 安 裝 的 音 頻CODECs 總 數。 函 數acmDriverEnum() 的 功 能 是 枚 舉 所 有 的 音 頻CODECs,在acmDriverEnum() 的 參 數 中 指 定 回 調 函 數CodecsEnumProc() 可 以 進 一 步 查 詢 每 個CODEC 的 信息。Windows 編 程 中 經 常 要 用 到 回 調 函 數, 下 面 是 枚 舉 音 頻CODECs 的 一 個 回 調 函 數 的 示 例。

 

 

BOOL CALLBACK CodecsEnumProc(HACMDRIVERID 

 

hadid, DWORD dwInstance, DWORD fdwSupport) {

 

DWORD dwSize = 0;

 

if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)

 

 printf("多格式轉換/n");

 

ACMDRIVERDETAILS add;

 

acmdd.cbStruct = sizeof(acmdd);

 

MMRESULT mmr = acmDriverDetails(hadid, &acmdd, 0);

 

if (mmr)  error_msg(mmr);

 

else {

 

printf(" 全稱:  %s/n", acmdd.szLongName);

 

printf(" 描述:   %s/n", acmdd.szFeatures);

 

}

 

HACMDRIVER had = NULL;

 

mmr = acmDriverOpen(&had, hadid, 0);      //打開驅動

 

if (mmr)  error_msg(mmr);

 

else {

 

mmr = acmMetrics(had, ACM_METRIC_

 

MAX_SIZE_FORMAT, &dwSize);

 

WAVEFORMATEX* pwf = (WAVEFORMATEX*) malloc(dwSize);

 

memset(pwf, 0, dwSize);

 

pwf->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);

 

pwf->wFormatTag = WAVE_FORMAT_UNKNOWN;

 

ACMFORMATDETAILS fd;

 

memset(&fd, 0, sizeof(fd));

 

fd.cbStruct = sizeof(fd);  fd.pwfx = pwf;  fd.cbwfx = dwSize;

 

fd.dwFormatTag = WAVE_FORMAT_UNKNOWN;

 

mmr = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);  

 

if (mmr)  error_msg(mmr);

 

free(pwf);

 

acmDriverClose(had, 0);

 

}

 

return TRUE; 

 

}

 

---- CodecsEnumProc() 共 有 三 個 參 數。 第 一 個 參 數 是 驅 動 程 序 的ID 值; 第 二 個 參 數 是 實 例 數 據, 本文 例 子 中 未 使 用; 第 三 個 參 數 描 述 該 驅 動 程 序 所 支 持 的 功 能, 它 由 一 組 標 識 進 行 或 運 算 構 成, 例如, 如 果 設 置 了 標 識ACMDRIVERDETAILS_SUPPORTF_CODEC, 則 說 明 該 驅 動 程 序 可 以 將 一 種 編 碼 格式 的 音 頻 信 號 轉 換 成 另 一 種 編 碼 格 式。 通 過acmDriverDetails() 函 數 可 以 獲 得 對 該 驅 動 程 序 進一 步 的 信 息, 如CODEC 的 名 稱、 簡 單 描 述 等。 以 上 信 息 實 際 上 是 由ACM 收 集, 並 保 存 在ACM 內 部, 所以 查 詢 以 上 信 息 時 並 未 真 正 將 驅 動 程 序 加 載 至 內 存。 而 要 獲 得 每 一 種 驅 動 程 序 支 持 的 音 頻 格 式信 息, 則 必 須 將 驅 動 程 序 加 載 至 內 存, 這 是 通 過acmDriverOpen() 完 成 的, 在 退 出CodecsEnumProc() 前, 還 要 用acmDriverClose() 來 關 閉 已 打 開 的 驅 動 程 序。 在 使 用 音 頻 格 式 枚 舉 函 數 前, 需 要 先 分配 一 塊 緩 衝 區 存 置 格 式 信 息, 緩 衝 區 的 大 小 可 通 過 調 用acmMetrics() 查 詢ACM_METRIC_MAX_SIZE_FORMAT 獲 得, 格 式 信 息 中 的 音 頻 格 式 標 識 設 爲WAVE_FORMAT_UNKNOWN。 在 音 頻 格 式 枚 舉 中 同 樣 使 用 了 回調 函 數, 此 回 調 函 數 只 是 列 出 了 該 音 頻 格 式 的 名 稱 和 標 識 值。

BOOL CALLBACK FormatEnumProc

 

(HACMDRIVERID hadid, LPACMFORMATDETAILS

 

 pafd, DWORD dwInstance, DWORD fdwSupport) {

 

printf("%4.4lXH, %s/n", pafd- >dwFormatTag, pafd- >szFormat);

 

return TRUE; 

 

}

 

---- 上 面 介 紹 了 瀏覽 系 統 中 所 有 音 頻CODECs 及 每 種CODEC 所 支 持 的 音 頻 格 式 的 方 法, 某 些 典 型 的 應 用 程 序 可 能 需要 列 出 系 統 中 所 有 可 以 選 用 的CODECs, 並 由 用 戶 來 選 擇 使 用 哪 一 種CODEC 進 行 壓 縮, 此 時 就 需 要利 用 上 面 的 編 程 方 法 來 獲 取CODECs 的 信 息。

音 頻 數 據 的 壓 縮

---- 使 CODEC 程, 序。 8K 樣、16bits PCM 碼、 道、 1 號。 Windows 95 TrueSpeech CODEC 101 縮。 中,TrueSpeech CODEC 換, 中, CODEC 式, 法, 式, 式, PCM 單, CODEC 持, PCM 種。

---- 在 進 行 壓 縮 之前 首 先 需 要 確 定TrueSpeech 驅 動 程 序 的ID 值。 爲 此 需 要 用 到acmDriverEnum() 函 數, 對 枚 舉 到 的每 一 個 驅 動 程 序, 由acmDriverEnum() 指 定 的 回 調 函 數 將 檢 查 其 支 持 的 所 有 音 頻 格 式, 若 其 中 包括wFormatTag 值 爲WAVE_FORMAT_DSPGROUP_TRUESPEECH 的 音 頻 格 式, 則 此 驅 動 程 序 就 是 要 尋 找的TrueSpeech CODEC, 它 所 支 持 的 第 一 種WAVE_FORMAT_DSPGROUP_TRUESPEECH 音 頻 格 式 即 爲 目標 音 頻 壓 縮 格 式。 查 詢 所 需 的CODEC 及 其 支 持 的 音 頻 格 式 的 方 法 見 前 一 小 節 的 介 紹。

---- 根 據 查 詢 的 結果, 設hadID 爲TrueSpeech CODEC 的ID 值,pwfDrv 爲 指 向 目 標WAVEFORMATEX 結 構 的 指 針, 接 下 來利 用 獲 得 的ID 值 打 開 相 應 的 驅 動 程 序。

HACMDRIVER had = NULL;

 

mmr = acmDriverOpen(&had, hadID, 0);

 

if(mmr) {  printf(" 打開驅動失敗/n"); exit(1);  }

 

---- 壓 縮 和 解 壓 縮一 樣, 都 是 將 音 頻 信 號 從 一 種 音 頻 格 式 轉 換 成 另 一 種 格 式, 要 完 成 這 一 過 程, 首 先 要 打 開 轉 換 流。在 用acmStreamOpen 打 開 轉 換 流 時, 我 們 指 定 了ACM_STREAMOPENF_NONREALTIME 標 志, 它 表 示 轉換 無 需 實 時 進 行。 因 爲 很 多 壓 縮 算 法 的 計 算 量 是 相 當 大 的, 實 時 完 成 幾 乎 是 不 可 能 的, 例 如 在 本例 中, 如 果 不 指 定 此 標 志,TrueSpeech CODEC 就 會 返 回“ 無 法 完 成” 的 錯 誤。

HACMSTREAM hstr = NULL;

 

DWORD dwSrcBytes = dwSrcSamples * wfSrc.wBitsPerSample / 8;

 

mmr = acmStreamOpen(&hstr,had, //驅動句柄

 

pwfSrc, //指向源音頻格式的指針

 

pwfDrv, //指向目標音頻格式的指針

 

NULL, //無過濾器

 

NULL, //無回調函數

 

0,ACM_STREAMOPENF_NONREALTIME);

 

---- 在 真 正 進 行 轉換 之 前, 還 必 須 準 備 轉 換 流 的 信 息 頭。 下 面 一 段 代 碼 中, 先 利 用 源 數 據 的 大 小 以 及 目 標 格 式 的 平均 數 據 率 估 算 目 標 數 據 的 緩 存 區 大 小, 然 後 調 用acmStreamPrepareHeader 爲 轉 換 準 備 信 息 頭。

---- DWORD dwDstBytes=pwfDrv->nAvgBytesPerSec*dwSrcSamples/wfSrc.nSamplesPerSec;

---- dwDstBytes = dwDstBytes*3/2; // 計 算 壓 縮 後 音 頻 數 據 大 小, 並 依 此 適 當 增 加 輸 出 緩 衝 區 的 大 小。

BYTE* pDstData = new BYTE [dwDstBytes];

 

ACMSTREAMHEADER shdr;

 

memset(&strhdr, 0, sizeof(shdr));

 

shdr.cbStruct = sizeof(shdr);

 

shdr.pbSrc = pSrcData;          //源音頻數據區

 

shdr.cbSrcLength = dwSrcBytes;

 

shdr.pbDst = pDstData; //壓縮後音頻數據緩衝區

 

shdr.cbDstLength = dwDstBytes;

 

mmr = acmStreamPrepareHeader(hstr, &shdr, 0); 

 

---- 語 音 數 據 真 正的 壓 縮 過 程 是 由 函 數acmStreamConvert() 完 成 的。 在 調 用acmStreamConvert() 時 可 以 指 定 回 調函 數, 以 便 在 轉 換 過 程 中 顯 示 進 度 信 息 等。 在 本 例 中, 未 指 定 回 調 函 數, 只 是 簡 單 地 等 待 壓 縮 的結 束。

---- mmr = acmStreamConvert(hstr, &shdr, 0);

---- 數 據 壓 縮 完 畢後, 應 用 程 序 就 可 以 把 緩 衝 區 中 的 數 據 寫 入 目 標 文 件 中。

---- 最 後, 必 須 關閉 轉 換 流 和 驅 動 程 序。

mmr = acmStreamClose(hstr, 0);

 

mmr = acmDriverClose(had, 0);

 

---- ACM CODEC 程, ACM VC++ 5 ACM
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章