I'm using GetTextExtentPoint32()
to measure the text size and calculate the width and height of my combobox. However, it seems to be adding margin proportional to the amount of text, that I'd to get rid of. It seems the larger the string is, the larger margin I get on right. How do I it doesn't add this margin? a small one is acceptable but look at the second image, the big empty space on right.
With small strings, I find this margin acceptable:
However, with big ones, I get this big white space on right side, that I'd to get rid of:
I'm measuring the text size like this:
int len = wcslen(s);
HDC dc = GetDC(hwndCombo);
SIZE sz;
assert(GetTextExtentPoint32(dc, s, len, &sz));
ReleaseDC(hwndCombo, dc);
int weight = sz.cx + 10;
int height = sz.cy;
assert(SetWindowPos(hwndCombo, HWND_TOP, 0, 0, weight, height, SWP_NOMOVE));
full code:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "Comdlg32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <winuser.h>
#include <assert.h>
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int largestIndex();
HFONT getDefaultFont();
void SetDefaultFont(HWND hwnd);
HFONT hDefaultSystemFont;
HINSTANCE g_hinst;
const wchar_t *items[] =
{
L"Windows", L"Mac",
L"FreeBSD", L"Arch",
L"aaaaaa!!!!!!!aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#",
L"foo",
L"baaaa"
};
HWND hwndCombo;
enum
{
ID_COMBO = 10,
ID_BTN1,
};
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg ;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Application";
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc ;
wc.hCursor = LoadCursor(0,IDC_ARROW);
g_hinst = hInstance;
RegisterClassW(&wc);
hwnd = CreateWindowW(wc.lpszClassName, L"",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 300, 170, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch(msg)
{
case WM_CREATE:
{
hwndCombo = CreateWindowW(L"Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
10, 10, 60, 110, hwnd, (HMENU) ID_COMBO, g_hinst, NULL);
for (int i = 0; i < COUNTOF(items); i++ )
{
SendMessageW(hwndCombo, CB_ADDSTRING, 0, (LPARAM) items[i]);
}
SetDefaultFont(hwndCombo);
HWND btn1 =
CreateWindowW(L"Button", L"Click me",
WS_CHILD | WS_VISIBLE,
5, 40, 90, 25, hwnd, (HMENU) ID_BTN1, g_hinst, NULL);
SetDefaultFont(btn1);
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case ID_BTN1:
{
int i = largestIndex();
wchar_t *s = (wchar_t*) items[i];
int len = wcslen(s);
HDC dc = GetDC(hwndCombo);
SIZE sz;
assert(GetTextExtentPoint32(dc, s, len, &sz));
ReleaseDC(hwndCombo, dc);
int weight = sz.cx + 10;
int height = sz.cy;
assert(SetWindowPos(hwndCombo, HWND_TOP, 0, 0, weight, height, SWP_NOMOVE));
}
break;
default:
break;
}
}
break;
case WM_DESTROY:
DeleteObject(hDefaultSystemFont);
hDefaultSystemFont = NULL;
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
int largestIndex()
{
int m = 0;
int idx = -1;
for(int i = 0; i < COUNTOF(items); i++) {
int l = wcslen(items[i]);
if(l > m) {
m = l;
idx = i;
}
}
return idx;
}
HFONT getDefaultFont()
{
if(hDefaultSystemFont == NULL) {
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
hDefaultSystemFont = CreateFontIndirect(&ncm.lfMessageFont);
}
return hDefaultSystemFont;
}
void SetDefaultFont(HWND hwnd)
{
SendMessage(hwnd, WM_SETFONT, (LPARAM) getDefaultFont(), TRUE);
}
You are using different font for measurements.
Try
int len = wcslen(s);
HDC dc = GetDC(hwndCombo);
SIZE sz;
// Set correct font
HFONT old = SelectObject(dc,hDefaultSystemFont);
// or
// HFONT control_font = (HFONT)SendMessage(hwndCombo, WM_GETFONT, 0, 0);
// HFONT old = SelectObject(dc,control_font);
assert(GetTextExtentPoint32(dc, s, len, &sz));
// Restore font for cleanup
SelectObject(dc,old);
ReleaseDC(hwndCombo, dc);
int weight = sz.cx + 10;
int height = sz.cy;