News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

A prototype that needs testing on different OS versions

Started by hutch--, August 19, 2019, 04:08:27 AM

Previous topic - Next topic

hutch--

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.

TimoVJL

Perhaps sequence: start splash thread, create window, show window works.
May the source be with you

hutch--

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.

TimoVJL

In one example was used SetForegroundWindow(hFrame); in splash thread at the end of it.
May the source be with you

hutch--

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.

aw27

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;
}



hutch--

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.

TimoVJL

#22
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
May the source be with you