Тема: AHK: Скриншот выделенной части экрана поверх всех окон
Доброго времени суток. Есть задумка сделать скриншот выделенной части экрана по горячей клавише и показать его поверх всех окон . Помогите реализовать пожалуйста.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Доброго времени суток. Есть задумка сделать скриншот выделенной части экрана по горячей клавише и показать его поверх всех окон . Помогите реализовать пожалуйста.
Начинайте, поможем.
Вот мои задумки по поводу готовой программы , которая на F9 фотографирует выделенную часть экрана.
#NoEnv
#Persistent
WS_EX_TRANSPARENT := 0x20
WS_EX_LAYERED := 0x80000
*~F9::
IfExist, C:\Users\roma\Pictures\GameCenter\WEQ\Desktop\*.jpeg
Gui, -Caption +AlwaysOnTop +Lastfound +ToolWindow
Gui, Color, EEAA99
WinSet TransColor, EEAA99
Gui, Add, Picture, AltSubmit , C:\Users\roma\Pictures\GameCenter\WEQ\Desktop\*.jpeg
Gui, Show, NA
Return
*~F7::
FileDelete, C:\Users\roma\Pictures\GameCenter\WEQ\Desktop\*.jpeg
GuiClose:
ExitApp
Но вот как всё это подогнать что бы работало . Я весь измучился. Мне кажется легче на "AHK" всё написать чем всё это подгонять.
Честно говоря, задумку не понял. Как скрипт должен работать?
Если что, в коллекции есть мой скрипт для снятия скриншотов (правда, только под 32-bit, и скриншот не показывает). Для того, чтобы разобраться, в принципе сойдёт.
Кроме того, есть не совсем доделанный подобный код, который может показывать (опционально) скриншот перед сохранением и даже менять его размеры. Если нужно, могу выложить.
Честно говоря, задумку не понял. Как скрипт должен работать?
Если что, в коллекции есть мой скрипт для снятия скриншотов (правда, только под 32-bit, и скриншот не показывает). Для того, чтобы разобраться, в принципе сойдёт.
Кроме того, есть не совсем доделанный подобный код, который может показывать (опционально) скриншот перед сохранением и даже менять его размеры. Если нужно, могу выложить.
Ну скрипт из коллекции я нашёл своими силами,за старание всё равно спасибо но подогнать его я не смог. Задумка такая в браузере нужно списать информацию с одного сайта на другой . Вот ссылка на "Мас" приложение , там всё описано.
Вот простенький скрипт:
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
OnExit, Exit
oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
Return
^Space::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow([X, Y, W, H])
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
(v != 0 && DllCall("DeleteObject", Ptr, v))
ExitApp
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(oCoords)
{
global oGuiData
static SS_BITMAP := 0xE
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen(oCoords[1] "|" oCoords[2] "|" oCoords[3] "|" oCoords[4])
Gdip_GetImageDimensions(pBitmap, W, H)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
Gdip_DisposeImage(pBitmap)
for k, v in oGuiData
if (v = 0 && IsEmpty := k)
break
nGui := IsEmpty ? IsEmpty : (k = "" || k = 99) ? 1 : k + 1
oGuiData[nGui] := hBitmap
Gui, %nGui%:New
Gui, %nGui%:Default
Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound +Border -DPIScale
Gui, Margin, 0, 0
Gui, Add, Pic, hwndhPic w%W% h%H% %SS_BITMAP%
SetImage(hPic, hBitmap)
Gui, Show, % "x" oCoords[1] " y" oCoords[2]
Gdip_Shutdown(pToken)
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_RBUTTONUP()
{
global oGuiData
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData[A_Gui] := 0
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
global oGuiData
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData[A_Gui] := 0
}
Нужна библиотека Gdip.ahk.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, закрыть — щелчком правой.
Огромное вам спасибо teadrinker , то что надо. Хотя и есть небольшая ошибка ,что то связанное с выделением там поле выделения опережает крестик крестик .
У меня, вроде, нормально всё. CoordMode, Mouse не забыли?
У меня, вроде, нормально всё. CoordMode, Mouse не забыли?
Попробуйте сделать скрин где нибудь на тёмном фоне и там будет видна белая полоса справа от скриншота сантиметров на 8 и снизу сантиметра на 3.
У меня никаких полосок нет:
У кого-нибудь ещё есть полоски?
У меня тоже самое, потому всегда добавляю:
Gui, -DPIScale
С этим ошибка пропадает? Никогда не мог понять, что это даёт?
Ну это если в винде увеличенный шрифт, то по умолчанию (+DPIScale) размер окна увеличивается на столько же процентов.
С этим нормально работает?
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
OnExit, Exit
oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
Return
^Space::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow([X, Y, W, H])
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
(v != 0 && DllCall("DeleteObject", Ptr, v))
ExitApp
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(oCoords)
{
global oGuiData
static SS_BITMAP := 0xE
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen(oCoords[1] "|" oCoords[2] "|" oCoords[3] "|" oCoords[4])
Gdip_GetImageDimensions(pBitmap, W, H)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
Gdip_DisposeImage(pBitmap)
for k, v in oGuiData
if (v = 0 && IsEmpty := k)
break
nGui := IsEmpty ? IsEmpty : (k = "" || k = 99) ? 1 : k + 1
oGuiData[nGui] := hBitmap
Gui, %nGui%:New
Gui, %nGui%:Default
Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound +Border -DPIScale
Gui, Margin, 0, 0
Gui, Add, Pic, hwndhPic w%W% h%H% %SS_BITMAP%
SetImage(hPic, hBitmap)
Gui, Show, % "x" oCoords[1] " y" oCoords[2]
Gdip_Shutdown(pToken)
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_RBUTTONUP()
{
global oGuiData
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData[A_Gui] := 0
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
global oGuiData
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData[A_Gui] := 0
}
это решается:
там поле выделения опережает крестик
но вот полосы я у себя не наблюдал и до этого.
А нет, полосы всё таки были.
А, ок, добавлю тогда.
Заметил, что когда несколько скринов на экране, то не понятно в какие моменты (чаще в момент нового снимка) может появится пустое (белое) окно скрипта с заголовком.
Появляется когда резко отводишь мышь и отпускаешь LButton, а окно выделения ещё не "догнало" курсор.
Большое спасибо вам serzh82saratov ваш скрипт работае так как надо без лишних полосок.
А можно узнать что вы поменяли что бы всё заработало.
Ядрён Пожалуйста, Вы тут первый с увеличенным шрифтом, а я второй и последний.
teadrinker полоски убрал, а вот про выделение забыл.
Всё спасибо разобрался "-DPIScale" в двух местах добавили.
Заметил, что когда несколько скринов на экране, то не понятно в какие моменты (чаще в момент нового снимка) может появится пустое (белое) окно скрипта с заголовком.
А скриншот можно?
https://cloud.mail.ru/public/0f9d54cd90 … %D0%BA.PNG
Не представляю. В скрипте все окна создаются изначально с опцией -Caption. Если только эта самая -DPIScale с ней как-нибудь не конфликтует.
Без DPIScale тоже самое:
Появляется когда резко отводишь мышь и отпускаешь LButton, а окно выделения ещё не "догнало" курсор.
Ага, тоже получилось, подумаю.
Вот так у меня выглядело.
Появляется когда резко отводишь мышь и отпускаешь LButton, а окно выделения ещё не "догнало" курсор.
Нужно после KeyWait, LButton добавить SetTimer, EventHandling, Off.
/*
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, закрыть — щелчком правой.
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
OnExit, Exit
oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
Return
^Space::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow([X, Y, W, H])
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
(v != 0 && DllCall("DeleteObject", Ptr, v))
ExitApp
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(oCoords)
{
global oGuiData
static SS_BITMAP := 0xE
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen(oCoords[1] "|" oCoords[2] "|" oCoords[3] "|" oCoords[4])
Gdip_GetImageDimensions(pBitmap, W, H)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
Gdip_DisposeImage(pBitmap)
for k, v in oGuiData
if (v = 0 && IsEmpty := k)
break
nGui := IsEmpty ? IsEmpty : (k = "" || k = 99) ? 1 : k + 1
oGuiData[nGui] := hBitmap
Gui, %nGui%:New
Gui, %nGui%:Default
Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound +Border -DPIScale
Gui, Margin, 0, 0
Gui, Add, Pic, hwndhPic w%W% h%H% %SS_BITMAP%
SetImage(hPic, hBitmap)
Gui, Show, % "x" oCoords[1] - 1 " y" oCoords[2] - 1
Gdip_Shutdown(pToken)
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_RBUTTONUP()
{
global oGuiData
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData[A_Gui] := 0
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
global oGuiData
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData[A_Gui] := 0
}
Для работы скрипта нужна библиотека Gdip.ahk.
А можно ли добавить увеличение скрина внутри окна по горячей клавише .
Так можно менять размер колесом мыши:
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
^Space::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
К вопросу о скриншотах - кому-нибудь встречалась задача по созданию скрина свернутого окна приложения без использования внешнего софта (Paint и т.д.), а так же снятия скринов при разлогиненном компьютере (хм, вообще возможно ли такое)? Перелопатил несколько веток на англоязычном форуме, но к сожалению примеры не заработали.
кому-нибудь встречалась задача по созданию скрина свернутого окна приложения без использования внешнего софта
Встречалась.
а так же снятия скринов при разлогиненном компьютере
Нет, такая точно не встречалась.
teadrinker
Удалось снимать скрины со свернутых окон, поделитесь знанием)?
По второму вопросу я некорректно описал задачу - пользователь залогинен на рабочей станции, но система заблокирована.
Удалось снимать скрины со свернутых окон, поделитесь знанием)?
Со свёрнутых пока никому не удавалось, но можно временно развернуть за экраном.
И просьба, старайтесь не цитировать предыдущий пост целиком, пользуйтесь кнопкой «Ответить» или формой быстрого ответа.
Доброго времени суток . Подскажите пожалуйста как добавить сохранение скриншота выделенной части экрана .
Подскажите в какую сторону хоть смотреть.
Завтра попробую, пока некогда.
Смотреть нужно в сторону туториалов:
https://autohotkey.com/board/topic/2944 … 45-by-tic/
За сохранение файла отвечает функция: Gdip_SaveBitmapToFile(pBitmap, "File.png").
Соответственно вставьте ее в скрипте teadrinkerа после создания объекта pBitmap и до освобождения его ресурсов Gdip_DisposeImage(pBitmap).
Уважаемый Malcev всё получилось как вы говорили , правда выделяешь часть экрана и сразу происходит сохраняет . А подскажите пожалуйста как сделать сохранение по горячей клавише.
Сегодня пол ночи мучился , так и не одолел "сохранение по горячей клавише".
Нужно объявить глобальными переменные pBitmap и pToken и стереть Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken) из конца функции CreateScreenshotWindow(X, Y, W, H).
Вставить в начало функции:
if pBitmap
Gdip_DisposeImage(pBitmap)
if pToken
Gdip_Shutdown(pToken)
И тоже самое вставить в метку OnExit, чтобы при выходе из скрипта тоже подчищалось, хотя я читал, что винда сама должна подчищать.
Что то не получается помогите пожалуйста. Как сделать например нажал "F10" скрин сохранился.
Подскажите пожалуйста как добавить сохранение скриншота выделенной части экрана
Если речь идёт о вышеприведённом скрипте, то там можно выделять несколько областей экрана сразу. Как скрипт узнает, какую именно сохранять по горячей клавише? Кроме того, там можно менять размер окна со скриншотом. В каком размере должно сохраняться, в первоначальном, или в текущем?
Нужно объявить глобальными переменные pBitmap и pToken и стереть Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken) из конца функции CreateScreenshotWindow(X, Y, W, H).
Нет, ничего такого не нужно. В скрипте есть объект oGuiData с хэндлами hBitmap существующих окон. Скрипт немного подправил.
Вот сохранение по двойному клику:
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir, % A_ScriptDir
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
^Space::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_LBUTTONDBLCLK()
{
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
res := Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\" . A_Now . ".png")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
if (res = 0)
MsgBox, Файл успешно создан по адресу:`n%A_ScriptDir%\%A_Now%.png
else
MsgBox, Не удалось создать файл. Ошибка: %res%
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
Спасибо огромное вам teadrinker то что нужно , всё работает.
А где брать ф-ию Gdip_Startup() ? Без нее скрипт из 43-го поста не работает.
Там же написано:
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
Доброго времени суток. Решил добавить выборочное сохранение файла , но файл не сохраняется. Подскажите где ошибка.
WM_LBUTTONDBLCLK()
{
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
res := Gdip_SaveBitmapToFile(pBitmap, OutFile "\" A_Now ".png")
FileSelectFile, res, S3, %OutFile%\%A_Now%.png, Сохранить скриншот, All Files(*.*)
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
А чему переменная OutFile в шестой строке равна?
Как написано в справке. OutFile: Корневой (начальный) каталог, который предположительно является папкой нижележащего уровня в %A_WorkingDir% в том случае, если абсолютный путь точно не определен. Может я чего то недопонимаю. Но по идее всё ведь должно работать.
А причём тут справка к FileSelectFile? Я про шестую строку спросил, ещё до неё.
Я думал "OutFile" из шестой строки, это третий параметр из "FileSelectFile".Ну как то так наверное.Но скорее всего я ошибаюсь.Подскажите как правильно.
OutFile := %OutFile%
Ну никак не пойму если из встроенной переменной "A_Now" дата и время переходит в стандартное диалоговое окно(название файла),то почему "OutFile" не переходит как путь("OutFile" это конечно не путь)но даже если поставить вместо "OutFile" "A_ScriptDir"- а это уже путь, и почему нельзя его изменить из 3 -го параметра "FileSelectFile".
res := Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\" . A_Now . ".png")
FileSelectFile, res, S3, %A_ScriptDir%\%A_Now%.png, Сохранить скриншот, All Files(*.*)
Я наверное я как всегда перемудрил.
Сперва попытайтесь объяснить, зачем вы сначала сохраняете картинку в файл, а после этого выбираете ещё какой-то файл?
Функция Gdip_SaveBitmapToFile() как раз сохраняет файл по указанному пути. Может, сначала стоит выбрать путь с помощью FileSelectFile, а уже потом сохранять?
Верно но как это сделать.
Ваша задача сейчас получить нужный путь из FileSelectFile в переменную, и подставить его в Gdip_SaveBitmapToFile(). Почитайте справку по FileSelectFile.
Если только так но так тоже не работает. У меня закончились идеи .
Gdip_SaveBitmapToFile(pBitmap, %SelectFile% . "\" . A_Now . ".png")
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Ну где же ошибка.Никак не получается , капец в 2-х строках разобраться не могу.
получить нужный путь из FileSelectFile в переменную, и подставить его в Gdip_SaveBitmapToFile().
Может, сначала стоит выбрать путь с помощью FileSelectFile, а уже потом сохранять?
Не понимаю: Если параметр RootDir опущен или пуст, то начальным будет каталог по умолчанию, который, возможно, будет зависеть от версии операционной системы.
FileSelectFile, SelectFile, S3, RootDir\%A_Now%.png , Сохранить скриншот, All Files(*.*)
Я его и оставил пустым , значит путь должен быть по умолчанию.
FileSelectFile, SelectFile, S3,%A_Now%.png , Сохранить скриншот, All Files(*.*)
Нет всё сдаюсь.
Этот код
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
написан корректно. Можно проверить:
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
MsgBox, % SelectFile
Почему же так не работает.
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Gdip_SaveBitmapToFile(pBitmap, %SelectFile% . "\" . A_Now . ".png")
Получается "SelectFile" это путь.
SelectFile := %SelectFile%
И почему путь из "SelectFile" не переходит в "%SelectFile%" для последующего сохранения.
Ему никуда переходить не надо, он уже там. В функцию переменные подставляются без знаков процента.
Так тоже не работает.
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Gdip_SaveBitmapToFile(pBitmap, "SelectFile" . "\" . A_Now . ".png")
Ядрён, так посмотрите чему у вас равна переменная сохранения файла и поймёте почему у вас не сохраняется:
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
msgbox % "SelectFile" . "\" . A_Now . ".png"
Я действительно в ступоре . Я не понимаю почему.
stealzy он не долже быть сохранён . При таком пути.
Так фишка в том что в "FileSelectFile" можно выбрать любой путь.А так то пожалуйста.
Gdip_SaveBitmapToFile(pBitmap, "C:\Users\Public\Pictures\Sample Pictures" . "\" . A_Now . ".png")
В функцию переменные подставляются без знаков процента.
Gdip_SaveBitmapToFile(pBitmap, "SelectFile" . "\" . A_Now . ".png")
Ядрён, а вы изобретательны! Кавычками обрамлять тоже не надо. Кавычками переменные не обрамляются никогда.
Запомните, что функции всегда ждут от вас переменную
Нет, функции ждут выражение, а в них переменные пишутся без знака процента, а строки в кавычках.
Так тоже не работает .
Gdip_SaveBitmapToFile(pBitmap, SelectFile . "\" . A_Now . ".png")
Ядрён, ну так опять же, посмотрите путь в который вы сохраняете:
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
msgbox % SelectFile . "\" . A_Now . ".png"
Всем огромное спасибо разобрался.
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Gdip_SaveBitmapToFile(pBitmap, SelectFile)
Ну я и тугой .Хотя ребёнок малениький 2.5 месяца отходишь то и дело и сосредоточиться нереально.
Доброго времени суток. Помогите пожалуйста сделать кнопки на окне поделиться скриншотом в Telegram и WhatsApp .
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir, % A_ScriptDir
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
*~$vk2C::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_LBUTTONDBLCLK()
{
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gui, %A_Gui%:Hide
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
res := Gdip_SaveBitmapToFile(pBitmap, SelectFile )
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
; if (res = 0)
;MsgBox, Скриншот успешно сохранён: `n%SelectFile%\%A_Now%.png
;else
;MsgBox, Не удалось сохранить скриншот. Ошибка: %res%
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
Доброго времени суток. Подскажите как сделать при исчезании окна копирование выделенной части в буфер.
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
Где то здесь я думаю.
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir, % A_ScriptDir
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
*~$vk2C::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_LBUTTONDBLCLK()
{
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gui, %A_Gui%:Hide
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
res := Gdip_SaveBitmapToFile(pBitmap, SelectFile )
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
; if (res = 0)
;MsgBox, Скриншот успешно сохранён: `n%SelectFile%\%A_Now%.png
;else
;MsgBox, Не удалось сохранить скриншот. Ошибка: %res%
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
Используйте Gdip_SetBitmapToClipboard().
Уважаемый teadrinker что то не получается.
WM_RBUTTONUP()
{
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
Вот так помещает в буфер скрин полного экрана а не выделенной части экрана.
Используйте Gdip_SetBitmapToClipboard().
Уважаемый teadrinker большое спасибо за подсказку .
WM_RBUTTONUP()
{
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
res := Gdip_SetBitmapToClipboard(pBitmap)
if (A_Gui != "Select") {
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
Так всё получилось.
Отлично, лучше так:
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gdip_SetBitmapToClipboard(pBitmap)
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
Доброго времени суток. Обнаружил в работе скрипта баг. Если выделенную часть экрана заскролить
"WheelDown" "WheelUp"(увеличить или уменьшить окно) а потом сохранить или копировать картинку в буфер то сохраняется картинка изначального размера т.е(без увеличения или уменьшения окна). Помогите пожалуйста разобраться.
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir, % A_ScriptDir
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
*~$vk2C::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_LBUTTONDBLCLK()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gui, %A_Gui%:Hide
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Gdip_SaveBitmapToFile(pBitmap, SelectFile )
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gdip_SetBitmapToClipboard(pBitmap)
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
Почему баг, изначально функционал для сохранения в буфер обмена не предполагался. Версия, которую вы выложили, не сохраняет даже изначальный размер. Проверяйте код, перед тем как выкладывать.
Уважаемый teadrinker я всё исправил.
Был не прав.
WM_RBUTTONUP -удаление окна
Понял.
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
Gdip_SetBitmapToClipboard(pBitmap)
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
Gui, %A_Gui%:Destroy
}
}
А что там делает строка
Gdip_SetBitmapToClipboard(pBitmap)
? Она явно лишняя. А в коде
WM_MBUTTONDOWN()
{
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gui, %A_Gui%:Hide
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
res := Gdip_SaveBitmapToFile(pBitmap, SelectFile )
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
не сохранён приведённый мной алгоритм, там
if (A_Gui != "Select")
совсем не напрасно было.
Уважаемый teadrinker я исправил код алгоритм соблюдён.
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir, % A_ScriptDir
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
*~$vk2C::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_LBUTTONDBLCLK()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gui, %A_Gui%:Hide
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Gdip_SaveBitmapToFile(pBitmap, SelectFile )
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gdip_SetBitmapToClipboard(pBitmap)
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
Так будет в размере окна сохранять:
/*
Скрипт снимает скриншот выделенной области экрана и показывает его поверх всех окон.
Скрипт также позволяет изменять размеры скриншота при вращении над ним колеса мыши.
Ctrl + Space — начать выделение (отпустив Ctrl + Space).
Двигать окно со скриншотом левой кнопкой, менять размер вращая колесо, закрыть — щелчком правой.
При закрытии окна скриншот сохраняется в буфер обмена.
Для работы скрипта необходима библиотека Gdip.ahk
https://www.dropbox.com/s/73vpu9xdzn5ys13/Gdip.ahk?dl=1
*/
CoordMode, Mouse
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir, % A_ScriptDir
OnExit, Exit
global oGuiData := []
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
Return
Exit:
(CrossHair && CrossHair())
(hHookMouse && DllCall("UnhookWindowsHookEx", Ptr, hHookMouse))
for k, v in oGuiData
DllCall("DeleteObject", Ptr, v)
ExitApp
^Space::CrossHair(CrossHair := 1)
#If CrossHair = 1
LButton::
MouseGetPos, mouse_x_start, mouse_y_start
Gui, Select:Default
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop -DPIScale
Gui, Color, Grey
WinSet, Transparent, 150
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
KeyWait, LButton
SetTimer, EventHandling, Off
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse), hHookMouse := ""
CrossHair(CrossHair := "")
WinGetPos, X, Y, W, H
Gui, Destroy
CreateScreenshotWindow(X, Y, W, H)
Return
#If hGui := ScreenWindowUnderCursor()
WheelDown::
WheelUp:: WM_WHEEL(A_ThisHotkey = "WheelUp" ? 0 : 1, hGui)
CrossHair(OnOff = "")
{
static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
, hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
, sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
if !OnOff
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
else
for k, cursor in sys_cursors
hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
, DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}
LowLevelMouseProc(nCode, wParam, lParam)
{
static mouse_x, mouse_y, WM_MOUSEMOVE := 0x200
global mouse_x_start, mouse_y_start
if (wParam = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
SetTimer, EventHandling, -10
}
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
x := mouse_x_start < mouse_x ? mouse_x_start : mouse_x
y := mouse_y_start < mouse_y ? mouse_y_start : mouse_y
w := Abs(mouse_x - mouse_x_start)
h := Abs(mouse_y - mouse_y_start)
Gui, Select:Show, x%x% y%y% w%w% h%h% NA
Return
}
CreateScreenshotWindow(X, Y, W, H)
{
static WS_EX_LAYERED := 0x80000
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen( X "|" Y "|" W "|" H )
hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, W - 2, H - 2)
Gdip_DeletePen(pPen)
for k, v in oGuiData
if (v = 0 && IsEmpty := 1)
break
Gui, New, -Caption +E%WS_EX_LAYERED% +LastFound +AlwaysOnTop +ToolWindow +hwndhGui -DPIScale
Gui, Show, NA
oGuiData[hGui] := Gdip_CreateHBITMAPFromBitmap(pBitmap)
UpdateLayeredWindow(hGui, hdc, X, Y, W, H)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
}
ScreenWindowUnderCursor()
{
MouseGetPos,,, hGui
WinGet, PID, Pid, ahk_id %hGui%
if DllCall("GetCurrentProcessId") = PID
Return hGui
}
WM_LBUTTONDOWN()
{
if (A_Gui != "Select")
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}
WM_LBUTTONDBLCLK()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
Gui, %A_Gui%:Hide
FileSelectFile, SelectFile, S3, %A_Now%.png , Сохранить скриншот, All Files(*.*)
Gdip_SaveBitmapToFile(pBitmap, SelectFile )
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
}
WM_RBUTTONUP()
{
if (A_Gui != "Select") {
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[A_Gui])
pBitmap := ScaleImage(pBitmap, A_Gui)
Gdip_SetBitmapToClipboard(pBitmap)
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
DllCall("DeleteObject", Ptr, oGuiData[A_Gui])
oGuiData.Delete(A_Gui)
Gui, %A_Gui%:Destroy
}
}
ScaleImage(pBitmap, hGui) {
WinGetPos,,, W, H, ahk_id %hGui%
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
if (W = WidthBM)
Return pBitmap
pNewBitmap := Gdip_CreateBitmap(W, H)
G := Gdip_GraphicsFromImage(pNewBitmap)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, WidthBM, HeightBM)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap)
Return pNewBitmap
}
WM_SYSCOMMAND(wp)
{
static SC_CLOSE := 0xF060
if (wp = SC_CLOSE && A_Gui != "Select")
DllCall("DeleteObject", Ptr, oGuiData[A_Gui]), oGuiData.Delete(A_Gui)
}
WM_WHEEL(wp, hwnd)
{
Critical
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromHBITMAP(oGuiData[hwnd])
Gdip_GetImageDimensions(pBitmap, WidthBM, HeightBM)
RatioBM := WidthBM/HeightBM
SquareBM := WidthBM*HeightBM
WinGetPos, X, Y, W, H, ahk_id %hwnd%
DeltaW := Round(W/(!wp ? 10 : 11))
DeltaW := wp ? -DeltaW : DeltaW
ResultW := W + DeltaW
ResultH := Round(ResultW/RatioBM)
ResultX := X - Round(DeltaW/2)
ResultY := Y - Round((ResultH - H)/2)
SquareWin := ResultW*ResultH
if (!wp && SquareWin > 13000000) || (wp && SquareWin < 1000 && SquareWin < SquareBM)
Return, "", Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
hbm := CreateDIBSection(ResultW, ResultH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, ResultW, ResultH, 0, 0, WidthBM, HeightBM)
pPen := Gdip_CreatePen(0xFF808080, 2)
Gdip_DrawRectangle(G, pPen, 1, 1, ResultW - 2, ResultH - 2)
UpdateLayeredWindow(hwnd, hdc, ResultX, ResultY, ResultW, ResultH)
Gdip_DeletePen(pPen), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
}
Вернул горячую клавишу, чтобы соответствовала описанию — Ctrl + Space.
Немного подправил код.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться