alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (splashscreen_sys.c)

This example Java source code file (splashscreen_sys.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

ac_src_over, byte, false, getdevicecaps, getsystemmetrics, hdc, null, point, splashlock, splashredrawwindow, splashunlock, true, wm_splashreconfigure, wm_splashupdate

The splashscreen_sys.c Java example source code

/*
 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

// copy from awt.h
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif

// copy from awt.h
#ifndef _WIN32_IE
#define _WIN32_IE 0x0600
#endif

#include "splashscreen_impl.h"
#include <windowsx.h>
#include <windows.h>
#include <winuser.h>
#include "sizecalc.h"

#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED 0x80000
#endif

#ifndef ULW_ALPHA
#define ULW_ALPHA               0x00000002
#endif

#ifndef AC_SRC_OVER
#define AC_SRC_OVER                 0x00
#endif

#ifndef AC_SRC_ALPHA
#define AC_SRC_ALPHA                0x01
#endif

#define WM_SPLASHUPDATE         WM_USER+1
#define WM_SPLASHRECONFIGURE    WM_USER+2

/* Could use npt but decided to cut down on linked code size */
char* SplashConvertStringAlloc(const char* in, int *size) {
    int len, outChars, rc;
    WCHAR* buf;
    if (!in) {
        return NULL;
    }
    len = strlen(in);
    outChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, in, len,
                                       NULL, 0);
    buf = (WCHAR*) SAFE_SIZE_ARRAY_ALLOC(malloc, outChars, sizeof(WCHAR));
    if (!buf) {
        return NULL;
    }
    rc = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, in, len,
                                 buf, outChars);
    if (rc==0) {
        free(buf);
        return NULL;
    } else {
        if (size) {
            *size = rc;
        }
        return (char*)buf;
    }
}

unsigned
SplashTime(void)
{
    return GetTickCount();
}

void
SplashInitFrameShape(Splash * splash, int imageIndex)
{
    RGNDATA *pRgnData;
    RGNDATAHEADER *pRgnHdr;
    ImageRect maskRect;

    if (!splash->maskRequired)
        return;

    /* reserving memory for the worst case */
    if (!IS_SAFE_SIZE_MUL(splash->width / 2 + 1, splash->height)) {
        return;
    }
    pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(malloc, sizeof(RGNDATAHEADER),
            sizeof(RECT), (splash->width / 2 + 1) * splash->height);
    if (!pRgnData) {
        return;
    }
    pRgnHdr = (RGNDATAHEADER *) pRgnData;
    initRect(&maskRect, 0, 0, splash->width, splash->height, 1,
            splash->width * splash->imageFormat.depthBytes,
            splash->frames[imageIndex].bitmapBits, &splash->imageFormat);

    pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
    pRgnHdr->iType = RDH_RECTANGLES;
    pRgnHdr->nRgnSize = 0;
    pRgnHdr->rcBound.top = 0;
    pRgnHdr->rcBound.left = 0;
    pRgnHdr->rcBound.bottom = splash->height;
    pRgnHdr->rcBound.right = splash->width;

    pRgnHdr->nCount = BitmapToYXBandedRectangles(&maskRect,
            (RECT *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER)));

    splash->frames[imageIndex].hRgn = ExtCreateRegion(NULL,
            sizeof(RGNDATAHEADER) + sizeof(RECT) * pRgnHdr->nCount, pRgnData);

    free(pRgnData);
}

/* paint current splash screen frame to hdc
   this function is unused in layered window mode */

void
SplashPaint(Splash * splash, HDC hdc)
{
    unsigned numColors = splash->screenFormat.colorMap ?
        splash->screenFormat.numColors : 0;
    BITMAPV4HEADER *pBmi;
    HPALETTE hOldPal = NULL;

    if (!splash->frames)
        return;
    if (splash->currentFrame < 0 || splash->currentFrame >= splash->frameCount)
        return;
    pBmi = (BITMAPV4HEADER *) SAFE_SIZE_STRUCT_ALLOC(alloca, sizeof(BITMAPV4HEADER),
            sizeof(RGBQUAD), numColors);
    if (!pBmi) {
        return;
    }
    memset(pBmi, 0, sizeof(BITMAPV4HEADER));
    if (splash->screenFormat.colorMap)
        memcpy(((BYTE *) pBmi) + sizeof(BITMAPV4HEADER),
                splash->screenFormat.colorMap, sizeof(RGBQUAD) * numColors);

    pBmi->bV4Size = sizeof(BITMAPV4HEADER);
    pBmi->bV4Width = splash->width;
    pBmi->bV4Height = -splash->height;
    pBmi->bV4Planes = 1;
    pBmi->bV4BitCount = (WORD) (splash->screenFormat.depthBytes * 8);
    /* we're ALWAYS using BGRA in screenFormat */
    pBmi->bV4V4Compression = BI_RGB;
    pBmi->bV4ClrUsed = numColors;
    pBmi->bV4ClrImportant = numColors;
    pBmi->bV4AlphaMask = splash->screenFormat.mask[3];
    pBmi->bV4RedMask = splash->screenFormat.mask[2];
    pBmi->bV4GreenMask = splash->screenFormat.mask[1];
    pBmi->bV4BlueMask = splash->screenFormat.mask[0];

    /*  creating the palette in SplashInitPlatform does not work, so I'm creating it
       here on demand */
    if (!splash->hPalette) {
        unsigned i;
        LOGPALETTE *pLogPal = (LOGPALETTE *) SAFE_SIZE_STRUCT_ALLOC(malloc,
                sizeof(LOGPALETTE), sizeof(PALETTEENTRY), numColors);
        if (!pLogPal) {
            return;
        }

        pLogPal->palVersion = 0x300;
        pLogPal->palNumEntries = (WORD) numColors;
        for (i = 0; i < numColors; i++) {
            pLogPal->palPalEntry[i].peRed = (BYTE)
                QUAD_RED(splash->colorMap[i]);
            pLogPal->palPalEntry[i].peGreen = (BYTE)
                QUAD_GREEN(splash->colorMap[i]);
            pLogPal->palPalEntry[i].peBlue = (BYTE)
                QUAD_BLUE(splash->colorMap[i]);
            pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
        }
        splash->hPalette = CreatePalette(pLogPal);
        free(pLogPal);
    }
    if (splash->hPalette) {
        hOldPal = SelectPalette(hdc, splash->hPalette, FALSE);
        RealizePalette(hdc);
    }

    StretchDIBits(hdc, 0, 0, splash->width, splash->height, 0, 0,
            splash->width, splash->height, splash->screenData,
            (BITMAPINFO *) pBmi, DIB_RGB_COLORS, SRCCOPY);
    if (hOldPal)
        SelectPalette(hdc, hOldPal, FALSE);
}


/* The function makes the window visible if it is hidden
 or is not yet shown. */
void
SplashRedrawWindow(Splash * splash)
{
    SplashUpdateScreenData(splash);
    if (splash->isLayered) {
        BLENDFUNCTION bf;
        POINT ptSrc;
        HDC hdcSrc = CreateCompatibleDC(NULL), hdcDst;
        BITMAPINFOHEADER bmi;
        void *bitmapBits;
        HBITMAP hBitmap, hOldBitmap;
        RECT rect;
        POINT ptDst;
        SIZE size;

        bf.BlendOp = AC_SRC_OVER;
        bf.BlendFlags = 0;
        bf.AlphaFormat = AC_SRC_ALPHA;
        bf.SourceConstantAlpha = 0xFF;
        ptSrc.x = ptSrc.y = 0;

        memset(&bmi, 0, sizeof(bmi));
        bmi.biSize = sizeof(BITMAPINFOHEADER);
        bmi.biWidth = splash->width;
        bmi.biHeight = -splash->height;
        bmi.biPlanes = 1;
        bmi.biBitCount = 32;
        bmi.biCompression = BI_RGB;

        //      FIXME: this is somewhat ineffective
        //      maybe if we allocate memory for all frames as DIBSections,
        //      then we could select the frames into the DC directly

        hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS,
                &bitmapBits, NULL, 0);
        memcpy(bitmapBits, splash->screenData,
                splash->screenStride * splash->height);
        hOldBitmap = (HBITMAP) SelectObject(hdcSrc, hBitmap);
        hdcDst = GetDC(splash->hWnd);

        GetWindowRect(splash->hWnd, &rect);

        ptDst.x = rect.left;
        ptDst.y = rect.top;

        size.cx = splash->width;
        size.cy = splash->height;

        UpdateLayeredWindow(splash->hWnd, hdcDst, &ptDst, &size,
                hdcSrc, &ptSrc, 0, &bf, ULW_ALPHA);

        ReleaseDC(splash->hWnd, hdcDst);
        SelectObject(hdcSrc, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hdcSrc);
    }
    else {
       InvalidateRect(splash->hWnd, NULL, FALSE);
       if (splash->maskRequired) {
            HRGN hRgn = CreateRectRgn(0, 0, 0, 0);

            CombineRgn(hRgn, splash->frames[splash->currentFrame].hRgn,
                    splash->frames[splash->currentFrame].hRgn, RGN_COPY);
            SetWindowRgn(splash->hWnd, hRgn, TRUE);
        } else {
            SetWindowRgn(splash->hWnd, NULL, TRUE);
        }
        UpdateWindow(splash->hWnd);
    }
    if (!IsWindowVisible(splash->hWnd)) {
        POINT cursorPos;
        ShowWindow(splash->hWnd, SW_SHOW);
        // Windows won't update the cursor after the window is shown,
        // if the cursor is already above the window. need to do this manually.
        GetCursorPos(&cursorPos);
        if (WindowFromPoint(cursorPos) == splash->hWnd) {
            // unfortunately Windows fail to understand that the window
            // thread should own the cursor, even though the mouse pointer
            // is over the window, until the mouse has been moved.
            // we're using SetCursorPos here to fake the mouse movement
            // and enable proper update of the cursor.
            SetCursorPos(cursorPos.x, cursorPos.y);
            SetCursor(LoadCursor(NULL, IDC_WAIT));
        }
    }
    if (SplashIsStillLooping(splash)) {
        int time = splash->time +
            splash->frames[splash->currentFrame].delay - SplashTime();

        if (time < 0)
            time = 0;
        SetTimer(splash->hWnd, 0, time, NULL);
    }
    else {
        KillTimer(splash->hWnd, 0);
    }
}

void SplashReconfigureNow(Splash * splash) {
    splash->x = (GetSystemMetrics(SM_CXSCREEN) - splash->width) / 2;
    splash->y = (GetSystemMetrics(SM_CYSCREEN) - splash->height) / 2;
    if (splash->hWnd) {
        //Fixed 6474657: splash screen image jumps towards left while
        //    setting the new image using setImageURL()
        // We may safely hide the splash window because SplashRedrawWindow()
        //    will show the window again.
        ShowWindow(splash->hWnd, SW_HIDE);
        MoveWindow(splash->hWnd, splash->x, splash->y, splash->width, splash->height, FALSE);
    }
    SplashRedrawWindow(splash);
}

static LRESULT CALLBACK
SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;


    switch (message) {

    case WM_ERASEBKGND:
        return TRUE;            // to avoid flicker

    case WM_SYSCOMMAND:
        if (wParam==SC_CLOSE||wParam==SC_DEFAULT||wParam==SC_HOTKEY||
            wParam==SC_KEYMENU||wParam==SC_MAXIMIZE||
            wParam==SC_MINIMIZE||wParam==SC_MOUSEMENU||wParam==SC_MOVE||
            wParam==SC_RESTORE||wParam==SC_SIZE)
        {
            return 0;
        }

    /* double switch to avoid prologue/epilogue duplication */
    case WM_TIMER:
    case WM_SPLASHUPDATE:
    case WM_PAINT:
    case WM_SPLASHRECONFIGURE:
        {
            Splash *splash = (Splash *) GetWindowLongPtr(hWnd, GWLP_USERDATA);

            SplashLock(splash);
            if (splash->isVisible>0) {
                switch(message) {
                case WM_TIMER:
                    SplashNextFrame(splash);
                    SplashRedrawWindow(splash);
                    break;
                case WM_SPLASHUPDATE:
                    SplashRedrawWindow(splash);
                    break;
                case WM_PAINT:
                    hdc = BeginPaint(hWnd, &ps);
                    SplashPaint(splash, hdc);
                    EndPaint(hWnd, &ps);
                    break;
                case WM_SPLASHRECONFIGURE:
                    SplashReconfigureNow(splash);
                    break;
                }
            }
            SplashUnlock(splash);
            break;
        }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);

    }
    return 0;
}

HWND
SplashCreateWindow(Splash * splash)
{
    WNDCLASSEX wcex;
    ATOM wndClass;
    DWORD style, exStyle;
    HWND hWnd;

    ZeroMemory(&wcex, sizeof(WNDCLASSEX));

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = (WNDPROC) SplashWndProc;
    wcex.hInstance = GetModuleHandle(NULL);
    wcex.lpszClassName = "JavaSplash";
    wcex.hCursor = LoadCursor(NULL, IDC_WAIT);

    wndClass = RegisterClassEx(&wcex);
    if (!wndClass) {
        return 0;
    }

    splash->x = (GetSystemMetrics(SM_CXSCREEN) - splash->width) / 2;
    splash->y = (GetSystemMetrics(SM_CYSCREEN) - splash->height) / 2;
    exStyle = splash->isLayered ? WS_EX_LAYERED : 0;
    exStyle |= WS_EX_TOOLWINDOW;        /* don't show the window on taskbar */
    style = WS_POPUP;
    hWnd = CreateWindowEx(exStyle, (LPCSTR) wndClass, "", style,
            splash->x, splash->y, splash->width, splash->height, NULL, NULL,
            wcex.hInstance, NULL);
    SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) splash);
    return hWnd;
}

void
SplashLock(Splash * splash)
{
    EnterCriticalSection(&splash->lock);
}

void
SplashUnlock(Splash * splash)
{
    LeaveCriticalSection(&splash->lock);
}

void
SplashInitPlatform(Splash * splash)
{
    HDC hdc;
    int paletteMode;

    InitializeCriticalSection(&splash->lock);
    splash->isLayered = FALSE;
    hdc = GetDC(NULL);
    paletteMode = (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0;
    if (UpdateLayeredWindow && !paletteMode) {
        splash->isLayered = TRUE;
    }
    splash->byteAlignment = 4;
    if (splash->isLayered) {
        initFormat(&splash->screenFormat,
                0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
        splash->screenFormat.premultiplied = 1;
        splash->maskRequired = 0;
    }
    else {
        splash->maskRequired = 1;
        if (paletteMode) {
            int numColors = GetDeviceCaps(hdc, SIZEPALETTE) -
                GetDeviceCaps(hdc, NUMRESERVED);
            int i;
            int numComponents[3];

            initFormat(&splash->screenFormat, 0, 0, 0, 0);
            /*      FIXME: maybe remapping to non-reserved colors would improve performance */
            for (i = 0; i < numColors; i++) {
                splash->colorIndex[i] = i;
            }
            numColors = quantizeColors(numColors, numComponents);
            initColorCube(numComponents, splash->colorMap, splash->dithers,
                    splash->colorIndex);
            splash->screenFormat.colorIndex = splash->colorIndex;
            splash->screenFormat.depthBytes = 1;
            splash->screenFormat.colorMap = splash->colorMap;
            splash->screenFormat.dithers = splash->dithers;
            splash->screenFormat.numColors = numColors;
            splash->hPalette = NULL;
        }
        else {
            initFormat(&splash->screenFormat,
                    0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
        }
    }
    ReleaseDC(NULL, hdc);
}

void
SplashCleanupPlatform(Splash * splash)
{
    int i;

    if (splash->frames) {
        for (i = 0; i < splash->frameCount; i++) {
            if (splash->frames[i].hRgn) {
                DeleteObject(splash->frames[i].hRgn);
                splash->frames[i].hRgn = NULL;
            }
        }
    }
    if (splash->hPalette)
        DeleteObject(splash->hPalette);
    splash->maskRequired = !splash->isLayered;
}

void
SplashDonePlatform(Splash * splash)
{
    if (splash->hWnd)
        DestroyWindow(splash->hWnd);
}

void
SplashMessagePump()
{
    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

DWORD WINAPI
SplashScreenThread(LPVOID param)
{
    Splash *splash = (Splash *) param;

    splash->currentFrame = 0;
    SplashLock(splash);
    splash->time = SplashTime();
    splash->hWnd = SplashCreateWindow(splash);
    if (splash->hWnd) {
        SplashRedrawWindow(splash);
        SplashUnlock(splash);
        SplashMessagePump();
        SplashLock(splash);
    }
    SplashDone(splash);
    splash->isVisible = -1;
    SplashUnlock(splash);
    return 0;
}

void
SplashCreateThread(Splash * splash)
{
    DWORD threadId;

    CreateThread(NULL, 0, SplashScreenThread, (LPVOID) splash, 0, &threadId);
}

void
SplashClosePlatform(Splash * splash)
{
    PostMessage(splash->hWnd, WM_QUIT, 0, 0);
}

void
SplashUpdate(Splash * splash)
{
    PostMessage(splash->hWnd, WM_SPLASHUPDATE, 0, 0);
}

void
SplashReconfigure(Splash * splash)
{
    PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0);
}

Other Java examples (source code examples)

Here is a short list of links related to this Java splashscreen_sys.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.