The default dialog box font in Windows is MS Shell Dlg.
I don't like it, because it's not correct.
It's easy to manually change the font of a single dialog item, but how do I display a dialog box with the "correct" system font (from lfMessageFont) applied to all of its controls by default (not manually) when calling DialogBox (or using ATL/WTL)?
Note:
The reason I've said "not manually" so many times is that I am looking for a solution better than looping through everything with EnumChildWindows (or the like). Does one exist?
From About Dialog Boxes:
The system font can vary between different versions of Windows. To
have your application use the system font no matter which system it is
running on, use DS_SHELLFONT with the typeface MS Shell Dlg, and use
the DIALOGEX Resource instead of the DIALOG Resource. The system maps
this typeface such that your dialog box will use the Tahoma font. Note
that DS_SHELLFONT has no effect if the typeface is not MS Shell Dlg.
I think this is what you want. If that doesn't work, then I guess you'll have to load the resource manually and modify the template before passing it to DialogBox.
Related
I have an app that is trying to display U+23CE (⏎). This is a terminal app, so we are using "Consolas"/"Cascadia"/"Courier". As far as I can see, none of these fonts have this character. And yet, in Visual Studio, when I am debugging this app, it actually displays it correctly in the debugger. Also, when displayed by the new Windows Terminal, it displays correctly. But when I use the app I am working with (actually Putty), it displays the "I don't know this character" glyph.
Putty is a classic Win32 app using ExtTextOutW() to draw that text. I have checked that the correct font is bound to the HDC.
I am assuming that Visual Studio and Windows Terminal are using DirectWrite or other more modern text output logic, but ultimately they have to be getting these unknown glyphs from somewhere.
UPDATE:
I found a font with that character ("Segue UI Symbol"), and if I set Putty to use that font, it displays the missing character (woohoo). Sadly, this is a proportional font, so it looks terrible, and this is not the solution.
#dvix pointed me at a Microsoft page discussing this exact topic, but its not clear which things are done by Windows and which by an app developer. I tried linking "Courier New" (Putty's default) to "Segoe Symbol"", but it made no difference. Does the Putty code need to do all the work itself? Detect an unknown character, read the Registry, and substitute the font for that one char? That is certainly doable, but a pain.
Windows can be directed to "borrow" missing glyphs in a font from another font that carries them using font linking. This applies to both consoles and GUI apps that use GDI (DrawText, ExtTextOut) to render text in Windows 2000 and later.
For example, the following registry entry will link the Consolas font to Segoe UI Symbol (the following can be saved as a .reg file and merged into the registry, will take effect at the next logon).
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink]
"Consolas"=hex(7):53,45,47,55,49,53,59,4d,2e,54,54,46,2c,53,65,\
67,6f,65,20,55,49,20,53,79,6d,62,6f,6c,00,00
; "Consolas"=REG_MULTI_SZ:"SEGUISYM.TTF,Segoe UI Symbol"
One handy tool to explore coverage of the different fonts is BabelMap. For example this is the list of fonts that carry U+23CE (⏎) on a fairly clean Win10 system.
Another feature of BabelMap is the option to create temporary user-defined composite fonts on the fly, as opposed to the ones "statically" defined in the registry. This is presumably done using the MLang
IMLangFontLink interface, more about that in Raymond Chen's How to display a string without those ugly boxes and Michael Kaplan's Font substitution and linking #2.
When I select a language from the language toolbar, windows automatically changes the input font to one with characters from that language. Is there are a way to change the default font to something else?
Thank you for your help
You can change the default UI font (which will affect everything). If the characters you are typing are supported by the default UI font, then a fallback font is selected, and you can't (officially) change what that is.
One method used to work upto Windows 7, I'm not sure if it still works with Windows 8.
First, remove all fonts that support the given locale, and remember to copy the font files to somewhere rather than just deleting them.
Then, install the font you want to render the given locale. Open a document with characters from that range. In absence of the previous font font, Windows seems to fall back to the one available with characters defined in that range. Then install all the other fonts. The one Windows had already set does not get changed even when the "original" default font is available again.
This article showed me how to install fonts from a script, but now I'm faced with the problem of removing them. How can I do that ? Any language is ok, I'll convert the info to what I need later.
EDIT: Okay, so I now know how to uninstall fonts ( most of the part at least ). I'm issuing calls to RemoveFontResource. After that I use SendMessage with parameters: 0xffff,0x001D,0,0 ( HWND_BROACAST,WM_FONTCHANGE ... and I forgot what the other two parameters stand for ). The thing is, this deletes the font, but in the Control Panel's Fonts entry, the font still appears there ( even though if you try to delete it from there as well, it will say it cannot read from source file or disk.
So basically, I'm deleting a font in this order:
deleting physically from the C:\Windows\Fonts
calling RemoveFontResource
calling SendMessage
What's the proper way of uninstalling?
From all the documentation I've ever seen those three lines of code are the "proper" way to do it but as we well know it doesn't quite work - as expected.
RemoveFontResource(fontPath);
DeleteFile(fontPath);
::SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
REBOOT
I executed the code above and duplicated your problem (control panel still shows the font, however the font file is gone). I then rebooted. Now the font is gone from the Fonts Control Panel applet.
Something else to note: even though control panel still showed the font as "there" applications no longer listed it in their font lists (I specifically tried Wordpad, before and after deleting webdings.ttf - without rebooting)
Yea i know - rebooting is a poor solution - especially if you need to update the Font since you can't reinstall it (via the control panel anyways - it claims the font is still installed) until you reboot after removing it (I tried).
However if all you want to do is remove the font - its not the worst solution - the font is essentially gone after you uninstall it (apps don't see it, its only visible in control panel fonts as far as i can tell) and you wouldn't need to force a reboot.
From the SDK help on RemoveFontResourceFont (which may indicate why the oddness is seen)
If there are outstanding references to
a font, the associated resource
remains loaded until no device context
is using it.
Once you find the actual filename as Havenard mentioned and using the article you mentioned you can do a
objFSO.DeleteFile(FontFilePath);
where FontFilePath is the file path of the file you want to delete.
More Info here:
technet article
A problem that you may run into, which I didn't think of until I saw your comment, is that a program may require that font for some particular item. All known system fonts are stored within the registry. If you remove a font, you should also remove the key from the registry. Registry paths are as follows
Windows 95
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Fonts]
Windows NT
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts]
The keys are as followed:
Key name = Full name of the font
Key type = REG_SZ
Key Value = name of font file
All your fonts can be found at C:\WINDOWS\Fonts\
Explorer will mask this folder to display the font names instead of the real file names, but its all there. You can edit and comment out the lines of C:\WINDOWS\Fonts\desktop.ini to disable this feature and reveal the font files (maybe you need to reopen the Explorer to take effect).
We have a legacy application written in C that uses WinAPI. We'd like to add a "Yes to All" button to a few of our dialog boxes. Unfortunately, the existing MessageBox function does not allow for custom buttons or button captions.
What's the best way to do so? Is there a slick hack to easily add a custom button? Or should we create our own MessageBox replacement?
Something like that maybe? http://www.codeproject.com/KB/dialog/CRHYesNoToAllDialog.aspx
Or this: Using Windows Hooks to Enhance MessageBox in .NET
Marc
There is another kind of a message box in WinAPI, since Windows 2000. It's SHMessageBoxCheck.
It allows you to display a standard MB_OKCANCEL/MB_YESNO/MB_OK-type MessageBox with the option to Never show it again, by specifying which the default option in that case is.
Maybe it's not exactly what you're looking for, but it's fairly consistent with Windows UI.
In Vista most of the shell's "Yes to all" dialogs actually work this way - there's no additional button saying "Yes/No to all" - there's a "Perform chosen action on all items" checkbox instead.
However the Note in documentation worries me:
This function is available through Microsoft Windows XP and Windows Server 2003. It might be altered or unavailable in subsequent versions of Windows.
You may also need to take care of the text wrapping to make it similar to MessageBox. Also MessageBox uses a different font compared to the default GUI font. And don't forget to play the sound when the dialog pops up :)
We ended just creating our own DIALOGEX replacement resource template, then simply call DialogBox() and check the return value.
Reference: http://msdn.microsoft.com/library/ms644996(v=VS.85).aspx#modal_box
I want to replace the standard system open file dialog with the one I wrote, that means no matter within which programs you are opening a file, my dialog will be shown instead of the standard one, is this possible?
It seems that that there is no such API provided to accomplish this, is it possible to use some hooking technique, but this has to be reliable and not to be treated as spyware by anti-virus tools?
any other options?
If this is not possible, is it possible to add to the spacebar or toolbar in the standard open file dialog a button which invokes my dialog, which allow users select a file and in turn returns the path of the selected file to the "File name" input box of the standard dialog?
Any hits, links and code examples will be appreciated.
Starting in Vista, the FileOpen/FileSave dialogs are now "Common Item Dialogs" of which IFileOpenDialog & IFileSaveDialog are the two published implementations.
Since they're just COM objects with known CLSIDs you might get away with just replacing them by re-registering using their CLSIDs. Never tried something like that, might trip all sorts of alarm bells.
Pre-Vista file dialogs can be hooked in process, but I've never come across anything about global hooks or equivalent.
If you copy a file/folder to a dialog's filename field it usually pastes the full path anyway.
For example, if you have open both a program calling the standard open/save dialog box and also have a window open at the file or path that you want to work with (open from/save to), you can simply copy the file/folder from the explorer window, and then paste into the filename field of the dialog box, and it will insert the full path of the file/folder. No custom script is required!
Alternatively, for those programs that use custom dialog boxes where this step fails, copy the same file/folder in the window into the address bar of the same window (assuming it is visible). This will paste the full path, which you can copy again, and then paste this full path into the custom dialog box. I often use this when creating Office hyperlinks (Ctrl+K), because the Insert Hyperlink dialog does not work for the first method.
You can also use similar methods but paste into address bar fields and it works.