Thread: Proper sizing of single-line edit control.

  1. #1
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555

    Proper sizing of single-line edit control.

    How should I go about resizing a single-line edit control so that the client area's height is the same as the height of the font and perhaps padding by a pixel or two?
    I tried to GetObject() the font and then apply the absolute value of the lfHeight member from the generated LOGFONT struct in a RECT to be used in a call to AdjustWindowRectEx() to compensate for the WS_EX_CLIENTEDGE exstyle.
    However I feared that the lfHeight member probably wasn't in pixels (MSDN says it's in a "logical unit" format) and the result after finally calling SetWindowPos() wasn't what I wanted either.
    The position of the edit control is intended to be at the bottom of the screen.

    Here's the code I tried but with the unnecessary stuff removed so treat it as pseudocode:
    Code:
    HWND hwnd //parent
    HWND input; //the edit control
    const DWORD inputstyle, inputexstyle; //has the styles for the edit control
    RECT ca; //client area
    RECT r = {0, 0, 0};
    HFONT font;
    LOGFONT f;
    
    GetClientRect(hwnd, &ca);
    GetObject(font, sizeof(f), &f);
    r.bottom = f.lfHeight < 0 ? -f.lfHeight : f.lfHeight;
    AdjustWindowRectEx(&r, inputstyle, FALSE, inputexstyle);
    SetWindowPos(input, NULL, 0, ca.bottom - r.bottom, ca.right, r.bottom, SWP_NOZORDER);
    Like I said it's pseudocode so seemingly unitialized variables are actually initialized, I only had them declared to show their type.

  2. #2
    ... arjunajay's Avatar
    Join Date
    May 2005
    Posts
    203
    I'm not sure but don't you need the edit ctrl's HDC to get the font it is using?
    I don't see any GetDC() call. Infact I don't even see a HDC variable.

  3. #3
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>I'm not sure but don't you need the edit ctrl's HDC to get the font it is using?
    I don't see any GetDC() call. Infact I don't even see a HDC variable.<<

    You can get a handle to the font by sending a WM_GETFONT message. An option that relies on a device context would be to use GetTextExtentPoint32 to get the font dimensions for a specific string. Yet another, again using a dc, might use GetTextMetrics to get the dimensions of interest.

    >>logical unit<<

    These depend on the mapping mode of the device context. Use GetMapMode; the chances are it'll already be MM_TEXT in which case those units are pixels. You can always compare the results from using AdjustWindowRectEx to those obtained by manually building up the various window border dimensions yourself (see GetSystemMetrics).

    As far as I know there's no 'right' way to do this so what you're attempting seems as good an approach as any.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  4. #4
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    Quote Originally Posted by arjunajay
    I'm not sure but don't you need the edit ctrl's HDC to get the font it is using?
    I don't see any GetDC() call. Infact I don't even see a HDC variable.
    Shouldn't be necessay as I already have the font.
    Actual code:
    Code:
    		case WM_CREATE:
    		{
    			HFONT font;
    			LOGFONT f;
    
    			font = CreateFont(-MulDiv(10, GetDeviceCaps(GetDC(hwnd), LOGPIXELSY), 72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TEXT("MS Shell Dlg"));
    			if (font == NULL) {
    				Error();
    				PostQuitMessage(1);
    				break;
    			}
    			channel = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""),
    			                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL,
    			                         0, 0, 0, 0, hwnd, (HMENU) IDC_CHANNEL, GetModuleHandle(NULL), NULL);
    			if (channel == NULL) {
    				Error();
    				PostQuitMessage(1);
    				break;
    			}
    			SendMessage(channel, WM_SETFONT, (WPARAM) font, MAKELPARAM(FALSE, 0));
    			input = CreateWindowEx(inputexstyle, TEXT("EDIT"), TEXT(""), inputstyle, 0, 0, 0, 0, hwnd, (HMENU) IDC_INPUT, GetModuleHandle(NULL), NULL);
    			if (input == NULL) {
    				Error();
    				PostQuitMessage(1);
    				break;
    			}
    			SendMessage(input, WM_SETFONT, (WPARAM) font, MAKELPARAM(FALSE, 0));
    			_inputproc = (WNDPROC) SetWindowLongPtr(input, GWL_WNDPROC, (LONG_PTR) inputproc);
    			GetObject(font, sizeof(f), &f);
    			fonth = f.lfHeight < 0 ? -f.lfHeight : f.lfHeight;
    			bg = CreateSolidBrush(RGB(0x00, 0x00, 0x00));
    			break;
    		}
    fonth is a static LONG that WM_SIZE uses.
    I tried calling GetMapMode() and it did return MM_TEXT. I have also already compared the height before and after AdjustWindowRectEx call, which tells me that abs(lfHeight) is 13, r.top is -2 and r.bottom is 15.

    Two times the point size seems to give me a perfect edit box (i.e. fonth = 2*10, but this solution isn't applicable for large sizes.
    Code:
    		case WM_SIZE:
    		{
    			RECT ca;
    			RECT r = {0, 0, 0};
    
    			GetClientRect(hwnd, &ca);
    			ca.right -= 2*MARGIN;
    			r.bottom = fonth;
    			AdjustWindowRectEx(&r, inputstyle, FALSE, inputexstyle);
    			r.bottom -= r.top;
    			SetWindowPos(input, NULL, MARGIN, ca.bottom - r.bottom - MARGIN, ca.right, r.bottom, SWP_NOZORDER);
    			ca.bottom -= 3*MARGIN + r.bottom;
    			SetWindowPos(channel, NULL, MARGIN, MARGIN, ca.right, ca.bottom, SWP_NOZORDER);
    			break;
    		}
    Looks like a mIRC window but without the list box containing users.

    Attaching the source.

  5. #5
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    lfHeight does not include the internal leading, so text metrics seems to be the go. Also, some padding is desirable. Replacing your call to GetObject with the following does the trick on my machine:
    Code:
    			{
    				TEXTMETRIC tm;
    				HDC        hdcInput;
    				HFONT      hFontOld;
    
    				hdcInput = GetDC(input);
    
    				  /* Select our new font into the DC before getting text metrics.
    				   * Calling WM_SETFONT is not enough. */
    				  hFontOld = SelectObject(hdcInput, font);
    				  GetTextMetrics(hdcInput, &tm);
    				  SelectObject(hdcInput, hFontOld);
    
    				ReleaseDC(input, hdcInput);
    
    				/* Use a padding of 10% (rounded down) or 2 pixels, whatever is greater. */
    				fonth = tm.tmHeight + max(tm.tmHeight / 10, 2);
    
    				{
    				  /* Debugging code only. */
    				  char x[1000];
    				  GetObject(font, sizeof(f), &f);
    				  wsprintf(x, "%d, %d, %d, %d", tm.tmHeight, tm.tmInternalLeading, tm.tmExternalLeading, f.lfHeight);
    				  MessageBox(NULL, x, NULL, 0);
    				}
    			}
    Finally, "the result ... wasn't what I wanted" is not a particularly useful description. When I code, the result I want is a billion dollars in untraceable cash, world peace and prosperity and ... well, this is a family forum, but anyway, the result "wan't what I wanted". A sentence describing the result and what you were expecting can be very helpful. A screenshot is even better.

  6. #6
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    I thought that since I said what result I expected the fault would be an edit box that's either too big or too small. The included source code had the purpose of serving as a screenshot so the people could see the disaster themselves.
    Anyways, that's the solution I was looking for, thanks. But what happens if you wouldn't select the old object back into the DC?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Change cursor on single edit control
    By Niara in forum Windows Programming
    Replies: 3
    Last Post: 01-11-2009, 09:52 AM
  2. Controlling edit control input
    By Gerread in forum Windows Programming
    Replies: 6
    Last Post: 05-03-2007, 08:56 PM
  3. Buttons + Edit Control
    By jay kay in forum Windows Programming
    Replies: 6
    Last Post: 03-09-2005, 05:36 PM
  4. Controlling an edit control
    By master5001 in forum Windows Programming
    Replies: 2
    Last Post: 10-16-2001, 03:08 PM
  5. Rich edit control example Win API
    By Echidna in forum Windows Programming
    Replies: 1
    Last Post: 09-17-2001, 02:12 AM