ab.com コミュニティ
https://www.activebasic.com/forum/

コンソールの作成と入出力
https://www.activebasic.com/forum/viewtopic.php?t=2308
ページ 11

作成者:  ゲスト [ 2008年2月17日(日) 02:50 ]
記事の件名:  コンソールの作成と入出力

コンソールの作成・破棄とコンソールに対する入出力を行うクラスです。

ウィンドウプログラムでコンソールを使いたかったので、調べて作ってみました。


「#console」を指定したときにでてくるコンソールと同じですが、
個人的にString型(クラス)は好きではないのでBytePtr型で入出力を行っています。

また、AB5(CP3)では「#console」指定ができない(エラーになる)ため、
このクラスを使うことでAB5でもコンソールプログラムを書く事ができます。

コード:
/********  WIN32API定義  ********/
' 必要に応じてコメントアウトしてください
Declare Function AllocConsole Lib "kernel32" () As Long
Declare Function FreeConsole Lib "kernel32" () As Long
Declare Function ReadConsole Lib "kernel32" Alias "ReadConsoleA" ( _
    hConsoleInput As HANDLE, lpBuffer As BytePtr, nNumberOfCharsToRead As Long, _
    ByRef lpNumberOfCharsRead As DWord, lpReserved As Long) As Long
Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (
    hConOut As HANDLE, lpszText As BytePtr, lpcText As Long, ByRef NumWrite As DWord, NotUsed As Long) As Long

Const STD_INPUT_HANDLE      = -10   ' 標準入力のハンドルを取得
Const STD_OUTPUT_HANDLE     = -11   ' 標準出力のハンドルを取得
Const STD_ERROR_HANDLE      = -12   ' 標準エラーのハンドル取得



/********  コンソール処理クラス  ********/

Const CONSOLE_BUFSIZE = 1023

Class Console

    Private: StdIn As HANDLE                '標準入力ハンドル
    Private: StdOut As HANDLE               '標準出力ハンドル
    Private: buf[CONSOLE_BUFSIZE] As Byte   '入力バッファ(文字列用固定長)
    Private: _mem As VoidPtr                '入力バッファ(数値用可変長)


    Public '////////  コンストラクタ  ////////
    Sub Console()
        'AllocConsole()                             'コンソールを割り当てる
        StdIn   = GetStdHandle(STD_INPUT_HANDLE)    '標準入力ハンドルを取得
        StdOut  = GetStdHandle(STD_OUTPUT_HANDLE)   '標準出力ハンドルを取得
        _mem = 0                                    '可変長入力バッファの初期化
    End Sub

    Public '////////  デストラクタ  ////////
    Sub ~Console()
        'FreeConsole()                              'コンソールを解放する
        free(_mem)                                  '可変長入力バッファを解放する
    End Sub



    Public '////////  文字列出力(改行なし)  ////////
    Sub PrintStr(lpString As BytePtr)
        Dim length As DWord
        WriteConsole(StdOut, lpString, lstrlen(lpString), length, 0)
    End Sub


    Public '////////  文字列出力(改行あり)  ////////
    Sub PrintStrEx(lpString As BytePtr)
        Dim length As DWord
        WriteConsole(StdOut, lpString, lstrlen(lpString), length, 0)
        WriteConsole(StdOut, Ex"\r\n", 2, length, 0)
    End Sub


    Public '////////  整数値出力(改行なし)  ////////
    Sub PrintInt(Value As Long)
        Dim buf[31] As Byte
        wsprintf(buf, "%d", Value)
        PrintStr(buf)
    End Sub


    Public '////////  整数値出力(改行あり)  ////////
    Sub PrintIntEx(Value As Long)
        Dim buf[31] As Byte
        wsprintf(buf, Ex"%d\r\n", Value)
        PrintStr(buf)
    End Sub


    Public '////////  文字列入力  ////////
    Function InputStr(lpOutputString As BytePtr) As BytePtr
        Dim length As DWord
        PrintStr(lpOutputString)
        ReadConsole(StdIn, buf, CONSOLE_BUFSIZE, length, 0)
        buf[length-2]=0        '改行コードを読み取らない
        return buf
    End Function


    Public '////////  整数値入力  ////////
    Function InputInt(lpOutputString As BytePtr, item As Long) As *Long
        '戻り値: item=0 -> 入力した値    item<>0 -> 入力した値が格納された配列へのポインタ

        Dim ptr As *Long, str As BytePtr, ctr As Long
        Dim offset As Long

        'メモリバッファを更新
        If 0<>item then ptr=MemUpdate(SizeOf(Long)*item)

        Do
            '文字列で入力
            str = InputStr(lpOutputString)
            '「item=0」なら値をそのまま返す
            If 0=item then return Val(str) As Long

            'カウンタ類の初期化
            ctr = 0:  offset = 0
            Do
                '整数値に変換して格納
                ptr[ctr] = Val(str+offset) As Long
                ctr += 1

                '指定された個数の入力が終われば配列へのポインタを返す
                If item = ctr then return ptr

                '入力の区切りを見つける
                offset = InStr(offset+1, str, ",")
                If 0 = offset then Exit Do
            Loop

            '入力されたデータの個数が足らなければ再入力
            PrintStrEx("データが足らないよ!")
        Loop

    End Function



    Private '////////  メモリバッファを更新  ////////
    Function MemUpdate(size As DWord) As VoidPtr
        free(_mem)
        _mem = calloc(size)
        return _mem
    End Function

End Class

コンストラクタ・デストラクタ内のコメントアウトを外すとオブジェクト生成時にコンソールが生成され、
オブジェクト破棄時にはコンソールも解放されます。

コメントアウトを付けたままの場合は、コンソールを使用する前に「AllocConsole」を呼び出してコンソールを割り当て、
その後にこのクラスのオブジェクトを生成してください。

一旦コンソールを破棄して再び生成した場合は、このオブジェクトも生成しなおす必要があります。


また、コンソール自体はプログラム終了時に自動で破棄されるので、「FreeConsole」は呼び出さなくても大丈夫です。

作成者:  のぶあや [ 2008年2月17日(日) 02:58 ]
記事の件名:  追加事項

入力処理中は処理が止まってしまうので、ウィンドウプログラムからコンソールを処理するときは
コンソール用にスレッドを1つ作らないと固まってしまいます。

また、「ReadConsole」、「WriteConsole」の代わりに「ReadFile」、「WriteFile」 でも処理することができます。

ps.
久しぶりの投稿なので失敗してしまいました;;
・「hide」タグの付け忘れ
・自動ログオフ(タイムアウト?)でログアウトされた。

ページ 11 全ての表示時間は UTC+09:00 です
Powered by phpBB® Forum Software © phpBB Limited
https://www.phpbb.com/