如何判断指定字库中是否有该字

时间:2022-11-06 10:04:17
我的程序因为美观的需要,要显示各种字体,但因为字库的原因(不是所有的字库都跟宋体一样几乎包含现在用到的字),有很多字会显示不了。
无法显示的汉字它就显示一个空格。
但宋体肯定都(目前系统默认可以打出的汉字,它都可以显示)可以显示。
我看到过有些文档,当这个字体没有的时候,它不会不显示,而是自动显示为宋体。
也就是说,其它的汉字本都显示为我设置的字体,但这个显示不出来的汉字显示的是宋体。
这个在VB中要如何实现?
就是需要有一个判断该汉字是否存在于该字库中的程序。来决定当该汉字不在该字库中时,显示为宋体。


12 个解决方案

#1


这个比较麻烦

#2


就没有其它办法了吗?比如API
WORD就有这个功能,但我的VB实现不了。

#3


应该是可以的吧

#4


可以先picturebox1.print到一个隐藏的picturebox1上然后用picturebox1.Point函数逐点检查是否空白。(此法速度比较慢)

#5


晕,4楼的方法好象在程序里是不可被接受的。
虽然也是能把它判断出来,但是不要说几千字,估计几十个字时这的速度都无法让人接受。
还有别的方法吗?

#6


打包的时候把字体打进去不就得了。

#7


引用 6 楼 dingyanwei 的回复:
打包的时候把字体打进去不就得了。
人家说的显然不是缺少相应的ttf字体文件,只是某字库做的汉字不全,所以有缺字现象,我开始想的方法和4楼一样,我也觉得这个方法很不实际,楼主找找所以跟字体相关的api函数,看看有没有相关功能的。

#8


过滤了下所有含font的api函数,楼主继续折腾看看吧。
1.Declare Function AddFontResource Lib "gdi32" Alias "AddFontResourceA" (ByVal lpFileName As String) As Long

2.Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long

3.Declare Function CreateFont Lib "gdi32" Alias "CreateFontA" (ByVal H As Long, ByVal W As Long, ByVal E As Long, ByVal O As Long, ByVal W As Long, ByVal I As Long, ByVal u As Long, ByVal S As Long, ByVal C As Long, ByVal OP As Long, ByVal CP As Long, ByVal Q As Long, ByVal PAF As Long, ByVal F As String) As Long

4.Declare Function CreateScalableFontResource Lib "gdi32" Alias "CreateScalableFontResourceA" (ByVal fHidden As Long, ByVal lpszResourceFile As String, ByVal lpszFontFile As String, ByVal lpszCurrentPath As String) As Long

5.Declare Function GetFontData Lib "gdi32" Alias "GetFontDataA" (ByVal hdc As Long, ByVal dwTable As Long, ByVal dwOffset As Long, lpvBuffer As Any, ByVal cbData As Long) As Long

6.Declare Function RemoveFontResource Lib "gdi32" Alias "RemoveFontResourceA" (ByVal lpFileName As String) As Long

7.Declare Function EnumFontFamilies Lib "gdi32" Alias "EnumFontFamiliesA" (ByVal hdc As Long, ByVal lpszFamily As String, ByVal lpEnumFontFamProc As Long, ByVal lParam As Long) As Long

8.Declare Function EnumFontFamiliesEx Lib "gdi32" Alias "EnumFontFamiliesExA" (ByVal hdc As Long, lpLogFont As LOGFONT, ByVal lpEnumFontProc As Long, ByVal lParam As Long, ByVal dw As Long) As Long

9.Declare Function GetTextCharsetInfo Lib "gdi32" Alias "GetTextCharsetInfo" (ByVal hdc As Long, lpSig As FONTSIGNATURE, ByVal dwFlags As Long) As Long

10.Declare Function GetFontLanguageInfo Lib "gdi32" Alias "GetFontLanguageInfo" (ByVal hdc As Long) As Long

11.Declare Function ImmGetCompositionFont Lib "imm32.dll" Alias "ImmGetCompositionFontA" (ByVal himc As Long, lpLogFont As LOGFONT) As Long

12.Declare Function ImmSetCompositionFont Lib "imm32.dll" Alias "ImmSetCompositionFontA" (ByVal himc As Long, lpLogFont As LOGFONT) As Long

13.Declare Function ChooseFont Lib "comdlg32.dll" Alias "ChooseFontA" (pChoosefont As CHOOSEFONT) As Long

14.Declare Function EnumFonts Lib "gdi32" Alias "EnumFontsA" (ByVal hDC As Long, ByVal lpsz As String, ByVal lpFontEnumProc As Long, ByVal lParam As Long) As Long

#9


试试API函数:
GetCharWidth32

#10


为了美观,何不使用图片?先做好图片,载入即可。

#11


还可以用下面的代码人工查看一下用到的字体哪些字符是空白,记录到一个数组中。使用时查数组。
#include <windows.h>
#include <stdio.h>

int main() {
    const DWORD uWidth = 18 + 17 * 256, uHeight = 18 + 17 * 128;

    PBITMAPINFO pbmi = (PBITMAPINFO) LocalAlloc (LPTR, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2);
    pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = uWidth;
    pbmi->bmiHeader.biHeight = uHeight;
    pbmi->bmiHeader.biPlanes = 1;
    pbmi->bmiHeader.biBitCount = 1;
    pbmi->bmiHeader.biSizeImage = ((uWidth + 31) & ~31) / 8 * uHeight;
    pbmi->bmiColors[0].rgbBlue = 0;
    pbmi->bmiColors[0].rgbGreen = 0;
    pbmi->bmiColors[0].rgbRed = 0;
    pbmi->bmiColors[1].rgbBlue = 255;
    pbmi->bmiColors[1].rgbGreen = 255;
    pbmi->bmiColors[1].rgbRed = 255;

    HDC hDC = CreateCompatibleDC (0);
    void * pvBits;
    HBITMAP hBitmap = CreateDIBSection (hDC, pbmi, 0, &pvBits, NULL, 0);
    SelectObject (hDC, hBitmap);
    HFONT hFont = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "宋体");
    SelectObject (hDC, hFont);
    BitBlt (hDC, 0, 0, uWidth, uHeight, NULL, 0, 0, WHITENESS);

    char c[4];
    int i, j;
    for (i = 128; i < 256; i++) {
        sprintf (c, "%02X", i);
        TextOut (hDC, 1, (i - 127) * 17 + 1, c, 2);
    }
    for (j = 0; j < 256; j++) {
        sprintf (c, "%02X", j);
        TextOut (hDC, (j + 1)* 17 + 1, 1, c, 2);
    }
    for (i = 128; i < 256; i++) {
        for (j = 0; j < 256; j++) {
            c[0] = (char) i;
            c[1] = (char) j;
            TextOut (hDC, (j + 1) * 17 + 1, (i - 127) * 17 + 1, c, 2);
        }
    }
    for (i = 0; i < 130; i++) {
        MoveToEx (hDC, 0, i * 17, NULL);
        LineTo (hDC, uWidth, i * 17);
    }
    for (j = 0; j < 258; j++) {
        MoveToEx (hDC, j * 17, 0, NULL);
        LineTo (hDC, j * 17, uHeight);
    }

    BITMAPFILEHEADER bmfh;
    bmfh.bfType = *(PWORD) "BM";
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2;
    bmfh.bfSize = bmfh.bfOffBits + pbmi->bmiHeader.biSizeImage;

    HANDLE hFile = CreateFile ("goal.bmp", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwWritten;
        WriteFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), &dwWritten, NULL);
        WriteFile (hFile, pbmi, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2, &dwWritten, NULL);
        WriteFile (hFile, pvBits, pbmi->bmiHeader.biSizeImage, &dwWritten, NULL);

        CloseHandle (hFile);
    }

    DeleteObject (hFont);
    DeleteObject (hBitmap);
    DeleteDC (hDC);
    LocalFree (pbmi);

    return 0;
}

#12


引用 10 楼 veron_04 的回复:
为了美观,何不使用图片?先做好图片,载入即可。

哎~~!打印时图片就惨不忍睹了。
美观主要还是为了打印啊!
字变成图片后再打印,与直接打印字是完全二种不同的效果,不知道你们打印过没。
我自己慢慢研究吧!
散分!

#1


这个比较麻烦

#2


就没有其它办法了吗?比如API
WORD就有这个功能,但我的VB实现不了。

#3


应该是可以的吧

#4


可以先picturebox1.print到一个隐藏的picturebox1上然后用picturebox1.Point函数逐点检查是否空白。(此法速度比较慢)

#5


晕,4楼的方法好象在程序里是不可被接受的。
虽然也是能把它判断出来,但是不要说几千字,估计几十个字时这的速度都无法让人接受。
还有别的方法吗?

#6


打包的时候把字体打进去不就得了。

#7


引用 6 楼 dingyanwei 的回复:
打包的时候把字体打进去不就得了。
人家说的显然不是缺少相应的ttf字体文件,只是某字库做的汉字不全,所以有缺字现象,我开始想的方法和4楼一样,我也觉得这个方法很不实际,楼主找找所以跟字体相关的api函数,看看有没有相关功能的。

#8


过滤了下所有含font的api函数,楼主继续折腾看看吧。
1.Declare Function AddFontResource Lib "gdi32" Alias "AddFontResourceA" (ByVal lpFileName As String) As Long

2.Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long

3.Declare Function CreateFont Lib "gdi32" Alias "CreateFontA" (ByVal H As Long, ByVal W As Long, ByVal E As Long, ByVal O As Long, ByVal W As Long, ByVal I As Long, ByVal u As Long, ByVal S As Long, ByVal C As Long, ByVal OP As Long, ByVal CP As Long, ByVal Q As Long, ByVal PAF As Long, ByVal F As String) As Long

4.Declare Function CreateScalableFontResource Lib "gdi32" Alias "CreateScalableFontResourceA" (ByVal fHidden As Long, ByVal lpszResourceFile As String, ByVal lpszFontFile As String, ByVal lpszCurrentPath As String) As Long

5.Declare Function GetFontData Lib "gdi32" Alias "GetFontDataA" (ByVal hdc As Long, ByVal dwTable As Long, ByVal dwOffset As Long, lpvBuffer As Any, ByVal cbData As Long) As Long

6.Declare Function RemoveFontResource Lib "gdi32" Alias "RemoveFontResourceA" (ByVal lpFileName As String) As Long

7.Declare Function EnumFontFamilies Lib "gdi32" Alias "EnumFontFamiliesA" (ByVal hdc As Long, ByVal lpszFamily As String, ByVal lpEnumFontFamProc As Long, ByVal lParam As Long) As Long

8.Declare Function EnumFontFamiliesEx Lib "gdi32" Alias "EnumFontFamiliesExA" (ByVal hdc As Long, lpLogFont As LOGFONT, ByVal lpEnumFontProc As Long, ByVal lParam As Long, ByVal dw As Long) As Long

9.Declare Function GetTextCharsetInfo Lib "gdi32" Alias "GetTextCharsetInfo" (ByVal hdc As Long, lpSig As FONTSIGNATURE, ByVal dwFlags As Long) As Long

10.Declare Function GetFontLanguageInfo Lib "gdi32" Alias "GetFontLanguageInfo" (ByVal hdc As Long) As Long

11.Declare Function ImmGetCompositionFont Lib "imm32.dll" Alias "ImmGetCompositionFontA" (ByVal himc As Long, lpLogFont As LOGFONT) As Long

12.Declare Function ImmSetCompositionFont Lib "imm32.dll" Alias "ImmSetCompositionFontA" (ByVal himc As Long, lpLogFont As LOGFONT) As Long

13.Declare Function ChooseFont Lib "comdlg32.dll" Alias "ChooseFontA" (pChoosefont As CHOOSEFONT) As Long

14.Declare Function EnumFonts Lib "gdi32" Alias "EnumFontsA" (ByVal hDC As Long, ByVal lpsz As String, ByVal lpFontEnumProc As Long, ByVal lParam As Long) As Long

#9


试试API函数:
GetCharWidth32

#10


为了美观,何不使用图片?先做好图片,载入即可。

#11


还可以用下面的代码人工查看一下用到的字体哪些字符是空白,记录到一个数组中。使用时查数组。
#include <windows.h>
#include <stdio.h>

int main() {
    const DWORD uWidth = 18 + 17 * 256, uHeight = 18 + 17 * 128;

    PBITMAPINFO pbmi = (PBITMAPINFO) LocalAlloc (LPTR, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2);
    pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = uWidth;
    pbmi->bmiHeader.biHeight = uHeight;
    pbmi->bmiHeader.biPlanes = 1;
    pbmi->bmiHeader.biBitCount = 1;
    pbmi->bmiHeader.biSizeImage = ((uWidth + 31) & ~31) / 8 * uHeight;
    pbmi->bmiColors[0].rgbBlue = 0;
    pbmi->bmiColors[0].rgbGreen = 0;
    pbmi->bmiColors[0].rgbRed = 0;
    pbmi->bmiColors[1].rgbBlue = 255;
    pbmi->bmiColors[1].rgbGreen = 255;
    pbmi->bmiColors[1].rgbRed = 255;

    HDC hDC = CreateCompatibleDC (0);
    void * pvBits;
    HBITMAP hBitmap = CreateDIBSection (hDC, pbmi, 0, &pvBits, NULL, 0);
    SelectObject (hDC, hBitmap);
    HFONT hFont = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "宋体");
    SelectObject (hDC, hFont);
    BitBlt (hDC, 0, 0, uWidth, uHeight, NULL, 0, 0, WHITENESS);

    char c[4];
    int i, j;
    for (i = 128; i < 256; i++) {
        sprintf (c, "%02X", i);
        TextOut (hDC, 1, (i - 127) * 17 + 1, c, 2);
    }
    for (j = 0; j < 256; j++) {
        sprintf (c, "%02X", j);
        TextOut (hDC, (j + 1)* 17 + 1, 1, c, 2);
    }
    for (i = 128; i < 256; i++) {
        for (j = 0; j < 256; j++) {
            c[0] = (char) i;
            c[1] = (char) j;
            TextOut (hDC, (j + 1) * 17 + 1, (i - 127) * 17 + 1, c, 2);
        }
    }
    for (i = 0; i < 130; i++) {
        MoveToEx (hDC, 0, i * 17, NULL);
        LineTo (hDC, uWidth, i * 17);
    }
    for (j = 0; j < 258; j++) {
        MoveToEx (hDC, j * 17, 0, NULL);
        LineTo (hDC, j * 17, uHeight);
    }

    BITMAPFILEHEADER bmfh;
    bmfh.bfType = *(PWORD) "BM";
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2;
    bmfh.bfSize = bmfh.bfOffBits + pbmi->bmiHeader.biSizeImage;

    HANDLE hFile = CreateFile ("goal.bmp", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwWritten;
        WriteFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), &dwWritten, NULL);
        WriteFile (hFile, pbmi, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2, &dwWritten, NULL);
        WriteFile (hFile, pvBits, pbmi->bmiHeader.biSizeImage, &dwWritten, NULL);

        CloseHandle (hFile);
    }

    DeleteObject (hFont);
    DeleteObject (hBitmap);
    DeleteDC (hDC);
    LocalFree (pbmi);

    return 0;
}

#12


引用 10 楼 veron_04 的回复:
为了美观,何不使用图片?先做好图片,载入即可。

哎~~!打印时图片就惨不忍睹了。
美观主要还是为了打印啊!
字变成图片后再打印,与直接打印字是完全二种不同的效果,不知道你们打印过没。
我自己慢慢研究吧!
散分!