Jump to content
Ascer

Device Context (DC)

Recommended Posts

Ascer

Hello.

There is any way to create a bitmap of window using device context without mouse cursor?

Code below create devault DC including mouse cursor.

Func _CreateDC($hwnd)

    ; Create parametrs.
    Local $api

    ; Call function in user library to get DC of handle.
    $api = DllCall("user32.dll", "handle", "GetWindowDC", "hwnd", $hwnd)

    ; When result is not array then return {-1}
    If Not IsArray($api) Then Return -1

    ; Return handle to bitmap.
    Return $api[0]

EndFunc

I know that is method screen capute but my pc getting laggy using this.

@UEZ

Regards,

Ascer

Share this post


Link to post
Share on other sites
Ascer

@UEZ

Thanks for replay.

I've checked source of _ScreenCapture_CaptureWnd in WinAPI.au3 and this function call _ScreenCapture_Capture.

ScreenCapture make me laggy as I said in previous post so it's bad function.

; #FUNCTION# ====================================================================================================================
; Author ........: Paul Campbell (PaulIA)
; Modified.......: jpm based on Kafu
; ===============================================================================================================================
Func _ScreenCapture_CaptureWnd($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $bCursor = True)
    If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd)
    Local $tRECT = DllStructCreate($tagRECT)
    ; needed to get rect when Aero theme is active : Thanks Kafu, Zedna
    Local Const $DWMWA_EXTENDED_FRAME_BOUNDS = 9
    Local $bRet = DllCall("dwmapi.dll", "long", "DwmGetWindowAttribute", "hwnd", $hWnd, "dword", $DWMWA_EXTENDED_FRAME_BOUNDS, "struct*", $tRECT, "dword", DllStructGetSize($tRECT))
    If (@error Or $bRet[0] Or (Abs(DllStructGetData($tRECT, "Left")) + Abs(DllStructGetData($tRECT, "Top")) + _
            Abs(DllStructGetData($tRECT, "Right")) + Abs(DllStructGetData($tRECT, "Bottom"))) = 0) Then
        $tRECT = _WinAPI_GetWindowRect($hWnd)
        If @error Then Return SetError(@error + 10, @extended, False)
    EndIf

    $iLeft += DllStructGetData($tRECT, "Left")
    $iTop += DllStructGetData($tRECT, "Top")
    If $iRight = -1 Then $iRight = DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") - 1
    If $iBottom = -1 Then $iBottom = DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") - 1
    $iRight += DllStructGetData($tRECT, "Left")
    $iBottom += DllStructGetData($tRECT, "Top")
    If $iLeft > DllStructGetData($tRECT, "Right") Then $iLeft = DllStructGetData($tRECT, "Left")
    If $iTop > DllStructGetData($tRECT, "Bottom") Then $iTop = DllStructGetData($tRECT, "Top")
    If $iRight > DllStructGetData($tRECT, "Right") Then $iRight = DllStructGetData($tRECT, "Right") - 1
    If $iBottom > DllStructGetData($tRECT, "Bottom") Then $iBottom = DllStructGetData($tRECT, "Bottom") - 1
    $bRet = _ScreenCapture_Capture($sFileName, $iLeft, $iTop, $iRight, $iBottom, $bCursor)
    Return SetError(@error, @extended, $bRet)
EndFunc   ;==>_ScreenCapture_CaptureWnd

 

Share this post


Link to post
Share on other sites
UEZ

What do you mean with laggy? Can you post a screenshot of how it looks and how the result is looking created by the WinAPI function?


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Ascer

I need access to bitmap of pixels current window screen to create shadows on screen.

In this way simple 3 functions are required.

  1. Crate bitmap with current pixel colours.
  2. Get pixels colours on specific x and y coordines.
  3. Draw a new pixel colours.

I tested this with screenCapture but in loop 100ms my pc lost 99% of RAM and everything horrible lagging.

I digged this problem on MSDN forum and this is standard situation.

Fps drop rete per one second.

  • 10-50 screenshots = FPS -10
  • 50-100 screenshots = FPS -30
  • 100-1000 screenshots = FPS -40
  • 1000+ screenshots = FPS -50 {my pc cannot make more}

Using _CreateDC function i don't have this problem. I able to make 10000+ screenshots per 1s.

Single small problem is that DC create handle with mouse cursor.

If it not possible to dislable mouse detecing will ok, i try to findout other way.

Share this post


Link to post
Share on other sites
UEZ
Posted (edited)

I think I got you - you mean the performance of this function. Well, WinAPI calls are usually not the high-performance functions and in this case you can extract the needed functions and put it directly into the loop (direct DLL calls) taking screenshots but don't expect much higher FPS! It depends also on size of the screen you want to capture. This I did in Windows Screenshooter to capture regions to a video file. The bigger the region you want to capture the slower is the FPS.

Furthermore, AutoIt is an interpreter language and thus very limited in speed for such kind of operations where you need to read, modify and generate pixels. I would advise to use a different programming language, e.g. FreeBasic is easy to learn and much faster.

 

Quote

 I able to make 10000+ screenshots per 1s.

I don't believe you. ;) That would mean that 1 frame will be create in 0,1 ms!

 

Regarding the cursor. By default the cursor shouldn't be taken.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Ascer

@UEZ

Thanks for advice, i already fixed problem using _GDIPluse_BitmapLockBits

 Unfortunately i have another with drawing text on screen. I've use code from this post.

 

 

Could you tell me what is wrong with this code?

When i tried to create cunting down text-timer after ~10min PC screen was bugged, smth like big red square.

Share this post


Link to post
Share on other sites
UEZ
Posted (edited)

Here a modified examples from here

#include <Color.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIConstants.au3>
#include <WinAPISysWin.au3>


Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

Global $iH = 150, $iW = $iH

; Initialize GDI+
_GDIPlus_Startup()

Global $hGUI = GUICreate("GDI+ Countdown Circle", 0, 0, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))

GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUISetState()

Global $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH), $hHBitmap, $hOld
Global $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap)

; Using antialiasing
_GDIPlus_GraphicsSetSmoothingMode($hGfx, 2)

; Create a Pen object
Global $pen_size = Floor($iH / 6)
Global $hPen = _GDIPlus_PenCreate(0, $pen_size)

; Create String objects
Global $fsize = Floor($iH / 10)
Global $hFormat = _GDIPlus_StringFormatCreate()
Global $hFamily = _GDIPlus_FontFamilyCreate("Arial")
Global $hFont = _GDIPlus_FontCreate($hFamily, $fsize)
Global $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0)
Global $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000)
_GDIPlus_GraphicsSetTextRenderingHint($hGfx, 4)

Global $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
$tSize.X = $iW
$tSize.Y = $iH
$tBlend.Alpha = 255
$tBlend.Format = 1

Global Const $hScrDC = _WinAPI_GetDC($hGUI), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)

GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")

; Setup font parameters
Global $angle = 360
Global $countdown_t = 20 ;seconds
Global $countdown = $countdown_t
Global $t_calc = Round(1000 * ($countdown_t + 1) / 360, 0)
Global $timer = TimerInit()
Global $flash_color[3], $fx
$flash_color[1] = 0x00
$flash_color[2] = 0x00
Global $z = 1

While 1
    _GDIPlus_GraphicsClear($hGfx, 0x00000000)
    _GDIPlus_PenSetColor($hPen, 0xFFE0FFE0)
    _GDIPlus_GraphicsDrawEllipse($hGfx, $pen_size / 2, $pen_size / 2, $iW - $pen_size, $iH - $pen_size, $hPen)
    If $countdown > 5 Then
        _GDIPlus_PenSetColor($hPen, 0xFF00FF00)
    Else
        $flash_color[0] = Max(0xB0, Abs(0xFF * Sin($z / (0xC0 * $countdown))))
        _GDIPlus_PenSetColor($hPen, "0xFF" & Hex(_ColorSetRGB($flash_color), 6))
    EndIf
    _GDIPlus_GraphicsDrawArc($hGfx, $pen_size / 2, $pen_size / 2, $iW - $pen_size, $iH - $pen_size, -90, $angle, $hPen)
    $fx = StringLen(StringFormat("%.2f", $countdown)) * $fsize / 2.5
    $tLayout.x = $iW / 2 - $fx
    $tLayout.y = $iH / 2 - $fsize * 0.75
    _GDIPlus_GraphicsDrawStringEx($hGfx, StringFormat("%.2f", $countdown), $hFont, $tLayout, $hFormat, $hBrush)

    $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteObject($hHBitmap)

    If TimerDiff($timer) > $t_calc Then
        $countdown -= $t_calc / 1000
        $timer = TimerInit()
        $angle = 360 * $countdown / $countdown_t
        If $countdown <= 0 Then
            $countdown = $countdown_t
            $angle = 360
            $timer = TimerInit()
        EndIf
    EndIf
    $z += 2
    Sleep(10)
WEnd

Func Max($a, $b)
    Return ($a > $b ? $a : $b)
EndFunc

Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
    If ($hWnd = $hGui) And ($iMsg = $WM_NCHITTEST) Then Return $HTCAPTION
EndFunc ;==>WM_NCHITTEST

Func _Exit()
    ; Clean up
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGfx)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_DeleteDC($hMemDC)
    ; Shutdown GDI+
    _GDIPlus_Shutdown()
    Exit
EndFunc

 

Edited by UEZ
  • Thanks 1

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Ascer

@UEZ

You are one of best person when i ever meet. Thanks this example works perfectly!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×