代码改变世界

Win32 Application (VC\MFC) 控制台mini调试工具 mDebug 0.1

2013-04-10 14:51  wid  阅读(2873)  评论(5编辑  收藏  举报

 

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" 即可, 无需其他设置。

点此下载 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 下 (展开查看):

View Code - mDebug sample
 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 游戏编程 - 贪吃蛇