< システムメニューを持たない CDialog で、タイトルバーをダブルクリックされたら最大化 <-> 元のサイズに戻す | vbNullString 実験セット >

August 2, 2005

Windows AP にコンソール出力を提供するクラス

表題の通りです。コメントもありません。DEBUGCONSOLEが定義されている場合のみコンソールが作成されます。

CDebugConsole クラスのメンバを以下に示します。

GetInstance
唯一のインスタンスへの参照を返します
SetConsoleTitle
コンソールのタイトルバー文字列を更新します
Printf
標準出力に書式付きで出力します
Errorf
標準エラー出力に書式付きで出力します
VPrintf
引数リストへのポインタを使用して、標準出力に書式付きで出力します
VErrorf
引数リストへのポインタを使用して、標準エラー出力に書式付きで出力します
Dump
渡されたデータを16進でダンプした結果を標準出力に出力します

CDebugConsole クラスのインスタンスは1個のみの存在とし、CDebugConsole::GetInstance () で参照を取得します。

int n = 10;
CDebugConsole::GetInstance ().Printf ("n は %d です。", n);

また、C ソースにインクルードした場合に同等の機能を提供する関数も定義しています。

// DebugConsole.h
#ifndef __DEBUGCONSOLE__H
#define __DEBUGCONSOLE__H

#include <windows.h>
#include <stdarg.h>
#ifdef __cplusplus

#ifdef DEBUGCONSOLE
#define __DBGINLINE
#else   //DEBUGCONSOLE
#define __DBGINLINE {}
#endif  //DEBUGCONSOLE

class CDebugConsole
{
public:
    static CDebugConsole& GetInstance (void);
    ~CDebugConsole(void)__DBGINLINE;
    
    void SetConsoleTitle (LPCTSTR lpszConsoleTitle)__DBGINLINE;
    void Printf (LPCTSTR lpszFormat, ...)__DBGINLINE;
    void Errorf (LPCTSTR lpszFormat, ...)__DBGINLINE;
    void VPrintf (LPCTSTR lpszFormat, va_list args)__DBGINLINE;
    void VErrorf (LPCTSTR lpszFormat, va_list args)__DBGINLINE;
    void Dump (int nBytesBuffer, LPVOID lpBuffer, LPCTSTR lpszLabel = NULL)__DBGINLINE;

protected:
#ifdef DEBUGCONSOLE
    BOOL m_bInitialized;
    HANDLE m_hStdout;
    HANDLE m_hStderr;
    CRITICAL_SECTION m_csStdout;
    CRITICAL_SECTION m_csStderr;
#endif  //DEBUGCONSOLE
    static CDebugConsole    s_DebugConsole;

    CDebugConsole(void)__DBGINLINE;
    void WriteHandle (HANDLE hOutput, LPCTSTR lpszFormat, va_list args)__DBGINLINE;
};

#else   //__cplusplus

#ifdef DEBUGCONSOLE

#define DbgSetConsoleTitle      DebugSetConsoleTitle
#define DbgPrintf               DebugPrintf
#define DbgErrorf               DebugErrorf
#define DbgVPrintf              DebugVPrintf 
#define DbgVErrorf              DebugVErrorf 
#define DbgDump                 DebugDump

#else   //DEBUGCONSOLE

#define DbgSetConsoleTitle      0? (void)0: DebugSetConsoleTitle
#define DbgPrintf               0? (void)0: DebugPrintf
#define DbgErrorf               0? (void)0: DebugErrorf
#define DbgVPrintf              0? (void)0: DebugVPrintf 
#define DbgVErrorf              0? (void)0: DebugVErrorf 
#define DbgDump                 0? (void)0: DebugDump

#endif  //DEBUGCONSOLE

void DebugSetConsoleTitle (LPCTSTR lpszConsoleTitle);
void DebugPrintf (LPCTSTR lpszFormat, ...);
void DebugErrorf (LPCTSTR lpszFormat, ...);
void DebugVPrintf (LPCTSTR lpszFormat, va_list args);
void DebugVErrorf (LPCTSTR lpszFormat, va_list args);
void DebugDump (int nBytesBuffer, LPVOID lpBuffer, LPCTSTR lpszLabel);

#endif  //__cplusplus
#endif  //__DEBUGCONSOLE__H
// DebugConsole.cpp
#include <stdio.h>
#include <signal.h>
#include "DebugConsole.h"

// 唯一のインスタンス
CDebugConsole CDebugConsole::s_DebugConsole;

CDebugConsole& CDebugConsole::GetInstance (void)
{
    return s_DebugConsole;
}

#ifdef DEBUGCONSOLE
CDebugConsole::CDebugConsole(void)
: m_bInitialized(FALSE), m_hStderr (NULL), m_hStdout (NULL)
{
    if (AllocConsole ())
    {
        signal (SIGINT, SIG_IGN);
        m_hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
        if (INVALID_HANDLE_VALUE != m_hStdout)
        {
            m_hStderr = GetStdHandle (STD_ERROR_HANDLE);
            if (INVALID_HANDLE_VALUE != m_hStderr)
            {
                InitializeCriticalSection (&m_csStdout);
                InitializeCriticalSection (&m_csStderr);
                m_bInitialized = TRUE;
                return;
            }
            CloseHandle (m_hStdout);
        }
        FreeConsole ();
    }
}

CDebugConsole::~CDebugConsole(void)
{
    if (m_bInitialized)
    {
        FreeConsole ();
        DeleteCriticalSection (&m_csStdout);
        DeleteCriticalSection (&m_csStderr);
    }
}

void CDebugConsole::SetConsoleTitle (LPCTSTR lpszConsoleTitle)
{
    if (!m_bInitialized)
    {
        return;
    }
    ::SetConsoleTitle (lpszConsoleTitle);
}

void CDebugConsole::Printf (LPCTSTR lpszFormat, ...)
{
    if (!m_bInitialized)
    {
        return;
    }
    va_list args;
    va_start (args, lpszFormat);
    VPrintf (lpszFormat, args);
    va_end (args);
}

void CDebugConsole::Errorf (LPCTSTR lpszFormat, ...)
{
    if (!m_bInitialized)
    {
        return;
    }
    va_list args;
    va_start (args, lpszFormat);
    VErrorf (lpszFormat, args);
    va_end (args);
}

void CDebugConsole::VPrintf (LPCTSTR lpszFormat, va_list args)
{
    if (!m_bInitialized)
    {
        return;
    }
    EnterCriticalSection (&m_csStdout);
    WriteHandle (m_hStdout, lpszFormat, args);
    LeaveCriticalSection (&m_csStdout);
}

void CDebugConsole::VErrorf (LPCTSTR lpszFormat, va_list args)
{
    if (!m_bInitialized)
    {
        return;
    }
    EnterCriticalSection (&m_csStderr);
    WriteHandle (m_hStderr, lpszFormat, args);
    LeaveCriticalSection (&m_csStderr);
}

void CDebugConsole::Dump (int nBytesBuffer, LPVOID lpBuffer, LPCTSTR lpszLabel)
{
    if (!m_bInitialized)
    {
        return;
    }
    
    SYSTEMTIME LocalTime;
    ZeroMemory (&LocalTime, sizeof (SYSTEMTIME));
    GetLocalTime (&LocalTime);
    
    LPTSTR lpszLabelTemp = _T ("");
    if (lpszLabel)
    {
        lpszLabelTemp = const_cast <LPTSTR> (lpszLabel);
    }

    LPTSTR lpszHeader = NULL;
    DWORD dwAlloc = 0;
    DWORD dwHeaderSize = -1;
    while (-1 == dwHeaderSize)
    {
        dwAlloc += 1024;
        delete [] lpszHeader;
        lpszHeader = new TCHAR [dwAlloc];
        if (!lpszHeader)
        {
            return;
        }
        dwHeaderSize = _sntprintf (lpszHeader, dwAlloc, _T ("%04d/%02d/%02d %02d:%02d:%02d.%03d %dbytes [%s]\n"
                                                "         +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F  1234567890ABCDEF\n")
                                            , LocalTime.wYear
                                            , LocalTime.wMonth
                                            , LocalTime.wDay
                                            , LocalTime.wHour
                                            , LocalTime.wMinute
                                            , LocalTime.wSecond
                                            , LocalTime.wMilliseconds
                                            , nBytesBuffer
                                            , lpszLabelTemp);
    }

    if (WriteFile (m_hStdout, lpszHeader, dwHeaderSize, &dwHeaderSize, NULL))
    {
        LPBYTE  lpbBuffer = (LPBYTE)lpBuffer;
        int nWritten = 0;
        DWORD dwWritten = 0;
        while (nWritten < nBytesBuffer)
        {
            //                          0----+----1----+----2----+----3----+----4----+----5----+----6
            TCHAR szLine []     = _T ("        ");
            TCHAR szHex []      = _T ("                                                  ");
            TCHAR szAscii []    = _T ("                ");
            LPTSTR  lpszHexPtr = szHex;
            LPTSTR  lpszAsciiPtr = szAscii;
            _stprintf (szLine, _T ("%08X"), nWritten);
            do
            {
                _stprintf (lpszHexPtr, _T (" %02X"), *lpbBuffer);
                lpszHexPtr += 3;
                if (0x20 > *lpbBuffer)
                {
                    *lpszAsciiPtr = _T ('.');
                }
                else
                {
                    *lpszAsciiPtr = (TCHAR) *lpbBuffer;
                }
                lpszAsciiPtr ++;
                lpbBuffer ++;
                nWritten ++;
            } while ((nWritten % 0x00000010) && (nWritten < nBytesBuffer));

            while (nWritten % 0x00000010)
            {
                lstrcpy (lpszHexPtr, _T ("   "));
                lpszHexPtr += 3;
                *lpszAsciiPtr ++ = _T (' ');
                nWritten ++;
            }

            if (WriteFile (m_hStdout, szLine, 8, &dwWritten, NULL))
            {
                if (WriteFile (m_hStdout, szHex, 3 * 16 + 2, &dwWritten, NULL))
                {
                    if (WriteFile (m_hStdout, szAscii, 16, &dwWritten, NULL))
                    {
                        if (WriteFile (m_hStdout, _T ("\r\n"), sizeof _T ("\r\n") - 1, &dwWritten, NULL))
                        {
                            continue;
                        }
                    }
                }
            }
            nWritten = nBytesBuffer;
            return;
        }
        WriteFile (m_hStdout, _T ("\r\n"), sizeof _T ("\r\n") - 1, &dwWritten, NULL);
    }
    delete [] lpszHeader;
}

void CDebugConsole::WriteHandle (HANDLE hOutput, LPCTSTR lpszFormat, va_list args)
{
    if (!m_bInitialized)
    {
        return;
    }
    
    LPTSTR lpszMessage = NULL;
    DWORD dwAlloc = 0;
    DWORD dwMessageSize = -1;
    
    while (-1 == dwMessageSize)
    {
        dwAlloc += 1024;
        delete [] lpszMessage;
        lpszMessage = new TCHAR [dwAlloc];
        if (!lpszMessage)
        {
            return;
        }
        dwMessageSize = _vsntprintf (lpszMessage, dwAlloc, lpszFormat, args);
    }
    
    SYSTEMTIME LocalTime;
    TCHAR   szHeader [256];

    ZeroMemory (&LocalTime, sizeof (SYSTEMTIME));
    ZeroMemory (szHeader, sizeof szHeader);
    GetLocalTime (&LocalTime);
    DWORD dwHeaderSize = _stprintf (szHeader, _T ("%04d/%02d/%02d %02d:%02d:%02d.%03d ")
        , LocalTime.wYear
        , LocalTime.wMonth
        , LocalTime.wDay
        , LocalTime.wHour
        , LocalTime.wMinute
        , LocalTime.wSecond
        , LocalTime.wMilliseconds);
    if (WriteFile (hOutput, szHeader, dwHeaderSize, &dwHeaderSize, NULL))
    {
        if (WriteFile (hOutput, lpszMessage, dwMessageSize, &dwMessageSize, NULL))
        {
            WriteFile (hOutput, _T ("\r\n"), sizeof _T ("\r\n") - 1, &dwAlloc, NULL);
        }
    }
    delete [] lpszMessage;
    lpszMessage = NULL;
}
#endif  //DEBUGCONSOLE

extern "C"
{
void DebugSetConsoleTitle (LPCTSTR lpszConsoleTitle)
{
    CDebugConsole::GetInstance ().SetConsoleTitle (lpszConsoleTitle);
}
void DebugPrintf (LPCTSTR lpszFormat, ...)
{
    va_list args;
    va_start (args, lpszFormat);
    CDebugConsole::GetInstance ().VPrintf (lpszFormat, args);
    va_end (args);
}
void DebugErrorf (LPCTSTR lpszFormat, ...)
{
    va_list args;
    va_start (args, lpszFormat);
    CDebugConsole::GetInstance ().VErrorf (lpszFormat, args);
    va_end (args);
}
void DebugVPrintf (LPCTSTR lpszFormat, va_list args)
{
    CDebugConsole::GetInstance ().VPrintf (lpszFormat, args);
}
void DebugVErrorf (LPCTSTR lpszFormat, va_list args)
{
    CDebugConsole::GetInstance ().VErrorf (lpszFormat, args);
}
void DebugDump (int nBytesBuffer, LPVOID lpBuffer, LPCTSTR lpszLabel)
{
    CDebugConsole::GetInstance ().Dump (nBytesBuffer, lpBuffer, lpszLabel);
}

};  //extern "C"

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/1022

コメント

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?