my main app window is not painting properly

I used CreateWindowEx to create the window with these constants:
WS_EX_COMPOSITED, and (WS_POPUP|WS_SYSMENU|WS_MINIMIZEBOX)

I registered the window class and in the main window proc I handle the WM_PAINT message.

The program works perfectly fine until it is minimized or another window covers all/part of the window. When the window is restored from the taskbar, or the window covering it is moved/unselected, my window never reappears! It was my understanding that a WM_PAINT message is sent to the windowproc when it is restored or another window invalidates part of it. I know that the window is still there on the screen, because when I mouseover the area where a button would be if you could see the window the window reappears and continues functioning perfectly normally until it is minimized/covered again.

ALSO: the other phenomenon that I wasn't understanding is when I minimize the window, then restore it it doesn't show up of course... but then if I press ctrl+alt+delete and get taskmanager, it magically reappears... so what does taskmanager do to my window that causes the phenonmenon to go away?

edit: i have tried creating the same window using different constants, and am still experiencing the same problem, but also still have no idea what the problem could be.
Last edited on
Here's some random simple things to try:
* make sure you don't have the CS_OWNDC or CS_CLASSDC styles set.
* try setting CS_HREDRAW and CS_VREDRAW.
* try or'ing with another extended style like WS_EX_OVERLAPPEDWINDOW
- it has only CS_GLOBALCLASS set
- no effect
- no effect

if it helps at all, using a window style other than WS_EX_COMPOSITED will cause the window to show, but only the background, as registered in the window class is shown, which is especially a problem because I bitblt a bitmap as the content of the window, so there is no menu/subwindows, just graphics.
Last edited on
Can't you just post the code??
Registering the class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    WindowC::wc.hInstance = GetModuleHandle(NULL);
    WindowC::wc.style = CS_GLOBALCLASS;
    WindowC::wc.hIcon = NULL;
    WindowC::wc.hIconSm = NULL;
    WindowC::wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    WindowC::wc.lpszMenuName = NULL;
    WindowC::wc.hbrBackground = (HBRUSH)CreateSolidBrush( RGB( 0, 0, 0 ) );
    WindowC::wc.lpszClassName = TEXT("WindowCClass");
    WindowC::wc.lpfnWndProc = WindowCProc;
    WindowC::wc.cbClsExtra = 0;
    WindowC::wc.cbWndExtra = sizeof( WINDOWCDATA* );
    WindowC::wc.cbSize = sizeof( WNDCLASSEX );
    if( !RegisterClassEx( &(WindowC::wc) ) )
    {
        if( GetLastError() != 1410 )
        {
            g_wflog << STRLASTERROR;
            success = false;
        }
        if( GetLastError() == 1410 )
        {
            g_wflog << "Previously registered WindowCClass.";
        }
	}
	else if( success ){ g_wflog << "Registered WindowCClass."; }


Creating the window:
1
2
3
4
5
if( Main->create( "Survey Statistics", HWND_DESKTOP, x, y, xSize, ySize, 
            true, WS_EX_COMPOSITED | WS_EX_LAYERED, ( WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX ) ) )
        {
	        GUILog << "Main window created.";
        }


The code executed in the 'Main->create()' function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
this->handle = CreateWindowEx(
       ws_ex,
       TEXT("WindowCClass"),
       name,
	ws,
       xPos,
       yPos,
       width,
       height,
       parent,
       NULL,
       GetModuleHandle(NULL),
       NULL
       );

then some error checking.


if you notice in the create function, I now have the WS_EX_LAYERED style... for some weird reason this seems to completely fix the problem. it's only a small detail, but adding that style also seems to block the minimize animation when minimizing the window... which bothers me. So I would either like to figure out how to make the animation show, or make the window work without that style. any help would be appreciated. thank you all!

here is what layered windows (and thus the WS_EX_LAYERED) style is all about.
http://msdn.microsoft.com/en-us/library/ms997507.aspx

If you have the full code instead of the bits you've posted, I'd like to play around with it.

Have you tried it without the CS_GLOBALCLASS style (and without LAYERED)?
I've used layered windows before, and I actually may end up keeping it for fades in this project, but I am curious why that particular window style fixes the phenomenon I was experiencing, and causes the minimize animation not to be shown.

The problem with full code is that it is split between my DLL and the main app and some of it is part of a class hierarchy so it's difficult to use part of it but not all; but I'll see if I can get enough of it together.
thank you Hammurabi, but I have the same problem when I do that, so It doesn't appear to be the CS_GLOBALCLASS.
Have you tried adding the WS_CAPTION style,

WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX

How about just

WS_OVERLAPPEDWINDOW
The problem with those is that the window is a purely graphical interface, and so I draw my own minimize/exit button controls and don't want the border/title bar on the window as it doesn't need to move, and the system menu can be accessed from the start bar. the only way I have found to avoid getting the border or title bar is to use the WS_POPUP style.

Losing the minimize animation is only a small detail that I am not worried about right now, I can use the WS_EX_LAYERED style for now to solve the problem, and see if I can get the animation back later. The animation problem is not a functionality problem, so I will mark this thread as solved for now because the original problem is taken care of. If anyone does have any new information though, I'm still interested.
You've probably lost the minimize animation because you don't have a title bar. It might be possible to change the window style to have a title bar upon the user hitting minimize. Then when the window is restored, remove the title bar. Kind of a strange idea, but it might be the only way to "fix" the missing animation.

Below is a piece of code that may be related to your original problem, or it might be a different problem. When I use an extended style of 0 it works. But if I use the COMPOSITED style, the MOUSEMOVE event stops drawing dots to the window, but the PAINT event still draws a line. Adding LAYERED doesn't fix it. LAYERED alone doesn't even display the window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <windows.h>

#define WINDOW_POS_X   0
#define WINDOW_POS_Y   0
#define CLIENT_SIZE_X  400
#define CLIENT_SIZE_Y  300

LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) {
    switch( msg ) {
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint( hwnd, &ps );
            MoveToEx( hdc, 0, 0, NULL );
            LineTo( hdc, CLIENT_SIZE_X, CLIENT_SIZE_Y );
            EndPaint( hwnd, &ps );
            break;
        }
        case WM_MOUSEMOVE: {
            HDC hdc = GetDC( hwnd );
            SetPixelV( hdc, LOWORD( lp ), HIWORD( lp ), RGB( 0, 0, 0 ));
            ReleaseDC( hwnd, hdc );
            break;
        }
        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;
        default:
            return DefWindowProc( hwnd, msg, wp, lp );
    }
    return 0;
}

void registerWindow( HINSTANCE hinst, char *className,
                     WNDPROC wndproc, HBRUSH hbr, BOOL dblClicks ) {
    WNDCLASSEX wc    = { sizeof( wc )}; // set first member, zero the rest
    wc.style         = CS_HREDRAW | CS_VREDRAW | (dblClicks?CS_DBLCLKS:0);
    wc.hInstance     = hinst;
    wc.lpszClassName = className;
    wc.lpfnWndProc   = wndproc;
    wc.hbrBackground = hbr;
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hIcon         = LoadIcon( NULL, IDI_APPLICATION );
    wc.hIconSm       = LoadIcon( NULL, IDI_APPLICATION );
    if( !RegisterClassEx( &wc )) {
        MessageBox( 0, "RegisterClassEx failed", 0, 0 );
        exit( 1 );
    }
}

HWND createWindow( DWORD exStyle,
                   char* className, char* windowName,
                   DWORD style,
                   int x, int y, int clientWidth, int clientHeight,
                   HWND hwndParent, HMENU hMenu, HINSTANCE hInst ) {
    RECT r = { 0, 0, clientWidth, clientHeight };
    AdjustWindowRect( &r, style, hMenu?TRUE:FALSE );
    HWND hwnd = CreateWindowEx( exStyle,
        className, windowName, style | WS_VISIBLE,
        x, y, r.right - r.left, r.bottom - r.top,
        hwndParent, hMenu, hInst, NULL );
    if( !hwnd ) {
        MessageBox( 0, "CreateWindowEx failed", 0, 0 );
        exit( 1 );
    }
    return hwnd;
}

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE unused,
                    PSTR cmd, int show) {
    char *appName = "App";
    MSG msg;

    registerWindow( hInst, appName, WindowProc,
                    (HBRUSH) GetStockObject( WHITE_BRUSH ), FALSE );
    createWindow(
        0
//        | WS_EX_COMPOSITED
//        | WS_EX_LAYERED
        ,
        appName, appName,
        WS_OVERLAPPEDWINDOW,
        WINDOW_POS_X, WINDOW_POS_Y, CLIENT_SIZE_X, CLIENT_SIZE_Y,
        HWND_DESKTOP, NULL, hInst );

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

you're right. I don't think the caption style is necessary though, all it seems I have to do is remove the layered style on minimize and handle sc_restore.

and yes, I have realized that although the layered and composited styles seem to be affecting the situation, they are by no means the cause, and probably not the solution.

- one thing that I have discovered... one solution to the problem is to handle the WM_ERASEBKGND message and explicitly update the window on handling this message. this fixes any of the initial problems, however causes other new problems in my application.

- I have tried numerous combinations of window styles... are there any other reasons that anyone can think of that an app wouldn't recieve a WM_PAINT message after recieving an erasebkgnd message? That seems to be the problem; no paint message after the background is erased. That's why the window seemed to disappear.

I will try to post some new code soon. thank you for the help!
From MSDN on WM_ERASEBKGND:
An application should return nonzero if it erases the background; otherwise, it should return zero.
It sounds like you should return non-zero (as opposed to zero like most messages). But if you are already returning non-zero, try zero!
HOORAY!!! ok, so I made a completely new project, and started basically recreating parts of the main one. what I figured out was that the problem seems to stem from a Windows specific quirk. I still have much to learn about the Windows API and it appears my mistake was having two parent windows pulling from the same message pump in a single thread. as soon as I made one of them a child of the other window, it seems to work perfectly now.

QUESTION: I did not think that it was a problem to have more than one window pulling from a message pump in the same thread since messages are sent with a specific window identifier... Is there a trick to doing this, or should each parent window have it's own message pump?

Thank you, I appreciate the time and help you have contributed!
Last edited on
Topic archived. No new replies allowed.