[C++ API] Edit Box

Started by
14 comments, last by powerskill 17 years, 1 month ago
I know I made a post earlier relating to this, but I think it is full bad questions on my behalf. This is the cleaner better way to ask for help, I think. The program asks the user for input. The input should be stored into the HWNDedit variable, I think. Yet I have no idea how I would save that data into that variable once the user writes it into the EDIT box. Thanks for any help. Much obliged John [EDITED] for current Problem. I'm posting the full code I have now. I'm having a problem when I read off the second EDIT TEXT BOX. After debugging I saw that when I get to this line of code
 GetDlgItemTextA(hWnd, IDC_EDIT_YIELD, yield_buffer, 32);
What ever value was entered in the first EDIT TEXT BOX, the GetDlgItemTextA function is reading that same value and storring it into yield_buffer. I traced the whole code and everything seems to be in the right place.
#include <windows.h>
#include <cstring>
#include <string>
#include "RetirementPlanner.h"

#define IDC_EDIT_CONTRIBUTION 1000
#define IDC_EDIT_YIELD 1000
#define IDC_EDIT_AGE 1000
#define IDC_EDIT_retirementAGE 1000
#define IDC_EDIT_INFLATION 1000

using namespace std;

    RetirementPlanner savings;
  	double dContribute = 0;
	double dInterest = 0;
	int iAgeNow = 0;
	int iAgeThen = 0;
	double dInflate = 0;

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

HWND hWnd; 
HWND hwndEdit; 
HWND hwndTotPresentValue;
HWND hwndTotInterest;

HWND hwndContribution;
HWND hwndYield;
HWND hwndAge;
HWND hwndRetirementAge;
HWND hwndInflation;

HWND hwndButtonEnter; 
HWND hwndButtonClear;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{	
	WNDCLASS wc; 
	MSG msg;
    
	wc.lpszClassName = "Window";
	wc.lpfnWndProc	 = MainWndProc;			                
	wc.style	 = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
	wc.hInstance     = hInstance;							
	wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor	 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = " ";
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	
	RegisterClass(&wc);     	

	hWnd = CreateWindow ("Window", "Retirement Planner", 
						WS_OVERLAPPEDWINDOW,
                                                CW_USEDEFAULT, 
						CW_USEDEFAULT, 
						500, 
						400, 
						NULL, 
						NULL, 
						hInstance, NULL);

	ShowWindow(hWnd,nCmdShow);
    
	while (GetMessage(&msg, NULL, 0,0))
		  {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		  }

	return(int) msg.wParam;
}   

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{	
	HWND hwndCtl = (HWND) lParam;
    

switch(msg)
	  {
           HINSTANCE hInstance;

	   case WM_CREATE:
           hwndContribution = CreateWindow ("EDIT", NULL, WS_VISIBLE |  
                                             WS_CHILD | WS_BORDER | ES_NUMBER, 
                                             100, 10, 90, 20, hWnd, 
                                             (HMENU)IDC_EDIT_CONTRIBUTION, 
                                             GetModuleHandle(NULL), NULL);

	   hwndYield = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD |     
                                     WS_BORDER | ES_NUMBER, 100, 35, 90, 20,
                                     hWnd, (HMENU)IDC_EDIT_YIELD , 
                                     GetModuleHandle(NULL), NULL);

	   hwndAge = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_BORDER |  
                                   |ES_NUMBER, 100, 60, 90, 20, hWnd, 
                                   (HMENU)IDC_EDIT_AGE, 
                                   GetModuleHandle(NULL), NULL);

	   hwndRetirementAge = CreateWindow ("EDIT", NULL, WS_VISIBLE |   
                                             WS_CHILD | WS_BORDER | ES_NUMBER, 
	                                     100, 85, 90, 20, hWnd, (HMENU) 
                                             IDC_EDIT_retirementAGE ,
                                             GetModuleHandle(NULL), NULL); 

           hwndInflation = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD |
                                         WS_BORDER | ES_NUMBER, 100, 110, 90,
                                         20, hWnd, (HMENU)IDC_EDIT_INFLATION,
                                         GetModuleHandle(NULL), NULL); 


           hwndButtonEnter = CreateWindow ("BUTTON", "Enter", WS_VISIBLE | 
                                           WS_CHILD | BS_DEFPUSHBUTTON,   
                                            320, 240, 55, 30, hWnd, 
                                            NULL, hInstance, NULL);

	    hwndButtonClear = CreateWindow ("BUTTON", "Reset", WS_VISIBLE |
                                             WS_CHILD | BS_DEFPUSHBUTTON, 
		                            256, 240, 55, 30, hWnd, NULL, 
                                            hInstance, NULL);

	   case WM_COMMAND:
	   switch(wParam)
                 {
	          case BN_CLICKED:    
		  if(hwndCtl == hwndButtonEnter)
		  {
		  // setting up contribution
		  char contribution_buffer[32];
   		  GetDlgItemTextA(hWnd,IDC_EDIT_CONTRIBUTION, contribution_buffer, 32);
		double contribution = atoi(contribution_buffer);
		savings.setContribution(contribution); //class
						
		// setting up yield
		char yield_buffer[32];
		GetDlgItemTextA(hWnd, IDC_EDIT_YIELD, yield_buffer, 32);
		double yield = atoi(yield_buffer);

	        char age_buffer[32];
		GetDlgItemTextA(hWnd, IDC_EDIT_AGE, age_buffer, 32);
		int age = atoi(age_buffer);


		// back to string
		_gcvt(contribution, 10, contribution_buffer);
	        _gcvt(yield, 10, yield_buffer);
		_gcvt(age, 10, age_buffer);

		hwndEdit = CreateWindow ("EDIT", contribution_buffer, 
                                          WS_VISIBLE | WS_CHILD | WS_BORDER |
                                           ES_LEFT, 10, 260, 90, 20, hWnd,
                                           NULL, hInstance, NULL);
											
		hwndTotPresentValue = CreateWindow ("EDIT", yield_buffer,
                                                    WS_VISIBLE | WS_CHILD | 
						    WS_BORDER | ES_LEFT, 10,
                                                    285, 90, 20, hWnd, NULL,
                                                    hInstance, NULL);

	        hwndTotInterest = CreateWindow ("EDIT", age_buffer, WS_VISIBLE
                                                | WS_CHILD | WS_BORDER 
                                                |ES_LEFT, 10, 310, 90, 20,
                                                 hWnd, NULL, hInstance, NULL);

		}
		else 
		    if(hwndCtl == hwndButtonClear)
		      {
			SetWindowText(hwndEdit, "");
			SetWindowText(hwndTotPresentValue, "");
			SetWindowText(hwndTotInterest, "");
			SetWindowText(hwndContribution, "");
			SetWindowText(hwndYield, "");
			SetWindowText(hwndAge, "");
			SetWindowText(hwndRetirementAge, "");
			SetWindowText(hwndInflation, "");
	                }
	     }
	     break;

	    case WM_DESTROY:    PostQuitMessage(0);
				return 0;

	     default:    return DefWindowProc(hWnd, msg, wParam, lParam);
	 }
	return 0;
}
[Edited by - powerskill on March 10, 2007 1:35:07 AM]
Advertisement
Move all of the child window creation into a WM_CREATE case inside MainWndProc.

Move all this:

	hwndEdit = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 							  10, 10, 155, 20,hWnd, NULL, hInstance, NULL);	hwndContribution = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 							         10, 35, 155, 20, hWnd, NULL, hInstance, NULL);		hwndYield = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 							         10, 60, 155, 20, hWnd, NULL, hInstance, NULL);	hwndAge = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 							         10, 95, 155, 20, hWnd, NULL, hInstance, NULL);	hwndRetirementAge = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 							         10, 130, 155, 20, hWnd, NULL, hInstance, NULL);     hwndInflation = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 							         10, 165, 155, 20, hWnd, NULL, hInstance, NULL);     hwndButtonEnter = CreateWindow ("BUTTON", "Enter", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 									  130, 210, 35, 35, hWnd, NULL, hInstance, NULL);	hwndButtonClear = CreateWindow ("BUTTON", "Clear", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 									 10, 260, 155, 25, hWnd, NULL, hInstance, NULL);


into

    switch(msg) {    case WM_CREATE:


I know that in the other thread you said that you read the Forger tutorial, but it doesn't seem like you have because one of them goes over creating child edit controls in an application: App Part 1: Creating controls at runtime. I understand wanting to eat the entire apple with one bite, but that won't work with programming.

"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
After rereading that link several times, I find myself 100% confused. If I’m right, moving the Edit Boxes into the switch statement will only organize them but not give me the ability to store the input of the user.

Improved organization of gui components is an important part of programming.

Let's see. It's probably good to have the documentation for edit controls at hand. Unlike the edit control in the Forger tutorial, you want your edit controls to use the ES_NUMBER style so as to limit input to digits.

You might also want to assign different ID numbers to each child window. Forger's tutorial demonstrates that with the "(HMENU)IDC_MAIN_EDIT" argument to CreateWindow. This let's you use GetDlgItemText to extract the numbers from a particular control. You can also use GetWindowText for this purpose.

Typically such id numbers are defined in the resource header, for example

#define IDC_EDIT_CONTRIBUTION 1000

Then in the WM_CREATE

hwndContribution = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD | ES_NUMBER | ES_LEFT, 10, 35, 155, 20, hWnd, (HMENU)IDC_EDIT_CONTRIBUTION, GetModuleHandle(NULL), NULL);

Note that GetModuleHandle(NULL) supplies the hInstance for the current process.

The child id makes it much easier to deal with buttons especially.

To extract the information from the control, obtain the text from the control and convert it into an integer using atoi.

char contribution_buffer[32]
GetDlgItemTextA(hWnd,IDC_EDIT_CONTRIBUTION,contribution_buffer, 32);
int contribution = atoi(contribution_buffer);

Then repeat this as necessary for the other controls.

This code should go inside the MainWndProc in response to the WM_COMMAND message sent when the calculate button is clicked.

case WM_COMMAND:
switch(wParam) {
case IDC_CALCULATE:
{
// extract values, convert, calculate
}
case IDC_CLEAR:
{
}
default:
}

I think you should go through the Forger Tutorial from the beginning, building each sample program through from start to finish so as to give yourself a better feel for how Windows programs are coded.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Thanks so much. ES_NUMBER is so cool.
I don’t know, if you have time later I would like to show you the end result.

Thank you.
Sure. Post the code in this thread or send me a PM.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
I'm posting the full code I have now. I'm having a problem when I read off the second EDIT TEXT BOX.

After debugging I saw that when I get to this line of code
 GetDlgItemTextA(hWnd, IDC_EDIT_YIELD, yield_buffer, 32);


What ever value was entered in the first EDIT TEXT BOX, the GetDlgItemTextA function is reading that same value and storring it into yield_buffer.
I traced the whole code and everything seems to be in the right place.

#include <windows.h>#include <cstring>#include <string>#include "RetirementPlanner.h"#define IDC_EDIT_CONTRIBUTION 1000#define IDC_EDIT_YIELD 1000#define IDC_EDIT_AGE 1000#define IDC_EDIT_retirementAGE 1000#define IDC_EDIT_INFLATION 1000using namespace std;    RetirementPlanner savings;  	double dContribute = 0;	double dInterest = 0;	int iAgeNow = 0;	int iAgeThen = 0;	double dInflate = 0;LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);HWND hWnd; HWND hwndEdit; HWND hwndTotPresentValue;HWND hwndTotInterest;HWND hwndContribution;HWND hwndYield;HWND hwndAge;HWND hwndRetirementAge;HWND hwndInflation;HWND hwndButtonEnter; HWND hwndButtonClear;int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){		WNDCLASS wc; 	MSG msg;    	wc.lpszClassName = "Window";	wc.lpfnWndProc	 = MainWndProc;			                	wc.style	 = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;	wc.hInstance     = hInstance;								wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);	wc.hCursor	 = LoadCursor(NULL, IDC_ARROW);	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);	wc.lpszMenuName  = " ";	wc.cbClsExtra	 = 0;	wc.cbWndExtra	 = 0;		RegisterClass(&wc);     		hWnd = CreateWindow ("Window", "Retirement Planner", 						WS_OVERLAPPEDWINDOW,                                                CW_USEDEFAULT, 						CW_USEDEFAULT, 						500, 						400, 						NULL, 						NULL, 						hInstance, NULL);	ShowWindow(hWnd,nCmdShow);    	while (GetMessage(&msg, NULL, 0,0))		  {			TranslateMessage(&msg);			DispatchMessage(&msg);		  }	return(int) msg.wParam;}   LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){		HWND hwndCtl = (HWND) lParam;    switch(msg)	  {           HINSTANCE hInstance;	   case WM_CREATE:           hwndContribution = CreateWindow ("EDIT", NULL, WS_VISIBLE |                                               WS_CHILD | WS_BORDER | ES_NUMBER,                                              100, 10, 90, 20, hWnd,                                              (HMENU)IDC_EDIT_CONTRIBUTION,                                              GetModuleHandle(NULL), NULL);	   hwndYield = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD |                                          WS_BORDER | ES_NUMBER, 100, 35, 90, 20,                                     hWnd, (HMENU)IDC_EDIT_YIELD ,                                      GetModuleHandle(NULL), NULL);	   hwndAge = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_BORDER |                                     |ES_NUMBER, 100, 60, 90, 20, hWnd,                                    (HMENU)IDC_EDIT_AGE,                                    GetModuleHandle(NULL), NULL);	   hwndRetirementAge = CreateWindow ("EDIT", NULL, WS_VISIBLE |                                                WS_CHILD | WS_BORDER | ES_NUMBER, 	                                     100, 85, 90, 20, hWnd, (HMENU)                                              IDC_EDIT_retirementAGE ,                                             GetModuleHandle(NULL), NULL);            hwndInflation = CreateWindow ("EDIT", NULL, WS_VISIBLE | WS_CHILD |                                         WS_BORDER | ES_NUMBER, 100, 110, 90,                                         20, hWnd, (HMENU)IDC_EDIT_INFLATION,                                         GetModuleHandle(NULL), NULL);            hwndButtonEnter = CreateWindow ("BUTTON", "Enter", WS_VISIBLE |                                            WS_CHILD | BS_DEFPUSHBUTTON,                                               320, 240, 55, 30, hWnd,                                             NULL, hInstance, NULL);	    hwndButtonClear = CreateWindow ("BUTTON", "Reset", WS_VISIBLE |                                             WS_CHILD | BS_DEFPUSHBUTTON, 		                            256, 240, 55, 30, hWnd, NULL,                                             hInstance, NULL);	   case WM_COMMAND:	   switch(wParam)                 {	          case BN_CLICKED:    		  if(hwndCtl == hwndButtonEnter)		  {		  // setting up contribution		  char contribution_buffer[32];   		  GetDlgItemTextA(hWnd,IDC_EDIT_CONTRIBUTION, contribution_buffer, 32);		double contribution = atoi(contribution_buffer);		savings.setContribution(contribution); //class								// setting up yield		char yield_buffer[32];		GetDlgItemTextA(hWnd, IDC_EDIT_YIELD, yield_buffer, 32);		double yield = atoi(yield_buffer);	        char age_buffer[32];		GetDlgItemTextA(hWnd, IDC_EDIT_AGE, age_buffer, 32);		int age = atoi(age_buffer);		// back to string		_gcvt(contribution, 10, contribution_buffer);	        _gcvt(yield, 10, yield_buffer);		_gcvt(age, 10, age_buffer);		hwndEdit = CreateWindow ("EDIT", contribution_buffer,                                           WS_VISIBLE | WS_CHILD | WS_BORDER |                                           ES_LEFT, 10, 260, 90, 20, hWnd,                                           NULL, hInstance, NULL);													hwndTotPresentValue = CreateWindow ("EDIT", yield_buffer,                                                    WS_VISIBLE | WS_CHILD | 						    WS_BORDER | ES_LEFT, 10,                                                    285, 90, 20, hWnd, NULL,                                                    hInstance, NULL);	        hwndTotInterest = CreateWindow ("EDIT", age_buffer, WS_VISIBLE                                                | WS_CHILD | WS_BORDER                                                 |ES_LEFT, 10, 310, 90, 20,                                                 hWnd, NULL, hInstance, NULL);		}		else 		    if(hwndCtl == hwndButtonClear)		      {			SetWindowText(hwndEdit, "");			SetWindowText(hwndTotPresentValue, "");			SetWindowText(hwndTotInterest, "");			SetWindowText(hwndContribution, "");			SetWindowText(hwndYield, "");			SetWindowText(hwndAge, "");			SetWindowText(hwndRetirementAge, "");			SetWindowText(hwndInflation, "");	                }	     }	     break;	    case WM_DESTROY:    PostQuitMessage(0);				return 0;	     default:    return DefWindowProc(hWnd, msg, wParam, lParam);	 }	return 0;}


[Edited by - powerskill on March 10, 2007 1:35:15 AM]
bump
Does anyone see the problem?
Here is your problem:

#define IDC_EDIT_CONTRIBUTION 1000
#define IDC_EDIT_YIELD 1000
#define IDC_EDIT_AGE 1000
#define IDC_EDIT_retirementAGE 1000
#define IDC_EDIT_INFLATION 1000

These are IDs which means that they are supposed to be unique within a dialog. You keep on reading data from one edit box because when you use GetDialogItemText() its like saying "Hey, get the text of the item with ID number 1000" except in your case every control has ID number 1000. Ensure every control has a unique ID and your code should work.
Another problem with the code - something I should have made clearer earlier - is that the output windows should be created inside WM_CREATE as well.

		hwndEdit = CreateWindow ("EDIT", contribution_buffer,                                           WS_VISIBLE | WS_CHILD | WS_BORDER |                                           ES_LEFT, 10, 260, 90, 20, hWnd,                                           NULL, hInstance, NULL);													hwndTotPresentValue = CreateWindow ("EDIT", yield_buffer,                                                    WS_VISIBLE | WS_CHILD | 						    WS_BORDER | ES_LEFT, 10,                                                    285, 90, 20, hWnd, NULL,                                                    hInstance, NULL);	        hwndTotInterest = CreateWindow ("EDIT", age_buffer, WS_VISIBLE                                                | WS_CHILD | WS_BORDER                                                 |ES_LEFT, 10, 310, 90, 20,                                                 hWnd, NULL, hInstance, NULL);


You don't want to create these new every time the ENTER button is clicked. Create them one time in WM_CREATE and then access them when the ENTER button is clicked. You can use SetDlgItemText, SetDlgItemInt or SetWindowText to put the output results into the appropriate windows.

I should also have explained that I used GetDlgItemTextA in the snippet rather than GetDlgItemText in order to avoid fussing with TCHAR. The A appended means that function expects an ANSI character string, eg. char buffer[32] rather than wchar_t buffer[32] or TCHAR buffer[32]. You can also use GetDlgItemInt to avoid using atoi, but you'll still have to deal with the floating point variables yourself.




"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man

This topic is closed to new replies.

Advertisement