/*
------------------------------------------
左键拖动选择屏幕范围 v1.5 By FeiYue
说明:
按热键“F1”开始左键拖动选择范围,
然后点击范围确定,点其他位置取消
------------------------------------------
*/
F1:: MsgBox, 4096,, % GetRange(x,y,w,h) "范围:" x "," y "," w "," h
F2:: ;保存图片
file := A_ScriptDir . "\test.png"
GetRange(x,y,w,h)
SaveScreenshotToFile(x,y,w,h, file, Cursor:=1)
; SaveScreenshotToFile(0, 0, A_ScreenWidth, A_ScreenHeight, file, Cursor:=1)
Run, % file
return
GetRange(ByRef x="",ByRef y="",ByRef w="",ByRef h="")
{
Hotkey, *LButton, LButton_Return, On
CoordMode, Mouse
Ptr:=A_PtrSize ? "UPtr":"UInt", int:="int"
nW:=A_ScreenWidth, nH:=A_ScreenHeight
;-- 生成画布窗口和选框窗口
Gui, Canvas:New, +AlWaysOnTop +ToolWindow -Caption -DPIScale
Gui, Canvas:Add, Picture, x0 y0 w%nW% h%nH% +0xE HwndpicID
range_create("Red","Canvas")
;-- 截屏到内存图像并关联到画布窗口的图片控件
hDC:=DllCall("GetDC", Ptr,0, Ptr)
mDC:=DllCall("CreateCompatibleDC", Ptr,hDC, Ptr)
hBM:=DllCall("CreateCompatibleBitmap", Ptr,hDC, int,nW, int,nH, Ptr)
oBM:=DllCall("SelectObject", Ptr,mDC, Ptr,hBM, Ptr)
DllCall("BitBlt", Ptr,mDC, int,0, int,0, int,nW, int,nH
, Ptr,hDC, int,0, int,0, int,0x00CC0020|0x40000000)
SendMessage, 0x172, 0, hBM,, ahk_id %picID%
if ( E:=ErrorLevel )
DllCall("DeleteObject", Ptr,E)
DllCall("SelectObject", Ptr,mDC, Ptr,oBM)
DllCall("DeleteDC", Ptr,mDC)
DllCall("ReleaseDC", Ptr,0, Ptr,hDC)
;-- 显示画布窗口,开始等待选择范围
Gui, Canvas:Show, NA x0 y0 w%nW% h%nH%
ok:=w:=h:=0
ListLines, Off
Loop {
Sleep, 100
MouseGetPos, x2, y2
if GetkeyState("LButton","P")!=ok
{
ToolTip
ok:=!ok, x1:=x2, y1:=y2
if (ok and x2>x and y2>y and x2<x+w-1 and y2<y+h-1)
Break
}
if (ok=0)
{
ToolTip, % w+h>5 ? "点击范围确定,点其他位置取消"
: "请按下鼠标左键并拖动选择范围"
Continue
}
x:=x1<x2 ? x1:x2, y:=y1<y2 ? y1:y2
w:=Abs(x1-x2)+1, h:=Abs(y1-y2)+1
if (w+h>5)
range_show(x,y,w,h)
else
range_hide()
}
ListLines, On
range_delete()
Gui, Canvas:Destroy
;-- 不需要了才清除内存图像
DllCall("DeleteObject", Ptr,hBM)
KeyWait, LButton
Hotkey, *LButton, LButton_Return, Off
LButton_Return:
Return
}
range_create(color="Red", Owner="") {
j:=Owner ? "+Owner" Owner : "+ToolWindow"
Loop 4 {
i:=A_Index
Gui,range_%i%:+AlWaysOnTop -Caption %j% -DPIScale +E0x08000000
Gui,range_%i%:Color, %color%
}
Gui, Range:+LastFound +AlWaysOnTop -Caption %j% -DPIScale +E0x08000000
WinSet, Transparent, 50
Gui, Range:Color, Yellow
}
range_show(x, y, w, h, r:=2) {
Loop 4 { ; 顺时针上右下左
i:=A_Index
, x1:=i=2 ? x+w-r : x
, y1:=i=3 ? y+h-r : y
, w1:=i=1 or i=3 ? w : r
, h1:=i=1 or i=3 ? r : h
Gui, range_%i%:Show, NA x%x1% y%y1% w%w1% h%h1%
}
x+=r, y+=r, w-=2*r, h-=2*r
Gui, Range:Show, NA x%x% y%y% w%w% h%h%
}
range_hide() {
Loop 4
Gui, range_%A_Index%:Hide
Gui, Range:Hide
}
range_delete() {
Loop 4
Gui, range_%A_Index%:Destroy
Gui, Range:Destroy
}
;
;------------------------
; 截屏代码
;------------------------
SaveScreenshotToFile(x, y, w, h, filePath, captureCursor:=false)
{
gdip := new GDIplus
hBitmap:=GetHBitmapFromScreen(x, y, w, h, captureCursor)
pBitmap := gdip.BitmapFromHBitmap(hBitmap)
DllCall("DeleteObject", Ptr, hBitmap)
gdip.SaveBitmapToFile(pBitmap, filePath)
gdip.DisposeImage(pBitmap)
}
GetHBitmapFromScreen(x, y, w, h, captureCursor) {
hDC := DllCall("GetDC", Ptr, 0, Ptr)
hBM := DllCall("CreateCompatibleBitmap", Ptr, hDC, Int, w, Int, h, Ptr)
pDC := DllCall("CreateCompatibleDC", Ptr, hDC, Ptr)
oBM := DllCall("SelectObject", Ptr, pDC, Ptr, hBM, Ptr)
DllCall("BitBlt", Ptr, pDC, Int, 0, Int, 0, Int, w, Int, h
, Ptr, hDC, Int, x, Int, y, UInt, 0x00CC0020)
( captureCursor && CaptureCursor(pDC, x, y) )
DllCall("SelectObject", Ptr, pDC, Ptr, oBM)
DllCall("DeleteDC", Ptr, pDC)
DllCall("ReleaseDC", Ptr, 0, Ptr, hDC)
Return hBM ; should be deleted with DllCall("DeleteObject", Ptr, hBM)
}
CaptureCursor(hDC, x, y) {
VarSetCapacity(CURSORINFO, szCI := 4*2 + A_PtrSize + 8, 0)
NumPut(szCI, CURSORINFO)
DllCall("GetCursorInfo", Ptr, &CURSORINFO)
bShow := NumGet(CURSORINFO, 4, "UInt")
hCursor := NumGet(CURSORINFO, 4*2)
xCursor := NumGet(CURSORINFO, 4*2 + A_PtrSize, "Int")
yCursor := NumGet(CURSORINFO, 4*2 + A_PtrSize + 4, "Int")
if bShow && hCursor := DllCall("CopyIcon", Ptr, hCursor, Ptr)
{
VarSetCapacity(ICONINFO, 4*2 + A_PtrSize*3, 0)
DllCall("GetIconInfo", Ptr, hCursor, Ptr, &ICONINFO)
bIcon := NumGet(ICONINFO, "UInt")
xHotspot := NumGet(ICONINFO, 4, "UInt")
yHotspot := NumGet(ICONINFO, 4*2, "UInt")
hBMMask := NumGet(ICONINFO, 4*2 + A_PtrSize)
hBMColor := NumGet(ICONINFO, 4*2 + A_PtrSize*2)
DllCall("DrawIcon", Ptr, hDC, Int, xCursor - xHotspot - x
, Int, yCursor - yHotspot - y, Ptr, hCursor)
DllCall("DestroyIcon", Ptr, hCursor)
( hBMMask && DllCall("DeleteObject", Ptr, hBMMask) )
( hBMColor && DllCall("DeleteObject", Ptr, hBMColor) )
}
}
class GDIplus {
__New() {
if !DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
DllCall("LoadLibrary", Str, "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), NumPut(1,si,"char")
DllCall("gdiplus\GdiplusStartup", PtrP, pToken, Ptr, &si, Ptr, 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", Ptr, this.token)
if hModule := DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
DllCall("FreeLibrary", Ptr, hModule)
}
BitmapFromHBitmap(hBitmap, Palette := 0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP"
, Ptr, hBitmap, Ptr, Palette, PtrP, pBitmap)
return pBitmap ; should be deleted with this.DisposeImage(pBitmap)
}
SaveBitmapToFile(pBitmap, sOutput, Quality=75) {
SplitPath, sOutput,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", UIntP, nCount, UIntP, nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", UInt, nCount, UInt, nSize, Ptr, &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
idx := (48+7*A_PtrSize)*(A_Index-1)
sString := StrGet(NumGet(ci, idx+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75
{
DllCall("gdiplus\GdipGetEncoderParameterListSize"
, Ptr, pBitmap, Ptr, pCodec, UintP, nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList"
, Ptr, pBitmap, Ptr, pCodec, UInt, nSize, Ptr, &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt") {
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1)
&& (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if A_IsUnicode
pOutput := &sOutput
else {
VarSetCapacity(wOutput, StrPut(sOutput, "UTF-16")*2, 0)
StrPut(sOutput, &wOutput, "UTF-16")
pOutput := &wOutput
}
E := DllCall("gdiplus\GdipSaveImageToFile"
, Ptr, pBitmap, Ptr, pOutput, Ptr, pCodec, UInt, p ? p : 0)
return E ? -5 : 0
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", Ptr, pBitmap)
}
}
暂无讨论,说说你的看法吧