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).