2012-02-09 32 views
5

對於我的應用程序,我需要創建一個對話框而不使用資源。 我正在嘗試使用DialogBoxInderect函數。代碼難以置信地醜陋,但不知何故,我成功地做到了。DialogBoxIndirect創建的對話框大於

問題是,出於某種原因,對話框比我用更大的字體問得多。

下面是對話的樣子,如果我加載它從資源: enter image description here

這裏是說同樣大小的對話框當我打電話DialogBoxInderect功能。 enter image description here

這裏是它是如何在代碼中定義:

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

這裏是它是如何在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 

正如你所看到的,第二個對話框是多少比定義的大。我試圖玩各種風格的旗幟,但沒有任何成功(這就是爲什麼在更大的對話中有紅十字)。

任何幫助嗎? 謝謝!

回答

6

較大的尺寸很容易解釋。 Windows根據其字體自動調整對話框的大小,而較大的對話框使用不同的字體。實際上,它使用默認的系統字體(關於Windows對話框字體混淆問題的更多信息可在我的回答here中找到)。

所以真正要關注的問題是爲什麼它使用不同的字體,並修復它可以解決尺寸問題。

在對話框資源文件中,您指定DS_SETFONT flag作爲對話框樣式之一。根據文檔,此標誌

[i]表示對話框模板(標準或擴展)的標題包含額外的數據,指定用於客戶區域中的文本和對話框的控件的字體框。如果可能,系統會根據指定的字體數據選擇一種字體。系統通過發送WM_SETFONT消息將句柄傳遞給對話框和每個控件。

因此,這解釋了爲什麼人顯示與預期的字體。

下一個邏輯問題與您的動態創建的對話框模板有什麼不同,如DialogBoxIndirect函數所示。罪魁禍首再次是DS_SETFONT標誌,但在這種情況下,該標誌不存在。這意味着該對話框不包含任何有關使用哪種字體來顯示其控件的信息,並且系統默認爲默認系統字體(這是您在第二個屏幕截圖中看到的醜陋的Windows 2.0時代字體)。

一旦我們達成了這個理解,解決方案應該是顯而易見的:您需要告訴對話框您希望使用哪種字體。這樣做有兩種可能的方式浮現在腦海:

  1. 您可以設置DS_SETFONT標誌和作爲上述聯文檔中描述提供對話框模板的標題的字體信息。
  2. 或者您可以簡單地創建並設置對話框的字體以響應WM_INITDIALOG消息。

後者可能是你真正想做的事,因爲它允許您使用實際系統字體(其中,容易混淆,是我一直在呼籲的「默認」系統不同字體),這是Windows Vista及更高版本中的Segoe UI。請注意,即使在您的第一個屏幕截圖中,它使用的是MS Sans Serif,因此在Aero界面中顯得很粗糙。同樣,請參閱this answer以瞭解有關字體的更多信息,這些字體比您想知道的還要簡單。您需要確保爲對話框本身設置了字體的所有子控件。

+0

非常感謝您的快速回復。是的,我懷疑問題是字體,但是,我找不到任何示例,我如何將字體信息添加到標題。你能幫助我嗎?將所需的字體設置爲對WM_INITDIALOG的響應將無法實現,因爲它會更改字體,但不會調整對話框的大小,除非手動調整它的大小。 – 2012-02-09 09:05:30

+0

順便說一句,技術術語是DLU = dialog units。您(通常)在DLUs中設計對話框而不是像素 – demorge 2012-02-09 10:30:57

+0

@Iron:您可以在MSDN上找到其他背景信息(http://msdn.microsoft.com/en-us/library/windows/desktop/ms644994。 aspx#字體)(真的是整個文章)。我認爲如果你明白它是如何工作的,編寫實際的代碼是很容易的部分。但是Google的搜索示例代碼很快就會出現[此對話框模板類](http://www.flipcode.com/archives/DialogTemplate.cpp)。我不知道爲什麼'WM_INITDIALOG'不適合你;我一直這樣做,一切都得到正確調整。 – 2012-02-09 17:56:20

0

我曾玩過DialogBoxIndirect(實際上帶有DialogBoxIndirectParam),下面是設置字體的代碼部分。觀察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

謝謝!我只是想自己的那部分。但是,它有一些非常不尋常的效果。如果我使用「MS Shell Dlg」字體MyMessageProc不斷獲取WM_SETFONT消息並且程序停止。如果我使用任何其他幻想我得到WM_SETFONT消息,但無論我在那裏做什麼,它都沒有效果:( – 2012-02-09 10:23:10

+0

對不起,不能幫你。在我的代碼WM_SETFONT只處理一次。 – Dialecticus 2012-02-09 11:29:55

+0

問題是,作爲[文檔](http://msdn.microsoft.com/en-us/library/windows/desktop/ms645394.aspx)表示,*「DLGTEMPLATE'標頭中不支持'DS_SHELLFONT'樣式。」 *推薦閱讀:[與DS_SETFONT標誌有什麼關係?](http://blogs.msdn.com/b/oldnewthing/archive/2005/02/04/366987.aspx) – 2012-02-09 18:05:56

0

這可以在對話框的處理程序通過尋找WM_INITDIALOG消息,然後設置字體在該對話框中的所有控件來解決。

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