• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
MatsVed

Creating a child window?

18 posts in this topic

I'm creating an installer in C++ (or at least I'm trying to...) I messed around a bit to get the standard Win32 application to display a bitmap on the main window. Now I'd like a child window on top of the main window that is borderless! I couldn't actually find any examples of this on Google Image Search, so I made a mockup: ; This is what my InitInstance() function looks like:
//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   HWND ChildWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   ChildWnd = CreateWindow(szChldWndClass, szTitle, WS_OVERLAPPEDWINDOW,
	   CW_USEDEFAULT, WS_VISIBLE | WS_CHILD | BS_VCENTER | BS_CENTER, 
	   500, 100, NULL, NULL, hInst, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   ShowWindow(ChildWnd, nCmdShow);
   UpdateWindow(hWnd);
   UpdateWindow(ChildWnd);

   return TRUE;
}


The child window still doesn't display! Why is this?
0

Share this post


Link to post
Share on other sites
You need to define the parent in CreateWindowEx if you want to make it a real child window


ChildWnd = CreateWindow(szChldWndClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, WS_VISIBLE | WS_CHILD | BS_VCENTER | BS_CENTER,
500, 100, hWnd /* Parent Parameter */, NULL, hInst, NULL);


0

Share this post


Link to post
Share on other sites
You have
ChildWnd = CreateWindow(szChldWndClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, WS_VISIBLE | WS_CHILD | BS_VCENTER | BS_CENTER,
500, 100, NULL, NULL, hInst, NULL);
You want
ChildWnd = CreateWindow(szChldWndClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CHILD | BS_VCENTER | BS_CENTER,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100, NULL, NULL, hInst, NULL);
I question the BS_VCENTER and BS_CENTER styles though...
[edit] Plus you want to include the parent hWnd as Rattrap specified of course
[edit again] Plus WS_OVERLAPPEDWINDOW will give you a border ... but get the thing to display first and then mess with the styles I'd say.
0

Share this post


Link to post
Share on other sites
Thanks again!
Still doesn't display...

Should I call BeginPaint() on the childwindow? And where should I call it?
0

Share this post


Link to post
Share on other sites
Also, when you create your main window:
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

In order you have
CW_USEDEFAULT, // x pos
0, // y pos
CW_USEDEFAULT, // width
0, // height
So you create your parent window with a height of 0. Nothing will display, and your button/editbox/whatever child window you are making of course won't display because there is no parent window to display.
try CW_USEDEFAULT, CW_USEDEFAULT, 600, 200
or something since your child window is 500x100 and needs to fit inside it.

Note that CW_USEDEFAULT will pretty much plop the window anywhere, and the child. If you know where you want them, specify.
0

Share this post


Link to post
Share on other sites
You might want to use CreateWindowEx instead of the CreateWindow macro, so that you can specify WS_EX_TRANSPARENT, which might be necessary to achieve the effect shown in your mock up.

Also, and probably more importantly, you need to specify an identifier for the window in the hMenu parameter.

Quote:

hMenu
[in] Handle to a menu, or specifies a child-window identifier, depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.


Identifiers are usually #define[d] in the resource header.
0

Share this post


Link to post
Share on other sites
I am not sure exactly what you are trying to achieve.
You want a see through Box where you can display Text. Is that it?
WS_EX_TRANSPARENT should do the Trick.
The only Alternative, which requires a bit of Work, is creating a normal Child Window and then during WM_PAINT, send a Message to the Parent to request it to paint itself in the Child's Device Context, then the Child paints on top of that. This second Option would give you also the possibility of Alphablending.
Which is a very nice Effect.
0

Share this post


Link to post
Share on other sites
You're probably drawing over the top of your child window. Try adding WS_CLIPCHILDREN to the parent. In addition to what popsoftheyear and rattrap said.
0

Share this post


Link to post
Share on other sites
I don't want my child window to be transparent!
I just want it to be like a normal window, but without a border!

I already created an ID... I had to, to be able to call LoadString() in the beginning;

	// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_INSTALLER, szWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDC_INSTALLER_CHLD, szChldWndClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);






I added the ID to the hMenu param, and used WS_CLIPCHILDREN on the parent:

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
HWND ChildWnd;

hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
ChildWnd = CreateWindow(szChldWndClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE |
WS_CHILD | BS_VCENTER | BS_CENTER, CW_USEDEFAULT, CW_USEDEFAULT,
500, 100, hWnd, (HMENU)IDC_INSTALLER_CHLD, hInst, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
ShowWindow(ChildWnd, nCmdShow);
UpdateWindow(hWnd);
UpdateWindow(ChildWnd);

return TRUE;
}





The child window still isn't displaying!

Edit:

This is how I'd like the child window to be, without the image and the border:

0

Share this post


Link to post
Share on other sites
Your main window is being created with a height of 0, thus it doesn't really exist, so there is no where for the child window to go since it's parent isn't even there. Read my most recent post that explains why and what to do. Then, check all your parameters for CreateWindow and figure out if you did everything you meant to.

My recommendation? Comment out code for the child control, and get your parent window to display first. No sense in trying to get the child control to display if you can't get the parent first.
0

Share this post


Link to post
Share on other sites
Uhm, what?
The parent window is in the first post! It's been displayed all along!

Edit: Don't ask me how it's displayed with a height of 0, but it's there!
0

Share this post


Link to post
Share on other sites
Your (revised) code works for me.

You aren't checking for errors in the second CreateWindow call. I suspect CreateWindow is failing and you're getting back NULL for ChildWnd. If that's true then 99% of the time it's failing because you've screwed up your WndProc, does the WndProc for the child window ever get called?

It could also be something like you forgot to register your szChldWndClass or for some reason RegisterClass[Ex] is failing. Just for testing purposes I would recommend you try one of the built-in window classes (e.g. "EDIT" rather than szChldWndClass) and see if that works.

Some more nitpicking for whenever you get it figured out:

You say you want the child to be borderless but you're specifying WS_OVERLAPPEDWINDOW.

BS_* styles apply to the built-in BUTTON window class yet it looks very much like you're using a custom window class for your child.

Calling ShowWindow on the child window with nCmdShow is just plain wierd.

Calling UpdateWindow is (very likely) completely unnecessary.

You really need to read the docs about for CreateWindow, the large number of minor errors you're making make me suspect you're just cut&pasting code.
0

Share this post


Link to post
Share on other sites
I did read the docs about CreateWindow(), but it doesn't seem to explain anything about creating child windows?
I've been Googling around for tutorials on this topic, but there really isn't much information available, so I've had to guesstimate which functions to call and where.

How do I call RegisterClassEx() for the child window?!
The only time it's being called at present is after initializing the global strings;

	// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_INSTALLER, szWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDC_INSTALLER_CHLD, szChldWndClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);


This is what MyRegisterClass looks like:

//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INSTALLER));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_INSTALLER);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}



Anyways, I added a function called EnumChildProc() that is supposed to (I think) redraw any child windows when the parent window has changed size. I found it in this article.

BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam) 
{
LPRECT rcParent;
int i, idChild;

// Retrieve the child-window identifier. Use it to set the
// position of the child window.

idChild = GetWindowLong(hwndChild, GWL_ID);

if (idChild == IDC_INSTALLER_CHLD)
i = 0;
else
i = 2;

// Size and position the child window.

rcParent = (LPRECT) lParam;
MoveWindow(hwndChild,
(rcParent->right / 3) * i,
0,
rcParent->right / 3,
rcParent->bottom,
TRUE);

// Make sure the child window is visible.

ShowWindow(hwndChild, SW_SHOW);

return TRUE;
}


I'm calling it from my WndProc() like so:

	case WM_SIZE: //main window changed size 
// Get the dimensions of the main window's client
// area, and enumerate the child windows. Pass the
// dimensions to the child windows during enumeration.
GetClientRect(hWnd, &rcClient);
EnumChildWindows(hWnd, EnumChildProc, (LPARAM) &rcClient);
return 0;


It doesn't seem to have helped anything though...

I am at a loss as to what to do at this point! :(
0

Share this post


Link to post
Share on other sites
Focus on getting the window up and running before worrying about the style or about repainting it after the parent window has been resized.
0

Share this post


Link to post
Share on other sites
The following are instructions for creating a custom child window that I posted in an old thread. I'm calling it "FrameWindow" because the OP in that thread wanted to use it as a Win32 parent for other child controls, but call it whatever you want.
Quote:

1.) Register your custom frame class. Write something like the following and then call it when your app starts up:

void RegisterMyFrameClass(HINSTANCE app_instance) {
WNDCLASSEX wndclass;
ZeroMemory(&wndclass, sizeof (wndclass));
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MyFrameWindowProc;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = app_instance;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = "MyFrameClass";
wndclass.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wndclass);
}

2.) Write a barebones window procedure like the following. You could actually just use DefWindowProc in the wndclass above, but you may find that you want the frame to do something and you'll have to add this later anyway.

LRESULT MyFrameWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
return DefWindowProc(hwnd, msg, wparam, lparam);
}

3.) Create a frame by calling a function like this:

HWND CreateFrameWindow(HWND parent, int id, HINSTANCE app_inst,
int x, int y, int wd, int hgt) {
return CreateWindowEx(0, "MyFrameClass", "", WS_CHILD|WS_VISIBLE,
x, y, wd, hgt, parent, (HMENU)id, app_inst, NULL);
}

4.) When you create your controls use the hwnd of your frame as their parent.

Just do this in your program, put a break point in the MyFrameWindowProc, and if execution hits the break point you've created a child window.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0