• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

[SDK] 14 - VISTA & XP Skin Engine (full XP aero emulation)

Started by Patrice Terrier, September 20, 2007, 05:28:42 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

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:

%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)

Patrice Terrier
www.zapsolution.com
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#1
QuoteNote: 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 Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Petr Schreiber

Patrice,

thanks for the update on your perfect project!
Just one question - is there some simple way to get info determining that user is running on single or multi-display configuration ?


Thanks,
Petr
AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

Patrice Terrier

Petr,

See MSDN there:
http://msdn2.microsoft.com/en-us/library/ms534604.aspx

See also:

  • MonitorFromPoint
  • MonitorfromRect
  • MonitorFromWindow
  • GetMonitorInfo
  • MONITORINFOEX

Example:

#include <windows.h>
#include "multimon.h"   

#define MONITOR_CENTER   0x0001        // center rect to monitor
#define MONITOR_CLIP     0x0000        // clip rect to monitor
#define MONITOR_WORKAREA 0x0002        // use monitor work area
#define MONITOR_AREA     0x0000        // use monitor entire area

//
//  ClipOrCenterRectToMonitor
//
//  The most common problem apps have when running on a
//  multimonitor system is that they "clip" or "pin" windows
//  based on the SM_CXSCREEN and SM_CYSCREEN system metrics.
//  Because of app compatibility reasons these system metrics
//  return the size of the primary monitor.
//
//  This shows how you use the multi-monitor functions
//  to do the same thing.
//
void ClipOrCenterRectToMonitor(LPRECT prc, UINT flags)
{
    HMONITOR hMonitor;
    MONITORINFO mi;
    RECT        rc;
    int         w = prc->right  - prc->left;
    int         h = prc->bottom - prc->top;

    //
    // get the nearest monitor to the passed rect.
    //
    hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);

    //
    // get the work area or entire monitor rect.
    //
    mi.cbSize = sizeof(mi);
    GetMonitorInfo(hMonitor, &mi);

    if (flags & MONITOR_WORKAREA)
        rc = mi.rcWork;
    else
        rc = mi.rcMonitor;

    //
    // center or clip the passed rect to the monitor rect
    //
    if (flags & MONITOR_CENTER)
    {
        prc->left   = rc.left + (rc.right  - rc.left - w) / 2;
        prc->top    = rc.top  + (rc.bottom - rc.top  - h) / 2;
        prc->right  = prc->left + w;
        prc->bottom = prc->top  + h;
    }
    else
    {
        prc->left   = max(rc.left, min(rc.right-w,  prc->left));
        prc->top    = max(rc.top,  min(rc.bottom-h, prc->top));
        prc->right  = prc->left + w;
        prc->bottom = prc->top  + h;
    }
}

void ClipOrCenterWindowToMonitor(HWND hwnd, UINT flags)
{
    RECT rc;
    GetWindowRect(hwnd, &rc);
    ClipOrCenterRectToMonitor(&rc, flags);
    SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}


Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Petr Schreiber

AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

Patrice Terrier

Petr,

Multiple Monitor System Metrics:

The GetSystemMetrics function returns values for the primary monitor, except for SM_CXMAXTRACK and SM_CYMAXTRACK, which refer to the entire desktop. The following metrics are the same for all device drivers: SM_CXCURSOR, SM_CYCURSOR, SM_CXICON, SMCYICON. The following display capabilities are the same for all monitors: LOGPIXELSX, LOGPIXELSY, DESTOPHORZRES, DESKTOPVERTRES.

GetSystemMetrics also has constants that refer only to a Multiple Monitor system. SM_XVIRTUALSCREEN and SM_YVIRTUALSCREEN identify the upper-left corner of the virtual screen, SM_CXVIRTUALSCREEN and SM_CYVIRTUALSCREEN are the vertical and horizontal measurements of the virtual screen, SM_CMONITORS is the number of monitors attached to the desktop, and SM_SAMEDISPLAYFORMAT indicates whether all the monitors on the desktop have the same color format.

To get information about a single display monitor or all of the display monitors in a desktop, use EnumDisplayMonitors. The rectangle of the desktop window returned by GetWindowRect or GetClientRect is always equal to the rectangle of the primary monitor, for compatibility with existing applications. Thus, the result of

CALL GetWindowRect(GetDesktopWindow(), rc)

will be:

rc.nLeft = 0
rc.nTop = 0
rc.nRight = GetSystemMetrics (%SM_CXSCREEN)
rc.nBottom = GetSystemMetrics (%SM_CYSCREEN)

To change the work area of a monitor, call SystemParametersInfo with SPI_SETWORKAREA and pvParam pointing to a RECT structure that is on the desired monitor. If pvParam is NULL, the work area of the primary monitor is modified. Using SPI_GETWORKAREA always returns the work area of the primary monitor. To get the work area of a monitor other than the primary monitor, call GetMonitorInfo.

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

The zskin13.zip file has been updated to use HI / LO instead of HiWrd LoWrd and there is a small boost of the display speed on XP version (see change below)

If you don't want to download the whole ZIP file again, then remove the code shown below in red that is located at the end of zskin13.bas.

         CASE %WM_MOVING
              IF zDwmIsCompositionEnabled() = 0 THEN
                 IF SK_AEROEMULATE() AND zIsAeroLayered() THEN
                    DIM rw AS RECT PTR
                    rw = lparam
                    CALL zUpdateWindow(hWnd, 0)
                    CALL zMoveBackground(@rw.nLeft,@rw.nTop)
                    CALL zUpdateWindow(hWnd, 0)
                    FUNCTION = 1: EXIT FUNCTION
                 END IF
              END IF
'        //END AERO section ---------------------------------------------------------
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Petr Schreiber

Thanks Patrice,

again very useful information.


Thanks a lot,
Petr
AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

Patrice Terrier

The first post of this thread has been updated, to fix the ZIP file corruption caused by the "Server Collapse".

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com