Recent Posts

Pages: [1] 2 3 ... 10
1
The concept / WinLIFT 64-bit 8.00 (is attached to this post)
« Last post by Patrice Terrier on August 03, 2026, 05:22:16 pm »
WinLIFT 8.00 - Major update

WinLIFT 8.00 is a major evolution of my native Win32 skinning framework.

BBRTV (BassBox Radio/TV) was used as the development laboratory for this release and is provided as a working example showing how to use the new WinLIFT 8.00 API in a real-world application.

What's new in WinLIFT 8.00

  • New Grid control
    A native WinLIFT Grid control with headers, multiple columns, text, images, edit/combo/button support, hidden columns, selection management, scrolling and resizable columns.

  • New image compositor
    WinLIFT can compose the complete application window into an image, including the non-client area, child controls, scrollbars and GDImage content.

  • Tighter GDImage integration
    WinLIFT and GDImage now cooperate more closely, especially for WM_PRINT rendering and image composition.

  • DWM popup overlay support
    The compositor can integrate GDImage DWM-composited popup overlays used by applications such as MBox64 and ObjReader64.

  • Integrated snapshot
    CTRL+SCREENSHOT can be used at any time to create a snapshot of the fully composed application window. The picture is saved beside the executable.

  • New window animation engine
    skShowWindow() can display a window using one of the new WinLIFT effects:

        SK_EFFECT_FALLZOOM
        SK_EFFECT_TRANSLUCENTSPIRAL
        SK_EFFECT_CURL_FROM_BOTTOMLEFT
        SK_EFFECT_CURL_FROM_BOTTOMRIGHT
        SK_EFFECT_CURL_FROM_TOPRIGHT
        SK_EFFECT_CURL_FROM_TOPLEFT
        SK_EFFECT_LIQUIDFILL
        SK_EFFECT_BLURFOCUS

    The Curl effects are directional and the new effects are generated entirely at runtime from the composed window image.

  • WebView2 integration
    WinLIFT provides a compact native API for embedding WebView2 into a skinned application.

  • Embedded DLL memory loader
    A DLL stored inside the WinLIFT RCDATA resources can be loaded directly from memory, without extracting it to disk.

    This is used to keep the WebView2/WRL implementation isolated from the main WinLIFT runtime while preserving single-DLL deployment.

  • DPI scaling helpers
    WinLIFT itself does not claim Windows DPI awareness.

    It provides built-in DPI scaling helpers instead. The host Windows DPI is used by default and the .sks USE_DPI property can provide an explicit scaling value when required.

    The image compositor is designed to remain compatible with the DPI environment of the host computer.

  • zVector
    Internal STL vector usage has been replaced by the lightweight zVector implementation.

  • Windows 10/11 improvements
    Several rendering and compatibility issues have been addressed, including TreeView focus, SYSHEADER rendering, scrollbar overlap and control redraw behavior.

  • Smaller runtime
    Despite the new Grid, compositor, animation engine, WebView2 support and memory loader, considerable work has been done to reduce the WinLIFT64.dll footprint and external runtime dependencies.
    The overall binary size is only 223 KB.
.
 
BBRTV - WinLIFT 8.00 example

BBRTV is not the subject of this release; it is the application I used to develop, test and demonstrate the new WinLIFT 8.00 functionality.

Its source code provides practical examples of the new Grid API, WebView2 integration, compositor, snapshot facility and window effects.
(A different effect is selected at each startup in loop mode).

The current C/C++ BBRTV executable is only: 67 KB

WinLIFT 8.00 remains a native 64-bit Unicode Win32 SDK framework, without MFC or .NET, designed for applications where full control of the Windows interface and a small native footprint are important.
2
64-bit SDK programming / Re: Load DLL from memory (using RCDATA)
« Last post by Patrice Terrier on August 03, 2026, 08:18:41 am »
Here is the 64-bit version, based on PB's code.
This one is used by WinLIFT 8.00, to load my WV2B.dll directly in memory from RCDATA without disk access.
It allows me to provide only one single WinLIFT64.dll, rather than two (easier for code distribution).

Code: [Select]
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                          (LoadDLLfromMemory)                             |
//|                                                                          |
//|                         Author Patrice TERRIER                           |
//|                         copyright(c) 2007-2026                           |
//|                           www.zapsolution.com                            |
//|                        pterrier@zapsolution.com                          |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                  Project started on : 00-06-2007 (MM-DD-YYYY)            |
//|                        Last revised : 08-02-2026 (MM-DD-YYYY)            |
//+--------------------------------------------------------------------------+

#pragma once

static HMODULE Load_DLL(IN WCHAR* lpName) {
    typedef BOOL (WINAPI *DLLENTRYPROC)(HINSTANCE, DWORD, LPVOID);

    HMODULE hInstance = 0;
    HMODULE hModule = 0;
    HRSRC hResource = 0;
    HGLOBAL hGlobal = 0;
    BYTE* pRawDll = 0;
    BYTE* pImage = 0;
    DWORD RawDllSize = 0;
    DWORD HeadersSize = 0;
    DWORD OldProtect = 0;
    DWORD K = 0;
    LONG FunctionTableAdded = 0;

    IMAGE_DOS_HEADER* pSrcDos = 0;
    IMAGE_NT_HEADERS64* pSrcNt = 0;
    IMAGE_SECTION_HEADER* pSrcSection = 0;
    IMAGE_DOS_HEADER* pDstDos = 0;
    IMAGE_NT_HEADERS64* pDstNt = 0;
    IMAGE_SECTION_HEADER* pDstSection = 0;
    RUNTIME_FUNCTION* pFunctionTable = 0;

    if (!lpName) return 0;

    if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
                           (LPCWSTR) (LONG_PTR) &Load_DLL, &hInstance)) return 0;

    hResource = FindResource(hInstance, lpName, RT_RCDATA);
    if (!hResource) return 0;

    RawDllSize = SizeofResource(hInstance, hResource);
    if (!RawDllSize) return 0;

    hGlobal = LoadResource(hInstance, hResource);
    if (!hGlobal) return 0;

    pRawDll = (BYTE*) LockResource(hGlobal);
    if (!pRawDll) return 0;

    if (RawDllSize < sizeof(IMAGE_DOS_HEADER)) return 0;

    pSrcDos = (IMAGE_DOS_HEADER*) pRawDll;
    if (pSrcDos->e_magic != IMAGE_DOS_SIGNATURE) return 0;
    if (pSrcDos->e_lfanew < 0) return 0;
    if ((QWORD) pSrcDos->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > RawDllSize) return 0;

    pSrcNt = (IMAGE_NT_HEADERS64*) (pRawDll + pSrcDos->e_lfanew);
    if (pSrcNt->Signature != IMAGE_NT_SIGNATURE) return 0;
    if (pSrcNt->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) return 0;
    if (pSrcNt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return 0;
    if (pSrcNt->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64)) return 0;
    if (!pSrcNt->FileHeader.NumberOfSections) return 0;
    if (!pSrcNt->OptionalHeader.SizeOfImage) return 0;

    pSrcSection = IMAGE_FIRST_SECTION(pSrcNt);
    HeadersSize = (DWORD) ((BYTE*) (pSrcSection + pSrcNt->FileHeader.NumberOfSections) - pRawDll);
    if (HeadersSize > RawDllSize) return 0;
    if (pSrcNt->OptionalHeader.SizeOfHeaders < HeadersSize) return 0;
    if (pSrcNt->OptionalHeader.SizeOfHeaders > RawDllSize) return 0;

    pImage = (BYTE*) VirtualAlloc((LPVOID) (LONG_PTR) pSrcNt->OptionalHeader.ImageBase,
                                  pSrcNt->OptionalHeader.SizeOfImage,
                                  MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    if (!pImage) {
        pImage = (BYTE*) VirtualAlloc(0, pSrcNt->OptionalHeader.SizeOfImage,
                                      MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    }
    if (!pImage) return 0;

    memcpy(pImage, pRawDll, pSrcNt->OptionalHeader.SizeOfHeaders);

    pDstDos = (IMAGE_DOS_HEADER*) pImage;
    pDstNt = (IMAGE_NT_HEADERS64*) (pImage + pDstDos->e_lfanew);
    pDstSection = IMAGE_FIRST_SECTION(pDstNt);

    for (K = 0; K < pDstNt->FileHeader.NumberOfSections; K++) {
        DWORD RawSize = pDstSection[K].SizeOfRawData;
        DWORD RawOffset = pDstSection[K].PointerToRawData;
        DWORD VirtualAddress = pDstSection[K].VirtualAddress;
        DWORD VirtualSize = pDstSection[K].Misc.VirtualSize;

        if ((QWORD) VirtualAddress + max(RawSize, VirtualSize) > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;

        if (RawSize) {
            if ((QWORD) RawOffset + RawSize > RawDllSize) goto BailOut;
            memcpy(pImage + VirtualAddress, pRawDll + RawOffset, RawSize);
        }

        if (VirtualSize > RawSize) {
            ClearMemory(pImage + VirtualAddress + RawSize, VirtualSize - RawSize);
        }
    }

    {
        QWORD Delta = (QWORD) pImage - pDstNt->OptionalHeader.ImageBase;
        IMAGE_DATA_DIRECTORY RelocDir = pDstNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

        if (Delta) {
            if (!RelocDir.VirtualAddress || !RelocDir.Size) goto BailOut;
            if ((QWORD) RelocDir.VirtualAddress + RelocDir.Size > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;

            IMAGE_BASE_RELOCATION* pReloc = (IMAGE_BASE_RELOCATION*) (pImage + RelocDir.VirtualAddress);
            BYTE* pRelocEnd = (BYTE*) pReloc + RelocDir.Size;

            while ((BYTE*) pReloc < pRelocEnd && pReloc->SizeOfBlock) {
                if (pReloc->SizeOfBlock < sizeof(IMAGE_BASE_RELOCATION)) goto BailOut;
                if ((BYTE*) pReloc + pReloc->SizeOfBlock > pRelocEnd) goto BailOut;

                WORD* pTypeOffset = (WORD*) ((BYTE*) pReloc + sizeof(IMAGE_BASE_RELOCATION));
                DWORD Count = (pReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

                for (DWORD N = 0; N < Count; N++) {
                    WORD Type = pTypeOffset[N] >> 12;
                    WORD Offset = pTypeOffset[N] & 0x0FFF;
                    QWORD PatchRva = (QWORD) pReloc->VirtualAddress + Offset;

                    if (Type == IMAGE_REL_BASED_DIR64) {
                        if (PatchRva + sizeof(QWORD) > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;
                        *(QWORD*) (pImage + PatchRva) += Delta;
                    } else if (Type != IMAGE_REL_BASED_ABSOLUTE) {
                        goto BailOut;
                    }
                }

                pReloc = (IMAGE_BASE_RELOCATION*) ((BYTE*) pReloc + pReloc->SizeOfBlock);
            }
        }
    }

    {
        IMAGE_DATA_DIRECTORY ImportDir = pDstNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

        if (ImportDir.VirtualAddress) {
            if ((QWORD) ImportDir.VirtualAddress + ImportDir.Size > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;

            IMAGE_IMPORT_DESCRIPTOR* pImport = (IMAGE_IMPORT_DESCRIPTOR*) (pImage + ImportDir.VirtualAddress);
            BYTE* pImportEnd = pImage + ImportDir.VirtualAddress + ImportDir.Size;

            while ((BYTE*) (pImport + 1) <= pImportEnd && pImport->Name) {
                if (pImport->Name >= pDstNt->OptionalHeader.SizeOfImage) goto BailOut;
                if (pImport->FirstThunk >= pDstNt->OptionalHeader.SizeOfImage) goto BailOut;

                HMODULE hDll = LoadLibraryA((char*) (pImage + pImport->Name));
                if (!hDll) goto BailOut;

                IMAGE_THUNK_DATA64* pNameThunk = (IMAGE_THUNK_DATA64*) (pImage +
                    (pImport->OriginalFirstThunk ? pImport->OriginalFirstThunk : pImport->FirstThunk));
                IMAGE_THUNK_DATA64* pAddrThunk = (IMAGE_THUNK_DATA64*) (pImage + pImport->FirstThunk);

                while (pNameThunk->u1.AddressOfData) {
                    FARPROC hProc = 0;

                    if ((BYTE*) (pNameThunk + 1) > pImage + pDstNt->OptionalHeader.SizeOfImage) goto BailOut;
                    if ((BYTE*) (pAddrThunk + 1) > pImage + pDstNt->OptionalHeader.SizeOfImage) goto BailOut;

                    if (IMAGE_SNAP_BY_ORDINAL64(pNameThunk->u1.Ordinal)) {
                        hProc = GetProcAddress(hDll, (char*) (LONG_PTR) IMAGE_ORDINAL64(pNameThunk->u1.Ordinal));
                    } else {
                        DWORD NameRva = (DWORD) pNameThunk->u1.AddressOfData;
                        if ((QWORD) NameRva + sizeof(IMAGE_IMPORT_BY_NAME) > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;
                        IMAGE_IMPORT_BY_NAME* pImportName = (IMAGE_IMPORT_BY_NAME*) (pImage + NameRva);
                        hProc = GetProcAddress(hDll, (char*) pImportName->Name);
                    }

                    if (!hProc) goto BailOut;
                    pAddrThunk->u1.Function = (QWORD) hProc;
                    pNameThunk++;
                    pAddrThunk++;
                }

                pImport++;
            }
        }
    }

    {
        IMAGE_DATA_DIRECTORY ExceptionDir = pDstNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];

        if (ExceptionDir.VirtualAddress && ExceptionDir.Size) {
            if ((QWORD) ExceptionDir.VirtualAddress + ExceptionDir.Size > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;
            if (ExceptionDir.Size % sizeof(RUNTIME_FUNCTION)) goto BailOut;

            pFunctionTable = (RUNTIME_FUNCTION*) (pImage + ExceptionDir.VirtualAddress);
            DWORD EntryCount = ExceptionDir.Size / sizeof(RUNTIME_FUNCTION);

            if (EntryCount) {
                if (!RtlAddFunctionTable(pFunctionTable, EntryCount, (DWORD64) pImage)) goto BailOut;
                FunctionTableAdded = -1;
            }
        }
    }

    {
        IMAGE_DATA_DIRECTORY TlsDir = pDstNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];

        if (TlsDir.VirtualAddress && TlsDir.Size) {
            if ((QWORD) TlsDir.VirtualAddress + sizeof(IMAGE_TLS_DIRECTORY64) > pDstNt->OptionalHeader.SizeOfImage) goto BailOut;

            IMAGE_TLS_DIRECTORY64* pTls = (IMAGE_TLS_DIRECTORY64*) (pImage + TlsDir.VirtualAddress);
            PIMAGE_TLS_CALLBACK* pCallback = (PIMAGE_TLS_CALLBACK*) (LONG_PTR) pTls->AddressOfCallBacks;

            if (pCallback) {
                while (*pCallback) {
                    (*pCallback)((LPVOID) pImage, DLL_PROCESS_ATTACH, 0);
                    pCallback++;
                }
            }
        }
    }

    {
        static DWORD ProtectTable[8] = {
            PAGE_NOACCESS,
            PAGE_EXECUTE,
            PAGE_READONLY,
            PAGE_EXECUTE_READ,
            PAGE_READWRITE,
            PAGE_EXECUTE_READWRITE,
            PAGE_READWRITE,
            PAGE_EXECUTE_READWRITE
        };

        if (!VirtualProtect(pImage, pDstNt->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &OldProtect)) goto BailOut;

        for (K = 0; K < pDstNt->FileHeader.NumberOfSections; K++) {
            DWORD Index = 0;
            DWORD SectionSize = max(pDstSection[K].Misc.VirtualSize, pDstSection[K].SizeOfRawData);

            if (pDstSection[K].Characteristics & IMAGE_SCN_MEM_EXECUTE) Index |= 1;
            if (pDstSection[K].Characteristics & IMAGE_SCN_MEM_READ) Index |= 2;
            if (pDstSection[K].Characteristics & IMAGE_SCN_MEM_WRITE) Index |= 4;

            if (SectionSize) {
                if (!VirtualProtect(pImage + pDstSection[K].VirtualAddress, SectionSize,
                                    ProtectTable[Index], &OldProtect)) goto BailOut;
            }
        }
    }

    FlushInstructionCache(GetCurrentProcess(), pImage, pDstNt->OptionalHeader.SizeOfImage);

    if (pDstNt->OptionalHeader.AddressOfEntryPoint) {
        DLLENTRYPROC pEntryPoint = (DLLENTRYPROC) (pImage + pDstNt->OptionalHeader.AddressOfEntryPoint);
        if (!pEntryPoint((HINSTANCE) pImage, DLL_PROCESS_ATTACH, 0)) goto BailOut;
    }

    hModule = (HMODULE) pImage;
    return hModule;

BailOut:
    if (FunctionTableAdded && pFunctionTable) RtlDeleteFunctionTable(pFunctionTable);
    if (pImage) VirtualFree(pImage, 0, MEM_RELEASE);
    return 0;
}

static FARPROC GetProcAddressDirectly(IN HMODULE hModule, IN char* lpProcName) {
    FARPROC hProc = 0;
    BYTE* pImage = (BYTE*) hModule;

    if (pImage && lpProcName) {
        IMAGE_DOS_HEADER* pDos = (IMAGE_DOS_HEADER*) pImage;

        if (pDos->e_magic == IMAGE_DOS_SIGNATURE) {
            IMAGE_NT_HEADERS64* pNt = (IMAGE_NT_HEADERS64*) (pImage + pDos->e_lfanew);

            if (pNt->Signature == IMAGE_NT_SIGNATURE) {
                IMAGE_DATA_DIRECTORY ExportDir = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

                if (ExportDir.VirtualAddress && ExportDir.Size) {
                    IMAGE_EXPORT_DIRECTORY* pExport = (IMAGE_EXPORT_DIRECTORY*) (pImage + ExportDir.VirtualAddress);
                    DWORD* pFunctions = (DWORD*) (pImage + pExport->AddressOfFunctions);
                    DWORD* pNames = (DWORD*) (pImage + pExport->AddressOfNames);
                    WORD* pOrdinals = (WORD*) (pImage + pExport->AddressOfNameOrdinals);

                    for (DWORD K = 0; K < pExport->NumberOfNames; K++) {
                        char* pName = (char*) (pImage + pNames[K]);

                        if (lstrcmpA(pName, lpProcName) == 0) {
                            WORD Ordinal = pOrdinals[K];

                            if (Ordinal < pExport->NumberOfFunctions) {
                                DWORD FunctionRva = pFunctions[Ordinal];

                                if (FunctionRva < ExportDir.VirtualAddress ||
                                    FunctionRva >= ExportDir.VirtualAddress + ExportDir.Size) {
                                    hProc = (FARPROC) (pImage + FunctionRva);
                                }
                            }

                            break;
                        }
                    }
                }
            }
        }
    }

    return hProc;
}
3
Eye Candies / BassBox Radio & TV
« Last post by Patrice Terrier on June 14, 2026, 07:45:12 am »
BBR - New TV Feature (Release Candidate)

I have just completed a new TV feature for BBR (BassBox Radio).



Instead of maintaining a large list of individual TV channels, BBR now provides a visual TV catalog using thumbnails. Selecting a thumbnail opens the corresponding TV portal directly inside the integrated WebView2 browser.

Current portals include France and USA, and adding new entries is very simple.

The goal is to build a collection of useful, legal and freely accessible TV portals from different countries.

I am currently looking for suggestions, especially for:

  • Spain
  • Germany
  • Italy
  • Portugal
  • Canada
  • Belgium
  • Switzerland
  • Latin America

If you know a good TV portal that offers live television channels, please post the URL.

The TV catalog uses PNG thumbnails, so if you can suggest a suitable icon, even better.

Thank you for your help and testing.

The full VS2022 project is attached to this post.

4
Eye Candies / BassBox Radio C/C++ version 4.01
« Last post by Patrice Terrier on June 07, 2026, 01:52:12 pm »
BBR Update

Today I finished a major cleanup of the station management system.

Previously, stations automatically disabled by the validation thread and stations manually removed by the user were mixed together in the same file.

This has now been split into:

Code: [Select]
US_stations.lst   = master station list
US_favorite.lst   = favorites
US_broken.lst     = automatically detected bad URLs
US_removed.lst    = stations permanently removed by the user

This means:

  • A dead station is no longer confused with a user deletion.
  • User choices are preserved.
  • Broken stations can be rechecked independently.
  • Future restore and maintenance tools become possible.

I also added a small station statistics dialog showing:

Code: [Select]
Stations
Active
Broken
Removed
Favorites

The stream checker has also been improved and now distinguishes temporary network failures from more serious URL errors.

As usual, the attachment linked to the first post of this trhead has been updated.

A small change internally, but an important step toward making BBR more reliable and easier to maintain.
5
Eye Candies / BassBox Radio C/C++ version 4.00 (updated)
« Last post by Patrice Terrier on May 24, 2026, 01:50:10 pm »
The project code has been updated, see new attachment linked to the first post.

05-22-2026
Removing radio didn't updated the counter.
The Oscillo popup, is now a real child of the Radio TAB.

05-24-2026
Better radio icon management.
Thread detection revised when using "Update".
The tab "Radio" is now using auto column size adjustment when resizing the window.
Marquee alignment was improperly using anchor mode.
6
Eye Candies / BassBox Radio C/C++ version 4.00
« Last post by Patrice Terrier on May 21, 2026, 08:06:15 am »
BassBox Radio 4.00

Version 4.00 is a complete rewrite of BassBox Radio.

The original version was written with WinDev in 2014.
This new version has been fully rewritten in native C/C++ with a major size reduction, producing a tiny 62 KB executable.



Despite its very small size, BBR 4.00 includes:

  • Integrated Internet radio station browser
  • Favorites management
  • Country filtering
  • Embedded WebView2 browser
  • OpenGL visual plugin support
  • Realtime oscilloscope
  • GDImage/WinLIFT composited interface
  • Very low resource usage
  • Native Win32 responsiveness

The oscilloscope and rendering system are fully hardware accelerated and continue updating smoothly even while moving or resizing the window.

This version is based on my own native libraries:
  • WinLIFT
  • GDImage
  • BassBox audio engine

Everything has been designed to remain lightweight, reactive and visually clean without relying on heavy frameworks.

The full VS2022 project is attached to this post.

If you download it and test it, please give me your feedback.
I would be interested to know if you find any oddities, bugs, or if you have suggestions for improvement.


7
Eye Candies / Re: BassBox Radio (more than 33000 internet radio)
« Last post by Patrice Terrier on May 14, 2026, 09:31:34 pm »
Working on a brand new version, written in pure C/C++, to create tiny standalone binary, with great scope of features.
And compatible with the new GLSL plugins.

Stay tuned...
8
Runtime activation of Common Controls v6 (Manifest-free alternative)

For years, the standard way to enable modern Windows visual styles (ComCtl32 v6) has been through a manifest, either embedded or via:

Code: [Select]
// Include the v6 common controls in the manifest
#pragma comment(linker,""/manifestdependency:type='win32'
name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"")

While this works, it introduces a dependency on the linker and can sometimes lead to inconsistent behavior depending on build settings, resources, or memory conditions.


Alternative: Runtime activation (no manifest required)

It is possible to activate visual styles dynamically at runtime using an activation context (ACTCTX).
This method loads the ComCtl32 v6 resources directly from shell32.dll.

Code: [Select]
static HANDLE    g_hActCtx = INVALID_HANDLE_VALUE;
static ULONG_PTR g_ulActCookie = 0;
static BOOL      g_bActCtxActive = FALSE;

static BOOL EnableVisualStylesRuntime(VOID) {
    WCHAR dir[MAX_PATH];
    DWORD cch = GetSystemDirectory(dir, MAX_PATH);
    if (!cch || cch >= MAX_PATH) return FALSE;

    ACTCTX actCtx; ClearMemory(&actCtx, sizeof(actCtx));
    actCtx.cbSize = sizeof(actCtx);
    actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
    actCtx.lpSource = TEXT("shell32.dll");
    actCtx.lpAssemblyDirectory = dir;
    actCtx.lpResourceName = MAKEINTRESOURCE(124);

    g_hActCtx = CreateActCtx(&actCtx);
    if (g_hActCtx == INVALID_HANDLE_VALUE) return FALSE;

    if (!ActivateActCtx(g_hActCtx, &g_ulActCookie)) {
        ReleaseActCtx(g_hActCtx);
        g_hActCtx = INVALID_HANDLE_VALUE;
        return FALSE;
    }

    g_bActCtxActive = TRUE;
    return TRUE;
}

static VOID DisableVisualStylesRuntime(VOID) {
    if (g_bActCtxActive) {
        DeactivateActCtx(0, g_ulActCookie);
        g_bActCtxActive = FALSE;
        g_ulActCookie = 0;
    }

    if (g_hActCtx != INVALID_HANDLE_VALUE) {
        ReleaseActCtx(g_hActCtx);
        g_hActCtx = INVALID_HANDLE_VALUE;
    }
}


Important notes

* Must be called very early (ideally at the start of wWinMain or inside your core init like skInitEngine).
* Affects all subsequently created controls (ComboBox, ListView, TreeView, etc.).
* Ensures consistent theming without relying on external manifests.
* Particularly useful in:
   - CRT-free builds
   - DLL-based UI engines (e.g. WinLIFT)
   - Custom control frameworks
* Avoid calling it after controls are already created.


Why this matters

In practice, inconsistent behavior of controls (especially owner-drawn or themed ones) often comes from:

* Missing or partial v6 activation
* Timing issues (controls created before activation)
* Resource/memory edge cases

By forcing activation at runtime, behavior becomes deterministic and uniform.


Conclusion

This approach is a reliable replacement for manifest-based activation and gives full control over when and how visual styles are enabled.

In my case, integrating this directly into the initialization phase removed all inconsistencies without requiring any manifest handling.


Tip

If you already use a framework like WinLIFT, placing this call inside the engine initialization guarantees that all controls benefit from v6 styling automatically.
9
64-bit SDK programming / zBff.dll (C/C++ source code)
« Last post by Patrice Terrier on March 31, 2026, 10:08:19 am »
C/C++ Visual Studio 2022 source code for zBff.dll

Custom file dialog replacement built on GDImage and WinLIFT, providing full control over UI, rendering, and interaction.

Core features

  • Custom message loop
       
    • Fine-grained control over message flow
    • Idle-time processing (folder watch, process tracking)
    • Automatic Z-order restore after launched process termination

  • Full UI ownership (no common dialog)
       
    • Edit path + filter combo + view selector
    • TreeView (folder navigation)
    • ListView (details mode with sorting)
    • GDImage-based thumbnail view (custom rendered)

  • Dual view system
       
    • List mode (Explorer-like, sortable columns)
    • Thumbnail mode (GDImage objects, atlas + real previews)

  • Advanced thumbnail pipeline
       
    • Image formats via GDImage (including ORB/PNG-based content)
    • Embedded album art extraction (APIC / WMA tags)
    • Dynamic atlas fallback for non-previewable files

  • Custom drag & drop (no OLE)
       
    • WM_DROPFILES-based implementation
    • Multi-selection support via MULTI_SZ
    • Layered drag image with alpha blending
    • Real-time drop target detection (child window aware)
    • Dynamic cursor feedback over valid targets

  • Process integration
       
    • Launch files via ShellExecuteEx or custom ProcessCreate
    • Track external process lifetime (HANDLE-based)
    • Automatic dialog refocus when process exits

  • Context menu system
       
    • Open / Open with
    • Custom ObjReader integration (.orb)
    • Copy path / Delete / Properties
    • Registry-driven command resolution

  • Persistent state
       
    • Last folder, filter, view mode
    • Sort column + direction
    • Tree expansion state
    • Stored in lightweight binary config

  • Folder monitoring
       
    • Timestamp-based change detection
    • Auto-refresh with scroll/selection preservation

  • Save/Open behavior control
       
    • Unified engine with ZB_OPEN / ZB_SAVE
    • Automatic extension handling
    • Filter-aware filename correction

  • Skinning / theming
       
    • Full WinLIFT integration
    • V6 controls handled internally
    • GDImage rendering for custom visuals
Design goals

  • No dependency on standard Windows dialogs
  • No OLE drag & drop (lightweight alternative)
  • Minimal external dependencies
  • Full control over behavior, rendering, and interaction

Note: GoodMsg is the central point to add multiple language support.
10
64-bit SDK programming / zBrowser demo
« Last post by Patrice Terrier on March 27, 2026, 05:53:51 pm »
This is a small demo to expose the use of zBrowser with a skinned application.

The use of WinLIFT/GDImage is a mandatory to render the thumbnails (images, .orb thumbnail, audio tag cover art).
It is also important to use Common Controls (ComCtl32 v6), to use skinned combo drop down.

You can select one file, or several if you hold down the CTRL key while clicking on thumbnails.
Use right mouse click, to popup the contextual menu, to fire a specific actions.

Drag and drop, is available from a mouse wheel click, to drop a thumbnail onto MBox64 or ObjReader64 (audio, image, .orb, .obj, folder).
A complete folder audio, could be used with Mbox64.
That would work with any application using the classic DragAcceptFiles.
Pages: [1] 2 3 ... 10