Page 1 of 1

[Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 1:02 am
by Nituvious
Hi, I wanted see if it was possible to skin a window with a transparent PNG image.
This is an extremely simple window skinning example.

If a PB Pro can follow up and tell me if the code is redundant or bad, please let me know so I can see where to improve it.
Image

Code: Select all

; Skinny example
; PB 4.51 (x86)
; by Nituvious @ 2/21/2011

;IncludeFile "WinAPI.pbi"

Procedure OpenTransparentWindow(transColor, x, y, width, height) ;-- Create an invisible, borderless, and transparent window
	; HideWindow(winResult, 0) after gadgets have been placed. Otherwise you may see flicker.
	; I do not know if this works on all versions of windows or just Vista / 7
	; I have only tested on both x86 and x64 Windows 7

	winResult = OpenWindow(#PB_Any, 1, 1, 1, 1, "",#PB_Window_BorderLess| #PB_Window_Invisible)
	SetWindowColor(winResult,transColor)

	SetWindowLongPtr_(WindowID(winResult),#GWL_EXSTYLE,  #WS_EX_LAYERED)  ; -- According to the MSDN, this function will work with both x86 and x64 ( http://msdn.microsoft.com/en-us/library/ms644898(v=VS.85).aspx )
	SetWindowPos_(WindowID(winResult),#Null, x, y, width, height, #Null) ; -- Must redraw window, according to the MSDN

	SetLayeredWindowAttributes_(WindowID(winResult),transColor,#Null,#LWA_COLORKEY)

	ProcedureReturn winResult

EndProcedure

Procedure TransparentTextGadget(hwnd.l, x, y, string.s, Font.l, Color.l) ;-- Create Text without a background
	; TextGadget() seem's to leave holes behind everything
	; It is probably better practice to remove the StartDrawing(WindowOutput(hwnd)) from this procedure
	; and instead place it within the main loop. I do not know if keeping it within a Procedure would hinder performance.
	StartDrawing(WindowOutput(hwnd))
		If Font.l <> #Null
			DrawingFont(FontID(Font.l))
		EndIf
		DrawingMode(#PB_2DDrawing_Transparent)
		DrawText(x, y, string.s,Color.l)
	StopDrawing()
EndProcedure


Enumeration 1
	#Window_Font
	#Window_SkinPNG
	#Window_Skin
	#Window_Close
EndEnumeration

UsePNGImageDecoder()
LoadFont(#Window_Font, "Gabriola", 24)
LoadImage(#Window_SkinPNG,"C:\skin.png")

MyWindow = OpenTransparentWindow(RGB(255,0,0), 450,200, 400,200)
ImageGadget(#Window_Skin,0,0,200,200,ImageID(#Window_SkinPNG)) : DisableGadget(#Window_Skin,1) ; <-- borderless image gadget is our "skin", for some reason things act strangely if the gadget does not get disabled


Frame3DGadget(#PB_Any,5, 26, 135,40,"")
ButtonGadget(#Window_Close, 330,25, 15,15,"X")

HideWindow(MyWindow, 0) ; <-- no flashy here

Repeat : Delay(1)

	eventID = WaitWindowEvent(1)

	If eventID = #PB_Event_Gadget
		Select EventGadget()
			Case #Window_Close
				eventID = #PB_Event_CloseWindow
		EndSelect
	EndIf

	TransparentTextGadget(MyWindow, 10, 20, "Hello World!", #Window_Font, RGB(250,0,0))

Until eventID = #PB_Event_CloseWindow
[Edit] fixed code so it should work now

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 3:07 am
by rsts
winapi.pbi?

cheers

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 3:39 am
by Nituvious
rsts wrote:winapi.pbi?

cheers
Oops, sorry about that! It was just an include with contained function prototypes so I could use the functions in the demo version. Sorry about that.
I have edited the code so it should work now.

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 12:14 pm
by Alireza
Nice example, Thanks

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 12:43 pm
by ts-soft
Nice example.

You should change the eventloop to:

Code: Select all

Repeat
  
  eventID = WaitWindowEvent()
  
  If eventID = #PB_Event_Gadget
    Select EventGadget()
      Case #Window_Close
        eventID = #PB_Event_CloseWindow
    EndSelect
  ElseIf eventID = #PB_Event_Repaint
    TransparentTextGadget(MyWindow, 10, 20, "Hello World!", #Window_Font, RGB(250,0,0))
  EndIf
  
  
Until eventID = #PB_Event_CloseWindow 
A delay in event loop is a bad idea. Code outsided the events the same.

Greetings - Thomas

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 12:59 pm
by IdeasVacuum
XP x86 PB4.51, the Window cannot be moved?

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 1:21 pm
by ts-soft
IdeasVacuum wrote:XP x86 PB4.51, the Window cannot be moved?
The code isn't designed to move :wink:

Code: Select all

Repeat
  
  eventID = WaitWindowEvent()
  
  If eventID = #PB_Event_Gadget
    Select EventGadget()
      Case #Window_Close
        eventID = #PB_Event_CloseWindow
        
    EndSelect
  ElseIf eventID = #PB_Event_Repaint
    TransparentTextGadget(MyWindow, 10, 20, "Hello World!", #Window_Font, RGB(250,0,0))
    
  ElseIf  #WM_KEYDOWN
    If GetActiveGadget() <> #Window_Close
      ReleaseCapture_()
      SendMessage_(WindowID(MyWindow), #WM_SYSCOMMAND, #SC_MOVE | #HTCAPTION, 0)
    EndIf
  EndIf   
  
Until eventID = #PB_Event_CloseWindow 

Re: [Windows] Skin Window with PNG

Posted: Tue Feb 22, 2011 1:22 pm
by c4s
IdeasVacuum wrote:XP x86 PB4.51, the Window cannot be moved?
Use this code at e.g. #WM_LBUTTONDOWN and it should work:

Code: Select all

SendMessage_(WindowID(WindowNr), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)

Re: [Windows] Skin Window with PNG

Posted: Mon Feb 28, 2011 12:42 pm
by ultralazor
There are a lot of old skinning threads here, I remember stuff about gadgets breaking. You can't do it with GTK/Linux and Mac/MUI without further hacking UI libs.

Re: [Windows] Skin Window with PNG

Posted: Tue Mar 22, 2011 11:19 pm
by ricardo
But, if the image (PNG) has some part of it with alpha transparency, it does no show as transparent (showing the desktop) but get colored by red. How to avoid this problem?

Re: [Windows] Skin Window with PNG

Posted: Wed Mar 23, 2011 12:25 am
by c4s
@ricardo
Today is your lucky day. ;)
Yesterday I needed the same, so I just created a code (which is based on another one I forgot). It's a little more complex than this but works great. See here:
http://www.purebasic.fr/english/viewtop ... 12&t=45811

Re: [Windows] Skin Window with PNG

Posted: Wed Mar 23, 2011 2:26 am
by ricardo
c4s wrote:@ricardo
Today is your lucky day. ;)
Yesterday I needed the same, so I just created a code (which is based on another one I forgot). It's a little more complex than this but works great. See here:
http://www.purebasic.fr/english/viewtop ... 12&t=45811

Thanks!! :)

I found a different solution, BUT found the same problem... cant put gadgets on it!!
Now, with your code i guess this other question was already answered too :D

Thank you again!