Что нового

Рисовать мышью в окне

passwd

Новичок
Сообщения
30
Репутация
0
Здравствуйте. Подскажите, возможно ли рисовать "от руки" в GUI? Чтобы как наподобие ручкой по бумаге или как в Paint мышью по экрану =)
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
passwd
возможно ли рисовать "от руки" в GUI?
Конечно, возможно. И даже штатными средствами
Код:
#include <GuiConstantsEx.au3>

GUICreate("")
$g = GUICtrlCreateGraphic(0, 0, 400, 400)
GUISetState()

Do
  $info = GUIGetCursorInfo()
  If Not @error And $info[2] Then
    GUICtrlSetGraphic($g, $GUI_GR_PIXEL, $info[0], $info[1])
    GUICtrlSetGraphic($g, $GUI_GR_REFRESH)
    Sleep(10)
  EndIf
Until GUIGetMsg() = -3
Но, если вы хотите рисовать "по-человечески", то вам нужно изучать GDI. А если ещё и на прозрачных картинках, то GDI+. Специалистов по графике на этом форуме - единицы. И я (пока) таковым не являюсь.
 
Автор
passwd

passwd

Новичок
Сообщения
30
Репутация
0
Спасибо! Вот нашел способ через GDI+
Код:
#include <GDIPlus.au3>
#include <misc.au3>
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
$hwnd = GUICreate("Sample", 400, 400)
GUISetOnEvent(-3, "close")
GUISetState()

_GDIPlus_Startup()
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
_GDIPlus_GraphicsClear($graphics, 0xFFFFFFFF)
$pen = _GDIPlus_PenCreate(0xFF000000)

$dll = DllOpen("user32.dll")

Do
    If _IsPressed("01", $dll) And WinActive("Sample") Then
        $oldpos=MouseGetPos()
        _GDIPlus_GraphicsDrawRect($graphics,$oldpos[0],$oldpos[1],1,1,$pen)
        Do
            $pos = MouseGetPos()
            _GDIPlus_GraphicsDrawLine($graphics,$oldpos[0],$oldpos[1],$pos[0],$pos[1],$pen)
            $oldpos=$pos
        Until Not _IsPressed("01", $dll)
    EndIf
    Sleep(25)
Until False



Func close()
    _GDIPlus_PenDispose($pen)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close
Можете подсказать как делать то же самое но на прозрачном фоне, чтобы можно было потом сохранить этот файл в PNG? =)
 
Автор
passwd

passwd

Новичок
Сообщения
30
Репутация
0
Сделал окно, на котором рисовать - прозрачным. Но не получается сохранить рисунок.
Код:
#include <GDIPlus.au3>
#include <misc.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
$hwnd = GUICreate("Sample", 400, 400, -1, -1, -1, $WS_EX_LAYERED)
$button1 = GUICtrlCreateButton("save",10,5)
GUICtrlSetOnEvent(-1, "save")
GUISetBkColor(0xABCDEF, $hwnd)
GUISetOnEvent(-3, "close")
GUISetState()
_GDIPlus_Startup()
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
;_GDIPlus_GraphicsClear($graphics, 0xFFFFFFFF)
$pen = _GDIPlus_PenCreate(0xFF000000,3,0)
_WINAPI_SetLayeredWindowAttributes($hwnd, 0xABCDEF,255)

$dll = DllOpen("user32.dll")


Do
    If _IsPressed("01", $dll) And WinActive("Sample") Then
        $oldpos=MouseGetPos()
        _GDIPlus_GraphicsDrawRect($graphics,$oldpos[0],$oldpos[1],1,1,$pen)
        Do
            $pos = MouseGetPos()
            _GDIPlus_GraphicsDrawLine($graphics,$oldpos[0],$oldpos[1],$pos[0],$pos[1],$pen)
            $oldpos=$pos
        Until Not _IsPressed("01", $dll)
    EndIf
    Sleep(25)
Until False

Func save()
	$bitmap = _GDIPlus_BitmapCreateFromGraphics ( 400, 400, $graphics)
	$hCtxt = _GDIPlus_ImageGetGraphicsContext($bitmap)
	_GDIPlus_GraphicsSetSmoothingMode($hCtxt, 2)
	_GDIPlus_GraphicsDrawImage($graphics, $bitmap, 0, 0)
	_GDIPlus_ImageSaveToFile($bitmap, @DesktopDir & "\qqqqqqqqqqqq.png")
EndFunc;==>save

Func close()
    _GDIPlus_PenDispose($pen)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close
Подскажите, почему сохраняется пустой прозрачный PNG?
 
Автор
passwd

passwd

Новичок
Сообщения
30
Репутация
0
Решил рисовать на белом фоне а потом делать его прозрачным через ImageMagick такой командой:
Код:
RunWait(@ComSpec & " /c convert " & $drawing & " -transparent white " & $result)
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
passwd
Во-первых вы сами делаете фон непрозрачным:
Код:
_GDIPlus_GraphicsClear($graphics, 0xFFFFFFFF) ; Alpha = 0xFF (255)


Во-вторых рисовать прямо на поверхность окна не лучшая идея, так как при "перерисовке" фона ваши рисунки пропадут. Для примера задвиньте окно за пределы видимой области рабочего стола :smile:

Вам следует создать битмап размером с клиентскую область окна, далее все действия кистью отражать в битмап, который уже можно использовать для вывода в окно или сохранения в файл.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
passwd
Код:
#include <GDIPlus.au3>
#include <misc.au3>
#include <GUIConstants.au3>

Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)

$hwnd = GUICreate("Sample", 400, 400, -1, -1, -1, $WS_EX_LAYERED)
GUISetBkColor(0xABCDEF, $hwnd)
_WINAPI_SetLayeredWindowAttributes($hwnd, 0xABCDEF, 255)
GUISetOnEvent(-3, "close")

$button1 = GUICtrlCreateButton("save",10,5)
GUICtrlSetOnEvent(-1, "save")
GUISetState()

GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")
GUIRegisterMsg($WM_PAINT, "WM_ERASEBKGND")

_GDIPlus_Startup()
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
$bitmap = _GDIPlus_BitmapCreateFromGraphics(400, 400, $graphics)
$buffer = _GDIPlus_ImageGetGraphicsContext($bitmap)
_GDIPlus_GraphicsSetSmoothingMode($buffer, 2)
$pen = _GDIPlus_PenCreate(0xFFFF0000, 3)

$dll = DllOpen("user32.dll")

Do
    If _IsPressed("01", $dll) And WinActive("Sample") Then
        $oldpos = MouseGetPos()
        Do
            $pos = MouseGetPos()
            If $pos[0] <> $oldpos[0] Or $pos[1] <> $oldpos[1] Then
                _GDIPlus_GraphicsDrawLine($buffer, $oldpos[0], $oldpos[1], $pos[0], $pos[1], $pen)
                _GDIPlus_GraphicsDrawImage($graphics, $bitmap, 0, 0)
                $oldpos = $pos
            EndIf
            Sleep(10)
        Until Not _IsPressed("01", $dll)
    EndIf
    Sleep(10)
Until False

Func save()
    _GDIPlus_ImageSaveToFile($bitmap, @DesktopDir & "\qqqq.png")
EndFunc

Func close()
    _GDIPlus_PenDispose($pen)
    _GDIPlus_GraphicsDispose($buffer)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_Shutdown()
    DllClose($dll)
    Exit
EndFunc

Func WM_ERASEBKGND()
    _GDIPlus_GraphicsDrawImage($graphics, $bitmap, 0, 0)
    Return $GUI_RUNDEFMSG
EndFunc
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
InnI
OffTopic:
что то пробую ваш код, и что бы начать рисовать в окне, нужно очень постараться. Курсор всегда проходит насквозь
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
inververs
Курсор всегда проходит насквозь
Видимо, у вас отключено Aero (установлена упрощённая тема).


Добавлено:
Сообщение автоматически объединено:

Насколько я понял, функция _WINAPI_SetLayeredWindowAttributes() как раз для того и предназначена, чтобы делать области определённого цвета прозрачными для клика мышью. Но при включённом Aero на Win7 то ли ошибка присутствует, то ли особенность работы такая, но область становится прозрачной для клика только при одинаковых значениях компонент цвета. Например, 0xABABAB или 0x121212 и т.д. Если компоненты цветов разные, то, при включённом Aero, эта с виду прозрачная область клики не пропускает. Кстати, на Win10 клики проходят при любых значениях цветов, и там данный код не работает.


Добавлено:
Сообщение автоматически объединено:

passwd
Решил рисовать на белом фоне а потом делать его прозрачным через ImageMagick
В моём примере (Ответ #6) вы можете рисовать на фоне любого цвета с любой степенью прозрачности и даже на картинке. Также нет необходимости применять к окну стиль $WS_EX_LAYERED. Сохранение в PNG всё равно будет с прозрачным фоном, т.к. сохраняется bitmap из памяти, у которого фон не закрашен.
 
Верх