2012-02-09 9 views
5

Per la mia applicazione ho bisogno di creare una finestra di dialogo senza usare la risorsa. Sto provando a farlo con la funzione DialogBoxInderect. Il codice è incredibilmente brutto ma in qualche modo sono riuscito a farlo.DialogBoxIndirect crea una finestra di dialogo più grande di quella richiesta

Il problema è che il dialogo, per qualche motivo, è molto più grande di quello che ho chiesto con caratteri molto più grandi.

Ecco come la finestra si presenta come se carico dalla risorsa: enter image description here

E qui è il dialogo con la stessa dimensione indicata quando chiamo DialogBoxInderect funzione. enter image description here

Ecco come è definito nel codice:

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); 

Ed ecco come si è definita nel file 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 

Come si può vedere, la seconda finestra è molto più più grande di definito. Ho provato a giocare con varie bandiere di stile ma senza successo (ecco perché c'è una croce rossa nella finestra di dialogo più grande).

Qualsiasi aiuto con quello? Grazie!

risposta

6

La dimensione maggiore è facile da spiegare. Windows dimensiona automaticamente la finestra di dialogo in base al relativo carattere e la finestra di dialogo più grande utilizza un carattere diverso. Infatti, sta utilizzando il carattere di sistema predefinito (maggiori informazioni sul problema di confusione dei caratteri di dialogo di Windows si trovano nella mia risposta here).

Quindi il vero problema su cui concentrarsi è il motivo per cui sta utilizzando un font diverso e il fixing che risolve il problema delle dimensioni.

Nel file di risorse casella di dialogo, si specifica il DS_SETFONT flag come uno degli stili di finestra di dialogo. Secondo la documentazione, questo flag

[i] ndicates che l'intestazione del modello di finestra di dialogo (standard o estesa) contiene dati aggiuntivi che specificano il tipo di carattere da utilizzare per il testo nell'area client e controlli della finestra di dialogo scatola. Se possibile, il sistema seleziona un font in base ai dati del font specificato. Il sistema passa un handle al carattere alla finestra di dialogo e ad ogni controllo inviando loro il messaggio WM_SETFONT.

Quindi questo spiega perché che uno è la visualizzazione con il font previsto.

La prossima domanda logica è che cosa c'è di diverso sul modello di finestra creato dinamicamente, mostrato con la funzione DialogBoxIndirect. Il colpevole è, ancora una volta, il flag DS_SETFONT, ma in questo caso la bandiera è assente. Ciò significa che la finestra di dialogo non contiene alcuna informazione su quale font utilizzare per visualizzare i suoi controlli, e il sistema imposta automaticamente il font di sistema predefinito (che è il brutto font di Windows 2.0 che vedi nel secondo screenshot).

Una volta giunti a questa comprensione, la soluzione dovrebbe essere ovvia: è necessario indicare alla finestra di dialogo quale carattere si desidera utilizzare.Ci sono due possibili modi di fare in modo che vengono in mente:

  1. È possibile impostare il flag DS_SETFONT e fornire le informazioni di carattere nell'intestazione del modello di finestra di dialogo come descritto nella documentazione di cui sopra-linked.
  2. Oppure puoi semplicemente creare e impostare il carattere della finestra di dialogo in risposta al messaggio WM_INITDIALOG.

Quest'ultimo è probabilmente quello che vuole veramente fare, in quanto consente di utilizzare l'attuale carattere sistema (che, confusamente, è diverso da quello che io ho chiamato il sistema "default" font), che è l'interfaccia utente di Segoe in Windows Vista e versioni successive. Nota che anche nel tuo primo screenshot, sta usando MS Sans Serif e quindi sporge come un pollice dolente nell'interfaccia Aero. Ancora una volta, vedi this answer per ulteriori informazioni sui caratteri di quanti tu abbia mai voluto conoscere e esempi di codice per fare questo lavoro. Dovrai assicurarti di impostare il carattere per la finestra di dialogo e tutti i relativi controlli figlio.

+0

Grazie mille per la rapida risposta. Sì, ho il sospetto che il problema sia il font, tuttavia, non ho trovato alcun esempio su come aggiungere le informazioni sul font all'intestazione. Puoi aiutarmi con quello? L'impostazione del carattere richiesto come risposta a WM_INITDIALOG non risolverà il problema, poiché cambierà il carattere ma non ridimensionerà la finestra di dialogo a meno che non lo ridimensioni manualmente. –

+0

Btw, il termine tecnico è DLU = unità di dialogo. Si (di solito) progettare una finestra di dialogo in DLUs non pixel – demorge

+0

@Iron: Troverai ulteriori informazioni di base [qui su MSDN] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644994. Aspx # fonts) (e proprio quell'intero articolo). Penso che se capisci come funziona, scrivere il codice reale è la parte facile. Ma una rapida ricerca su Google per il codice di esempio risulta [questa classe template di dialogo] (http://www.flipcode.com/archives/DialogTemplate.cpp). Non so perché 'WM_INITDIALOG' non funzioni per te; Lo faccio sempre e tutto viene ridimensionato correttamente. –

0

Avevo giocato con DialogBoxIndirect (in realtà con DialogBoxIndirectParam), ed ecco la parte del codice che imposta il carattere. Osservare l'opzione 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

Grazie! Ho appena capito quella parte da solo. Tuttavia, ha un effetto molto insolito. Se si utilizza il carattere "MS Shell Dlg" MyMessageProc mantenere costantemente il messaggio WM_SETFONT e il programma si blocca. Se uso qualche altro fant, ottengo il messaggio WM_SETFONT, ma non importa cosa faccio lì non ha alcun effetto :( –

+0

Spiacente, non posso aiutarti con questo. Nel mio codice WM_SETFONT viene elaborato solo una volta. – Dialecticus

+0

Il problema è che, come [la documentazione] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645394.aspx) indica, * "Lo stile' DS_SHELLFONT' non è supportato nell'intestazione 'DLGTEMPLATE'." * Lettura consigliata: [Qual è l'accordo con il flag 'DS_SETFONT'?] (Http://blogs.msdn.com/b/oldnewthing/archive/2005/02/04/366987.aspx) –

0

questo può essere risolto nel vostro dialogo gestore, cercando per il messaggio WM_INITDIALOG, e quindi impostando il tipo di carattere per tutti i controlli nella finestra di dialogo.

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; 
} 
Problemi correlati