Re: AHK: Экранная лупа
Ну да.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Ну да.
Ещё можно тень "размазать", наложив несколько раз подряд, сдвигая на 1 px.
Как то видел окно которое не было видно в GetDC, то есть лупа смотрела сквозь него, и изображение под ним обновлялось, никто не знает что за стили могут быть у таких окон?
Не думаю, что здесь есть какие-то стили.
Возможно directx окно.
По смутным воспоминаниям какое то OSD из ахк скрипта. На GDI возможно вывести окно вне контекста рабочего стола? Хочу заблюрить кусок экрана, и обновлять blur исходя из того что под ним.
Я знаю, как можно черный экран сделать вместо получения изображения через
setwindowdisplayaffinity, но как прозрачный не копался. Возможно есть какие-то флаги. А чего ты добиться хочешь, я так и не понял.
setwindowdisplayaffinity
Спасибо, гляну.
Хочу размыть область экрана, blur эффект (гауссово размытие), но экран может измениться, а чтобы отобразить это изменение надо скрыть окно с блюром, чтобы узнать что на экране.
Думаю такое можно сделать 2 способами. Через gdi, но захватывая все видимые окна по очереди и отрисовывая их. Либо делая скриншот через апи лупы. Там есть такая функция, но это придется самому реализовывать. Еще можно попробовать сделать скриншот через gdi и если лупы видно не будет, то можно на окно лупы накладывать blur через dwm api.
DEL
setwindowdisplayaffinity
Там только один флаг.
Через gdi, но захватывая все видимые окна по очереди и отрисовывая их.
Ну это жесть, там надо ещё Z-Order вычислять, чтобы знать какое на какое наложено, а PrintWindow не со всеми окнами дружит.
Либо делая скриншот через апи лупы
Да, кажется это была лупа, но сейчас не могу найти рабочий пример, этот берёт картинку только на х64 и далее не обновляет, кушая процессор.
#NoEnv
#Persistent
#SingleInstance Force
OnExit, Uninitialize
SetBatchLines, -1
Gui, +E0x80000
Gui, +AlwaysOnTop -Caption
Gui,Show,w320 h240, MagnifierWindowAHK
Gui,+LastFound
WinGet,guiHwnd,Id
WinSet, Transparent, 255
hInstance := DllCall("GetWindowLong"
, "UInt", guiHwnd
, "UInt", GWL_HINSTANCE:=-6)
DllCall("LoadLibrary", "str", "magnification.dll")
DllCall("magnification.dll\MagInitialize")
WS_CHILD := 0x40000000
WS_VISIBLE := 0x10000000
MS_SHOWMAGNIFIEDCURSOR := 0x1
magHwnd := DllCall("CreateWindowEx"
, "UInt", 0
, "Str", "Magnifier"
, "Str", "MagnifierWindow"
, "UInt", WS_CHILD | MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE
, "Int", 0
, "Int", 0
, "Int", 320
, "Int", 240
, "UInt", guiHwnd
, "UInt", 0
, "UInt", hInstance
, "UInt", 0)
; Magnification transform matrix
Matrix := "1|0|0|"
. "0|1|0|"
. "0|0|1"
StringSplit, Matrix, Matrix, |
VarSetCapacity(magMatrix, 36, 0)
Loop, 9
{
NumPut(Matrix, magMatrix, (A_Index-1)*4, "float")
}
DllCall("magnification.dll\MagSetWindowTransform"
, "UInt", magHwnd
, "UInt", &magMatrix)
loop
DllCall("magnification.dll\MagSetWindowSource"
, "UInt", magHwnd
, "Int", -110
, "Int", 110
, "Int", 320
, "Int", 240)
return
Escape::
GuiEscape:
GuiClose:
Uninitialize:
Gui, Destroy
DllCall("magnification.dll\MagUninitialize")
ExitApp
там надо ещё Z-Order вычислять
Не надо.
https://autohotkey.com/docs/commands/WinGet.htm#List
сейчас не могу найти рабочий пример
Пример для взятия скриншота:
https://www.codeproject.com/Articles/60 … on-library
Враппер апи лупы на автоит:
https://www.autoitscript.com/forum/topi … ipulation/
Не надо.
Как не надо, надо же всё равно смотреть какое выше, координаты чтобы края видимых за ним знать, и WinGet List всех окон это долго.
Пример для взятия скриншота
В общем на АНК ничего нет.
надо же всё равно смотреть какое выше
WinGet list возвращает их в порядке z-order.
Вообщем на АНК ничего нет
Переведи с автоит.
Там вызовы dllcall практически идентичны.
Прошу не писать "вобщем" и "вообщем".
Исправил.
WinGet list возвращает их в порядке z-order.
Знаю, но это же всё равно долго.
Там вызовы dllcall практически идентичны.
Попробую.
Пример для взятия скриншота:
Это совсем тяжело, а в чём примерно отличие от DllCall("GetDC", "UPtr", 0, "UPtr")?
Отличие в том, что есть возможность внести в список окна, которые не надо захватывать:
https://docs.microsoft.com/en-us/window … filterlist
Да, кажется это была лупа, но сейчас не могу найти рабочий пример, этот берёт картинку только на х64 и далее не обновляет, кушая процессор.
Для ahk64 бит функцию MagSetWindowSource надо вызывать так:
VarSetCapacity(rect, 16, 0)
NumPut(-110, rect, 0, "int")
NumPut(110, rect, 4, "int")
NumPut(320, rect, 8, "int")
NumPut(240, rect, 12, "int")
loop
{
DllCall("magnification.dll\MagSetWindowSource", "ptr", magHwnd, ptr, &rect)
sleep 50
}
Если требуется передавать в вызове копию структуры, то есть свои правила.
Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed as if they were integers of the same size. Structs or unions of other sizes are passed as a pointer to memory allocated by the caller.
So indeed, struct S {int;int;} must be passed as int64 for x64 calling convention, and it can be for cdecl too. But struct S2 {char c1;short s;char c2;} would need to be passed as "ptr", &S2 for x64. But, for cdecl, S2 would be passed as "int64", c1 | (s << 16) | (c2 << 32), you cannot do "char", c1, "short", s, "char", c2. Finally struct d {double; double; ... double;} must be passed as "ptr", &d for x64 and "double", d1, ..., "double", dn for cdecl.
Для ahk64 бит функцию MagSetWindowSource надо вызывать так:
Работает! А на х32 это возможно запускать?
Если требуется передавать в вызове копию структуры
А зачем это может понадобится?
Не пойму, всё что надо это вроде как правильно вызвать:
DllCall("magnification\MagSetWindowFilterList","Ptr",magHwnd,"Int",0,"Int",1,"Ptr*",guiHwnd)
может в "Ptr*" надо как то по другому передавать.
А на х32 это возможно запускать?
На x32 должен работать твой код из 110 поста.
Но в udf пишут:
; Built-In Windows Magnification API (since Windows Vista)
;
; NOTE: TRY to run this at the same bit-mode your O/S is running in, as the GUI can be funky at times
; when run in an incompatible bit mode. So for 64-bit O/S's, run this as x64 only!
Не знаю так оно или нет - я не копался.
А зачем это может понадобится?
Это надо спрашивать у авторов библиотеки.
Не пойму, всё что надо это вроде как правильно вызвать:
Не понимаю, что ты хочешь добиться, но если сделать принтскрин через апи лупы, то возможно придется поплясать с бубном, так как MagImageScalingCallback() - устарела и может по каким-то причинам не пойти, а аналогов у нее нету.
Copy of structure vs pointer:
https://flaviocopes.com/golang-methods-receivers/
https://github.com/golang/go/wiki/CodeR … eiver-type
Copy of structure vs pointer:
Это для меня дебри, я даже не понял к чему ты это привёл.
Не понимаю, что ты хочешь добиться, но если сделать принтскрин через апи лупы, то возможно придется поплясать с бубном, так как MagImageScalingCallback() - устарела и может по каким-то причинам не пойти, а аналогов у нее нету.
А зачем нужна MagImageScalingCallback?
С MagSetWindowFilterList разобрался. То есть теперь мне надо запустить окно лупы скрыто, запустить окно с блюром, добавить его в исключения и как то выуживать битмап из лупы которая показывает в скрытом окне экран в тех же координатах что и окно с блюром.
Не знаю так оно или нет - я не копался.
Иногда запускается под х32.
Это для меня дебри, я даже не понял к чему ты это привёл.
Ты же спрашивал почему авторы функции MagSetWindowSource требуют чтобы им отправляли копию структуры, а не указатель на структуру.
Наверное, это происходит из-за каких-то причин описываемых по этим ссылкам.
Не совсем понял твой алгоритм.
Я изначально предполагал 2 алгоритма.
Первый:
1) Создать прозрачное окно с лупой
2) Брать снимок через Gdi
3) Анализировать этот снимок
4) По результатам анализа делать размытие через wdm на окно с лупой.
Если первый чем-то не подходит, то второй:
1) Создать прозрачное окно Gdi
2) Создать прозрачное окно с лупой
3) Брать снимок через лупу, беря в исключения окно Gdi
4) Анализировать этот снимок
5) По результатам анализа делать размытие через gdi на окно с Gdi.
Для второго алгоритма нужен MagImageScalingCallback, иначе не достать информацию с снимка через лупу.
Если первый чем-то не подходит, то второй:
Я почти тоже самое и предложил, только не пойму почему у тебя оба окна должны быть прозрачные.
Gdi не прозрачный.
А чего не хочешь пойти по более легкому первому алгоритму?
1) Создать прозрачное окно с лупой
2) Брать снимок через Gdi
3) Анализировать этот снимок
4) По результатам анализа делать размытие через wdm на окно с лупой.
Мне это не понятно.
Точнее первое теперь не понятно, ни GetDC ни PrintWindow не получают данные из magnification.
А тебе нужно данные именно из magnification?
Я так понял, что ты просто хочешь размывать участки экрана в зависимости от его контента.
Участок экрана закрыт окном GDI с размытием, нужно получить картинку под ним, чтобы обновить размытие. Чтобы узнать что под ним, надо воспользоватся лупой не беря окно с размытием.
Я так понял, что ты просто хочешь размывать участки экрана в зависимости от его контента.
Ну да.
Так размывай окно с лупой, а картинку получай через gdi.
Это как?
Мне на это дело сверху ещё надо кучу своих картинок кинуть уже без размытия.
EnableBlurBehindWindow это наверное не то размытие, я не нашёл там параметра глубины.
Это стандартное размытие, которое использует виндовс без дополнительных настроек.
Но тебе видно придется-таки получать CreateCompatibleDC из колбека.
нужен MagImageScalingCallback, иначе не достать информацию с снимка через лупу.
С такими примечаниями, не хочется.
А почему ты так уверен, что не может быть других вариантов?
Я других не знаю. Да и вообще программ с таким функционалом ни разу не встречал.
Я других не знаю
Просто интересно чем это окно так отличается, если в других можно получить картинку из DC, а тут нет.
О, с выключенным аеро картинка есть.
И без аеро каким то чудом определяется задний фон.
И по краям появляются артефакты. (
#SingleInstance, Force
#NoEnv
SetBatchLines, -1
CoordMode, Mouse
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
Gui, -Caption +E0x80000 +AlwaysOnTop +ToolWindow +OwnDialogs +E0x08000000 +HWNDhGui ; +E0x20
Gui Show, NA, test
x:= 505
y:= 505
w:= 600
h:= 600
xv := 400
yv := 200
Blur := 22
hdcSrc := GetDCEx(0)
hdcDest := CreateCompatibleDC()
GoTo Update
1::
Update:
; Gui, hide
; KeyWait, 1
hBitmap := CreateDIBSection(w, h, hdcDest)
SelectObject(hdcDest, hBitmap)
StretchBlt(hdcDest, 0, 0, w, h, hdcSrc, xv, yv, w, h)
pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap)
DeleteObject(hBitmap)
pBlurBitmap := Gdip_BlurBitmap(pBitmap, Blur)
Gdip_DisposeImage(pBitmap)
G := Gdip_GraphicsFromHDC(hdcDest)
Gdip_DrawImage(G, pBlurBitmap, 0, 0, w, h, 0, 0, w, h)
Gdip_DisposeImage(pBlurBitmap)
Gdip_DeleteGraphics(G)
UpdateLayeredWindow(hGui, hdcDest, xv, yv, w, h)
Gui, Show, NA
Return
esc::
Exit:
DeleteDC(hdcSrc)
DeleteDC(hdcDest)
Gdip_Shutdown(pToken)
ExitApp
У меня при включенном аэро (win7 x64 ahk 64 bit) и при adjust for best appearance в настройках perfomance при нажатии пригтскрин окно лупы копируется в клипбоард.
Если к окну лупы применить MagSetWindowFilterList с хендлом на какое-либо окно, то это окно в лупе показываться не будет и соответственно в буфере обмена тоже.
То что лупа может исключать окна мы разобрались, а буфер обмена что даёт?
DC рабочего стола даёт картинку лупы при любых раскладах, это сразу было известно.
Ну во-первых не при любых раскладах. А во-вторых если мы можем получить снимок лупы, то следовательно мы можем получить снимок без размытого окна. Разве не это твоя цель?
Ну во-первых не при любых раскладах.
А что может быть?
А во-вторых если мы можем получить снимок лупы, то следовательно мы можем получить снимок без размытого окна. Разве не это твоя цель?
Да, но как получить снимок лупы которой не должно быть видно на экране. Как он окажется в буфере, и чем пригтскрин отличается от DC всего экрана?
А что может быть?
Если выключим desktop composition, то в принтскрине лупы не будет.
Да, но как получить снимок лупы которой не должно быть видно на экране. Как он окажется в буфере, и чем пригтскрин отличается от DC всего экрана?
Там же всё пошагово расписано:
Пример для взятия скриншота:
https://www.codeproject.com/Articles/60 … on-library
Если выключим desktop composition, то в принтскрине лупы не будет.
Если выключим, то и лупа ненужна.
Там же всё пошагово расписано:
Так мы же обсуждали:
This is a simple way to take a screenshot using the powerful Magnification library. However there is a problem that is need to be solved. The MagImageScalingCallback() function is deprecated, and could be removed from newer versions of Windows. So we need to find another way to access the data. Currently I haven't not found any solution yet. If anyone could find anyway, please let me know.
Если выключим, то и лупа ненужна.
Почему?
Так мы же обсуждали:
Во всяком случае за 5 лет не убрали.
Ну а с семерки уж точно уже не уберут.
без аеро каким то чудом определяется задний фон.
В 140 код, попробуй обновлять на кл. 1.
Ну а с семерки уж точно уже не уберут.
Если делать, то уже с расчётом на 10.
В GetDCEx DCX_EXCLUDERGN может иметь отношение к теме?
Не знаю, но думаю вряд ли это поможет.
А зачем тебе вообще это надо?
Что за приложение ты делаешь в котором этот функционал необходим?
Да теперь просто стало любопытно, как получить скриншот без некоторых окон.
Походу только через Magnification API.
А для "наведения красоты" возможно достаточно такого примера:
gui, +hwndhwnd
Gui, color, 000001
gui, add, button, gExt,Toggle
gui, show, w300 h200, Glass
ext()
{
static toggle:=0
global hwnd
toggle:=!toggle
WinSet,TransColor, % toggle ? "000001" : "off", % "ahk_id " hwnd
Dwm_ExtendFrameIntoClientArea(hwnd,toggle?-1:0)
return
}
Dwm_ExtendFrameIntoClientArea(hwnd,l:=0,r:=0,t=0,b:=0)
{
; Extends the window frame into the client area.
; Input:
; hwnd, unique id to the window to which to extend window frame
; l,r,t,b is left, right top and bottom margins, respectively. Use negative to create "sheet of glass"-effect
; Output:
; hresult, error msg. 0 is ok!
; Notes:
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa969512(v=vs.85).aspx
; https://msdn.microsoft.com/en-us/library/windows/desktop/bb773244(v=vs.85).aspx (margins struct)
VarSetCapacity(margin,16,0)
NumPut(l,margin,0,"Int")
NumPut(r,margin,4,"Int")
NumPut(t,margin,8,"Int")
NumPut(b,margin,12,"Int")
hr:=DllCall("Dwmapi.dll\DwmExtendFrameIntoClientArea", "Uint", hwnd, "Uint", &margin)
return hr ; 0 is ok!
}
Dwm_EnableBlurBehindWindow(hwnd,onOff,x1:=0,y1:=0,x2:=0,y2:=0,fTransitionOnMaximized:=0)
{
;
; Enables the blur effect on a specified window.
; Input:
; hwnd, The handle to the window on which the blur behind data is applied.
; onOff, 1 to turn the effect on, 0 offset
; x1,...,y2, The region within the client area where the blur behind will be applied. Let be 0 to apply the blur behind on the entire client area.
; fTransitionOnMaximized, 1 if the window's colorization should transition to match the maximized windows; otherwise, 0.
; Output:
; hresult, error msg. 0 is ok!
; Url:
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa969508(v=vs.85).aspx - DwmEnableBlurBehindWindow function
;
; DWM_BLURBEHIND structure:
; Url:
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa969500(v=vs.85).aspx
; Create region
hrgn:=DllCall("Gdi32.dll\CreateRectRgn", "Int", x1, "Int", y1, "Int", x2, "Int", y2)
VarSetCapacity(DWM_BLURBEHIND,12+A_PtrSize,0)
NumPut(1|2|4,DWM_BLURBEHIND,0,"Uint") ; dwFlags
NumPut(onOff,DWM_BLURBEHIND,4,"Int") ; fEnable
NumPut(hrgn,DWM_BLURBEHIND,8,"Uint") ; hrgn
NumPut(fTransitionOnMaximized,DWM_BLURBEHIND,8+A_PtrSize,"Int") ; fTransitionOnMaximized
hr:= DllCall("Dwmapi.dll\DwmEnableBlurBehindWindow", "Uint", hwnd, "Uint", &DWM_BLURBEHIND)
DllCall("Gdi32.dll\DeleteObject", "Uint", hrgn) ; The region is not needed after the call.
return hr ; 0 is ok!
}
Без аеро не работает. Лучше уже обычное полупрозрачное.
Без аеро не работает
Ты ж на Win10 ориентируешься.
Кстати я ошибся, функционал не 5 лет не убирают, а уже скоро как 10.
озможно причина именно в:
получить скриншот без некоторых окон
И я погуглил, в некоторых разработках она до сих пор используется.
Надо будет попробовать, а у тебя получилось?
Я не пробовал - Visual Studio не установлена.
Мне такие примеры удобнее тестировать сначала на приведенном языке, так как мало ли вообще работать не будет, а ты будешь голову ломать, что не те/не там структуры или пойнтеры отправляешь/получаешь.
А тут всегда можно посмотреть полученный результат в функциях исходного примера и сравнить со своим.
Там нужен второй параметр void *srcdata?
Почему нужен? Ты же его получаешь.
А что в нём?
Пойнтер на битмап.
Непохоже, у меня с него картинки нет.
https://pt.stackoverflow.com/questions/ … api-magnif
Там что то с CreateDIBitmap.
https://autohotkey.com/board/topic/3423 … -gradient/
The srcdata parameter is the pointer to the bitmap source, and the srcheader contains the information of the captured image, so we can use these two parameters to create the BITMAPINFOHEADER and the BITMAPFILEHEADER.
Я читал, а если по русски.
Получаем ссылку на битмап и сам хедер.
Исходя из полученных данных создаем структуры BITMAPINFOHEADER и BITMAPFILEHEADER.
После чего переворачиваем горизонтально полученное изображение, соединяем всё это и получаем bmp.
Но это только выводы из прочитанного.
Я конечно же могу ошибаться, так как не C не C++ не знаю.
У нас на форуме в этом YMP дока.
На крайний случай можно будет на оф.форуме спросить, там точно есть сишники.
Кстати, смотри, что автор в комментах пишет:
https://www.codeproject.com/Articles/60 … x4590085xx
Ты про это - My conclusion is that MagSetImageScalingCallback function is deprecated in Windows 7 and later (32 Bits only).
Исходя из полученных данных создаем структуры BITMAPINFOHEADER и BITMAPFILEHEADER.
Да уж...
Про это:
вопрос
I have Windows7 32bit, VS2010 Professional. I copied your files and it compiled - 0 warnings or errors. Great work.
I do have a question, is there a function in the magnification library to resize the bitmap before it is saved?
ответ
Thank you for your question. The library has the SetMagnificationFactor() function that lets you to set the factor to the captured image. But unfortunately, the main purpose of this library is "magnifying things", not "capturing things" so you cannot set the factor less then 1.
So to resize the bitmap, I think you can perform these steps in the callback function:
1. Create a compatible device context from the magnification window
2. Create a compatible HBITMAP
3. Use the SetDIBits() function to set the bitmap data into the HBITMAP object
4. Create another device context and another HBITMAP object
5. Use the StretchBlt() function to zoom in or zoom out the first HBITMAP object into the second HBITMAP object
6. Then you can save the content of the second HBITMAP to file, as described in here[^]
Да уж...
Да не так уж там всё и сложно, наверное.
Нужно смотреть, что возвращает функция на c++ и пытаться получить тоже самое на ahk.
В примере на дельфи вроде всё понятно, но у меня самое простое не выходит
ToolTip % NumGet(srcheader, 0, "UInt" ) "х" NumGet(srcheader, 4, "UInt" )
MAGIMAGEHEADER structure тут же должны быть ширина и высота картинки - 320х240.
#NoEnv
#Persistent
#SingleInstance Force
OnExit, Uninitialize
DllCall("LoadLibrary", "str", "magnification.dll")
DllCall("magnification.dll\MagInitialize")
Gui, +AlwaysOnTop -Caption +toolwindow +HWNDhGui
Gui,Show, w320 h240 na, MagnifierWindowAHK
hInstance := DllCall("GetWindowLong"
, "Ptr", hGui
, "UInt", GWL_HINSTANCE:=-6)
WS_CHILD := 0x40000000
WS_VISIBLE := 0x10000000
MS_SHOWMAGNIFIEDCURSOR := 0x1
magHwnd := DllCall("CreateWindowEx"
, "UInt", 0
, "Str", "Magnifier"
, "Str", "MagnifierWindow"
, "UInt", MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE | WS_CHILD
, "Int", 0
, "Int", 0
, "Int", 320
, "Int", 240
, "Ptr", hGui
, "UInt", 0
, "Ptr", hInstance
, "UInt", 0)
DllCall("magnification.dll\MagSetImageScalingCallback"
, "Ptr", magHwnd
, "Int", RegisterCallback("MagImageScalingCallback", "Fast"))
VarSetCapacity(rect, 16, 0)
NumPut(0, rect, 0, "int")
NumPut(0, rect, 4, "int")
NumPut(320, rect, 8, "int")
NumPut(240, rect, 12, "int")
DllCall("magnification.dll\MagSetWindowSource", "ptr", magHwnd, ptr, &rect)
return
MagImageScalingCallback(hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) {
ToolTip % NumGet(srcheader, 0, "UInt" ) "`n" NumGet(srcheader, 4, "UInt" )
}
Escape::
Uninitialize:
DllCall("magnification.dll\MagUninitialize")
ExitApp
На x32 так:
ToolTip % srcheader "`n" destdata
На x64:
ToolTip % NumGet(srcheader+0, 0, "UInt" ) "х" NumGet(srcheader+0, 4, "UInt" )
Ух, тяжело.
На x32 так:
Это что получается, если какой то параметр является указателем на структуру, то каждая её часть превращается в отдельный параметр!?
На x64:
Зачем плюсовать ноль?
Перед твоим ответом ответом как раз читал RegisterCallback, но хоть убей не пойму как можно прийти к таким выводам.
На x32 так:
И это когда ос64, или на ос32 также?
И magnification.dll работает на ос32?
Зачем плюсовать ноль?
if the variable contains the target address; in that case, pass an expression such as MyVar+0.
https://autohotkey.com/docs/commands/NumGet.htm
Это что получается, если какой то параметр является указателем на структуру, то каждая её часть превращается в отдельный параметр!?
В принципе я сам не понимаю почему так происходит, так как в таком виде должна передаваться копия структуры.
На x32 я имел в виду версию ahk.
И magnification.dll работает на ос32?
А почему бы ей там не работать?
Вот тут мы обсуждали dllcall:
http://forum.script-coding.com/viewtopi … 83#p130683
На x32 я имел в виду версию ahk.
Я так тебя и понял, то есть анк32 на ос64. Если ос32, то получаем через NumGet?
А почему бы ей там не работать?
Так на ос64 из под анк32 почему не работаетсама лупа?
Если ос32, то получаем через NumGet?
Не понял вопроса.
Так на ос64 из под анк32 почему не работаетсама лупа?
Наверное потому, что на win x64 32-bit dll лупы не корректно работает.
Не понял вопроса.
На анк32 в ос64 параметр как структура не передаётся, в ос32 структура передаётся?
На анк32 в ос64 структура не передаётся,
Структура-то передается, только у меня в экране лупы отображается черный прямоугольник (либо проблема отображения, либо битмап пустой).
Структура-то передается
ToolTip % srcheader "`n" destdata
Так ведь не структура, а её части отдельными параметрами.
Отдельными параметрами должна передаваться копия структуры для x32 вызова.
Получается в ахк колбек передает копию структуры, а не ссылку на нее.
Хотя пишут, что:
If an incoming parameter is the address of a structure, the individual members may be extracted by following the steps at DllCall structures.
Можно на оффоруме спросить.
Так это как же тогда функцию расписывать надо, с кучей параметров, и
A function assigned to a callback address may accept up to 31 parameters
Надо на win32 проверить, может такое явление происходит из-за вызова 32битной длл на win64.
Я тоже так подумал.
Теперь надо создать переменную _info под структуру, как вычислить её размер?
Fillchar(_info, sizeof(_info), 0);
_info.bmiHeader.biSize:= sizeOf(TBitmapInfoHeader);
_info.bmiHeader.biWidth:= _srcheader.width;
_info.bmiHeader.biHeight:= -_srcheader.height;
_info.bmiHeader.biplanes:= 1;
_info.bmiHeader.biBitCount:= 32;
_info.bmiHeader.biCompression:= BI_RGB;
_bitmap:= 0;
_bitmap:= CreateDIBitmap(_DC, _info.bmiHeader, CBM_INIT, _srcdata, _info, DIB_RGB_COLORS);
Ну как берешь и считаешь.
https://www.autoitscript.com/autoit3/do … Create.htm
То есть структуру для CreateDIBitmap.
Это сплюсовать. CIEXYZTRIPLE не нашёл размер.
DWORD bV5Size;
LONG bV5Width;
LONG bV5Height;
WORD bV5Planes;
WORD bV5BitCount;
DWORD bV5Compression;
DWORD bV5SizeImage;
LONG bV5XPelsPerMeter;
LONG bV5YPelsPerMeter;
DWORD bV5ClrUsed;
DWORD bV5ClrImportant;
DWORD bV5RedMask;
DWORD bV5GreenMask;
DWORD bV5BlueMask;
DWORD bV5AlphaMask;
DWORD bV5CSType;
CIEXYZTRIPLE bV5Endpoints;
DWORD bV5GammaRed;
DWORD bV5GammaGreen;
DWORD bV5GammaBlue;
DWORD bV5Intent;
DWORD bV5ProfileData;
DWORD bV5ProfileSize;
DWORD bV5Reserved;
Это структура.
Ptr?
Или добавить размер этой структуры?
Со структурой всё правильно работает так как возвращается копия, а не ссылка.
srcheader
Type: MAGIMAGEHEADER
The description of the input format.
Надо считать сколько занимают ее члены.
Посчитаешь, можешь сравнить результат.
http://d3s.mff.cuni.cz/teaching/princip … 20Wiki.pdf
Так CIEXYZTRIPLE считать как указатель, или плюсовать её размер?
Со структурой всё правильно работает так как возвращается копия, а не ссылка.
Это на что ответ?
Надо считать сколько занимают ее члены.
Так мы же это и пытаемся сделать...
Посчитаешь, можешь сравнить результат.
Там BITMAPV5HEADER идёт последним, как понять сколько он занимает.
Если считать CIEXYZTRIPLE как Ptr, то 92.
def_Struct := "
(LTrim Join
DWORD bV5Size;
LONG bV5Width;
LONG bV5Height;
WORD bV5Planes;
WORD bV5BitCount;
DWORD bV5Compression;
DWORD bV5SizeImage;
LONG bV5XPelsPerMeter;
LONG bV5YPelsPerMeter;
DWORD bV5ClrUsed;
DWORD bV5ClrImportant;
DWORD bV5RedMask;
DWORD bV5GreenMask;
DWORD bV5BlueMask;
DWORD bV5AlphaMask;
DWORD bV5CSType;
Ptr bV5Endpoints;
DWORD bV5GammaRed;
DWORD bV5GammaGreen;
DWORD bV5GammaBlue;
DWORD bV5Intent;
DWORD bV5ProfileData;
DWORD bV5ProfileSize;
DWORD bV5Reserved;
)"
oStruct := new DllStruct(def_Struct)
msgbox % oStruct.GetSize()
; ======================================================================================================================
; AHK_L 1.1 +
; ======================================================================================================================
; Function: Class definitions for windows structures used with DllCall
; AHK version: 1.1.05.06 (U 32) / (U64)
; Language: English
; Tested on: Win XPSP3, Win VistaSP2 (x86) / Win 7 (x64)
; Version: 0.0.01.09/2011-12-09/just me
; Remarks: To create a structure create a new instance of the class using
; MyStruct := New DllStruct(StructStr)
;
; The parameter "StructStr" describes the fields of the structure as follows:
; "TYPE name[n];"
; TYPE : Datatype, for valid types see AHKTypes and WINTypes below
; name (optional) : Name to access the field with the methods described below. If name is not
; specified, you have to access the field by it's 1-based index, otherwise
; TYPE and name must be seperated with at least one space.
; If name is preceded with a "*" the TYPE will be changed to "UPTR".
; [n] (optional) : Number of occurrences, if [n] is not specified it defaults to 1.
; To access a certain occurrence with Get/SetData methods you have to pass
; the 1-based index within the parameter Index. String types (CHAR [n],
; TCHAR [n], WCHAR [n]) are always accessed as strings.
; To supply names for occurences append a colon (:) to the counter (n)
; followed by the names seperated by commas (,) and the closing bracket,
; e.g. "[4: Left, Top, Right, Bottom]". To access an occurence by name just
; pass the name instead of the numeric index.
; ; : Each field description must be closed with a semicolon
;
; Alignment and padding:
; By default, each structure member is aligned to start at an address which is a multiple of its
; length. In addition the structure is padded to set the size to be a multiple of its longest
; member when needed. This can be changed by specifing "Align n;" within "StructStr" where n may
; be 0, 1, 2, 4, or 8. It changes alignment for all subsequent structure members be a multiple of n
; or their size, whatever is smaller. "Align 0;" restores the default alignment.
; Since inluding of embedded structures by name is not supported, the script doesn't notice the start
; or end of these structures. But sometimes the structure's size has to be aligned, especially
; in 64-bit environments. To avoid displacements you should enclose the structure decleration in
; braces followed by a semicolon, e.g. "{; HWND hwndFrom; UINT_PTR idFrom; UINT code; };" (NMHDR).
;
; The following public methods provide access to the structure's memory/fields (see below):
; Init Sets structure's memory to binary NULL
; GetData Gets the current value of a field
; SetData Sets the value of a field
; GetCount Returns the number of occurrences of a field defined as TYPE [nn]
; GetPtr Returns a pointer to the structure or one of the fields
; GetSize Returns the size of the structure or one of the fields in bytes
;
; It's also possible to access fields using the object syntax "Class.Property". To access
; a subitem of a field with multiple occurences (e.g. "LONG [4];") you must use the array syntax
; Class.Property[4] or Class.Property["Name"].
; The notation "Class.Property.4" is not supported and will yield a blank result.
;
; Fields with multiple occurrences may be accessed as a whole if no subitem index is passed. To
; set the values you have to pass an appropriate array containing all values, reading access returns
; an array containing them.
;
; Names of "private" properties/methods are prefixed with underscores, they must not be
; set/called by the script!
;
; You can find the description of windows data types at
; http://msdn.microsoft.com/en-us/library/aa383751%28VS.85%29.aspx
; ======================================================================================================================
; This software is provided 'as-is', without any express or implied warranty.
; In no event will the authors be held liable for any damages arising from the use of this software.
; ======================================================================================================================
;=======================================================================================================================
Class DllStruct {
; ===================================================================================================================
; Base Class Definition
; ===================================================================================================================
Class _Base {
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Meta-Functions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ================================================================================================================
; CONSTRUCTOR __New - you must not instantiate instances
; ================================================================================================================
__New(P*) {
Return False
}
; ================================================================================================================
; __Get Get pseudo properties
; ================================================================================================================
__Get(Name, Index = 0) {
Return This.GetData(Name, Index)
}
; ================================================================================================================
; __Set Set pseudo properties
; ================================================================================================================
__Set(Name, Params*) {
If !IsObject(Params) || (Params.MaxIndex() > 2)
Return ""
If (Params.MaxIndex() = 1) {
Index := 0
Value := Params[1]
} Else {
Index := Params[1]
Value := Params[2]
}
Return This.SetData(Name, Value, Index)
}
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Private Methods ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ================================================================================================================
; PRIVATE METHOD _IsInt()
; ================================================================================================================
_IsInt(Value) {
If Value Is Not Integer
Return False
Return True
}
; ================================================================================================================
; PRIVATE METHOD _IsIn()
; ================================================================================================================
_IsIn(Value, MatchList) {
If Value Not In %MatchList%
Return False
Return True
}
; ================================================================================================================
; PRIVATE METHOD _StructHasField()
; ================================================================================================================
_StructHasField(ByRef Name) {
StringUpper, Name, Name
If !(This._IsInt(Name)) {
If !This._StructObj.HasKey(Name) {
This.Error := True
Return False
}
Name := This._StructObj[Name]
}
If !This._StructArr.HasKey(Name) {
This.Error := True
Return False
}
Return True
}
; ================================================================================================================
; PRIVATE METHOD _FieldHasIndex()
; ================================================================================================================
_FieldHasIndex(ByRef Index, Field) {
If !(This._IsInt(Index)) {
If Field.Names.HasKey(Index) {
Index := Field.Names[Index]
Return True
} Else {
This.Error := True
Return False
}
}
If (Index < 0) || (Index > Field.Cnt) {
This.Error := True
Return False
}
Return True
}
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; PUBLIC Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ================================================================================================================
; METHOD Init Sets structure's memory to NULL
; Return values: On success - True
; On failure - False, This.Error is set
; ================================================================================================================
Init() {
This.Error := False
If !(This._Ptr) || !(This._Alloc) {
This.Error := True
Return False
}
DllCall("Kernel32.dll\RtlZeroMemory", "Ptr", This._Ptr, "Ptr", This._Size)
If (ErrorLevel) {
This.Error := True
Return False
}
Return True
}
; ================================================================================================================
; METHOD GetData Get current value of structure field
; Parameters: Name - Name or index of the field
; Index - Optional: 1-based index of subitem (Name[nn])
; Return values: On success - Field value
; On failure - False, This.Error is set
; Remarks: To access a certain field "Name" must contain the 1-based field index or the name defined
; in the structure description string.
; ================================================================================================================
GetData(Name, Index = 0) {
This.Error := False
If !This._StructHasField(Name) {
This.Error := True
Return False
}
Field := This._StructArr[Name]
If !This._FieldHasIndex(Index, Field) {
This.Error := True
Return False
}
If (Index = 0) && (Field.Cnt > 1) {
Value := []
Loop, % Field.Cnt
Value.Insert(NumGet(This._Ptr + 0, Field.Pos + ((A_Index - 1) * Field.Len), Field.Type))
Return Value
}
If (Index > 0)
Index--
If (Field.Type = "ASTR") || (Field.Type = "WSTR") {
CP := (Field.Type = "WSTR" ? "UTF-16" : "CP0")
Len := (Field.Type = "WSTR" ? Field.Len // 2 : Field.Len)
Value := StrGet(This._Ptr + Field.Pos, Len, CP)
} Else {
Value := NumGet(This._Ptr + 0, Field.Pos + (Index * Field.Len), Field.Type)
}
Return Value
}
; ================================================================================================================
; METHOD SetData Set value of a structure field
; Parameters: Name - Name or index of the field
; Value - New value
; Index - Optional: 1-based index of subitem (Name[nn])
; Return values: On success - True
; On failure - False, This.Error is set
; Remarks: To access a certain field "Name" must contain the 1-based field index or the name defined
; in the structure description string.
; ================================================================================================================
SetData(Name, Value, Index = 0) {
This.Error := False
If !This._StructHasField(Name) {
This.Error := True
Return False
}
Field := This._StructArr[Name]
If !This._FieldHasIndex(Index, Field) {
This.Error := True
Return False
}
If (Index = 0) && IsObject(Value) && (Value.MaxIndex() = Field.Cnt) {
For I, V In Value
NumPut(V, This._Ptr + 0, Field.Pos + ((I - 1) * Field.Len), Field.Type)
Return True
}
If (Index > 0)
Index--
If (Field.Type = "ASTR") || (Field.Type = "WSTR") {
CP := (Field.Type = "WSTR" ? "UTF-16" : "CP0")
Len := (Field.Type = "WSTR" ? Field.Len // 2 : Field.Len)
StrPut(Value, This._Ptr + Field.Pos, Len, CP)
} Else {
NumPut(Value, This._Ptr + 0, Field.Pos + (Index * Field.Len), Field.Type)
}
Return True
}
; ================================================================================================================
; METHOD GetCount Returns the number of occurrences of a field defined as TYPE [nn]
; Parameters: Name - Name or index of the field
; Return values: On success - Integer value > 0
; On failure - False, This.Error is set
; Remarks: To access a certain field "Name" must contain the 1-based field index or the name defined
; in the structure description string.
; ================================================================================================================
GetCount(Name) {
This.Error := False
If !(This._Ptr) {
This.Error := True
Return False
}
If !This._StructHasField(Name) {
This.Error := True
Return False
}
Field := This._StructArr[Name]
Return (Field.Cnt)
}
; ================================================================================================================
; METHOD GetPtr Returns a pointer to the structure or one of the fields
; Parameters: Name - Optional: Name or index of the field
; Return values: On success - Address of the structure or the field passed in Name
; On failure - False, This.Error is set
; Remarks: To access a certain field "Name" must contain the 1-based field index or the name defined
; in the structure description string.
; ================================================================================================================
GetPtr(Name = "") {
This.Error := False
If !(This._Ptr) {
This.Error := True
Return False
}
If (Name = "")
Return This._Ptr
If !This._StructHasField(Name) {
This.Error := True
Return False
}
Field := This._StructArr[Name]
Return (This._Ptr + Field.Pos)
}
; ================================================================================================================
; METHOD GetSize Returns the size of the structure or one of the fields in bytes
; Parameters: Name - Optional: Name or index of the field
; Return values: On success - Size in bytes of the structure or the field passed in Name
; On failure - False, This.Error is set
; Remarks: To access a certain field "Name" must contain the 1-based field index or the name defined
; in the structure description string.
; ================================================================================================================
GetSize(Name = "") {
This.Error := False
If !(This._Size) {
This.Error := True
Return False
}
If (Name = "")
Return This._Size
If !This._StructHasField(Name) {
This.Error := True
Return False
}
Field := This._StructArr[Name]
Return (Field.Len * Field.Cnt)
}
}
; ===================================================================================================================
; Helper Class for Windows Types
; ===================================================================================================================
Class _WINTypes {
Static ATOM := "USHORT"
Static BOOL := "INT"
, BOOLEAN := "UCHAR"
, BYTE := "UCHAR"
Static COLORREF := "UINT"
Static DWORD32 := "UINT"
, DWORD64 := "UINT64"
, DWORD := "UINT"
, DWORD_PTR := "UPTR"
, DWORDLONG := "UINT64"
Static HACCEL := "UPTR"
, HALF_PTR := (A_PtrSize = 8 ? "INT" : "SHORT")
, HANDLE := "UPTR"
, HBITMAP := "UPTR"
, HBRUSH := "UPTR"
, HCOLORSPACE := "UPTR"
, HCONV := "UPTR"
, HCONVLIST := "UPTR"
, HCURSOR := "UPTR"
, HDC := "UPTR"
, HDDEDATA := "UPTR"
, HDESK := "UPTR"
, HDROP := "UPTR"
, HDWP := "UPTR"
, HENHMETAFILE := "UPTR"
, HFILE := "INT"
, HFONT := "UPTR"
, HGDIOBJ := "UPTR"
, HGLOBAL := "UPTR"
, HHOOK := "UPTR"
, HICON := "UPTR"
, HINSTANCE := "UPTR"
, HKEY := "UPTR"
, HKL := "UPTR"
, HLOCAL := "UPTR"
, HMENU := "UPTR"
, HMETAFILE := "UPTR"
, HMODULE := "UPTR"
, HMONITOR := "UPTR"
, HPALETTE := "UPTR"
, HPEN := "UPTR"
, HRESULT := "INT"
, HRGN := "UPTR"
, HRSRC := "UPTR"
, HSZ := "UPTR"
, HWINSTA := "UPTR"
, HWND := "UPTR"
Static INT32 := "INT"
, INT_PTR := "PTR"
Static LANGID := "USHORT"
, LCID := "UINT"
, LCTYPE := "UINT"
, LGRPID := "UINT"
, LONG32 := "INT"
, LONG64 := "INT64"
, LONG := "INT"
, LONG_PTR := "PTR"
, LONGLONG := "INT64"
, LPARAM := "PTR"
, LPBOOL := "UPTR"
, LPBYTE := "UPTR"
, LPCOLORREF := "UPTR"
, LPCSTR := "UPTR"
, LPCTSTR := "UPTR"
, LPCVOID := "UPTR"
, LPCWSTR := "UPTR"
, LPDWORD := "UPTR"
, LPHANDLE := "UPTR"
, LPINT := "UPTR"
, LPLONG := "UPTR"
, LPSTR := "UPTR"
, LPTSTR := "UPTR"
, LPVOID := "UPTR"
, LPWORD := "UPTR"
, LPWSTR := "UPTR"
, LRESULT := "PTR"
Static PBOOL := "PTR"
, PBOOLEAN := "PTR"
, PBYTE := "PTR"
, PCHAR := "PTR"
, PCSTR := "PTR"
, PCTSTR := "PTR"
, PCWSTR := "PTR"
, PDWORD32 := "PTR"
, PDWORD64 := "PTR"
, PDWORD := "PTR"
, PDWORD_PTR := "PTR"
, PDWORDLONG := "PTR"
, PFLOAT := "PTR"
, PHALF_PTR := "PTR"
, PHANDLE := "UPTR"
, PHKEY := "UPTR"
, PINT32 := "UPTR"
, PINT64 := "UPTR"
, PINT := "UPTR"
, PINT_PTR := "UPTR"
, PLCID := "UPTR"
, PLONG32 := "UPTR"
, PLONG64 := "UPTR"
, PLONG := "UPTR"
, PLONG_PTR := "UPTR"
, PLONGLONG := "UPTR"
, POINTER_32 := "UINT"
, POINTER_64 := "PTR"
, POINTER_SIGNED := "PTR"
, POINTER_UNSIGNED := "UPTR"
, PSHORT := "UPTR"
, PSIZE_T := "UPTR"
, PSSIZE_T := "UPTR"
, PSTR := "UPTR"
, PTBYTE := "UPTR"
, PTCHAR := "UPTR"
, PTSTR := "UPTR"
, PUCHAR := "UPTR"
, PUHALF_PTR := "UPTR"
, PUINT32 := "UPTR"
, PUINT64 := "UPTR"
, PUINT := "UPTR"
, PUINT_PTR := "UPTR"
, PULONG32 := "UPTR"
, PULONG64 := "UPTR"
, PULONG := "UPTR"
, PULONG_PTR := "UPTR"
, PULONGLONG := "UPTR"
, PUSHORT := "UPTR"
, PVOID := "UPTR"
, PWCHAR := "UPTR"
, PWORD := "UPTR"
, PWSTR := "UPTR"
Static SC_HANDLE := "UPTR"
, SC_LOCK := "UPTR"
, SERVICE_STATUS_HANDLE := "UPTR"
, SIZE_T := "UPTR"
, SSIZE_T := "PTR"
Static TBYTE := (A_ISUNICODE ? "USHORT" : "UCHAR")
, TCHAR := (A_ISUNICODE ? "USHORT" : "UCHAR")
Static UHALF_PTR := (A_PtrSize = 8 ? "UINT" : "USHORT")
, UINT32 := "UINT"
, UINT_PTR := "UPTR"
, ULONG32 := "UINT"
, ULONG64 := "UINT64"
, ULONG := "UINT"
, ULONG_PTR := "UPTR"
, ULONGLONG := "UINT64"
, USN := "INT64"
Static VOID := "PTR"
Static WCHAR := "USHORT"
, WORD := "USHORT"
, WPARAM := "UPTR"
}
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; CLASS Properties and Methods ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ===================================================================================================================
; CONSTRUCTOR __New
; Parameters: StructStr - String describing the structure fields
; Pointer - Optional: Pointer to the structure as returned from SendMessage or API-Calls
; Return values: On success - new object
; On failure - False, ErrorLevel contains additional informations
; ===================================================================================================================
__New(StructStr, Pointer = "") {
Static AHKTypes := {CHAR: 1, SHORT: 2, INT: 4, INT64: 8, PTR: A_PtrSize
, UCHAR: 1, USHORT: 2, UINT: 4, UINT64: 8, UPTR: A_PtrSize}
Static StructsP := {RECT: "{;LONG [4: Left, Top, Right, Bottom];};"
, POINT: "{;LONG [2: X, Y];};"
, POINTS: "{;SHORT [2: X, Y];};"}
; Create class variables -----------------------------------------------------------------------------------------
This._DllStruct := "" ; Structure variable (Binary)
This._StructArr := [] ; Array of structure fields (Object)
This._StructObj := {} ; Object for field names (Object)
This._Alloc := False ; Did the class allocate memory? (BOOL)
This._Ptr := 0 ; Structure pointer (Pointer)
This._Size := 0 ; Structure size (Integer)
This.Error := False ; Set to True in case of errors (BOOL)
; ----------------------------------------------------------------------------------------------------------------
Align := FieldIndex := MaxLen := MaxStructLen := Pad := Ptr := Size := StructAlign := 0
InStruct := False
StructStr := RegExReplace(StructStr, "[\r\n]")
StructStr := RTrim(StructStr, ";")
Loop, Parse, StructStr, `;
{
If !(A_LoopField) {
ErrorLevel := "Improper structure declaration!"
Return False
}
StringUpper, Part, A_LoopField
Part := RegExReplace(Trim(Part), "\s+", " ")
Rep := ""
If RegExMatch(Part, "\[(?P<ep>[^\]]+)\]$", R) {
Rep := RegExReplace(Rep, "\s+")
Part := RegExReplace(Part, "\s*\[.*$")
}
StringSplit, Parts, Part, %A_Space%
If (Parts0 > 2) {
ErrorLevel := "Improper field declaration: " . Part . "!"
Return False
}
; Check for alignment presetting
If (Parts1 = "Align") {
If (Parts0 = 2) && (StrLen(Parts2) = 1) && InStr("01248", Parts2) {
If (InStruct) {
StructAlign := Parts2
} Else {
Align := Parts2
}
Continue
}
ErrorLevel := "Invalid alignment value""" . Parts2 . """!"
Return False
}
; Check for explicit padding
If (Parts1 = "Pad") {
If (Parts0 = 2) && (StrLen(Parts2) = 1) && InStr("012345678", Parts2) {
Size += Parts2
Continue
}
ErrorLevel := "Invalid padding value""" . Parts2 . """!"
Return False
}
; Check for embedded structures
If (Parts1 = "{") { ; start of structure
If (InStruct) {
ErrorLevel := "Improper use of ""{""!"
Return False
}
; Set / initialize structure related variables
InStruct := True
MaxStructLen := 0
StructAlign := Align
Continue
}
If (Parts1 = "}") { ; end of structure
If !(InStruct) || (MaxStructLen = 0) {
ErrorLevel := "Improper use of ""}""!"
Return False
}
; Align structure's size if required and reset structure related variables
StructAlign := (StructAlign) && (StructAlign < MaxStructLen) ? StructAlign : MaxStructLen
If (Pad := Mod(Size, StructAlign))
Size += StructAlign - Pad
MaxStructLen := 0
InStruct := False
StructAlign := 0
Continue
}
;
Cnt := 1
If (Rep) && !RegExMatch(Rep, "^\d+", Cnt) {
ErrorLevel := "Improper repetition factor """ . Rep . """!"
Return False
}
If (Parts0 = 2) {
If (SubStr(Parts2, 1, 1) = "*") {
Parts1 := "UPTR"
Parts2 := RegExReplace(Parts2, "^\*+")
}
}
Type := Parts1
If This._WINTypes.HasKey(Parts1)
Type := This._WINTypes[Parts1]
If !AHKTypes.HasKey(Type) {
ErrorLevel := "Invalid data type """ . Parts1 . """!"
Return False
}
Len := AHKTypes[Type]
If (Len > MaxLen)
MaxLen := Len
If (Len > MaxStructLen)
MaxStructLen := Len
If (Pad := Mod(Size, ((Align) && (Align < Len))? Align : Len))
Size += Len - Pad
Pos := Size
If (Cnt > 1) {
If (Parts1 = "WCHAR")
Type := "WSTR"
Else If (Parts1 = "CHAR")
Type := "ASTR"
Else If (Parts1 = "TCHAR")
Type := (A_IsUnicode ? "WSTR" : "ASTR")
}
If (Type = "ASTR") || (Type = "WSTR") {
Len := Cnt * (Type = "WSTR" ? 2 : 1)
Rep := ""
Cnt := 1
}
Names := {}
If InStr(Rep, ":") {
StringReplace, Rep, Rep, %Cnt%:
StringSplit, Name, Rep, `,
If (Name0 = Cnt) {
Loop, %Name0%
Names[Name%A_Index%] := A_Index
}
}
FieldIndex++
This._StructArr[FieldIndex] := {"Type": Type, "Pos": Pos, "Len": Len, "Cnt": Cnt, "Names": Names}
Size += (Len * Cnt)
If (Parts0 = 2)
This._StructObj[Parts2] := FieldIndex
}
Align := (Align) && (Align < MaxLen) ? Align : MaxLen
If (Pad := Mod(Size, Align))
Size += Align - Pad
If (Pointer <> "") {
This._Ptr := Pointer
This._Size := Size
} Else {
If (This.SetCapacity("_DllStruct", Size) <> Size)
Return False
This._Size := Size
Ptr := This.GetAddress("_DllStruct")
If !(Ptr)
Return False
This._Ptr := Ptr
This._Alloc := True
}
This.Base := This._Base
If This._Alloc
This.Init()
}
}
Ответ на то, что для x32 надо перечислять все члены. На счет последней структуры ptr она не может быть ровна, так как возвращается ее копия. Последним идет не член структуры, а ее название (считать не надо).
Ответ на то, что для x32 надо перечислять все члены.
А если их больше 31.
На счет последней структуры ptr она не может быть ровна, так как возвращается ее копия.
Так как её считать.
Последним идет не член структуры, а ее название (считать не надо).
DWORD bV5Reserved; нее надо считать.
А их разве больше? Считать надо сумму ее членов. Ресервед тоже учитывать.
Запутали друг друга, давай по порядку, с х32 потом.
Как считать CIEXYZTRIPLE bV5Endpoints, если это не Ptr, то сколько байт под него выделять и почему?
Посчитаешь, можешь сравнить результат.
Перепутал колонку, думал 124 это смещение.
Значит размер 124.
Если считать CIEXYZTRIPLE как Ptr, то 92.
И DllStruct запускал под х32, под х64 выдаёт 104.
Размышления чайника:
Разные размеры из за того что размер Ptr зависит от битности.
Значит CIEXYZTRIPLE = 36.
И DllStruct запускал под х32, под х64 выдаёт 104
Хотя нет, под х32 если 94, то под х64 должно быть 94+4=98.
Все кроме CIEXYZTRIPLE занимают 88, CIEXYZTRIPLE это набор из 9 координат, координата = FLOAT. 88+9*4=124.
MagImageScalingCallback(hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) {
Static BI_RGB := 0, CBM_INIT := 6, DIB_RGB_COLORS := 0
bV5Width := NumGet(srcheader + 0, 0, "UInt")
bV5Height := NumGet(srcheader + 0, 4, "UInt")
VarSetCapacity(BITMAPV5HEADER, 124, 0)
NumPut(124, BITMAPV5HEADER, 0, "UInt") ; DWORD bV5Size;
NumPut(bV5Width, BITMAPV5HEADER, 4, "UInt") ; LONG bV5Width;
NumPut(bV5Height, BITMAPV5HEADER, 8, "UInt") ; LONG bV5Height;
NumPut(1, BITMAPV5HEADER, 12, "Short") ; WORD bV5Planes;
NumPut(32, BITMAPV5HEADER, 14, "Short") ; WORD bV5BitCount;
NumPut(BI_RGB, BITMAPV5HEADER, 16, "UInt") ; DWORD bV5Compression;
hDC := DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
hBMP := DllCall("CreateDIBitmap"
, "Ptr", hDC
, "Ptr", &BITMAPV5HEADER
, "UInt", CBM_INIT
, "Ptr", &srcdata
, "UInt", ??????
, "UInt", DIB_RGB_COLORS)
}
Не знаю насколько я тут вообще что то понял, теперь пытаюсь разобратся с:
https://docs.microsoft.com/en-us/window … tedibitmap
const BITMAPINFO *pbmi,
Надо создать BITMAPINFO structure, только что в ней заполнять, какие то из полей.
VarSetCapacity(BITMAPINFO, 44, 0)
NumPut(44, BITMAPINFO, 0, "UInt") ; DWORD biSize;
NumPut(bV5Width, BITMAPINFO, 4, "UInt") ; LONG biWidth;
NumPut(bV5Height, BITMAPINFO, 8, "UInt") ; LONG biHeight;
NumPut(1, BITMAPINFO, 12, "Short") ; WORD biPlanes;
NumPut(32, BITMAPINFO, 14, "Short") ; WORD biBitCount;
NumPut(BI_RGB, BITMAPINFO, 16, "UInt") ; DWORD biCompression;
Впервые разобрался с апи!
Конечно не без советов и безграничного терпения от Malcev.
Осталось перевернуть картинку.
#NoEnv
#Persistent
#SingleInstance Force
OnExit, Uninitialize
DllCall("LoadLibrary", "str", "magnification.dll")
DllCall("magnification.dll\MagInitialize")
Gui, +AlwaysOnTop -Caption +ToolWindow +HWNDhGui
Gui, Show, x320 y0 w320 h240 NA, MagnifierWindowAHK
Global hPic
Gui 2: -Caption +AlwaysOnTop +ToolWindow
Gui, 2: Margin, 0,0
Gui, 2: Add, text, w320 h240 0xE hwndhPic ; SS_BITMAP = 0xE
Gui, 2: Show, x640 y0 NA
hInstance := DllCall("GetWindowLong"
, "Ptr", hGui
, "UInt", GWL_HINSTANCE:=-6)
WS_CHILD := 0x40000000
WS_VISIBLE := 0x10000000
MS_SHOWMAGNIFIEDCURSOR := 0x1
magHwnd := DllCall("CreateWindowEx"
, "UInt", 0
, "Str", "Magnifier"
, "Str", "MagnifierWindow"
, "UInt", MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE | WS_CHILD
, "Int", 0
, "Int", 0
, "Int", 320
, "Int", 240
, "Ptr", hGui
, "UInt", 0
, "Ptr", hInstance
, "UInt", 0)
DllCall("magnification\MagSetWindowFilterList","Ptr",magHwnd,"Int",0,"Int",1,"Ptr*", WinExist("ahk_class Notepad++")) ; MW_FILTERMODE_EXCLUDE
DllCall("magnification.dll\MagSetImageScalingCallback"
, "Ptr", magHwnd
, "Int", RegisterCallback("MagImageScalingCallback", "Fast"))
VarSetCapacity(rect, 16, 0)
NumPut(0, rect, 0, "int")
NumPut(0, rect, 4, "int")
NumPut(320, rect, 8, "int")
NumPut(240, rect, 12, "int")
Loop
DllCall("magnification.dll\MagSetWindowSource", "ptr", magHwnd, ptr, &rect)
return
MagImageScalingCallback(hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) {
Static BI_RGB := 0, CBM_INIT := 6, DIB_RGB_COLORS := 0
, Ptr := A_PtrSize = 8 ? "UPtr" : "UInt"
, STM_SETIMAGE := 0x172, IMAGE_BITMAP := 0x0
, _ := VarSetCapacity(BITMAPV5HEADER, 124, 0)
, __ := VarSetCapacity(BITMAPINFO, 44, 0)
bV5Width := NumGet(srcheader + 0, 0, "UInt")
bV5Height := NumGet(srcheader + 0, 4, "UInt")
NumPut(124, BITMAPV5HEADER, 0, "UInt") ; DWORD bV5Size;
NumPut(bV5Width, BITMAPV5HEADER, 4, "UInt") ; LONG bV5Width;
NumPut(bV5Height, BITMAPV5HEADER, 8, "UInt") ; LONG bV5Height;
NumPut(1, BITMAPV5HEADER, 12, "Short") ; WORD bV5Planes;
NumPut(32, BITMAPV5HEADER, 14, "Short") ; WORD bV5BitCount;
NumPut(BI_RGB, BITMAPV5HEADER, 16, "UInt") ; DWORD bV5Compression;
NumPut(44, BITMAPINFO, 0, "UInt") ; DWORD biSize;
NumPut(bV5Width, BITMAPINFO, 4, "UInt") ; LONG biWidth;
NumPut(bV5Height, BITMAPINFO, 8, "UInt") ; LONG biHeight;
NumPut(1, BITMAPINFO, 12, "Short") ; WORD biPlanes;
NumPut(32, BITMAPINFO, 14, "Short") ; WORD biBitCount;
NumPut(BI_RGB, BITMAPINFO, 16, "UInt") ; DWORD biCompression;
hDC := DllCall("GetDC", Ptr, hwnd)
hBMP := DllCall("CreateDIBitmap"
, Ptr, hDC
, Ptr, &BITMAPV5HEADER
, "UInt", CBM_INIT
, Ptr, srcdata
, Ptr, &BITMAPINFO
, "UInt", DIB_RGB_COLORS)
hBitmap := DllCall("CopyImage", Ptr, hBMP, "UInt", 0, "Int", 320, "Int", 240, "UInt", 0)
SendMessage, STM_SETIMAGE, IMAGE_BITMAP, hBitmap,, ahk_id %hPic%
DllCall("DeleteDC", Ptr, hDC)
DllCall("DeleteObject", Ptr, hBMP)
DllCall("DeleteObject", Ptr, hBitmap)
return 1
}
Escape::
Uninitialize:
DllCall("magnification.dll\MagUninitialize")
ExitApp
АП: Память куда то утекает. (
Потому что не удаляешь битмап.
Из Gdi+:
SetImage(hwnd, hBitmap)
{
SendMessage, 0x172, 0x0, hBitmap,, ahk_id %hwnd%
E := ErrorLevel
DeleteObject(E)
return E
}
Точно, забыл. Оно как то не явно создаёт битмап. Под рукой был этот пример, в нём без DeleteObject с памятью всё нормально, но он не идёт под х64.
#SingleInstance Force
#NoEnv
; https://autohotkey.com/board/topic/34232-for-gdi-experts-how-to-resample-image-to-produce-gradient/?p=216747
SetBatchLines, -1
; Process Priority,,high
Hex2=
(Join
424D8600000000000000360000002800
00000500000005000000010018000000
00005000000000000000000000000000
0000000000000000800080FF00004000
80FF000080000080FF00004000008000
00400080FF000000400000800080FF00
0080000040000080FF00004000008000
00400080FF000000800080FF00004000
80FF00008000
)
Hex1=
(Join
424D8600000000000000360000002800
00000500000005000000010018000000
00005000000000000000000000000000
00000000000000008000008000004000
0080000080000000800000400080FF00
0040000080000000400080FF00008000
80FF000040000000800000400080FF00
00400000800000008000008000004000
008000008000
)
Hex=
(JOIN
424D5A000000000000003600000028000000030000000300000001001800000000002400000000000000000000
00000000000000000000004000008000004000000000008030B3F0000080000000000040000080000040000000
)
VarSetCapacity( BMP,(cLen:=StrLen(hex)//2))
Loop %cLen%
NumPut("0x" SubStr(hex,2*a_index-1,2),BMP,a_index-1,"char")
VarSetCapacity( BMP1,(cLen1:=StrLen(hex1)//2))
Loop %cLen1%
NumPut("0x" SubStr(hex1,2*a_index-1,2),BMP1,a_index-1,"char")
VarSetCapacity( BMP2,(cLen2:=StrLen(hex2)//2))
Loop %cLen2%
NumPut("0x" SubStr(hex2,2*a_index-1,2),BMP2,a_index-1,"char")
Hex=
Hex1=
Hex2=
DIB_PAL_COLORS := 1
Gui 1:-Caption +LastFound
Gui, Margin, 0,0
GUI1:=WinExist() , hDC:=DllCall("GetDC",UInt,Gui1)
Gui, Add, text, w640 h480 0xE vPic hwndhPic ; SS_BITMAP = 0xE
hBMP := DllCall( "CreateDIBitmap", UInt,hDC, UInt,(bmiHAddr:=&BMP+14)
,UInt,(CBM_INIT:=6), UInt,&BMP+NumGet(BMP,10), UInt,&BMP+14, UInt,(DIB_PAL_COLORS) )
hBitmap:=DllCall("CopyImage",UInt, hBMP,UInt,0,Int,640,Int,480, UInt,0)
hBMP1 := DllCall( "CreateDIBitmap", UInt,hDC, UInt,(bmiHAddr1:=&BMP1+14)
,UInt,(CBM_INIT:=6), UInt,&BMP1+NumGet(BMP1,10), UInt,&BMP1+14, UInt,(DIB_PAL_COLORS) )
hBitmap1:=DllCall("CopyImage",UInt, hBMP1,UInt,0,Int,640,Int,480, UInt,0)
hBMP2 := DllCall( "CreateDIBitmap", UInt,hDC, UInt,(bmiHAddr2:=&BMP2+14)
,UInt,(CBM_INIT:=6), UInt,&BMP2+NumGet(BMP2,10), UInt,&BMP2+14, UInt,(DIB_PAL_COLORS) )
hBitmap2:=DllCall("CopyImage",UInt, hBMP2,UInt,0,Int,640,Int,480, UInt,0)
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %hPic%
Gui, Show, w640 h480
Loop
{
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %hPic%
Sleep, 50
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap1,, ahk_id %hPic%
Sleep, 50
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap2,, ahk_id %hPic%
Sleep, 50
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap1,, ahk_id %hPic%
Sleep, 50
}
Return
GuiClose:
ExitApp
Escape:: ExitApp