Author Topic: [SDK] 13 - VISTA & XP Skin Engine (full XP aero emulation)  (Read 3766 times)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1982
    • zapsolution
[SDK] 13 - VISTA & XP Skin Engine (full XP aero emulation)
« on: February 09, 2020, 04:58:56 pm »
Get same Blur and Crystal appearance on both VISTA and XP

This screen shot shows you both "Moonraker" and "PhotoComposer" (GDImage) using the new Skin Engine!
As you can see you can create stunning interface with it...



This is the result of many days of brain storming trying to understand DWM, and to work around all the bugs VISTA causes to existing advanced graphic application.

In short, it doesn't respect own Microsoft rules to perform compositing!
and there are many situations where DWM would cause indeed much flickering than on XP, if you are not aware of it.

This is the reason why this new version uses its own way to perform compositing on VISTA.

Note: if you are using Dual monitor with VISTA, there is a problem if you move the skinned window to the second monitor (see the next post for the solution).

Now about this new VISTA version, it allows you to do easily things that are very hard to perform even with VS2005 and WPF.

The new DWM code section:
Code: [Select]
%S_OK = 0
%WM_DWMCOMPOSITIONCHANGED     = &H031E
%DWM_BB_ENABLE                = &H00000001
%DWM_BB_BLURREGION            = &H00000002
%DWM_BB_TRANSITIONONMAXIMIZED = &H00000004
%DWM_EC_ENABLECOMPOSITION     = 1
%DWM_EC_DISABLECOMPOSITION    = 0

TYPE DWM_BLURBEHIND
    dwFlags  AS DWORD
    fEnable  AS LONG
    hRgnBlur AS DWORD
    fTransitionOnMaximized AS LONG
END TYPE

TYPE MARGINS
    cxLeftWidth    AS LONG
    cxRightWidth   AS LONG
    cyTopHeight    AS LONG
    cyBottomHeight AS LONG
END TYPE

FUNCTION LoadDWM () AS LONG
    STATIC hLib AS DWORD, nChecked AS LONG
    IF nChecked = 0 THEN nChecked = -1: hLib = LoadLibrary ("dwmapi.dll")
    FUNCTION = hLib
END FUNCTION

DECLARE FUNCTION DwmEnableComposition (BYVAL uCompositionAction AS LONG) AS LONG
SUB zDwmEnableComposition (BYVAL uCompositionAction AS LONG)
    LOCAL nRet AS LONG, hLib AS DWORD
    STATIC hProc AS DWORD
    hLib = LoadDWM()
    IF hLib THEN
       IF hProc = 0 THEN hProc = GetProcAddress(hLib, "DwmEnableComposition")
       IF hProc THEN
          CALL DWORD hProc USING DwmEnableComposition(uCompositionAction) TO nRet
       END IF
    END IF
END SUB

DECLARE FUNCTION DwmIsCompositionEnabled () AS LONG
FUNCTION zDwmIsCompositionEnabled () AS LONG
    LOCAL nRet AS LONG, hLib AS DWORD
    STATIC hProc AS DWORD
    hLib = LoadDWM()
    IF hLib THEN
       IF hProc = 0 THEN hProc = GetProcAddress(hLib, "DwmIsCompositionEnabled")
       IF hProc THEN
          CALL DWORD hProc USING DwmIsCompositionEnabled() TO nRet
          IF nRet THEN FUNCTION = -1
       END IF
    END IF
END FUNCTION

DECLARE FUNCTION DwmEnableBlurBehindWindow (BYVAL LONG, pBlurBehind AS DWM_BLURBEHIND) AS LONG
SUB zSetBlurBehindMode(BYVAl hWnd AS LONG, BYVAL nBOOL AS LONG, BYVAL hRgnBlur AS LONG)
    LOCAL bb AS DWM_BLURBEHIND
    LOCAL hLib AS DWORD, nRet AS LONG
    STATIC hProc AS DWORD
    hLib = LoadDWM ()
    IF hLIB THEN
       IF zDwmIsCompositionEnabled() THEN
          IF hProc = 0 THEN hProc = GetProcAddress(hLib, "DwmEnableBlurBehindWindow")
          IF hProc THEN
             nRet = %S_OK
'            // Create and populate the BlurBehind structure.
'            // Set Blur Behind and Blur Region.
             bb.fEnable = nBOOL
             bb.dwFlags = %DWM_BB_ENABLE OR %DWM_BB_BLURREGION
             bb.hRgnBlur = hRgnBlur
'            // Set Blur Behind mode.
             CALL DWORD hProc USING DwmEnableBlurBehindWindow(hWnd, bb) TO nRet
          END IF
       END IF
    END IF
END SUB

SUB zSetCrystalBehindMode(BYVAl hWnd AS LONG, BYVAL nBOOL AS LONG)
    LOCAL bb AS DWM_BLURBEHIND
    LOCAL hLib AS DWORD, nRet, hRgnBlur AS LONG
    STATIC hProc AS DWORD
    hLib = LoadDWM ()
    IF hLIB THEN
       IF zDwmIsCompositionEnabled() THEN
          IF hProc = 0 THEN hProc = GetProcAddress(hLib, "DwmEnableBlurBehindWindow")
          IF hProc THEN
             nRet = %S_OK
'            // Create and populate the BlurBehind structure.
'            // Set Blur Behind and Blur Region.
             bb.dwFlags = %DWM_BB_ENABLE OR %DWM_BB_BLURREGION
             bb.fEnable = nBOOL
             bb.fTransitionOnMaximized = 0
'            // Fool VISTA with a fake region
             hRgnBlur = CreateRectRgn(-1, -1, 0, 0)
             bb.hRgnBlur = hRgnBlur
'            // Set Blur Behind mode.
             CALL DWORD hProc USING DwmEnableBlurBehindWindow(hWnd, bb) TO nRet
          END IF
       END IF
    END IF
END SUB

The complete project is in the attached zskin13.zip

And now that all the hard stuff is done, we will be able to play the fun... using GDImage.  8)

« Last Edit: February 09, 2020, 06:11:50 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1982
    • zapsolution
Re: [SDK] 13 - VISTA & XP Skin Engine (full XP aero emulation)
« Reply #1 on: February 09, 2020, 06:12:36 pm »
Quote
Note: if you are using Dual monitor with VISTA, there is a problem if you move the skinned window to the second monitor.

To fix the Dual monitor mouse location problem, replace in the source code all reference to
LOWRD(lParam), HIWRD(lParam)
with
LO(INTEGER, lParam), HI(INTEGER, lParam)
to get a signed value instead of the unsigned WORD.

'// Monitor Windows DEF PROC to take over HITTEST detection
FUNCTION zDefWindowProc(BYVAL hWnd AS LONG, BYVAL Msg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
    LOCAL nRet, HITTEST AS LONG
    LOCAL rc AS RECT

    nRet = DefWindowProc(hWnd, Msg, wParam, lParam)

    IF Msg = %WM_NCHITTEST THEN
       LOCAL p AS POINTAPI
       LOCAL CaptionHeight AS LONG
       CALL zGetImageSize(zGetProperty(hWnd, %FORM_TopMid), 0, CaptionHeight)
       p.X = LO(INTEGER, lParam): p.Y = HI(INTEGER, lParam)
       CALL ScreenToClient(hWnd, p)
       IF IsZoomed(hWnd) = 0 THEN
          IF nRet = %HTCLIENT THEN
             HITTEST = %HTCAPTION
             IF SK_DRAG_BACKGROUND() = 0 THEN
                IF p.Y > CaptionHeight AND CaptionHeight > 0 THEN
                   HITTEST = %HTNOWHERE
                   IF hWnd <> GetForegroundWindow THEN CALL SetFocus(hWnd)
                END IF
             END IF
Patrice
(Always working with the latest Windows version available...)