icd
asked on
DestroyWindow newby question.
I have a simple test program that I have been using to develop a splash screen. There are two problems with it.
1. If I do a 'DestroyWindow' for the splash screen and then try to do a 'MessageBox' then the message box is not displayed (The function returns code 0x01). Any MessageBox before the DestroyWindow call works however.
2. If the splash screen is hidden by another window it is not re-painted when it is un-hidden.
The code that demonstrates these problems is:-
#include <windows.h>
HINSTANCE hSplashInstance;
HINSTANCE hSplashInst;
HWND hSplashWnd;
HBITMAP imgHandle;
BITMAP gBitMap;
LRESULT CALLBACK SplashProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
HDC hDCMem;
switch (message) {
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
hDCMem = CreateCompatibleDC(hdc);
SelectObject(hDCMem, imgHandle);
SetMapMode(hDCMem, GetMapMode(hdc));
// Draw the bitmap using the BitBlt function
if (BitBlt(
hdc, // The destination device context
0, 0, // Coordinates of the destination rectangle
gBitMap.bmWidth, // Width of the dest. and source rectangle
gBitMap.bmHeight,// Height of the dest. and source rectangle
hDCMem, 0, 0, SRCCOPY)) {
DeleteDC(hDCMem);
}
RECT rt;
GetClientRect(hWnd, &rt);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL InitSplashInstance(HINSTAN CE hSplashInstance, int nCmdShow) {
//
imgHandle = (HBITMAP)LoadImage(NULL,"s plash.bmp" ,NULL,NULL ,NULL,LR_L OADFROMFIL E);
if (!imgHandle) {
return FALSE;
}
GetObject(imgHandle, sizeof(BITMAP), &gBitMap);
hSplashInst = hSplashInstance; // Store instance handle in our global variable
hSplashWnd = CreateWindowEx(WS_EX_CLIEN TEDGE | WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE, "SplashClass", NULL, WS_POPUP,
(GetSystemMetrics(SM_CXSCR EEN) - gBitMap.bmWidth) / 2,
(GetSystemMetrics(SM_CYSCR EEN) - gBitMap.bmHeight) / 2,
gBitMap.bmWidth, gBitMap.bmHeight,
NULL, NULL, hSplashInstance, NULL);
if (!hSplashWnd) {
return FALSE;
}
ShowWindow(hSplashWnd, nCmdShow);
UpdateWindow(hSplashWnd);
return TRUE;
}
ATOM SplashRegisterClass(HINSTA NCE hSplashInstance) {
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)SplashProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hSplashInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "SplashClass";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
int retval;
// Create and display a SPLASH SCREEN
SplashRegisterClass(hSplas hInstance) ;
if(!InitSplashInstance(hSp lashInstan ce, nCmdShow)){
return FALSE;
}
Sleep(2000);
DestroyWindow(hSplashWnd);
retval = MessageBox(NULL, "test message", "Diagnostics", MB_APPLMODAL|MB_ICONSTOP|M B_OK);
Sleep(2000);
return(0);
}
1. If I do a 'DestroyWindow' for the splash screen and then try to do a 'MessageBox' then the message box is not displayed (The function returns code 0x01). Any MessageBox before the DestroyWindow call works however.
2. If the splash screen is hidden by another window it is not re-painted when it is un-hidden.
The code that demonstrates these problems is:-
#include <windows.h>
HINSTANCE hSplashInstance;
HINSTANCE hSplashInst;
HWND hSplashWnd;
HBITMAP imgHandle;
BITMAP gBitMap;
LRESULT CALLBACK SplashProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
HDC hDCMem;
switch (message) {
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
hDCMem = CreateCompatibleDC(hdc);
SelectObject(hDCMem, imgHandle);
SetMapMode(hDCMem, GetMapMode(hdc));
// Draw the bitmap using the BitBlt function
if (BitBlt(
hdc, // The destination device context
0, 0, // Coordinates of the destination rectangle
gBitMap.bmWidth, // Width of the dest. and source rectangle
gBitMap.bmHeight,// Height of the dest. and source rectangle
hDCMem, 0, 0, SRCCOPY)) {
DeleteDC(hDCMem);
}
RECT rt;
GetClientRect(hWnd, &rt);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL InitSplashInstance(HINSTAN
//
imgHandle = (HBITMAP)LoadImage(NULL,"s
if (!imgHandle) {
return FALSE;
}
GetObject(imgHandle, sizeof(BITMAP), &gBitMap);
hSplashInst = hSplashInstance; // Store instance handle in our global variable
hSplashWnd = CreateWindowEx(WS_EX_CLIEN
WS_EX_WINDOWEDGE, "SplashClass", NULL, WS_POPUP,
(GetSystemMetrics(SM_CXSCR
(GetSystemMetrics(SM_CYSCR
gBitMap.bmWidth, gBitMap.bmHeight,
NULL, NULL, hSplashInstance, NULL);
if (!hSplashWnd) {
return FALSE;
}
ShowWindow(hSplashWnd, nCmdShow);
UpdateWindow(hSplashWnd);
return TRUE;
}
ATOM SplashRegisterClass(HINSTA
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)SplashProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hSplashInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "SplashClass";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
int retval;
// Create and display a SPLASH SCREEN
SplashRegisterClass(hSplas
if(!InitSplashInstance(hSp
return FALSE;
}
Sleep(2000);
DestroyWindow(hSplashWnd);
retval = MessageBox(NULL, "test message", "Diagnostics", MB_APPLMODAL|MB_ICONSTOP|M
Sleep(2000);
return(0);
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
alexo.
Thanks for that answer, it certainly answered the first part of my question.
As for the second part, do you have any idea how I can get the program to repaint my splash screen when it is un-hidden?
Thanks for that answer, it certainly answered the first part of my question.
As for the second part, do you have any idea how I can get the program to repaint my splash screen when it is un-hidden?
>> As for the second part [...]
Sorry, missed it.
Sleep(2000) is your problem. While the thread is asleep, no message processing takes place. Use a timer instead (SetTimer(), WM_TIMER and friends).
Sorry, missed it.
Sleep(2000) is your problem. While the thread is asleep, no message processing takes place. Use a timer instead (SetTimer(), WM_TIMER and friends).
Alex, it is a bigger problem than that. He also needs a message loop for the splash screen. Currently he displays the window, initializes the program, and destroys the window in a stream. That is typical for splash windows, but it does make them rather unreactive. To make it more reactive, you may need to start a 2nd thread for the splash window and provide it with a message loop.
>> He also needs a message loop for the splash screen
Right. Where are my glasses? :-)
>> To make it more reactive, you may need to start a 2nd thread for the splash window
Why a second thread? Using a timer should be easier.
Right. Where are my glasses? :-)
>> To make it more reactive, you may need to start a 2nd thread for the splash window
Why a second thread? Using a timer should be easier.
I was thinking a second thread that could handle its window messages why the 1st thread does its initialization and then destroys the splash window and thread. However, I think I might need to clean my glasses as there is no evidence of any initialization going on as the splash window is displayed.
ASKER
The sleep(2000) is to emulate my own (real) code which carries out several seconds of initialisation. I suspect that a second thread may be the only solution here since there will be no messages processed while I carry out my initialisation. Indeed I don't have a message loop in my (real) program at all since I don't (at least until now) need one!
icd, you *should* have a message pump in your program for it to behave in a manner consistent with windows guidelines. One example is DDE - if *any* running app is not processing messages, all DDE is blocked during this time.
And the autograder hits again!
Did it just get autograded? That is not 21 days. Is there a Y2K-1 problem?
Maybe EE changed the timeout?
ASKER