Thread: Measurement Converter

  1. #1
    Registered User
    Join Date
    May 2007
    Posts
    77

    Measurement Converter

    Hi. I'm trying to write a windows application (i.e. GUI) that takes a number given by the user and outputs another number based on the input and output units selected. The problem is, I don't know how to read the text from the edit control I have in my program and print it successfully to the output edit control. I'm using C, and I'm making all my controls (radio buttons, pushbuttons, edit controls, etc.) using the "CreateWindow" command. Here is what I have for the code for the edit controls and pushbutton and their interactions.

    Code:
    #include <windows.h>
    #include <windowsx.h>
    
    #pragma region Definitions
    
    #define inputNumber			157
    #define outputNumber		158
    #define calculateButton		159
    
    #pragma endregion
    
    // function prototypes
    void InitApp(HINSTANCE);
    LRESULT APIENTRY MainProc(HWND,UINT,WPARAM,LPARAM);
    
    // variables
    #pragma region Handles
    
    HWND hwnd;
    HWND inputText;
    HWND outputText;
    HWND calculateButtonH;
    
    #pragma endregion
    
    HINSTANCE g_hInst;
    
    
    // winmain entry point
    int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR line,int CmdShow)
    {
    	MSG msg;
    	g_hInst = hInst;
    	InitApp(hInst);
    
    	while(GetMessage(&msg,0,0,0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	return msg.wParam;
    }
    
    // initlize application
    void InitApp(HINSTANCE hInst)
    {
    	WNDCLASS wc;
    	wc.cbClsExtra = 0;
    	wc.cbWndExtra = 0;
    	wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
    	wc.hInstance = hInst;
    	wc.hCursor = LoadCursor(NULL,IDC_ARROW);
    	wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
    	wc.lpfnWndProc = (WNDPROC) MainProc;
    	wc.lpszClassName = "Main";
    	wc.lpszMenuName = NULL;
    	wc.style = CS_HREDRAW | CS_VREDRAW;
    
    	
    	RegisterClass(&wc);
    
    	hwnd = CreateWindow("Main","Unit Converter",WS_OVERLAPPEDWINDOW,200,200,800,600,0,0,hInst,0);
    	
    
    	ShowWindow(hwnd,SW_SHOW);
    	UpdateWindow(hwnd);
    	
    }
    
    // Main Process CallBack Function
    LRESULT APIENTRY MainProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
    {
    	LPSTR input;
    	LPCSTR output;
    	int inputType, outputType;
    	switch(msg)
    	{
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			break;
    		case WM_CREATE:
    		{
    			inputText = CreateWindow("Edit","",WS_CHILD | WS_VISIBLE | ES_LEFT,100,380,70,20,hwnd,(HMENU)inputNumber,g_hInst,0);
                outputText = CreateWindow("Edit","",WS_CHILD | WS_VISIBLE | ES_LEFT,400,380,70,20,hwnd,(HMENU)outputNumber,g_hInst,0);
                calculateButtonH = CreateWindow("Button","Calculate",WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,600,68,80,30,hwnd,(HMENU)calculateButton,g_hInst,0);
    
    		}
    		break;
    		case WM_COMMAND:
    		{
    			switch(HIWORD(wParam))
    			{
    			case BN_CLICKED:
    				switch(LOWORD(wParam))
    				{
    
    				case calculateButton:
    					output = Button_GetText(inputText,&input,sizeof(input));
    					
    					Button_SetText(outputText,&output);
    
    					break;
    				}
    			}
    		}
    		
    		break;
    		default: return DefWindowProc(hwnd,msg,wParam,lParam);
    	}
    
    	return 0;
    }
    It's greatly trimmed to take out the radio button definitions, handle declarations, and the code for the creation of the buttons themselves.

    Just as a warning, for some reason, if I make a new application in VS2005 and paste this code into it, no matter what configuration for the application I have, it doesn't compile, and yet it does just fine from my imported project. Just FYI.

    Oh, and here's the list of warnings I get. The program compiles, but all I get is that square character.
    Code:
    .\Main.c(99) : warning C4047: 'function' : 'LPSTR' differs in levels of indirection from 'LPSTR *'
    .\Main.c(99) : warning C4024: 'GetWindowTextA' : different types for formal and actual parameter 2
    .\Main.c(99) : warning C4047: '=' : 'LPCSTR' differs in levels of indirection from 'int'
    .\Main.c(101) : warning C4047: 'function' : 'LPCSTR' differs in levels of indirection from 'LPCSTR *'
    .\Main.c(101) : warning C4024: 'SetWindowTextA' : different types for formal and actual parameter 2
    .\Main.c(76) : warning C4101: 'outputType' : unreferenced local variable
    .\Main.c(76) : warning C4101: 'inputType' : unreferenced local variable
    Last edited by Molokai; 06-08-2008 at 09:39 PM.

  2. #2
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Here is a function I made to get the text out of an edit control, pass it the hanlde to the window the edit control it is on and the ID of the edit control, feel free to modify it:
    Code:
    char *GetTextFromTextField(HWND hwnd,UINT tID) {
    
    	int len = GetWindowTextLength(GetDlgItem(hwnd, tID));
    	char* bufTxt;
    	if(len > 0)    {
    			bufTxt = (char*)GlobalAlloc(GPTR, len + 1);
    			GetDlgItemText(hwnd, tID, bufTxt, len + 1);
    		}
    	return bufTxt;
    
    }
    You might want to do some checks to see if the text in the edit field is numeric (this might be best to filter the characters that the user is typing in to the edit real-time). Use a send message with WM_SETTEXT, wParam=0, lParam=(char*)text. Not too difficult.
    Also It is a bit hard to fix the errors if you haven't posted the lines they occur on. Use/modify the function above and you should be fine.
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  3. #3
    Registered User
    Join Date
    May 2007
    Posts
    77
    OK, so I don't have a problem getting the text from the input edit control. My problem is, when I try to edit the text on the output control to match the input, the method I'm using (Button_SetText or SetWindowText) doesn't like the fact that the data is an integer. It likes to have quotes around what it's setting as the text (i.e., if I input the number 20, it doesn't like that, but I can easily set the output to 20 if I set a string variable to "20", including the quotes, to make it a string). So what I really need is a way to take the input (or the number that is calculated from the conversion) and make it a string by an explicit conversion, or by somehow putting quotes around the end number. Anyone know how to do that?

    Oh, and the error is occurring in the code I gave you. I'm not doing any conversions yet, I'm just trying to get the output control to print correctly.

    That makes me think of something, though. Do you think it would be easier if I tried using the TextOut() function, without having an edit control for the output? Or would I encounter the same problems with it not wanting to print non-quoted data?
    Last edited by Molokai; 06-09-2008 at 12:55 PM.

  4. #4
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Here you go.
    Code:
    BOOL SetWindowIntText(HWND hWnd,int uValue){
        char szBuffer[16];
        itoa(uValue,szBuffer,10);
        return SetWindowText(hWnd,szBuffer);
    }
    Quote Originally Posted by Molokai
    That makes me think of something, though. Do you think it would be easier if I tried using the TextOut() function, without having an edit control for the output? Or would I encounter the same problems with it not wanting to print non-quoted data?
    I am quite sure TextOut() does not do what you expect it to do.
    Last edited by maxorator; 06-09-2008 at 01:36 PM.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by P4R4N01D View Post
    Code:
    char *GetTextFromTextField(HWND hwnd,UINT tID) {
    
    	int len = GetWindowTextLength(GetDlgItem(hwnd, tID));
    	char* bufTxt;
    	if(len > 0)    {
    			bufTxt = (char*)GlobalAlloc(GPTR, len + 1);
    			GetDlgItemText(hwnd, tID, bufTxt, len + 1);
    		}
    	return bufTxt;
    
    }

    Careful you don't leave a dangling pointer....
    "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

  6. #6
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Ok, that was just an example to illustrate the process, (it is really only one function call). This would be a more safe implementation of the function:
    Code:
    char *GetTextFromTextField(HWND hwnd,UINT tID) {
    
    	int len = GetWindowTextLength(GetDlgItem(hwnd, tID));
    	char* bufTxt;
    	if(len > 0)    {
    			bufTxt = (char*)LocalAlloc(LPTR, len + 1);
     if(bufTxt == NULL )
        {
           messageBox(NULL, "LocalAlloc failed, not enough memory", "Error", MB_ICONERROR);
           return;
        }
    			GetDlgItemText(hwnd, tID, bufTxt, len + 1);
    		}
    	return bufTxt;
    
    }
    And as for TextOut(), although I haven't used it I wouldn't recommend it. I mainly don't like the idea of writing a sting to a specified x, y coordinate. This would involve checking the screen size and whether the program could write to that position (if not, who knows what strange things would happen). For just output, use a static (a.k.a. label) control for both I/O use an edit. They are both just as easy setting/retrieving text.
    Edit: How could you specify the font with text out and finally msdn example:
    //Send some text out into the world
    that is what msdn thinks about this function: send text out "into the world", as oppose to direct the text privately to its own control - which is more likely to get lost. The Win32 GUI uses windows, not functions. It is event driven, not procedural. Think about it! If a procedural application is required than mabye a console interface might be the better option.
    Last edited by P4R4N01D; 06-10-2008 at 12:08 AM. Reason: msdn quote.
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    On a side note there is a very nice freeware app that does hundreds of popular unit conversions. I used to use it at the factory when I was an auditor and it was invaluable to my work.

    Unfortunately I forget the name of it. Google for unit conversion apps and I'm sure it will pop up.

  8. #8
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    TextOut() is used for drawing text onto a Device Context.

    More 'owner draw' (without a control) than if you use an edit or static control (which handles its own drawing and DCs).



    My point about the dynamic allocation of a string (char array) to get the text was;

    Remember to free the memory!

    If you call that function in response to an EN_CHANGE event you may have issues (due to each character entered in the edit generating a seperate event).

    I never do dynamic allocation for a simple edit string.

    I just declare a char array of MAX_PATH.

    If you are worried about the length of the text use EM_SETLIMITTEXT.
    "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

  9. #9
    Registered User
    Join Date
    May 2007
    Posts
    77
    Quote Originally Posted by Bubba View Post
    On a side note there is a very nice freeware app that does hundreds of popular unit conversions. I used to use it at the factory when I was an auditor and it was invaluable to my work.

    Unfortunately I forget the name of it. Google for unit conversion apps and I'm sure it will pop up.
    The point of this app is not to just have a conversion app. The point is to see if I can successfully program a working version of my own, as this is my first venture into GUI programming on Windows. Unless some of those apps out there give the source as well (so I can possibly see how they handle the int to char/string problem), which I haven't seen yet (yes, I did search for source of conversion apps), then they wouldn't do me any good.

    Quote Originally Posted by P4R4N01D View Post
    Ok, that was just an example to illustrate the process, (it is really only one function call).
    The problem isn't getting the text from the input box. The problem is after getting the input and doing the calculations, I can't print the result in another control, because the result is in int form and the "Button_SetText" and "SetWindowText" macros only print strings (they need the quotation marks for some reason). I think I see where you're going to with your code, but that makes a string directly from the input. That doesn't do me any good!

  10. #10
    Registered User
    Join Date
    Dec 2007
    Posts
    214
    You have your result in an integer, so just put that into a string buffer, like P4R4N0ID showed.

    char szBuffer[16];
    itoa(uValue,szBuffer,10);

    Then use SetWindowText to put it in your control.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    itoa is unfortunately non-standard. It's better to use sprintf.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    You could use SetDlgItemInt()

    But printing the data into a string allows better formatting in most cases.


    Quote Originally Posted by Elysia View Post
    itoa is unfortunately non-standard. It's better to use sprintf.
    None of my coders are allowed to use sprintf() and I advise against using it.

    _snprintf() is MUCH safer.
    "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

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I have no quarrel with safer versions.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. converter currency in C
    By MyRedz in forum C Programming
    Replies: 7
    Last Post: 10-16-2008, 10:39 PM
  2. Is there any up to date C++ to C converter?
    By sept in forum C Programming
    Replies: 35
    Last Post: 09-15-2008, 01:56 PM
  3. Base10 to Base n converter
    By P4r4digm in forum C++ Programming
    Replies: 1
    Last Post: 10-04-2006, 09:34 PM
  4. Help with Error - Binary to Character Converter
    By dvldrmmr in forum C++ Programming
    Replies: 7
    Last Post: 04-30-2004, 01:21 PM
  5. Hex converter?
    By Nasimov in forum C++ Programming
    Replies: 2
    Last Post: 11-10-2003, 01:44 PM