Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Bitmap gradients in Windows 7


  • Please log in to reply
10 replies to this topic
Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
I am trying to write a script using the Bitmap Gradient routine by SKAN. It works fine in XP, but in Windows 7 the first colour is always black. The bitmap itself is generated correctly in Windows 7 (confirmed by enlarging it in a graphic programme).
The line that doesn't work is:

Gui, Add, Picture, x0 y0 w640 h400, %GradientFile%

No matter what the top colour is in XP, it is always black in Windows 7.

Does anyone know a way around this problem?

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
Does the following work for you?

Hex=
( JOIN
424D5A000000000000003600000028000000030000000300000001001800000000002400000000000000000000
00000000000000000000004000008000004000000000008030B3F0000080000000000040000080000040000000
)
VarSetCapacity( BMP,(cLen:=StrLen(hex)//2))
Loop %cLen%
   NumPut("0x" SubStr(hex,2*a_index-1,2),BMP,a_index-1,"char")

Hex=

Gui 1:-Caption +LastFound
Gui, Margin, 0,0
GUI1:=WinExist() , hDC:=DllCall("GetDC",UInt,Gui1)
Gui, Add, text, w640 h480 0xE vPic hwndhPic ; SS_BITMAP = 0xE
hBMP := DllCall( "CreateDIBitmap", UInt,hDC, UInt,(bmiHAddr:=&BMP+14)
,UInt,(CBM_INIT:=6), UInt,&BMP+NumGet(BMP,10), UInt,&BMP+14, UInt,(DIB_PAL_COLORS:=1) )
hBitmap:=DllCall("CopyImage",UInt, hBMP,UInt,0,Int,640,Int,480, UInt,0)
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %hPic%
Gui, Show, w640 h480
Return

GuiClose:
 ExitApp

The above code produces a Sunburst gradient for me in XP.

Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
Yes, that works in XP and Win7 - wonderful!

I'm afraid I don't understand the code, though.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

I don't understand the code


I hope the following is better:

; Redundant code edited out


Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
Thank you very much. That's much easier. Can I also use this method for gradients on buttons etc?

Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
Sorry! I spoke too soon. The second script doesn't work in Win7. It has the same result as my script - first colour always black.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
In that case you may revert back to:

Gui, Add, Picture, x0 y0 w640 h400, %GradientFile%

and try using a 9x9 pixels bitmap instead of 1x2.
Windows can be quiry when width/height of an image is 1 pixel

Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
Thanks to your suggestion I have found a solution. I didnt try 9x9 because it doesn't fit the concept, but tried a 9x2 bitmap. This produced a split colour screen in XP and Win7. I then tried a 2x2 bitmap and, lo, it produced a perfect gradient in XP and in Win7.

So, to make BitmapGradient compatible with Windows 7, the CreateBitmapGradient routine needs to be modified to create a 2x2 pixel bitmap instead of 1x2 pixel. This code makes my brain hurt, so perhaps someone with more experience than me could do it. :wink:

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

tried a 2x2 bitmap and, lo, it produced a perfect gradient in XP and in Win7.


Good to know! :)

the CreateBitmapGradient routine needs to be modified to create a 2x2 pixel bitmap instead of 1x2 pixel.


Can you try this instead and confirm?


#SingleInstance, Force

Gui, Margin, 0,0
Gui, Add, Picture, w640 h480 [color=red]0xE[/color] hwnd[color=red]cHwnd[/color]
ApplyGradient( cHwnd, [color=black]0x000000[/color], [color=blue]0x0000FF[/color] )
Gui, Show,,


ApplyGradient( cHwnd=0, RB=0x0, LT=0x0, Vertical=1 ) { ; LT = Left/Top,  RB = Right/Bottom
 ; By SKAN / 27-Jul-2010            www.autohotkey.com/forum/viewtopic.php?p=372006#372006
 HotkeyIt := 6                    ; Credit:   Undocumented constant discovered by HotkeyIt
                                  ; www.autohotkey.com/forum/viewtopic.php?p=229361#229361
 VarSetCapacity( BMP,70,0 ),  NumPut( 0x10, NumPut( 0x180001, NumPut( 0x0200000002
 , NumPut( 0x2800000036, NumPut( 0x464D42, BMP ) + 6, 0, "Int64" ), 0, "Int64" ) ) + 4 )
 P := ( Vertical<>0 ) ?  NumPut( 0x14, NumPut( LT, NumPut( LT, NumPut( 0x14, NumPut( RB
 , NumPut( RB,BMP,54 )-1 )-1, 0, "UShort" ) )-1)-1, 0, "UShort" ) : NumPut( RB, NumPut( LT
 , NumPut( RB, NumPut( LT, BMP, 54 )-1 ) +1 ) -1 )
 TBM := DllCall( "CreateDIBitmap", UInt,hDC := DllCall("GetDC", UInt,cHwnd ), UInt,&BMP+14
                , UInt,[color=red]HotkeyIt[/color], UInt, &BMP+NumGet(BMP,10), UInt,&BMP+14, UInt,1 )
 ControlGetPos,,,W, H,, ahk_id %cHwnd%
 hBitmap := DllCall( "CopyImage", UInt,TBM, UInt,0, Int,W, Int,H, UInt,0 )
 DllCall( "SendMessage", UInt,cHwnd, UInt,0x172, UInt,0, UInt,hBitmap )
 DllCall( "DeleteObject", UInt,TBM ),  DllCall( "ReleaseDC", UInt,hDC )
Return hBitmap
}

Edit: HotKeyIt's discovery has been Credited

Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
That works in both XP and Windows 7. Wonderful!

By the way, I found an easy way to make the bitmaps in different widths is to use the panorama function in Irfanview (1x2+1x2+1x2) = (3x2).

Raki
  • Members
  • 7 posts
  • Last active: Sep 18 2010 06:54 PM
  • Joined: 25 Jul 2010
I've been playing with different gradient routines and trying to get the following proof of concept to work.
The user can choose two gradient colours, see the combined effect in a preview window and then, if he wishes, apply this gradient to the whole programme.
Problems:
1. The first ListView remains hidden, even when its background colour shows through.
2. I can't apply the gradient bitmap to the buttons because there is no %gradientfile%.
3. I can't display a new gradient in the preview window.
Here is the code:
; Gradient Preview by Raki
#SingleInstance, Force 

Colour1 = 0xADD7F7
Colour2 = 0xF3F3F3
TextColour = 5A78AA

Gui, Margin, 0,0 
Gui, Add, Picture, w355 h340 0xE hwndcHwnd 
ApplyGradient( cHwnd, Colour1, Colour2 ) 

	Gui, Add, GroupBox, x60 y31 w226 h143 ; 0x400000 ?
	Gui, Add, Picture, xp+1 yp+8 w224 h133 0xE hwndcHwnd ; %GradientFile% ; ShowGradient
	ApplyGradient( cHwnd, Colour1, Colour2 ) 


	Gui, Font, s18, Verdana
	Gui, Add, Text, xp+70 yp+48 BackgroundTrans c%TextColour%, Preview
	Gui, Font, s8, Verdana

	Gui, Add, Picture, xp-70 yp+110 w120 h23 0x400000 vButtonPickColour1 gPickColour, %GradientFile% 
	Gui, Add, Text,    xp+8 yp+5 w120 BackgroundTrans c000060, Pick Upper Colour
	Gui, Add, ListView, xp+184 yp-5 w30 h30 ReadOnly 0x4000 +Background%Colour2% vColourBlock1 lv0x800000

	Gui, Add, Picture, xp-192 yp+38 w120 h23 0x400000 vButtonPickColour2 gPickColour, %GradientFile%
	Gui, Add, Text,    xp+8 yp+5 w120 BackgroundTrans c000060, Pick Lower Colour
	Gui, Add, ListView, xp+184 yp-5 w30 h30 ReadOnly 0x4000 +Background%Colour1% vColourBlock2 lv0x800000

	Gui, Add, Picture, xp-192 yp+38 w120 h23 0x400000 gResetGradient, %GradientFile%
	Gui, Add, Text,    xp+8 yp+5 w120 BackgroundTrans c000060, Reset Colours
	
	Gui, Add, Picture, xp+134 yp-5 w80 h23 0x400000 gApplyColours, %GradientFile%
	Gui, Add, Text,    xp+28 yp+5 w120 BackgroundTrans c000060, Apply

Gui, Show,, 
	Gui, +LastFound
	hwnd := WinExist("G")
return

ApplyGradient( cHwnd=0, RB=0x0, LT=0x0, Vertical=1 ) { ; LT = Left/Top,  RB = Right/Bottom 
 ; By SKAN / 27-Jul-2010            www.autohotkey.com/forum/viewtopic.php?p=372006#372006 
 HotkeyIt := 6                    ; Credit:   Undocumented constant discovered by HotkeyIt 
                                  ; www.autohotkey.com/forum/viewtopic.php?p=229361#229361 
 VarSetCapacity( BMP,70,0 ),  NumPut( 0x10, NumPut( 0x180001, NumPut( 0x0200000002 
 , NumPut( 0x2800000036, NumPut( 0x464D42, BMP ) + 6, 0, "Int64" ), 0, "Int64" ) ) + 4 ) 
 P := ( Vertical<>0 ) ?  NumPut( 0x14, NumPut( LT, NumPut( LT, NumPut( 0x14, NumPut( RB 
 , NumPut( RB,BMP,54 )-1 )-1, 0, "UShort" ) )-1)-1, 0, "UShort" ) : NumPut( RB, NumPut( LT 
 , NumPut( RB, NumPut( LT, BMP, 54 )-1 ) +1 ) -1 ) 
 TBM := DllCall( "CreateDIBitmap", UInt,hDC := DllCall("GetDC", UInt,cHwnd ), UInt,&BMP+14 
                , UInt,HotkeyIt, UInt, &BMP+NumGet(BMP,10), UInt,&BMP+14, UInt,1 ) 
 ControlGetPos,,,W, H,, ahk_id %cHwnd% 
 hBitmap := DllCall( "CopyImage", UInt,TBM, UInt,0, Int,W, Int,H, UInt,0 ) 
 DllCall( "SendMessage", UInt,cHwnd, UInt,0x172, UInt,0, UInt,hBitmap ) 
 DllCall( "DeleteObject", UInt,TBM ),  DllCall( "ReleaseDC", UInt,hDC ) 
Return hBitmap 
}

PickColour:

if A_GuiControl = ButtonPickColour1
{
		if Dlg_Color( color, hwnd )
			GuiControl, +background%color%, ColourBlock1
			Show_Colour_Value2 = color
}
else
{

if A_GuiControl = ButtonPickColour2
{
	 	if Dlg_Color( color, hwnd )
			GuiControl, +background%color%, ColourBlock2
			Show_Colour_Value1 = color
}		
}

return	

ResetGradient:		

ShowGradientFile:=ApplyGradient( cHwnd, Show_Colour_Value1, Show_Colour_Value2 )

GuiControl Hide, ShowGradient
sleep 250
GuiControl,, ShowGradient, %ShowGradientFile%
GuiControl Show, ShowGradient
Return

Dlg_Color(ByRef Color, hGui=0){ 				; Copied from Forms library by majkinetor
  ;convert from rgb
    clr := ((Color & 0xFF) << 16) + (Color & 0xFF00) + ((Color >> 16) & 0xFF)

    VarSetCapacity(CHOOSECOLOR, 0x24, 0), VarSetCapacity(CUSTOM, 64, 0)
     ,NumPut(0x24,		CHOOSECOLOR, 0)      ; DWORD lStructSize 
     ,NumPut(hGui,		CHOOSECOLOR, 4)      ; HWND hwndOwner (makes dialog "modal"). 
     ,NumPut(clr,		CHOOSECOLOR, 12)     ; clr.rgbResult 
     ,NumPut(&CUSTOM,	CHOOSECOLOR, 16)     ; COLORREF *lpCustColors
     ,NumPut(0x00000103,CHOOSECOLOR, 20)     ; Flag: CC_ANYCOLOR || CC_RGBINIT 

    nRC := DllCall("comdlg32\ChooseColorA", str, CHOOSECOLOR)  ; Display the dialog. 
    if (errorlevel <> 0) || (nRC = 0) 
       return  false 

    clr := NumGet(CHOOSECOLOR, 12) 
    
    oldFormat := A_FormatInteger 
    SetFormat, integer, hex  ; Show RGB color extracted below in hex format. 

 ;convert to rgb 
    Color := (clr & 0xff00) + ((clr & 0xff0000) >> 16) + ((clr & 0xff) << 16) 
    StringTrimLeft, Color, Color, 2 
    loop, % 6-strlen(Color) 
		Color=0%Color% 
    Color=0x%Color% 
    SetFormat, integer, %oldFormat% 
	return true
}


ApplyColours:

return

GuiEscape:
GuiClose:
	ExitApp
Please, can anyone help me get this to work?