Added a splash screen for the Windows version of Celestia.
parent
83f9f6b2d9
commit
db3b454cb6
Binary file not shown.
After Width: | Height: | Size: 469 KiB |
|
@ -39,6 +39,7 @@ OBJS=\
|
|||
$(INTDIR)\winhyperlinks.obj \
|
||||
$(INTDIR)\winlocations.obj \
|
||||
$(INTDIR)\winmain.obj \
|
||||
$(INTDIR)\winsplash.obj \
|
||||
$(INTDIR)\winssbrowser.obj \
|
||||
$(INTDIR)\winstarbrowser.obj \
|
||||
$(INTDIR)\wintime.obj \
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "wineclipses.h"
|
||||
#include "winhyperlinks.h"
|
||||
#include "wintime.h"
|
||||
#include "winsplash.h"
|
||||
#include "odmenu.h"
|
||||
|
||||
#include "res/resource.h"
|
||||
|
@ -2954,6 +2955,22 @@ static bool parseCommandLine(int argc, char* argv[])
|
|||
}
|
||||
|
||||
|
||||
class WinSplashProgressNotifier : public ProgressNotifier
|
||||
{
|
||||
public:
|
||||
WinSplashProgressNotifier(SplashWindow* _splash) : splash(_splash) {};
|
||||
virtual ~WinSplashProgressNotifier() {};
|
||||
|
||||
virtual void update(const string& filename)
|
||||
{
|
||||
splash->setMessage(string("Loading: ") + filename);
|
||||
}
|
||||
|
||||
private:
|
||||
SplashWindow* splash;
|
||||
};
|
||||
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
|
@ -2998,6 +3015,10 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
}
|
||||
}
|
||||
|
||||
SplashWindow splash("splash.png");
|
||||
splash.setMessage("Loading data files...");
|
||||
splash.showSplash();
|
||||
|
||||
OleInitialize(NULL);
|
||||
dropTarget = new CelestiaDropTarget();
|
||||
if (dropTarget)
|
||||
|
@ -3078,12 +3099,16 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
if (startDirectory != "")
|
||||
SetCurrentDirectory(startDirectory.c_str());
|
||||
|
||||
WinSplashProgressNotifier progressNotifier(&splash);
|
||||
string* altConfig = useAlternateConfigFile ? &configFileName : NULL;
|
||||
if (!appCore->initSimulation(altConfig, &extrasDirectories))
|
||||
if (!appCore->initSimulation(altConfig, &extrasDirectories, &progressNotifier))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Close the splash screen after all data has been loaded
|
||||
splash.close();
|
||||
|
||||
if (startURL != "")
|
||||
appCore->setStartURL(startURL);
|
||||
|
||||
|
|
|
@ -0,0 +1,361 @@
|
|||
// winsplash.cpp
|
||||
//
|
||||
// Copyright (C) 2005, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// Win32 splash window
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#include "winsplash.h"
|
||||
#include <string>
|
||||
#include <winuser.h>
|
||||
#include <commctrl.h>
|
||||
#include "res/resource.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Required for transparent Windows, but not present in VC6 headers. Only present
|
||||
// on Win2k or later.
|
||||
typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)
|
||||
(HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
|
||||
typedef BOOL (WINAPI *lpfnUpdateLayeredWindow)
|
||||
(HWND hwnd, HDC hdcDst, POINT* pptDst, SIZE* psize,
|
||||
HDC hdcSrc, POINT* pptSrc, COLORREF crKey, BLENDFUNCTION* pblend,
|
||||
DWORD dwFlags);
|
||||
|
||||
lpfnSetLayeredWindowAttributes winSetLayeredWindowAttributes = NULL;
|
||||
lpfnUpdateLayeredWindow winUpdateLayeredWindow = NULL;
|
||||
|
||||
#define WS_EX_LAYERED 0x00080000
|
||||
#define LWA_COLORKEY 1
|
||||
#define LWA_ALPHA 2
|
||||
|
||||
#define ULW_COLORKEY 1
|
||||
#define ULW_ALPHA 2
|
||||
#define ULW_OPAQUE 4
|
||||
|
||||
|
||||
static LRESULT CALLBACK SplashWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static SplashWindow *splash = NULL;
|
||||
|
||||
if (uMsg == WM_CREATE)
|
||||
{
|
||||
splash = reinterpret_cast<SplashWindow*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
|
||||
}
|
||||
|
||||
if (splash)
|
||||
return splash->windowProc(hwnd, uMsg, wParam, lParam);
|
||||
else
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
SplashWindow::SplashWindow(const string& _imageFileName) :
|
||||
hwnd(NULL),
|
||||
className(NULL),
|
||||
imageFileName(_imageFileName),
|
||||
image(NULL),
|
||||
hBitmap(0),
|
||||
hCompositionBitmap(0),
|
||||
useLayeredWindow(false),
|
||||
winWidth(640),
|
||||
winHeight(480)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
SplashWindow::~SplashWindow()
|
||||
{
|
||||
if (hBitmap)
|
||||
::DeleteObject(hBitmap);
|
||||
if (hCompositionBitmap)
|
||||
::DeleteObject(hCompositionBitmap);
|
||||
}
|
||||
|
||||
|
||||
LRESULT CALLBACK
|
||||
SplashWindow::windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
if (!useLayeredWindow)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC hDC = BeginPaint(hwnd, &ps);
|
||||
paint(hDC);
|
||||
EndPaint(hwnd, &ps);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return DefWindowProc (hwnd, uMsg, wParam, lParam) ;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SplashWindow::paint(HDC hDC)
|
||||
{
|
||||
RECT rect;
|
||||
::GetClientRect(hwnd, &rect);
|
||||
|
||||
if (hBitmap)
|
||||
{
|
||||
// Display the splash image
|
||||
HDC hMemDC = ::CreateCompatibleDC(hDC);
|
||||
HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hMemDC, hBitmap);
|
||||
|
||||
BitBlt(hDC, 0, 0, winWidth, winHeight, hMemDC, 0, 0, SRCCOPY);
|
||||
|
||||
::SelectObject(hMemDC, hOldBitmap);
|
||||
::DeleteDC(hMemDC);
|
||||
|
||||
SetTextColor(hDC, RGB(255, 255, 255));
|
||||
SetBkMode(hDC, TRANSPARENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the splash image couldn't be loaded, just paint a black background
|
||||
HBRUSH hbrush = CreateSolidBrush(RGB(0, 0, 0));
|
||||
FillRect(hDC, &rect, hbrush);
|
||||
DeleteObject(hbrush);
|
||||
}
|
||||
|
||||
// Show the message text
|
||||
RECT r;
|
||||
r.left = rect.right - 250;
|
||||
r.top = rect.bottom - 70;
|
||||
r.right = rect.right;
|
||||
r.bottom = r.top + 30;
|
||||
|
||||
HFONT hFont = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
|
||||
SelectObject(hDC, hFont);
|
||||
|
||||
DrawText(hDC, message.c_str(), message.length(), &r, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SplashWindow::init()
|
||||
{
|
||||
hwnd = NULL;
|
||||
className = TEXT("CELSPLASH");
|
||||
|
||||
// Get the function pointer for SetLayeredWindowAttributes
|
||||
HMODULE user32 = GetModuleHandle(TEXT("USER32.DLL"));
|
||||
|
||||
winSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes) GetProcAddress(user32, "SetLayeredWindowAttributes");
|
||||
winUpdateLayeredWindow = (lpfnUpdateLayeredWindow) GetProcAddress(user32, "UpdateLayeredWindow");
|
||||
|
||||
if (winSetLayeredWindowAttributes != NULL && winUpdateLayeredWindow != NULL)
|
||||
useLayeredWindow = true;
|
||||
|
||||
image = LoadImageFromFile(imageFileName);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SplashWindow::updateWindow()
|
||||
{
|
||||
// If we're using layered windows, draw into the compositing bitmap and use it to
|
||||
// as the source for UpdateLayeredWindow. Otherwise, we use the traditional approach
|
||||
// and send a paint message to the window.
|
||||
if (useLayeredWindow)
|
||||
{
|
||||
HDC hwndDC = GetDC(hwnd);
|
||||
HDC hDC = CreateCompatibleDC(hwndDC);
|
||||
|
||||
HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hDC, hCompositionBitmap);
|
||||
paint(hDC);
|
||||
|
||||
SIZE size;
|
||||
POINT origin = { 0, 0 };
|
||||
size.cx = winWidth;
|
||||
size.cy = winHeight;
|
||||
BLENDFUNCTION blend;
|
||||
blend.BlendOp = AC_SRC_OVER;
|
||||
blend.BlendFlags = 0;
|
||||
blend.AlphaFormat = AC_SRC_ALPHA;
|
||||
blend.SourceConstantAlpha = 0xff;
|
||||
winUpdateLayeredWindow(hwnd, hwndDC, NULL, &size, hDC, &origin, 0, &blend, ULW_ALPHA);
|
||||
|
||||
::SelectObject(hDC, hOldBitmap);
|
||||
::DeleteDC(hDC);
|
||||
}
|
||||
|
||||
::UpdateWindow(hwnd);
|
||||
}
|
||||
|
||||
|
||||
HWND
|
||||
SplashWindow::createWindow()
|
||||
{
|
||||
WNDCLASSEX wndclass;
|
||||
wndclass.cbSize = sizeof (wndclass);
|
||||
wndclass.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
|
||||
wndclass.lpfnWndProc = SplashWndProc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = DLGWINDOWEXTRA;
|
||||
wndclass.hInstance = ::GetModuleHandle(NULL);
|
||||
wndclass.hIcon = NULL;
|
||||
wndclass.hCursor = ::LoadCursor( NULL, IDC_WAIT );
|
||||
wndclass.hbrBackground = (HBRUSH)::GetStockObject(LTGRAY_BRUSH);
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = className;
|
||||
wndclass.hIconSm = NULL;
|
||||
|
||||
if (!RegisterClassEx(&wndclass))
|
||||
return NULL;
|
||||
|
||||
if (image != NULL)
|
||||
{
|
||||
winWidth = image->getWidth();
|
||||
winHeight = image->getHeight();
|
||||
}
|
||||
|
||||
// Create the application window centered in the middle of the screen
|
||||
DWORD nScrWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);
|
||||
DWORD nScrHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);
|
||||
|
||||
int x = (nScrWidth - winWidth) / 2;
|
||||
int y = (nScrHeight - winHeight) / 2;
|
||||
hwnd = ::CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, className,
|
||||
TEXT("Banner"), WS_POPUP, x, y,
|
||||
winWidth, winHeight, NULL, NULL, NULL, this);
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
createBitmap();
|
||||
|
||||
// If this version of Windows supports layered windows, set the window
|
||||
// style to layered.
|
||||
if (useLayeredWindow)
|
||||
{
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
|
||||
}
|
||||
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
updateWindow();
|
||||
}
|
||||
|
||||
delete image;
|
||||
image = NULL;
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SplashWindow::createBitmap()
|
||||
{
|
||||
if (image != NULL)
|
||||
{
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory(&bmi, sizeof(bmi));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = image->getWidth();
|
||||
bmi.bmiHeader.biHeight = image->getHeight();
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = image->getWidth() * image->getHeight() * 4;
|
||||
|
||||
HDC hwndDC = GetDC(hwnd);
|
||||
HDC hDC = CreateCompatibleDC(hwndDC);
|
||||
|
||||
void* bmPixels = NULL;
|
||||
|
||||
// create our DIB section and select the bitmap into the dc
|
||||
hBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bmPixels, NULL, 0x0);
|
||||
|
||||
// Windows bitmaps are upside-down and the order of the color channels is different
|
||||
// than for a PNG. When copying pixels to the bitmap, we remap the color channels and
|
||||
// flip the image vertically.
|
||||
if (bmPixels != NULL)
|
||||
{
|
||||
unsigned char* src = image->getPixels();
|
||||
unsigned char* dst = reinterpret_cast<unsigned char*>(bmPixels);
|
||||
|
||||
for (unsigned int i = 0; i < (unsigned int) image->getHeight(); i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < (unsigned int) image->getWidth(); j++)
|
||||
{
|
||||
unsigned char* srcPix = &src[4 * (image->getWidth() * (image->getHeight() - i - 1) + j)];
|
||||
unsigned char* dstPix = &dst[4 * (image->getWidth() * i + j)];
|
||||
|
||||
// Windows requires that we premultiply by alpha
|
||||
unsigned int alpha = srcPix[3];
|
||||
dstPix[0] = (unsigned char) ((srcPix[2] * alpha) / 255);
|
||||
dstPix[1] = (unsigned char) ((srcPix[1] * alpha) / 255);
|
||||
dstPix[2] = (unsigned char) ((srcPix[0] * alpha) / 255);
|
||||
dstPix[3] = srcPix[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeleteDC(hDC);
|
||||
|
||||
// Create the composition bitmap (always created, though it's only used when we've got
|
||||
// layered window support.)
|
||||
if (hBitmap)
|
||||
{
|
||||
hCompositionBitmap = CreateCompatibleBitmap(hwndDC, image->getWidth(), image->getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
return hBitmap != 0 && hCompositionBitmap != 0;
|
||||
}
|
||||
|
||||
|
||||
int SplashWindow::messageLoop()
|
||||
{
|
||||
if (!hwnd)
|
||||
showSplash();
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return msg.wParam ;
|
||||
}
|
||||
|
||||
|
||||
// Redraw the window with a new text message
|
||||
void SplashWindow::setMessage(const string& msg)
|
||||
{
|
||||
message = msg;
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
updateWindow();
|
||||
}
|
||||
|
||||
|
||||
void SplashWindow::showSplash()
|
||||
{
|
||||
close();
|
||||
createWindow();
|
||||
}
|
||||
|
||||
|
||||
int SplashWindow::close()
|
||||
{
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
DestroyWindow(hwnd);
|
||||
hwnd = 0;
|
||||
UnregisterClass(className, ::GetModuleHandle(NULL));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// winsplash.h
|
||||
//
|
||||
// Copyright (C) 2005, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// Win32 splash window
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <celengine/image.h>
|
||||
|
||||
|
||||
class SplashWindow
|
||||
{
|
||||
public:
|
||||
SplashWindow(const std::string& _imageFileName);
|
||||
~SplashWindow();
|
||||
|
||||
LRESULT CALLBACK windowProc(HWND, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
void init();
|
||||
void paint(HDC hDC);
|
||||
HWND createWindow();
|
||||
int messageLoop();
|
||||
void showSplash();
|
||||
int close();
|
||||
bool createBitmap();
|
||||
void updateWindow();
|
||||
|
||||
void setMessage(const std::string& msg);
|
||||
|
||||
private:
|
||||
HWND hwnd;
|
||||
char* className;
|
||||
std::string imageFileName;
|
||||
Image* image;
|
||||
HBITMAP hBitmap;
|
||||
HBITMAP hCompositionBitmap;
|
||||
bool useLayeredWindow;
|
||||
std::string message;
|
||||
unsigned int winWidth;
|
||||
unsigned int winHeight;
|
||||
};
|
Loading…
Reference in New Issue