WinLIFT and GDImage custom controls

Started by Patrice Terrier, March 30, 2010, 02:11:35 PM

Previous topic - Next topic

Patrice Terrier

I have attached a ZIP project to this post, to show you how to use GDImage and WinLIFT custom controls within FireFly.

Rather than using a CTL file, i am using dummy buttons as template to figure the location of the custom controls, then these dummy buttons are destroyed, however you can still refer to their IDC to manipulate the custom controls the FireFly way.

The custom controls exposed in this project are:

  • GDImage graphic control to embed and manipulate transparent sprite image layers (like in PhotoShop).
  • WinLIFT button image.
  • WinLIFT clock widget.
  • WinLIFT rotating knob.

For the purpose of fast smooth display and to avoid flicker when resizing the main window, i am using exclusively the WinLIFT anchor/resize API to preserve the composited mode (transparency). Try maximize/restore to see the anchor mode in action.

There are three rotating knobs, however they all produce the same effect: rotation of the main sprite image (at any angle within 0-360 degree).
The purpose of using three knobs was to show you, how they could interact together, using the "skGaugeSetPos" and "skGaugeGetPos" API.
Hold down the left mouse button, while moving it, to rotate a knob control. Click on the right mouse button, to reset its angle rotation to zero degree.

I am using the WinLIFT "skCreateToolTip" API to use the skin color theme instead of Windows's.

The checkbox allows you to switch the GDImage graphic control between standard and composited mode, in composited mode you can see the current WinLIFT active background behind the graphic control without any speed loss. I keep drawing a small border around the graphic control to show you the frontier between GDImage and WinLIFT.

When using the "Select image" button you will see the common OpenFileDialog skinned by WinLIFT, the technic being used is explained here.

You can move the sprite image around with the mouse, while the transparent watermak logo is locked and anchored to the top right of the graphic control.

You will find a complete list of the WinLIFT API in the WINLIFT.INC file.

Screen shot of the project is also attached to this post.

...



[attachment deleted by admin]

Patrice Terrier

I have updated the zip file attached to the first post of this thread, because in the initial project i forgot to anchor the checkbox control, this has been fixed.

...

Patrice Terrier

Now, that i have more experience with FireFly, i have updated the ZIP file attached to the first post of this thread, to use the SplitTemplate function to work with the FireFly's global variables being used for IDC and HWND.

...

David Kenny

#3
Patrice,

I am struggling to understand your last post. Here is the SplitTemplate function from your last .zip:
Function SplitTemplate(ByVal hParent As Dword, ByVal IDC As Long, ByRef x As Long, ByRef y As Long, ByRef w As Long, ByRef h As Long, ByRef sLabel As String, ByRef sImagePath As String, ByRef dwStyle As Dword) As Long
    Local rc As Rect, p As PointApi, zString As Asciiz * 1024, hTemplate As Dword, sExt As String
   
    hTemplate = GetDlgItem(hParent, IDC)
    x = 0: y = 0: w = 0: h = 0: sLabel = "": sImagePath = ""
    If IsWindow(hTemplate) Then
       Call GetWindowRect(hTemplate, rc)
       p.X = rc.nLeft: p.Y = rc.nTop: Call ScreenToClient(GetParent(hTemplate), p)
       x = p.X: y = p.Y: w = rc.nRight - rc.nLeft: h = rc.nBottom - rc.nTop
       Call GetWindowText(hTemplate, zString, SizeOf(zString))
       If ParseCount(zString) = 2 Then
          sLabel = Parse$(zString, 2)
          sImagePath = Trim$(Parse$(zString, 1))
          If Instr(-1, sImagePath, "\") = 0 Then
             sImagePath = Exe.Path$ + "Resource\" + sImagePath
          End If
       Else
          sLabel = RTrim$(zString): sExt = "." + LCase$(Right$(sLabel, 3)) + "."
          If Instr(".png.jpg.bmp.gif.tif.", sExt) Then
             sImagePath = sLabel
             If Instr(-1, sImagePath, "\") = 0 Then
                sImagePath = Exe.Path$ + "Resource\" + sLabel
             End If
             sLabel = ""
          End If
       End If
       dwStyle = GetWindowLong(hTemplate, %GWL_STYLE)
'      // We don't need it anymore
       Call DestroyWindow(hTemplate)
       Function = -1     
    Else
       Function = 0
    End If
End Function

I don't see any IDC or HWND FF variable used in there.  I don't see any that should be used in there either.

** I figured it out. You were referring to the Main_WM_CREATE routine where you 'fixed' the HWND_MAIN_... global variables, after replacing the 'Template' buttons with the skinned buttons you created.  Very nice!

An excerpt from the MAIN_WM_CREATE:
'      // Create WinLIFT ImageButton, based on template.       
       If SplitTemplate(hWndForm, IDC_MAIN_BTNSELECT, x, y, w, h, sLabel, sImagePath, dwStyle) Then
          hCtrl = skButtonImage(hWndForm, (sImagePath), x, y, IDC_MAIN_BTNSELECT, 0)
'         // Anchor the buttom to bottom Right.           
          Call skSetAnchorCtrl(hCtrl, %ANCHOR_BOTTOM_RIGHT)
          Call skCreateToolTip(hCtrl, "WinLIFT button image")
'         // Assign the local hCtrl to the FF3 global handle         
          HWND_MAIN_BTNSELECT = hCtrl         
       End If

'      // Create WinLIFT ClockControl, based on template.       
       If SplitTemplate(hWndForm, IDC_MAIN_CLOCK, x, y, w, h, sLabel, sImagePath, dwStyle) Then
          hCtrl = skClockCtrl(hWndForm, (sImagePath), x, y, 0, 0, IDC_MAIN_CLOCK, &H7FCB0000, &H7F8F8F8F, 0)
'         // Anchor the button to bottom left.           
          Call skSetAnchorCtrl(hCtrl, %ANCHOR_BOTTOM)
          Call skCreateToolTip(hCtrl, "WinLIFT clock control")
'         // Assign the local hCtrl to the FF3 global handle         
          HWND_MAIN_CLOCK = hCtrl         
       End If

'      // Create WinLIFT KnobGauge, based on template.       
       If SplitTemplate(hWndForm, IDC_MAIN_KNOBLEFT, x, y, w, h, sLabel, sImagePath, dwStyle) Then
          hCtrl = skKnobGauge(hWndForm, (sImagePath), x, y, 0, 0, IDC_MAIN_KNOBLEFT, 0, 0, 0, 0)
'         // Anchor the button to bottom center.           
          Call skSetAnchorCtrl(hCtrl, %ANCHOR_CENTER_HORZ_BOTTOM)
          Call skCreateToolTip(hCtrl, "WinLIFT knob gauge")
'         // Assign the local hCtrl to the FF3 global handle         
          HWND_MAIN_KNOBLEFT = hCtrl         
       End If
       
'      // Create WinLIFT KnobGauge, based on template.       
       If SplitTemplate(hWndForm, IDC_MAIN_KNOBBIG, x, y, w, h, sLabel, sImagePath, dwStyle) Then
          hCtrl = skKnobGauge(hWndForm, (sImagePath), x, y, 0, 0, IDC_MAIN_KNOBBIG, 0, 0, 0, 0)
'         // Anchor the button to bottom center.           
          Call skSetAnchorCtrl(hCtrl, %ANCHOR_CENTER_HORZ_BOTTOM)
          Call skCreateToolTip(hCtrl, "WinLIFT knob gauge")
'         // Assign the local hCtrl to the FF3 global handle         
          HWND_MAIN_KNOBBIG = hCtrl         
       End If

'      // Create WinLIFT KnobGauge, based on template.       
       If SplitTemplate(hWndForm, IDC_MAIN_KNOBRIGHT, x, y, w, h, sLabel, sImagePath, dwStyle) Then
          hCtrl = skKnobGauge(hWndForm, (sImagePath), x, y, 0, 0, IDC_MAIN_KNOBRIGHT, 0, 0, 0, 0)
'         // Anchor the button to bottom center.           
          Call skSetAnchorCtrl(hCtrl, %ANCHOR_CENTER_HORZ_BOTTOM)
          Call skCreateToolTip(hCtrl, "WinLIFT knob gauge")
'         // Assign the local hCtrl to the FF3 global handle         
          HWND_MAIN_KNOBRIGHT = hCtrl         
       End If
It did look strange to see assignments to the FF HWND variables (for a second or two). :)

There are other places that could be cleaned up though. For instance:
Sub GDImageSetZoomRange(ByVal bmW As Long, ByVal bmH As Long, xSize As Long, ySize As Long)
    Local lpr As Rect, xPos, yPos, hZoomSlider, hGDImageCtrl As Long

    hGDImageCtrl = GetDlgItem(gFLY_hDlgCurrent, IDC_MAIN_GRAPHICCONTROL)
    hZoomSlider = GetDlgItem(gFLY_hDlgCurrent, IDC_MAIN_SLIDEZOOM)

    Call GetClientRect(hGDImageCtrl, lpr)
    Call ZI_Iconise(bmW, bmH, lpr.nRight, lpr.nBottom, xPos, yPos, xSize, ySize)

    Call SendMessage(hZoomSlider, %TBM_SETRANGE, 1, Mak(Long, CLng((xSize / bmW) * 128), 1500))
End Sub

Could be:
Sub GDImageSetZoomRange(ByVal bmW As Long, ByVal bmH As Long, xSize As Long, ySize As Long)
    Local lpr As Rect, xPos, yPos As Long

    Call GetClientRect(HWND_MAIN_GRAPHICCONTROL, lpr)
    Call ZI_Iconise(bmW, bmH, lpr.nRight, lpr.nBottom, xPos, yPos, xSize, ySize)

    Call SendMessage(HWND_MAIN_SLIDEZOOM, %TBM_SETRANGE, 1, Mak(Long, CLng((xSize / bmW) * 128), 1500))
End Sub


Not that those changes would measurably improve execution speed. FF already has them, I tend to take advantage of that fact.

Very nice work Patrice!

David 


Patrice Terrier

David,

Yes, you understood very well, and you are right, i should have cleaned GDImageSetZoomRange as you stated in your post, good catch!

Will do it  ;)

Patrice Terrier

#5
I have followed David's advice, and converted everything to use FF's HWND_ and IDC_  globals.

I have posted a new ZIP file, that is attached to the first post of this thread, it also embeds the latest WinLIFT version 4.84, that allows you to change the "font and color" of a StaticLabel or PushButton on the fly. The declaration for this API is:
  %FontStyleRegular = 0
  %FontStyleBold = 1
  %FontStyleItalic = 2
  %FontStyleBoldItalic = 3
  %FontStyleUnderline = 4
  %FontStyleStrikeout = 8
'// 4.84 This API is to be used only with STATIC and BUTTON controls exclusively!
  DECLARE SUB skSetLabelFont LIB "WinLIFT.dll" ALIAS "skSetLabelFont" ( _
  BYVAL hCtrl AS LONG, _             ' The control handle.
  zFontName AS ASCIIZ, _             ' The GDI+ compatible font name to use.
  BYVAL nFontSize AS WORD, _         ' The font size in pixel.
  BYVAL ARGBcolor AS LONG, _         ' The ARGB color (use the skARGB() function above, or NULL to apply the skin theme color).
  BYVAL nFontStyle AS WORD _         ' One of the FontStyle constant above.       
  )

It must be used after the SkinEngine has been fired.

TIP
If you have VISTA or SEVEN, edit Onyx.sks and change this parameter near the end of file.
"DWM_AERO,             0"              ' 4.70, 0 = OFF, 1 = ON (Use VISTA-SEVEN Aero composited mode)

to this

"DWM_AERO,             1"              ' 4.70, 0 = OFF, 1 = ON (Use VISTA-SEVEN Aero composited mode)


...