1

Тема: AHK: графика

Есть необходимость построить прямо в окне AutoHotkey GUI простейшие графические изображения (линии, точки, окружности), не запуская сторонних программ.
Вопрос в том, как это лучше сделать. Имеется вариант размещать в окне элементы управления типа "Picture" (с ссылкой на изображение размером 1х1 пиксель).

2

Re: AHK: графика

Можно ещё и с буквами.

#SingleInstance, Force

Gui, Font, s1, Lucida console

a := 00
b := 100
Loop, 100
{
a := a+2
b := 31.4*sin(a)+100
GUI, Add, text, x%a% y%b%,o
}
GUI, Show, h200 w200

F12:: Exitapp

3

Re: AHK: графика

А использование Canvas и SetPixel не подходит ?

http://www.autohotkey.com/forum/topic7938.html

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

4

Re: AHK: графика

GDI+, там и примеры есть.
Если скажешь, что нужно конкретно, могу пояснить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5

Re: AHK: графика

Спасибо за ссылки, сейчас буду читать.
Вот пока наваял ("навалял" ).

#SingleInstance, Force
pi := 3.1415926535
Gui, Font, s1, Lucida console

 fr := 20    ; Качество изображения (от 10 до 50)
  w := 100    ; Ширина одного периода (в пикселях)
amp := 50    ; Амплитуда (в пикселях)
  n := 2    ; Число периодов

 x0 := 0    ; Начальные
 y0 := 100    ; координаты

a := 0
Loop, % fr*(n*2*pi)
{
b  := -amp*sin(a)+y0
a1 := a*w/(2*pi) + x0

a  := a + 1/fr
GUI, Add, text, x%a1% y%b%, | ; рисовать буквами
;Gui, Add, Picture, x%a1% y%b%, 1.bmp ; рисовать картинками
; GUI, Add, text, x%a1% y100, o ; изобразить горизонтальную ось
}
GUI, Show, h200 w300, Test - построение синусоиды

F12:: Exitapp

6

Re: AHK: графика

Xameleon пишет:

А использование Canvas и SetPixel не подходит ?
http://www.autohotkey.com/forum/topic7938.html

Как-то медленно прорисовывает. Зато при перетаскивании окна не требует перерисовки и можно цвета менять:

#SingleInstance, Force
pi := 3.1415926535
Gui, Font, s1, Lucida console

 fr := 20    ; Качество изображения (от 10 до 50)
  w := 100    ; Ширина одного периода (в пикселях)
amp := 50    ; Амплитуда (в пикселях)
  n := 2    ; Число периодов

 x0 := 0    ; Начальные
 y0 := 100    ; координаты

Gui, Show, w200 h300, gui1: unique title

SelectCanvas( "gui1: unique title" )


a := 0
Loop, % fr*(n*2*pi)
{
b  := ceil(-amp*sin(a)+y0)
a1 := ceil(a*w/(2*pi) + x0)

a  := a + 1/fr
SetPixel( a1, b, 1, "red" ) ; рисовать при помощи Canvas
SetPixel( a1, y0, 1, "blue" ) ; изобразить горизонтальную ось
}

return





GuiClose:
ExitApp


SelectCanvas( p_title=false )
{
   static   hw_canvas

   if ( !p_title )
      return, hw_canvas
   
   Process, Exist
   WinGet, hw_canvas, ID, %p_title% ahk_class AutoHotkeyGUI ahk_pid %ErrorLevel%
}

SetPixel( p_x, p_y, p_size, p_color )
{
   static   total
   
   total++

   Gui, Add, Progress, % "x" ( p_x-1 ) " y" ( p_y-1 ) " w" ( p_size+2 ) " h" ( p_size+2 ) " background" p_color
   
   hw_canvas := SelectCanvas()

   ; WS_EX_STATICEDGE   
   Control, ExStyle, -0x20000, msctls_progress32%total%, ahk_id %hw_canvas%
   
   WinSet, Redraw,, ahk_id %hw_canvas%
}

7

Re: AHK: графика

teadrinker, в любом примере из GDI+ получаю ошибку:

AutoHotkey.exe пишет:

Error: Call to nonexistent function.

Specifically: Gdip_Startup()

Line#
008: SetBatchLines,-1
---> 014: if !pToken := Gdip_Startup()

Чего в супе не хватает? Форточки ХР, библиотеку не скачивал.

8

Re: AHK: графика

Gdip.ahk должна лежать в пользовательской библиотеке (сам не знаю где это)
Или положить рядом с запускаемым скриптом и раскомментировать строку

;#Include, Gdip.ahk

9

Re: AHK: графика

Пользовательская и стандартная библиотеки. (ё-моё, пора бы знать )

Синусоида будет как-то так:

   If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }
   SetWinDelay, 0
   SetBatchLines, -1
   
   k1 = 25   ; коэффициент ширины периода
   k2 = 70   ; коэффициент высоты периода
   Width := 400
   Height := 200   ; размеры картинки
   H2 := Height//2, W2 := Width//2   ; средние пиксели
   
   Gui, Add, Pic, x20 y20 w%Width% h%Height% hwndhPic +0xE      ; SS_BITMAP = 0xE
   
   pBitmap := Gdip_CreateBitmap(Width, Height)
   G := Gdip_GraphicsFromImage(pBitmap)
   Gdip_SetSmoothingMode(G, 4)
   pBrush := Gdip_BrushCreateSolid(0xffffffff)   ; кисть для заливки
   pBlackPen := Gdip_CreatePen(0xff000000, 1)    ; карандаш для осей
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)     ; карандаш для графика
   
   Gdip_FillRectangle(G, pBrush, -1, -1, Width+2, Height+2)
   Gdip_DrawLine(G, pBlackPen, 0, H2, Width, H2)
   Gdip_DrawLine(G, pBlackPen, W2, 0, W2, Height)
   
   x1 = 0
   y1 := Round((-Sin((x1 - W2)/k1))*k2 + H2)
   While x1 < Width
   {
      x2 := x1 + 1
      y2 := Round((-Sin((x2 - W2)/k1))*k2 + H2)
      Gdip_DrawLine(G, pBluePen, x1, y1, x2, y2)
      x1 := x2, y1 := y2
   }
   
   hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
   SetImage(hPic, hBitmap)
   
   Gdip_DeleteBrush(pBrush), Gdip_DeletePen(pBlackPen), Gdip_DeletePen(pBluePen)
   Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap), Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   
   Gui, Show, % "w" Width+40 " h" Height + 40
   Return
   
GuiClose:
   ExitApp
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

10

Re: AHK: графика

teadrinker пишет:

Пользовательская и стандартная библиотеки. (ё-моё, пора бы знать )

Спасибо, закинул GDIp.ahk в Мои документы\AutoHotkey\Lib - заработало.

teadrinker пишет:

Синусоида будет как-то так:

Можно добавить комментариев?

11

Re: AHK: графика

   If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }
   SetWinDelay, 0
   SetBatchLines, -1
   
   k1 = 28   ; коэффициент частоты
   k2 = 80   ; коэффициент амплитуды
   Width := 440
   Height := 200   ; размеры картинки
   H2 := Height//2, W2 := Width//2   ; средние пиксели
   
   Gui, Color, 0xD4D0C8
   Gui, Add, Pic, x20 y20 w%Width% h%Height% hwndhPic +0xE      ; SS_BITMAP = 0xE
   
; создаём битовую карту нужных размеров и получаем указатель (поинтер) на неё:
   pBitmap := Gdip_CreateBitmap(Width, Height)
   
; создаём объект Graphics и получаем указатель на него:
   G := Gdip_GraphicsFromImage(pBitmap)
   
   Gdip_SetSmoothingMode(G, 4)    ; вариант сглаживания при рисовании (см. Gdip.ahk)
   pBrush := Gdip_BrushCreateSolid(0xffffffff)  ; кисть для заливки
   pBlackPen := Gdip_CreatePen(0x88000000, 1)   ; карандаш для осей
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)    ; карандаш для графика
   
   Gdip_FillRectangle(G, pBrush, -1, -1, Width+2, Height+2)   ; заливаем прямоугольник с небольшим запасом
   
; рисуем оси графика:
   Gdip_DrawLine(G, pBlackPen, 0, H2, Width, H2)
   Gdip_DrawLine(G, pBlackPen, W2, 0, W2, Height)
   
; рисуем сам график:
   x1 = 0
   y1 := Round((-Sin((x1 - W2)/k1))*k2 + H2)
   While x1 < Width
   {
      x2 := x1 + 1
      y2 := Round((-Sin((x2 - W2)/k1))*k2 + H2)
      Gdip_DrawLine(G, pBluePen, x1, y1, x2, y2)
      x1 := x2, y1 := y2
   }
   
   hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)  ; хэндл объекта bitmap для использования в SetImage()
   SetImage(hPic, hBitmap)  ; применяем нашу битовую карту к контролу Picture со стилем SS_BITMAP
   
; удаляем ненужные объекты и освобождаем память:
   Gdip_DeleteBrush(pBrush), Gdip_DeletePen(pBlackPen), Gdip_DeletePen(pBluePen)
   Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap), Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   
   Gui, Show, % "w" Width+40 " h" Height + 40
   Return
   
GuiClose:
   ExitApp
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

12

Re: AHK: графика

Можно оси сделать менее жирными, уменьшив прозрачность их карандаша (отредактировано).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

13

Re: AHK: графика

Спасибо, начинаю понемногу разбираться.

14

Re: AHK: графика

Я собираюсь запускать скрипт на компьютере, на котором не установлена AutoHotkey. Если откомпилировать скрипт, он будет искать файл GDIp.ahk?

Вот, подогнал под свои нужды, рисует прямо на глазах (теперь думаю, как избавиться от мельканий и разгрузить процессор):

;--------= НАЧАЛЬНЫЕ ПРЕДУСТАНОВКИ =----------------------------------------------------------------------------
#SingleInstance, Force
 If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }
   SetWinDelay, 0
   SetBatchLines, -1


;--------= НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ =----------------------------------------------------------------------------  
   k1 = 28   ; коэффициент частоты
   k2 = 80   ; коэффициент амплитуды
   Width := 440
   Height := 200   ; размеры картинки
   H2 := Height//2, W2 := Width//2   ; средние пиксели


;--------= ПОСТРОЕНИЕ ИЗОБРАЖЕНИЯ =----------------------------------------------------------------------------    
   Gui, Color, 0xD4D0C8        ; задаётся фон окна

; добавляется элемент Picture, являющийся основой растрового изображения
   Gui, Add, Pic, x20 y20 w%Width% h%Height% hwndhPic +0xE      ; SS_BITMAP = 0xE
   
; создаём битовую карту нужных размеров и получаем указатель (поинтер) на неё:
   pBitmap := Gdip_CreateBitmap(Width, Height)
   
; создаём объект Graphics и получаем указатель на него:
   G := Gdip_GraphicsFromImage(pBitmap)
   
   Gdip_SetSmoothingMode(G, 4)    ; вариант сглаживания при рисовании (см. Gdip.ahk)
   pBrush := Gdip_BrushCreateSolid(0xffffffff)  ; кисть для заливки
   pBlackPen := Gdip_CreatePen(0x88000000, 1)   ; карандаш для осей
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)    ; карандаш для графика
   
   Gdip_FillRectangle(G, pBrush, -1, -1, Width+2, Height+2)   ; заливаем прямоугольник с небольшим запасом
   
; рисуем оси графика:
   Gdip_DrawLine(G, pBlackPen, 0, H2, Width, H2)
   Gdip_DrawLine(G, pBlackPen, W2, 0, W2, Height)
   
   Gui, Show, % "w" Width+40 " h" Height + 40 ;<<<<<

; рисуем сам график:
   x1 = 0
   y1 := Round((-Sin((x1 - W2)/k1))*k2 + H2)
   While x1 < Width
   {
    x2 := x1 + 1
    y2 := Round((-Sin((x2 - W2)/k1))*k2 + H2)
    Gdip_DrawLine(G, pBluePen, x1, y1, x2, y2)
    x1 := x2, y1 := y2
;; }
    hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)  ; хэндл объекта bitmap для использования в SetImage()
    SetImage(hPic, hBitmap)  ; применяем нашу битовую карту к контролу Picture со стилем SS_BITMAP
   }
   
; удаляем ненужные объекты и освобождаем память:
   Gdip_DeleteBrush(pBrush), Gdip_DeletePen(pBlackPen), Gdip_DeletePen(pBluePen)
   Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap), Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   
;;  Gui, Show, % "w" Width+40 " h" Height + 40 ;<<<<<
   Return

Esc::   
GuiClose:
   ExitApp

15

Re: AHK: графика

ypppu пишет:

Я собираюсь запускать скрипт на компьютере, на котором не установлена AutoHotkey. Если откомпилировать скрипт, он будет искать файл GDIp.ahk?

Прочитай статью по моей ссылке до конца.

ypppu пишет:

теперь думаю, как избавиться от мельканий и разгрузить процессор

Если ты только сегодня познакомился с GDI+, вряд ли это получится у тебя в скором времени! Чтобы рисовать "на глазах", нужен совсем другой алгоритм отображения. Кроме того, в коде, что ты наваял, грубая ошибка: в цикле много раз подряд создаётся обект hBitmap (он каждый раз будет другим), а удаляется в конце только один раз. Такой скрипт будет бешено жрать память. Можешь открыть Диспетчер задач и проверить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

16

Re: AHK: графика

teadrinker пишет:

Прочитай статью по моей ссылке до конца.

Libraries of Functions: Standard Library and User Library [v1.0.47+] Прочитал ещё раз, но не понял. Придётся выделить время, чтобы качественно перевести. Методом тыка и ошибок понял, что если GDIp.ahk находится в пользовательской или стандартной библиотеке (либо указан в теле скрипта через #Include), то скомпилированному скрипту этот файл уже не понадобится.

teadrinker пишет:

Если ты только сегодня познакомился с GDI+, вряд ли это получится у тебя в скором времени! Чтобы рисовать "на глазах", нужен совсем другой алгоритм отображения. Кроме того, в коде, что ты наваял, грубая ошибка: в цикле много раз подряд создаётся объект hBitmap (он каждый раз будет другим), а удаляется в конце только один раз. Такой скрипт будет бешено жрать память. Можешь открыть Диспетчер задач и проверить.

А в общих чертах, что это за алгоритм? Или может рисовать отдельными пикселями, не соединяя их отрезками, будет не так тяжко для CPU?

17

Re: AHK: графика

В общих чертах, для этого лучше использовать layered windows, что в примерах к Gdip.ahk. Они не мелькают при перерисовке.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

18

Re: AHK: графика

Спасибо, буду копать.

   о
  /|\_&#8215;
  / \       &#64481;&#64392;&#64468;&#64484;

19

Re: AHK: графика

Даже написал ради интереса:

   If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }

   OnExit, Exit
   SetBatchLines, -1
   SetWinDelay, 0

   k1 = 52   ; коэффициент частоты
   k2 = 80   ; коэффициент амплитуды
   Width = 502
   Height = 250       ; размеры картинки
   SleepDuration = 6  ; пауза в цикле
   Frame = 10         ; рамка

   H2 := Height//2, W2 := Width//2
   X := (A_ScreenWidth-Width)//2
   Y := (A_ScreenHeight-Height)//2

   Gui, -Caption +E0x80000 +LastFound +ToolWindow +AlwaysOnTop  ; WS_EX_LAYERED := 0x80000
   WinGet, ID
   Gui, Show
   OnMessage(0x201, "WM_LBUTTONDOWN")
   OnMessage(0x003, "WM_MOVE")

   DllCall("Winmm\timeBeginPeriod", UInt, 3)

   hbm := CreateDIBSection(Width, Height)
   hdc := CreateCompatibleDC()
   obm := SelectObject(hdc, hbm)
   G := Gdip_GraphicsFromHDC(hdc)
   Gdip_SetSmoothingMode(G, 4)

   pFillBrush := Gdip_BrushCreateSolid(0xffffffff)   ; кисть для заливки
   pFrameBrush := Gdip_BrushCreateSolid(0xffD4D0C8)  ; кисть для рамки
   pGrayPen := Gdip_CreatePen(0xff808080, 1)         ; карандаш для оси
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)         ; карандаш для графика

   Gdip_FillRectangle(G, pFrameBrush, 0, 0, Width, Height)
   Gdip_FillRectangle(G, pFillBrush, Frame, Frame, Width-Frame*2, Height-Frame*2)
   Gdip_DeleteBrush(pFrameBrush)

   Gdip_DrawLine(G, pGrayPen, Frame, H2, Width-Frame, H2)
   UpdateLayeredWindow(ID, hdc, X, Y, Width, Height)
   Sleep, 500

   Loop
   {
      i := !i
      x1 := Frame
      y1 := Round((-Sin((x1 - W2)*k1/1000))*k2 + H2)
      While x1 < Width-Frame
      {
         x2 := x1 + 1
         y2 := Round((-Sin((x2 - W2)*k1/1000))*k2 + H2)
         if i
            Gdip_DrawLine(G, pBluePen, x1, y1, x2, y2)
         Else
         {
            end := x1 = Width-Frame-1
            Gdip_FillRectangle(G, pFillBrush, x1, Frame+1, end ? 1 : 2, Height-Frame*2-2)
            Gdip_DrawLine(G, pGrayPen, x1, H2, x2 + (end ? 0 : 1), H2)
         }
         x1 := x2, y1 := y2
         UpdateLayeredWindow(ID, hdc, X > A_ScreenWidth ? 0 : X, Y, Width, Height)
         DllCall("Sleep", UInt, SleepDuration)
      }
   }

GuiClose:
GuiEscape:
   ExitApp

Exit:
   Gdip_DeletePen(pGrayPen), Gdip_DeletePen(pBluePen), Gdip_DeleteBrush(pFillBrush)
   SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   ExitApp

WM_LBUTTONDOWN()
{
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
}

WM_MOVE(wp, lp)
{
   global X, Y
   X := lp & 0xFFFF, Y := lp >> 16
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

20

Re: AHK: графика

Правильно ли я понял, что после задания окну GUI стиля WS_EX_LAYERED := 0x80000 использовать в нём элементы вроде "Edit", "Button", "Progress" и т. п. нельзя? Если требуется ввести исходные данные, нужно создавать ещё одно окно GUI?

21

Re: AHK: графика

Нельзя после использования функции UpdateLayeredWindow(). Рисовать можно и в обычных окнах, но там алгоритм сложнее.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

22

Re: AHK: графика

teadrinker, расшифруй, пожалуйста, блок:

 Else
  {
  end := x1 = Width-Frame-1
  Gdip_FillRectangle(G, pFillBrush, x1, Frame+1, end ? 1 : 2, Height-Frame*2-2) ; Не понял, что делает эта строчка
  Gdip_DrawLine(G, pGrayPen, x1, H2, x2 + (end ? 0 : 1), H2)
  }

23

Re: AHK: графика

Здесь я постепенно "стираю" нарисованный график путём последовательной зарисовки его белыми прямоугольниками высотой, чуть меньшей высоты белого поля, и шириной в 2 пиксела, за исключением момента, когда до конца поля остаётся всего один пиксел, тогда ширина прямоугольника уменьшается до 1 пиксела, чтобы не закрасить часть серой рамки. Параллельно перерисовывается ось, которая тоже закрашивается белыми прямоугольниками.
В начале я попробовал стирать график путем закрашивания его белым по тому же алгоритму, что он был нарисован, но так не почему-то не получилось, он не стирался полностью, оставался след.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

24

Re: AHK: графика

Понятно. Изменил Gdip_SetSmoothingMode(G, 1), заработало нормально закрашивание карандашом.
Изменил While x1 < Width-Frame-1, чтобы не упиралось в рамку.

25

Re: AHK: графика

ypppu пишет:

Изменил Gdip_SetSmoothingMode(G, 1)

Я тоже подумал, что связано с этим, но если не применять сглаживание, рисуется некрасиво.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

26

Re: AHK: графика

teadrinker пишет:

Нельзя после использования функции UpdateLayeredWindow(). Рисовать можно и в обычных окнах, но там алгоритм сложнее.

Может, есть способы привязать одно окно к другому? Например, в GUI1 (окно со стандартными элементами управления) выделить площадь под GUI2 (LayeredWindow). Затем сделать так, чтобы GUI2 было всегда поверх GUI1 и перемещалось вместе с ним.
Или лучше разобрать алгоритм, как рисовать в обычных окнах?

27

Re: AHK: графика

Нет, layered window дочерним быть не может, а привязывать как-то по-другому — извращение. Разрабатывать алгоритм не нужно, он уже есть, но как я уже сказал, немного сложнее (имею в виду для рисования "в режиме реального времени"). Попозже попробую сделать предыдущий пример для обычного окна.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

28

Re: AHK: графика

Уж больно широкое название у темы, поэтому решил новую не заводить - спросить тут...
Насколько я правильно понимаю всю эту кухню, bitmap есть некая битовая карта в памяти.
На официальном форуме даже нарыл возможность заменить в любой картинке любой конкретный цвет на любой другой цвет.
Вобщем, задача довольно неординарная. Требуется определить координаты всех пикселей заданного цвета в картинке и представить эту информацию в виде массива координат. Возможно ли осуществить такую операцию с помощью gdip?

29

Re: AHK: графика

Задача простая. Алгоритм такой: получаем указатель на bitmap, с помощью Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height) определяем её размеры и перебираем пиксели посредством Gdip_GetPixel(pBitmap, x, y), которая возвращает ARGB пиксела.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

30

Re: AHK: графика

teadrinker пишет:

Нет, layered window дочерним быть не может, а привязывать как-то по-другому — извращение. Разрабатывать алгоритм не нужно, он уже есть, но как я уже сказал, немного сложнее (имею в виду для рисования "в режиме реального времени"). Попозже попробую сделать предыдущий пример для обычного окна.

Ok, лучше сразу осваивать правильный алгоритм. Даже простой пример был бы очень полезен.

31 (изменено: pant-79, 2011-03-11 02:15:13)

Re: AHK: графика

teadrinker, ты гений. И как я сразу не догадался?
Однако в каком-то странном формате он это ARGB извлекает.
Я ожидал что-то типа 0xffaabbcc , а он выдает десятичное безобразие типа 4288733184.
Конвертировать, по ходу, придется...

32

Re: AHK: графика

Почему в странном? Числа по умолчанию в AHK представляются в десятичной системе, что меняется с помощью SetFormat.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

33

Re: AHK: графика

Анимация (рисование синусоиды) в обычном окне:

   If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }

   OnExit, Exit
   SetBatchLines, -1
   SetWinDelay, 0

   k1 = 52   ; коэффициент частоты
   k2 = 80   ; коэффициент амплитуды
   Width = 492
   Height = 250       ; размеры картинки
   SleepDuration = 6  ; пауза в цикле
   Frame = 3          ; рамка

   H2 := Height//2
   X := (A_ScreenWidth-Width)//2
   Y := (A_ScreenHeight-Height)//2
   
   DllCall("Winmm\timeBeginPeriod", UInt, 3)

   hbm := CreateDIBSection(Width, Height)
   hdc := CreateCompatibleDC()
   obm := SelectObject(hdc, hbm)
   G := Gdip_GraphicsFromHDC(hdc)
   Gdip_SetSmoothingMode(G, 4)

   pFrameBrush := Gdip_BrushCreateSolid(0xffC4C0B8)  ; кисть для рамки
   pFillBrush := Gdip_BrushCreateSolid(0xffffffff)   ; кисть для заливки
   pGrayPen := Gdip_CreatePen(0xff808080, 1)         ; карандаш для оси
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)         ; карандаш для графика

   Gdip_FillRectangle(G, pFrameBrush, -1, -1, Width+2, Height+2)   ; с запасом
   Gdip_FillRectangle(G, pFillBrush, Frame, Frame, Width-Frame*2-1, Height-Frame*2-1)
   Gdip_DeleteBrush(pFrameBrush)
   Gdip_DrawLine(G, pGrayPen, Frame, H2, Width-Frame-1, H2)
   
   Gui, Color, 0xECE9D8
   Gui, Add, Pic, x20 y20 w%Width% h%Height% hwndhPic
   Gui, Add, Button, % "x" (Width - 40)//2 " y" 35 + Height " w80 h23 gPause vButton", Start
   Gui, Show, % "w" Width+40 " h" Height + 75
   
   hPicDC := GetDC(hPic)  ; получаем контекст контрола, чтобы переносить в него изображение
   BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)  ; переносим рисунок в контекст контрола
   OnMessage(0xF, "WM_PAINT")  ; поддержка изображения при перерисовке окна

   Loop
   {
      i := !i
      x1 := Frame+1
      y1 := Round((-Sin((x1 - Frame - 1)*k1/1000))*k2 + H2)
      While x1 < Width-Frame-2
      {
         DllCall("Sleep", UInt, SleepDuration)
         if !p
            Continue
         x2 := x1 + 1
         y2 := Round((-Sin((x2 - Frame - 1)*k1/1000))*k2 + H2)
         if i
            Gdip_DrawLine(G, pBluePen, x1, y1, x2, y2)
         Else
         {
            end := x2 = Width-Frame-2
            Gdip_FillRectangle(G, pFillBrush, x1-1, Frame+1, end ? 3 : 2, Height-Frame*2-2)
            Gdip_DrawLine(G, pGrayPen, x1-1, H2, end ? x2+1 : x2, H2)
         }
         x1 := x2, y1 := y2
         BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)
      }
   }

Pause:
   p := !p
   GuiControl,, Button, % p ? "Stop" : "Start"
   Return
   
GuiClose:
GuiEscape:
   ExitApp
   
   
Exit:
   Gdip_DeletePen(pGrayPen), Gdip_DeletePen(pBluePen), Gdip_DeleteBrush(pFillBrush)
   ReleaseDC(hPicDC, hPic)
   SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   ExitApp   
   
WM_PAINT()   ; поддержка изображения при перерисовке окна
{
   global
   BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)
}

Требует наличия Gdip.ahk в пользовательской библиотеке (папка Мои документы\AutoHotkey\Lib\).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

34

Re: AHK: графика

Здорово! http://i.smiles2k.net/aiwan_smiles/good.gif Практически разобрался, хочу только один момент уточнить.
Если окно свернуть, а потом развернуть, картинку не будет видно (имеется в виду, когда рисование остановлено). Чтобы этого избежать, нужно периодически выполнять  BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0), правильно?

35

Re: AHK: графика

ypppu пишет:

Если окно свернуть, а потом развернуть, картинку не будет видно

Вот так попробуй (WM_PAINT() изменена):

   If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }

   OnExit, Exit
   SetBatchLines, -1
   SetWinDelay, 0

   k1 = 52   ; коэффициент частоты
   k2 = 80   ; коэффициент амплитуды
   Width = 492
   Height = 250       ; размеры картинки
   SleepDuration = 6  ; пауза в цикле
   Frame = 3          ; рамка

   H2 := Height//2
   X := (A_ScreenWidth-Width)//2
   Y := (A_ScreenHeight-Height)//2

   DllCall("Winmm\timeBeginPeriod", UInt, 3)

   hbm := CreateDIBSection(Width, Height)
   hdc := CreateCompatibleDC()
   obm := SelectObject(hdc, hbm)
   G := Gdip_GraphicsFromHDC(hdc)
   Gdip_SetSmoothingMode(G, 4)

   pFrameBrush := Gdip_BrushCreateSolid(0xffC4C0B8)  ; кисть для рамки
   pFillBrush := Gdip_BrushCreateSolid(0xffffffff)   ; кисть для заливки
   pGrayPen := Gdip_CreatePen(0xff808080, 1)         ; карандаш для оси
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)         ; карандаш для графика

   Gdip_FillRectangle(G, pFrameBrush, -1, -1, Width+2, Height+2)   ; с запасом
   Gdip_FillRectangle(G, pFillBrush, Frame, Frame, Width-Frame*2-1, Height-Frame*2-1)
   Gdip_DeleteBrush(pFrameBrush)
   Gdip_DrawLine(G, pGrayPen, Frame, H2, Width-Frame-1, H2)

   Gui, Color, 0xECE9D8
   Gui, Add, Pic, x20 y20 w%Width% h%Height% hwndhPic
   Gui, Add, Button, % "x" (Width - 40)//2 " y" 35 + Height " w80 h23 gPause vButton", Start
   Gui, Show, % "w" Width+40 " h" Height + 75

   hPicDC := GetDC(hPic)  ; получаем контекст контрола, чтобы переносить в него изображение
   BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)  ; переносим рисунок в контекст контрола
   OnMessage(0xF, "WM_PAINT")  ; поддержка изображения при перерисовке окна

   Loop
   {
      i := !i
      x1 := Frame+1
      y1 := Round((-Sin((x1 - Frame - 1)*k1/1000))*k2 + H2)
      While x1 < Width-Frame-2
      {
         DllCall("Sleep", UInt, SleepDuration)
         if !p
            Continue
         x2 := x1 + 1
         y2 := Round((-Sin((x2 - Frame - 1)*k1/1000))*k2 + H2)
         if i
            Gdip_DrawLine(G, pBluePen, x1, y1, x2, y2)
         Else
         {
            end := x2 = Width-Frame-2
            Gdip_FillRectangle(G, pFillBrush, x1-1, Frame+1, end ? 3 : 2, Height-Frame*2-2)
            Gdip_DrawLine(G, pGrayPen, x1-1, H2, end ? x2+1 : x2, H2)
         }
         x1 := x2, y1 := y2
         BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)
      }
   }

Pause:
   p := !p
   GuiControl,, Button, % p ? "Stop" : "Start"
   Return

GuiClose:
GuiEscape:
   ExitApp


Exit:
   Gdip_DeletePen(pGrayPen), Gdip_DeletePen(pBluePen), Gdip_DeleteBrush(pFillBrush)
   ReleaseDC(hPicDC, hPic)
   SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   DllCall("Winmm\timeEndPeriod", UInt, 3)
   ExitApp

WM_PAINT()   ; поддержка изображения при перерисовке окна
{
   global
   SetTimer, Timer, -10
   Return

Timer:
   BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)
   Return
}

Так нормально перерисовывается?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

36

Re: AHK: графика

Да, нормально.

37

Re: AHK: графика

Возможно создать кисть прозрачного цвета?
Нужно, чтобы было видно окно и элементы управления под "графическим контролом". А он по умолчанию чёрного непрозрачного цвета.

38

Re: AHK: графика

Gdip_BrushCreateSolid(ARGB=0xff000000), выделенный байт отвечает за прозрачность.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

39

Re: AHK: графика

teadrinker пишет:

Gdip_BrushCreateSolid(ARGB=0xff000000), выделенный байт отвечает за прозрачность.

Наверное я неправильно спросил. В Paint есть такой инструмент "цветной ластик".   Он может стирать какой-то один заданный цвет (под стиранием подразумевается замена одного цвета другим цветом).
Можно создать такую кисть, чтоб она закрашивала при заливке только один цвет? Или все цвета, кроме одного?

40

Re: AHK: графика

Кисти такой нет, но есть функции Gdip_GetPixel() и Gdip_SetPixel(), с их помощью можно заменить пиксели определённого цвета.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

41

Re: AHK: графика

В предыдущем примере с синусоидой использовались два прямоугольника:

   Gdip_FillRectangle(G, pFrameBrush, -1, -1, Width+2, Height+2)   ; с запасом
   Gdip_FillRectangle(G, pFillBrush, Frame, Frame, Width-Frame*2-1, Height-Frame*2-1)

Если эти строчки закомментировать, видно, что фон чёрный. Его можно сделать прозрачным?

42

Re: AHK: графика

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

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

43

Re: AHK: графика

Контрол, в котором рисунок, должен быть прозрачным. Потому что под ним будет ещё один контрол такого же типа, но непрозрачный. Верхний контрол будет перемещаться. Если бы я попытался сделать всё в одном контроле, то пришлось бы перерисовывать весь контрол при каждом "перемещении". По определённым соображениям это было бы связано с большим расходом оперативной памяти и уменьшением быстродействия. Поэтому хотелось бы не перерисовывать основной (нижний) контрол, а просто перемещать над ним другой контрол.

44

Re: AHK: графика

Нашёл один параметр, поэкспериментировал, но так и не понял, что это такое.

BitBlt(hPicDC2, 0, 0, Width, Height, hdc2, 0, 0, 0x666666)  ; переносим рисунок в контекст контрола

45

Re: AHK: графика

Как раз пишу об этом.
Ну, во-первых, верхнему контролу нужно задать +BackgroundTrans, а при выполнении фунции BitBlt() поиграть с последним параметром (Raster, по умолчанию используется SRCCOPY = 0x00CC0020). Описание здесь (параметр dwRop).
Например:

pToken := Gdip_Startup()

Gui, Add, Pic, x75 y75 w50 h50 +0x4  ; чёрный квадрат
Gui, Add, Pic, x50 y50 w100 h100 hwndhPic +BackgroundTrans
Gui, Show, w200 h200
hPicDC := GetDC(hPic)

hbm := CreateDIBSection(100, 100)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)

pBrush := Gdip_BrushCreateSolid(0xFFFF0000)
Gdip_FillRectangle(G, pBrush, -1, -1, 102, 102)
Gdip_DeleteBrush(pBrush)

BitBlt(hPicDC, 0, 0, 100, 100, hdc, 0, 0, 0x008800C6)   ; SRCAND = 0x008800C6

ReleaseDC(hPicDC, hPic), SelectObject(hdc, obm), DeleteObject(hbm)
DeleteDC(hdc), Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

46

Re: AHK: графика

Заинтересовал чёрный квадрат. А можно таким образом сделать картинки-кнопки, чтобы не загружать изображение из отдельного файла?
В смысле цветные квадратики с меткой перехода gSub.

47

Re: AHK: графика

Вот все варианты, описание здесь.

   Gui, Color, B0B0B0
   Gui, Add, Pic, gSub vSS_BLACKRECT   +0x4  x10 y10 w30 h30
   Gui, Add, Pic, gSub vSS_GRAYRECT    +0x5  x50 y10 w30 h30
   Gui, Add, Pic, gSub vSS_WHITERECT   +0x6  x90 y10 w30 h30
   Gui, Add, Pic, gSub vSS_BLACKFRAME  +0x7  x10 y50 w30 h30
   Gui, Add, Pic, gSub vSS_GRAYFRAME   +0x8  x50 y50 w30 h30
   Gui, Add, Pic, gSub vSS_WHITEFRAME  +0x9  x90 y50 w30 h30
   Gui, Add, Pic, gSub vSS_ETCHEDHORZ  +0x10 x10 y90 w30 h30
   Gui, Add, Pic, gSub vSS_ETCHEDVERT  +0x11 x50 y90 w30 h30
   Gui, Add, Pic, gSub vSS_ETCHEDFRAME +0x12 x90 y90 w30 h30
   Gui, Show, w130 h130
   Return

Sub:
   MsgBox, % A_GuiControl
   Return
   
GuiClose:
   ExitApp
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

48

Re: AHK: графика

Вот такой вариант придумал:

Gui, Add, text, x40 y110 c00FFFF s18 gsub,•

49

Re: AHK: графика

Я в GDI+ очень ниже нуля, помогите пожалуйста со скриптом.
Я написал себе скрипт, который делает скриншоты выбранной области.
Работает он так: пользователь наводит курсор куда-то, жмёт хоткей, потом наводит курсор ещё куда-то и снова жмёт тот же хоткей. Пространство между позициями курсора в момент обоих нажатий хоткея - и становится скриншотом.
Захотелось добавить визуальной индикации "фотографируемой" области, путём рисования прямоугольника с помощью GDI+. У этого прямоугольника только одна вершина статична, а 2-ая - до момента 2-ого нажатия на хоткей - должна быть динамичной: она должна находиться там, куда указывает курсор, и если пользователь двигает курсор - то и прямоугольник должен перерисовываться снова и снова, следя за курсором.

Как это сделать?
Подозреваю, что через SetTimer/Loop внутри которого должно находиться что-то типа


; x1 и y1 - нам известны
Loop ; или setTimer
{
    MouseGetPos, x4, y4    ; следим за курсором
    x3 := x4
    y3 := y4
    ; здесь должна быть проверка типа "if cursor moves", можно реализовать через сравнение x1,y1 и x3,y3 с x4,y4.
    ; If (cursor = moved)
    ;
    ; {
        DeleteDC(hdc) ; удаляем старый прямоугольник
        Gdip_DrawLines(G, pRedPen, "x1,y1|x4,y1|x4,y4|x1,y4")    ; перерисовываем прямоугольник
        If GetKeyState(A_ThisHotkey, "P")
            Break
    ; }
}

50

Re: AHK: графика

Если я правильно понял вашу задачу, то она уже решена teadrinker'ом в этой теме (сообщения 2 и 3).

51

Re: AHK: графика

Там конечно довольно изящное решение применено, но чтобы сделать скриншот таким скриншоттером нужно больше времени чем моим, причём как раз из-за гуи: его надо вручную двигать и ресайзить.
К тому же, насколько я понял из кода - там используется создание обычного GUI окна с помощью AHK, у которого убираются все тулбары и рамки так, что видимым остаётся только контент окна, и всё содержимое этого окна просто заливается с помощью GDI+ обычным прямоугольником:

DllCall("gdiplus\GdipFillRectangle", UInt, G, Int, pBrush, "float", 0, "float", 0, "float", w, "float", h)

Мне же - не нужно создандие GUI окна, мне нужно рисовать поверх всего экрана (и мне нужно Gdip_DrawLines(), т.к. хочу только рамку от прямоугольника, а не сам прямоугольник).

52

Re: AHK: графика

А может я не правильно понял, как работает GDI+: судя по примерам - там везде всё равно создаётся GUI окно сначала.
В любом случае, я настолько не силён в этом, что даже готовый скрипт от teadrinker'а не смогу переделать под свои нужды

53 (изменено: Drugoy, 2013-02-26 21:47:21)

Re: AHK: графика

см. след. сообщение

54

Re: AHK: графика

Если хорошо поискать, на форуме есть тема "Сохранить произвольный кусок экрана".

55

Re: AHK: графика

Drugoy пишет:

а дальше загрузка ядра процессора под 100% и скрипт ни на что не реагирует:

Добавьте в цикл небольшой Sleep, хотя бы на 100 мс.

56

Re: AHK: графика

Всем спасибо, вопрос решён:

~Esc::
Clean:
    Gui 1: Destroy
    firstTimeHit :=
Return

...

~PrintScreen:: ; Since we use the same hotkey twice, we have to distinguish the calls
KeyWait, PrintScreen
If !(firstTimeHit = true)
{
    firstTimeHit := true
    pToken := Gdip_Startup()
    MouseGetPos, x1, y1
    Gui, 1: -Caption +E0x80000 +HWNDhwnd1 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
    Gui, 1: Show, NA
    Loop
    {
        If GetKeyState("PrintScreen","P") || GetKeyState("Escape", "P") || GetKeyState("LButton", "P")
        {
            KeyWait, PrintScreen
            Break
        }
        Sleep 20
        MouseGetPos, x2, y2
        If !(x1 = x2 || y1 = y2)
        {
            Gosub, x1x2
            hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight)
            hdc := CreateCompatibleDC()
            obm := SelectObject(hdc, hbm)
            G := Gdip_GraphicsFromHDC(hdc)
            Gdip_SetSmoothingMode(G, 4)
            pPen := Gdip_CreatePen(0xffff0000, 1)
            Gdip_DrawLines(G, pPen, x1 "," y1 "|" x2 "," y1 "|" x2 "," y2 "|" x1 "," y2 "|" x1 "," y1)
            Gdip_DeleteBrush(pPen)
            UpdateLayeredWindow(hwnd1, hdc, 0, 0, A_ScreenWidth, A_ScreenHeight)
            SelectObject(hdc, obm)
            DeleteObject(hbm)
            DeleteDC(hdc)
            Gdip_DeleteGraphics(G)
        }
    }
    Return
}
Else

...

x1x2:
    If x1 > x2    ; We have to keep x1 < x2 and y1 < y2 or GDI+ function will fail.
    {
        x3 := x2
        x2 := x1
        x1 := x3
    }
    If y1 > y2    ; We have to keep y1 < y2 and y1 < y2 or GDI+ function will fail.
    {
        y3 := y2
        y2 := y1
        y1 := y3
    }
Return

57

Re: AHK: графика

Раз уж тут обсуждается графика, решил не создавать новую тему и задать свою кучу вопросов тут. Авось, кто знает, в какую сторону мне танцевать...
Все вышеописанное в этом разделе я довольно активно использую в своих скриптах, но недавно уперся, как головой в стену в одно ограничение GDI+.
Все способы рисования (по крайней мере из того массива, который поддерживает gdip.ahk) основаны на методах объекта Graphics. Прямоугольник рисуется методом DrawRectangle, линия - методом DrawLine и т.д.
Но методы - не есть объекты. Нарисовал ты линию, она отобразилась на растровом изображении, и единственный, кто помнит, что была нарисована линия - сам рисунок с измененными в нужных местах пикселами. Все, больше с этой линией ничего сделать нельзя, только стереть чем-нибудь позже нарисованным, вернув пиксели к исходному цвету, ну и заменить цвет линии, да и то, если не применено сглаживание.
А мне же нужна та же линия, как управляемый объект, что реализовано в большинстве векторных редакторов.
То есть, чтобы по ходу действия можно было менять ее цвет, толщину, положение, не затрагивая при этом другие объекты.
Попытавшись курить документацию по GDI+, я обнаружил, что все-таки можно создавать объекты Point и Rectangle, у которых есть свои свойства и методы и даже (ура!) есть "Например, методы Inflate и Offset позволяют изменять размер и расположение прямоугольника. Метод IntersectsWith позволяет определить, не пересекается ли данный прямоугольник с некоторым указанным прямоугольником, а метод Contains позволяет определить, находится ли указанная точка внутри данного прямоугольника."
Но, увы, этим все и ограничилось, большего функционала GDI+ не предложила. Да и эти вкусности не поддерживаются в gdip.ahk (ну это, вроде, разрешимо, можно их туда прописать через DllCall, благо, на форуме есть знающие люди, которые подскажут правильный код, но дальше то что?)
Ведь это не даст в итоге нужного функционала.
Но когда я обновился до AHK_L, то узнал, что в нем, оказывается уже есть поддержка объектов просто и даже объектов COM. И тут получается распутье. В какую сторону дальше завернуть?
Разобраться в создании собственных объектов и прикрутить это дело в gdip.ahk?
Как-то по новому подключаться к GDI+ через COM объекты, что позволит реализовать требуемый функционал?
Рисовать многомногослойные рисунки, на каждый объект по слою (имхо, извращение)?
Или плюнуть на все, и коряво реализовать все через стирание и перерисовку объектов, запоминая все их параметры в едреной куче переменных (еще большее извращение)?
Кто что подскажет?

58

Re: AHK: графика

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

Во-вторых, по моему представлению, в любом случае нужно перерисовывать картинку, если фигура изменила размер или изменила координаты.
Для создания векторной графической анимации мне приходилось перерисовывать все фигуры поочерёдно (начиная с нижнего, завершая верхним). Размеры все фигур брались из переменных.

59

Re: AHK: графика

ypppu пишет:

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

Вот рабочий пример двухслойного изображения, в котором верхний слой прозрачный:


#SingleInstance, Force
#NoEnv
#NoTrayIcon
SetBatchLines, -1
   SetWinDelay, 0
;#Include, Gdip.ahk

If !pToken := Gdip_Startup()
   {
      MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
      ExitApp
   }
   Width := 400
   Height := 200   ; размеры картинки
   DllCall("Winmm\timeBeginPeriod", UInt, 3)
   SleepDuration := 4

Gui, Add, Pic, x10 y10 w%Width% h%Height% hwndhPic  gRepaint 
Gui, Add, Pic, x10 y10 w%Width% h%Height% hwndhPic2  BackgroundTrans
GUI,show,,DualLayer
 gosub StartDraw
WinGet,MyWindow,ID,DualLayer
ControlGetPos,Xpic, Ypic,,,Static1,ahk_id %MyWindow%
OnMessage(0xF, "WM_PAINT")  ; поддержка изображения при перерисовке окна
Settimer, SetTime, 1000
return

StartDraw:
   hbm := CreateDIBSection(Width, Height)
   hdc := CreateCompatibleDC()
   obm := SelectObject(hdc, hbm)
   G := Gdip_GraphicsFromHDC(hdc)
   Gdip_SetSmoothingMode(G, 2)              ;задаем режим сглаживания
   pBlackPen := Gdip_CreatePen(0xff000000, 1)    
   pBluePen := Gdip_CreatePen(0xff0000ff, 1)     ; карандаш для графика
   pWhiteBrush := Gdip_BrushCreateSolid(0xffffffff)   ; кисть для заливки
   Gdip_FillRoundedRectangle(G, pWhiteBrush, 0, 0, Width, Height, 2) ;рисуем белый фон
hPicDC := GetDC(hPic)  ; получаем контекст контрола, чтобы переносить в него изображение
BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)  ; переносим рисунок в контекст контрола

hbm2 := CreateDIBSection(Width, Height)
hdc2 := CreateCompatibleDC()
obm2 := SelectObject(hdc2, hbm2)
G2 := Gdip_GraphicsFromHDC(hdc2)
Gdip_SetSmoothingMode(G2, 4)
Gdip_FillRectangle(G2, pWhiteBrush, -1, -1, Width, Height)
hPicDC2 := GetDC(hPic2)
BitBlt(hPicDC2, 0, 0, Width, Height, hdc2, 0, 0, 0x008800C6 )   ; SRCAND = 0x008800C6
return

GuiClose:
ReleaseDC(hPicDC2, hPic2), SelectObject(hdc2, obm2), DeleteObject(hbm2)
DeleteDC(hdc2), Gdip_DeleteGraphics(G2)

Gdip_DeleteBrush(pWhiteBrush)
Gdip_DeletePen(pBlackPen)
Gdip_DeletePen(pBluePen)
   ReleaseDC(hPicDC, hPic)
   SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   DllCall("Winmm\timeEndPeriod", UInt, 3)
ExitApp

SetTime:
FormatTime, TimeString,, HH:mm:ss
Gdip_FillRectangle(G2, pWhiteBrush, 2, 2, 350, 100)
DrawText(G2, TimeString, "Arial", 0xff000000, 50, 2, 2, 350, 100)
   BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)
   BitBlt(hPicDC2, 0, 0, Width, Height, hdc2, 0, 0, 0x008800C6 ) ; SRCAND = 0x008800C6
return

Repaint:
   if A_GuiControlEvent = Normal
{
CoordMode,Mouse,Window
MouseGetPos,mX, mY
Ydm := mY - Ypic
Xdm := mX - Xpic
 Settimer, Drawing, 100
KeyWait,LButton
MouseGetPos,mX, mY
Yum := mY - Ypic
Xum := mX - Xpic
 Settimer, Drawing, off
}
Return

Drawing:
CoordMode,Mouse,Window
MouseGetPos,msX, msY
Ydraw := msY - Ypic
Xdraw := msX - Xpic
   MyLine := Gdip_DrawLine(G, pBluePen, Xdm, Ydm, Xdraw, Ydraw)  ;рисуем 
Xdm := Xdraw
Ydm := Ydraw
 BitBlt(hPicDC2, 0, 0, Width, Height, hdc2, 0, 0, 0x008800C6 )   ; SRCAND = 0x008800C6
return

WM_PAINT()   ; поддержка изображения при перерисовке окна
{
   global
   SetTimer, Timer, -10
   Return

Timer:
   BitBlt(hPicDC, 0, 0, Width, Height, hdc, 0, 0)
   BitBlt(hPicDC2, 0, 0, Width, Height, hdc2, 0, 0, 0x008800C6 )   ; SRCAND = 0x008800C6
   Return
}

DrawText(workG, MyText, Font, TextColor=0xff000000, SizeFont=10, Xt=0, Yt=0, Wt=100, Ht=50, Underline=0, Italic=0, Strike=0, Bold=0, Outlined=0)
{
global 
if !Font
Font = Arial
If !hFamily := Gdip_FontFamilyCreate(Font)
{
   MsgBox, 48, Font error!, The font you have specified does not exist on the system
   ExitApp
}
Gdip_DeleteFontFamily(hFamily)
Options := "x" . Xt . " y" . Yt . " w" . Wt . " h" . Ht . " cFF00ff00 r4 center s" . SizeFont . ""
if Underline = 1
Options := Options . " Underline"
if Italic = 1
Options := Options . " Italic"
if Strike = 1
Options := Options . " Strikeout"
if Bold = 1
Options := Options . " Bold"
if !pPath := Gdip_CreatePath(0)
Return errorlevel
Gdip_AddString(pPath, MyText, Font, Options)    
if !pTextBrush := Gdip_BrushCreateSolid(TextColor)
Return errorlevel
Gdip_FillPath(workG, pTextBrush, pPath)
Gdip_DeleteBrush(pTextBrush)
Gdip_DeletePath(pPath)
}


Gdip_AddString(Path, sString,fontName, options,stringFormat=0x4000)
{
   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)

    hFamily := Gdip_FontFamilyCreate(fontName)
    RegExMatch(Options, "i)X([\-0-9]+)", xpos)
    RegExMatch(Options, "i)Y([\-0-9]+)", ypos)
    RegExMatch(Options, "i)W([0-9]+)", Width)
    RegExMatch(Options, "i)H([0-9]+)", Height)
    RegExMatch(Options, "i)R([0-9])", Rendering)    
        
    Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
    Loop, Parse, Styles, |
    {
        If RegExMatch(Options, "i)\b" A_loopField)
        Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
    }
    RegExMatch(Options, "i)S([0-9]+)", fontSize)
    Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
    Loop, Parse, Alignments, |
    {
        If RegExMatch(Options, "i)\b" A_loopField)
        Align |= A_Index//2.1      ; 0|0|1|1|2|2
    }
    hFormat := Gdip_StringFormatCreate(stringFormat)
    Gdip_SetStringFormatAlign(hFormat, Align)    
    Gdip_SetTextRenderingHint(pGraphics, Rendering)
    CreateRectF(textbox, xpos1, ypos1, Width1, Height1)    
    iRet := DllCall("gdiplus\GdipAddPathString", "UInt", Path,  "UInt", &wString, "Int", -1, "Uint",hFamily, "Int", Style, "Float", fontSize1,"UInt", &textbox, "UInt", hFormat)
    Gdip_DeleteFontFamily(hFamily)
    Gdip_DeleteStringFormat(hFormat)
    return iRet             
}

Gdip_DrawPath(pGraphics, pPen, Path)
{
    return DllCall("gdiplus\GdipDrawPath", "UInt", pGraphics, "UInt", pPen, "UInt", Path)
}

Каждую секунду на верхнем слое перерисовывается отображаемое время, т.е. сначала белым прямоугольником стирается старое, потом пишется новое.
При этом с помощью мыши можно рисовать ломаные линии на нижнем слое. Если их нарисовать "под" текстом, то они все равно будут видны, несмотря на ежесекундно рисуемый поверх них белый прямоугольник.

ypppu пишет:

Во-вторых, по моему представлению, в любом случае нужно перерисовывать картинку, если фигура изменила размер или изменила координаты.
Для создания векторной графической анимации мне приходилось перерисовывать все фигуры поочерёдно (начиная с нижнего, завершая верхним). Размеры все фигур брались из переменных.

Дык, никто не спорит, что там все надо перерисовывать, вопрос в том, как удобнее для кодера организовать хранение этих данных и управление объектами. Мне кажется, что если АНК теперь позволяет работать с объектами, то можно все реализовать через объектную модель. Или написанную собственноручно, или взятую оттуда, где она уже реализована. Как эти данные были организованы у вас?

60

Re: AHK: графика

Мне же - не нужно создандие GUI окна, мне нужно рисовать поверх всего экрана

  И мне нужно рисовать и писать текст без GUI. Это вообще возможно?

61

Re: AHK: графика

Pogodin, нужны подробности. Что значит "рисовать и писать текст без GUI"?

62

Re: AHK: графика

Не создавая нового окна писать и рисовать в уже существующем чужом.

63

Re: AHK: графика

В таком случае не смогу помочь.

Настоящие герои не ищут лёгкий путей:
AHK: Добавить кнопку в произвольное окно (не ahk GUI) ▬►создавать свои окна и контолы в чужом процессе

64

Re: AHK: графика

Pogodin пишет:

Не создавая нового окна писать и рисовать в уже существующем чужом

Рисовать-то можно, вопрос зачем?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

65

Re: AHK: графика

Чтобы вносить нужные элементы без дополнительных окон.

66

Re: AHK: графика

Можно вносить все элементы в одно окно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

67

Re: AHK: графика

Это хорошо, но нужно без создания собственного под эти элементы.

68

Re: AHK: графика

Ну вот пример рисования в окне cmd:

Run, cmd,,, PID
WinWait, ahk_pid %PID%
Loop 4 {
   WinSet, Redraw
   Sleep, 400
   DrawTextInAnyWindow(WinExist(), "AutoHotkey is cool!", "Verdana", "italic", 40, 0xFF0000, 40, 40)
   Sleep, 400
}

DrawTextInAnyWindow(hwnd, text, FontName, FontStyle, FontSize, FontColorBGR, x, y)
{
   static TRANSPARENT := 1, LOGPIXELSY := 90, ANTIALIASED_QUALITY := 4, mult := A_IsUnicode ? 2 : 1
        , styles := { bold: {value: 700, offset: 16, size: "Int"}
                    , italic: {value: 1, offset: 20, size: "Char"}
                    , underline: {value: 1, offset: 21, size: "Char"}
                    , strikeout: {value: 1, offset: 22, size: "Char"} }

   hDC := DllCall("GetDC", Ptr, hwnd, Ptr)
   VarSetCapacity(LOGFONT, 28 + 32 * mult, 0)
   height := -DllCall("MulDiv", Int, FontSize, Int, DllCall("GetDeviceCaps", Ptr, hDC, Int, LOGPIXELSY), Int, 72)
   NumPut(height, LOGFONT, "Int")
   
   Loop, parse, FontStyle, %A_Space%
      if obj := styles[A_LoopField]
         NumPut(obj.value, &LOGFONT + obj.offset, obj.size)
      
   NumPut(ANTIALIASED_QUALITY, &LOGFONT + 26, "Char")
   StrPut(FontName, &LOGFONT + 28, StrLen(FontName) * mult, A_IsUnicode ? "UTF-16" : "CP0")
   hFont := DllCall("CreateFontIndirect", Ptr, &LOGFONT, Ptr)
   
   DllCall("SetBkMode", Ptr, hDC, Int, TRANSPARENT)
   prevObj := DllCall("SelectObject", Ptr, hDC, Ptr, hFont, Ptr)
   DllCall("SetTextColor", Ptr, hDC, Int64, FontColorBGR)
   DllCall("TextOut", Ptr, hDC, Int, x, Int, y, Str, text, Int, StrLen(text))
   DllCall("SelectObject", Ptr, hDC, Ptr, prevObj, Ptr)
   DllCall("ReleaseDC", Ptr, hwnd, Ptr, hDC)
   DllCall("DeleteObject", Ptr, hFont)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

69

Re: AHK: графика

Да, работает. А для обычных окон существует подобное?

70

Re: AHK: графика

Функцию DrawTextInAnyWindow() можно применить для любого окна. Другое дело, что текст не во всех окнах будет показываться, он там находится до ближайшей перерисовки. Для примера можно просто заменить cmd на notepad, или на что-то ещё.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

71

Re: AHK: графика

Да, я сразу попробовал. Даже на рабочем столе рисует, но пропадает.
Есть шанс переделать так, чтобы выводилось несколько разных сообщений, чтобы отслеживалось состояние, перерисовывалось содержимое, сдвигалось с окном, и при этом не мигало и комп не грузило?

72

Re: AHK: графика

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

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

73

Re: AHK: графика

teadrinker пишет:

Убедитесь в наличии gdiplus.dll в вашей системе!

Насколько я понимаю, для нормальной работы этого скрипта gdiplus.dll должен быть специальный? Я скачал вот отсюда: https://github.com/tariqporter/Gdip/ , но не знаю где он должен находиться в Win10 x64?  Я нашёл несколько уже имеющихся штук, но папки все какие-то странные вроде C:\Windows\WinSxS\x86_microsoft.windows.gdiplus_xxxxxx_none_xxxxxxxx\GdiPlus.dll.
Куда этот скачанный перенести?

74

Re: AHK: графика

Файл GDIplus.dll отсутствует только в ОС старше XP. Чтобы проверить его наличие, выполните код

If !pToken := Gdip_Startup()
MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!

У меня в XP этот файл встречается три раза:
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.GdiPlus_6595b64144ccf1df_1.0.0.0_x-ww_8d353f13\GdiPlus.dll
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.GdiPlus_6595b64144ccf1df_1.0.2600.2180_x-ww_522f9f82\GdiPlus.dll
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.GdiPlus_6595b64144ccf1df_1.0.2600.5512_x-ww_dfb54e0c\GdiPlus.dll
Все три файла имеют разный размер. Но скрипт ругается только если переименовать третий файл.

75

Re: AHK: графика

Foma, а что, у вас с тем файлом, что есть в системе, что-то не работает?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

76 (изменено: Foma, 2017-04-29 21:04:54)

Re: AHK: графика

Не работало. Сейчас работает. Может перезагрузка помогла. Вопрос снимаю.

Добавлю другой. Я ищу самый простой вариант для рисования отдельных точек по известным координатам. Пока не смог приспособить ни синусоиду, ни что-то из набора https://autohotkey.com/board/topic/2944 … 145-by-tic.

77

Re: AHK: графика

Кто-то может подсказать, как выводить отдельные точки?

78

Re: AHK: графика

http://forum.script-coding.com/viewtopic.php?id=10974

79

Re: AHK: графика

Спасибо!

80

Re: AHK: графика

Как сохранить полупрозрачный Bitmap?
Нашёл для этого только DrawImage, но как потом сохранить результат в файл?
Если изменения происходят в Graphics, то логично из неё получить Bitmap.
GdipCreateBitmapFromGraphics? Но как ни странно её нет ни в библиотеке, ни на форумах.
У меня сохраняет белый цвет.


File = test.png

Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromFile(File)

Gdip_GetImageDimensions(pBitmap, W, H)   

hBitmap := CreateDIBSection(W, H)
hDC := CreateCompatibleDC()
SelectObject(hDC, hBitmap)
G := Gdip_GraphicsFromHDC(hDC)

Matrix = 0.5
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)
Gui, -Caption +E0x80000 +HWNDhGui +AlwaysOnTop +ToolWindow +OwnDialogs +E0x08000000  
Gui, Show, Na
UpdateLayeredWindow(hGui, hDC, 0, 0, W, H)

DllCall("gdiplus\GdipCreateBitmapFromGraphics", "int", W, "int", H, "UPtr", G, "UPtr*", pBitmap2)

Gdip_SaveBitmapToFile(pBitmap2, "FinalImage.png")

run FinalImage.png
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

81

Re: AHK: графика

Или так, по идее должно копироваться во втором окне.


File = test.png

Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromFile(File)

Gdip_GetImageDimensions(pBitmap, W, H)   

hBitmap := CreateDIBSection(W, H)
hDC := CreateCompatibleDC()
SelectObject(hDC, hBitmap)
G := Gdip_GraphicsFromHDC(hDC)

Matrix = 0.5
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)

Gui, -Caption +E0x80000 +HWNDhGui +AlwaysOnTop +ToolWindow +OwnDialogs +E0x08000000  
Gui, Show, Na

UpdateLayeredWindow(hGui, hDC, 0, 0, W, H)

Gui, New
Gui, -Caption +AlwaysOnTop 
Gui, Margin, 0,0
Gui, Add, text, x0 y0 w%W% h%H% 0xE hwndhPic ; SS_BITMAP = 0xE
Gui, Show, Na

hBM := CreateCompatibleBitmap(hDC, W, H)
; hBM := Gdip_CreateHBITMAPFromBitmap(pBitmap)  ;	для проверки hPic
STM_SETIMAGE := 0x172, IMAGE_BITMAP := 0x0
SendMessage, STM_SETIMAGE, IMAGE_BITMAP, hBM, , ahk_id %hPic% 
Return
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

82

Re: AHK: графика

Нужно Gdip_CreateBitmapFromHBITMAP(hBitmap), но вместо прозрачных пикселей будут чёрные. Чтобы сохранить прозрачные, нужно как-то вручную перебирать пиксели, смотреть, у каких есть прозрачность и создавать что-то типа маски. Я подробно не разбирался.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

83

Re: AHK: графика

Не соображу в какое место Gdip_CreateBitmapFromHBITMAP.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

84

Re: AHK: графика

А, ты про 80.
А 81?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

85

Re: AHK: графика

File = D:\Downloads\Иконки\LOWs6vLjqH0.jpg

Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromFile(File)

Gdip_GetImageDimensions(pBitmap, W, H)   

hBitmap := CreateDIBSection(W, H)
hDC := CreateCompatibleDC()
SelectObject(hDC, hBitmap)
G := Gdip_GraphicsFromHDC(hDC)

Matrix = 0.5
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)
Gui, -Caption +E0x80000 +HWNDhGui +AlwaysOnTop +ToolWindow
Gui, Show, Na
UpdateLayeredWindow(hGui, hDC, 500, 0, W, H)

pBitmap2 := Gdip_CreateBitmapFromHBITMAP(hBitmap)

Gdip_SaveBitmapToFile(pBitmap2, A_Desktop . "\FinalImage.png")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

86

Re: AHK: графика

serzh82saratov пишет:

А, ты про 80.
А 81?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

87

Re: AHK: графика

pBitmap2 := Gdip_CreateBitmapFromHBITMAP(hBitmap)
hBM2 := Gdip_CreateHBITMAPFromBitmap(pBitmap2)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

88 (изменено: teadrinker, 2019-02-27 00:16:28)

Re: AHK: графика

Чтобы сохранить прозрачность, гугли примеры с AlphaBlend().

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

89

Re: AHK: графика

Спасибо, ясно, вообщем дело тёмное.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

90

Re: AHK: графика

teadrinker пишет:

Чтобы сохранить прозрачность, гугли примеры с AlphaBlend().

Зачем так сложно?
Можно же через GdipCreateBitmapFromScan0.

91

Re: AHK: графика

А, точно, забыл про это. Вот так вышло:

pBitmap2 := Gdip_CreateBitmap(W, H)
G2 := Gdip_GraphicsFromImage(pBitmap2)
Matrix = 0.5
Gdip_DrawImage(G2, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)
Gdip_SaveBitmapToFile(pBitmap2, A_Desktop . "\FinalImage.png")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

92 (изменено: serzh82saratov, 2019-02-28 21:47:46)

Re: AHK: графика

А если в графике несколько слоёв?


File =  

Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromFile(File)

Gdip_GetImageDimensions(pBitmap, W, H)   

hBitmap := CreateDIBSection(W, H)
hDC := CreateCompatibleDC()
SelectObject(hDC, hBitmap)
G := Gdip_GraphicsFromHDC(hDC)

pBrush := Gdip_BrushCreateSolid(0x88FBD986)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, W, H, 0) 
Gdip_DeleteBrush(pBrush)

Matrix = 0.5
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)
Gui, -Caption +E0x80000 +HWNDhGui +AlwaysOnTop +ToolWindow +OwnDialogs +E0x08000000  
Gui, Show, Na

UpdateLayeredWindow(hGui, hDC, 0, 0, W, H)

pBitmap2 := Gdip_CreateBitmap(W, H)
G2 := Gdip_GraphicsFromImage(pBitmap2)
Matrix = 0.5
Gdip_DrawImage(G2, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)

Gdip_SaveBitmapToFile(pBitmap2, A_Desktop . "\FinalImage.png")

Run  % A_Desktop . "\FinalImage.png"
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

93

Re: AHK: графика

Аналогично:


File = D:\Downloads\Иконки\LOWs6vLjqH0.jpg

Gdip_Startup()
pBitmap := Gdip_CreateBitmapFromFile(File)

Gdip_GetImageDimensions(pBitmap, W, H)   

hBitmap := CreateDIBSection(W, H)
hDC := CreateCompatibleDC()
SelectObject(hDC, hBitmap)
G := Gdip_GraphicsFromHDC(hDC)

pBrush := Gdip_BrushCreateSolid(0x88FBD986)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, W, H, 0) 

Matrix = 0.5
Gdip_DrawImage(G, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)
Gui, -Caption +E0x80000 +HWNDhGui +AlwaysOnTop +ToolWindow
Gui, Show, Na

UpdateLayeredWindow(hGui, hDC, 0, 0, W, H)

pBitmap2 := Gdip_CreateBitmap(W, H)
G2 := Gdip_GraphicsFromImage(pBitmap2)
Gdip_FillRoundedRectangle(G2, pBrush, 0, 0, W, H, 0) 
Gdip_DeleteBrush(pBrush)
Matrix = 0.5
Gdip_DrawImage(G2, pBitmap, 0, 0, W, H, 0, 0, W, H, Matrix)

Gdip_SaveBitmapToFile(pBitmap2, A_Desktop . "\FinalImage.png")

Run  % A_Desktop . "\FinalImage.png"
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

94

Re: AHK: графика

Спасибо, для меня не до конца прозрачно что к чему в GDI.
Тут получается из чего создаём графику то и меняется. Если создали из Bitmap, то после операций с графикой меняется Bitmap. Я думал что изменения происходят только в графике.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

95

Re: AHK: графика

То есть думал, что после всех преобразований для UpdateLayeredWindow, все эти изменения я могу получить из какого то объекта, а не производить те же манипуляции снова.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

96

Re: AHK: графика

По идее конечно должно быть можно как-то получить из первого графикса.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

97 (изменено: serzh82saratov, 2019-03-01 03:03:30)

Re: AHK: графика

Так искажаются цвета. Но результат в файле.


File =  

Gdip_Startup()
pBitmapFile := Gdip_CreateBitmapFromFile(File)

Gdip_GetImageDimensions(pBitmapFile, W, H)   

pBitmap := Gdip_CreateBitmap(W, H)
G := Gdip_GraphicsFromImage(pBitmap)

pBrush := Gdip_BrushCreateSolid(0x8000FF00)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, W, H, 0) 
Gdip_DeleteBrush(pBrush)
Matrix = 0.5
Gdip_DrawImage(G, pBitmapFile, 0, 0, W, H, 0, 0, W, H, Matrix)

Gui, -Caption +E0x80000 +HWNDhGui +AlwaysOnTop +ToolWindow
Gui, Show, Na

hDCBuf := CreateCompatibleDC()
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap, 0x00000000)
SelectObject(hDCBuf, hBitmap)

UpdateLayeredWindow(hGui, hDCBuf, 0, 0, W, H)

Gdip_SaveBitmapToFile(pBitmap, A_Desktop . "\FinalImage.png")

Run  % A_Desktop . "\FinalImage.png"
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

98

Re: AHK: графика

Хотя нет, вроде туда копаю.

hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap, 0x00000000)
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

99

Re: AHK: графика

Так хочешь?

........
UpdateLayeredWindow(hGui, hDC, 0, 0, W, H)

VarSetCapacity(dib, 104, 0)
DllCall("GetObject", Ptr, hBitmap, "int", A_PtrSize = 8 ? 104 : 84, Ptr, &dib)
Stride := NumGet(dib, 12, "Int")
Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0))
DllCall("Gdiplus.dll\GdipCreateBitmapFromScan0", "uint", W, "uint", H, "uint", Stride, "uint", 0x26200A, "ptr", Bits, "ptr*", pBitmap2)
Gdip_SaveBitmapToFile(pBitmap2, "FinalImage.png")

Чтобы не была перевернутая поставь отрицательную высоту в:

hBitmap := CreateDIBSection(W, -H)

100

Re: AHK: графика

Хороший пример, спасибо.
В 97 по проще?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui