Jump to content
Sign in to follow this  

Scrolling GDI Images

Recommended Posts


Hello again! Working on another project I'm using for a game called PokeMMO. Let me first say I am not automating any part of the game. I set the current location and the script will then display the available Pokemon in the area (In a transparent GUI, making the game the parent).

The GUI height is based on the height of the game window, setting the max number of sprites displayed based on that. If there are more sprites than can be displayed I'm trying to make it so when you hover over the top/bottom it will scroll the images up/down, wrapping around in one vertical circle. I started working on it and managed to make it scroll up but it looked messy, didn't work properly, and just didn't seem right...

Maybe it's because it's late, I've been working on this and my simple editor all day, lack of sleep, lack of food, I'm giving up for now but posting this in the hopes someone can point me in the right direction and show me what kind of algorithm I need to use to make it work lol

Here's a link to the images used: http://imgur.com/a/AMtWn

(Images in order should be named Hoothoot.png, Pidgey.png, Rattata.png, and Caterpie.png)

#include <GDIPlus.au3>
#include <Array.au3>
#include <File.au3>
#include <GUIConstants.au3>
#include <GDIPlus.au3>
#include <String.au3>
#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <ScreenCapture.au3>
#include <Color.au3>
#include <Misc.au3>

HotKeySet("+{Esc}", "Close")

AutoItSetOption("GuiOnEventMode", 1)
AutoItSetOption("MustDeclareVars", 1)

Global const $INI_PATH = @ScriptDir & "\PokeTracker.ini"
Global $x
Global $y
Global $max_height = 0
Global $new_size = 0
Global $sprite_width = 56
Global $sprite_height = 56
Global $current_location = "Route 1"
Global $possible_locations
Global $frmTracker
Global $frmResize
Global $lblTitleBar
Global $hWnd_graphics
Global $hWnd_bitmap
Global $hWnd_gdi_buffer
Global $hWnd_family
Global $hWnd_format
Global $hWnd_brush
Global $hWnd_pen
Global $scroll = False
Global $frm_tracker_state = @SW_HIDE
Global $pokemon_count = 4
Global $pokemon_in_location[] = [5, "Pidgey", "Rattata", "Caterpie", "Hoothoot"]
Global $hWnd_dll


Func WinMain()
    $hWnd_dll = DllOpen("user32.dll")
    ; Create the tracker GUI
    $frmTracker = GUICreate("PokeTracker", $sprite_width, $sprite_height * $pokemon_count, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
    ; Create a label that can be used to drag the tracker
    $lblTitleBar = GUICtrlCreateLabel("", 0, 0, $sprite_width, $sprite_height, -1, $GUI_WS_EX_PARENTDRAG)
    GUICtrlSetOnEvent($lblTitleBar, "Resize")
    ; Set colors of the GUI and label
    GUISetBkColor(0x000000, $frmTracker)
    GUICtrlSetBkColor($lblTitleBar, $GUI_BKCOLOR_TRANSPARENT)
    ; Set the GUI to transparent
    _WinAPI_SetLayeredWindowAttributes($frmTracker, 0x000000, 255)
    GUISetState(@SW_SHOW, $frmTracker)
    ; Create GDI handles used for drawing the sprites
    $hWnd_graphics = _GDIPlus_GraphicsCreateFromHWND($frmTracker)
    $hWnd_bitmap = _GDIPlus_BitmapCreateFromGraphics($sprite_width, $sprite_height * $pokemon_count, $hWnd_graphics)
    $hWnd_gdi_buffer = _GDIPlus_ImageGetGraphicsContext($hWnd_bitmap)
    ; Set the GDI objects to smooth
    _GDIPlus_GraphicsSetSmoothingMode($hWnd_gdi_buffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsSetTextRenderingHint($hWnd_graphics, $GDIP_TEXTRENDERINGHINT_ANTIALIASGRIDFIT)
    ; Create GDI Handles used for writing the Strings
    $hWnd_format = _GDIPlus_StringFormatCreate()
    _GDIPlus_StringFormatSetAlign($hWnd_format, 1)
    $hWnd_brush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
    $hWnd_pen = _GDIPlus_PenCreate(0xFF1F1F1F, 1)
    $hWnd_family = _GDIPlus_FontFamilyCreate("Segoe UI")
    While (True)
EndFunc   ;==>WinMain

Func Close()
    ; Free GDI Resources
    ; Delete the current location file
    FileDelete(@ScriptDir & "\Images\Current Location.png")
    Exit (0)
EndFunc   ;==>Close

Func Resize()
    If (Not _IsPressed(11, $hWnd_dll)) Then Return
    Local $abscoord_tracker = WinGetPos($frmTracker)
    $frmResize = GUICreate("", $abscoord_tracker[2] - 14, $abscoord_tracker[3], $abscoord_tracker[0], $abscoord_tracker[1], $WS_SIZEBOX, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
    GUISetOnEvent($GUI_EVENT_CLOSE, "SetTrackerSize", $frmResize)
    GUIRegisterMsg($WM_SIZE, "WM_SIZE")
    GUISetBkColor(0x000000, $frmResize)
    ;_WinAPI_SetLayeredWindowAttributes($frmResize, 0x000000, 255)
    GUISetState(@SW_SHOW, $frmResize)
    GUISetState(@SW_DISABLE, $frmTracker)
    GUISetState(@SW_LOCK, $frmTracker)

Func SetTrackerSize()
    Local $abscoord_resize = WinGetPos($frmResize)
    Local $abscoord_tracker = WinGetPos($frmTracker)
    $frmResize = Null
    $new_size = $abscoord_resize[3]
    $max_height = $new_size
    GUISetState(@SW_ENABLE, $frmTracker)
    GUISetState(@SW_UNLOCK, $frmTracker)
    WinMove($frmTracker, "", $abscoord_resize[0], $abscoord_resize[1], $abscoord_resize[2], $new_size)
    GUICtrlSetPos($lblTitleBar, 0, 0, $sprite_width, $new_size)
    $hWnd_graphics = _GDIPlus_GraphicsCreateFromHWND($frmTracker)
    $hWnd_bitmap = _GDIPlus_BitmapCreateFromGraphics($sprite_width, $new_size, $hWnd_graphics)
    $hWnd_gdi_buffer = _GDIPlus_ImageGetGraphicsContext($hWnd_bitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hWnd_gdi_buffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsSetTextRenderingHint($hWnd_graphics, $GDIP_TEXTRENDERINGHINT_ANTIALIASGRIDFIT)

Func UpdateTracker()
    _GDIPlus_GraphicsClear($hWnd_gdi_buffer, 0x00000000)
    If ($pokemon_count >= 1 and IsArray($pokemon_in_location)) Then
        For $i = 1 To $pokemon_count
            ; Split the data for the pokemon_in_location
            Local $pokemon_data = StringSplit($pokemon_in_location[$i], ',')
            ; Rectangle for the area of the sprite and string
            Local $rect_pokemon_image[4] = [0, ($i - 1) * $sprite_height, $sprite_width, $sprite_height]
            ; If there is a Pokemon name in the $pokemon_data array ($pokemon_data[1] = Pokemon Name)
            If ($pokemon_data[0] >= 1) Then
                Local $hWnd_image = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Images\Sprites\" & $pokemon_data[1] & ".png")
                _GDIPlus_GraphicsDrawImageRect($hWnd_gdi_buffer, $hWnd_image, $rect_pokemon_image[0], $rect_pokemon_image[1], $rect_pokemon_image[2], $rect_pokemon_image[3])
            ; If there are 2 pieces of data for the Pokemon [1] = Pokemon name, [2] = Rarity
            If ($pokemon_data[0] = 2) Then
                Local $hWnd_path = _GDIPlus_PathCreate()
                Local $rect_layout = _GDIPlus_RectFCreate($rect_pokemon_image[0], $rect_pokemon_image[1], $rect_pokemon_image[2], $rect_pokemon_image[3] - ($sprite_height / 2))
                _GDIPlus_PathAddString($hWnd_path, $pokemon_data[2], $rect_layout, $hWnd_family, 0, 14, $hWnd_format)
                _GDIPlus_GraphicsDrawPath($hWnd_gdi_buffer, $hWnd_path, $hWnd_pen)
                _GDIPlus_GraphicsFillPath($hWnd_gdi_buffer, $hWnd_path, $hWnd_brush)
                _GDIPlus_GraphicsFillPath($hWnd_gdi_buffer, $hWnd_path, $hWnd_brush)
    _GDIPlus_GraphicsDrawImage($hWnd_graphics, $hWnd_bitmap, 0, 0)
EndFunc   ;==>UpdateTracker

Func WM_PAINT($hWndFrom, $iMsg, $wParam, $lParam)
    Return UpdateTracker()
EndFunc   ;==>WM_PAINT

Func WM_WINDOWPOSCHANGING($hWndFrom, $iMsg, $wParam, $lParam)
    Local $abscoord_pokemmo = WinGetPos("[Class:LWJGL]")
    If (Not IsArray($abscoord_pokemmo)) Then Return $GUI_RUNDEFMSG
    Local $stWinPos = DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
    Local $iLeft = DllStructGetData($stWinPos, 3)
    Local $iTop = DllStructGetData($stWinPos, 4)
    Local $iWidth = DllStructGetData($stWinPos, 5)
    Local $iHeight = DllStructGetData($stWinPos, 6)
    If ($iHeight > $abscoord_pokemmo[3] + 64) Then DllStructSetData($stWinPos, 6, $abscoord_pokemmo[3] - 64)
    If $iLeft < $abscoord_pokemmo[0] + 8 Then DllStructSetData($stWinPos, 3, $abscoord_pokemmo[0] + 8)
    If $iTop < $abscoord_pokemmo[1] + 30 Then DllStructSetData($stWinPos, 4, $abscoord_pokemmo[1] + 30)
    If $iLeft > $abscoord_pokemmo[0] + $abscoord_pokemmo[2] - $iWidth - 8 Then DllStructSetData($stWinPos, 3, $abscoord_pokemmo[0] + $abscoord_pokemmo[2] - $iWidth - 8)
    If $iTop > $abscoord_pokemmo[1] + $abscoord_pokemmo[3] - $iHeight - 8 Then DllStructSetData($stWinPos, 4, $abscoord_pokemmo[1] + $abscoord_pokemmo[3] - $iHeight - 8)
    If ($iLeft < $abscoord_pokemmo[0] + 167 and $iTop < $abscoord_pokemmo[1] + 64) Then
        If ($iTop < $abscoord_pokemmo[1] + 64) Then DllStructSetData($stWinPos, 4, $abscoord_pokemmo[1] + 64)

; Not used, was going to use it for a second GUI that would dictate the size of the buffer to draw (how many rows/columns to draw and each Pokemon)
Func WM_GETMINMAXINFO($hWnd, $iMsg, $wParam, $lParam)
    Local $abscoord_pokemmo = WinGetPos("[Class:LWJGL]")
    Local $tagMaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($tagMaxinfo,  7, $sprite_width) ; min width
    DllStructSetData($tagMaxinfo,  8, $sprite_height)  ; min height
    DllStructSetData($tagMaxinfo,  9, $sprite_width) ; max width
    DllStructSetData($tagMaxinfo,  10, $max_height)  ; max height

Func WM_MOUSEMOVE($hWnd, $iMsg, $wParam, $lParam)
    Local $abscoord_mouse = MouseGetPos()
    Local $abscoord_tracker = WinGetPos($frmTracker)
    Local $mouse_in_point
    If (Not IsArray($abscoord_tracker)) Then
        Return $GUI_RUNDEFMSG
    If (_WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1], $abscoord_tracker[0] + $abscoord_tracker[2], $abscoord_tracker[1] + $sprite_height)) Then
        $mouse_in_point = True
        While ($mouse_in_point)
            $abscoord_mouse = MouseGetPos()
            $abscoord_tracker = WinGetPos($frmTracker)
            $mouse_in_point = _WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1], $abscoord_tracker[0] + $abscoord_tracker[2], $abscoord_tracker[1] + $sprite_height)
    ElseIf (_WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1] + $abscoord_tracker[3] - $sprite_height, $abscoord_tracker[0] + $abscoord_tracker[1], $abscoord_tracker[1] + $abscoord_tracker[3])) Then
        ToolTip("bottom", 0, 0)


Share this post

Link to post
Share on other sites

Lack of sleep, I swear.... Figured it out in 15 mins when I woke up this morning.

Fortunately, since I'm  using an array to hold the values of what to draw my solution was to just move the first item to the last, or the last item to the first (depending on where I start drawing)

(Kind of dirty right now but I'll go through and clean up everything when I'm done)

It's pretty smooth, occasional flicker but I haven't found a solution for something like this because I do have to clear the main graphic since I'm using a transparent background.

The new WM_MOUSEMOVE function, tracks the mouse and if the pointer is inside the top or bottom of the GUI, scroll. Adjusting the $gdi_start_y accordingly.

Func WM_MOUSEMOVE($hWnd, $iMsg, $wParam, $lParam)
    Local $abscoord_mouse = MouseGetPos()
    Local $abscoord_tracker = WinGetPos($frmTracker)
    Local $mouse_in_point = True
    Local $scroll_speed = 2
    If (Not IsArray($abscoord_tracker)) Then
        Return $GUI_RUNDEFMSG
    If (_WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1], $abscoord_tracker[0] + $abscoord_tracker[2], $abscoord_tracker[1] + ($sprite_height / 2))) Then
        While ($mouse_in_point)
            $gdi_start_y -= $scroll_speed
            If ($gdi_start_y < ($sprite_height * -1)) Then
                $gdi_start_y = 0
                ArrayMoveValue($pokemon_in_location, 1, $pokemon_count)
            $abscoord_mouse = MouseGetPos()
            $abscoord_tracker = WinGetPos($frmTracker)
            $mouse_in_point = _WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1], $abscoord_tracker[0] + $abscoord_tracker[2], $abscoord_tracker[1] + ($sprite_height / 2))
    ElseIf (_WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1] + $abscoord_tracker[3] - ($sprite_height / 2), $abscoord_tracker[0] + $abscoord_tracker[1], $abscoord_tracker[1] + $abscoord_tracker[3])) Then
        While ($mouse_in_point)
            $gdi_start_y += $scroll_speed
            If ($gdi_start_y > $sprite_height) Then
                $gdi_start_y = 0
                ArrayMoveValue($pokemon_in_location, $pokemon_count, 1)
            $abscoord_mouse = MouseGetPos()
            $abscoord_tracker = WinGetPos($frmTracker)
            $mouse_in_point = _WinAPI_PtInRectEx($abscoord_mouse[0], $abscoord_mouse[1], $abscoord_tracker[0], $abscoord_tracker[1] + $abscoord_tracker[3] - ($sprite_height / 2), $abscoord_tracker[0] + $abscoord_tracker[1], $abscoord_tracker[1] + $abscoord_tracker[3])

And the ArrayMoveValue

Func ArrayMoveValue($aArray, Const $index_from, Const $index_to)
    Local const $tmp_val = $pokemon_in_location[$index_from]
    $aArray = $pokemon_in_location
    _ArrayDelete($aArray, $index_from)
    If ($index_to = $pokemon_count) Then
        _ArrayAdd($aArray, $tmp_val)
        _ArrayInsert($aArray, $index_to, $tmp_val)
    $pokemon_in_location = $aArray


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
Sign in to follow this  

  • Similar Content

    • Sven-Seyfert
      By Sven-Seyfert
      Hi Community,

      I'm looking for a way to do a Video Overlay GUI or something like that. The idea is to create a GUI which plays a video loop (with transparency/alpha channel) in front of an other GUI. Before you asking why - because I don't believe that GDIPlus can do it out of the box. My skillset for that kind of graphical things isn't good enough to do that, but here are some specialist like @UEZ maybe who can help.

      Example alpha channel video (visualized as animated *.gif):

      I tried to do the light rays effect directly with GDIPlus, but honestly that's a bit too difficult for me. I would be very glad and grateful if there are some suggestions, ideas or recommendations.

      Code for the Video play:
      Example video "End.mpeg":
      The next challenge is that the overlay GUI should be not clickable. If I hover over the overlay area, I want to have the possibility to control the GUI or what ever, in the background. But if there is any chance to make it with GDIPlus as a Video Overlay for light rays, I would prefer that approach instead of my crazy work-around idea.

      Thanks for any suggestion - I'm grateful!
    • aiter
      By aiter
      I am trying to get an image showing through a edit box.  I am only successful in making the edit box totally transparent
      #include-once #include <GUIConstants.au3> #include <GDIPlus.au3> #include <WinAPISys.au3> #include <colorconstants.au3> ;WS_EX_TRANSPARENT $gui = GUICreate("", 1000, 800, -1, -1, -1 , $WS_EX_LAYERED) ; use layered to get _winapi_setlay... to work $pic = GUICtrlCreatePic("c:\Program Files (x86)\AutoIt3\Examples\GUI\Merlin.gif", 0,0,1000, 800) GUICtrlSetState(-1, $GUI_DISABLE) $edit = GUICtrlCreateEdit("First line" & @CRLF, 176, 32,200,600) GUICtrlSetBkColor(-1,$COLOR_YELLOW) _WinAPI_SetLayeredWindowAttributes($gui,$COLOR_YELLOW,199) ; 199 is alpha (transparency level) GUISetState(@SW_SHOW,$gui) While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case Else EndSelect WEnd Exit Func Terminate() exit(0) EndFunc So I am making the edit box's background yellow then using the _WINAPI_SetLayeredWIndowAttributes command to make the yellow disappear (which it does), but the alpha level is supposed to give a bit of opaqueness to it, but its not, just making it totally transparent.  The alpha level is in fact affecting the window itself and not the edit box. I only want the edit box to be partially transparent.
      Help appreciated.
    • ISI360
      By ISI360
      I am searching for a way to display a transparent image (or Icon) over an Button. And the image should always stay on top.

      Here is what i have so far:
      At script start the picture is over the button..but if you move the mouse over the button it overlaps the image.
      And if i add $GUI_ONTOP to the picture, the transparency is gone

      Maybe someone has an idea..

      Thanks in advance!
      #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WinAPIIcons.au3> #include <WinAPIShellEx.au3> GUICreate("GUI", 300, 300) $hbutton = GUICtrlCreateButton("This is a button", 20, 40, 150, 30,$WS_CLIPSIBLINGS) $hpic = GUICtrlCreatePic("", 10, 10, 128, 128) _SetIconAlpha($hpic,"shell32.dll", 12,128,128) GUICtrlSetState(-1, $GUI_DISABLE) ;~ GUICtrlSetState(-1,$GUI_ONTOP) ;If you uncomment this..the picture is on top...but the transparency is gone :( GUISetState() While 1 $Msg = GUIGetMsg() If $Msg = $GUI_EVENT_CLOSE Then ExitLoop WEnd Func _SetIconAlpha($hWnd, $sIcon, $iIndex, $iWidth, $iHeight) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) If $hWnd = 0 Then Return SetError(1, 0, 0) EndIf EndIf If $iIndex <> 0 Then $iIndex = $iIndex - 1 Local $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight) If $hIcon = 0 Then Return SetError(1, 0, 0) EndIf Local $hBitmap, $hObj, $hDC, $hMem, $hSv $hDC = _WinAPI_GetDC($hWnd) $hMem = _WinAPI_CreateCompatibleDC($hDC) $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight) $hSv = _WinAPI_SelectObject($hMem, $hBitmap) _WinAPI_DrawIconEx($hMem, 0, 0, $hIcon, $iWidth, $iHeight, 0, 0, 2) _WinAPI_ReleaseDC($hWnd, $hDC) _WinAPI_SelectObject($hMem, $hSv) _WinAPI_DeleteDC($hMem) _WinAPI_DestroyIcon($hIcon) _WinAPI_DeleteObject(_SendMessage($hWnd, 0x0172, 0, 0)) _SendMessage($hWnd, 0x0172, 0, $hBitmap) $hObj = _SendMessage($hWnd, 0x0173) If $hObj <> $hBitmap Then _WinAPI_DeleteObject($hBitmap) EndIf Return 1 EndFunc ;==>_SetIconAlpha  
    • UEZ
      By UEZ
      AutoIt Windows Screenshooter
      Key Features:
      takes easily a screenshot from any visible window capture any region of the desktop incl. freehand capturing capture GUI controls and GUI menus separately capture a marked area every x seconds for a duration of y seconds create a GIF animation from saved frames (Vista or higher os required) capture to AVI file (without audio!) takes a screenshot from web sites (available only on Vista+ os and when Aero is enabled) put images to clipboard to paste to other applications easily color picker save image in different formats and also to PDF! add timestamp to saved images simple image editing options: greyscale, b&w, invert, rotate +-90° send image to printer and default email client preview of captured screens incl. zoom option multi monitor support display pixel color under mouse ruler basic image editor (paint, highlight, ellipse, rectangle, text and some graphic FX) watermark captured image no 3rd party tools or DLLs used - pure AutoIt! fully portable - no installation is needed multi language feature (Eng, Ger, Tur, Fra and Rus only) To do:
      capture content of scrollable window/control capture cascaded menus Due to DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0) limitation some windows cannot be captured properly (GDI+, ProgDVB, etc.) but can take screenshots of hidden windows. One workaround is to use full screen capturing (F11/F12) or "Grab Screen" function! Or try double click with rmb on listview items (beta).
      Download source code (5771 downloads previously): AutoIt Windows Screenshooter v1.79 Build 2018-05-08.7z (version needed!)
      You are not allowed to sell this code or just parts of it in a commercial project or modify it and distribute it with a different name!
      Download compiled Exe only: 4shared / Media Fire / Softpedia (1.54mb)
      Distributing copies of the program in compiled format (exe) must be free of any fee!
      -----> click here to Donate!  
      (Current donators: 1. Cuong N.) 
      It is designed for Vista+ operating systems with AERO enabled! E.g. on WinXP machines some functions are not working properly and might crash the application!
      AV scanners may have a negative impact the execution of compiled exe and might report any malware. I guarantee that there is no malicious code in the source code / exe!!! 
      Main GUI:

      About Intro:

      Basic Image Editor:


      Click link for an enhanced version of Watermark Image.
      main code by UEZ additional code (alphabetical order) by Authenticity, AutoItObject Team, Eemuli, Eukalyptus, funkey, _Kurt, martin, monoceres, ProgAndy, taietel, trancexx, Ward, wolf9228 and Yashied! mesale0077 for turkish translation wakillon for french translation AZJIO for russian translation Keys:
      Main GUI:
      User your mouse to scroll preview window or
      Numpad 8: Scroll preview window up
      Numpad 2: Scroll preview window down
      Numpad 4: Scroll preview window left
      Numpad 6: Scroll preview window right
      Numpad +: zoom in preview window or mousewheel down
      Numpad -: zoom out preview window or mousewheel up
      F1: capture again on last position
      F5: refresh Windows Name list
      PRINTSCREEN: take screenshot from whole screen
      ALT+PRINTSCR: take a screenshot from active window
      F10: Undo made changes with Image Editing function
      F11: take screenshot from whole screen incl mouse cursor
      F12: take screenshot from whole screen
      Ctrl+Alt+F9 start "Grab Screen" mode
      Ctrl+Alt+F12: take a screenshot from active window using alternative screenshot functionality (beta)!
      Ctrl+r: call ruler
      Ctrl+s: save current displayed image
      Ctrl+x: exit program
      ctrl+w: call web grab input field (availabe only when Aero is enabled)
      Ctrl+i: call image editor
      Ctrl+m: call watermark editor
      Ctrl+z: undo
      Only available on Vista+ os: double click with rmb on list items to use alternative screenshot functionality (beta)!
      When 'Grab Screen' is clicked you can hold down the ctrl key to switch to 'grab controls' mode. Control under mouse will be framed red.
      ctrl + shift will take the screenshot of appropriate control. To capture GUI menues you can press rmb which simulates the lmb. When a menu is opened press shift additionaly to capture it.
      Press and hold only the shift key to capture any region on the desktop using freehand capturing - release it so capture marked regions!
      Or just mark resizeable area which you want to grab. Press CTRL key to grab marked area or right mouse button to capture the marked area every x seconds for a duration of y seconds.
      When saving the image just enter the extension you whish to use (*.jpg;*.png;*.bmp;*.gif;*.tif;*.pdf). Big thanks to taietel for his PDF UDF!
      Image Editor:
      s: save
      c: copy
      n: send
      h: highlighter
      p: pen
      r: rectangle
      e: ellipse
      a: arrow
      o: color
      t: text
      g: text config
      Ctrl+z: undo
      Watermark editor:
      Ctrl+z: undo
      To start the app minimized just call it "Windows Screenshooter.exe /min"
      Maybe it is useful for someone...
      Any kind of comment is welcome.
      Change log:
    • c.haslam
      By c.haslam
      I think that _GDIPlus_ImageGetPropertyItem should return a Property Item that can readily be set as a property of another image. Why would one want to do this? A script might (as one of mine does) edit an image of a .jpg file then write the result to a .jpg file. In editing it, in my case, the number of horizontal and vertical pixels change, and the date/time edited should be set as a property. All other property items remain the same. Other GDI+ users may change other properties.
      So an approach is to copy all the property items from image1 to image2, then update a few properties.
      M$ provides a Property Item class (id, length, pointer to an array of values) but _GDIPlus_ImageGetPropertyItem returns something different.
      I think that, wherever reasonable, UDFs that are wrappers for M$ methods should work like M$'s methods. _GDIPlus_ImageGetPropertyItem does not do this:
      While M$ returns 2 values for a value that is a ratio of 2 numbers,  _GDIPlus_ImageGetPropertyItem returns numerator/denominator as a single value (often a Double). _GDIPlus_ImageSetPropertyItem (when included in GDIPlus.au3) will be unable to set ratio property items properly because it cannot know what the numerator and denominator are. So copying such property items will not work properly. M$ has a Void* buffer where the buffer is an array of values but _GDIPlus_ImageGetPropertyItem() returns the values in the same 1-d array as id, length and type. M$'s approach produces a 1-d array with the same number of elements for all property items while _GDIPlus_ImageGetPropertyItem produces a 1-d array with various numbers of elements. To me, this is not good programming practice. For a photo from a Sony camera, the worst case has 1-d array with 67 elements. When combined into a 2-d array with the property items of all properties, there are 66 rows and 67 columns, with many elements not used. So I suggest that _GDIPlus_ImageGetPropertyItem look like this:
      ; #FUNCTION# ==================================================================================================================== ; Name ..........: cGDIPlus_ImageGetPropertyItem ; Description ...: Gets a specified property item (piece of meta data) from an Image object ; Syntax ........: cGDIPlus_ImageGetPropertyItem($hImage, $iPropID) ; Parameters ....: $hImage - Pointer to an image object ; $iPropID - Identifier of the property item to be retrieved ; Return values .: Success: Array containing the values of the property item ; [0] - identifier ; [1] - size, in bytes, of the value array ; [2] - type of value(s) in the value array ; [3] - value array ; Failure: Sets the @error flag to non-zero, @extended may contain GPSTATUS error code ($GPID_ERR*). ; Author ........: Eukalyptus ; Modified ......: c.haslam ; Remarks .......: types: unsigned byte = 1, ASCII string = 2, unsigned short = 3, unsigned long = 4, ; unsinged rational = 5, undefined = 7, signed long = 9, signed rational = 10 ; Related .......: _GDIPlus_ImageGetPropertyIdList ; Link ..........: https://msdn.microsoft.com/en-us/library/windows/desktop/ms535390(v=vs.85).aspx, ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms534493(v=vs.85).aspx, ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms534414(v=vs.85).aspx ; Example .......: Yes ; =============================================================================================================================== Func cGDIPlus_ImageGetPropertyItem($hImage, $iPropID) Local $iSize = __GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID) If @error Then Return SetError(@error, @extended, -1) Local $tBuffer = DllStructCreate("byte[" & $iSize & "];") Local $pBuffer = DllStructGetPtr($tBuffer) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetPropertyItem", "handle", $hImage, "uint", _ $iPropID, "uint", $iSize, "struct*", $tBuffer) If @error Then Return SetError(@error, @extended, -1) If $aResult[0] Then Return SetError(10, $aResult[0], False) Local $tPropertyItem = DllStructCreate("int id; int length; short type; ptr pvalue;", $pBuffer) Local $iBytes = DllStructGetData($tPropertyItem, "length") Local $pValue = DllStructGetData($tPropertyItem, "pvalue") Local $aRet[4] Local $type = DllStructGetData($tPropertyItem,'type') Local $tValues, $iValues Switch $type Case 2 ;ASCII String $iValues = 1 $tValues = DllStructCreate("char[" & $iBytes & "];", $pValue) Case 3 ;Array of UShort $iValues = Int($iBytes / 2) $tValues = DllStructCreate("ushort[" & $iValues & "];", $pValue) Case 4, 5 ;Array of UInt / Fraction $iValues = Int($iBytes / 4) $tValues = DllStructCreate("uint[" & $iValues & "];", $pValue) Case 9, 10 ;Array of Int / Fraction $iValues = Int($iBytes / 4) $tValues = DllStructCreate("int[" & $iValues & "];", $pValue) Case Else ;Array of Bytes $iValues = 1 $tValues = DllStructCreate("byte[" & $iBytes & "];", $pValue) EndSwitch $aRet[0] = DllStructGetData($tPropertyItem,'id') $aRet[1] = $iBytes $aRet[2] = $type Local $aVals[$iValues] If $type=2 Or $type=7 Then ; ASCII string or undefined $aVals[0] = DllStructGetData($tValues,1) Else For $i = 0 To $iValues-1 $aVals[$i] = DllStructGetData($tValues,1,$i+1) Next EndIf $aRet[3] = $aVals Return $aRet EndFunc And here is an example:
      #include <GDIPlus.au3> #include <Array.au3> Example() Func Example() _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile(RegRead((@AutoItX64 = True ? "HKLM\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt" : "HKLM\SOFTWARE\AutoIt v3\AutoIt"), "InstallDir") & "\Examples\GUI\Torus.png") If @error Then _GDIPlus_Shutdown() MsgBox(16, "", "An error has occured - unable to load image!", 30) Return False EndIf Local $ar = _GDIPlus_ImageGetPropertyIdList($hImage) Local $vPropNbrs[UBound($ar,1)-1] ; Extract ID numbers For $i = 1 To UBound($ar,1)-1 $vPropNbrs[$i-1] = $ar[$i][0] Next ; Get all property items Local $aPropItems[UBound($vPropNbrs)][4],$vPropItem For $i = 0 To UBound($vPropNbrs)-1 $vPropItem = cGDIPlus_ImageGetPropertyItem($hImage,$vPropNbrs[$i]) For $j = 0 To 3 $aPropItems[$i][$j] = $vPropItem[$j] Next Next ; Collapse values arrays so _ArrayDisplay can display them Local $ar = $aPropItems For $i = 0 To UBound($aPropItems,1)-1 $ar[$i][0] = '0x'&Hex($ar[$i][0],4) $ar[$i][3] = '' For $j = 0 To UBound($aPropItems[$i][3])-1 $ar[$i][3] &= ($aPropItems[$i][3])[$j]&'|' Next $ar[$i][3] = StringTrimRight($ar[$i][3],1) Next _ArrayDisplay($ar) _GDIPlus_Shutdown() EndFunc Unfortunately this example (based on one now in the Help) does not exercise most of the item types, but I do not know of a file with EXIF metadata that is on most PCs. I have tested this code by updating and adding property items to torus.jpg and to a photo taken by a Sony camera. The code for implementing and calling _GDIPlus_ImageSetPropertyItem will be fairly simple [see below].
      Your thoughts?