Тема: AHK: Gdip_HBitmapFromScreen минуя окно
Моя задача взять центр экрана, увеличить и показать картинку в том же центре. Как я могу это сделать, чтобы мое окно было "невидимым" для "Gdip_HBitmapFromScreen"?
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Моя задача взять центр экрана, увеличить и показать картинку в том же центре. Как я могу это сделать, чтобы мое окно было "невидимым" для "Gdip_HBitmapFromScreen"?
А сначала получить bitmap, а потом показать окно не вариант?
Мне нужна картинка в реал тайме.
Phoenixxx_Czar
Вроде как Gdip позволяет такое организовать 'Gdip_BitmapFromHWND(hwnd)'.
Здесь где-то был пост malcev'а про magnifier (то же, что экранная лупа), думаю, это то, что надо.
__Михаил__, данный код выдает черный экран:
WinGet, hwnd, ID, A
pBitmap := Gdip_BitmapFromHWND(hwnd)
Насколько помню не все окна выйдет заскриншотить, скрипт запускать нужно от админа. Если найду пример - скину.
У меня отключен UAC, но скрипты все равно запускаются дополнительно от имени админа.
pToken := Gdip_Startup()
OnExit, Exit
X := 0, Y := 0 ; Позиция отображения.
hwnd := WinExist("ahk_Class Notepad") ; Окно по умолчанию, если нужно.
Return
;---------------------------
F3:: ; Выбрать текущее окно для отображения:
hwnd := WinExist("A")
Return
F2:: ; Вкл. / Выкл. отображение выбранного окна:
If !hwnd{
ToolTip, Окно не указано!
Return
}
If !(SW := !SW){
Gui Destroy
Return
}
GoSub, Show
Return
;-------------------------------------------------------------------------------------------------------
Show:
pBitmap := Gdip_BitmapFromHWND(hwnd)
Gdip_GetDimensions(pBitmap, w, h)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
Gui -SysMenu +AlwaysOnTop +ToolWindow -Caption
Gui Margin, 0, 0
Gui Add, Text, hWndPic w%w% h%h% +0xE
PostMessage, 0x172, 0, hBitmap,, ahk_id %Pic%
Gui, Show, % "NoActivate x" X " y" Y, [Testing]
Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
Return
Exit:
Gdip_Shutdown(pToken)
ExitApp
К сожалению на нужном окне черный экран.
Возможно инжект в окно или другие манипуляции смогут получить желаемое. Это уже вопрос к знатокам.
Проверьте, работает ли скрипт malcev'а с вашим окном.
Я думаю стоит тогда переместить тему в раздел с вопросами связанные с играми. Думал раз "Gdip_HBitmapFromScreen" может взять поверх игры, значит и другое функции без проблем, но видать глубоко ошибался.
Вот попробуйте, это для win8+ чтоб было поверх всех окон.
Не будет работать с полноэкранными directx и с окнами у которых установлен SetWindowDisplayAffinity.
x := 500
y := 500
w := 320
h := 240
Gui, +HWNDhGui +AlwaysOnTop
DllCall("GetWindowBand", "ptr", hGui, "uint*", band)
Gui, Destroy
hGui := ""
if (band = 1)
{
If (A_PtrSize = 8)
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyU64_UIA.exe" "%A_ScriptFullPath%"
Else If A_IsUnicode
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyU32_UIA.exe" "%A_ScriptFullPath%"
Else
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyA32_UIA.exe" "%A_ScriptFullPath%"
}
#SingleInstance Force
SetBatchLines -1
SetWinDelay -1
OnExit, Uninitialize
Gui, +HWNDhGui -DPIScale -Caption +AlwaysOnTop +E0x02000000 +E0x00080000 +E0x20 ; WS_EX_COMPOSITED := E0x02000000 WS_EX_LAYERED := E0x00080000
Gui, Show, x%x% y%y% w%w% h%h% NA
DllCall("LoadLibrary", "str", "magnification.dll")
DllCall("magnification.dll\MagInitialize")
hChildMagnifier := DllCall("CreateWindowEx", "UInt", 0, "Str", "Magnifier", "Str", "MagnifierWindow", "UInt", (WS_CHILD := 0x40000000)|(MS_INVERTCOLORS := 0x0004), "Int", 0, "Int", 0, "Int", w, "Int", h, "Ptr", hGui, "UInt", 0, "Ptr", DllCall("GetWindowLong" (A_PtrSize=8 ? "Ptr" : ""), "Ptr", hGui, "Int", GWL_HINSTANCE := -6 , "ptr"), "UInt", 0, "ptr")
WinShow, ahk_id %hChildMagnifier%
Loop
{
if (A_PtrSize = 8)
{
VarSetCapacity(RECT, 16, 0)
NumPut(x, RECT, 0, "Int")
NumPut(y, RECT, 4, "Int")
NumPut(w, RECT, 8, "Int")
NumPut(h, RECT, 12, "Int")
DllCall("magnification.dll\MagSetWindowSource", "Ptr", hChildMagnifier, "Ptr", &RECT)
}
else
DllCall("magnification.dll\MagSetWindowSource", "Ptr", hChildMagnifier, "Int", x, "Int", y, "Int", w, "Int", h)
}
Return
Uninitialize:
DllCall("magnification.dll\MagUninitialize")
ExitApp
Что-то такое появилось:
Значит работает.
Размер изменяется примерно так:
x := 500
y := 500
w := 320
h := 240
ScaleFactor := 2
Gui, +HWNDhGui +AlwaysOnTop
DllCall("GetWindowBand", "ptr", hGui, "uint*", band)
Gui, Destroy
hGui := ""
if (band = 1)
{
If (A_PtrSize = 8)
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyU64_UIA.exe" "%A_ScriptFullPath%"
Else If A_IsUnicode
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyU32_UIA.exe" "%A_ScriptFullPath%"
Else
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyA32_UIA.exe" "%A_ScriptFullPath%"
}
#SingleInstance Force
SetBatchLines -1
SetWinDelay -1
OnExit, Uninitialize
Gui, +HWNDhGui -DPIScale -Caption +AlwaysOnTop +E0x02000000 +E0x00080000 +E0x20 ; WS_EX_COMPOSITED := E0x02000000 WS_EX_LAYERED := E0x00080000
Gui, Margin, 0,0
Gui, Show, x%x% y%y% w%w% h%h% NA
DllCall("LoadLibrary", "str", "magnification.dll")
DllCall("magnification.dll\MagInitialize")
hChildMagnifier := DllCall("CreateWindowEx", "UInt", 0, "Str", "Magnifier", "Str", "MagnifierWindow", "UInt", (WS_CHILD := 0x40000000), "Int", 0, "Int", 0, "Int", w, "Int", h, "Ptr", hGui, "UInt", 0, "Ptr", DllCall("GetWindowLong" (A_PtrSize=8 ? "Ptr" : ""), "Ptr", hGui, "Int", GWL_HINSTANCE := -6 , "ptr"), "UInt", 0, "ptr")
Matrix := ScaleFactor "|0|0|"
. "0|" ScaleFactor "|0|"
. "0|0|1"
VarSetCapacity(MAGTRANSFORM, 36, 0)
Loop, Parse, Matrix, |
NumPut(A_LoopField, MAGTRANSFORM, (A_Index - 1) * 4, "Float")
DllCall("magnification.dll\MagSetWindowTransform", "Ptr", hChildMagnifier, "Ptr", &MAGTRANSFORM)
WinShow, ahk_id %hChildMagnifier%
Loop
{
if (A_PtrSize = 8)
{
VarSetCapacity(RECT, 16, 0)
NumPut(x, RECT, 0, "Int")
NumPut(y, RECT, 4, "Int")
NumPut(w, RECT, 8, "Int")
NumPut(h, RECT, 12, "Int")
DllCall("magnification.dll\MagSetWindowSource", "Ptr", hChildMagnifier, "Ptr", &RECT)
}
else
DllCall("magnification.dll\MagSetWindowSource", "Ptr", hChildMagnifier, "Int", x, "Int", y, "Int", w, "Int", h)
}
Return
Uninitialize:
DllCall("magnification.dll\MagUninitialize")
ExitApp
Подскажите, зачем эти строки?
if (band = 1)
{
If (A_PtrSize = 8)
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyU64_UIA.exe" "%A_ScriptFullPath%"
Else If A_IsUnicode
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyU32_UIA.exe" "%A_ScriptFullPath%"
Else
RunWait "C:\Program Files\AutoHotkey\AutoHotkeyA32_UIA.exe" "%A_ScriptFullPath%"
}
Чтобы было поверх всех окон.
https://blog.adeltax.com/window-z-order-in-windows-10/
Как обнаружил teadrinker запуск скрипта через AutoHotkey_UIA.exe with +AlwaysOnTop равносильно CreateWindowInBand with ZBID_UIACCESS.
Я закоментировал данные строки и все по прежнему работает.
У меня тут вопрос, я так понимаю обновляется оно в том вечном loop? Достаточно будет тот код вызывать по таймеру?
И тут еще такое дело.. Почему-то оно зумит со смещением:
Так же хотелось бы узнать, как можно поменять scale в real time.
Я закоментировал данные строки и все по прежнему работает.
Я дал вам ссылку, где описано, где работать не будет.
Достаточно будет тот код вызывать по таймеру?
Да.
Почему-то оно зумит со смещением:
Не знаю почему. Может в игре меняются координаты, протестируйте с обычной картинкой.
как можно поменять scale в real time.
MagSetWindowTransform
Я так понимаю оно увеличивает картинку, но отображает верхний левый угол, остальное вылазит за область, только вот как настроить можно, чтобы оно показывало центр?.. С матрицей игрался, но так и не надумал.
Кхм.. У меня получилось сместить картинку с помощью:
DllCall("magnification.dll\MagSetWindowSource", "Ptr", hChildMagnifier, "Int", x + 18, "Int", y + 18, "Int", w, "Int", h)
Но выглядит что-то очень костыльно, размеры w, h по 100, scale 1.5. Как высчитать теперь эти 18 не особо понимаю.
UPD:
Кажется до меня долшло..
w := 100
h := 100
ScaleFactor := 2
winX := (A_ScreenWidth / 2) - (w / 2)
winY := (A_ScreenHeight / 2) - (h / 2)
x := (A_ScreenWidth / 2) - ((w / 2) / ScaleFactor)
y := (A_ScreenHeight / 2) - ((h / 2) / ScaleFactor)
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться