2012-02-09 9 views
5

Para mi aplicación, necesito crear un cuadro de diálogo sin usar el recurso. Estoy tratando de hacerlo con DialogBoxInderect función. El código es increíblemente feo, pero de alguna manera lo logré.DialogBoxIndirect crea un diálogo más grande que

El problema es que el diálogo, por alguna razón, es mucho más grande de lo que pedí con fuentes mucho más grandes.

Aquí es cómo el diálogo se ve como si lo cargo a partir de recursos: enter image description here

Y aquí es el diálogo con el mismo tamaño indicado cuando llamo DialogBoxInderect función. enter image description here

Aquí es como se define en el código:

HGLOBAL    hGlobal; 
LPDLGTEMPLATE  wlsDialogTemplate; 
LPDLGITEMTEMPLATE wlsDialogItemTemplate; 
LPWORD    nextItem; 
LPWSTR    itemString; 
int32_t    itemStringLength; 

// Check for memory allocation errors 
hGlobal = GlobalAlloc(GMEM_ZEROINIT, 1024); 
if (!hGlobal) 
    return -1; 

wlsDialogTemplate = (LPDLGTEMPLATE)GlobalLock(hGlobal); 

// Define a dialog box. 
wlsDialogTemplate->style = WS_CAPTION; 
wlsDialogTemplate->x  = 0; 
wlsDialogTemplate->y  = 0; 
wlsDialogTemplate->cx  = 320; 
wlsDialogTemplate->cy  = 115; 

GlobalUnlock(hGlobal); 
retCode = DialogBoxIndirect(0, (LPDLGTEMPLATE)hGlobal, 0, ActivateWlsMsgDialog); 

Y aquí es como se define en el archivo RC:

IDD_WLS_SMALL_MESSAGE_DLG DIALOGEX 0, 0, 320, 115 
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION 
CAPTION "Dialog" 
FONT 8, "MS Shell Dlg", 400, 0, 0x1 
BEGIN 
    DEFPUSHBUTTON "OK",ID_CUSTOM_OK,175,95,120,15 
    PUSHBUTTON  "Cancel",ID_CUSTOM_CANCEL,45,95,120,15 
    CTEXT   "Static",IDC_HEADER_TEXT,120,10,170,70 
    CONTROL   "",IDC_LOGO,"Static",SS_BITMAP,16,10,83,70 
END 

Como se puede ver, el segundo de diálogo es mucho más grande que definido. Traté de jugar con varias banderas de estilo pero sin ningún éxito (es por eso que hay una cruz roja en el diálogo más grande).

¿Alguna ayuda con eso? Gracias!

Respuesta

6

El tamaño más grande es fácil de explicar. Windows ajusta automáticamente el tamaño del diálogo de acuerdo con su fuente, y el cuadro de diálogo más grande usa una fuente diferente. De hecho, está utilizando la fuente predeterminada del sistema (más información sobre el tema confuso de las fuentes de diálogo de Windows se encuentra en mi respuesta here).

Así que el problema real en el que enfocarse es por qué está usando una fuente diferente, y corregir eso resolverá el problema de tamaño.

En el archivo de recursos del cuadro de diálogo, especifique DS_SETFONT flag como uno de los estilos del cuadro de diálogo. Según la documentación, esta bandera

[i] indica que el encabezado de la plantilla de cuadro de diálogo (estándar o extendido) contiene datos adicionales que especifican la fuente a usar para el texto en el área del cliente y los controles del diálogo caja. Si es posible, el sistema selecciona una fuente de acuerdo con los datos de fuente especificados. El sistema pasa un identificador a la fuente al cuadro de diálogo y a cada control enviándoles el mensaje WM_SETFONT.

Eso explica por qué que uno está mostrando con la fuente esperada.

La siguiente pregunta lógica es qué tiene de diferente la plantilla de diálogo creada dinámicamente, que se muestra con la función DialogBoxIndirect. El culpable es, una vez más, la bandera DS_SETFONT, pero en este caso, la bandera está ausente. Esto significa que el cuadro de diálogo no contiene ninguna información sobre qué fuente usar para mostrar sus controles, y el sistema adopta de manera predeterminada la fuente predeterminada del sistema (que es la fea fuente de Windows 2.0 que ve en la segunda captura de pantalla).

Una vez que hemos llegado a este entendimiento, la solución debe ser obvia: debe indicarle al cuadro de diálogo qué fuente desea que use.Hay dos posibles maneras de hacerlo que vienen a la mente:

  1. Puede establecer el indicador DS_SETFONT y proporcionar la información de fuente en la cabecera de la plantilla de la caja de diálogo como se describe en la documentación anteriormente unido.
  2. O simplemente puede crear y establecer la fuente del diálogo en respuesta al mensaje WM_INITDIALOG.

Este último es probablemente lo que realmente quiere hacer, ya que le permite utilizar la fuente real del sistema(que, confusamente, es diferente de lo que he estado llamando la sistema de "default" fuente), que es la interfaz de usuario de Segoe en Windows Vista y posterior. Tenga en cuenta que incluso en su primera captura de pantalla, está utilizando MS Sans Serif y por lo tanto sobresale como un pulgar dolorido en la interfaz Aero. Nuevamente, vea this answer para obtener más información acerca de las fuentes de lo que siempre quiso saber y código de muestra para hacer que esto funcione. Deberá asegurarse de configurar la fuente del cuadro de diálogo y con todos sus controles secundarios.

+0

Muchas gracias por la respuesta rápida. Sí, sospeché que el problema es la fuente, sin embargo, no pude encontrar ningún ejemplo. ¿Cómo agrego la información de la fuente al encabezado? ¿Me puede ayudar con eso? Establecer la fuente requerida como respuesta a WM_INITDIALOG no servirá, ya que cambiará la fuente pero no cambiará el tamaño del cuadro de diálogo a menos que cambie el tamaño manualmente. –

+0

Por cierto, el término técnico es DLU = unidades de diálogo. Usted (por lo general) diseña un cuadro de diálogo en DLU, no píxeles – demorge

+0

@Iron: encontrará información de fondo adicional [aquí en MSDN] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644994. fuentes aspx #) (y realmente ese artículo completo). Creo que si entiendes cómo funciona todo, escribir el código real es la parte fácil. Pero aparece una búsqueda rápida de Google para el código de muestra [esta clase de plantilla de diálogo] (http://www.flipcode.com/archives/DialogTemplate.cpp). No sé por qué 'WM_INITDIALOG' no funciona para usted; Lo hago de esa manera todo el tiempo y todo se redimensiona correctamente. –

0

He jugado con DialogBoxIndirect (en realidad con DialogBoxIndirectParam), y esta es la parte del código que establece la fuente. Observe la opción DS_SHELLFONT.

LPWORD lpwAlign(LPWORD lpIn, int nAlignment) 
{ 
    return (LPWORD)(((ULONG_PTR)lpIn + nAlignment - 1) & -nAlignment); 
} 

LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, LPMYMESSAGEPARAMS pParams) 
{ 
    WORD mem[1024];   // Buffer for dialog resource 
    LPDLGTEMPLATEW lpdt;  // Pointer to heading resource structure 
    LPDLGITEMTEMPLATEW lpdit; // Pointer to current control 
    LPWORD lpw;    // Cursor to resource buffer 
    LPWSTR lpwsz;    // Cursor to resource buffer (of type WCHAR) 
    LPCWSTR lpwszCaption;  // Aux pointer for text copying 
    LRESULT ret;    // Function's return value 

    lpdt = (LPDLGTEMPLATEW)lpwAlign(mem, 4); 

    //----------------------- 
    // Define a dialog box. 
    //----------------------- 
    lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | 
     DS_MODALFRAME | DS_CENTER | DS_SHELLFONT; 
    lpdt->dwExtendedStyle = 0; 
    lpdt->cdit = 3; // number of controls 
    lpdt->x = 0; lpdt->y = 0; 
    lpdt->cx = 164; lpdt->cy = 49; 

    lpw = (LPWORD)(lpdt + 1); 
    // Dialog menu 
    *lpw++ = 0; 
    // Dialog class 
    *lpw++ = 0; 
    // Dialog title 
    for (lpwsz = (LPWSTR)lpw, lpwszCaption = L"Choose language"; 
     *lpwsz++ = *lpwszCaption++; 
     ); 
    lpw = (LPWORD)lpwsz; 
    // Dialog font 
    if (lpdt->style & (DS_SETFONT | DS_SHELLFONT)) 
    { 
     // Size 
     *lpw++ = 8; 
     // Typeface name 
     for (lpwsz = (LPWSTR)lpw, lpwszCaption = L"MS Shell Dlg"; 
      *lpwsz++ = *lpwszCaption++; 
      ); 
     lpw = (LPWORD)lpwsz; 
    } 


    // Define the rest of the controls 
    ... 

    ret = DialogBoxIndirectParamW(hinst, lpdt, 
     hwndOwner, MyMessageProc, (LPARAM)pParams); 

    return ret; 
} 
+0

¡Gracias! Solo pensé en esa parte yo mismo. Sin embargo, tiene un efecto muy inusual. Si uso la fuente "MS Shell Dlg" MyMessageProc, mantenga constantemente el mensaje WM_SETFONT y el programa se para. Si utilizo cualquier otro elemento, recibo el mensaje WM_SETFONT, pero no importa lo que haga allí, no tiene ningún efecto :( –

+0

Lo siento, no puedo ayudarte con eso. En mi código WM_SETFONT se procesa solo una vez. – Dialecticus

+0

El problema es que, como [la documentación] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645394.aspx) indica, * "El estilo' DS_SHELLFONT' no se admite en el encabezado 'DLGTEMPLATE'." * Lectura recomendada: [¿Cuál es el problema con el indicador 'DS_SETFONT'?] (Http://blogs.msdn.com/b/oldnewthing/archive/2005/02/04/366987.aspx) –

0

Esto se puede resolver en el controlador de diálogo buscando el mensaje WM_INITDIALOG, y luego Cambiando la fuente de todos los controles en el cuadro de diálogo.

int CALLBACK SetChildFont(HWND child, LPARAM font) { 
    SendMessage(child, WM_SETFONT, font, TRUE); 
    return TRUE; 
} 

static int CALLBACK MyMessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 
     switch (msg) { 
     case WM_INITDIALOG: 
      /* Set font for dialog and all child controls */ 
      EnumChildWindows(hwnd, (WNDENUMPROC)SetChildFont, (LPARAM)GetStockObject(DEFAULT_GUI_FONT)); 
      break; 
     } 
     return 0; 
} 
Cuestiones relacionadas