Thread: hwnd and variables in them

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    108

    hwnd and variables in them

    Hey, (im new to this forum, hi all )

    I'm quite accustomed with C programming, but rather new to win32 API. Just recently I started learning it, and although I now have good understanding of how window procedures work, the message queue etc etc, some question which answer is hard to find always comes.

    The question, is how are you supposed to store variables for windows? Say your program consists of many different windows of the same window class, and users can interact with any of them. Of course this means that those windows will have different "states" (for lack of a better word). How do you store them?

    You only have a hwnd (window handle), and if you want multiple windows of the same class, you can't just use a single global variable for it..

    Since hwnd is just an integer (or so I think), I could make a table for it which has pointers to some structures and look up the variables through the table, but it would be inefficient, and it would be much better if we can store the variables (or a pointer to the variables) in the HWND.

    So yeah, can someone enlighten me? Thanks in advance!

  2. #2
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    Simply use arrays, thats a good way of doing it. Before anyone jumps on you for it try to search for stuff on this board to see of other posts answer your question. Here is a sample code I posted on another post that demonstrates having 2 child windows. The handles are stored in an array.

    Code:
    #include <windows.h>
    
    #define numChild 2
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    //children window procedure
    LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM); 
    
    TCHAR szChildClass [] = TEXT("Children"); //Child class name
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    
    	static TCHAR szAppName[] = TEXT("ChildWindowDemo");
    	WNDCLASS wc;
    	MSG msg;
    	HWND hwnd;
    
    	wc.cbClsExtra = 0;
    	wc.cbWndExtra = 0;
    	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	wc.hInstance = hInstance;
    	wc.lpfnWndProc = WndProc;
    	wc.lpszClassName = szAppName;
    	wc.lpszMenuName = NULL;
    	wc.style = CS_HREDRAW | CS_VREDRAW;
    
    	if(!RegisterClass(&wc)) {
    		MessageBox(NULL, TEXT("Could not register class"), szAppName, MB_ICONERROR);
    		return 0;
    	}
    
    	//define and register child window class
    	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    	wc.lpfnWndProc = ChildWndProc;
    	wc.hIcon = NULL;
    	wc.lpszClassName = szChildClass;
    	RegisterClass(&wc);
    	//-------------------------------------
    	
    	hwnd = CreateWindow(szAppName,
    					    TEXT("Child Window Demo"),
    						WS_OVERLAPPEDWINDOW,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						CW_USEDEFAULT,
    						NULL,
    						NULL,
    						hInstance,
    						NULL);
    
    	ShowWindow(hwnd, iCmdShow);
    	UpdateWindow(hwnd);
    
    	while(GetMessage(&msg, NULL, 0, 0)) {
    
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return msg.wParam;
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    
    	static HWND hwndChild[numChild]; //create array to hold children
    	int cxBlock, cyBlock, x;
    
    	switch(message) {
    
    		case WM_CREATE:
    			//create our children
    			for(x = 0; x < numChild; x++) {
    				hwndChild[x] = CreateWindow(szChildClass,
    											NULL,
    											WS_CHILDWINDOW | WS_VISIBLE,
    											0,
    											0,
    											0,
    											0,
    											hwnd,
    											(HMENU)(1 << 8 | x), //child window ID
    											(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
    											NULL);
    			}
    			return 0;
    		case WM_SIZE:
    			//each window will be 1/2 width of parent and = height
    			cxBlock = LOWORD(lParam) / numChild;
    			cyBlock = HIWORD(lParam);
    
    			for(x = 0; x < numChild; x++) {
    				MoveWindow(hwndChild[x],
    						   x * cxBlock,
    						   0,
    						   cxBlock,
    						   cyBlock,
    						   TRUE);
    			}
    			return 0;
    		case WM_DESTROY:
    
    			PostQuitMessage(0);
    			return 0;
    	}
    	return DefWindowProc(hwnd, message, wParam, lParam);
    }
    LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    
    	static int iColor;
    	int bkgColor[4] = {WHITE_BRUSH, LTGRAY_BRUSH, DKGRAY_BRUSH, BLACK_BRUSH};
    
    	switch(message) {
    
    		case WM_CREATE:
    
    			iColor = 0;
    			SetWindowLong(hwnd, 0, 0);
    			return 0;
    		case WM_LBUTTONUP:
    
    			SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(bkgColor[iColor]));
    			InvalidateRect(hwnd, NULL, TRUE);
    			if(!(iColor == 3)) {
    				iColor++;
    			}else {
    				iColor = 0;
    			}
    			return 0;
    	}
    	return DefWindowProc(hwnd, message, wParam, lParam);
    }
    As you can see the same child window procedure is used for both the child windows, its not like you have to worry about iterating through all your windows to do something to them, hence no inefficiency. To prove the point just change numChild to some other number, and you will see the program still acts the same. Windows is message based so it resolves who the messages are going to for you. Hope this helps to answer your question and welcome to the board.

    Happy coding!!
    Last edited by andyhunter; 01-16-2005 at 03:47 AM.
    i don't think most standard compilers support programmers with more than 4 red boxes - Misplaced

    It is my sacred duity to stand in the path of the flood of ignorance and blatant stupidity... - quzah

    Such pointless tricks ceased to be interesting or useful when we came down from the trees and started using higher level languages. - Salem

  3. #3
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    The last parameter to CreateWindowEx enables you to attach a pointer to anything you want to each individual window; this is passed to the windows WM_CREATE handler as the lpCreateParams of a CREATESTRUCT structure.

    You can get or set user defined information (usually pointers) with GetWindowLongPtr/SetWindowLongPtr or GetWindowLong/SetWindowLong), typically with the GWLP_USERDATA (GWL_USERDATA is equivalent for compilers where GWLP_USERDATA is not defined), which is good for any window, including system defined ones (buttons, edits, statics etc) or the zero-based offset into the window extra memory.

    The window extra memory (and class extra memory) can be set when you register a unique windows class with RegisterClassEx by specifying how much extra memory you want on a per window class or per window created basis by setting the values of the cbClsExtra and cbWndExtra parameters of the WNDCLASSEX structure.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>Say your program consists of many different windows of the same window class, and users can interact with any of them.

    sounds like a good time to use a MDI application (multiple document interface).
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    108
    Thanks guys, that was what I was looking for. I couldnt believe that I missed that fact tho, that you can store pointers with hwnds just when you make the window.. silly me (or my old win32 reference)

    andy : sorry i may have been unclear about my problems (as your solution involves making 2 different kinds of classes). I was more interested with 2 windows of the same class.

    Anyhow, thanks a lot guys, really appreciate the help.

    cheers

    edit: novacain : you could say I was interested in making such thing
    Last edited by underthesun; 01-16-2005 at 03:56 AM.

  6. #6
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    Actually the 2 child windows have the same class. The other class is for the parent window. I'm glad you got your answer though.

    Happy coding!!!!
    i don't think most standard compilers support programmers with more than 4 red boxes - Misplaced

    It is my sacred duity to stand in the path of the flood of ignorance and blatant stupidity... - quzah

    Such pointless tricks ceased to be interesting or useful when we came down from the trees and started using higher level languages. - Salem

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    108
    oh right, I must have missed that sorry

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. processing window messages w/out DispatchMessage ()
    By xixpsychoxix in forum Windows Programming
    Replies: 10
    Last Post: 01-18-2009, 10:07 PM
  2. My progress.. thnx to Cprogramming forumites
    By csonx_p in forum Windows Programming
    Replies: 6
    Last Post: 05-21-2008, 01:17 AM
  3. Avoiding Global variables
    By csonx_p in forum Windows Programming
    Replies: 32
    Last Post: 05-19-2008, 12:17 AM
  4. My first "real" windows app
    By JoshR in forum Windows Programming
    Replies: 2
    Last Post: 07-28-2005, 07:40 AM
  5. eMbedded C++
    By ober in forum C++ Programming
    Replies: 8
    Last Post: 10-01-2002, 12:04 PM