Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dynamic Libraries (Windows)
#2
Extended _ScreenImage (declared with existing dynamic libraries in BAS source)

  The built-in _ScreenImage returns the image of the primary monitor only.

   This version returns the image of the primary monitor, or the secondary monitor, or both.


Code: (Select All)

Option _Explicit


'      API types

Type RECT
    left As Long
    top As Long
    right As Long
    bottom As Long
End Type

Type POINTAPI
    x As Long
    y As Long
End Type

Type MONITORINFOEX
    cbSize As _Unsigned Long
    rcMonitor As RECT
    rcWork As RECT
    dwFlags As _Unsigned Long
    szDevice As String * 32
End Type

Type BITMAPINFOHEADER
    biSize As _Unsigned Long
    biWidth As Long
    biHeight As Long
    biPlanes As _Unsigned Integer
    biBitCount As _Unsigned Integer
    biCompression As _Unsigned Long
    biSizeImage As _Unsigned Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As _Unsigned Long
    biClrImportant As _Unsigned Long
End Type

Type BITMAPINFO
    bmiHeader As BITMAPINFOHEADER
    bmiColors0 As _Unsigned Long
End Type


'      API declaring

Declare Dynamic Library "user32"
    Function GetDC%& (ByVal hwnd As _Offset)
    Function ReleaseDC& (ByVal hwnd As _Offset, ByVal hdc As _Offset)
    Function GetSystemMetrics& (ByVal nIndex As Long)
    Function GetCursorPos (lpPoint As POINTAPI)
    Function MonitorFromRect%& (lprc As RECT, ByVal dwFlags As _Unsigned Long)
    Function GetMonitorInfoA& (ByVal hMon As _Offset, lpmi As MONITORINFOEX)
End Declare

Declare Dynamic Library "gdi32"
    Function CreateCompatibleDC%& (ByVal hdc As _Offset)
    Function DeleteDC& (ByVal hdc As _Offset)
    Function CreateCompatibleBitmap%& (ByVal hdc As _Offset, ByVal nWidth As Long, ByVal nHeight As Long)
    Function SelectObject%& (ByVal hdc As _Offset, ByVal hObject As _Offset)
    Function DeleteObject& (ByVal hObject As _Offset)
    Function BitBlt& (ByVal hDestDC As _Offset, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As _Offset, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As _Unsigned Long)
    Function GetDIBits& (ByVal hdc As _Offset, ByVal hbmp As _Offset, ByVal uStartScan As _Unsigned Long, ByVal cScanLines As _Unsigned Long, ByVal lpvBits As _Offset, bmi As BITMAPINFO, ByVal uUsage As _Unsigned Long)
End Declare

'--------------------------------------------

' 1 = primary monitor
' 2 = secondary monitor
' 3 = both (virtual desktop)
' ESC = end
'--------------------------------------------

Screen _NewImage(1280, 720, 32)
_Title "Extended _ScreenImage! Press 1 for primary monitor, 2 for secondary monitor, 3 for both!"

Dim shot&: shot& = 0

Do
    _Limit 60

    Dim k$: k$ = InKey$
    If k$ <> "" Then
        Select Case k$
            Case Chr$(27)
                Exit Do

            Case "1"
                If shot& Then _FreeImage shot&
                shot& = CapturePrimary32&

            Case "2"
                If shot& Then _FreeImage shot&
                shot& = CaptureMonitorIndex32&(2)

            Case "3"
                If shot& Then _FreeImage shot&
                shot& = CaptureAll32&
        End Select

        Cls
        If shot& Then
            _PutImage (0, 0)-(_Width(0) - 1, _Height(0) - 1), shot&
        Else
            _PrintString (10, 10), "Capture selhalo (shot&=0)."
        End If
        _Display
    End If
Loop

If shot& Then _FreeImage shot&
End








'  Both monitors at once (virtual desktop)

Function CaptureAll32& ()
    Const SM_XVIRTUALSCREEN = 76
    Const SM_YVIRTUALSCREEN = 77
    Const SM_CXVIRTUALSCREEN = 78
    Const SM_CYVIRTUALSCREEN = 79

    Dim x As Long, y As Long, w As Long, h As Long
    x = GetSystemMetrics(SM_XVIRTUALSCREEN)
    y = GetSystemMetrics(SM_YVIRTUALSCREEN)
    w = GetSystemMetrics(SM_CXVIRTUALSCREEN)
    h = GetSystemMetrics(SM_CYVIRTUALSCREEN)

    CaptureAll32& = CaptureRect32&(x, y, w, h)
End Function


'  Primary monitor only

Function CapturePrimary32& ()
    Const SM_CXSCREEN = 0
    Const SM_CYSCREEN = 1

    Dim w As Long, h As Long
    w = GetSystemMetrics(SM_CXSCREEN)
    h = GetSystemMetrics(SM_CYSCREEN)

    CapturePrimary32& = CaptureRect32&(0, 0, w, h)
End Function


'  Monitor according to index: (1 = first,, 2 = second, 3 = third...)

Function CaptureMonitorIndex32& (idx As Long)
    Dim r As RECT
    If GetMonitorRectByIndex%(idx, r) = 0 Then Exit Function
    CaptureMonitorIndex32& = CaptureRect32&(r.left, r.top, r.right - r.left, r.bottom - r.top)
End Function


' Internal capture any rectangle of the virtual surface

Function CaptureRect32& (sx As Long, sy As Long, w As Long, h As Long)
    Const BI_RGB = 0
    Const DIB_RGB_COLORS = 0
    Const SRCCOPY = &H00CC0020~&
    Const CAPTUREBLT = &H40000000~&

    If w <= 0 Or h <= 0 Then Exit Function

    Dim img&: img& = 0
    Dim hScreenDC As _Offset, hMemDC As _Offset, hBmp As _Offset, hOld As _Offset
    Dim bmi As BITMAPINFO
    Dim m As _MEM
    Dim ok As Long

    hScreenDC = GetDC(0)
    If hScreenDC = 0 Then GoTo cleanup

    hMemDC = CreateCompatibleDC(hScreenDC)
    If hMemDC = 0 Then GoTo cleanup

    hBmp = CreateCompatibleBitmap(hScreenDC, w, h)
    If hBmp = 0 Then GoTo cleanup

    hOld = SelectObject(hMemDC, hBmp)
    ok = BitBlt(hMemDC, 0, 0, w, h, hScreenDC, sx, sy, (SRCCOPY Or CAPTUREBLT))
    If ok = 0 Then GoTo cleanup

    img& = _NewImage(w, h, 32)
    If img& = 0 Then GoTo cleanup

    m = _MemImage(img&)

    bmi.bmiHeader.biSize = Len(bmi.bmiHeader)
    bmi.bmiHeader.biWidth = w
    bmi.bmiHeader.biHeight = -h
    bmi.bmiHeader.biPlanes = 1
    bmi.bmiHeader.biBitCount = 32
    bmi.bmiHeader.biCompression = BI_RGB
    bmi.bmiHeader.biSizeImage = w * h * 4

    ok = GetDIBits(hMemDC, hBmp, 0, h, m.OFFSET, bmi, DIB_RGB_COLORS)
    If ok = 0 Then
        _MemFree m
        _FreeImage img&
        img& = 0
        GoTo cleanup
    End If

    ' B,G,R,X -> set alpha to 255
    Dim o As _Offset, oLast As _Offset
    o = m.OFFSET + 3
    oLast = m.OFFSET + (w * h * 4)
    $Checking:Off
    Do While o < oLast
        _MemPut m, o, 255 As _UNSIGNED _BYTE
        o = o + 4
    Loop
    $Checking:On

    _MemFree m

    cleanup:
    If hMemDC <> 0 And hOld <> 0 Then hOld = SelectObject(hMemDC, hOld)
    If hBmp <> 0 Then hBmp = DeleteObject(hBmp)
    If hMemDC <> 0 Then hMemDC = DeleteDC(hMemDC)
    If hScreenDC <> 0 Then hScreenDC = ReleaseDC(0, hScreenDC)

    CaptureRect32& = img&
End Function


' Internal: find monitor rectangle by index
' idx=1 primary; others left to right, top to bottom

Function GetMonitorRectByIndex% (idx As Long, rOut As RECT)
    Const SM_XVIRTUALSCREEN = 76
    Const SM_YVIRTUALSCREEN = 77
    Const SM_CXVIRTUALSCREEN = 78
    Const SM_CYVIRTUALSCREEN = 79
    Const SM_CMONITORS = 80

    Const MONITOR_DEFAULTTONULL = 0
    Const MONITORINFOF_PRIMARY = 1

    Dim need As Long: need = GetSystemMetrics(SM_CMONITORS)
    If need <= 0 Then need = 1

    'scan a unique HMONITOR without a callback: via MonitorFromRect on a grid of points
    Dim vx As Long, vy As Long, vw As Long, vh As Long
    vx = GetSystemMetrics(SM_XVIRTUALSCREEN)
    vy = GetSystemMetrics(SM_YVIRTUALSCREEN)
    vw = GetSystemMetrics(SM_CXVIRTUALSCREEN)
    vh = GetSystemMetrics(SM_CYVIRTUALSCREEN)
    If vw <= 0 Or vh <= 0 Then Exit Function

    Dim hMon As _Offset
    Dim monCount As Long: monCount = 0
    ReDim hMon(1 To 1) As _Offset

    Dim stepPx As Long: stepPx = 256
    If stepPx < 32 Then stepPx = 32

    Dim xx As Long, yy As Long, i As Long, found As Long
    Dim rr As RECT
    Dim hm As _Offset

    For yy = vy To vy + vh - 1 Step stepPx
        For xx = vx To vx + vw - 1 Step stepPx
            rr.left = xx: rr.top = yy: rr.right = xx + 1: rr.bottom = yy + 1
            hm = MonitorFromRect(rr, MONITOR_DEFAULTTONULL)
            If hm <> 0 Then
                found = 0
                For i = 1 To monCount
                    If hMon(i) = hm Then found = 1: Exit For
                Next
                If found = 0 Then
                    monCount = monCount + 1
                    If monCount = 1 Then
                        hMon(1) = hm
                    Else
                        ReDim _Preserve hMon(1 To monCount) As _Offset
                        hMon(monCount) = hm
                    End If
                    If monCount >= need Then Exit For
                End If
            End If
        Next
        If monCount >= need Then Exit For
    Next

    If monCount = 0 Then Exit Function

    ' načíst recty + flagy
    Dim leftA As Long, topA As Long, primA As Long
    ReDim leftA(1 To monCount) As Long
    ReDim topA(1 To monCount) As Long
    ReDim primA(1 To monCount) As Long
    Dim mi As MONITORINFOEX, ok As Long

    For i = 1 To monCount
        mi.cbSize = Len(mi)
        ok = GetMonitorInfoA(hMon(i), mi)
        If ok Then
            leftA(i) = mi.rcMonitor.left
            topA(i) = mi.rcMonitor.top
            primA(i) = ((mi.dwFlags And MONITORINFOF_PRIMARY) <> 0)
        Else
            leftA(i) = 0: topA(i) = 0: primA(i) = 0
        End If
    Next

    ' sort: primary first, rest left/top
    Dim As Long j, swp, tmpL, tmpT, tmpP
    Dim tmpO As _Offset
    For i = 1 To monCount - 1
        For j = i + 1 To monCount
            swp = 0

            ' primary always before non-primary
            If primA(i) = 0 And primA(j) = 1 Then swp = 1

            ' both of the same "primary" type -> left/top
            If swp = 0 And primA(i) = primA(j) Then
                If leftA(j) < leftA(i) Then swp = 1
                If leftA(j) = leftA(i) And topA(j) < topA(i) Then swp = 1
            End If

            If swp Then
                tmpO = hMon(i): hMon(i) = hMon(j): hMon(j) = tmpO
                tmpL = leftA(i): leftA(i) = leftA(j): leftA(j) = tmpL
                tmpT = topA(i): topA(i) = topA(j): topA(j) = tmpT
                tmpP = primA(i): primA(i) = primA(j): primA(j) = tmpP
            End If
        Next
    Next

    If idx < 1 Or idx > monCount Then Exit Function

    mi.cbSize = Len(mi)
    ok = GetMonitorInfoA(hMon(idx), mi)
    If ok = 0 Then Exit Function

    rOut = mi.rcMonitor
    GetMonitorRectByIndex% = 1
End Function


Reply


Messages In This Thread
Dynamic Libraries (Windows) - by Petr - 12-08-2025, 06:48 PM
RE: Dynamic Libraries - by Petr - 12-08-2025, 07:12 PM
RE: Dynamic Libraries - by Petr - 12-08-2025, 07:52 PM
RE: Dynamic Libraries - by Jack - 12-08-2025, 08:41 PM
RE: Dynamic Libraries - by Petr - 12-09-2025, 07:21 PM
RE: Dynamic Libraries - by Petr - 12-11-2025, 04:19 PM
RE: Dynamic Libraries - by Petr - 12-12-2025, 10:00 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 05:56 PM
RE: Dynamic Libraries - by 2112 - 12-13-2025, 07:06 PM
RE: Dynamic Libraries - by ahenry3068 - 12-13-2025, 07:47 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 07:41 PM
RE: Dynamic Libraries - by 2112 - 12-13-2025, 08:23 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 08:36 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 09:03 PM
RE: Dynamic Libraries - by ahenry3068 - 12-13-2025, 11:16 PM
RE: Dynamic Libraries - by Petr - 12-14-2025, 12:15 AM
RE: Dynamic Libraries - by Petr - 12-15-2025, 08:22 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-15-2025, 06:30 PM
RE: Dynamic Libraries (Windows) - by Mad Axeman - 12-19-2025, 02:37 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-18-2025, 07:45 PM
RE: Dynamic Libraries (Windows) - by Steffan-68 - 12-18-2025, 08:31 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-18-2025, 08:55 PM
RE: Dynamic Libraries (Windows) - by Steffan-68 - 12-18-2025, 09:48 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-18-2025, 09:32 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-18-2025, 11:53 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-19-2025, 06:40 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 03:08 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 10:35 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 10:54 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 11:20 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-19-2025, 11:37 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-20-2025, 10:22 PM
RE: Dynamic Libraries (Windows) - by SMcNeill - 12-20-2025, 11:03 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-21-2025, 05:40 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-22-2025, 08:23 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-23-2025, 09:06 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-24-2025, 09:54 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-25-2025, 10:02 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-26-2025, 11:14 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-27-2025, 01:35 PM
RE: Dynamic Libraries (Windows) - by MasterGy - 12-27-2025, 07:23 PM
RE: Dynamic Libraries (Windows) - by Petr - 01-07-2026, 06:31 PM
RE: Dynamic Libraries (Windows) - by Petr - 01-07-2026, 09:13 PM
RE: Dynamic Libraries (Windows) - by Petr - 02-24-2026, 06:38 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Dynamic Libraries (Linux) Petr 19 1,153 12-29-2025, 09:52 PM
Last Post: Petr

Forum Jump:


Users browsing this thread: 1 Guest(s)