Win32 Application (VC\MFC) 控制台mini調試工具 mDebug 0.1
目錄
1. 這是什么
mDebug 是一個 VC \ MFC Win32 Application 的輸出級調試工具, 他能方便的在寫 win32 窗口程序時添加一個控制台台窗口, 對所要輸出的變量進行值的查看, 支持增強型格式化輸出以及輸出顏色自定義色彩、高亮等。
通常, 在使用 C\C++ 寫 VC\MFC 窗口程序中, 由於離開了控制台, 也就意味着不能使用 printf、puts 等輸出函數來快捷的在運行過程中查看某個變量的當前值, 要在程序運行中即時查看某個變量的當前值是多少, 除使用專業的調試工具外, 常用的做法還有:
- 用 MessageBox 彈出
- 輸出結果到文件
先來看這個 MessageBox 進行彈出, 根據 MessageBox 的函數原型:
int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
首先他只能輸出兩個字符串型的值, 對於要查看一個數字, 我們還得先建立一個 szBuffer, 然后使用 sprintf 將數字寫到 szBuffer 中再使用 MessageBox 進行彈出。
對於第二種方式, 輸出結果到文件, 盡管 C\C++ 語言提供了非常簡便的標准輸入輸出來進行文件的創建與寫入, 但是不能即時的查看結果, 必須等文件關閉后, 然后我們去打開那個文本文件才能看到結果。
總的來說, 這兩種方式都不太理想, 筆者還是希望能夠像在控制台中那樣, 一個 printf 格式化輸出就能看到值是多少, 在前幾天用 C語言 win32 寫一個小游戲中( [開源] C 語言 win32 游戲編程 - 貪吃蛇 ), 由於要處理一些 點 (POINT結構) 和 矩形 (RECT結構)時, 筆者就深深的感覺到了不能方便的通過輸出即時的查看一個點或矩形的值所帶來的麻煩, mDebug 正是為了解決這個小問題而誕生的, 他的特色如下:
- 在調試窗口程序時將引入控制台
- 能夠使用像 printf 格式的普通的格式化輸出
- 增強型格式化輸出能夠直接輸出 POINT、SIZE、RECT 等結構變量的信息
- 支持通過格式化輸出的方式對輸出的顏色進行自定義的高亮
2. 如何使用
mDebug 為了方便使用, 目前僅有一個 .h 構成, 在使用時只需要將該文件放在 include 目錄下或者當前項目所在的目錄下然后 #include "mdebug.h" 即可, 無需其他設置。
1>. 初始化
mDebug 在程序中使用時需要進行初始化, 也就是引入控制台窗口, 初始化函數的原型為
void debugInit(); //初始化 mDebug 調試庫
你可以在使用 mDebug 的格式化輸出函數前的任何地方進行初始化, 一個比較好的方案就是在處理 WM_CREATE 消息對 mDebug 進行初始化, 這樣控制台窗口就會隨着win32窗口的創建而建立。
switch( message ) { case WM_CREATE: debugInit(); //初始化 mDebug 調試庫 return 0;
與初始化相反的還有一個 debugFree(); 函數, 當該函數被調用時控制台窗口會被關閉, 如果你想讓控制台窗口隨窗口程序一同關閉, 那么便無需調用該函數, 或者在處理 WM_DESTROY 小時時進行調用。
2>. 普通格式化輸出 mPuts
mPuts為 mDebug 提供的基礎型格式化輸出, 使用方法同 C 語言的 printf 相同, 可以輸出一個字符串, 也可以進行 %c, %d, %f 這樣的格式化輸出, 示例:
mPuts( "n = %d, f = %.2f\n", 1024, 0.6183 );
3>. 增強型格式化輸出 mPutsEx
增強型格式化輸出能夠直接輸出一個結構中的全部成員, 而不必一個個的對單個成員進行輸出, 目前支持的結構有 POINT、SIZE、RGBQUAD、RECT 這些常用結構, 並且, mPutsEx 能夠使用字體以及背景顏色。
%pt == 輸出 POINT 結構 %rect == 輸出 RECT 結構 %size == 輸出 SIZE 結構 %rgb == 輸出 RGBQUAD 結構
示例:
rect.left = 10; rect.top = 20; rect.right = 30; rect.bottom = 40; pt.x = 100; pt.y = 200; mPutsEx( "POINT結構: %pt\nRECT結構: %rect", pt, rect );
輸出如下:
4>. 對 mPutsEx 輸出進行顏色控制
mPutsEx的輸出顏色管理也是通過格式化符 % 來完成的, 默認文字顏色為白色, 背景顏色為黑色, 先來一個使用示例:
mPutsEx( "%bkgreenRECT結構: %fryellow%rect", rect );
輸出如下:
在上面的示例中, %bkxxx 表示輸出的背景顏色, %frxxx 表示前景顏色, 除默認的黑色和白色外, mPutsEx還持支持以下6種顏色:
// %frred == 前景顏色, 紅色 // %frgreen == 前景顏色, 綠色 // %frblue == 前景顏色, 藍色 // %fryellow == 前景顏色, 黃色 // %frfrcyan == 前景顏色, 青色 // %frmag == 前景顏色, 品紅 // %bkred == 背景顏色, 紅色 // %bkgreen == 背景顏色, 綠色 // %bkblue == 背景顏色, 藍色 // %bkyellow == 背景顏色, 黃色 // %bkfrcyan == 背景顏色, 青色 // %bkmag == 背景顏色, 品紅 // %endfr == 結束前景顏色格式化輸出 // %endbk == 結束背景顏色格式化輸出
在默認情況下, 背景顏色以及前景顏色的作用域僅為當前一行, 遇到換行符 \n 自動恢復默認的前景顏色以及背景顏色。
3. 現有不足
盡管目前的這個版本已經能夠滿足筆者暫時對控制台下進行即時輸出的需求, 但從真正的實用性來說, 它還是不夠強大,主要表現在以下三個方面:
- mPuts 的緩沖區大小設置為 10*1024 個字節, 沒有做到能夠無盡輸出;
- mPuts 還沒有實現標准的 %f, %d 等這些普通格式化輸出, 要使用普通的格式化輸出暫時只能使用 mPuts 進行代替了, 但是這樣一來有沒法對顏色進行輸出;
- 增強型格式化輸出支持的結構體還不夠多, 目前只有 RECT、POINT、SIZE、RGBQUAD 這4種, 有待添加更多。
不過筆者也會根據實際需求來對 mDebug 進行不定期的擴展, 盡量讓其實用性更強一些,
4. 如何擴展
如果你想讓 mDebug 更個性化些, 可以直接打開 mdebug.h 文件直接對文件進行修改, 隨意發布你的修改后屬於你的版本, 且無需注明以前有關作者的任何相關信息。
1>. 自定義RECT、POINT等結構體的輸出格式:
mdebug.h 中的注釋差不多也算十分明確了, 以修改輸出點POINt結構的信息為例, 在 mdebug.h 中的 printPOINT 即為POINT結構體的輸出方法, 默認如下:
//輸出點 int printPOINT( POINT pt ) { _cprintf( "(x=%d, y=%d)", pt.x, pt.y ); //輸出格式 return 0; }
可以看到, _cprintf 中的輸出格式為一對小括號加pt.x, pt.y的值說明x=, y=, 修改這里的輸出格式即可影響到調用時的輸出格式。mdebug.h 的主要實現原理就是C語言可變參數 va_list 以及其相關的宏的運用。
2>. 添加更多的結構體格式化輸出支持:
添加更多的結構體支持需要2步, 以 XXXX 結構體為例, 第一步是實現結構體的輸出格式函數, 例如, int printXXXX( XXXX var ), 第二步將該函數關聯到格式化符中, 例如:
//增強型數據類型輸出 -- 找到這個注釋, 在這里添加 if( matchString( "xxxx", &szFormat ) ) // %xxxx == 你對 XXXX 結構期望的格式符, 不含 % 號 { var = va_arg( pArgList, XXXX ); //需要在上面(mPutsEx函數內)定義一個 XXXX 類型的結構變量 var printXXX( var ); //然后將 var 傳到輸出格式中 }
3>. 自由發揮
5. 使用示例
一個完整的使用示例, 工程類型為 Win32 Application, 運行在 VC6 下 (展開查看):

1 #include <windows.h> 2 #include "mdebug.h" 3 4 ////////////////////////////////////////////////////////////////////////// 5 6 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); 7 8 ////////////////////////////////////////////////////////////////////////// 9 10 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdline, int iCmdShow ) 11 { 12 TCHAR szAppName[] = TEXT("mDebug"); 13 14 HWND hwnd; 15 MSG msg; 16 WNDCLASS wndclass; 17 18 wndclass.cbClsExtra = 0; 19 wndclass.cbWndExtra = 0; 20 wndclass.hbrBackground = GetSysColorBrush( COLOR_3DFACE ); 21 wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); 22 wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); 23 wndclass.hInstance = hInstance; 24 wndclass.lpfnWndProc = WndProc; 25 wndclass.lpszClassName = szAppName; 26 wndclass.lpszMenuName = NULL; 27 wndclass.style = CS_HREDRAW | CS_VREDRAW; 28 29 if( !RegisterClass(&wndclass) ) 30 { 31 MessageBox( NULL, TEXT("窗口類注冊失敗!"), TEXT("應用程序錯誤"), MB_OK | MB_ICONERROR ); 32 return 0; 33 } 34 35 hwnd = CreateWindow( 36 szAppName, 37 TEXT("mDebug - Win32 Application 調試工具 - Demo"), 38 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 39 600, 400, 40 NULL, NULL, hInstance, NULL 41 ); 42 43 ShowWindow( hwnd, iCmdShow ); 44 UpdateWindow( hwnd ); 45 46 while( GetMessage(&msg, NULL, 0, 0) ) 47 { 48 TranslateMessage( &msg ); 49 DispatchMessage( &msg ); 50 } 51 52 return msg.wParam; 53 } 54 55 ////////////////////////////////////////////////////////////////////////// 56 57 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) 58 { 59 RECT rect = {0}; 60 POINT pt = {0}; 61 RGBQUAD rgb = {0}; 62 63 rgb.rgbBlue = 100; 64 rgb.rgbGreen = 125; 65 rgb.rgbRed = 213; 66 67 switch( message ) 68 { 69 case WM_CREATE: //在處理創建消息時對 mDebug 進行初始化 70 debugInit(); //初始化 mDebug 71 return 0; 72 73 case WM_LBUTTONDOWN: //點擊鼠標左鍵查看輸出 74 rect.left = 10; rect.top = 20; 75 rect.right = 30; rect.bottom = 40; 76 77 pt.x = 100; pt.y = 200; 78 79 mPuts( "mDebug提供的普通格式化輸出:\n" ); //使用普通格式化輸出函數 mPuts 80 mPuts( "x = %d, f = %f, c = %c\n\n", 3+5, 1.79, 'w' ); 81 82 mPutsEx( "mDebug提供的增強型格式化輸出:\n" ); //使用增強型格式化輸出函數 mPutEx 83 mPutsEx( "RECT結構: %rect\n", rect ); 84 mPutsEx( "%bkgreen顏色增強:%endbk %fryellow%rect\n", rect ); 85 mPutsEx( "%frmagRGBQUAD結構:%endbk %bkred%rgb\n", rgb ); 86 87 return 0; 88 89 case WM_DESTROY: 90 debugFree(); //關閉調試窗口 91 PostQuitMessage(0); 92 return 0; 93 } 94 95 return DefWindowProc( hwnd, message, wParam, lParam ); 96 }
--------------------
wid, 2013.04.10
上一篇: [開源] C 語言 win32 游戲編程 - 貪吃蛇