PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Рисование на скриншоте


Рисование на скриншоте

Сообщений 1 страница 3 из 3

1

Решил попробовать рисование на скриншоте линий, фигур, стрелок.

Код:
EnableExplicit

Declare CaptureActiveWindow()

; Загружаем кодеры
UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()
UsePNGImageEncoder()

#Image0 = 0
#Image1 = 1
#Image2 = 2
#Window0 = 0
#Menu0 = 0

Enumeration
	#mSave
	#mCapture
	#mToClipboard
EndEnumeration

Enumeration
	#Canvas0
	#Combo
	#ChB
	#btnColor
	#btnCapture
	#btnToClipboard
	#btnV
EndEnumeration

Define LineWidth = 2, imgH, imgW, cY, cX

Define bitPointDown = 0
Define bitPointUp = 0
Define hImage
Define hImage1
Define hImage2
Define hDC_tmp
Define hDC
Define hCanvas
Define obj
Define Mode = 0
Define LineH, LineW
Define File$
Define Color = $2A04FF, tmp
; Define *Buffer

Define point1.Point
Define point2.Point
point1\x = 0
point1\y = 0

; загружаем рисунок
; LoadImage(#Image0, "C:\PureBasic\Source\file.png")
CaptureActiveWindow()
GetClipboardImage(#Image0)

imgH = ImageHeight(#Image0)
imgW = ImageWidth(#Image0)
hImage = ImageID(#Image0)

If OpenWindow(#Window0, 0, 0, imgW, imgH+30, "Рисование", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CanvasGadget(#Canvas0, 0, 30, imgW, imgH)
	hCanvas = GadgetID(#Canvas0)
	ComboBoxGadget(#Combo, 10, 3, 120, 21)
	AddGadgetItem(#Combo, -1, "Линия")
	AddGadgetItem(#Combo, -1, "Прямоугольник")
	AddGadgetItem(#Combo, -1, "Элипс")
	AddGadgetItem(#Combo, -1, "Обрезать")
	SetGadgetState(#Combo, 0)

	CheckBoxGadget(#ChB, 140, 4, 80, 21, "Заполнить")
	; 	ButtonGadget(#btnColor, 220, 2, 26, 26, "")
	CanvasGadget(#btnColor, 220, 2, 26, 26, #PB_Canvas_Buttons)

	If StartDrawing(CanvasOutput(#btnColor))
    Box(0, 0, 26, 26, Color)
    StopDrawing()
	EndIf

	ButtonGadget(#btnV, 250, 2, 24, 24, Chr($25BC)) ; "v"

	;--> Menu
	If CreatePopupMenu(#Menu0) ; Создаёт всплывающее меню
    MenuItem(#mSave, "Сохранить")
    MenuItem(#mCapture, "Из буфера")
    MenuItem(#mToClipboard, "В буфер")
    ;     MenuBar()
	EndIf

	SetGadgetAttribute(#Canvas0, #PB_Canvas_Image, hImage)
	; 	hImage1 = GetGadgetAttribute(#Canvas0, #PB_Canvas_Image)
	hDC = GetWindowDC_(hCanvas)




	Repeat
    Select WaitWindowEvent()
    	Case #PB_Event_Gadget

        Select EventGadget()
        	Case #Canvas0
            Select EventType()
            	Case #PB_EventType_LeftButtonDown
                cX = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseX)
                cY = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseY)
                bitPointDown = 1
                point1\x = cX
                point1\y = cY

                hDC_tmp = CreateCompatibleDC_(hDC)
                hImage = CreateCompatibleBitmap_(hDC, imgW, imgH)
                obj=SelectObject_(hDC_tmp,hImage)
                BitBlt_(hDC_tmp, 0, 0, imgW, imgH, hDC, 0, 0, #SRCCOPY)

            	Case #PB_EventType_LeftButtonUp
                bitPointDown = 0
;                 bitPointUp = 1
                If Mode = 3
                	imgW = cX - point1\x
                	imgH = cY - point1\y
                	If GrabImage(#Image0, #Image2, point1\x, point1\y, imgW, imgH)
                    hImage2 = StartDrawing(ImageOutput(#Image2))
                    BitBlt_(hDC, point1\x, point1\y, imgW, imgH, hImage2, 0, 0, #SRCCOPY)
;                     BitBlt_(hImage2, point1\x, point1\y, imgW, imgH, hDC, 0, 0, #SRCCOPY)
                	    StopDrawing()
                    hImage = ImageID(#Image2)
                    ResizeGadget(#Canvas0, #PB_Ignore, #PB_Ignore, imgW, imgH)
                    ResizeWindow(#Window0, #PB_Ignore, #PB_Ignore, imgW, imgH+30)
                    SetGadgetAttribute(#Canvas0, #PB_Canvas_Image, hImage)
;                     FreeImage(#Image2)
                    SetGadgetState(#Combo, 0)
                    Mode = 0
                    If CreateImage(#Image0, imgW, imgH)
                    	hImage2 = StartDrawing(ImageOutput(#Image0))
                    	BitBlt_(hImage2, 0, 0, imgW, imgH, hDC, 0, 0, #SRCCOPY)
                        StopDrawing()
                        FreeImage(#Image2)
                    EndIf
                	EndIf
                EndIf
                DeleteObject_(hImage)
                DeleteObject_(obj)
                DeleteDC_(hDC_tmp)

            	Case #PB_EventType_MouseMove
                If bitPointDown
                	cX = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseX)
                	cY = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseY)
                	;             	hImage2 = StartDrawing(CanvasOutput(#Canvas0))
                	StartDrawing(CanvasOutput(#Canvas0))
                	If GetGadgetState(#ChB) = #PB_Checkbox_Checked And Mode And Mode < 3
                    DrawingMode(#PB_2DDrawing_AlphaBlend)
                	Else
                    DrawingMode(#PB_2DDrawing_Outlined)
                	EndIf
                	DrawImage(hImage, 0, 0)
                	Select Mode
                    Case 0
                    	LineXY(point1\x, point1\y, cX, cY, Color)
                    Case 1
                    	Box(point1\x, point1\y, cX - point1\x, cY - point1\y, Color | $44000000)
                    Case 2
                    	Ellipse(point1\x, point1\y, Abs(cX - point1\x), cY - point1\y, Color | $44000000)
                    Case 3
                    	Box(point1\x, point1\y, cX - point1\x, cY - point1\y, Color | $44000000)
                	EndSelect
                	StopDrawing()
                EndIf
            EndSelect

        	Case #btnV
            DisplayPopupMenu(#Menu0, WindowID(#Window0))  ; покажем всплывающее Меню

        	Case #btnColor
            Select EventType()
            	Case #PB_EventType_LeftClick
                tmp = ColorRequester()
                If tmp > -1
                	Color = tmp
                	If StartDrawing(CanvasOutput(#btnColor))
                    Box(0, 0, 26, 26, Color)
                    StopDrawing()
                	EndIf
                EndIf
            EndSelect

        	Case #Combo
            Mode = GetGadgetState(#Combo)
        EndSelect
    	Case #PB_Event_Menu        ; кликнут элемент всплывающего Меню
        Select EventMenu()	   ; получим кликнутый элемент Меню...
        	Case #mSave
            File$ = SaveFileRequester("Сохранение", "скрин.png", "Изображение|*.png;*.jpg;*.gif", 0)
            If File$ And CreateImage(#Image2, imgW, imgH)
            	hImage2 = StartDrawing(ImageOutput(#Image2))
            	BitBlt_(hImage2, 0, 0, imgW, imgH, hDC, 0, 0, #SRCCOPY)
                StopDrawing()
                SetClipboardImage(#Image2)
            	SaveImage(#Image2, File$) ; Сохранение
                FreeImage(#Image2)
            EndIf
        	Case #mCapture
            If GetClipboardImage(#Image0) ; если в буфере действительно изображение, то
            	imgH = ImageHeight(#Image0)
            	imgW = ImageWidth(#Image0)
            	hImage = ImageID(#Image0)
            	ResizeGadget(#Canvas0, #PB_Ignore, #PB_Ignore, imgW, imgH)
            	ResizeWindow(#Window0, #PB_Ignore, #PB_Ignore, imgW, imgH+30)
            	SetGadgetAttribute(#Canvas0, #PB_Canvas_Image, hImage)
            Else
            	MessageRequester("", "В буфере нет изображения")
            EndIf
        	Case #mToClipboard
            If CreateImage(#Image2, imgW, imgH)
            	hImage2 = StartDrawing(ImageOutput(#Image2))
            	BitBlt_(hImage2, 0, 0, imgW, imgH, hDC, 0, 0, #SRCCOPY)
                StopDrawing()
                SetClipboardImage(#Image2)
                FreeImage(#Image2)
            EndIf
        EndSelect
    	Case #PB_Event_CloseWindow
        ReleaseDC_(WindowID(#Window0),hDC)
        FreeImage(#PB_All)
        CloseWindow(0)
        End
    EndSelect
	ForEver
EndIf


Procedure CaptureActiveWindow() ; функция из код-архива, но испорчена для нужного результата
	Protected Handle
	Protected hDC
	Protected RECT.RECT
	Protected hPrinterDC

	;   Handle = GetForegroundWindow_()
	Handle = GetDesktopWindow_() ; получим рабочий стол вместа окна, так как с компилятора ничего не получить
	hDC = GetWindowDC_(Handle)
	GetWindowRect_(Handle,@RECT.RECT)

	With RECT
    \right-\left - 400 ; добавил - 400, чтобы не на весь экран было окно
    \bottom-\top - 400 ; добавил - 400, чтобы не на весь экран было окно
    CreateImage(0,\right,\bottom)
    hPrinterDC = StartDrawing(ImageOutput(0))
    If hPrinterDC
    	BitBlt_(hPrinterDC,0,0,\right,\bottom,hDC,0,0,#SRCCOPY)
    	StopDrawing()
    EndIf

	EndWith

	ReleaseDC_(Handle,hDC)
	SetClipboardImage(0)
EndProcedure

Ниже была начальная попытка сделать на векторной графике, может ещё вернусь к ней.

Код:
EnableExplicit

; Загружаем кодеры
UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()

#Image0 = 0
#Window0 = 0
#Canvas0 = 0
Define LineWidth = 2, imgH, imgW, cY, cX

Define bitPointDown = 0
Define bitPointUp = 0
Define CVO
Define hImage

Define point1.Point
Define point2.Point
point1\x = 111
point1\y = 111

; загружаем рисунок
LoadImage(#Image0, "C:\PureBasic\Source\file.png")
imgH = ImageHeight(#Image0)
imgW = ImageWidth(#Image0)
hImage = ImageID(#Image0)

If OpenWindow(#Window0, 0, 0, imgW, imgH+30, "Рисование", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CanvasGadget(#Canvas0, 0, 30, imgW, imgH)
	ButtonGadget (1, 10, 0, 200, 30, "кнопка")
	
	SetGadgetAttribute(#Canvas0, #PB_Canvas_Image, hImage)

	Repeat
    Select WaitWindowEvent()
    	Case #PB_Event_Gadget
        Select EventType()
        	Case #PB_EventType_LeftButtonDown:
            cX = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseX)
            cY = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseY)
            bitPointDown = 1
            point1\x = cX
            point1\y = cY
;             StartVectorDrawing(CanvasVectorOutput(#Canvas0, #PB_Unit_Pixel))
;             VectorSourceColor($FF2A04FF)
        	Case #PB_EventType_LeftButtonUp:
            cX = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseX)
            cY = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseY)
            bitPointDown = 0
            bitPointUp = 1
            ; bitPoint = 1
            point2\x = cX
            point2\y = cY
            	StartVectorDrawing(CanvasVectorOutput(#Canvas0, #PB_Unit_Pixel))
            MovePathCursor(point1\x, point1\y)
            AddPathLine(cX, cY)
            StrokePath(LineWidth)
            	StopVectorDrawing()
            
        	Case #PB_EventType_MouseMove:
            If bitPointDown
            	cX = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseX)
            	cY = GetGadgetAttribute(#Canvas0, #PB_Canvas_MouseY)
            	StartVectorDrawing(CanvasVectorOutput(#Canvas0, #PB_Unit_Pixel))
            	BeginVectorLayer(55)
            	MovePathCursor(point1\x, point1\y)
            	AddPathLine(cX, cY)
            	StrokePath(LineWidth)
            	EndVectorLayer()
            	StopVectorDrawing()
;             	DrawVectorImage(hImage)
            EndIf
        EndSelect
        
        Select EventGadget()
        	Case 1
            MessageRequester("", "")
        EndSelect
    	Case #PB_Event_CloseWindow
        SaveImage(#Image0, "C:\PureBasic\Source\file1.png") ; Сохранение
        FreeImage(#Image0)
        CloseWindow(0)
        End
    EndSelect
	ForEver
EndIf

Отредактировано AZJIO (01.09.2020 04:43:42)

0

2

AZJIO написал(а):

Решил попробовать рисование на скриншоте линий, фигур, стрелок.

Сдаётся мне, что стандартный пример PureBasic - CanvasGadget example file (c) Fantaisie Software
похоже делает то же самое, если его дополнить скриншотером.

0

3

ВиниПур
Изучаю и этот пример сейчас, уже не напрочь забыл что он там есть, наверняка когда нибудь открывал его.

Пока писал кучу вопросов задавал, но все они решились. В коде отсутствует оптимизация. Во первых я хочу попробовать поэкспериментировать с CopyImage(#Image1 , #Image2), потому что я копирую с помощью BitBlt_(), так как я думал не экономично создавать ещё один гаджет канвас с #Image2 для копирования, но потом понял что возможно CreateImage(#Image... решает этот вопрос. Также не хватает буферизации, чтобы по Ctrl+Z отменить хотя бы последнюю операцию. То есть создать #ImageBackup или hImageBackup. Также удивило что в справке указано для StartDrawing возвращающее значение как 0 - нельзя рисовать и не 0 можно рисовать, на самом деле возвращает контекст устройства, но так как PureBasic кросплатформенный, то решили не использовать такое понятие, но тогда копирование должно осуществляться внутренними функциями, оно так и есть с помощью CopyImage, но она требует создавать ещё один #Image зарегистрированный внутренне, когда можно было бы использовать дескрипторы возвращённые например контекст устройства канваса, я же не могу получить из дескриптора #Image. В общем я долго распутывал и это только начало.
___________________________
Обновления
Добавил кнопку "Отмена", позволяет отменить 1 раз. При каждом мазке делает предварительную копию рисунка.
Добавил "Кисть", избавился от BitBlt_(...)
Убрал UseJPEGImageDecoder() и UsePNGImageDecoder() работает без них, но размер с 500кб упал до100кб. И вернул назад, потому что LoadImage() не работает, как и написано в справке.
Сохраняло в BMP не важно от расширения, исправил, теперь поддерживает jpg и png, в остальных случаях в bmp.
Добавил если нажата клавиша Ctrl то фигуры рисуются правильными (квадрат, круг), а линии горизонтальными или вертикальными.
Скачать

Отредактировано AZJIO (01.09.2020 23:09:20)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Рисование на скриншоте