<?xml version="1.0" encoding="UTF-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>VBForums - CodeBank - Visual Basic 6 and earlier</title>
		<link>https://www.vbforums.com/</link>
		<description>Find cool or practical code examples using Visual Basic.</description>
		<language>en</language>
		<lastBuildDate>Thu, 04 Jun 2026 02:05:09 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.vbforums.com/images/misc/rss.png</url>
			<title>VBForums - CodeBank - Visual Basic 6 and earlier</title>
			<link>https://www.vbforums.com/</link>
		</image>
		<item>
			<title>Hosting console in VB6 form</title>
			<link>https://www.vbforums.com/showthread.php?912051-Hosting-console-in-VB6-form&amp;goto=newpost</link>
			<pubDate>Sat, 30 May 2026 18:35:48 GMT</pubDate>
			<description><![CDATA[This time (https://gist.github.com/wqweto/e7601ad80c1defa6af1e1f4fb9591fa3) it comes with colors. 

Image: https://dl.unicontsoft.com/upload/pix/ss_host_console.png 

Place a Timer1 on Form1 and paste this code:


Code:
---------
'--- Form1
Option Explicit
DefObj A-Z
Private Const MODULE_NAME As String = "Form1"

'=========================================================================
' API
'=========================================================================

Private Declare Function AllocConsole Lib "kernel32" () As Long
Private Declare Function FreeConsole Lib "kernel32" () As Long
Private Declare Function GetConsoleWindow Lib "kernel32" () As Long
Private Declare Function SetConsoleCtrlHandler Lib "kernel32" (ByVal HandlerRoutine As Long, ByVal Add As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileW" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetConsoleScreenBufferInfo Lib "kernel32" (ByVal hConsoleOutput As Long, lpInfo As CONSOLE_SCREEN_BUFFER_INFO) As Long
Private Declare Function SetConsoleScreenBufferSize Lib "kernel32" (ByVal hConsoleOutput As Long, ByVal dwSize As Long) As Long
Private Declare Function SetConsoleWindowInfo Lib "kernel32" (ByVal hConsoleOutput As Long, ByVal bAbsolute As Long, lpConsoleWindow As SMALL_RECT) As Long
Private Declare Function ReadConsoleOutput Lib "kernel32" Alias "ReadConsoleOutputW" (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal dwBufferSize As Long, ByVal dwBufferCoord As Long, lpReadRegion As SMALL_RECT) As Long
Private Declare Function WriteConsoleInput Lib "kernel32" Alias "WriteConsoleInputW" (ByVal hConsoleInput As Long, lpBuffer As INPUT_RECORD, ByVal nLength As Long, lpNumberOfEventsWritten As Long) As Long
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateJobObject Lib "kernel32" Alias "CreateJobObjectW" (ByVal lpJobAttributes As Long, ByVal lpName As Long) As Long
Private Declare Function SetInformationJobObject Lib "kernel32" (ByVal hJob As Long, ByVal JobObjectInformationClass As Long, lpJobObjectInformation As Any, ByVal cbJobObjectInformationLength As Long) As Long
Private Declare Function AssignProcessToJobObject Lib "kernel32" (ByVal hJob As Long, ByVal hProcess As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nW As Long, ByVal nH As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, ByVal crColor As Long) As Long
Private Declare Function SetBkColor Lib "gdi32" (ByVal hDC As Long, ByVal crColor As Long) As Long
Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, ByVal nBkMode As Long) As Long
Private Declare Function TextOutW Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal lpString As Long, ByVal nCount As Long) As Long
Private Declare Function GetTextMetrics Lib "gdi32" Alias "GetTextMetricsA" (ByVal hDC As Long, lpMetrics As TEXTMETRIC) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hDC As Long, lpBitsInfo As Any, ByVal wUsage As Long, lpBits As Long, ByVal Handle As Long, ByVal dw As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function FillRect Lib "user32" (ByVal hDC As Long, lpRect As RECT, ByVal hBrush As Long) As Long
Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal uCode As Long, ByVal uMapType As Long) As Long
Private Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
Private Declare Function ToUnicode Lib "user32" (ByVal wVirtKey As Long, ByVal wScanCode As Long, lpKeyState As Byte, ByVal pwszBuff As Long, ByVal cchBuff As Long, ByVal wFlags As Long) As Long
'--- GDI+
Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As Any, ByVal outputbuf As Long) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hBitmap As Long, ByVal hPalette As Long, hGdipBmp As Long) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
Private Declare Function GdipSaveImageToFile Lib "gdiplus" (ByVal image As Long, ByVal fileName As Long, clsidEncoder As Any, encoderParams As Any) As Long

Private Type COORD
    X                   As Integer
    Y                   As Integer
End Type

Private Type SMALL_RECT
    Left                As Integer
    Top                 As Integer
    Right               As Integer
    Bottom              As Integer
End Type

Private Type RECT
    Left                As Long
    Top                 As Long
    Right               As Long
    Bottom              As Long
End Type

Private Type CONSOLE_SCREEN_BUFFER_INFO
    dwSize              As COORD
    dwCursorPosition    As COORD
    wAttributes         As Integer
    srWindow            As SMALL_RECT
    dwMaximumWindowSize As COORD
End Type

Private Type CHAR_INFO
    UnicodeChar         As Integer
    Attributes          As Integer
End Type

Private Type KEY_EVENT_RECORD
    bKeyDown            As Long
    wRepeatCount        As Integer
    wVirtualKeyCode     As Integer
    wVirtualScanCode    As Integer
    UnicodeChar         As Integer
    dwControlKeyState   As Long
End Type

Private Type INPUT_RECORD
    EventType           As Integer
    Padding             As Integer
    KeyEvent            As KEY_EVENT_RECORD
End Type

Private Type STARTUPINFO
    cb                  As Long
    lpReserved          As Long
    lpDesktop           As Long
    lpTitle             As Long
    dwX                 As Long
    dwY                 As Long
    dwXSize             As Long
    dwYSize             As Long
    dwXCountChars       As Long
    dwYCountChars       As Long
    dwFillAttribute     As Long
    dwFlags             As Long
    wShowWindow         As Integer
    cbReserved2         As Integer
    lpReserved2         As Long
    hStdInput           As Long
    hStdOutput          As Long
    hStdError           As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess            As Long
    hThread             As Long
    dwProcessId         As Long
    dwThreadId          As Long
End Type

Private Type TEXTMETRIC
    tmHeight            As Long
    tmAscent            As Long
    tmDescent           As Long
    tmInternalLeading   As Long
    tmExternalLeading   As Long
    tmAveCharWidth      As Long
    tmMaxCharWidth      As Long
    tmWeight            As Long
    tmOverhang          As Long
    tmDigitizedAspectX  As Long
    tmDigitizedAspectY  As Long
    tmFirstChar         As Byte
    tmLastChar          As Byte
    tmDefaultChar       As Byte
    tmBreakChar         As Byte
    tmItalic            As Byte
    tmUnderlined        As Byte
    tmStruckOut         As Byte
    tmPitchAndFamily    As Byte
    tmCharSet           As Byte
End Type

Private Type BITMAPINFOHEADER
    biSize              As Long
    biWidth             As Long
    biHeight            As Long
    biPlanes            As Integer
    biBitCount          As Integer
    biCompression       As Long
    biSizeImage         As Long
    biXPelsPerMeter     As Long
    biYPelsPerMeter     As Long
    biClrUsed           As Long
    biClrImportant      As Long
End Type

Private Type JOBOBJECT_EXTENDED_LIMIT_INFORMATION
    '--- BasicLimitInformation
    PerProcessUserTimeLimit As Currency
    PerJobUserTimeLimit     As Currency
    LimitFlags              As Long
    MinimumWorkingSetSize   As Long
    MaximumWorkingSetSize   As Long
    ActiveProcessLimit      As Long
    Affinity                As Long
    PriorityClass           As Long
    SchedulingClass         As Long
    dwPadding1              As Long
    '--- IoInfo
    ReadOperationCount      As Currency
    WriteOperationCount     As Currency
    OtherOperationCount     As Currency
    ReadTransferCount       As Currency
    WriteTransferCount      As Currency
    OtherTransferCount      As Currency
    '--- rest
    ProcessMemoryLimit      As Long
    JobMemoryLimit          As Long
    PeakProcessMemoryUsed   As Long
    PeakJobMemoryUsed       As Long
End Type

'=========================================================================
' Constants and member vars
'=========================================================================

Private Const LNG_CONSOLE_COLS      As Long = 120
Private Const LNG_CONSOLE_ROWS      As Long = 30

Private m_uCtx                  As UcsConsoleContext
Private m_aColors(0 To 15)      As Long

Private Type UcsConsoleContext
    hConOut             As Long
    hConIn              As Long
    hMemDC              As Long
    hDib                As Long
    lpBits              As Long
    hOldDib             As Long
    Font                As IFont
    hOldFont            As Long
    CellWidth           As Long
    CellHeight          As Long
    BmpWidth            As Long
    BmpHeight           As Long
    ProcessInfo         As PROCESS_INFORMATION
    hJob                As Long
    CharInfo()          As CHAR_INFO
    ScreenInfo          As CONSOLE_SCREEN_BUFFER_INFO
End Type

Private Sub PrintError(sFunction As String)
    #If ImplUseDebugLog Then
        DebugLog MODULE_NAME, sFunction & "(" & Erl & ")", Err.Description & " &H" & Hex$(Err.Number), vbLogEventTypeError
    #Else
        Debug.Print "Critical error: " & Err.Description & " [" & MODULE_NAME & "." & sFunction & "]"
    #End If
End Sub

Private Sub Form_Load()
    On Error GoTo EH
    Me.ScaleMode = vbPixels
    Me.KeyPreview = True
    Me.BackColor = vbBlack
    pvConsoleInit m_uCtx
    Me.Width = Me.Width - Me.ScaleWidth * Screen.TwipsPerPixelX + m_uCtx.BmpWidth * Screen.TwipsPerPixelX
    Me.Height = Me.Height - Me.ScaleHeight * Screen.TwipsPerPixelY + m_uCtx.BmpHeight * Screen.TwipsPerPixelY
    Timer1.Interval = 30
    Timer1.Enabled = True
    Exit Sub
EH:
    PrintError "Form_Load"
End Sub

Private Sub Timer1_Timer()
    On Error GoTo EH
    pvConsoleRender m_uCtx
    Form_Paint
    If m_uCtx.ProcessInfo.hProcess <> 0 Then
        If WaitForSingleObject(m_uCtx.ProcessInfo.hProcess, 0) = 0 Then
            Unload Me
        End If
    End If
    Exit Sub
EH:
    PrintError "Timer1_Timer"
End Sub

Private Sub Form_Paint()
    Const SRCCOPY           As Long = &HCC0020

    On Error GoTo EH
    Call BitBlt(Me.hDC, 0, 0, m_uCtx.BmpWidth, m_uCtx.BmpHeight, m_uCtx.hMemDC, 0, 0, SRCCOPY)
    SaveBitmapAsPng m_uCtx.hDib, Environ$("TEMP") & "\aaa.png"
    Exit Sub
EH:
    PrintError "Form_Paint"
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    On Error GoTo EH
    Select Case KeyCode + Shift * &H10000
    Case vbKeyF4 + vbAltMask * &H10000
        Exit Sub
    Case vbKeyV + vbCtrlMask * &H10000, vbKeyInsert + vbShiftMask * &H10000
        If Clipboard.GetFormat(vbCFText) Then
            pvConsoleSendText m_uCtx.hConIn, Clipboard.GetText()
        End If
    Case Else
        pvConsoleSendKey m_uCtx.hConIn, 0, KeyCode, Shift
    End Select
    KeyCode = 0
    Exit Sub
EH:
    PrintError "Form_KeyDown"
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    On Error GoTo EH
    If Button = vbRightButton Then
        Form_KeyDown vbKeyV, vbCtrlMask
    End If
    Exit Sub
EH:
    PrintError "Form_MouseDown"
End Sub

Private Sub Form_Unload(Cancel As Integer)
    On Error GoTo EH
    Timer1.Enabled = False
    pvConsoleTerminate m_uCtx
    Exit Sub
EH:
    PrintError "Form_Unload"
End Sub

'= private ===============================================================

Private Function pvConsoleInit(uCtx As UcsConsoleContext) As Boolean
    Const SW_HIDE           As Long = 0
    Const GENERIC_READ      As Long = &H80000000
    Const GENERIC_WRITE     As Long = &H40000000
    Const FILE_SHARE_READ   As Long = 1
    Const FILE_SHARE_WRITE  As Long = 2
    Const OPEN_EXISTING     As Long = 3
    Const OPAQUE            As Long = 2
    Const DIB_RGB_COLORS    As Long = 0
    Const JobObjectExtendedLimitInformation As Long = 9
    Const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE As Long = &H2000
    Dim vSplit          As Variant
    Dim lIdx            As Long
    Dim uMetric         As TEXTMETRIC
    Dim uRect           As SMALL_RECT
    Dim uBmpHeader      As BITMAPINFOHEADER
    Dim uStartup        As STARTUPINFO
    Dim uLimit          As JOBOBJECT_EXTENDED_LIMIT_INFORMATION
    
    If m_aColors(15) = 0 Then
        vSplit = Split("&H0 &H800000 &H8000 &H808000 &H80 &H800080 &H8080 &HC0C0C0 &H808080 &HFF0000 &HFF00 &HFFFF00 &HFF &HFF00FF &HFFFF &HFFFFFF")
        For lIdx = 0 To 15
            m_aColors(lIdx) = vSplit(lIdx)
        Next
    End If
    With uCtx
        Call AllocConsole
        Call ShowWindow(GetConsoleWindow(), SW_HIDE)
        Call SetConsoleCtrlHandler(0, 1)
        .hConOut = CreateFile(StrPtr("CONOUT$"), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
        .hConIn = CreateFile(StrPtr("CONIN$"), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
        Call SetConsoleWindowInfo(.hConOut, 1, uRect)
        Call SetConsoleScreenBufferSize(.hConOut, MakeCoord(LNG_CONSOLE_COLS, LNG_CONSOLE_ROWS))
        uRect.Right = LNG_CONSOLE_COLS - 1
        uRect.Bottom = LNG_CONSOLE_ROWS - 1
        Call SetConsoleWindowInfo(.hConOut, 1, uRect)
        .hMemDC = CreateCompatibleDC(0)
        Set .Font = New StdFont
        .Font.Name = "Consolas"
        .Font.Size = 11
        .hOldFont = SelectObject(.hMemDC, .Font.hFont)
        Call GetTextMetrics(.hMemDC, uMetric)
        .CellWidth = uMetric.tmAveCharWidth
        .CellHeight = uMetric.tmHeight + uMetric.tmExternalLeading
        .BmpWidth = LNG_CONSOLE_COLS * .CellWidth
        .BmpHeight = LNG_CONSOLE_ROWS * .CellHeight
        With uBmpHeader
            .biSize = LenB(uBmpHeader)
            .biPlanes = 1
            .biBitCount = 32
            .biWidth = uCtx.BmpWidth
            .biHeight = -uCtx.BmpHeight
            .biSizeImage = (4 * uCtx.BmpWidth) * uCtx.BmpHeight
        End With
        .hDib = CreateDIBSection(.hMemDC, uBmpHeader, DIB_RGB_COLORS, .lpBits, 0, 0)
        .hOldDib = SelectObject(.hMemDC, .hDib)
        Call SetBkMode(.hMemDC, OPAQUE)
        ReDim .CharInfo(0 To LNG_CONSOLE_COLS * LNG_CONSOLE_ROWS - 1)
        uStartup.cb = LenB(uStartup)
        Call CreateProcess(vbNullString, "cmd.exe", 0, 0, 0, 0, 0, vbNullString, uStartup, .ProcessInfo)
        If .ProcessInfo.hProcess <> 0 Then
            .hJob = CreateJobObject(0, 0)
            If .hJob <> 0 Then
                uLimit.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                Call SetInformationJobObject(.hJob, JobObjectExtendedLimitInformation, uLimit, LenB(uLimit))
                Call AssignProcessToJobObject(.hJob, .ProcessInfo.hProcess)
            End If
            '--- success
            pvConsoleInit = True
        End If
    End With
End Function

Private Sub pvConsoleRender(uCtx As UcsConsoleContext)
    Dim uPrevScreen     As CONSOLE_SCREEN_BUFFER_INFO
    Dim uPrevInfo()     As CHAR_INFO
    Dim uRegion         As SMALL_RECT
    Dim lRow            As Long
    Dim lCol            As Long
    Dim lIdx            As Long
    Dim lAttr           As Long
    Dim lLastFg         As Long
    Dim lLastBg         As Long
    Dim lCode           As Long
    Dim sChar           As String
    Dim lFg             As Long
    Dim lBg             As Long
    Dim uRect           As RECT
    Dim hBrush          As Long
    Dim bDirty          As Boolean
    
    With uCtx
        If .hConOut = 0 Then
            Exit Sub
        End If
        uPrevScreen = .ScreenInfo
        If GetConsoleScreenBufferInfo(.hConOut, .ScreenInfo) = 0 Then
            Exit Sub
        End If
        bDirty = uPrevScreen.dwCursorPosition.X <> .ScreenInfo.dwCursorPosition.X Or uPrevScreen.dwCursorPosition.Y <> .ScreenInfo.dwCursorPosition.Y
        uPrevInfo = .CharInfo
        uRegion.Right = LNG_CONSOLE_COLS - 1
        uRegion.Bottom = LNG_CONSOLE_ROWS - 1
        Call ReadConsoleOutput(.hConOut, .CharInfo(0), MakeCoord(LNG_CONSOLE_COLS, LNG_CONSOLE_ROWS), 0, uRegion)
        lLastFg = -1
        lLastBg = -1
        For lRow = 0 To LNG_CONSOLE_ROWS - 1
            For lCol = 0 To LNG_CONSOLE_COLS - 1
                lIdx = lRow * LNG_CONSOLE_COLS + lCol
                If uPrevInfo(lIdx).UnicodeChar <> .CharInfo(lIdx).UnicodeChar Or uPrevInfo(lIdx).Attributes <> .CharInfo(lIdx).Attributes _
                        Or bDirty And uPrevScreen.dwCursorPosition.X = lCol And uPrevScreen.dwCursorPosition.Y = lRow Then
                    lAttr = .CharInfo(lIdx).Attributes
                    lFg = m_aColors(lAttr And &HF)
                    lBg = m_aColors((lAttr \ &H10) And &HF)
                    If lFg <> lLastFg Then
                        Call SetTextColor(.hMemDC, lFg)
                        lLastFg = lFg
                    End If
                    If lBg <> lLastBg Then
                        Call SetBkColor(.hMemDC, lBg)
                        lLastBg = lBg
                    End If
                    lCode = .CharInfo(lIdx).UnicodeChar And &HFFFF&
                    If lCode = 0 Then
                        lCode = 32
                    End If
                    sChar = ChrW$(lCode)
                    Call TextOutW(.hMemDC, lCol * .CellWidth, lRow * .CellHeight, StrPtr(sChar), 1)
                    bDirty = True
                End If
            Next
        Next
        If bDirty Then
            uRect.Left = .ScreenInfo.dwCursorPosition.X * .CellWidth
            uRect.Right = uRect.Left + .CellWidth
            uRect.Bottom = (.ScreenInfo.dwCursorPosition.Y + 1) * .CellHeight
            uRect.Top = uRect.Bottom - 2
            hBrush = CreateSolidBrush(m_aColors(7))
            Call FillRect(.hMemDC, uRect, hBrush)
            Call DeleteObject(hBrush)
        End If
    End With
End Sub

Private Sub pvConsoleSendKey(ByVal hConIn As Long, ByVal lUnicodeChar As Long, ByVal lVk As Integer, ByVal Shift As Integer)
    Const SHIFT_PRESSED     As Long = &H10
    Const LEFT_CTRL_PRESSED As Long = &H8
    Const LEFT_ALT_PRESSED  As Long = &H4
    Const KEY_EVENT         As Long = 1
    Dim lScanCode       As Long
    Dim aKeys(0 To 255) As Byte
    Dim aBuf(0 To 7)    As Integer
    Dim lCount          As Long
    Dim lControlState   As Long
    Dim uRecord         As INPUT_RECORD
    Dim lWritten        As Long
    
    If hConIn = 0 Then
        Exit Sub
    End If
    If lUnicodeChar = 0 Then
        lScanCode = MapVirtualKey(lVk, 0)
        Call GetKeyboardState(aKeys(0))
        lCount = ToUnicode(lVk, lScanCode, aKeys(0), VarPtr(aBuf(0)), 8, 0)
        If lCount = 1 Then
            lUnicodeChar = aBuf(0)
        Else
            lUnicodeChar = 0
        End If
    ElseIf lUnicodeChar >= &H80 And lUnicodeChar <= &HFF Then
        lUnicodeChar = AscW(Chr$(lUnicodeChar))
    End If
    If (Shift And vbShiftMask) <> 0 Then
        lControlState = lControlState Or SHIFT_PRESSED
    End If
    If (Shift And vbCtrlMask) <> 0 Then
        lControlState = lControlState Or LEFT_CTRL_PRESSED
    End If
    If (Shift And vbAltMask) <> 0 Then
        lControlState = lControlState Or LEFT_ALT_PRESSED
    End If
    uRecord.EventType = KEY_EVENT
    With uRecord.KeyEvent
        .wRepeatCount = 1
        .wVirtualKeyCode = lVk
        .wVirtualScanCode = lScanCode And &HFFFF&
        .UnicodeChar = lUnicodeChar And &HFFFF&
        .dwControlKeyState = lControlState
        .bKeyDown = 1
    End With
    Call WriteConsoleInput(hConIn, uRecord, 1, lWritten)
    uRecord.KeyEvent.bKeyDown = 0
    Call WriteConsoleInput(hConIn, uRecord, 1, lWritten)
End Sub

Private Sub pvConsoleSendText(ByVal hConIn As Long, ByVal sText As String)
    Dim lIdx            As Long

    sText = Replace(Replace(sText, vbCrLf, vbCr), vbLf, vbCr)
    For lIdx = 1 To Len(sText)
        pvConsoleSendKey hConIn, AscW(Mid$(sText, lIdx, 1)), 0, 0
    Next
End Sub

Private Sub pvConsoleTerminate(uCtx As UcsConsoleContext)
    With uCtx
        If .ProcessInfo.hProcess <> 0 Then
            Call TerminateProcess(.ProcessInfo.hProcess, 0)
            Call CloseHandle(.ProcessInfo.hProcess)
            .ProcessInfo.hProcess = 0
        End If
        If .ProcessInfo.hThread <> 0 Then
            Call CloseHandle(.ProcessInfo.hThread)
            .ProcessInfo.hThread = 0
        End If
        If .hConOut <> 0 Then
            Call CloseHandle(.hConOut)
            .hConOut = 0
        End If
        If .hConIn <> 0 Then
            Call CloseHandle(.hConIn)
            .hConIn = 0
        End If
        If .hMemDC <> 0 Then
            Call SelectObject(.hMemDC, .hOldDib)
            Call SelectObject(.hMemDC, .hOldFont)
            Call DeleteObject(.hDib)
            .hDib = 0
            Call DeleteDC(.hMemDC)
            .hMemDC = 0
        End If
        If .hJob <> 0 Then
            Call CloseHandle(.hJob)
            .hJob = 0
        End If
'        Call FreeConsole
    End With
End Sub

Private Function MakeCoord(ByVal lX As Long, ByVal lY As Long) As Long
    MakeCoord = (lY And &HFFFF&) * &H10000 Or (lX And &HFFFF&)
End Function

Private Function SaveBitmapAsPng(ByVal hDib As Long, ByVal sFile As String) As Boolean
    Dim uStartup(0 To 3) As Long
    Dim hToken          As Long
    Dim hBitmap         As Long
    Dim uEncoder(0 To 3) As Long

    uStartup(0) = 1
    If GdiplusStartup(hToken, uStartup(0), 0) <> 0 Then
        Exit Function
    End If
    If GdipCreateBitmapFromHBITMAP(hDib, 0, hBitmap) = 0 Then
        uEncoder(0) = &H557CF406: uEncoder(1) = &H11D31A04      '--- {557CF406-1A04-11D3-9A73-0000F81EF32E}
        uEncoder(2) = &H739A&: uEncoder(3) = &H2EF31EF8
        If GdipSaveImageToFile(hBitmap, StrPtr(sFile), uEncoder(0), ByVal 0) = 0 Then
            SaveBitmapAsPng = True
        End If
        Call GdipDisposeImage(hBitmap)
    End If
    Call GdiplusShutdown(hToken)
End Function
---------
Supports paste on right mouse click (no copy yet). Saves output bitmap to *%TEMP%\aaa.png* on each frame.

Win10+ only.

cheers,
</wqw>]]></description>
			<content:encoded><![CDATA[<div><a rel="nofollow" href="https://gist.github.com/wqweto/e7601ad80c1defa6af1e1f4fb9591fa3" target="_blank" rel="nofollow">This time</a> it comes with colors. <br />
<br />
<img src="https://dl.unicontsoft.com/upload/pix/ss_host_console.png" border="0" alt="" /><br />
<br />
Place a Timer1 on Form1 and paste this code:<br />
<br />
<div class="bbcode_container">
	<div class="bbcode_description">Code:</div>
	<hr /><code class="bbcode_code">'--- Form1<br />
Option Explicit<br />
DefObj A-Z<br />
Private Const MODULE_NAME As String = &quot;Form1&quot;<br />
<br />
'=========================================================================<br />
' API<br />
'=========================================================================<br />
<br />
Private Declare Function AllocConsole Lib &quot;kernel32&quot; () As Long<br />
Private Declare Function FreeConsole Lib &quot;kernel32&quot; () As Long<br />
Private Declare Function GetConsoleWindow Lib &quot;kernel32&quot; () As Long<br />
Private Declare Function SetConsoleCtrlHandler Lib &quot;kernel32&quot; (ByVal HandlerRoutine As Long, ByVal Add As Long) As Long<br />
Private Declare Function CreateFile Lib &quot;kernel32&quot; Alias &quot;CreateFileW&quot; (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long<br />
Private Declare Function CloseHandle Lib &quot;kernel32&quot; (ByVal hObject As Long) As Long<br />
Private Declare Function GetConsoleScreenBufferInfo Lib &quot;kernel32&quot; (ByVal hConsoleOutput As Long, lpInfo As CONSOLE_SCREEN_BUFFER_INFO) As Long<br />
Private Declare Function SetConsoleScreenBufferSize Lib &quot;kernel32&quot; (ByVal hConsoleOutput As Long, ByVal dwSize As Long) As Long<br />
Private Declare Function SetConsoleWindowInfo Lib &quot;kernel32&quot; (ByVal hConsoleOutput As Long, ByVal bAbsolute As Long, lpConsoleWindow As SMALL_RECT) As Long<br />
Private Declare Function ReadConsoleOutput Lib &quot;kernel32&quot; Alias &quot;ReadConsoleOutputW&quot; (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal dwBufferSize As Long, ByVal dwBufferCoord As Long, lpReadRegion As SMALL_RECT) As Long<br />
Private Declare Function WriteConsoleInput Lib &quot;kernel32&quot; Alias &quot;WriteConsoleInputW&quot; (ByVal hConsoleInput As Long, lpBuffer As INPUT_RECORD, ByVal nLength As Long, lpNumberOfEventsWritten As Long) As Long<br />
Private Declare Function CreateProcess Lib &quot;kernel32&quot; Alias &quot;CreateProcessA&quot; (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long<br />
Private Declare Function TerminateProcess Lib &quot;kernel32&quot; (ByVal hProcess As Long, ByVal uExitCode As Long) As Long<br />
Private Declare Function WaitForSingleObject Lib &quot;kernel32&quot; (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long<br />
Private Declare Function CreateJobObject Lib &quot;kernel32&quot; Alias &quot;CreateJobObjectW&quot; (ByVal lpJobAttributes As Long, ByVal lpName As Long) As Long<br />
Private Declare Function SetInformationJobObject Lib &quot;kernel32&quot; (ByVal hJob As Long, ByVal JobObjectInformationClass As Long, lpJobObjectInformation As Any, ByVal cbJobObjectInformationLength As Long) As Long<br />
Private Declare Function AssignProcessToJobObject Lib &quot;kernel32&quot; (ByVal hJob As Long, ByVal hProcess As Long) As Long<br />
Private Declare Function CreateCompatibleDC Lib &quot;gdi32&quot; (ByVal hDC As Long) As Long<br />
Private Declare Function SelectObject Lib &quot;gdi32&quot; (ByVal hDC As Long, ByVal hObject As Long) As Long<br />
Private Declare Function DeleteObject Lib &quot;gdi32&quot; (ByVal hObject As Long) As Long<br />
Private Declare Function DeleteDC Lib &quot;gdi32&quot; (ByVal hDC As Long) As Long<br />
Private Declare Function BitBlt Lib &quot;gdi32&quot; (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nW As Long, ByVal nH As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long<br />
Private Declare Function SetTextColor Lib &quot;gdi32&quot; (ByVal hDC As Long, ByVal crColor As Long) As Long<br />
Private Declare Function SetBkColor Lib &quot;gdi32&quot; (ByVal hDC As Long, ByVal crColor As Long) As Long<br />
Private Declare Function SetBkMode Lib &quot;gdi32&quot; (ByVal hDC As Long, ByVal nBkMode As Long) As Long<br />
Private Declare Function TextOutW Lib &quot;gdi32&quot; (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal lpString As Long, ByVal nCount As Long) As Long<br />
Private Declare Function GetTextMetrics Lib &quot;gdi32&quot; Alias &quot;GetTextMetricsA&quot; (ByVal hDC As Long, lpMetrics As TEXTMETRIC) As Long<br />
Private Declare Function CreateSolidBrush Lib &quot;gdi32&quot; (ByVal crColor As Long) As Long<br />
Private Declare Function CreateDIBSection Lib &quot;gdi32&quot; (ByVal hDC As Long, lpBitsInfo As Any, ByVal wUsage As Long, lpBits As Long, ByVal Handle As Long, ByVal dw As Long) As Long<br />
Private Declare Function ShowWindow Lib &quot;user32&quot; (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long<br />
Private Declare Function FillRect Lib &quot;user32&quot; (ByVal hDC As Long, lpRect As RECT, ByVal hBrush As Long) As Long<br />
Private Declare Function MapVirtualKey Lib &quot;user32&quot; Alias &quot;MapVirtualKeyA&quot; (ByVal uCode As Long, ByVal uMapType As Long) As Long<br />
Private Declare Function GetKeyboardState Lib &quot;user32&quot; (pbKeyState As Byte) As Long<br />
Private Declare Function ToUnicode Lib &quot;user32&quot; (ByVal wVirtKey As Long, ByVal wScanCode As Long, lpKeyState As Byte, ByVal pwszBuff As Long, ByVal cchBuff As Long, ByVal wFlags As Long) As Long<br />
'--- GDI+<br />
Private Declare Function GdiplusStartup Lib &quot;gdiplus&quot; (token As Long, inputbuf As Any, ByVal outputbuf As Long) As Long<br />
Private Declare Function GdiplusShutdown Lib &quot;gdiplus&quot; (ByVal token As Long) As Long<br />
Private Declare Function GdipCreateBitmapFromHBITMAP Lib &quot;gdiplus&quot; (ByVal hBitmap As Long, ByVal hPalette As Long, hGdipBmp As Long) As Long<br />
Private Declare Function GdipDisposeImage Lib &quot;gdiplus&quot; (ByVal image As Long) As Long<br />
Private Declare Function GdipSaveImageToFile Lib &quot;gdiplus&quot; (ByVal image As Long, ByVal fileName As Long, clsidEncoder As Any, encoderParams As Any) As Long<br />
<br />
Private Type COORD<br />
&nbsp; &nbsp; X&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; Y&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
End Type<br />
<br />
Private Type SMALL_RECT<br />
&nbsp; &nbsp; Left&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Integer<br />
&nbsp; &nbsp; Top&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; Right&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; Bottom&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Integer<br />
End Type<br />
<br />
Private Type RECT<br />
&nbsp; &nbsp; Left&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Top&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Right&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Bottom&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
End Type<br />
<br />
Private Type CONSOLE_SCREEN_BUFFER_INFO<br />
&nbsp; &nbsp; dwSize&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As COORD<br />
&nbsp; &nbsp; dwCursorPosition&nbsp; &nbsp; As COORD<br />
&nbsp; &nbsp; wAttributes&nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; srWindow&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As SMALL_RECT<br />
&nbsp; &nbsp; dwMaximumWindowSize As COORD<br />
End Type<br />
<br />
Private Type CHAR_INFO<br />
&nbsp; &nbsp; UnicodeChar&nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; Attributes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Integer<br />
End Type<br />
<br />
Private Type KEY_EVENT_RECORD<br />
&nbsp; &nbsp; bKeyDown&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; wRepeatCount&nbsp; &nbsp; &nbsp; &nbsp; As Integer<br />
&nbsp; &nbsp; wVirtualKeyCode&nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; wVirtualScanCode&nbsp; &nbsp; As Integer<br />
&nbsp; &nbsp; UnicodeChar&nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; dwControlKeyState&nbsp;  As Long<br />
End Type<br />
<br />
Private Type INPUT_RECORD<br />
&nbsp; &nbsp; EventType&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; Padding&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; KeyEvent&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As KEY_EVENT_RECORD<br />
End Type<br />
<br />
Private Type STARTUPINFO<br />
&nbsp; &nbsp; cb&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; lpReserved&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; lpDesktop&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; lpTitle&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwX&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwXSize&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwYSize&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwXCountChars&nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwYCountChars&nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwFillAttribute&nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwFlags&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; wShowWindow&nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; cbReserved2&nbsp; &nbsp; &nbsp; &nbsp;  As Integer<br />
&nbsp; &nbsp; lpReserved2&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; hStdInput&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; hStdOutput&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; hStdError&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
End Type<br />
<br />
Private Type PROCESS_INFORMATION<br />
&nbsp; &nbsp; hProcess&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; hThread&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwProcessId&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwThreadId&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
End Type<br />
<br />
Private Type TEXTMETRIC<br />
&nbsp; &nbsp; tmHeight&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; tmAscent&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; tmDescent&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; tmInternalLeading&nbsp;  As Long<br />
&nbsp; &nbsp; tmExternalLeading&nbsp;  As Long<br />
&nbsp; &nbsp; tmAveCharWidth&nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; tmMaxCharWidth&nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; tmWeight&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; tmOverhang&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; tmDigitizedAspectX&nbsp; As Long<br />
&nbsp; &nbsp; tmDigitizedAspectY&nbsp; As Long<br />
&nbsp; &nbsp; tmFirstChar&nbsp; &nbsp; &nbsp; &nbsp;  As Byte<br />
&nbsp; &nbsp; tmLastChar&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Byte<br />
&nbsp; &nbsp; tmDefaultChar&nbsp; &nbsp; &nbsp;  As Byte<br />
&nbsp; &nbsp; tmBreakChar&nbsp; &nbsp; &nbsp; &nbsp;  As Byte<br />
&nbsp; &nbsp; tmItalic&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Byte<br />
&nbsp; &nbsp; tmUnderlined&nbsp; &nbsp; &nbsp; &nbsp; As Byte<br />
&nbsp; &nbsp; tmStruckOut&nbsp; &nbsp; &nbsp; &nbsp;  As Byte<br />
&nbsp; &nbsp; tmPitchAndFamily&nbsp; &nbsp; As Byte<br />
&nbsp; &nbsp; tmCharSet&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Byte<br />
End Type<br />
<br />
Private Type BITMAPINFOHEADER<br />
&nbsp; &nbsp; biSize&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; biWidth&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; biHeight&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; biPlanes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Integer<br />
&nbsp; &nbsp; biBitCount&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Integer<br />
&nbsp; &nbsp; biCompression&nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; biSizeImage&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; biXPelsPerMeter&nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; biYPelsPerMeter&nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; biClrUsed&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; biClrImportant&nbsp; &nbsp; &nbsp; As Long<br />
End Type<br />
<br />
Private Type JOBOBJECT_EXTENDED_LIMIT_INFORMATION<br />
&nbsp; &nbsp; '--- BasicLimitInformation<br />
&nbsp; &nbsp; PerProcessUserTimeLimit As Currency<br />
&nbsp; &nbsp; PerJobUserTimeLimit&nbsp; &nbsp;  As Currency<br />
&nbsp; &nbsp; LimitFlags&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; MinimumWorkingSetSize&nbsp;  As Long<br />
&nbsp; &nbsp; MaximumWorkingSetSize&nbsp;  As Long<br />
&nbsp; &nbsp; ActiveProcessLimit&nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Affinity&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; PriorityClass&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; SchedulingClass&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; dwPadding1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; '--- IoInfo<br />
&nbsp; &nbsp; ReadOperationCount&nbsp; &nbsp; &nbsp; As Currency<br />
&nbsp; &nbsp; WriteOperationCount&nbsp; &nbsp;  As Currency<br />
&nbsp; &nbsp; OtherOperationCount&nbsp; &nbsp;  As Currency<br />
&nbsp; &nbsp; ReadTransferCount&nbsp; &nbsp; &nbsp;  As Currency<br />
&nbsp; &nbsp; WriteTransferCount&nbsp; &nbsp; &nbsp; As Currency<br />
&nbsp; &nbsp; OtherTransferCount&nbsp; &nbsp; &nbsp; As Currency<br />
&nbsp; &nbsp; '--- rest<br />
&nbsp; &nbsp; ProcessMemoryLimit&nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; JobMemoryLimit&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; PeakProcessMemoryUsed&nbsp;  As Long<br />
&nbsp; &nbsp; PeakJobMemoryUsed&nbsp; &nbsp; &nbsp;  As Long<br />
End Type<br />
<br />
'=========================================================================<br />
' Constants and member vars<br />
'=========================================================================<br />
<br />
Private Const LNG_CONSOLE_COLS&nbsp; &nbsp; &nbsp; As Long = 120<br />
Private Const LNG_CONSOLE_ROWS&nbsp; &nbsp; &nbsp; As Long = 30<br />
<br />
Private m_uCtx&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As UcsConsoleContext<br />
Private m_aColors(0 To 15)&nbsp; &nbsp; &nbsp; As Long<br />
<br />
Private Type UcsConsoleContext<br />
&nbsp; &nbsp; hConOut&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; hConIn&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; hMemDC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; hDib&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; lpBits&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; hOldDib&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Font&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As IFont<br />
&nbsp; &nbsp; hOldFont&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; CellWidth&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; CellHeight&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; BmpWidth&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; BmpHeight&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; ProcessInfo&nbsp; &nbsp; &nbsp; &nbsp;  As PROCESS_INFORMATION<br />
&nbsp; &nbsp; hJob&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; CharInfo()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As CHAR_INFO<br />
&nbsp; &nbsp; ScreenInfo&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As CONSOLE_SCREEN_BUFFER_INFO<br />
End Type<br />
<br />
Private Sub PrintError(sFunction As String)<br />
&nbsp; &nbsp; #If ImplUseDebugLog Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; DebugLog MODULE_NAME, sFunction &amp; &quot;(&quot; &amp; Erl &amp; &quot;)&quot;, Err.Description &amp; &quot; &amp;H&quot; &amp; Hex$(Err.Number), vbLogEventTypeError<br />
&nbsp; &nbsp; #Else<br />
&nbsp; &nbsp; &nbsp; &nbsp; Debug.Print &quot;Critical error: &quot; &amp; Err.Description &amp; &quot; [&quot; &amp; MODULE_NAME &amp; &quot;.&quot; &amp; sFunction &amp; &quot;]&quot;<br />
&nbsp; &nbsp; #End If<br />
End Sub<br />
<br />
Private Sub Form_Load()<br />
&nbsp; &nbsp; On Error GoTo EH<br />
&nbsp; &nbsp; Me.ScaleMode = vbPixels<br />
&nbsp; &nbsp; Me.KeyPreview = True<br />
&nbsp; &nbsp; Me.BackColor = vbBlack<br />
&nbsp; &nbsp; pvConsoleInit m_uCtx<br />
&nbsp; &nbsp; Me.Width = Me.Width - Me.ScaleWidth * Screen.TwipsPerPixelX + m_uCtx.BmpWidth * Screen.TwipsPerPixelX<br />
&nbsp; &nbsp; Me.Height = Me.Height - Me.ScaleHeight * Screen.TwipsPerPixelY + m_uCtx.BmpHeight * Screen.TwipsPerPixelY<br />
&nbsp; &nbsp; Timer1.Interval = 30<br />
&nbsp; &nbsp; Timer1.Enabled = True<br />
&nbsp; &nbsp; Exit Sub<br />
EH:<br />
&nbsp; &nbsp; PrintError &quot;Form_Load&quot;<br />
End Sub<br />
<br />
Private Sub Timer1_Timer()<br />
&nbsp; &nbsp; On Error GoTo EH<br />
&nbsp; &nbsp; pvConsoleRender m_uCtx<br />
&nbsp; &nbsp; Form_Paint<br />
&nbsp; &nbsp; If m_uCtx.ProcessInfo.hProcess &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; If WaitForSingleObject(m_uCtx.ProcessInfo.hProcess, 0) = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Unload Me<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; Exit Sub<br />
EH:<br />
&nbsp; &nbsp; PrintError &quot;Timer1_Timer&quot;<br />
End Sub<br />
<br />
Private Sub Form_Paint()<br />
&nbsp; &nbsp; Const SRCCOPY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long = &amp;HCC0020<br />
<br />
&nbsp; &nbsp; On Error GoTo EH<br />
&nbsp; &nbsp; Call BitBlt(Me.hDC, 0, 0, m_uCtx.BmpWidth, m_uCtx.BmpHeight, m_uCtx.hMemDC, 0, 0, SRCCOPY)<br />
&nbsp; &nbsp; SaveBitmapAsPng m_uCtx.hDib, Environ$(&quot;TEMP&quot;) &amp; &quot;\aaa.png&quot;<br />
&nbsp; &nbsp; Exit Sub<br />
EH:<br />
&nbsp; &nbsp; PrintError &quot;Form_Paint&quot;<br />
End Sub<br />
<br />
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)<br />
&nbsp; &nbsp; On Error GoTo EH<br />
&nbsp; &nbsp; Select Case KeyCode + Shift * &amp;H10000<br />
&nbsp; &nbsp; Case vbKeyF4 + vbAltMask * &amp;H10000<br />
&nbsp; &nbsp; &nbsp; &nbsp; Exit Sub<br />
&nbsp; &nbsp; Case vbKeyV + vbCtrlMask * &amp;H10000, vbKeyInsert + vbShiftMask * &amp;H10000<br />
&nbsp; &nbsp; &nbsp; &nbsp; If Clipboard.GetFormat(vbCFText) Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pvConsoleSendText m_uCtx.hConIn, Clipboard.GetText()<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; Case Else<br />
&nbsp; &nbsp; &nbsp; &nbsp; pvConsoleSendKey m_uCtx.hConIn, 0, KeyCode, Shift<br />
&nbsp; &nbsp; End Select<br />
&nbsp; &nbsp; KeyCode = 0<br />
&nbsp; &nbsp; Exit Sub<br />
EH:<br />
&nbsp; &nbsp; PrintError &quot;Form_KeyDown&quot;<br />
End Sub<br />
<br />
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)<br />
&nbsp; &nbsp; On Error GoTo EH<br />
&nbsp; &nbsp; If Button = vbRightButton Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; Form_KeyDown vbKeyV, vbCtrlMask<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; Exit Sub<br />
EH:<br />
&nbsp; &nbsp; PrintError &quot;Form_MouseDown&quot;<br />
End Sub<br />
<br />
Private Sub Form_Unload(Cancel As Integer)<br />
&nbsp; &nbsp; On Error GoTo EH<br />
&nbsp; &nbsp; Timer1.Enabled = False<br />
&nbsp; &nbsp; pvConsoleTerminate m_uCtx<br />
&nbsp; &nbsp; Exit Sub<br />
EH:<br />
&nbsp; &nbsp; PrintError &quot;Form_Unload&quot;<br />
End Sub<br />
<br />
'= private ===============================================================<br />
<br />
Private Function pvConsoleInit(uCtx As UcsConsoleContext) As Boolean<br />
&nbsp; &nbsp; Const SW_HIDE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long = 0<br />
&nbsp; &nbsp; Const GENERIC_READ&nbsp; &nbsp; &nbsp; As Long = &amp;H80000000<br />
&nbsp; &nbsp; Const GENERIC_WRITE&nbsp; &nbsp;  As Long = &amp;H40000000<br />
&nbsp; &nbsp; Const FILE_SHARE_READ&nbsp;  As Long = 1<br />
&nbsp; &nbsp; Const FILE_SHARE_WRITE&nbsp; As Long = 2<br />
&nbsp; &nbsp; Const OPEN_EXISTING&nbsp; &nbsp;  As Long = 3<br />
&nbsp; &nbsp; Const OPAQUE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long = 2<br />
&nbsp; &nbsp; Const DIB_RGB_COLORS&nbsp; &nbsp; As Long = 0<br />
&nbsp; &nbsp; Const JobObjectExtendedLimitInformation As Long = 9<br />
&nbsp; &nbsp; Const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE As Long = &amp;H2000<br />
&nbsp; &nbsp; Dim vSplit&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Variant<br />
&nbsp; &nbsp; Dim lIdx&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim uMetric&nbsp; &nbsp; &nbsp; &nbsp;  As TEXTMETRIC<br />
&nbsp; &nbsp; Dim uRect&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As SMALL_RECT<br />
&nbsp; &nbsp; Dim uBmpHeader&nbsp; &nbsp; &nbsp; As BITMAPINFOHEADER<br />
&nbsp; &nbsp; Dim uStartup&nbsp; &nbsp; &nbsp; &nbsp; As STARTUPINFO<br />
&nbsp; &nbsp; Dim uLimit&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As JOBOBJECT_EXTENDED_LIMIT_INFORMATION<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; If m_aColors(15) = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; vSplit = Split(&quot;&amp;H0 &amp;H800000 &amp;H8000 &amp;H808000 &amp;H80 &amp;H800080 &amp;H8080 &amp;HC0C0C0 &amp;H808080 &amp;HFF0000 &amp;HFF00 &amp;HFFFF00 &amp;HFF &amp;HFF00FF &amp;HFFFF &amp;HFFFFFF&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; For lIdx = 0 To 15<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m_aColors(lIdx) = vSplit(lIdx)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Next<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; With uCtx<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call AllocConsole<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call ShowWindow(GetConsoleWindow(), SW_HIDE)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call SetConsoleCtrlHandler(0, 1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; .hConOut = CreateFile(StrPtr(&quot;CONOUT$&quot;), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; .hConIn = CreateFile(StrPtr(&quot;CONIN$&quot;), GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call SetConsoleWindowInfo(.hConOut, 1, uRect)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call SetConsoleScreenBufferSize(.hConOut, MakeCoord(LNG_CONSOLE_COLS, LNG_CONSOLE_ROWS))<br />
&nbsp; &nbsp; &nbsp; &nbsp; uRect.Right = LNG_CONSOLE_COLS - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; uRect.Bottom = LNG_CONSOLE_ROWS - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call SetConsoleWindowInfo(.hConOut, 1, uRect)<br />
&nbsp; &nbsp; &nbsp; &nbsp; .hMemDC = CreateCompatibleDC(0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Set .Font = New StdFont<br />
&nbsp; &nbsp; &nbsp; &nbsp; .Font.Name = &quot;Consolas&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; .Font.Size = 11<br />
&nbsp; &nbsp; &nbsp; &nbsp; .hOldFont = SelectObject(.hMemDC, .Font.hFont)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call GetTextMetrics(.hMemDC, uMetric)<br />
&nbsp; &nbsp; &nbsp; &nbsp; .CellWidth = uMetric.tmAveCharWidth<br />
&nbsp; &nbsp; &nbsp; &nbsp; .CellHeight = uMetric.tmHeight + uMetric.tmExternalLeading<br />
&nbsp; &nbsp; &nbsp; &nbsp; .BmpWidth = LNG_CONSOLE_COLS * .CellWidth<br />
&nbsp; &nbsp; &nbsp; &nbsp; .BmpHeight = LNG_CONSOLE_ROWS * .CellHeight<br />
&nbsp; &nbsp; &nbsp; &nbsp; With uBmpHeader<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .biSize = LenB(uBmpHeader)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .biPlanes = 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .biBitCount = 32<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .biWidth = uCtx.BmpWidth<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .biHeight = -uCtx.BmpHeight<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .biSizeImage = (4 * uCtx.BmpWidth) * uCtx.BmpHeight<br />
&nbsp; &nbsp; &nbsp; &nbsp; End With<br />
&nbsp; &nbsp; &nbsp; &nbsp; .hDib = CreateDIBSection(.hMemDC, uBmpHeader, DIB_RGB_COLORS, .lpBits, 0, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; .hOldDib = SelectObject(.hMemDC, .hDib)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call SetBkMode(.hMemDC, OPAQUE)<br />
&nbsp; &nbsp; &nbsp; &nbsp; ReDim .CharInfo(0 To LNG_CONSOLE_COLS * LNG_CONSOLE_ROWS - 1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; uStartup.cb = LenB(uStartup)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call CreateProcess(vbNullString, &quot;cmd.exe&quot;, 0, 0, 0, 0, 0, vbNullString, uStartup, .ProcessInfo)<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .ProcessInfo.hProcess &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .hJob = CreateJobObject(0, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If .hJob &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uLimit.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call SetInformationJobObject(.hJob, JobObjectExtendedLimitInformation, uLimit, LenB(uLimit))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call AssignProcessToJobObject(.hJob, .ProcessInfo.hProcess)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '--- success<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pvConsoleInit = True<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; End With<br />
End Function<br />
<br />
Private Sub pvConsoleRender(uCtx As UcsConsoleContext)<br />
&nbsp; &nbsp; Dim uPrevScreen&nbsp; &nbsp;  As CONSOLE_SCREEN_BUFFER_INFO<br />
&nbsp; &nbsp; Dim uPrevInfo()&nbsp; &nbsp;  As CHAR_INFO<br />
&nbsp; &nbsp; Dim uRegion&nbsp; &nbsp; &nbsp; &nbsp;  As SMALL_RECT<br />
&nbsp; &nbsp; Dim lRow&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim lCol&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim lIdx&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim lAttr&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim lLastFg&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim lLastBg&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim lCode&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim sChar&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As String<br />
&nbsp; &nbsp; Dim lFg&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim lBg&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim uRect&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  As RECT<br />
&nbsp; &nbsp; Dim hBrush&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim bDirty&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Boolean<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; With uCtx<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .hConOut = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exit Sub<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; uPrevScreen = .ScreenInfo<br />
&nbsp; &nbsp; &nbsp; &nbsp; If GetConsoleScreenBufferInfo(.hConOut, .ScreenInfo) = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exit Sub<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; bDirty = uPrevScreen.dwCursorPosition.X &lt;&gt; .ScreenInfo.dwCursorPosition.X Or uPrevScreen.dwCursorPosition.Y &lt;&gt; .ScreenInfo.dwCursorPosition.Y<br />
&nbsp; &nbsp; &nbsp; &nbsp; uPrevInfo = .CharInfo<br />
&nbsp; &nbsp; &nbsp; &nbsp; uRegion.Right = LNG_CONSOLE_COLS - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; uRegion.Bottom = LNG_CONSOLE_ROWS - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call ReadConsoleOutput(.hConOut, .CharInfo(0), MakeCoord(LNG_CONSOLE_COLS, LNG_CONSOLE_ROWS), 0, uRegion)<br />
&nbsp; &nbsp; &nbsp; &nbsp; lLastFg = -1<br />
&nbsp; &nbsp; &nbsp; &nbsp; lLastBg = -1<br />
&nbsp; &nbsp; &nbsp; &nbsp; For lRow = 0 To LNG_CONSOLE_ROWS - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; For lCol = 0 To LNG_CONSOLE_COLS - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lIdx = lRow * LNG_CONSOLE_COLS + lCol<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If uPrevInfo(lIdx).UnicodeChar &lt;&gt; .CharInfo(lIdx).UnicodeChar Or uPrevInfo(lIdx).Attributes &lt;&gt; .CharInfo(lIdx).Attributes _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Or bDirty And uPrevScreen.dwCursorPosition.X = lCol And uPrevScreen.dwCursorPosition.Y = lRow Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lAttr = .CharInfo(lIdx).Attributes<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lFg = m_aColors(lAttr And &amp;HF)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lBg = m_aColors((lAttr \ &amp;H10) And &amp;HF)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If lFg &lt;&gt; lLastFg Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call SetTextColor(.hMemDC, lFg)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lLastFg = lFg<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If lBg &lt;&gt; lLastBg Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call SetBkColor(.hMemDC, lBg)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lLastBg = lBg<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lCode = .CharInfo(lIdx).UnicodeChar And &amp;HFFFF&amp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If lCode = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lCode = 32<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sChar = ChrW$(lCode)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call TextOutW(.hMemDC, lCol * .CellWidth, lRow * .CellHeight, StrPtr(sChar), 1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bDirty = True<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Next<br />
&nbsp; &nbsp; &nbsp; &nbsp; Next<br />
&nbsp; &nbsp; &nbsp; &nbsp; If bDirty Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uRect.Left = .ScreenInfo.dwCursorPosition.X * .CellWidth<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uRect.Right = uRect.Left + .CellWidth<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uRect.Bottom = (.ScreenInfo.dwCursorPosition.Y + 1) * .CellHeight<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uRect.Top = uRect.Bottom - 2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hBrush = CreateSolidBrush(m_aColors(7))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call FillRect(.hMemDC, uRect, hBrush)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call DeleteObject(hBrush)<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; End With<br />
End Sub<br />
<br />
Private Sub pvConsoleSendKey(ByVal hConIn As Long, ByVal lUnicodeChar As Long, ByVal lVk As Integer, ByVal Shift As Integer)<br />
&nbsp; &nbsp; Const SHIFT_PRESSED&nbsp; &nbsp;  As Long = &amp;H10<br />
&nbsp; &nbsp; Const LEFT_CTRL_PRESSED As Long = &amp;H8<br />
&nbsp; &nbsp; Const LEFT_ALT_PRESSED&nbsp; As Long = &amp;H4<br />
&nbsp; &nbsp; Const KEY_EVENT&nbsp; &nbsp; &nbsp; &nbsp;  As Long = 1<br />
&nbsp; &nbsp; Dim lScanCode&nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim aKeys(0 To 255) As Byte<br />
&nbsp; &nbsp; Dim aBuf(0 To 7)&nbsp; &nbsp; As Integer<br />
&nbsp; &nbsp; Dim lCount&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim lControlState&nbsp;  As Long<br />
&nbsp; &nbsp; Dim uRecord&nbsp; &nbsp; &nbsp; &nbsp;  As INPUT_RECORD<br />
&nbsp; &nbsp; Dim lWritten&nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; If hConIn = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; Exit Sub<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; If lUnicodeChar = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; lScanCode = MapVirtualKey(lVk, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call GetKeyboardState(aKeys(0))<br />
&nbsp; &nbsp; &nbsp; &nbsp; lCount = ToUnicode(lVk, lScanCode, aKeys(0), VarPtr(aBuf(0)), 8, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; If lCount = 1 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lUnicodeChar = aBuf(0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; Else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lUnicodeChar = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; ElseIf lUnicodeChar &gt;= &amp;H80 And lUnicodeChar &lt;= &amp;HFF Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; lUnicodeChar = AscW(Chr$(lUnicodeChar))<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; If (Shift And vbShiftMask) &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; lControlState = lControlState Or SHIFT_PRESSED<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; If (Shift And vbCtrlMask) &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; lControlState = lControlState Or LEFT_CTRL_PRESSED<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; If (Shift And vbAltMask) &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; lControlState = lControlState Or LEFT_ALT_PRESSED<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; uRecord.EventType = KEY_EVENT<br />
&nbsp; &nbsp; With uRecord.KeyEvent<br />
&nbsp; &nbsp; &nbsp; &nbsp; .wRepeatCount = 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; .wVirtualKeyCode = lVk<br />
&nbsp; &nbsp; &nbsp; &nbsp; .wVirtualScanCode = lScanCode And &amp;HFFFF&amp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; .UnicodeChar = lUnicodeChar And &amp;HFFFF&amp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; .dwControlKeyState = lControlState<br />
&nbsp; &nbsp; &nbsp; &nbsp; .bKeyDown = 1<br />
&nbsp; &nbsp; End With<br />
&nbsp; &nbsp; Call WriteConsoleInput(hConIn, uRecord, 1, lWritten)<br />
&nbsp; &nbsp; uRecord.KeyEvent.bKeyDown = 0<br />
&nbsp; &nbsp; Call WriteConsoleInput(hConIn, uRecord, 1, lWritten)<br />
End Sub<br />
<br />
Private Sub pvConsoleSendText(ByVal hConIn As Long, ByVal sText As String)<br />
&nbsp; &nbsp; Dim lIdx&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
<br />
&nbsp; &nbsp; sText = Replace(Replace(sText, vbCrLf, vbCr), vbLf, vbCr)<br />
&nbsp; &nbsp; For lIdx = 1 To Len(sText)<br />
&nbsp; &nbsp; &nbsp; &nbsp; pvConsoleSendKey hConIn, AscW(Mid$(sText, lIdx, 1)), 0, 0<br />
&nbsp; &nbsp; Next<br />
End Sub<br />
<br />
Private Sub pvConsoleTerminate(uCtx As UcsConsoleContext)<br />
&nbsp; &nbsp; With uCtx<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .ProcessInfo.hProcess &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call TerminateProcess(.ProcessInfo.hProcess, 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call CloseHandle(.ProcessInfo.hProcess)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .ProcessInfo.hProcess = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .ProcessInfo.hThread &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call CloseHandle(.ProcessInfo.hThread)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .ProcessInfo.hThread = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .hConOut &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call CloseHandle(.hConOut)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .hConOut = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .hConIn &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call CloseHandle(.hConIn)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .hConIn = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .hMemDC &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call SelectObject(.hMemDC, .hOldDib)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call SelectObject(.hMemDC, .hOldFont)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call DeleteObject(.hDib)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .hDib = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call DeleteDC(.hMemDC)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .hMemDC = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; If .hJob &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Call CloseHandle(.hJob)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .hJob = 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
'&nbsp; &nbsp; &nbsp; &nbsp; Call FreeConsole<br />
&nbsp; &nbsp; End With<br />
End Sub<br />
<br />
Private Function MakeCoord(ByVal lX As Long, ByVal lY As Long) As Long<br />
&nbsp; &nbsp; MakeCoord = (lY And &amp;HFFFF&amp;) * &amp;H10000 Or (lX And &amp;HFFFF&amp;)<br />
End Function<br />
<br />
Private Function SaveBitmapAsPng(ByVal hDib As Long, ByVal sFile As String) As Boolean<br />
&nbsp; &nbsp; Dim uStartup(0 To 3) As Long<br />
&nbsp; &nbsp; Dim hToken&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long<br />
&nbsp; &nbsp; Dim hBitmap&nbsp; &nbsp; &nbsp; &nbsp;  As Long<br />
&nbsp; &nbsp; Dim uEncoder(0 To 3) As Long<br />
<br />
&nbsp; &nbsp; uStartup(0) = 1<br />
&nbsp; &nbsp; If GdiplusStartup(hToken, uStartup(0), 0) &lt;&gt; 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; Exit Function<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; If GdipCreateBitmapFromHBITMAP(hDib, 0, hBitmap) = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; uEncoder(0) = &amp;H557CF406: uEncoder(1) = &amp;H11D31A04&nbsp; &nbsp; &nbsp; '--- {557CF406-1A04-11D3-9A73-0000F81EF32E}<br />
&nbsp; &nbsp; &nbsp; &nbsp; uEncoder(2) = &amp;H739A&amp;: uEncoder(3) = &amp;H2EF31EF8<br />
&nbsp; &nbsp; &nbsp; &nbsp; If GdipSaveImageToFile(hBitmap, StrPtr(sFile), uEncoder(0), ByVal 0) = 0 Then<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SaveBitmapAsPng = True<br />
&nbsp; &nbsp; &nbsp; &nbsp; End If<br />
&nbsp; &nbsp; &nbsp; &nbsp; Call GdipDisposeImage(hBitmap)<br />
&nbsp; &nbsp; End If<br />
&nbsp; &nbsp; Call GdiplusShutdown(hToken)<br />
End Function</code><hr />
</div>Supports paste on right mouse click (no copy yet). Saves output bitmap to <b>%TEMP%\aaa.png</b> on each frame.<br />
<br />
Win10+ only.<br />
<br />
cheers,<br />
&lt;/wqw&gt;</div>

]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>wqweto</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912051-Hosting-console-in-VB6-form</guid>
		</item>
		<item>
			<title><![CDATA[[VB6, VBA, twinBASIC] Intro to Vectored Exception Handling: Crash-proof CopyMemory]]></title>
			<link>https://www.vbforums.com/showthread.php?912039-VB6-VBA-twinBASIC-Intro-to-Vectored-Exception-Handling-Crash-proof-CopyMemory&amp;goto=newpost</link>
			<pubDate>Sat, 23 May 2026 08:11:55 GMT</pubDate>
			<description><![CDATA[Attachment 196124 (https://www.vbforums.com/attachment.php?attachmentid=196124)

It's been a long standing problem that access violations like a bad address for CopyMemory and other exceptions can't be handled by On Error. One solution to that is Vectored Exception Handling (VEH). You can register a procedure to handle true exceptions like access violations, then set it to skip the offending instruction.

This is a small module to introduce the concept that allows you to call CopyMemory safely, your app will not crash even if you supply an invalid address. If an invalid address is provided, the operation is skipped and it returns False.

This works by modifying the CONTEXT structure, which contains among other things the contents of all registers (where things like arguments and return values are actually stored at the assembly code/hardware level), including the instruction pointer register that tells the system exactly what instruction is executing- Eip for 32bit, Rip for 64bit. If an access violation is encountered, we skip the instruction by adding the instruction size-- this is where it gets the most complicated, and to be honest I used Claude AI for the functions to calculate the length, and don't totally understand it, since it's dynamic at runtime and not just looking at the disassembly on disk.

Requirements: This is a standalone module with no dependencies.
The definitions were copied from Windows Development Library for twinBASIC, so if you use that package, you can remove all the declares/types/enums/consts.

Usage Just add modSafeCopy.bas to your project and use CopyMemorySafe in place of CopyMemory. Note you'll have to use VarPtr/StrPtr/ObjPtr since neither VB6 nor tB supports As Any in local functions. You can also use CopyMemorySafe as a function, if the copy is successful without being passed a null pointer and without an exception it returns True.

NOTE: In twinBASIC this currently only works in compiled exes.

Important: For VBA, the document must be saved in a Trusted Location

*Download on GitHub (https://github.com/fafalone/CopyMemorySafe)*]]></description>
			<content:encoded><![CDATA[<div><div style="text-align: center;"><img src="https://www.vbforums.com/attachment.php?attachmentid=196124&amp;d=1779574167" border="0" alt="Name:  copymemsafe.jpg
Views: 85
Size:  27.1 KB"  /></div><br />
It's been a long standing problem that access violations like a bad address for CopyMemory and other exceptions can't be handled by On Error. One solution to that is Vectored Exception Handling (VEH). You can register a procedure to handle true exceptions like access violations, then set it to skip the offending instruction.<br />
<br />
This is a small module to introduce the concept that allows you to call CopyMemory safely, your app will not crash even if you supply an invalid address. If an invalid address is provided, the operation is skipped and it returns False.<br />
<br />
This works by modifying the CONTEXT structure, which contains among other things the contents of all registers (where things like arguments and return values are actually stored at the assembly code/hardware level), including the instruction pointer register that tells the system exactly what instruction is executing- Eip for 32bit, Rip for 64bit. If an access violation is encountered, we skip the instruction by adding the instruction size-- this is where it gets the most complicated, and to be honest I used Claude AI for the functions to calculate the length, and don't totally understand it, since it's dynamic at runtime and not just looking at the disassembly on disk.<br />
<br />
Requirements: This is a standalone module with no dependencies.<br />
The definitions were copied from Windows Development Library for twinBASIC, so if you use that package, you can remove all the declares/types/enums/consts.<br />
<br />
Usage Just add modSafeCopy.bas to your project and use CopyMemorySafe in place of CopyMemory. Note you'll have to use VarPtr/StrPtr/ObjPtr since neither VB6 nor tB supports As Any in local functions. You can also use CopyMemorySafe as a function, if the copy is successful without being passed a null pointer and without an exception it returns True.<br />
<br />
NOTE: In twinBASIC this currently only works in compiled exes.<br />
<br />
Important: For VBA, the document must be saved in a Trusted Location<br />
<br />
<b><a rel="nofollow" href="https://github.com/fafalone/CopyMemorySafe" target="_blank" rel="nofollow">Download on GitHub</a></b></div>


	<div style="padding:10px">

	

	
		<fieldset class="fieldset">
			<legend>Attached Images</legend>
				<div style="padding:10px">
				<img class="attach" src="https://www.vbforums.com/attachment.php?attachmentid=196124&amp;stc=1&amp;d=1779574167" alt="" />&nbsp;
			</div>
		</fieldset>
	

	

	

	</div>
]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>fafalone</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912039-VB6-VBA-twinBASIC-Intro-to-Vectored-Exception-Handling-Crash-proof-CopyMemory</guid>
		</item>
		<item>
			<title>VB6 - Add-in tools</title>
			<link>https://www.vbforums.com/showthread.php?912033-VB6-Add-in-tools&amp;goto=newpost</link>
			<pubDate>Thu, 21 May 2026 13:23:33 GMT</pubDate>
			<description><![CDATA[i updated the Tab-strip add-in:
1 - added the windows maximizated, but, seems, these part autor add it on another version: https://www.vbforums.com/showthread.php?890318-Add-In-IDE-Code-Pane-Tabs-for-MDI-SDI-(No-sub-classing-hooking);
2 - added: when we create a form the AutoRedraw is True and ScaleMode is pixels;
3 - added some nice classes(Pixels(GDIPlus), image(DIB's), and more)\functions(APIDoEvents())(add the DLL with Project-References for use them).. PS: we can't use the CConsole class with a form(the form will freeze  until we close the Console);
the VB6 can be Absolete, but i love it and we can make allmost everything with it ;)
Attachment 196104 (https://www.vbforums.com/attachment.php?attachmentid=196104)]]></description>
			<content:encoded><![CDATA[<div>i updated the Tab-strip add-in:<br />
1 - added the windows maximizated, but, seems, these part autor add it on another version: <a rel="nofollow" href="https://www.vbforums.com/showthread.php?890318-Add-In-IDE-Code-Pane-Tabs-for-MDI-SDI-(No-sub-classing-hooking);" target="_blank">https://www.vbforums.com/showthread....sing-hooking);</a><br />
2 - added: when we create a form the AutoRedraw is True and ScaleMode is pixels;<br />
3 - added some nice classes(Pixels(GDIPlus), image(DIB's), and more)\functions(APIDoEvents())(add the DLL with Project-References for use them).. PS: we can't use the CConsole class with a form(the form will freeze  until we close the Console);<br />
the VB6 can be Absolete, but i love it and we can make allmost everything with it ;)<br />
<a href="https://www.vbforums.com/attachment.php?attachmentid=196104&amp;d=1779369874"  title="Name:  TabStrip Addin.zip
Views: 39
Size:  118.4 KB">TabStrip Addin.zip</a></div>


	<div style="padding:10px">

	

	

	

	
		<fieldset class="fieldset">
			<legend>Attached Files</legend>
			<ul>
			<li>
	<img class="inlineimg" src="http://www.vbforums.com/images/attach/zip.gif" alt="File Type: zip" />
	<a href="https://www.vbforums.com/attachment.php?attachmentid=196104&amp;d=1779369874">TabStrip Addin.zip</a> 
(118.4 KB)
</li>
			</ul>
		</fieldset>
	

	</div>
]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>joaquim</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912033-VB6-Add-in-tools</guid>
		</item>
		<item>
			<title>VB6 - Console Project Template</title>
			<link>https://www.vbforums.com/showthread.php?912032-VB6-Console-Project-Template&amp;goto=newpost</link>
			<pubDate>Thu, 21 May 2026 13:13:02 GMT</pubDate>
			<description><![CDATA[heres my class and a standard\template project.... for be added on VB6 type projects..
add these project on: C:\Program Files (x86)\Microsoft Visual Studio\VB98\Template\Projects (where the VS98 was installed)
Attachment 196103 (https://www.vbforums.com/attachment.php?attachmentid=196103)
do we need VBW and VBF files?
heres a sample:

Code:
---------
Option Explicit

Dim Console As New CConsole

Sub Main()
    'your code goes here:

    Console.Writes "Hello World!!!" 
    Console.Read 'pauses here until enter
    Set Console = Nothing 'clear object
End Sub
---------
]]></description>
			<content:encoded><![CDATA[<div>heres my class and a standard\template project.... for be added on VB6 type projects..<br />
add these project on: C:\Program Files (x86)\Microsoft Visual Studio\VB98\Template\Projects (where the VS98 was installed)<br />
<a href="https://www.vbforums.com/attachment.php?attachmentid=196103&amp;d=1779368937"  title="Name:  Console.zip
Views: 33
Size:  4.6 KB">Console.zip</a><br />
do we need VBW and VBF files?<br />
heres a sample:<br />
<div class="bbcode_container">
	<div class="bbcode_description">Code:</div>
	<hr /><code class="bbcode_code">Option Explicit<br />
<br />
Dim Console As New CConsole<br />
<br />
Sub Main()<br />
&nbsp; &nbsp; 'your code goes here:<br />
<br />
&nbsp; &nbsp; Console.Writes &quot;Hello World!!!&quot; <br />
&nbsp; &nbsp; Console.Read 'pauses here until enter<br />
&nbsp; &nbsp; Set Console = Nothing 'clear object<br />
End Sub</code><hr />
</div></div>


	<div style="padding:10px">

	

	

	

	
		<fieldset class="fieldset">
			<legend>Attached Files</legend>
			<ul>
			<li>
	<img class="inlineimg" src="http://www.vbforums.com/images/attach/zip.gif" alt="File Type: zip" />
	<a href="https://www.vbforums.com/attachment.php?attachmentid=196103&amp;d=1779368937">Console.zip</a> 
(4.6 KB)
</li>
			</ul>
		</fieldset>
	

	</div>
]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>joaquim</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912032-VB6-Console-Project-Template</guid>
		</item>
		<item>
			<title><![CDATA[[VBA/VB6] COM prototyping and monkey patching without dlls]]></title>
			<link>https://www.vbforums.com/showthread.php?912028-VBA-VB6-COM-prototyping-and-monkey-patching-without-dlls&amp;goto=newpost</link>
			<pubDate>Tue, 19 May 2026 11:01:00 GMT</pubDate>
			<description><![CDATA[For those who daily struggle against the limitations imposed by VBA/VB6 regarding class inheritance, polymorphism, and advanced methods for arrays and objects, as well as for those who have found areas of code that could be handled more elegantly and concisely with more expressive syntax, and for those who have dreamed of safely modifying the behavior of certain DLLs at runtime without code injection or enforced memory protection, today I present the Advanced Scripting Framework (ASF (https://github.com/ECP-Solutions/ASF)), an abstract runtime layer that even includes its own independent regular expression engine. 

Below is an example of what is possible to achieve in a limited language like VBA.


Code:
---------
    // prototypes.vas
    export prototype.COM.Range addStyle(color) {
        this.Interior.Color = color;
    };
    
    export prototype.COM.Worksheet highlight(rng, color) {
        rng.addStyle(color);
    };
    
    // main_prototype.vas
    scwd(wd);
    import { Range_addStyle, Worksheet_highlight } from './prototypes.vas';
    // Prototypes are live immediately after import
    let ws = $1.ActiveSheet;
    let rng = ws.Range('J1:L3');
    rng.addStyle(65535);          // yellow
    ws.highlight(rng, 255);       // red
    return rng.Interior.Color
---------
Here is the driving VBA code:


Code:
---------
    Private Sub module_system_prototype_imports()
        Dim result As Long
        Dim wd As String
        Dim eng As New ASF
        wd = ThisWorkbook.path
        With eng
            .AppAccess = True
            .InjectVariable "wd", wd
            result = CLng(.Execute(wd & "\main_prototype.vas", ThisWorkbook))
        End With
        'Expected: 255
    End Sub
---------
And here is the execution trace:


Code:
---------
    === Runtime Log ===
    RUN Program: 
    CALL: ActiveSheet() -> <Worksheet>
    CALL: range('J1:L3') -> <Range>
    CALL: addstyle(65535) -> 
    CALL: __PROTOTYPE_RANGE_ADDSTYLE(65535) -> 
    CALL: Interior() -> <Interior>
    CALL: highlight(<Range>, 255) -> 
    CALL: __PROTOTYPE_WORKSHEET_HIGHLIGHT(<Range>, 255) -> 
    CALL: addstyle(255) -> 
    CALL: __PROTOTYPE_RANGE_ADDSTYLE(255) -> 
    CALL: Interior() -> <Interior>
    CALL: Interior() -> <Interior>
    CALL: Color() -> 255
    CALL: @anon() -> 255
---------
ASF comes with 233 Ruberduck tests and its regex engine has over 190 tests. Community testing is now welcome!]]></description>
			<content:encoded><![CDATA[<div>For those who daily struggle against the limitations imposed by VBA/VB6 regarding class inheritance, polymorphism, and advanced methods for arrays and objects, as well as for those who have found areas of code that could be handled more elegantly and concisely with more expressive syntax, and for those who have dreamed of safely modifying the behavior of certain DLLs at runtime without code injection or enforced memory protection, today I present the Advanced Scripting Framework (<a rel="nofollow" href="https://github.com/ECP-Solutions/ASF" target="_blank" rel="nofollow">ASF</a>), an abstract runtime layer that even includes its own independent regular expression engine. <br />
<br />
Below is an example of what is possible to achieve in a limited language like VBA.<br />
<br />
<div class="bbcode_container">
	<div class="bbcode_description">Code:</div>
	<hr /><code class="bbcode_code">&nbsp; &nbsp; // prototypes.vas<br />
&nbsp; &nbsp; export prototype.COM.Range addStyle(color) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.Interior.Color = color;<br />
&nbsp; &nbsp; };<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; export prototype.COM.Worksheet highlight(rng, color) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; rng.addStyle(color);<br />
&nbsp; &nbsp; };<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; // main_prototype.vas<br />
&nbsp; &nbsp; scwd(wd);<br />
&nbsp; &nbsp; import { Range_addStyle, Worksheet_highlight } from './prototypes.vas';<br />
&nbsp; &nbsp; // Prototypes are live immediately after import<br />
&nbsp; &nbsp; let ws = $1.ActiveSheet;<br />
&nbsp; &nbsp; let rng = ws.Range('J1:L3');<br />
&nbsp; &nbsp; rng.addStyle(65535);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // yellow<br />
&nbsp; &nbsp; ws.highlight(rng, 255);&nbsp; &nbsp; &nbsp;  // red<br />
&nbsp; &nbsp; return rng.Interior.Color</code><hr />
</div>Here is the driving VBA code:<br />
<br />
<div class="bbcode_container">
	<div class="bbcode_description">Code:</div>
	<hr /><code class="bbcode_code">&nbsp; &nbsp; Private Sub module_system_prototype_imports()<br />
&nbsp; &nbsp; &nbsp; &nbsp; Dim result As Long<br />
&nbsp; &nbsp; &nbsp; &nbsp; Dim wd As String<br />
&nbsp; &nbsp; &nbsp; &nbsp; Dim eng As New ASF<br />
&nbsp; &nbsp; &nbsp; &nbsp; wd = ThisWorkbook.path<br />
&nbsp; &nbsp; &nbsp; &nbsp; With eng<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .AppAccess = True<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .InjectVariable &quot;wd&quot;, wd<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = CLng(.Execute(wd &amp; &quot;\main_prototype.vas&quot;, ThisWorkbook))<br />
&nbsp; &nbsp; &nbsp; &nbsp; End With<br />
&nbsp; &nbsp; &nbsp; &nbsp; 'Expected: 255<br />
&nbsp; &nbsp; End Sub</code><hr />
</div>And here is the execution trace:<br />
<br />
<div class="bbcode_container">
	<div class="bbcode_description">Code:</div>
	<hr /><code class="bbcode_code">&nbsp; &nbsp; === Runtime Log ===<br />
&nbsp; &nbsp; RUN Program: <br />
&nbsp; &nbsp; CALL: ActiveSheet() -&gt; &lt;Worksheet&gt;<br />
&nbsp; &nbsp; CALL: range('J1:L3') -&gt; &lt;Range&gt;<br />
&nbsp; &nbsp; CALL: addstyle(65535) -&gt; <br />
&nbsp; &nbsp; CALL: __PROTOTYPE_RANGE_ADDSTYLE(65535) -&gt; <br />
&nbsp; &nbsp; CALL: Interior() -&gt; &lt;Interior&gt;<br />
&nbsp; &nbsp; CALL: highlight(&lt;Range&gt;, 255) -&gt; <br />
&nbsp; &nbsp; CALL: __PROTOTYPE_WORKSHEET_HIGHLIGHT(&lt;Range&gt;, 255) -&gt; <br />
&nbsp; &nbsp; CALL: addstyle(255) -&gt; <br />
&nbsp; &nbsp; CALL: __PROTOTYPE_RANGE_ADDSTYLE(255) -&gt; <br />
&nbsp; &nbsp; CALL: Interior() -&gt; &lt;Interior&gt;<br />
&nbsp; &nbsp; CALL: Interior() -&gt; &lt;Interior&gt;<br />
&nbsp; &nbsp; CALL: Color() -&gt; 255<br />
&nbsp; &nbsp; CALL: @anon() -&gt; 255</code><hr />
</div>ASF comes with 233 Ruberduck tests and its regex engine has over 190 tests. Community testing is now welcome!</div>

]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>n013</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912028-VBA-VB6-COM-prototyping-and-monkey-patching-without-dlls</guid>
		</item>
		<item>
			<title>Tiny midiplayer</title>
			<link>https://www.vbforums.com/showthread.php?912019-Tiny-midiplayer&amp;goto=newpost</link>
			<pubDate>Fri, 15 May 2026 07:08:40 GMT</pubDate>
			<description>This demonstration shows how to extract basic data from a MIDI file. Currently, it only handles musical information, which can be used to isolate a specific channel or synchronize with other applications or even hardware.

Image: https://i.ibb.co/CsMqGd5W/midiplayer.png 

A+</description>
			<content:encoded><![CDATA[<div>This demonstration shows how to extract basic data from a MIDI file. Currently, it only handles musical information, which can be used to isolate a specific channel or synchronize with other applications or even hardware.<br />
<br />
<img src="https://i.ibb.co/CsMqGd5W/midiplayer.png" border="0" alt="" /><br />
<br />
A+</div>


	<div style="padding:10px">

	

	

	

	
		<fieldset class="fieldset">
			<legend>Attached Files</legend>
			<ul>
			<li>
	<img class="inlineimg" src="http://www.vbforums.com/images/attach/zip.gif" alt="File Type: zip" />
	<a href="https://www.vbforums.com/attachment.php?attachmentid=196082&amp;d=1778828878">MidiPlayer.zip</a> 
(7.4 KB)
</li>
			</ul>
		</fieldset>
	

	</div>
]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>anycoder</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912019-Tiny-midiplayer</guid>
		</item>
		<item>
			<title>ai4vb - Ai integration</title>
			<link>https://www.vbforums.com/showthread.php?912015-ai4vb-Ai-integration&amp;goto=newpost</link>
			<pubDate>Wed, 13 May 2026 23:24:33 GMT</pubDate>
			<description>This is a small project that shows how you can integrate the Claude or ChatGPT api into your programs.

The main classes can be use in many ways. This example shows how to give the AI access to your programs data / API so it can automate your app and generate reports or do searches.

We do this by adding our programs classes to the msscript control, and then giving the AI access to probe and query it. We have designed a way that the AI can automatically discover our API surface then access it dynamically with javascript.

We use an auto generated dump of our class public prototypes to show whats available. There is a source code parser included to create these dumps by pointing it at the project file. If you wanted to keep some api private from the AI you could modify the parser to add function decorators as comments to omit them.

There is a readme.md included and more discussion here: https://sandsprite.com/papers/Agentic_Coding_Against_Live_Object_Models.pdf

You will need to generate your own API key for Claude and or Chatgpt to use this. Kinda fun.

repo: https://github.com/dzzie/ai4vb

edit: 
added optional async=false
added image analysis example
added database analysis example</description>
			<content:encoded><![CDATA[<div>This is a small project that shows how you can integrate the Claude or ChatGPT api into your programs.<br />
<br />
The main classes can be use in many ways. This example shows how to give the AI access to your programs data / API so it can automate your app and generate reports or do searches.<br />
<br />
We do this by adding our programs classes to the msscript control, and then giving the AI access to probe and query it. We have designed a way that the AI can automatically discover our API surface then access it dynamically with javascript.<br />
<br />
We use an auto generated dump of our class public prototypes to show whats available. There is a source code parser included to create these dumps by pointing it at the project file. If you wanted to keep some api private from the AI you could modify the parser to add function decorators as comments to omit them.<br />
<br />
There is a readme.md included and more discussion here: <a rel="nofollow" href="https://sandsprite.com/papers/Agentic_Coding_Against_Live_Object_Models.pdf" target="_blank" rel="nofollow">https://sandsprite.com/papers/Agenti...ect_Models.pdf</a><br />
<br />
You will need to generate your own API key for Claude and or Chatgpt to use this. Kinda fun.<br />
<br />
repo: <a rel="nofollow" href="https://github.com/dzzie/ai4vb" target="_blank" rel="nofollow">https://github.com/dzzie/ai4vb</a><br />
<br />
edit: <br />
added optional async=false<br />
added image analysis example<br />
added database analysis example</div>


	<div style="padding:10px">

	

	

	

	
		<fieldset class="fieldset">
			<legend>Attached Files</legend>
			<ul>
			<li>
	<img class="inlineimg" src="http://www.vbforums.com/images/attach/zip.gif" alt="File Type: zip" />
	<a href="https://www.vbforums.com/attachment.php?attachmentid=196093&amp;d=1779062286">ai4vb.zip</a> 
(417.8 KB)
</li>
			</ul>
		</fieldset>
	

	</div>
]]></content:encoded>
			<category domain="https://www.vbforums.com/forumdisplay.php?43-CodeBank-Visual-Basic-6-and-earlier">CodeBank - Visual Basic 6 and earlier</category>
			<dc:creator>dz32</dc:creator>
			<guid isPermaLink="true">https://www.vbforums.com/showthread.php?912015-ai4vb-Ai-integration</guid>
		</item>
	</channel>
</rss>
