CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Aug 2009
    Posts
    20

    Edit Box Controls

    I'm making a simple database program for a friend and am stuck. The program has a small text box, a large multiline text box, and a button. When the user types a word or series of words(in this case, a dog breed) into the small text box and presses the button, the program takes the text from the small text box, puts it in a string variable fn, and calls a function that takes the file "data/" + fn + ".txt", gets the text from the file one line at a time, and puts the text into the large multiline text box.

    It's going well so far. I made a simple console version that worked great and the only thing I'm having trouble with is trying to find WinAPI help that has nothing to do with Visual Studios. Specifically, what I'm having trouble with is:

    1) How do I make a pointer to the contents of a text box and/or how do I put the contents of a text box into a string variable?
    2) How do I clear, write, and append to a multiline text box?

    Here's the code. I'm pretty new to WinAPI programming, so if you see any errors or bad practices don't hesitate to set me straight.

    Code:
    #include <windows.h>
    #include <fstream.h>
    #include <string.h>
    #define ID_EDIT 1
    #define ID_BUTTON 2
    #define ID_MAINBOX 3
    
    void Datafile_Input(string fn);
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    TCHAR szAppName[] = TEXT("Simple Database Program");
    
    int WINAPI WinMain
    (
     HINSTANCE hInstance, 
     HINSTANCE hPrevInstance,
     PSTR szCmdLine, 
     int iCmdShow
    )
    {
     HWND hwnd;
     MSG msg;
     WNDCLASS wndclass;
     wndclass.style = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc = WndProc;
     wndclass.cbClsExtra = 0;
     wndclass.cbWndExtra = 0;
     wndclass.hInstance = hInstance;
     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
     wndclass.lpszMenuName = NULL;
     wndclass.lpszClassName = szAppName;
    
     if(!RegisterClass(&wndclass))
     {
      MessageBox(NULL, TEXT("Ths program require Windows NT!"),
      szAppName, MB_ICONERROR);
      return 0;
     }
    
     hwnd = CreateWindow
     (
      szAppName, 
      szAppName, 
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 
      CW_USEDEFAULT, 
      640, 
      480,
      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 msg, 
     WPARAM wParam, 
     LPARAM lParam
    )
    {
     static HWND hwndEdit;
     static HWND hwndButton;
     static HWND hwndMainBox;
     HDC hdc;
     PAINTSTRUCT ps;
     RECT rect;
     static TCHAR szText[512] = "";
     switch(msg)
     {
      case WM_CREATE:
      
      hwndEdit = CreateWindow
      (
       "edit",
       NULL,
       WS_CHILD | WS_VISIBLE | WS_BORDER,
       10, 10, 500, 20, hwnd, (HMENU) ID_EDIT,
       ((LPCREATESTRUCT) lParam)->hInstance, NULL
      );
      
      hwndButton = CreateWindow
      (
       "Button","Find Data",
       BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,
       530,10,80,20,hwnd,(HMENU)ID_BUTTON,
       ((LPCREATESTRUCT) lParam)->hInstance,0
      );
      
      hwndMainBox = CreateWindow
      (
       "edit",
       NULL,
       WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | WS_VSCROLL,
       10, 40, 610, 400, hwnd, (HMENU) ID_MAINBOX,
       ((LPCREATESTRUCT) lParam)->hInstance, NULL
      );
    
      
      return 0;
      break;
      
     case WM_SETFOCUS:
      SetFocus(hwndEdit);
      return 0;
      break;
      
     case WM_COMMAND:
      switch(wParam)
      {
       case ID_BUTTON:
       {
       SetFocus(hwndMainBox);
       //Datafile_Input("data/breeds/" + fn + ".txt");
        break;
       }
      }
      return 0;
      break;
    
      case WM_PAINT:
       hdc = BeginPaint(hwnd, &ps);
       EndPaint(hwnd, &ps);
    
       return 0;
       break;
    
     case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
      break;
     }
    
     return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    void Datafile_Input(string fn)
    {
    
    ifstream inf;
    inf.open(fn.c_str());
      if( !inf ) 
      {
      //
      }
    string s;
    getline(inf,s);
    while( s != "999" ) 
    {
    //    cout << s << endl;
    	getline(inf,s);
    }
    
    inf.close();
    }

  2. #2
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Edit Box Controls

    You can copy the contents of an edit control to a string using the GetWindowText API call. This will retrieve all the text.

    For manipulating portions of text in a multiline edit control, use the EM_SETSEL and EM_GETSEL, and EM_REPLACESEL messages.

    http://msdn.microsoft.com/en-us/library/aa924582.aspx

  3. #3
    Join Date
    Aug 2009
    Posts
    20

    Re: Edit Box Controls

    Thanks a million. I was able to put the text into a variable with

    Code:
       int TxtLen = GetWindowTextLength(hwndEdit) + 1;
       char breed[128];
       GetWindowText(hwndEdit, breed, TxtLen);
    And I was able to open the file and read it one line at a time while appending to the multi-line text box with this

    Code:
       SetWindowText(hwndMainBox, " ");
        string s;
        getline(inf,s);
        char fileline[30000];
        int TempNum;
    
        while( s != "999" )
        {
         TempNum=s.size();
         for (int a=0;a<=TempNum;a++)
         {
          fileline[a]=s[a];
         }
        SendMessage(hwndMainBox, EM_REPLACESEL,0,(LPARAM)fileline);
        SendMessage(hwndMainBox, EM_REPLACESEL,0,(LPARAM)"\r\n");
    
         getline(inf,s);
        }
    My next(and hopefully last) question is how do I return focus to the top(first line) of the text box after the program is done writing the file to it?

  4. #4
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Edit Box Controls

    Code:
    SendMessage(hwndMainBox, EM_SETSEL,0,0);
    should set the cursor to the very beginning of the edit control if that's what you are wanting to do.

  5. #5
    Join Date
    Aug 2009
    Posts
    20

    Re: Edit Box Controls

    Maybe I should have been more specific, sorry.

    The program loads text files that are hundreds of lines long. When it loads them, the text box's scroll bar stays at the bottom making it so that when the file is done being paced into the text box, the user is looking at the bottom of the file. How do I make the program automatically scroll to the top of the text box when it's done loading the file?

    Also, how do I change the default font of a text box? I'd like to use a mono-spaced font to make it easier on the eyes.

  6. #6
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Edit Box Controls

    You can sent it the EM_LINESCROLL message.

    To change a font, create a new font (globally) and send the control the WM_SETFONT message.

  7. #7
    Join Date
    Aug 2009
    Posts
    20

    Re: Edit Box Controls

    Thanks again. I had a bit of trouble getting EM_LINESCROLL to work, then I had the idea of scrolling a negative number and it works great.

    Code:
    int nLength = SendMessage(hwndMainBox, EM_GETLINECOUNT, 0, 0);
    SendMessage (hwndMainBox, EM_LINESCROLL, (WPARAM) NULL, -((LPARAM) nLength));
    Also, your advice of creating a global font and giving the text box the WM_SETFONT message worked wonders.

    Code:
    static HFONT FONT_CourierNew;
    ...
    ...
    ...
    FONT_CourierNew=CreateFont
    (18,                          
    0,                        
    0,                      
    0,                      
    FW_BOLD,             
    FALSE,               
    FALSE,                
    0,                   
    ANSI_CHARSET,               
    OUT_DEFAULT_PRECIS,        
    CLIP_DEFAULT_PRECIS,         
    DEFAULT_QUALITY,           
    DEFAULT_PITCH | FF_SWISS,  
    "Courier New");
    ...
    ...
    ...
    SendMessage(hwndMainBox, WM_SETFONT, (WPARAM)FONT_CourierNew, (LPARAM)TRUE);
    Not sure if I did that right, but it works. "static HFONT FONT_CourierNew;" is defined globally, CreateFont is right after the parent window is created in WinMain, and the WM_SETFONT message is sent to the edit box right after it is created in WM_CREATE. Is there anything I've done that will case problems in the future? I'm pretty much winging it at this point and learning from my mistakes since I'm programming in territory I've never touched before.


    I do have another question that is on my mind. Is it possible to bind the width and height of child controls to the width and height of the parent window? I want the controls to be resized and redrawn when the user alters the size of the window either with the maximize/restore button or with dragging the edges.

  8. #8
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Edit Box Controls

    Looks good on the font.

    You can handle the WM_SIZE message in you parent WndProc and call MoveWindow on the edit control.

  9. #9
    Join Date
    Aug 2009
    Posts
    20

    Re: Edit Box Controls

    A little flicker, but other than that it works perfectly, thanks again for your help.

    Code:
      case WM_SIZE:
      {
       static BOOL sizing = FALSE;
       int MainWinY;
       int MainWinX;
       if (!sizing)
       {
        sizing = TRUE;
        MainWinY = HIWORD (lParam); 
        MainWinX = LOWORD (lParam); 
        MoveWindow(
        hwndMainBox,
    	10,
    	40,
    	(MainWinX-20),
    	(MainWinY-50),
    	TRUE);
    	
    	MoveWindow(
    	hwndEdit,
    	10,
    	10,
    	(MainWinX-120),
    	20,
    	TRUE);
    		 
    	MoveWindow(
    	hwndButton,
    	(MainWinX-100),
    	10,
    	80,
    	20,
    	TRUE);		 
    	
    	sizing = FALSE;
       }
       return 0;
      }
      break;
    My last question is, how do I integrate keypresses into the program? I've tried this:

    Code:
    ...
    ...
     case WM_KEYDOWN:
     switch(wParam)
      {
      case VK_RETURN:
      MessageBox(hwnd,"Enter Key Pressed ","Message",MB_OK);
      return 0;
      }
     return 0;
     
     
     case WM_COMMAND:
      switch(wParam)
      {
       case ID_BUTTON:
       {
    ...
    ...
    and it compiles without error but nothing happens when I press the enter key. I've also tried different combinations of that with the same result of nothing when I press enter.
    Last edited by Dispiacere; December 29th, 2009 at 05:10 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured