Click here to Skip to main content
15,889,867 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a main window which has a child window which in turn have a child window and a button. When i restore the window from taskbar the button and third child window refuse to display. I tried using RedrawWindow() on the child first, and then the grand child and the button but didnt work. So far it looks like there is no connection between the child window and its child cos the parent is responsible for repainting its child, but the child has no duty. How do i repaint child window's controls / child window (child of a child), during parent (main window) repaint. That is after restore of parent using Win32 API.

I created a control class as the entry point of the app and to oversee all other classes(Screen class- for GUI, Database class...), the Screen class have all the child creation codes in it. This is how:

C++
//MainControl Class

#include <tchar.h>
#include "Screen.h"
#include <stdlib.h>
#include "FreeImage.h"
#pragma comment(lib, "user32")
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"FreeImage.lib")




const char g_szClassName[] = "myWindowClass";
Screen display;
HWND welcomScreenHndl, menuScreenHndl, butt;

// Function prototypes
LRESULT CALLBACK WndProc(HWND hwnd, UINT messages, WPARAM wParam, LPARAM lParam);




int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
					int nCmdShow){
	
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;
	
	// Registering the Window Class.
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = 0;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

	
	if(!RegisterClassEx(&wc)){
		MessageBox(NULL, "Window Registration Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
	
	// Creating the Window.
	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName,
		"Prison Management System",
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN,
        100, 30, 750, 700, NULL, NULL, hInstance, NULL);
	
	if(hwnd == NULL){
		MessageBox(NULL, "Window Creation Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
	
	
	// Creating Other Windows with Scree class object.
	welcomScreenHndl = display.welcomeScreen(hwnd, hInstance);//Child to Main Window
	menuScreenHndl = display.menuScreen(welcomScreenHndl, hInstance);//grand child
	
	
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	// The message loop.
	while(GetMessage(&Msg, NULL, 0, 0) > 0){
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}


Here is the Screen class:  // Screen Class

#include <tchar.h>
#include <windows.h>



class Screen{
	
	char winClassName[20];
public:
	
	HWND welcomeScreen(HWND parent, HINSTANCE hInstance);
	HWND menuScreen(HWND parent, HINSTANCE hInstance);
	
};



HWND Screen::welcomeScreen(HWND parent, HINSTANCE hInstance){
	
		GetClassName(parent, winClassName, 20);
		
		HWND hwndpan = CreateWindowEx( WS_EX_CLIENTEDGE,
				winClassName,
				"",
				WS_CHILD | WS_VISIBLE | CS_HREDRAW | CS_VREDRAW,
				0, 20, 745, 695,
				parent, NULL, hInstance/*GetModuleHandle(NULL)*/, NULL);
				
		
		return hwndpan;
	}
	
	HWND Screen::menuScreen(HWND parent, HINSTANCE hInstance){
	
		HWND hwndpan = CreateWindowEx( WS_EX_CLIENTEDGE,
				winClassName,
				"",
				WS_CHILD | WS_VISIBLE | CS_HREDRAW | CS_VREDRAW,
				0, 100, 745, 695,
				parent, NULL, hInstance/*GetModuleHandle(NULL)*/, NULL);
		
		return hwndpan;
	}
Posted
Updated 9-Jan-14 20:28pm
v2
Comments
AlwaysLearningNewStuff 9-Jan-14 18:39pm    
We really need to see some code. Start with WM_CREATE and WM_PAINT. Here is the subclassing example I have described earlier: http://pastebin.com/Pmis9VQx. Just create default Win32 project in Visual Studio and modify the code in your main .cpp file with mine. Hopefully it will help you to find out what is wrong with your code. Without seeing your code there is nothing else anyone can do. Good luck and best regards.
enhzflep 10-Jan-14 2:58am    
Never had a problem repainting child controls myself, with the exception of something else entirely unrelated.

It seems to me that the likely source of your problem is the way you've re-used a window-class. I see that you've got three windows - all of them the same type of window (myWindowClass). This is unusual in my experience.

I'd expect to normally see either a dialog or a window with an accompanying window-class definition. This is what you have. I would then expect to see other controls of a different window-class. Perhaps a group-box with child static-controls.

Unless of course, you wish for the main application window to exhibit the same exact behaviour as the welcomeScreen and the menuScreen. (Which I can imagine a reason for, nor have any recollection of having seen) Even their name suggests to me that they'll have very different behaviour and should each have their own window-class, complete with their own WindowProc.


I also note that, (a) you give neither the menuScreen or the welcomeScreen an id (b) that you don't store their HWND anywhere. This will make later interaction with these windows rather tough.
The usual way is to use an integer as the HMENU property (cast to a HMENU). Naturally, since you're using a class to create the windows, it would likely make more sense to create a copy of the window handles as they're created.
Tonex247 10-Jan-14 9:31am    
I've tried alot of ways but so long as it is specified to be a child of a child (grand child) it gives the same problem. As for ID, thats not a problem, as soon as I get this working, every other thing goes in smoothly. And Thanks for your effort.
AlwaysLearningNewStuff 10-Jan-14 4:25am    
I really wish to help, but your design is not understandable to me.

It seems that you wanted to create main window, then show "welcome window", and then show menu.

If your project is not commercial/copyright protected, can you upload it somewhere so we can have a look?

You can remove the irrelevant parts, just upload a sample project that illustrates the problem.

I will keep following this post in order to try to help, but at this moment I see no solution-maybe we can find the error in your project if we see the code, since I doubt that you can post the entire code here.

Also, I have spotted a mistake-CS_HREDRAW | CS_VREDRAW do not belong in the call to CreateWindowEx. The very least you can do is removing them-hopefully that fixes your problem, but I doubt. Most likely the design of your UI/usage of the class is the problem.

Best regards.

I have tried to open CLASS FILEs with NetBeans but have failed.

Notepad and Word didn't help either. However, seeing your application "in action" seems to made things clear to me.

Let me just confirm this:

In your JAVA program, class welcomeScreen is the login window, and menuScreen window is the panel that has buttons from the left and a picture of the hand-cuffs on the right?

If that is so, then total approach is "not the usual one" to say the least. It will lead to great complications in the future, even if you manage to solve this problem somehow.

This is the concept I suggest to you:

1. Create main window.

2. In it create ALL the controls you need ( you do this in the main window's window procedure in the WM_CREATE handler ).

3. Using ShowWindow API show the login and exit button, other buttons hide ( again, you do this in WM_CREATE handler ).

4. Pictures, orange lines and text in your JAVA application's main window can be drawn with the use of GDI, with a BitBlt API, and you should do that in your WM_PAINT handler. However, I would use static controls with SS_BITMAP to display pictures, and simply hide/show them in WM_CREATE handler, showing them later on when necessary. In both cases you will have to convert your JPEG images to BMP, unless you wish to use GDI+ which is fine too.

5. For message boxes in your JAVA application ( like View Prisoner option ), I would create dialog boxes. For simple messages ( information/errors ), use MessageBox API. Dialog boxes are made with resource editor and it should come with your IDE, but just in case here is the free one:
http://www.resedit.net/[^]

6. Events, such as button clicks are handled in WM_COMMAND handler, from where you can launch dialog boxes you want.

7. As for database communication, ADO.NET could be useful, but maybe you should ask someone more experienced than me for an advice about that.

Since you are starting out ( I made this assumption based on your previous comments ), I would like to suggest you a simple and effective WIN32 tutorial:

http://www.winprog.org/tutorial/[^]

Download both source code and PDF!

Going through it should teach you enough so you can translate most of your existing application to C++.

After you go through it, browsing through MSDN documentation will help you do the rest ( mostly for your JPEG images, the rest you can figure out from the tutorial ).

I suggest you to first go through the entire tutorial, and then to implement the design I have suggested, or the way you suit best.

If you get stuck you can always ask another question here. You can also leave me a comment and I will try to help you as much as I can.

I know that this is not the answer you have expected, but I believe that this approach will be much better than the one you have chose.

Hopefully this answer will help you.

Wish you best of luck.

Best regards.
 
Share this answer
 
Comments
Tonex247 11-Jan-14 6:07am    
You are wonderful, Thanks. I think you understand my JAVA app. perfectly, but the problem in the C++ is that in JAVA we have JPanenl which is a container that carries buttons and other controls, and this container is usually fit into the client area of the main window. this container can also contain other containers(like the ones with orange border on the menuScreen of my JAVA app), this containers can then contain buttons... But in C++, the first container(Child window) refused to display the second container(grand child window) on restore of the main window. It seems that the parent window takes care of the repaint of its child automatically, but the child cannot repaint its child. I've tried alot of ways to do this including sending paint messages to each window, redraw... but didn't work. I'm try to trace how and when the repaint message is send to the main window so i can try forwarding it if possible. And, as for every other part, including image painting with GDI, i have taken care of that. And as for beginners tutorials, i've done that including Petzol and many others about a year ago. Once again Thank you for your help so far
AlwaysLearningNewStuff 11-Jan-14 6:34am    
In JAVA you have panels, but here the approach is different. You have one "main panel" that contains controls. You do not need 2 more windows to have your menu and welcome picture, you need to jump directly to the creation of the controls on that "panel". If I remember well, in JAVA you can make main panel, then put sub panel with buttons in it, and put another panel with the picture as well. In Win32 things are slightly different-you create main window that acts as panel, then you add controls you just need to display them properly via ShowWindow API-there is no need for addition of other windows-you work with one "panel" only. If it is not a problem for you, try to post your current C++ project so we can have a look, your class implementation is unusual and I can not come up with another solution right now. Best regards.
Tonex247 11-Jan-14 10:35am    
Looks like a dead end here! The concept is that when i click the login button i want the welcome screen window with its controls to disappear and the login window with its controls shown. I just cant call ShowWindow() for every control on the welcomeScreen window and on the login Screen window. Since when a window is hidden its children are hidden with it, it becomes easy to call ShowWindow() on the child window which contains the welcome screen controls, and call it again on the login child window. I just hope its not a dead end this time.
AlwaysLearningNewStuff 11-Jan-14 10:42am    
The concept of creating windows to serve you as panels is the faulty one in my opinion. I strongly encourage you to upload your C++ code with your GUI code only. Without seeing how you create "panels" and how your controls interact there is nothing else I or anyone else can do, I fear. Best regards.
I had a quick look and play around the other night.

Perhaps this code will be of some use to you. I've used it to demonstrate (a) checking for the return value of a dialog, before deciding which action to take. (b) open multiple windows, each dialog may then open another dialog or be closed itself.
(c) a way of using DialogBoxParam to pass info to the dialog being created, such that it can be initialized in a particular way.

The main dialog's 3 buttons just open child dialogs or exit the program. The child dialog box I'e used has been designed to have a brownish background. You get one of these when you hit the Login button. This child dialog will then create another copy of itself if you hit OK, or will close itself if you hit close.

As for the 'Test' button, that opens up the same dialog, but passes it info such as the window title and the background colour. Hitting OK on this dialog will open up another of the 'default' dialog boxes - that is to say, the new one will have a brown background.

You can easily (a) convert the images to BMP format and use LoadImage or (b) use GDI+ to open jpg/png images by filling a Gdiplus::Bitmap object from a disk file. You can use the following function to load anything natively supported by windows. Just don't forget to initialize Gdi+ before you call it!

C++
// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP mLoadImageFile(wchar_t *filename)
{
    HBITMAP result = NULL;
    Bitmap bitmap(filename, false);
    bitmap.GetHBITMAP(0, &result);
    return result;
}


Anyway, that's enough chatter. Here's the code. If you've any questions, feel free to ask.

main.cpp
C++
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"

HINSTANCE hInst;

typedef struct DLGDATA
{
    wchar_t *windowText;
    COLORREF bkgCol;
} *pDlGDATA;

BOOL CALLBACK LoginDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_INITDIALOG:
    {
        HBRUSH bkBrush;
        pDlGDATA refData;
        refData = (pDlGDATA)lParam;
        if (refData != NULL)
        {
            bkBrush = CreateSolidBrush( refData->bkgCol );
            SetProp(hwndDlg, "bkBrush", (HANDLE)bkBrush);
            SetWindowTextW(hwndDlg, refData->windowText );
        }
        else
        {
            bkBrush = CreateSolidBrush( RGB(137, 48, 14) );
            SetProp(hwndDlg, "bkBrush", (HANDLE)bkBrush);
        }
    }
    return TRUE;

    case WM_NCDESTROY:
        {
            HBRUSH bkBrush;
            bkBrush = (HBRUSH) GetProp(hwndDlg, "bkBrush");
            if (bkBrush)
            {
                DeleteObject(bkBrush);
                RemoveProp(hwndDlg, "bkBrush");
            }
        }
        return 0;

    case WM_CLOSE:
    {
        EndDialog(hwndDlg, 0);
    }
    return TRUE;

    case WM_ERASEBKGND:
        {
            HBRUSH mBrush;
            RECT clientRect;
            GetClientRect(hwndDlg, &clientRect);
            mBrush = (HBRUSH) GetProp(hwndDlg, "bkBrush");
            if (mBrush)
                FillRect( (HDC) wParam, &clientRect, mBrush);
            else
                FillRect( (HDC) wParam, &clientRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
        }
        return 1;

    case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
        case IDOK:
            ShowWindow(hwndDlg, SW_HIDE);
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)LoginDlgProc);
            ShowWindow(hwndDlg, SW_SHOW);
            break;

        case IDCANCEL:
            EndDialog(hwndDlg,-2);
            break;
        }
    }
    return TRUE;
    }
    return FALSE;
}

BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_INITDIALOG:
    {
    }
    return TRUE;

    case WM_CLOSE:
    {
        EndDialog(hwndDlg, 0);
    }
    return TRUE;

    case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
        case IDC_BUTTON1:
            ShowWindow(hwndDlg, SW_HIDE);
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)LoginDlgProc);
            ShowWindow(hwndDlg, SW_SHOW);
            break;

        case IDC_BUTTON2:
            EndDialog(hwndDlg,-2);
            break;

        case IDC_BUTTON3:
            {
                ShowWindow(hwndDlg, SW_HIDE);
                DLGDATA mData;
                mData.bkgCol = RGB(50,200,60);
                mData.windowText = L"lParam-passed data modified dialog";
                DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hwndDlg, (DLGPROC)LoginDlgProc, (LPARAM)&mData );
                ShowWindow(hwndDlg, SW_SHOW);
            }
            break;
        }
    }
    return TRUE;
    }
    return FALSE;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst=hInstance;
    InitCommonControls();
    return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}



resource.h
C++
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define DLG_MAIN                                100
#define IDD_DIALOG1                             101
#define IDC_BUTTON1                             1000
#define IDC_BUTTON2                             1001
#define IDC_BUTTON3                             1002



resource.rc
C++
// Generated by ResEdit 1.5.11
// Copyright (C) 2006-2012
// http://www.resedit.net

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"




//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOG 0, 0, 277, 230
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Prison Management System"
FONT 8, "Ms Shell Dlg"
{
    CONTROL         "", IDC_STATIC, WC_STATIC, SS_BLACKFRAME, 53, 51, 171, 119
    PUSHBUTTON      "Login", IDC_BUTTON1, 53, 189, 50, 14
    PUSHBUTTON      "Exit", IDC_BUTTON2, 174, 189, 50, 14
    LTEXT           "A computerized prison management system", IDC_STATIC, 67, 27, 142, 8, SS_LEFT
    PUSHBUTTON      "Test", IDC_BUTTON3, 113, 193, 50, 14
}



LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG1 DIALOG 0, 0, 186, 95
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Dialog"
FONT 8, "Ms Shell Dlg"
{
    DEFPUSHBUTTON   "OK", IDOK, 129, 7, 50, 14
    PUSHBUTTON      "Cancel", IDCANCEL, 129, 24, 50, 14
}



//
// Manifest resources - used to ensure app has winxp (or newer) theming engine enabled.
//  ResEdit can provide a default manifest for you, as presumably can VS. I won't include it
// sine it's generic info not really related to achieving the aims of the application.
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
1                  RT_MANIFEST    ".\\manifest.xml"
 
Share this answer
 
Comments
AlwaysLearningNewStuff 13-Jan-14 5:12am    
You "stole my thunder"! :)

Seems like a good answer, OP might pull it off with this-let us hope.

I still believe that e should create all the controls in the main window and show them in respond to clicks-that is what his JAVA application was all about.

Still, my +5 for the effort!

Best regards!
enhzflep 13-Jan-14 6:55am    
Oops! Sorry about that.

It's often hard for me to discern just how much to lead someone down the path to a solution. Does one say 'the path is over there', or does one say 'come with me, I'll show you'?

Thanks again, regards. :)
better use InvalidateRect with coordinates, so the system can better redraw it =>
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002(v=vs.85).aspx[^]
 
Share this answer
 
Comments
Tonex247 10-Jan-14 9:00am    
Separating the codes into different classes is really not the problem, i've tried everything in one module and its still the same. I tried using CreateWindow() instead but that was worse, the grand child didn't even appear in the first place. My Project is about prison management system, I've written it fully in JAVA but I was asked to translate to C++. I battled with MFC but that was a headache with its Documents and Views. I figured out WinAPI was easier and better (IMO). I'll try and upload the JAVA app so u can understand what i intend doing. Thanks to you all.
AlwaysLearningNewStuff 10-Jan-14 9:58am    
I will give it a look as soon as I can. A small tip: Update your question by adding the link to your project so everybody can see it. This could help you greatly by increasing your chances of someone actually seeing your code and help you translate it into C++. Until we hear again best regards.
Tonex247 10-Jan-14 9:21am    
After many days of search and trials, i decided to strip the code to minimum then i found the problem. You can make any number of child window level (grand child, great grand child...) and they will display perfectly but once you place a
C++
WM_PAINT
message in the
C++
winProc()
function, the grand children and beyond wont display on restore. So I registered two window classes, one for main window and the other for the child and grand child and did my painting in the child window procedure. I dont know if this is a good way of doing it, but it worked for me. Thanks to you all for the help.
 
Share this answer
 
Comments
AlwaysLearningNewStuff 25-Jan-14 16:36pm    
Your solution is "unusual" to say the least, and I fear that it will lead to numerous complications, but since the program you make is not so complicated you might pull it off your way. I still believe that my way is more efficient, but never mind. If you have further issues leave a comment and I will help again. Best regards.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900