Could I impose on a few folks to test this simple app for me, its a prototype for a splash screen that shows the screen fading in to a full image then it disappears before the main window appears. The main window is just a can to test the splash screen but the help menu will also run the same splash screen. Its working OK here but there are many other variables from different human language OS versions and OS versions.
The splash screen window runs in a separate thread from the main app so it can be handled in a modular manner and it uses a normal timer for its duration. The idea is to have a simple function call that specifies a resource ID for a JPG image and a duration in milliseconds for it to be displayed.
Hi hutch,
Win 10 - OK
Win 7 - OK
WinXP - nothing is displayed, but then the program works (Perhaps due to the fact that the visual styles of Windows are disabled.)
I like it! works fine in windows 8.1 :thumbsup:
W10 works fine
Is intended behaviour to see the splash when selecting "about"?
Works OK with Win10/64
Biterider
2000(after installing gdiplus.dll)/XP/XP64/Vista64 - main window shows, splash shows in the taskbar but not on screen
7/8.1/10 - works OK
Thanks guys, its pointed at win7 upwards and uses GDI+ to handle a JPG stored in the resource section. I think it will be a reasonably easy port to Win64 and it should be useful for UI apps.
works ok on this build of W10,wonder if reporting build number for W10 ,should make it more helpful for all kinds of future tests?
separate thread for GDI+ drawing ,example would be nice and useful for smoother and better drawing on newer computer than make messagepump laggy
Hi,
Win 2000 Grayed window, but runs and exits.
Win 98 Complained of missing gdi+ dll.
When supplied DLL, aborted with an illegal instruction.
Win XP Grayed window, but runs and exits.
Win 8.1 Shows splash screen then grayed window.
Clicking Help => About shows a splash screen somewhat
wider and shorter than the window.
Cheers,
Steve N.
Just tested in Windows Server 2019 and it works fine too.
I have done the 64 bit MASM version and it seems to work OK here. It has been a pain to get the start splash screen going as Win64 instantly displays the window without needing to use ShowWindow() so I have used an old technique of starting the window off screen, displaying the splash screen then using MoveWindow() to display the main window. No such problem once the main window is displayed, the Help/About menu displays a different image with a single call. This one has the full 64 bit MASM code and a directory that builds the test library for the splash module. Once I am happy with it, the module goes into the 64 bit library.
Quote from: hutch-- on August 20, 2019, 07:13:45 PMas Win64 instantly displays the window without needing to use ShowWindow()
Did you try without WS_VISIBLE?
invoke CreateWindowEx,WS_EX_LEFT or WS_EX_ACCEPTFILES, \
ADDR classname,ADDR caption, \
WS_OVERLAPPEDWINDOW
or WS_VISIBLE,\
-1000,-1000,wid,hgt,0,0,hInstance,0 ; start off screen
It works but at the price that the main window no longer has the focus after the splash screen is finished.
Do you main focus (->SetFocus) or z-order (->SetWindowPos)?
Both, it no longer had the focus AND it was not on the top of the Z order. Starting it off screen minimised did the job and when the splash screen was finished and the ShowWindow restoired it, MoveWindow() put it at the right location. The mess was because the splash screen was done in a separate thread that took the original focus. It was a lot less problematic in Win32.
Perhaps sequence: start splash thread, create window, show window works.
Timo,
That was the original idea but if the splash thread is the first thread the main app window is then not the main thread and it does not gain the keyboard focus when it starts. I tried all of the combinations and starting the main window first minimised was the only one that safely worked. As in the about box, once the main thread has started everything works normally.
In one example was used SetForegroundWindow(hFrame); in splash thread at the end of it.
The thread does not know what the main window handle is and you would have to pass the handle to the splash thread to try it. I have tried both SetActiveWindow() and SetForegroundWindow() and neither brought the main window to the top. The library module works fine so I don't see any point to changing how its called. Starting off screen has always worked well and a call to MoveWindow()) does the job.
LATER : Had a quick play with an old API, BringWindowToTop() and it works OK with the window starting minimised, running the splash screen then setting the Z order with this API.
This is an example of splash screen of 2 seconds made without using a second thread. It is made in C, 90% of it copied straight from the internet.
#include <windows.h>
#include "resource.h"
const char ClassName[] = "MainWindowClass";
const char SplashClassName[] = "SplashWindowClass";
HWND hMainWnd;
HBITMAP hSplashBMP;
HDC hSplashDC;
HDC hMemoryDC;
LONG BitmapWidth, BitmapHeight;
LRESULT CALLBACK WndProc(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
switch (Msg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, Msg, wParam, lParam));
}
return 0;
}
LRESULT CALLBACK SplashWndProc(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
switch (Msg)
{
case WM_ERASEBKGND:
BitBlt((HDC)wParam, 0, 0, BitmapWidth, BitmapHeight, hMemoryDC, 0, 0, SRCCOPY);
break;
case WM_TIMER:
DeleteObject(hSplashBMP);
ReleaseDC(hWnd, hSplashDC);
ReleaseDC(hWnd, hMemoryDC);
DestroyWindow(hWnd);
ShowWindow(hMainWnd, SW_SHOW);
UpdateWindow(hMainWnd);
SetForegroundWindow(hMainWnd);
break;
default:
return (DefWindowProc(hWnd, Msg, wParam, lParam));
}
return 0;
}
INT WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
INT nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Failed To Register The Window Class.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
WNDCLASSEX splashwc;
splashwc.cbSize = sizeof(WNDCLASSEX);
splashwc.style = 0;
splashwc.lpfnWndProc = (WNDPROC)SplashWndProc;
splashwc.cbClsExtra = 0;
splashwc.cbWndExtra = 0;
splashwc.hInstance = hInstance;
splashwc.hIcon = NULL;
splashwc.hIconSm = NULL;
splashwc.hCursor = LoadCursor(NULL, IDC_ARROW);
splashwc.hbrBackground = NULL;
splashwc.lpszMenuName = NULL;
splashwc.lpszClassName = SplashClassName;
if (!RegisterClassEx(&splashwc))
{
MessageBox(NULL, "Failed To Register The Splash Window Class.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
RECT DesktopRect;
GetWindowRect(GetDesktopWindow(), &DesktopRect);
hMainWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
ClassName,
"Splash Screen",
WS_OVERLAPPEDWINDOW,
(DesktopRect.right - 340) / 2,
(DesktopRect.bottom - 200) / 2,
340,
200,
NULL,
NULL,
hInstance,
NULL);
if (!hMainWnd)
{
MessageBox(NULL, "Window Creation Failed.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
hSplashBMP = LoadBitmap(hInstance, MAKEINTRESOURCE(BITMAP_ID));
if (!hSplashBMP)
{
MessageBox(NULL, "Failed To Load Bitmap", "Error", MB_OK | MB_ICONERROR);
return 0;
}
BITMAP Bitmap;
GetObject(hSplashBMP, sizeof(BITMAP), &Bitmap);
BitmapWidth = Bitmap.bmWidth;
BitmapHeight = Bitmap.bmHeight;
HWND hSplashWnd = CreateWindowEx(
0,
SplashClassName,
"Splash Screen",
WS_POPUP,
(DesktopRect.right - BitmapWidth) / 2,
(DesktopRect.bottom - BitmapHeight) / 2,
Bitmap.bmWidth,
Bitmap.bmHeight,
NULL,
NULL,
hInstance,
NULL);
if (!hSplashWnd)
{
MessageBox(NULL, "Splash Window Creation Failed.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
hSplashDC = GetDC(hSplashWnd);
hMemoryDC = CreateCompatibleDC(hSplashDC);
SelectObject(hMemoryDC, (HGDIOBJ)hSplashBMP);
SetTimer(hSplashWnd, 0, 2000, (TIMERPROC)NULL);
ShowWindow(hSplashWnd, SW_SHOW);
UpdateWindow(hSplashWnd);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
They can be coded inline but I was after a separate module that could be called without complex setup and use a JPG image to keep the app size down.
Better to use thread, as it don't disturb main thread, a simple test.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_THREAD
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ULONG ShowSplash(void *p);
char *szAppName = "WinFrame";
char *szFrameClass = "cWinFrame";
HWND hFrame;
HANDLE hInst;
void __cdecl WinMainCRTStartup(void)
{
ExitProcess(WinMain(GetModuleHandle(NULL), 0, 0, SW_NORMAL));
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcx;
MSG msg;
wcx.cbSize = sizeof(WNDCLASSEX);
GetClassInfoEx(hInstance, MAKEINTRESOURCE(32770), &wcx);
wcx.lpfnWndProc = (WNDPROC) WndProc;
wcx.hInstance = hInstance;
wcx.hbrBackground= (HBRUSH)COLOR_APPWORKSPACE+1;
wcx.lpszClassName= szFrameClass;
if (!RegisterClassEx(&wcx))
return 0;
hInst = hInstance;
#ifndef USE_THREAD
ShowSplash();
#else
CreateThread(0, 0, ShowSplash, 0, 0, NULL);
#endif
hFrame = CreateWindowEx(0, szFrameClass, szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInst, NULL);
if(!hFrame) return 0;
ShowWindow(hFrame, nCmdShow);
//UpdateWindow(hFrame);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch(wMsg) {
case WM_CREATE:
Sleep(1000);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, wMsg, wParam, lParam);
}
void WINAPI TimerProc1(HWND hwnd, UINT uMsg, UINT timerId, DWORD dwTime)
{
SetForegroundWindow(hFrame);
KillTimer(hwnd, timerId);
DestroyWindow(hwnd);
}
ULONG ShowSplash(void *p)
{
int x = GetSystemMetrics(SM_CXFULLSCREEN) / 2 - 250;
int y = GetSystemMetrics(SM_CYFULLSCREEN) / 2 - 250;
HWND hWnd = CreateWindowEx(0, "STATIC", "#8001",
WS_POPUP | WS_BORDER | WS_VISIBLE | SS_BITMAP
, x, y, 500, 500, 0,
(HMENU)0, hInst, NULL);
SetTimer(hWnd, 1, 2000, TimerProc1);
#ifdef USE_THREAD
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#endif
return (ULONG)hWnd;
}
8001 BITMAP "WFSplash.bmp"
EDIT: using thread don't add much code#ifndef USE_THREAD
ShowSplash(8001);
#else
CreateThread(0, 0, ShowSplash, (void*)8001, 0, NULL);
#endif