is ahk possible to read d3 screen directly ? menu

These ads disappear when you log in.

Page 1 of 3 123 LastLast
Results 1 to 15 of 40
  1. #1
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)

    is ahk possible to read d3 screen directly ?

    the latest TH is disable the screen capture where ahk use the same/similar api for imagesearch function.


    my own wriiten lod mages and vyr wizard ahk script which use imagesearch to capture skill cooldown status

    These ads disappear when you log in.

  2. #2
    laurens362's Avatar Member CoreCoins User
    Reputation
    1
    Join Date
    Jun 2012
    Posts
    36
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Code or link?

  3. #3
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    solved.........using gdi+ to read d3 screen

  4. #4
    DeeThree's Avatar Member
    Reputation
    4
    Join Date
    Feb 2018
    Posts
    32
    Thanks G/R
    30/3
    Trade Feedback
    0 (0%)
    I'd like to continue your discussion from here:
    https://www.ownedcore.com/forums/dia...ml#post4071403 (Permanent closure of the plugin API and the removal of China/Asia realm support)

    In exchange for some help with an image based rotation such as you are using.

    What I found was that Gdip_BitmapFromHWND forces you to capture the whole window simply because that is what they programmed it to do. Comparing the code with Gdip_BitmapFromScreen showed it was nearly the same except they left out all x|y|w|h stuff.

    Another oddity is there are multiple Gdip_All.ahk versions from different maintainers. The one that seemed to be the most up to date is GitHub - marius-sucan/AHK-GDIp-Library-Compilation: Gdip_All library mega-compilation of user contributions, compatible with AHK v1.1 and AHK v2 which is missing Gdip_ImageSearch for some reason. I just used a standalone version of that.

    The original Gdip_BitmapFromHWND looks like this:

    Code:
    ;#####################################################################################
    
    ; Function           Gdip_BitmapFromHWND
    ; Description        Uses PrintWindow to get a handle to the specified window and return a bitmap from it
    ;
    ; hwnd               handle to the window to get a bitmap from
    ; return             If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;
    ; notes              Window must not be not minimised in order to get a handle to it's client area
    
    Gdip_BitmapFromHWND(hwnd) {
       Ptr := A_PtrSize ? "UPtr" : "UInt"
       GetWindowRect(hwnd, Width, Height)
       hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
       PrintWindow(hwnd, hdc)
       pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
       SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
       return pBitmap
    }
    
    ;#####################################################################################
    I simply changed it to this:

    Code:
    ;#####################################################################################
    
    ; Function           Gdip_BitmapFromHWND
    ; Description        Uses PrintWindow to get a handle to the specified window and return a bitmap from it
    ;
    ; hwnd               handle to the window to get a bitmap from
    ; Screen          0 = All screens
    ;                 Any numerical value = Just that screen
    ;                 x|y|w|h = Take specific coordinates with a width and height
    ; Raster          raster operation code
    ;
    ; return          If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;                 -1: one or more of x,y,w,h parameters were not passed properly
    ;
    ; return             If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;
    ; notes              Window must not be not minimised in order to get a handle to it's client area
    
    Gdip_BitmapFromHWND(hwnd, Screen:=0, Raster:="") {
       hhdc := 0
       Ptr := A_PtrSize ? "UPtr" : "UInt"
       if (Screen = 0)
       {
          _x := DllCall("GetSystemMetrics", "Int", 76 )
          _y := DllCall("GetSystemMetrics", "Int", 77 )
          _w := DllCall("GetSystemMetrics", "Int", 78 )
          _h := DllCall("GetSystemMetrics", "Int", 79 )
       }
       else if (SubStr(Screen, 1, 5) = "hwnd:")
       {
          Screen := SubStr(Screen, 6)
          if !WinExist("ahk_id " Screen)
             return -2
    
          GetWindowRect(Screen, _w, _h)
          _x := _y := 0
          hhdc := GetDCEx(Screen, 3)
       }
       else if IsInteger(Screen)
       {
          M := GetMonitorInfo(Screen)
          _x := M.Left, _y := M.Top, _w := M.Right-M.Left, _h := M.Bottom-M.Top
       }
       else
       {
          S := StrSplit(Screen, "|")
          _x := S[1], _y := S[2], _w := S[3], _h := S[4]
       }
    
       if (_x = "") || (_y = "") || (_w = "") || (_h = "")
          return -1
    
       chdc := CreateCompatibleDC(), hbm := CreateDIBSection(_w, _h, chdc)
       obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
       BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster)
       ReleaseDC(hhdc)
    
       pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
       SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
       return pBitmap
    }
    
    
    ;#####################################################################################
    I then adapted the screenshot ahk from the other thread to use the new method and was able to clip the entire skill bar instead of the whole screen:

    Code:
    #NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
    ; #Warn  ; Enable warnings to assist with detecting common errors.
    SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
    SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
    
    #Include GDIP_All.ahk
    
    Screenshot(outfile, screen)
    {
    	pToken := Gdip_Startup()
        hwnd := WinExist("ahk_exe Diablo III64.exe")  ;;; D3 64 bit client
    	pBitmap := Gdip_BitmapFromHWND(hwnd, "350|425|200|100")
    	Gdip_SaveBitmapToFile(pBitmap, outfile, 100)
    	Gdip_DisposeImage(pBitmap)
    	Gdip_Shutdown(pToken)
    }
    
    !F5:: ;;ALT-F5
    Screenshot(A_ScriptDir "\Screenshot_\" A_Now ".png") 
    
    ; screen: X|Y|W|H
    Return
    *note you may need to create the Screenshot_ folder in your script directory first

    20191027184832.png20191027184552.png
    Last edited by DeeThree; 10-30-2019 at 10:24 PM.

  5. Thanks takayo72, johnbl (2 members gave Thanks to DeeThree for this useful post)
  6. #5
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    Dee.......many thanks~~~~~~~~~

    I will make a test with ur modification of code of that function call


    The _all.ahk version is worked for both ahk 32 and 64bit while gdip.ahk is worked for 32bit only

    Edit: The Gdip_BitmapFromHWND function is not working. When turbohud enabled, a black screen captured.
    Meaning that, it is not using the game hwnd handle to retrieve screen bitmap info
    Last edited by takayo72; 10-31-2019 at 05:58 PM.

  7. #6
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    I am curious about these several if statments.

    There is code statement to deal with the new function argument hwnd. That's Gdip_BitmapFromHWND is still using printscreen to capture screen as of Gdip_BitmapFromScreen

    Code:
    if (Screen = 0)
       {
          _x := DllCall("GetSystemMetrics", "Int", 76 )
          _y := DllCall("GetSystemMetrics", "Int", 77 )
          _w := DllCall("GetSystemMetrics", "Int", 78 )
          _h := DllCall("GetSystemMetrics", "Int", 79 )
       }
       else if (SubStr(Screen, 1, 5) = "hwnd:")
       {
          Screen := SubStr(Screen, 6)
          if !WinExist("ahk_id " Screen)
             return -2
    
          GetWindowRect(Screen, _w, _h)
          _x := _y := 0
          hhdc := GetDCEx(Screen, 3)
       }
    This is a string text, not the hwnd function parameter
    Code:
    if (SubStr(Screen, 1, 5) = "hwnd:")


    As of reading these code segment. I'm thinking of if hwnd is passed to that function,
    we need few more code to game window ahk_id from hwnd handle

    These code segment use ahk_id to get the screen
    Code:
    else if (SubStr(Screen, 1, 5) = "hwnd:")
       {
          Screen := SubStr(Screen, 6)
          if !WinExist("ahk_id " Screen)
             return -2
    
          GetWindowRect(Screen, _w, _h)
          _x := _y := 0
          hhdc := GetDCEx(Screen, 3)
       }
    Last edited by takayo72; 10-31-2019 at 06:24 PM.

  8. Thanks DeeThree (1 members gave Thanks to takayo72 for this useful post)
  9. #7
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    After a few testing, i ensured that Gdip_BitmapFromScreen is not just add a hwnd arugment to handle window handle

  10. #8
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    After studying the function, here is working Gdip_BitmapFromHWND function support selection area capture same as Gdip_BitmapFromScreen.
    At least the screenshot test ahk is working

    I added following code segment
    Code:
       if (hwnd <> "")
       { 
          hwnd_id := hwnd
          if !WinExist("ahk_id " hwnd_id)
            return -2
        
          hhdc := GetDCEx(hwnd_id, 3)
    
          S := StrSplit(Screen, "|")
          _x := S[1], _y := S[2], _w := S[3], _h := S[4]
       } else

    Full code
    Code:
    ;#####################################################################################
    
    ; Function           Gdip_BitmapFromHWND
    ; Description        Uses PrintWindow to get a handle to the specified window and return a bitmap from it
    ;
    ; hwnd               handle to the window to get a bitmap from
    ; Screen          0 = All screens
    ;                 Any numerical value = Just that screen
    ;                 x|y|w|h = Take specific coordinates with a width and height
    ; Raster          raster operation code
    ;
    ; return          If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;                 -1: one or more of x,y,w,h parameters were not passed properly
    ;
    ; return             If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;
    ; notes              Window must not be not minimised in order to get a handle to it's client area
    
    Gdip_BitmapFromHWND(hwnd:="", Screen:=0, Raster:="") {
    
       hhdc := 0
       Ptr := A_PtrSize ? "UPtr" : "UInt"
       if (hwnd <> "")
       { 
          hwnd_id := hwnd
          if !WinExist("ahk_id " hwnd_id)
            return -2
        
          hhdc := GetDCEx(hwnd_id, 3)
    
          S := StrSplit(Screen, "|")
          _x := S[1], _y := S[2], _w := S[3], _h := S[4]
       } else if (Screen = 0)
       { 
          _x := DllCall("GetSystemMetrics", "Int", 76 )
          _y := DllCall("GetSystemMetrics", "Int", 77 )
          _w := DllCall("GetSystemMetrics", "Int", 78 )
          _h := DllCall("GetSystemMetrics", "Int", 79 )
       }
       else if (SubStr(Screen, 1, 5) = "hwnd:")
       { 
          Screen := SubStr(Screen, 6)
          if !WinExist("ahk_id " Screen)
             return -2
    
          GetWindowRect(Screen, _w, _h)
          _x := _y := 0
          hhdc := GetDCEx(Screen, 3)
       }
       else if IsInteger(Screen)
       { 
          M := GetMonitorInfo(Screen)
          _x := M.Left, _y := M.Top, _w := M.Right-M.Left, _h := M.Bottom-M.Top
       }
       else
       { 
          S := StrSplit(Screen, "|")
          _x := S[1], _y := S[2], _w := S[3], _h := S[4]
       }
    
       if (_x = "") || (_y = "") || (_w = "") || (_h = "")
          return -1
    
       chdc := CreateCompatibleDC(), hbm := CreateDIBSection(_w, _h, chdc)
       obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
       BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster)
       ReleaseDC(hhdc)
    
       pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
       SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
       return pBitmap
    }
    
    
    ;#####################################################################################
    I maynot check for some conditions, so the code may have bugs

    Next i can go for frame rate test on gameplay
    I will post the result
    Last edited by takayo72; 10-31-2019 at 07:40 PM.

  11. Thanks DeeThree (1 members gave Thanks to takayo72 for this useful post)
  12. #9
    DeeThree's Avatar Member
    Reputation
    4
    Join Date
    Feb 2018
    Posts
    32
    Thanks G/R
    30/3
    Trade Feedback
    0 (0%)
    Excellent work! Tested again with D3 and THUD running (embarrassed I skipped that...) and it grabbed the cropped image of the skill bar as expected.

  13. #10
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    I have been tested in game play thoroughly, no more frame rate dropped

    I'm wondering the code can go further optimization, some of the code is not necessary

  14. #11
    JarJarD3's Avatar Contributor CoreCoins User
    Reputation
    96
    Join Date
    Oct 2017
    Posts
    394
    Thanks G/R
    41/92
    Trade Feedback
    0 (0%)
    Originally Posted by takayo72 View Post
    I have been tested in game play thoroughly, no more frame rate dropped

    I'm wondering the code can go further optimization, some of the code is not necessary
    You don't need to be faster than frame rate and using BitBlt should grant you enough time to do all image processing you need.
    I'm using C# and do initial gdi32.BitBlt from the whole screen and then Bitmap.Clone to copy buttons and other interesting portions of screen to individual bitmaps to processing (comparing them etc.).
    I can do about thousand BitBlt per sec and hundreds of thousands of image comparisons per sec.

    But you could take systems calls like GetSystemMetrics and GetMonitorInfo out of your inner loop and just calculate those results once.
    They will never change.

  15. #12
    takayo72's Avatar Member CoreCoins User
    Reputation
    12
    Join Date
    Jan 2018
    Posts
    134
    Thanks G/R
    21/11
    Trade Feedback
    0 (0%)
    optimized code which can capture whole window screen or specify the capture area by x|y|w|h
    Code:
    ;#####################################################################################
    
    ; Function           Gdip_BitmapFromHWND2
    ; Description        Uses PrintWindow to get a handle to the specified window and return a bitmap from it
    ;
    ; hwnd               handle to the window to get a bitmap from
    ; Screen          0 = whole screen
    ;                 x|y|w|h = Take specific coordinates with a width and height
    ; Raster          raster operation code
    ;
    ; return          If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;                 -1: one or more of x,y,w,h parameters were not passed properly
    ;
    ; return             If the function succeeds, the return value is a pointer to a gdi+ bitmap
    ;
    ; notes              Window must not be not minimised in order to get a handle to it's client area
    
    Gdip_BitmapFromHWND2(hwnd:="", Screen:=0, Raster:="") {
       hhdc := 0
       Ptr := A_PtrSize ? "UPtr" : "UInt"
       if (hwnd <> "")
       {
          hwnd_id := hwnd
          if !WinExist("ahk_id " hwnd_id)
            return -2
    
          if (Screen = 0)
          { 
              GetWindowRect(hwnd_id, _w, _h)
              _x := _y := 0
              hhdc := GetDCEx(hwnd_id, 3)
          } else {
                hhdc := GetDCEx(hwnd_id, 3)
                S := StrSplit(Screen, "|")
                _x := S[1], _y := S[2], _w := S[3], _h := S[4]
          }
       }
    
       chdc := CreateCompatibleDC(), hbm := CreateDIBSection(_w, _h, chdc)
       obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
       BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster)
       ReleaseDC(hhdc)
    
       pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
       SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
       return pBitmap
    }

  16. Thanks DeeThree, johnbl (2 members gave Thanks to takayo72 for this useful post)
  17. #13
    DeeThree's Avatar Member
    Reputation
    4
    Join Date
    Feb 2018
    Posts
    32
    Thanks G/R
    30/3
    Trade Feedback
    0 (0%)
    Hate to ask but can you give some details on how you made your imagesearch macro work? :
    https://www.ownedcore.com/forums/dia...ml#post4071348 (Permanent closure of the plugin API and the removal of China/Asia realm support)

    Code:
    global gdipToken := Gdip_Startup()
    , hwnd := WinExist("ahk_exe Diablo III64.exe")
    , ArchonImage = Archon.png // part of archon skill image in the the skill bar
    
    gameBitmap := Gdip_BitmapFromHWND(hwnd) // d3 game screen
    skillBitmap := Gdip_CreateBitmapFromFile(ArchonImage) // 
    
    // similar as ahk builtin imagesearch 
    // where var1,var2,var3,var4 is the search area of a image (d3 screen)
    // 30 is variation
    vRet := Gdip_ImageSearch(gameBitmap, skillBitmap, vPosXY, Var1, Var2, Var3, Var4, 30)   
    
    
    if vRet = 1 {
    ; found do something
    } else if vRet=0 {
    ; not found do otherthing
    }
    I am not finding good information on how to use gdip_imagesearch in a macro for a game, and not enough in that snippet for me to extrapolate it out. Help would be appreciated, Thanks!

  18. #14
    johnbl's Avatar Member CoreCoins User
    Reputation
    13
    Join Date
    Dec 2016
    Posts
    118
    Thanks G/R
    314/12
    Trade Feedback
    0 (0%)
    Here's a snippet from my script:
    Code:
    KeyLoop:
    	While _RunFlag {
    		If WinActive("ahk_class D3 Main Window Class") {
    			bmpHaystack := Gdip_BitmapFromHWNDCropped(d3hwnd, _x "|" _y "|" _w "|" _h)
    			sready := Gdip_ImageSearch(bmpHaystack,vengeanceNeedle,LIST,0,0,0,0,0,0xFFFFFF,1,0)
    			if (sready == 1) {
    				Send %Key3%
    			}
    			sready := Gdip_ImageSearch(bmpHaystack,companionNeedle,LIST,0,0,0,0,0,0xFFFFFF,1,0)
    			if (sready == 1) {
    				Send %Key4%
    			}
    			Gdip_DisposeImage(bmpHaystack)
    			
    			RandomSleep(40, 125)			
    		}
    	}
    Return
    The needles were previously defined:
    Code:
    vengeanceNeedle := Gdip_CreateBitmapFromFile("IMG/vengeance.bmp")
    companionNeedle := Gdip_CreateBitmapFromFile("IMG/companion.bmp")

  19. Thanks DeeThree (1 members gave Thanks to johnbl for this useful post)
  20. #15
    johnbl's Avatar Member CoreCoins User
    Reputation
    13
    Join Date
    Dec 2016
    Posts
    118
    Thanks G/R
    314/12
    Trade Feedback
    0 (0%)
    I'm also using a simpler function than takayo72:
    Code:
    Gdip_BitmapFromHWNDCropped(hwnd, Screen) {
    	Raster := ""
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	hhdc := GetDCEx(hwnd, 3)
    	S := StrSplit(Screen, "|")
    	_x := S[1], _y := S[2], _w := S[3], _h := S[4]
    
    
    	chdc := CreateCompatibleDC(), hbm := CreateDIBSection(_w, _h, chdc)
    	obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
    	BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster)
    	ReleaseDC(hhdc)
    
    	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
    	SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
    	return pBitmap
    }

  21. Thanks DeeThree (1 members gave Thanks to johnbl for this useful post)
Page 1 of 3 123 LastLast

Similar Threads

  1. Is it possible to get account back
    By asrstech in forum World of Warcraft General
    Replies: 11
    Last Post: 01-07-2007, 09:15 PM
  2. is it possible to...
    By qwert in forum WoW ME Questions and Requests
    Replies: 2
    Last Post: 11-21-2006, 08:36 PM
  3. Is it possible to change mount into Druid form?
    By Vincent in forum WoW ME Questions and Requests
    Replies: 3
    Last Post: 11-11-2006, 08:56 PM
  4. Is it possible to add weapon sounds to model changes?
    By sparrow in forum WoW ME Questions and Requests
    Replies: 3
    Last Post: 10-11-2006, 01:42 PM
  5. Is it possible to set up glider to only pick up certain fish?
    By RichyG in forum World of Warcraft General
    Replies: 1
    Last Post: 07-15-2006, 06:36 PM
All times are GMT -5. The time now is 04:21 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2020 vBulletin Solutions, Inc. All rights reserved. Digital Point modules: Sphinx-based search