-
creating a child window
I am learning Windows API programming and I have a question about creating a child window. I would like to set it so that I can right click on the parent window and have the child window popup. How do I do this? This is my code so far...
Code:
#include <windows.h>
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); //Windows procedure
char szClassName[ ] = "Main Window"; //main window class name
char szClassName2[ ] = "Child Window";//child window class name
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd, hwnd2; //message handle for window
MSG messages; //messages saved here
WNDCLASSEX mainWindow, childWindow;//declare
//the parent window
mainWindow.hInstance = hThisInstance;
mainWindow.lpszClassName = szClassName;
mainWindow.lpfnWndProc = WindowProcedure; //function called by windows
mainWindow.style = CS_DBLCLKS; //registers double-clicks
mainWindow.cbSize = sizeof (WNDCLASSEX);
mainWindow.hIcon = LoadIcon (NULL, IDI_APPLICATION);
mainWindow.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
mainWindow.hCursor = LoadCursor (NULL, IDC_ARROW);
mainWindow.lpszMenuName = NULL;
mainWindow.cbClsExtra = 0;
mainWindow.cbWndExtra = 0;
mainWindow.hbrBackground = (HBRUSH) COLOR_BACKGROUND; //background color
if (!RegisterClassEx (&mainWindow)) //register the window class
return 0; //quit if failure
//the child window
childWindow.hInstance = hThisInstance;
childWindow.lpszClassName = szClassName2;
childWindow.lpfnWndProc = WindowProcedure;
childWindow.style = CS_DBLCLKS;
childWindow.cbSize = sizeof (WNDCLASSEX);
childWindow.hIcon = LoadIcon (NULL, IDI_APPLICATION);
childWindow.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
childWindow.hCursor = LoadCursor (NULL, IDC_ARROW);
childWindow.lpszMenuName = NULL;
childWindow.cbClsExtra = 0;
childWindow.cbWndExtra = 0;
childWindow.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&childWindow)) //register the window class
return 0; //quit if failure
hwnd = CreateWindowEx ( //create main window
0,
szClassName, //class name
"Main Window", //title
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, //windows decides position
CW_USEDEFAULT, //windows decides position
200,
550,
HWND_DESKTOP, //child to desktop
NULL,
hThisInstance, //program instance handler
NULL
);
ShowWindow (hwnd, nFunsterStil); //show main window
while (GetMessage (&messages, NULL, 0, 0)){//run until get message returns 0
TranslateMessage(&messages);
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
//This function called by DispatchMessage();
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_RBUTTONDOWN:
hwnd2 = CreateWindowEx ( //create main window
0,
szClassName, //class name
"Main Window", //title
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, //windows decides position
CW_USEDEFAULT, //windows decides position
200,
550,
hwnd, //child to parent window
NULL,
hThisInstance, //error here
NULL
);
break;
case WM_DESTROY:
PostQuitMessage (0); // send a WM_QUIT to the message queue
break;
default: //for messages that we don't deal with
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}//end WindowProcedure
I know that I'm supposed to have the message loop handle the message WM_RBUTTONDOWN. I'm guessing I use it to call CreateWindowEx()? When I do this my CreateWindowEx gets an error saying hThisInstance and hwnd2 are undeclared. What am I doing wrong?
-
Variable scope. Here's an example:
Code:
int global_var = 0; // This variable is global, can be seen by all.
int function_one()
{
int var1 = 0; // var1 is only valid for function_one() - nobody else can see it.
int var2 = 6;
global_var = 5; // Legal. global_var is "in scope".
}
int function_two()
{
int var2 = 5; // Legal, but this is not the same variable as the first var2.
// It is unique to this function, just like var1 is to function_one(). (Despite sharing a name.)
var1 = 6; // Illegal. var1 has not been declared in this scope.
}
Google for more on variable scope. You need the variable to be in scope, essentially. You can either make it global (declare it outside a function), but most people tend to frown on too many global variables. (And in this situation, it might get confusing.)
You're not required to save the return value of CreateWindow(Ex), and you may not really want to. So merely removing hwnd2 will help you. As for hThisInstance, again, you can make it global, or you can pull it from the window. (Replace it with: (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE) and it should work - read the manual on what that function does.)
Also note than once your code compiles, your "child" window will be the same class as your parent: It will look the same, and more importantly, will have the same window procedure, and hence act the same. Hence right clicking the child would open up a "grandchild" per se.
Edit: You might want to read this about nFunsterStil. (Variable name doesn't matter, but an English translation might make more sense.)
-
Thanks Cactus_Hugger
I do know about global and local scope (sry to sound like a complete C++ newb), I wasn't sure if it was good form to declare my handles as global variables since I am completely new to Windows API.
I see in the MSDN help files that GWL_HINSTANCE retrieves the handle to the application instance. Is this equal to hThisInstance? Also why is (HINSTANCE) in parenthesizes?