Bilddaten aus Picture Element kopieren - Wie?

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
Gucky_87
Posts: 376
Joined: 03 Jul 2014, 05:09

Bilddaten aus Picture Element kopieren - Wie?

22 Aug 2019, 09:59

Hallöle zusammen,

ich hab ein GUI und darin ein normales Picture Element.
Mittes der GDIp Library zeichne ich Kurven in das Fenster und möchte per Script diese Bilddaten
ins Clipboard kopieren, um sie z.B. in Paint.NET einzufügen.

Gibt es dafür eine Möglichkeit?


Danke im Voraus,

Gucky.
aifritz
Posts: 301
Joined: 29 Jul 2018, 11:30
Location: Germany

Re: Bilddaten aus Picture Element kopieren - Wie?

24 Aug 2019, 09:38

Hallo Gucky,

mit dieser Funktion kannst Du einen Bildausschnitt definieren, der in das ClipBoard kopiert wird.

Code: Select all

CaptureScreen("100, 100, 200, 200")

Code: Select all

/*
 *-------------------------------------------------------------------------------------
 *	Screen Capture with Transparent Windows and Mouse Cursor:
 *			http://www.autohotkey.com/forum/topic18146.html
 *-------------------------------------------------------------------------------------
	CaptureScreen(aRect, bCursor, sFileTo, nQuality)
		1) If the optional parameter bCursor is True, captures the cursor too.
		2) If the optional parameter sFileTo is 0, set the image to Clipboard.
		   If it is omitted or "", saves to screen.bmp in the script folder,
		   otherwise to sFileTo which can be BMP/JPG/PNG/GIF/TIF.
		3) The optional parameter nQuality is applicable only when sFileTo is JPG. Set it to the desired quality level of the resulting JPG, an integer between 0 - 100.
		4) If aRect is 0/1/2/3, captures the entire desktop/active window/active client area/active monitor.
		5) aRect can be comma delimited sequence of coordinates, e.g., "Left, Top, Right, Bottom" or "Left, Top, Right, Bottom, Width_Zoomed, Height_Zoomed".
		   In this case, only that portion of the rectangle will be captured. Additionally, in the latter case, zoomed to the new width/height, Width_Zoomed/Height_Zoomed.

	Example:
		CaptureScreen(0)
		CaptureScreen(1)
		CaptureScreen(2)
		CaptureScreen(3)
		CaptureScreen("100, 100, 200, 200")
		CaptureScreen("100, 100, 200, 200, 400, 400")   ; Zoomed

	Convert:
		Convert(sFileFr, sFileTo, nQuality)
		Convert("C:\image.bmp", "C:\image.jpg")
		Convert("C:\image.bmp", "C:\image.jpg", 95)
		Convert(0, "C:\clip.png")   ; Save the bitmap in the clipboard to sFileTo if sFileFr is "" or 0.
*/

CaptureScreen(aRect = 0, bCursor = False, sFile = "", nQuality = "")
{
	If	!aRect
	{
		SysGet, nL, 76  ; virtual screen left & top
		SysGet, nT, 77
		SysGet, nW, 78	; virtual screen width and height
		SysGet, nH, 79
	}
	Else If	aRect = 1
		WinGetPos, nL, nT, nW, nH, A
	Else If	aRect = 2
	{
		WinGet, hWnd, ID, A
		VarSetCapacity(rt, 16, 0)
		DllCall("GetClientRect" , "Uint", hWnd, "Uint", &rt)
		DllCall("ClientToScreen", "Uint", hWnd, "Uint", &rt)
		nL := NumGet(rt, 0, "int")
		nT := NumGet(rt, 4, "int")
		nW := NumGet(rt, 8)
		nH := NumGet(rt,12)
	}
	Else If	aRect = 3
	{
		VarSetCapacity(mi, 40, 0)
		DllCall("GetCursorPos", "int64P", pt)
		DllCall("GetMonitorInfo", "Uint", DllCall("MonitorFromPoint", "int64", pt, "Uint", 2), "Uint", NumPut(40,mi)-4)
		nL := NumGet(mi, 4, "int")
		nT := NumGet(mi, 8, "int")
		nW := NumGet(mi,12, "int") - nL
		nH := NumGet(mi,16, "int") - nT
	}
	Else
	{
		StringSplit, rt, aRect, `,, %A_Space%%A_Tab%
		nL := rt1	; convert the Left,top, right, bottom into left, top, width, height
		nT := rt2
		nW := rt3 - rt1
		nH := rt4 - rt2
		znW := rt5
		znH := rt6
	}

	mDC := DllCall("CreateCompatibleDC", "Uint", 0)
	hBM := CreateDIBSection(mDC, nW, nH)
	oBM := DllCall("SelectObject", "Uint", mDC, "Uint", hBM)
	hDC := DllCall("GetDC", "Uint", 0)
	DllCall("BitBlt", "Uint", mDC, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", hDC, "int", nL, "int", nT, "Uint", 0x40000000 | 0x00CC0020)
	DllCall("ReleaseDC", "Uint", 0, "Uint", hDC)
	If	bCursor
		CaptureCursor(mDC, nL, nT)
	DllCall("SelectObject", "Uint", mDC, "Uint", oBM)
	DllCall("DeleteDC", "Uint", mDC)
	If	znW && znH
		hBM := Zoomer(hBM, nW, nH, znW, znH)
	If	sFile = 0
		SetClipboardData(hBM)
	Else	Convert(hBM, sFile, nQuality), DllCall("DeleteObject", "Uint", hBM)
}

CaptureCursor(hDC, nL, nT)
{
	VarSetCapacity(mi, 20, 0), mi := Chr(20)
	DllCall("GetCursorInfo", "Uint", &mi)
	bShow   := NumGet(mi, 4)
	hCursor := NumGet(mi, 8)
	xCursor := NumGet(mi,12)
	yCursor := NumGet(mi,16)

	If	bShow && hCursor:=DllCall("CopyIcon", "Uint", hCursor)
	{
	VarSetCapacity(ni, 20, 0)
	DllCall("GetIconInfo", "Uint", hCursor, "Uint", &ni)
	bIcon    := NumGet(ni, 0)
	xHotspot := NumGet(ni, 4)
	yHotspot := NumGet(ni, 8)
	hBMMask  := NumGet(ni,12)
	hBMColor := NumGet(ni,16)

	DllCall("DrawIcon", "Uint", hDC, "int", xCursor - xHotspot - nL, "int", yCursor - yHotspot - nT, "Uint", hCursor)
	DllCall("DestroyIcon", "Uint", hCursor)
	If	hBMMask
	DllCall("DeleteObject", "Uint", hBMMask)
	If	hBMColor
	DllCall("DeleteObject", "Uint", hBMColor)
	}
}

Zoomer(hBM, nW, nH, znW, znH)
{
	mDC1 := DllCall("CreateCompatibleDC", "Uint", 0)
	mDC2 := DllCall("CreateCompatibleDC", "Uint", 0)
	zhBM := CreateDIBSection(mDC2, znW, znH)
	oBM1 := DllCall("SelectObject", "Uint", mDC1, "Uint",  hBM)
	oBM2 := DllCall("SelectObject", "Uint", mDC2, "Uint", zhBM)
	DllCall("SetStretchBltMode", "Uint", mDC2, "int", 4)
	DllCall("StretchBlt", "Uint", mDC2, "int", 0, "int", 0, "int", znW, "int", znH, "Uint", mDC1, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", 0x00CC0020)
	DllCall("SelectObject", "Uint", mDC1, "Uint", oBM1)
	DllCall("SelectObject", "Uint", mDC2, "Uint", oBM2)
	DllCall("DeleteDC", "Uint", mDC1)
	DllCall("DeleteDC", "Uint", mDC2)
	DllCall("DeleteObject", "Uint", hBM)
	Return	zhBM
}

Convert(sFileFr = "", sFileTo = "", nQuality = "")
{
	If	sFileTo  =
		sFileTo := A_ScriptDir . "\screen.bmp"
	SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

	If Not	hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
		Return	sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo . "\" . sNameTo . ".bmp") : ""
	VarSetCapacity(si, 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

	If	!sFileFr
	{
		DllCall("OpenClipboard", "Uint", 0)
		If	 DllCall("IsClipboardFormatAvailable", "Uint", 2) && (hBM:=DllCall("GetClipboardData", "Uint", 2))
		DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0, "UintP", pImage)
		DllCall("CloseClipboard")
	}
	Else If	sFileFr Is Integer
		DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0, "UintP", pImage)
	Else	DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr), "UintP", pImage)

	DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
	VarSetCapacity(ci,nSize,0)
	DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
	Loop, %	nCount
		If	InStr(Ansi4Unicode(NumGet(ci,76*(A_Index-1)+44)), "." . sExtTo)
		{
			pCodec := &ci+76*(A_Index-1)
			Break
		}
	If	InStr(".JPG.JPEG.JPE.JFIF", "." . sExtTo) && nQuality<>"" && pImage && pCodec
	{
	DllCall("gdiplus\GdipGetEncoderParameterListSize", "Uint", pImage, "Uint", pCodec, "UintP", nSize)
	VarSetCapacity(pi,nSize,0)
	DllCall("gdiplus\GdipGetEncoderParameterList", "Uint", pImage, "Uint", pCodec, "Uint", nSize, "Uint", &pi)
	Loop, %	NumGet(pi)
		If	NumGet(pi,28*(A_Index-1)+20)=1 && NumGet(pi,28*(A_Index-1)+24)=6
		{
			pParam := &pi+28*(A_Index-1)
			NumPut(nQuality,NumGet(NumPut(4,NumPut(1,pParam+0)+20)))
			Break
		}
	}

	If	pImage
		pCodec	? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage, "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec, "Uint", pParam) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage, "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap), DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

	DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
	DllCall("FreeLibrary", "Uint", hGdiPlus)
}

CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
	NumPut(VarSetCapacity(bi, 40, 0), bi)
	NumPut(nW, bi, 4)
	NumPut(nH, bi, 8)
	NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
	NumPut(0,  bi,16)
	Return	DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", 0, "UintP", pBits, "Uint", 0, "Uint", 0)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
	DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
	hFile:=	DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0, "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
	DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16, "Uint", 6, "UintP", 0, "Uint", 0)
	DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
	DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
	DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
	DllCall("CloseHandle", "Uint", hFile)
}

SetClipboardData(hBitmap)
{
	DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
	hDIB :=	DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
	pDIB :=	DllCall("GlobalLock", "Uint", hDIB)
	DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
	DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
	DllCall("GlobalUnlock", "Uint", hDIB)
	DllCall("DeleteObject", "Uint", hBitmap)
	DllCall("OpenClipboard", "Uint", 0)
	DllCall("EmptyClipboard")
	DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
	DllCall("CloseClipboard")
}

Unicode4Ansi(ByRef wString, sString)
{
	nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
	VarSetCapacity(wString, nSize * 2)
	DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize)
	Return	&wString
}

Ansi4Unicode(pString)
{
	nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
	VarSetCapacity(sString, nSize)
	DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
	Return	sString
}

/*
 *====================================================================================
 *									END OF FILE
 *====================================================================================
 */
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Bilddaten aus Picture Element kopieren - Wie?

25 Aug 2019, 04:22

Moin,

wie und wohin genau zeichnest du Deine Kurven? Wenn Du an ein Bitmap Handle (HBITMAP) kommen kannst (z.B. STM_GETIMAGE), sollte es die Funktion SetClipboardData() aus dem von aifritz eingestellten Skript tun.
User avatar
Gucky_87
Posts: 376
Joined: 03 Jul 2014, 05:09

Re: Bilddaten aus Picture Element kopieren - Wie?

26 Aug 2019, 05:32

Hallöle,

hier ein Scriptauszug (noch im Test.

Code: Select all

    Gui, Main: Add, Picture     , x10 y10 w640 h480            +Border -BackgroundTrans      vPICTURE , 
    ...
    ...
    ...

    pBitmap := Gdip_CreateBitmap(Width, Height)
    G       := Gdip_GraphicsFromImage(pBitmap)
    Gdip_SetSmoothingMode(G, 0)
    pBrush  := Gdip_BrushCreateSolid(0xffffffff)
    Gdip_FillRectangle(G, pBrush, 0, 0, Width, Height)
    pBrush  := Gdip_BrushCreateSolid(0xff000000)

    ...
    Hier werden dann Linien, Kurven, etc. gezeichnet.
    ...
    Gdip_DeleteBrush(pBrush)
    hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
    GuiControl, Main: , PICTURE, HBITMAP:%hBitMap%
    Gdip_SetBitmapToClipboard(pBitmap)
    Gdip_SaveBitmapToFile(pBitmap, A_Desktop . "\Test.bmp") ; 0x30101   0x21808   0x26200a   
    Gdip_DeleteGraphics(G)
    Gdip_DisposeImage(pBitmap)
Dieses PICTURE würde ich halt gerne...
1) unverändert ins Clipboard kopieren (zur weiteren Bearbeitung z.B. mit Grafikprogrammen) und
2) als BMP Datei speichern (die müsste dann allerdings 2 Bit sein und nicht 24 oder 32 Bit), aber die Idee kam mir erst gestern, daher habe ich hierzu noch keinen Ansatz.
Allerdings brachte meine kurze Suche im Netz bisher keinen Aufschluss darüber, wie ich in der GDIp Library das 2-Bit Bitmap Format einstellen kann.

Ach so, ja ,icj verwende diese GDIp Library.

Wie immer lieben Dank für Eure Tipps, GDIp Library.
Nach meinen Recherchen sollte die recht aktuell sein.

Gucky.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 43 guests