Page 1 of 2

Create an HBitmap with transparency

Posted: 12 May 2020, 10:47
by kyuuuri
Hello, I'm trying to create a simple HBitmap (to be used in a Picture control) that only has a background with transparency. The idea is to use it to overlay some controls I have that are going to be disabled.
I tried the following code:

Code: Select all

pBitmap := Gdip_CreateBitmap(400, 400)
hBackground := Gdip_CreateHBITMAPFromBitmap(pBitmap, 0xff000000)
hOverlay := Gdip_CreateHBITMAPFromBitmap(pBitmap, 0x00F000FF)
gui, add, picture, x0 y0 Altsubmit, HBITMAP:%hBackground%
gui, add, picture, x0 y0 Altsubmit BackgroundTrans, HBITMAP:%hOverlay%
gui, show
return
But I read that Gdip_CreateHBITMAPFromBitmap ignores the alpha channel.

So I found about DIB section, but the problem is that when I create it I can't specify what background I want, and I don't know how to change the pixels on it because Gdip_GetPixel works only with pBitmap and DIB sections are hBitmap.

So to make it short:
I need a simple hBitmap that only holds a semi-transparent color and it will go on top of other controls.
Gdip_CreateHBITMAPFromBitmap doesn't support transparency and the methods I found on this forum are only for images from files.

Any ideas? I want to avoid using another gui, changing the transparency of the entire gui and/or using an image from a file.

Re: Create an HBitmap with transparency

Posted: 12 May 2020, 11:25
by serzh82saratov
For win10, the transparency of child elements is supported. Gdip not required.
For win7 unsupported, so inserting in control will still not give anything.

Code: Select all

BckgMain = F000FF
Gui, Color, FAD886 
Gui, Margin, 0, 0
Gui, Add, Progress, x111 y111 w222 h222 BackgroundC0C0C0
Gui, Add, Progress, x0 y0 w222 h222 Background%BckgMain% HwndhProgress
WinSet, TransParent, 55, ahk_id %hProgress% 
Gui, Show
return

Re: Create an HBitmap with transparency

Posted: 12 May 2020, 11:32
by Smile_
@kyuuuri
The idea is to use it to overlay some controls I have that are going to be disabled.
You will add overlay on controls to disable them?, or they are disabled and you just want to add overlay on them?

Re: Create an HBitmap with transparency

Posted: 12 May 2020, 12:31
by kyuuuri
serzh82saratov wrote:
12 May 2020, 11:25
For win10, the transparency of child elements is supported. Gdip not required.
For win7 unsupported, so inserting in control will still not give anything.

Code: Select all

BckgMain = F000FF
Gui, Color, FAD886 
Gui, Margin, 0, 0
Gui, Add, Progress, x111 y111 w222 h222 BackgroundC0C0C0
Gui, Add, Progress, x0 y0 w222 h222 Background%BckgMain% HwndhProgress
WinSet, TransParent, 55, ahk_id %hProgress% 
Gui, Show
return
Hello, thank you for the suggestion but I need it to work on w7 as well.
Smile_ wrote:
12 May 2020, 11:32
@kyuuuri
The idea is to use it to overlay some controls I have that are going to be disabled.
You will add overlay on controls to disable them?, or they are disabled and you just want to add overlay on them?
I have disabled controls and a disabled gui and I want to add an overlay over them.

Re: Create an HBitmap with transparency  Topic is solved

Posted: 12 May 2020, 14:05
by teadrinker
Perhaps you want something like this:

Code: Select all

colorWithoutTransparency := 0xC0C0C0
colorWithTransparency := 0x55F000FF
width := 200
height := 200

Gui, Color, FAD886
Gui, Margin, 0, 0
Gui, Add, Pic,, % "HBITMAP:" . CreateColoredBitmap(width, height, colorWithoutTransparency)
Gui, Add, Pic, x100 y100 BackgroundTrans, % "HBITMAP:" . CreateColoredBitmap(width, height, colorWithTransparency)
Gui, Show

CreateColoredBitmap(width, height, color) {
   hBitmap := CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + width*4*i + (A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0)
{
   hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(bi, 40, 0)
   NumPut( 40, bi,  0, "UInt")
   NumPut(  w, bi,  4, "UInt")
   NumPut(  h, bi,  8, "UInt")
   NumPut(  1, bi, 12, "UShort")
   NumPut(  0, bi, 16, "UInt")
   NumPut(bpp, bi, 14, "UShort")
   hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
   return hbm
}
Edited (2 times)

Re: Create an HBitmap with transparency

Posted: 12 May 2020, 14:56
by serzh82saratov
Это работает на семёрке?

Re: Create an HBitmap with transparency

Posted: 12 May 2020, 15:01
by kyuuuri
teadrinker wrote:
12 May 2020, 14:05
Perhaps you want something like this:

Code: Select all

colorWithoutTransparency := 0xC0C0C0
colorWithTransparency := 0x55F000FF
width := 200
height := 200

Gui, Color, FAD886
Gui, Margin, 0, 0
Gui, Add, Pic,, % "HBITMAP:" . CreateColoredBitmap(width, height, colorWithoutTransparency)
Gui, Add, Pic, x100 y100 BackgroundTrans, % "HBITMAP:" . CreateColoredBitmap(width, height, colorWithTransparency)
Gui, Show

CreateColoredBitmap(width, height, color) {
   hBitmap := CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + width*4*i + (A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0)
{
   hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(bi, 40, 0)
   NumPut( 40, bi,  0, "UInt")
   NumPut(  w, bi,  4, "UInt")
   NumPut(  h, bi,  8, "UInt")
   NumPut(  1, bi, 12, "UShort")
   NumPut(  0, bi, 16, "UInt")
   NumPut(bpp, bi, 14, "UShort")
   hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
   return hbm
}
Edited (2 times)
That's exactly what I needed, thank you!, do you know if it works on w7 as well?

Re: Create an HBitmap with transparency

Posted: 12 May 2020, 15:06
by teadrinker
I've tested on Windows 7.

Re: Create an HBitmap with transparency

Posted: 13 May 2020, 02:53
by serzh82saratov
Как это работает? Я может забыл, но вроде если в 7 указать для Picture png с прозрачностью, то прозрачность не работала.

Re: Create an HBitmap with transparency

Posted: 13 May 2020, 09:04
by teadrinker
С png у меня на Win 7 так же работает:

Code: Select all

imagePath := "D:\Downloads\Иконки\1481055823_weather-01.png"
Gui, Color, Red
Gui, Margin, 0, 0
Gui, Add, Pic,, % imagePath
Gui, Add, Pic, x+-62 yp BackgroundTrans, % imagePath
Gui, Add, Pic, x+0 yp -BackgroundTrans, % imagePath
Gui, Show
 
 Image

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 04:39
by serzh82saratov
Ок, а как в такой hBitmap вставить текст, или нарисовать линию?

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 14:15
by teadrinker
I think it's only possible using GDI+, since GDI doesn't support transparency directly.

Code: Select all

colorWithTransparency := 0x70AABB00
width := 300
height := 100

hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
DrawText(hBitmap, "AutoHotkey", "x0 y18 cAAAA00FF Center s40", "calibri", width)
DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)

Gui, Margin, 0, 0
Gui, Color, White
Gui, Add, Text, x10 y5, test
Gui, Add, Pic, x0 y0 BackgroundTrans, HBITMAP:%hBitmap%
Gui, Show

CreateColoredBitmap(width, height, color) {
   hBitmap := GDI.CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + (width*i + A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

DrawLine(ByRef hBitmap, color, FromXY, ToXY, thickness) {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   (color >> 24 = 0 && color |= 0xFF000000)
   pPen := Gdip_CreatePen(color, thickness)
   Gdip_DrawLine(G, pPen, FromXY[1], FromXY[2], ToXY[1], ToXY[2])
   Gdip_DeletePen(pPen)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

DrawText(ByRef hBitmap, text, options, font, width := "", height := "") {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   Gdip_TextToGraphics(G, text, options, font, width, height)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

class GDI {
   __New(ByRef hBitmap) {
      static szBITMAP := 4*4 + A_PtrSize*2
      VarSetCapacity(BITMAP, szBITMAP, 0)
      DllCall("GetObject", "Ptr", hBitmap, "UInt", szBITMAP, "Ptr", &BITMAP)
      width := NumGet(BITMAP, 4, "UInt")
      height := NumGet(BITMAP, 8, "UInt")
      hTmpBitmap := this.CreateDIBSection(width, -height)
      this.MDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      this.hTmpObj := DllCall("SelectObject", "Ptr", this.MDC, "Ptr", hTmpBitmap, "Ptr")
      this.DrawBackground(hBitmap, width, height)
      DllCall("DeleteObject", "Ptr", hBitmap)
      hBitmap := hTmpBitmap
   }
   
   __Delete() {
      DllCall("SelectObject", "Ptr", this.MDC, "Ptr", this.hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", this.MDC)
   }
   
   DrawBackground(hBitmap, width, height) {
      static SRCCOPY := 0xCC0020
      hTmpDC := DllCall("CreateCompatibleDC", "Ptr", this.MDC, "Ptr")
      hTmpObj := DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hBitmap, "Ptr")
      DllCall("BitBlt", "Ptr", this.MDC, "Int", 0, "Int", 0, "Int", width, "Int", height, "Ptr", hTmpDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
      DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", hTmpDC)
   }
   
   CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0) {
      hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
      VarSetCapacity(bi, 40, 0)
      NumPut( 40, bi,  0, "UInt")
      NumPut(  w, bi,  4, "UInt")
      NumPut(  h, bi,  8, "UInt")
      NumPut(  1, bi, 12, "UShort")
      NumPut(  0, bi, 16, "UInt")
      NumPut(bpp, bi, 14, "UShort")
      hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
      DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
      return hbm
   }
}

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 14:36
by serzh82saratov
Круто.
А возможно тут повысить производительность? Или скорее возможно ли рисовать напрямую в DC Picture без необходимости подписываться на WM_Paint?

Code: Select all

colorWithTransparency := 0x70AABB00
width := 300
height := 100

hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
DrawText(hBitmap, "AutoHotkey", "x0 y18 cffAA00FF Center s40", "calibri", width)
DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)

Gui, Margin, 0, 0
Gui, Color, White
Gui, Add, Text, x10 y5, test
Gui, Add, Pic, x0 y0 BackgroundTrans vPic, HBITMAP:%hBitmap%
Gui, Show

loop
{ 
	hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
	DrawText(hBitmap, A_TickCount, "x0 y18 cffAA00FF Center s40", "calibri", width)
	DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)
	GuiControl, , Pic, HBITMAP:*%hBitmap% 
}

CreateColoredBitmap(width, height, color) {
   hBitmap := GDI.CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + (width*i + A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

DrawLine(ByRef hBitmap, color, FromXY, ToXY, thickness) {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   (color >> 24 = 0 && color |= 0xFF000000)
   pPen := Gdip_CreatePen(color, thickness)
   Gdip_DrawLine(G, pPen, FromXY[1], FromXY[2], ToXY[1], ToXY[2])
   Gdip_DeletePen(pPen)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

DrawText(ByRef hBitmap, text, options, font, width := "", height := "") {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   Gdip_TextToGraphics(G, text, options, font, width, height)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

class GDI {
   __New(ByRef hBitmap) {
      static szBITMAP := 4*4 + A_PtrSize*2
      VarSetCapacity(BITMAP, szBITMAP, 0)
      DllCall("GetObject", "Ptr", hBitmap, "UInt", szBITMAP, "Ptr", &BITMAP)
      width := NumGet(BITMAP, 4, "UInt")
      height := NumGet(BITMAP, 8, "UInt")
      hTmpBitmap := this.CreateDIBSection(width, -height)
      this.MDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      this.hTmpObj := DllCall("SelectObject", "Ptr", this.MDC, "Ptr", hTmpBitmap, "Ptr")
      this.DrawBackground(hBitmap, width, height)
      DllCall("DeleteObject", "Ptr", hBitmap)
      hBitmap := hTmpBitmap
   }
   
   __Delete() {
      DllCall("SelectObject", "Ptr", this.MDC, "Ptr", this.hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", this.MDC)
   }
   
   DrawBackground(hBitmap, width, height) {
      static SRCCOPY := 0xCC0020
      hTmpDC := DllCall("CreateCompatibleDC", "Ptr", this.MDC, "Ptr")
      hTmpObj := DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hBitmap, "Ptr")
      DllCall("BitBlt", "Ptr", this.MDC, "Int", 0, "Int", 0, "Int", width, "Int", height, "Ptr", hTmpDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
      DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", hTmpDC)
   }
   
   CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0) {
      hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
      VarSetCapacity(bi, 40, 0)
      NumPut( 40, bi,  0, "UInt")
      NumPut(  w, bi,  4, "UInt")
      NumPut(  h, bi,  8, "UInt")
      NumPut(  1, bi, 12, "UShort")
      NumPut(  0, bi, 16, "UInt")
      NumPut(bpp, bi, 14, "UShort")
      hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
      DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
      return hbm
   }
}

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 14:48
by teadrinker
serzh82saratov wrote: А возможно тут повысить производительность?
Must be

Code: Select all

loop
{ 
   DllCall("DeleteObject", "Ptr", hBitmap)  ; <<<<<<<<
   hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
   DrawText(hBitmap, A_TickCount, "x0 y18 cffAA00FF Center s40", "calibri", width)
   DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)
   GuiControl, , Pic, HBITMAP:*%hBitmap% 
}
serzh82saratov wrote: Или скорее возможно ли рисовать напрямую в DC Picture без необходимости подписываться на WM_Paint?
Of course it's possible. Just after drawing stopped, use STM_SETIMAGE.
UPD. Or GuiControl, , Pic, HBITMAP:*%hBitmap%

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 15:16
by serzh82saratov
С STM_SETIMAGE хуже.
Быстрее наверное не получится, всё тормозит CreateColoredBitmap.

Code: Select all

colorWithTransparency := 0x70AABB00
width := 300
height := 100

hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
DrawText(hBitmap, "AutoHotkey", "x0 y18 cffAA00FF Center s40", "calibri", width)
DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)
STM_SETIMAGE := 0x172
Gui, Margin, 0, 0
Gui, Color, White
Gui, Add, Text, x10 y5, test
Gui, Add, Pic, x0 y0 BackgroundTrans vPic HWNDhPic, HBITMAP:%hBitmap%
Gui, Show


STM_SETIMAGE := 0x172, IMAGE_BITMAP := 0x0


loop
{ 
	DllCall("DeleteObject", "Ptr", hBitmap)  ; <<<<<<<<
	hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
	DrawText(hBitmap, A_TickCount, "x0 y18 cffAA00FF Center s40", "calibri", width)
	DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)
	; GuiControl, , Pic, HBITMAP:*%hBitmap% 
	SendMessage, STM_SETIMAGE, IMAGE_BITMAP, hBitmap, , % "ahk_id " hPic
	DllCall("DeleteObject", Ptr, ErrorLevel)
	DllCall("DeleteObject", Ptr, hBitmap)
}

CreateColoredBitmap(width, height, color) {
   hBitmap := GDI.CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + (width*i + A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

DrawLine(ByRef hBitmap, color, FromXY, ToXY, thickness) {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   (color >> 24 = 0 && color |= 0xFF000000)
   pPen := Gdip_CreatePen(color, thickness)
   Gdip_DrawLine(G, pPen, FromXY[1], FromXY[2], ToXY[1], ToXY[2])
   Gdip_DeletePen(pPen)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

DrawText(ByRef hBitmap, text, options, font, width := "", height := "") {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   Gdip_TextToGraphics(G, text, options, font, width, height)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

class GDI {
   __New(ByRef hBitmap) {
      static szBITMAP := 4*4 + A_PtrSize*2
      VarSetCapacity(BITMAP, szBITMAP, 0)
      DllCall("GetObject", "Ptr", hBitmap, "UInt", szBITMAP, "Ptr", &BITMAP)
      width := NumGet(BITMAP, 4, "UInt")
      height := NumGet(BITMAP, 8, "UInt")
      hTmpBitmap := this.CreateDIBSection(width, -height)
      this.MDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      this.hTmpObj := DllCall("SelectObject", "Ptr", this.MDC, "Ptr", hTmpBitmap, "Ptr")
      this.DrawBackground(hBitmap, width, height)
      DllCall("DeleteObject", "Ptr", hBitmap)
      hBitmap := hTmpBitmap
   }
   
   __Delete() {
      DllCall("SelectObject", "Ptr", this.MDC, "Ptr", this.hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", this.MDC)
   }
   
   DrawBackground(hBitmap, width, height) {
      static SRCCOPY := 0xCC0020
      hTmpDC := DllCall("CreateCompatibleDC", "Ptr", this.MDC, "Ptr")
      hTmpObj := DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hBitmap, "Ptr")
      DllCall("BitBlt", "Ptr", this.MDC, "Int", 0, "Int", 0, "Int", width, "Int", height, "Ptr", hTmpDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
      DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", hTmpDC)
   }
   
   CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0) {
      hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
      VarSetCapacity(bi, 40, 0)
      NumPut( 40, bi,  0, "UInt")
      NumPut(  w, bi,  4, "UInt")
      NumPut(  h, bi,  8, "UInt")
      NumPut(  1, bi, 12, "UShort")
      NumPut(  0, bi, 16, "UInt")
      NumPut(bpp, bi, 14, "UShort")
      hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
      DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
      return hbm
   }
}

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 15:20
by teadrinker
You need using STM_SETIMAGE only once. :)
Draw an image with BitBlt. But I'm not sure if transparency will be maintained, haven't tested.

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 15:22
by serzh82saratov
В "обычном" исполнении цвета какие то грязные.

Попутно возник вопрос, как вывести Pic на передний план?
Неожиданно для меня эти варианты работают, и почему то уменьшают прозрачность

Code: Select all

; MsgBox % 1
; GuiControl, Disable, %hPic1%
; MsgBox % 2
; GuiControl, Enable, %hPic1%
или

Code: Select all

; MsgBox % 1
; GuiControl, +gGuiEscape, %hPic1% 
; GuiControl, -g, %hPic1% 
; MsgBox % 2
; GuiControl, +gGuiEscape, %hPic2% 
; GuiControl, -g, %hPic2% 

Code: Select all

GDI := new GDIpLoad

colorWithoutTransparency := 0x55FF0000
colorWithTransparency := 	0x550000FF
width := 200
height := 200 

exDIB1 := new DIBSection(Width, Height)   
 
pBrush := Gdip_BrushCreateSolid(colorWithoutTransparency)
Gdip_FillRoundedRectangle(exDIB1.pGraphics, pBrush, 0, 0, Width, Height, 40)   
Gdip_TextToGraphics(exDIB1.pGraphics, "Rounded not AntiAlias`nSmoothingMode", "x0 y0 vCenter Center s18 cffffffff r4 Italic", "", Width, Height)  
Gdip_DeleteBrush(pBrush)
exDIB2 := new DIBSection(Width, Height)   

pBrush := Gdip_BrushCreateSolid(colorWithTransparency)
Gdip_FillRectangle(exDIB2.pGraphics, pBrush, 0, 0, Width, Height)  
Gdip_DeleteBrush(pBrush)
Gdip_SetCompositingMode(exDIB2.pGraphics, 1)  
pBrush := Gdip_BrushCreateSolid(0x00000000)
Gdip_FillRoundedRectangle(exDIB2.pGraphics, pBrush, Width / 4, Height / 4, Width / 2, Height / 2, 40)   
Gdip_DeleteBrush(pBrush) 


Gui +AlwaysOnTop
Gui, Color, FAD886
Gui, Margin, 0, 0
Gui, Font, s18  
Gui, Add, Text, x0 y0 w%Width% Right, Background text
Gui, Add, Pic, x0 y0 HWNDhPic1 BackgroundTrans, % "HBITMAP:*" exDIB1.hBitmap
Gui, Add, Pic, x100 y100 HWNDhPic2 BackgroundTrans, % "HBITMAP:*" exDIB2.hBitmap
Gui, Show, xCenter y0
 
; WinSet, AlwaysOnTop, On, ahk_id %hPic1% 
; GuiControl, MoveDraw, %hPic1%
; GuiControl, Hide, %hPic1%
; GuiControl, Show, %hPic1%

; MsgBox % 1
; GuiControl, Disable, %hPic1%
; MsgBox % 2
; GuiControl, Enable, %hPic1%

; MsgBox % 1
; GuiControl, +gGuiEscape, %hPic1% 
; GuiControl, -g, %hPic1% 
; MsgBox % 2
; GuiControl, +gGuiEscape, %hPic2% 
; GuiControl, -g, %hPic2% 
Return

class GDIpLoad {  
	__New() { 
		this.pToken := Gdip_Startup() 
	}
	__Delete() { 
		Gdip_Shutdown(this.pToken)
	}
}

class DIBSection {
	__New(w, h) { 
		this.hDC := CreateCompatibleDC()
		this.hBitmap := CreateDIBSection(w, h, this.hDC)
		; this.hBitmap := CreateColoredBitmap(w, h, this.hDC)
		this.obm := SelectObject(this.hDC, this.hBitmap)
		this.pGraphics := Gdip_GraphicsFromHDC(this.hDC)
		Gdip_SetSmoothingMode(this.pGraphics, 4)
		Gdip_SetInterpolationMode(this.pGraphics, 7)
	}
	__Delete() { 
		SelectObject(this.hDC, this.obm)
		DeleteObject(this.hBitmap)
		DeleteDC(this.hDC)
		Gdip_DeleteGraphics(this.pGraphics)
	}
}

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 15:29
by teadrinker
serzh82saratov wrote: Попутно возник вопрос, как вывести Pic на передний план?
No ideas right now, I haven't tried.

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 18:52
by teadrinker
I wrote an example with BitBlt:

Code: Select all

colorWithTransparency := 0x70AABB00
width := 300
height := 100

hBitmap := CreateColoredBitmap(width, height, colorWithTransparency)
RC := DrawText(hBitmap, "Timer:", "x45 y18 cAAAA00FF s40", "calibri")
x := RegExReplace(RC, "([^|]+\|){2}([^|]+).+", "$2") + 45
drawWidth := 250 - x
drawHeight := RegExReplace(RC, "([^|]+\|){3}([^|]+).+", "$2")
DrawLine(hBitmap, 0x99FF0000, [50, 70], [250, 70], 4)

Gui, Margin, 0, 0
Gui, Color, White
Gui, Add, Text, x10 y5, test
Gui, Add, Pic, x0 y0 BackgroundTrans hwndhPic, HBITMAP:*%hBitmap%
Gui, Show

pToken := Gdip_Startup()
hPicDc := GetDC(hPic)

SRCCOPY := 0xCC0020
MDC := CreateCompatibleDC()
MBM := CreateDIBSection(drawWidth, drawHeight)
oBM := SelectObject(MDC, MBM)
BitBlt(MDC, 0, 0, drawWidth, drawHeight, hPicDc, x, 18, SRCCOPY)

DrawDC := CreateCompatibleDC()
DrawBM := CreateDIBSection(drawWidth, drawHeight)
oDrawBM := SelectObject(DrawDC, DrawBM)
G := Gdip_GraphicsFromHDC(DrawDC)

Loop 1000 {
   BitBlt(DrawDC, 0, 0, drawWidth, drawHeight, MDC, 0, 0, SRCCOPY)
   Gdip_TextToGraphics(G, A_Index, "w" . drawWidth . " c809900DD s40 Center", "calibri")
   BitBlt(hPicDc, x, 18, drawWidth, drawHeight, DrawDC, 0, 0, SRCCOPY)
   Sleep, 10
}

Gdip_DeleteGraphics(G)
SelectObject(DrawDC, oDrawBM)
DeleteDC(DrawDC)
DeleteObject(DrawBM)

SelectObject(MDC, oBM)
DeleteDC(MDC)
DeleteObject(MBM)

DeleteDC(hPicDc)
Gdip_Shutdown(pToken)

DrawText(hBitmap, "1000", "x" x - 8 " y18 cAAAA00FF s40", "calibri")
GuiControl,, %hPic%, HBITMAP:%hBitmap%
Return

GuiClose() {
   ExitApp
}

CreateColoredBitmap(width, height, color) {
   hBitmap := GDI.CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + (width*i + A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

DrawLine(ByRef hBitmap, color, FromXY, ToXY, thickness) {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   (color >> 24 = 0 && color |= 0xFF000000)
   pPen := Gdip_CreatePen(color, thickness)
   Gdip_DrawLine(G, pPen, FromXY[1], FromXY[2], ToXY[1], ToXY[2])
   Gdip_DeletePen(pPen)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}

DrawText(ByRef hBitmap, text, options, font, width := "", height := "") {
   DC := new GDI(hBitmap)
   pToken := Gdip_Startup()
   G := Gdip_GraphicsFromHDC(DC.MDC)
   RC := Gdip_TextToGraphics(G, text, options, font, width, height)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
   Return RC
}

class GDI {
   __New(ByRef hBitmap) {
      static szBITMAP := 4*4 + A_PtrSize*2
      VarSetCapacity(BITMAP, szBITMAP, 0)
      DllCall("GetObject", "Ptr", hBitmap, "UInt", szBITMAP, "Ptr", &BITMAP)
      width := NumGet(BITMAP, 4, "UInt")
      height := NumGet(BITMAP, 8, "UInt")
      hTmpBitmap := this.CreateDIBSection(width, -height)
      this.MDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      this.hTmpObj := DllCall("SelectObject", "Ptr", this.MDC, "Ptr", hTmpBitmap, "Ptr")
      this.DrawBackground(hBitmap, width, height)
      DllCall("DeleteObject", "Ptr", hBitmap)
      hBitmap := hTmpBitmap
   }
   
   __Delete() {
      DllCall("SelectObject", "Ptr", this.MDC, "Ptr", this.hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", this.MDC)
   }
   
   DrawBackground(hBitmap, width, height) {
      static SRCCOPY := 0xCC0020
      hTmpDC := DllCall("CreateCompatibleDC", "Ptr", this.MDC, "Ptr")
      hTmpObj := DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hBitmap, "Ptr")
      DllCall("BitBlt", "Ptr", this.MDC, "Int", 0, "Int", 0, "Int", width, "Int", height, "Ptr", hTmpDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
      DllCall("SelectObject", "Ptr", hTmpDC, "Ptr", hTmpObj, "Ptr")
      DllCall("DeleteDC", "Ptr", hTmpDC)
   }
   
   CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0) {
      hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
      VarSetCapacity(bi, 40, 0)
      NumPut( 40, bi,  0, "UInt")
      NumPut(  w, bi,  4, "UInt")
      NumPut(  h, bi,  8, "UInt")
      NumPut(  1, bi, 12, "UShort")
      NumPut(  0, bi, 16, "UInt")
      NumPut(bpp, bi, 14, "UShort")
      hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
      DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
      return hbm
   }
}

Re: Create an HBitmap with transparency

Posted: 17 May 2020, 21:03
by malcev
Transparency with pure GDI
https://parnassus.co/transparent-graphics-with-pure-gdi-part-1/
serzh82saratov, if You need speed You have to forgot about legacy technologies and OS and use DirectComposition with Direct3D 11 and DXGI like in this example::
https://docs.microsoft.com/en-us/windows/win32/directcomp/how-to--animate-the-bitmap-of-a-layered-child-window