Create an HBitmap with transparency Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Create an HBitmap with transparency

12 May 2020, 10:47

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.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

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
User avatar
Smile_
Posts: 857
Joined: 03 May 2020, 00:51

Re: Create an HBitmap with transparency

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?
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Create an HBitmap with transparency

12 May 2020, 12:31

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.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency  Topic is solved

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)
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

12 May 2020, 14:56

Это работает на семёрке?
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Create an HBitmap with transparency

12 May 2020, 15:01

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?
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

13 May 2020, 02:53

Как это работает? Я может забыл, но вроде если в 7 указать для Picture png с прозрачностью, то прозрачность не работала.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

13 May 2020, 09:04

С 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
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

17 May 2020, 04:39

Ок, а как в такой hBitmap вставить текст, или нарисовать линию?
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

17 May 2020, 14:15

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
   }
}
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

17 May 2020, 14:36

Круто.
А возможно тут повысить производительность? Или скорее возможно ли рисовать напрямую в 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
   }
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

17 May 2020, 14:48

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%
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

17 May 2020, 15:16

С 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
   }
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

17 May 2020, 15:20

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.
Last edited by teadrinker on 17 May 2020, 15:23, edited 1 time in total.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

17 May 2020, 15:22

В "обычном" исполнении цвета какие то грязные.

Попутно возник вопрос, как вывести 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)
	}
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

17 May 2020, 15:29

serzh82saratov wrote: Попутно возник вопрос, как вывести Pic на передний план?
No ideas right now, I haven't tried.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

17 May 2020, 18:52

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
   }
}
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Create an HBitmap with transparency

17 May 2020, 21:03

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

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Chunjee and 110 guests