Tengo una casilla de verificación que quiero medir con precisión para poder colocar los controles en un cuadro de diálogo correctamente. Puedo medir fácilmente el tamaño del texto en el control, pero no conozco la forma "oficial" de calcular el tamaño de la casilla de verificación y el espacio antes (o después) del texto.¿Cómo obtener el tamaño del cheque y el espacio en la casilla de verificación?
Respuesta
estoy bastante seguro de que el ancho de la casilla de verificación es igual a
int x = GetSystemMetrics(SM_CXMENUCHECK);
int y = GetSystemMetrics(SM_CYMENUCHECK);
A continuación, puede calcular el área interior de restar el siguiente ...
int xInner = GetSystemMetrics(SM_CXEDGE);
int yInner = GetSystemMetrics(SM_CYEDGE);
uso que, en mi código y no he tenido ningún problema hasta el momento ...
Este código no funciona en Win7 con UI escalada (fuentes 125% más grandes o 150% más grandes). Lo único que parece funcionar es:
int WID = 13 * dc.GetDeviceCaps(LOGPIXELSX)/96;
int HEI = 13 * dc.GetDeviceCaps(LOGPIXELSY)/96;
Es una pena que Microsoft no haya proporcionado una forma de saber esto con certeza. Estaba luchando con la misma pregunta y la respuesta proporcionada anteriormente no está completa. El problema principal es que si la fuente de la ventana de diálogo está configurada en un valor diferente al tamaño predeterminado, esa solución no funcionará porque las casillas de verificación se redimensionarán.
Así es como he resuelto este problema (es solo una aproximación que parece haber funcionado para mí). El código es para el proyecto MFC.
1 - Crea dos controles de prueba en su forma, una casilla de verificación y una caja de radio:
2 - Definir la siguiente estructura personalizada:
struct CHECKBOX_DIMS{
int nWidthPx;
int nHeightPx;
int nSpacePx; //Space between checkbox and text
CHECKBOX_DIMS()
{
nWidthPx = 0;
nHeightPx = 0;
nSpacePx = 0;
}
};
3 - Llame a la siguiente código cuando el formulario se inicializa para cada uno de los controles de prueba (que los medirá y eliminará para que los usuarios finales no los parezcan):
BOOL OnInitDialog()
{
CDialog::OnInitDialog();
//Calculate the size of a checkbox & radio box
VERIFY(GetInitialCheckBoxSize(IDC_CHECK_TEST, &dimsCheckBox, TRUE));
VERIFY(GetInitialCheckBoxSize(IDC_RADIO_TEST, &dimsRadioBox, TRUE));
//Continue with form initialization ...
}
BOOL GetInitialCheckBoxSize(UINT nCtrlID, CHECKBOX_DIMS* pOutCD, BOOL bRemoveCtrl)
{
//Must be called initially to calculate the size of a checkbox/radiobox
//'nCtrlID' = control ID to measure
//'pOutCD' = if not NULL, receives the dimensitions
//'bRemoveCtrl' = TRUE to delete control
//RETURN:
// = TRUE if success
BOOL bRes = FALSE;
//Get size of a check (not exactly what we need)
int nCheckW = GetSystemMetrics(SM_CXMENUCHECK);
int nCheckH = GetSystemMetrics(SM_CYMENUCHECK);
//3D border spacer (not exactly what we need either)
int nSpacerW = GetSystemMetrics(SM_CXEDGE);
//Get test checkbox
CButton* pChkWnd = (CButton*)GetDlgItem(nCtrlID);
ASSERT(pChkWnd);
if(pChkWnd)
{
CRect rcCheckBx;
pChkWnd->GetWindowRect(&rcCheckBx);
//We need only the height
//INFO: The reason why we can't use the width is because there's
// an arbitrary text followed by a spacer...
int h = rcCheckBx.Height();
CDC* pDc = pChkWnd->GetDC();
if(pDc)
{
//Get horizontal DPI setting
int dpiX = pDc->GetDeviceCaps(LOGPIXELSX);
//Calculate
if(pOutCD)
{
//Use height as-is
pOutCD->nHeightPx = h;
//Use height for the width
pOutCD->nWidthPx = (int)(h * ((double)nCheckW/nCheckH));
//Spacer is the hardest
//INFO: Assume twice and a half the size of 3D border &
// take into account DPI setting for the window
// (It will give some extra space, but it's better than less space.)
// (This number is purely experimental.)
// (96 is Windows DPI setting for 100% resolution setting.)
pOutCD->nSpacePx = (int)(nSpacerW * 2.5 * dpiX/96.0);
}
//Release DC
pChkWnd->ReleaseDC(pDc);
if(bRemoveCtrl)
{
//Delete window
bRes = pChkWnd->DestroyWindow();
}
else
{
//Keep the window
bRes = TRUE;
}
}
}
return bRes;
}
4 - Ahora usted puede fácilmente cambiar el tamaño de cualquier cuadro de casilla o radio llamando a este:
//Set checkbox size & new text
VERIFY(SetCheckBoxTextAndSize(this, IDC_CHECK_ID, &dimsCheckBox, L"New text") > 0);
//Just resize radio box
VERIFY(SetCheckBoxTextAndSize(this, IDC_RADIO_ID, &dimsRadioBox, NULL) > 0);
int SetCheckBoxTextAndSize(CWnd* pParWnd, UINT nCheckBoxID, CHECKBOX_DIMS* pDims, LPCTSTR pNewText)
{
//Set size of the checkbox/radio to 'pNewText' and update its size according to its text
//'pParWnd' = parent dialog window
//'nCheckBoxID' = control ID to resize (checkbox or radio box)
//'pDims' = pointer to the struct with checkbox/radiobox dimensions
//'pNewText' = text to set, or NULL not to change the text
//RETURN:
// = New width of the control in pixels, or
// = 0 if error
int nRes = 0;
ASSERT(pParWnd);
ASSERT(pDims);
CButton* pChkWnd = (CButton*)pParWnd->GetDlgItem(nCheckBoxID);
ASSERT(pChkWnd);
if(pChkWnd)
{
CDC* pDc = pChkWnd->GetDC();
CFont* pFont = pChkWnd->GetFont();
if(pDc)
{
if(pFont)
{
//Make logfont
LOGFONT lf = {0};
if(pFont->GetLogFont(&lf))
{
//Make new font
CFont font;
if(font.CreateFontIndirect(&lf))
{
//Get font from control
CFont* pOldFont = pDc->SelectObject(&font);
//Get text to set
CString strCheck;
if(pNewText)
{
//Use new text
strCheck = pNewText;
}
else
{
//Keep old text
pChkWnd->GetWindowText(strCheck);
}
//Calculate size
RECT rc = {0, 0, 0, 0};
::DrawText(pDc->GetSafeHdc(), strCheck, strCheck.GetLength(), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE);
//Get text width
int nTextWidth = abs(rc.right - rc.left);
//See if it's valid
if(nTextWidth > 0 ||
(nTextWidth == 0 && strCheck.GetLength() == 0))
{
//Get location of checkbox
CRect rcChk;
pChkWnd->GetWindowRect(&rcChk);
pParWnd->ScreenToClient(rcChk);
//Update its size
rcChk.right = rcChk.left + pDims->nWidthPx + pDims->nSpacePx + nTextWidth;
//Use this line if you want to change the height as well
//rcChk.bottom = rcChk.top + pDims->nHeightPx;
//Move the control
pChkWnd->MoveWindow(rcChk);
//Setting new text?
if(pNewText)
{
pChkWnd->SetWindowText(pNewText);
}
//Done
nRes = abs(rcChk.right - rcChk.left);
}
//Set font back
pDc->SelectObject(pOldFont);
}
}
}
//Release DC
pChkWnd->ReleaseDC(pDc);
}
}
return nRes;
}
Respuesta corta:
Versión larga
De MSDN Layout Specifications: Win32, nos tener las especificaciones de las dimensiones de una casilla de verificación.
Es 12 unidades de diálogo desde el borde izquierdo del control al inicio del texto:
y un control de casilla de verificación es de 10 unidades de diálogo de altura:
Surfaces and Controls Height (DLUs) Width (DLUs)
===================== ============= ===========
Check box 10 As wide as possible (usually to the margins) to accommodate localization requirements.
Primero calculamos el tamaño de una unidad de diálogo horizontal y vertical:
const dluCheckBoxInternalSpacing = 12; //12 horizontal dlus
const dluCheckboxHeight = 10; //10 vertical dlus
Size dialogUnits = GetAveCharSize(dc);
Integer checkboxSpacing = MulDiv(dluCheckboxSpacing, dialogUnits.Width, 4);
Integer checkboxHeight = MulDiv(dluCheckboxHeight, dialogUnits.Height, 8);
Uso de la práctica función de ayudante:
Size GetAveCharSize(HDC dc)
{
/*
How To Calculate Dialog Base Units with Non-System-Based Font
http://support.microsoft.com/kb/125681
*/
TEXTMETRIC tm;
GetTextMetrics(dc, ref tm);
String buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Size result;
GetTextExtentPoint32(dc, buffer, 52, out result);
result.Width = (result.X/26 + 1)/2; //div uses trunc rounding; we want arithmetic rounding
result.Height = tm.tmHeight;
return result;
}
Ahora que sabemos el número de píxeles (checkboxSpacing
) para añadir, calculamos el tamaño de la etiqueta de forma normal:
textRect = Rect(0,0,0,0);
DrawText(dc, Caption, -1, textRect, DT_CALCRECT or DT_LEFT or DT_SINGLELINE);
chkVerification.Width = checkboxSpacing+textRect.Right;
chkVerification.Height = checkboxHeight;
Nota: Cualquier código publicado en el dominio público. No se requiere atribución.
Ok dudes my way es posible que no sean los tiempos de uso en tiempo de ejecución, pero a mí me funciona en cualquier caso que haya probado hasta ahora. En el beginnin de mis proggys puse en una función para obtener el tamaño y almacenarlo en una variable global (sí he oído esto sería malo, pero no me importa sobre esto)
aquí la explicación:
- Crear una vista de árbol (invisible si quieres)
- Crear una lista de imágenes con al menos la imagen 1 en el interior (16x16 tamaño)
- Establecer la lista de imágenes a la vista de árbol ("TVSIL_NORMAL")
- obtener el "TVSIL_STATE" lista de imágenes de treeview (tienes que crear " TVSIL_NORMAL "antes, de lo contrario, esta fallara!)
- Use ImageList_GetIconSize (..) y almacene el tamaño. Guau, las casillas de verificación y los botones de radio tienen el mismo tamaño que los íconos de estado de la vista de árbol. ¡Ahora tienes lo que quieres!
- Destruir al "TVSIL_NORMAL" imagelist
- Destruye la vista de árbol
este código sólo necesita unos pocos microsegundos al comienzo de mis proggies y puedo usar el valor cada vez que lo necesite.
Preámbulo:
que tenía la misma pregunta al tratar de determinar el tamaño necesario del control de casilla de verificación de un texto dado y se encontró que las respuestas existentes no funcionan realmente para mí, por varias razones:
SM_CXMENUCHECK
no da cuenta de la brecha. De hecho, no estoy convencido de que esto sea incluso para casillas de verificación regulares, aunque puede tener el mismo valor. También puede depender de estilos visuales habilitados.- Las otras respuestas fueron demasiado complicadas y se sintieron un poco hacky (sin intención de falta de respeto, es MS que no lo hacen fácil).
- El diseño de 12DLU indicado fue muy útil, aunque nuevamente se siente arbitrario sin una métrica de sistema en la que confiar.
- Las respuestas que probé todavía no dieron un valor de píxel lo suficientemente alto como para detener el ajuste del texto de la casilla de verificación.
Mi investigación:
Miré a cómo vino reproduce el comportamiento y encontraron que también da los mismos resultados que simplemente asumiendo 12DLU. Sin embargo, el texto todavía está envuelto, a menos que agregue 3 píxeles adicionales al ancho (aunque el texto debería quedar bien sin). También noté que GetTextExtentPoint32
produce un valor de 3 para una cadena vacía (hmmm ...)
Desactivar el estilo BS_MULTILINE
obviamente detuvo el ajuste del texto. Mi conjetura es que los cálculos de ajuste de palabras de DrawTextW
son imperfectos.
En este punto, decidí que la solución más simple era simplemente agregar 1 espacio adicional a GetTextExtentPoint32
, por lo que definitivamente habría suficientes píxeles. La sobreestimación de un par de píxeles fue aceptable para mí.
Tenga en cuenta que todo esto supone que su aplicación se manifiesta como DPI consciente. De lo contrario, me pareció que la casilla de verificación parecía mucho más grande en algunos sistemas con Windows 7 (aunque no todos).
Mi solución (en su mayoría del Vino):
// This code gets the size of a piece of text and adds the size of a
// checkbox and gap. Note that this is very rough code with no error handling.
BOOL isCheckbox = TRUE;
HWND dialog = ... // Your control or dialog
HFONT font = ... // The font your control will use if it hasn't been set yet
PTCHAR text = ... // Your text
HFONT currentFont;
SIZE size;
HDC dc = GetDC(dialog);
if (!font) {
font = (HFONT)SendMessage(dialog, WM_GETFONT, 0, 0);
}
currentFont = (HFONT)SelectObject(dc, font); // NB: You should add error handling here
if (isCheckbox) {
// Or you can disable BS_MULTILINE
_tcscat(text, TEXT(" ")); // NB: This assumes text is allocated for +1 char
}
GetTextExtentPoint32(dc, text, _tcslen(text), &size); // NB: You should add error handling here
if (isCheckbox) {
int checkBoxWidth = 12 * GetDeviceCaps(dc, LOGPIXELSX)/96 + 1;
int checkBoxHeight = 12 * GetDeviceCaps(dc, LOGPIXELSY)/96 + 1;
int textOffset;
GetCharWidthW(dc, '0', '0', &textOffset);
textOffset /= 2;
size->cx += checkBoxWidth + textOffset;
if (size->cy < checkBoxHeight) {
size->cy = checkBoxHeight;
}
}
if (currentFont) {
SelectObject(dc, currentFont);
}
ReleaseDC(dialog, dc);
- 1. ¿Cómo puedo aumentar el espacio entre la casilla de verificación y el texto asociado?
- 2. Cambiar el tamaño de una casilla de verificación y la marca de verificación
- 3. Tamaño de casilla de verificación IE 9
- 4. cambiar el color del borde de la casilla de verificación
- 5. ¿Cómo aumentar el tamaño de la casilla de verificación en WinForms?
- 6. ¿Cómo elimino el borde de la casilla de verificación?
- 7. Obtener la identificación de una casilla de verificación? - jQuery
- 8. ¿Cómo hago que una casilla de verificación sea más pequeña que el tamaño predeterminado?
- 9. el estado de una casilla de verificación en Cocoa
- 10. obtener múltiples valores de la casilla de verificación
- 11. Control CheckedListBox - Solo marcando la casilla de verificación cuando se hace clic en la casilla de verificación real
- 12. cómo establecer la casilla de verificación en el lado derecho del texto
- 13. ¿Cómo puedo obtener los valores de casilla de verificación en el androide
- 14. cómo borrar la casilla de verificación
- 15. ¿Cómo obtener el valor de una casilla de verificación en capibara?
- 16. usando el manillar bindAttr para la casilla de verificación
- 17. ¿Cómo obtener el valor de la casilla marcada en php?
- 18. Lista de Android y casilla de verificación
- 19. cómo obtener los valores de casilla de verificación utilizando php CodeIgniter en el controlador
- 20. jQuery: seleccione la casilla de verificación basado en el nombre y el valor
- 21. JQuery La verificación de la casilla de verificación está marcada
- 22. Obtener el atributo de valor de la casilla de verificación cliqueada a través de JQuery
- 23. Casilla de verificación Grails
- 24. Casilla de verificación en ExpandableListView
- 25. Winforms Casilla de verificación Enfoque Problema si no se aplica texto en la casilla de verificación
- 26. Cómo obtener el tamaño del archivo HttpPostedFileBase
- 27. personalizar la casilla de verificación preferencia
- 28. ¿Cómo obtener el tamaño del widget de la aplicación?
- 29. knockout.js y escuchar para verificar el evento en la casilla de verificación
- 30. Obtener el tamaño del puntero en C
parece funcionar bien para mí :) (? Odd cómo es "cheque menú" y no es una opción para una casilla de verificación regular) –
I Sé que es un hilo viejo, lo encontré a través de Google. Lamentablemente, esta respuesta no es del todo correcta. Ver mi explicación a continuación ... – c00000fd