Sign in to follow this  
powerskill

[C++ API] Edit Box

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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:15 AM]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.




Share this post


Link to post
Share on other sites
Quote:
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.

Oh that’s another good one :)

Quote:

You don't want to create these new every time the ENTER button is clicked.

Hmm that does sound like a bad idea. I had it to make a cool effect so that once the user clicked the Enter Button they would pop up. But I had a better thought, I'm going to create them in the correct place, but borderless, so it’s professional and I will add the text once the user clicks ENTER.

For the final result I plan to give it a background picture, and some text labels.

Share this post


Link to post
Share on other sites
Just wondering. I’m looking for it but maybe someone knows it by memory. Is there a parameter I can give the EDIT BOX so that the user cant write on it.

This is ideal for my last 3 EDIT boxes that only print out the value of the calculations, so there is no reason for the user to write in them.

PS I think I'm creating the best program ever done by me lol :)

Share this post


Link to post
Share on other sites
I don't think I will use that. Its making my edit box into a grey color, and my background is white.
[edited] background is a white bmp I loaded with some 'art'.

Share this post


Link to post
Share on other sites
Quote:
Original post by powerskill
I don't think I will use that. Its making my edit box into a grey color, and my background is white.


That's the normal Windows UI way of telling the user that he can't edit the control's contents, so that users don't waste time trying. You're supposed to create a background that will work with that text colour, if you need to disable controls that appear over the background.

Share this post


Link to post
Share on other sites
I'll work around that. I will add something cheap thought; I don't want the user to change the size of the window... I hope that’s not a bad idea.



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