Thanks Patrice,
As I got some requests to explain how to use it in PureBasic, here is the long story and a sceleton PB Include for Winlift 32 and 64 bit.
The screenshot Patrice provided (and some other on Patrice's objreader.com forum)
are from a working PureBasic Email Client - so I can confirm, that most things work quite fine and also look good!
As PureBasic executables on Windows are not a pure WinAPI applications, some caveats are to be considered.
Please do not ostracize me for poor coding of the include below - I started using PB a year ago and only on the Weekends
Link to the Download:
http://www.objreader.com/download/demo/SkinTheme.7z
Before you start screaming, please read below:
Demo version skins only main screen.
Winlift 7 does not need any special Window styles or WinAPI calls or additional Message Pumps.
Not every single gadget will work - so chose your controls or check if you can use those, which work.
Splitters will not be skinned (or WebGadget or canvas) BUT to show a nice splitter - make your own splitter bars using CanvasGadget and as long as it is less than 15 px wide or less than 15 px in height - it will be considered as splitter!
Background images are rotated by left or right click on the "System Menu" - if they contain transparency (png) and skin is defined as using DWM/Aplha - it will nicely show through desktop/background - don't complain - amount of alpha in your image needs tweaking to get ideal result (readable / transparent)
It works the same on 32 and 64 bit - it will not work on XP, Vista/Win 7 or later is needed.
It will increase RAM for your application (for an app using 10-12 MB RAM it will become 20 - something)
Resizing trees and very complex screens may not be perfectly smooth - just like resizing treegadget in PB itself is not smooth - you can use Winlift sizing instead (proportional, anchored etc.) - this may work or may not work for you, if you have nested containers. Play with your code to see the best option.
Menus are replaced and work well *only* if they have no images (images in menus are not implemented in Winlift)
Not all gadgets are tested with PB, following should work fine: window frame, menu (no images), statusbars, progress bars, String, Tree, Text, ImageList (Report View), ListView, combos boxes, lists, virtual ListView (so secondary subclassing also works), buttons, checkboxes, option boxes and toolbars.
There is a neat function to add multiple PNG sliced images to (Image)ListView in single column, which will adjust their size to row height. Refer to Objreader forum - there is an example of what I'm using and Patrice made it neat.
Multiple windows - no problem.
Hidden windows - if they have menu a click on main window may pass through to the hidden window menu (neither Patrice nor I could figure it out completely) so keep your hidden window off-screen if you must or do not use hidden windows apart from window start-up.
An application must have a main window and main window needs to be skinned first.
If you want to switch skin at runtime: from no skin to skin you need to restart the application and init skin engine properly. From one skin to another: just switch skin with a new path to the skin definition file. From Skin to no skin - restart application and do not init the skin engine.
Do not skin the same window repeatedly, it would work, but will cause memory leaks.
If you do not like the System Menu button to rotate the skin backgrounds - intercept the Windows message and add your own "system" menu
Bitmaps used for the (transparent or not) background are defined in the .sks file.
Always cleanly unload (FreeLibrary) at the end of your application - after all windows are closed, to remove hooks and release resources.
Finally: if you do not like the fancy skin styles from Patrice's distribution, find it odd, outdated or not to your taste - just make your own - it is easy to program (but hard if you are not skilled in graphic design

) : skin definition is in plain text, bitmaps for frame, buttons, check, splitter handles are in the skin folder.
Usage:
Design you main window.
Call wrapper function below: InitSkins(MainWindow.i, SkinName.s) where MainWindow is the Window and Skinname (full) path to the .sks file.
For additional windows (if you have a license): call wrapper "SkinWindow(thewin.i)"
If you want to use message boxes or sizing / anchoring - implement also other functions form WinLift(64).h the same way as you see below
simple include file (remove LIB implementation code if you just use DLL):
Code: Select all
EnableExplicit
; you need to free library on the application exit using this handle.
; if libhandle is 0 or 2 - do not call FreeLibrary() if it is any other integer - FreeLibrary at app exit.
Global libhandle
#COMPILE_WINLIFTDLL = 1 ; you can try Lib version if you want
; check the other C contants from Winlift.h if you want to use Winlift Sizing,
; below is not necessary for skinning, just a sample how to translate from C++ header
#SK_CXFRAMERIGHT = 4
#SK_CYFRAMEBOTTOM = 5
#SK_CYFRAMETOP = 0
CompilerIf #COMPILE_WINLIFTDLL = 1 ; use DLL not lib - default
Prototype.l skInitEngine(skinname.p-unicode, userkey.p-unicode)
Prototype skSkinWindow(hwnd.l, tooltips.p-unicode)
Prototype.l skDialogYesNo(Zcaption.p-unicode, zText.p-unicode, zButton.p-unicode)
Prototype skSkinChildCtrl(hwnd.l, Redraw.l)
Prototype skDoNotSkinPopupMenu(yesno.l, rw.l)
Prototype skSkinEnable(hwnd.l)
Prototype skSkinDisable(hwnd.l)
Prototype skSetLabelFont(hctrl.l, zFontName.s, nFontSize.l, ARGBcolor.l, nFontStyle.l, redraw.b = 0)
Prototype skSetListViewImage(FullPathName.s, ReadWriteFlag.l) ;set to 1!
Prototype skGetClientSize(hWnd.l, xClient.l, yClient.l, ClientWidth.l, ClientHeight.l)
Prototype skUseAnchorMode(hWnd.l, UseMode.l)
Prototype skHomotheticResize(hwnd.l, bool.i)
Prototype skAnchorInit(hWnd.l)
Prototype.s skDialogInput(zCaption.s, zMessage.s, zButtons.s);
Prototype.l skGetSystemMetrics(sksize.l)
Prototype.l skARGB(a.i, r.i, g.i, b.i)
Prototype skGetWindowSize(hWnd.l, xClient.l, yClient.l, ClientWidth.l, ClientHeight.l)
Prototype.b skSkinChange(zSkinFile.p-unicode)
Prototype skShowScrollBarEx(hCtrl.l, lParam.b);
CompilerElseIf #COMPILE_WINLIFTDLL =0 ; only if using static LIB, othersise - remove the whole block
;Sample: if using lib and 32 bit, obviously use conditional compilation for each:
CompilerSelect #PB_Compiler_Processor
CompilerCase #PB_Compiler_32Bit
#Libfile = "WinLIFT32.lib"
ImportC #Libfile
CompilerEndSelect
;End sample, remove
; below works with a static C Lib and 64 bit:
ImportC "WinLIFT64.lib" ; or ImportC "winlift32.lib"
skInitEngine.l(skinname.p-unicode, userkey.p-unicode)
skSkinWindow(hwnd.l, tooltips.p-unicode)
skDialogYesNo.l(Zcaption.p-unicode, zText.p-unicode, zButton.p-unicode)
skSkinChildCtrl(hwnd.l, Redraw.l)
skDoNotSkinPopupMenu(yesno.l, rw.l)
skSkinEnable(hwnd.l)
skSkinDisable(hwnd.l)
skSetLabelFont(hctrl.l, zFontName.s, nFontSize.l, ARGBcolor.l, nFontStyle.l, redraw.b = 0)
skSetListViewImage(FullPathName.s, ReadWriteFlag.l) ;set to 1!
skGetClientSize(hWnd.l, xClient.l, yClient.l, ClientWidth.l, ClientHeight.l)
skUseAnchorMode(hWnd.l, UseMode.l)
skHomotheticResize(hwnd.l, bool.i)
skAnchorInit(hWnd.l)
;skDialogInput.s(zCaption.s, zMessage.s, zButtons.s);
skGetSystemMetrics.l(sksize.l)
skARGB.l(a.i, r.i, g.i, b.i)
skGetWindowSize(hWnd.l, xClient.l, yClient.l, ClientWidth.l, ClientHeight.l)
skSkinChange.b(zSkinFile.p-unicode)
skShowScrollBarEx(hCtrl.l, lParam.b);
EndImport
CompilerEndIf
Procedure InitSkinLib() ; PRIVATE load and init WinLift64/32
Protected appDir.s = ""
If #PB_Compiler_Debugger
appdir = GetCurrentDirectory()
Else
appdir = GetPathPart(ProgramFilename())
EndIf
Define libfile.s
If #PB_Compiler_32Bit = 0
libfile = appDir + "WinLIFT64.DLL"
Else
libfile = appDir + "WinLIFT32.DLL"
EndIf
CompilerIf #COMPILE_WINLIFTDLL ; using DLL, get addresses of functions
libhandle.i = OpenLibrary (#PB_Any,libfile)
Global skInitEngine.skInitEngine = GetFunction(libhandle,"skInitEngine")
Global skSkinWindow.skSkinWindow = GetFunction(libhandle,"skSkinWindow")
Global skDialogYesNo.skDialogYesNo = GetFunction(libhandle,"skDialogYesNo")
Global skSkinDisable.skSkinDisable = GetFunction(libhandle,"skSkinDisable")
Global skSetListViewImage.skSetListViewImage = GetFunction(libhandle,"skSetListViewImage")
Global skSetLabelFont.skSetLabelFont = GetFunction(libhandle,"skSetLabelFont")
Global skGetClientSize.skGetClientSize = GetFunction(libhandle,"skGetClientSize")
Global skHomotheticResize.skHomotheticResize = GetFunction(libhandle,"skHomotheticResize")
Global skAnchorInit.skAnchorInit = GetFunction(libhandle,"skAnchorInit")
Global skUseAnchorMode.skUseAnchorMode = GetFunction(libhandle,"skUseAnchorMode")
Global skDialogInput.skDialogInput = GetFunction(libhandle,"skDialogInput")
Global skARGB.skARGB = GetFunction(libhandle,"skARGB")
Global skGetSystemMetrics.skGetSystemMetrics = GetFunction(libhandle,"skGetSystemMetrics")
Global skGetWindowSize.skGetWindowSize = GetFunction(libhandle,"skGetWindowSize")
Global skSkinChange.skSkinChange = GetFunction(libhandle,"skSkinChange")
Global skShowScrollBarEx.skShowScrollBarEx = GetFunction(libhandle,"skShowScrollBarEx")
CompilerElse
libhandle = 2 ; Libhandle is set to 2 as we use static LIB - there is no FreeLibrary needed. On application end - call FreeLibrary only if libhandle is a valid handle, not 0 or 2
CompilerEndIf
EndProcedure
Procedure SkinWindow(thewin.i) ; PUBLIC This should be used, after Init to skin any subsequent window. Use only once per each window!
If libhandle <> 0
Protected hwnd.l = WindowID(thewin)
skSkinWindow(hwnd , " Dock | Undock | Minimize | Maximize | Restore | Close ")
EndIf
EndProcedure
; shorthand for Init and skin Main window - use this at start of the applicaiton (when window is still hidden) to initialize engine and apply skin.
; As first window becomes main window for WinLift this is better called first.
Procedure.i InitSkins(MainWindow.i, SkinName.s) ; PUBLIC
If libhandle = 0
InitSkinLib()
EndIf
If libhandle
If IsWindow(MainWindow) = 0
ProcedureReturn
EndIf
Protected skinfile.s
If FindString(SkinName, #PS$)
skinfile = SkinName
Else
SetCurrentDirectory(appDir)
skinfile.s = appDir + SkinName
EndIf
If FileSize(skinfile) < =0
MessageRequester("Skin file not present", "Skin not found: " + skinfile)
ProcedureReturn 0 ; but be aware - lib is loaded already and needs to be freed!
EndIf
Protected hwnd.i = WindowID(MainWindow)
Protected isok =0
isok = skInitEngine(skinfile , "") ; add you license key here, or try with single window
If isok
SkinWindow(MainWindow)
EndIf
ProcedureReturn isok
EndIf
EndProcedure
You can contact me here for WinLift questions I may have answer to or not regarding PureBasic, for Winlift itself - use Patrice's ObjReader.com forum, CHM file (also Forum)
Cheers!