大家好,我想开发一个windows应用程序,这个程序在绘制的时候从字库中取出一个汉字的位图数据,然后绘制出来。
我查了若干资料,参考一个已有的程序做,未达到理想的效果。我把代码附上,请各位帮忙指点迷津,感谢!代码如下:
/*---------------------------------------------------------
   DEVCAPS1.C -- Device Capabilities Display Program No. 1
                 (c) Charles Petzold, 1998
  ---------------------------------------------------------*/#include <windows.h>
#include "tchar.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;#define NUM 1000
#ifdef UNICODE
#define GetGlyphOutline GetGlyphOutlineW
#else
#define GetGlyphOutline GetGlyphOutlineA
#endifint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("draw line sample1 ") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("draw line sample1 "),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
} FIXED FixedFromDouble(double d)
 {   long l;   l = (long) (d * 65536L);
   return *(FIXED *)&l; }
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static int  cxChar, cxCaps, cyChar,cxClient,cyClient;
     TCHAR       szBuffer[10],chText;
     HDC         hdc ;
     UINT         i,k ;
 int j;
     PAINTSTRUCT ps ;
     TEXTMETRIC  tm ;
 RECT rcClient;
 POINT currentPosition;
 POINT apt[NUM];
 POINT apt1[4]={0,0,50,200,150,300,400,247};
 HFONT hFont,oldFont;
 DWORD dwBufSize;     
     switch (message)
     {
 case WM_SIZE:
  cxClient=LOWORD(lParam);
  cyClient=HIWORD(lParam);
  return 0;     case WM_CREATE:
          hdc = GetDC (hwnd) ;
          GetTextMetrics (hdc, &tm) ;
          cxChar = tm.tmAveCharWidth ;
          cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
          cyChar = tm.tmHeight + tm.tmExternalLeading ;          
          ReleaseDC (hwnd, hdc) ;
          return 0 ;
          
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
  hFont=(HFONT)GetStockObject(ANSI_VAR_FONT);
  oldFont=(HFONT)SelectObject(hdc,hFont);
  MAT2 mat2;
  mat2.eM11 = FixedFromDouble(2);
  mat2.eM12 = FixedFromDouble(0);
          mat2.eM21 = FixedFromDouble(0);
          mat2.eM22 = FixedFromDouble(2);
 
  GLYPHMETRICS gm;
  //chText=L'泰';
  chText =L'泰';
  dwBufSize=GetGlyphOutline(hdc,chText,GGO_BITMAP,&gm,0L,NULL,&mat2);
  if(dwBufSize>0 && dwBufSize<0xFFFF)
  {
  //char* lpBuf=NULL;
  //lpBuf=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBufSize);   LPBYTE lpBuf=(LPBYTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBufSize);
    if(lpBuf)
  {
  GetGlyphOutline(hdc,chText,GGO_BITMAP,&gm,dwBufSize,lpBuf,&mat2);   int nByteCount = ((gm.gmBlackBoxX +31) >> 5) << 2;   for (i = 0; i<gm.gmBlackBoxY; i++)
  {
  for (j = 0; j<nByteCount; j++)
  {
  BYTE btCode = lpBuf[i* nByteCount + j];   for (k = 0; k<8; k++)
  {    if (btCode & (0x80>>k))
                                  {                    
SetPixel(hdc,j*8+k,i*1,RGB(244,0,0));
                                  }
                                  else
                                  {
                                    SetPixel(hdc,j*8+k,i*1,RGB(0,0,0));
                                  }    }
  }
  }
  HeapFree(GetProcessHeap(),0,lpBuf);
  }
  }
  SelectObject(hdc,oldFont);
  DeleteObject(hFont);          
          EndPaint (hwnd, &ps) ;
          return 0 ;
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

解决方案 »

  1.   

    dwBufSize=GetGlyphOutline(hdc,chText,GGO_BITMAP,&gm,0L,NULL,&mat2);这个缓冲区大小远远超过了65535;
      

  2.   

    是不是GetGlyphOutline调用失败了
    看看GetGlyphOutline的说明
    http://baike.baidu.com/view/1080765.htm
      

  3.   

    我参考了MSDN,MSDN解释如下:
    If GGO_BITMAP, GGO_GRAY2_BITMAP, GGO_GRAY4_BITMAP, GGO_GRAY8_BITMAP, or GGO_NATIVE is specified and the function succeeds, the return value is greater than zero; otherwise, the return value is GDI_ERROR. If one of these flags is specified and the buffer size or address is zero, the return value specifies the required buffer size, in bytes. If GGO_METRICS is specified and the function fails, the return value is GDI_ERROR. 我刚才测试了一下,果然返回的是GDI_ERROR,我再修改代码试试。
      

  4.   

    弄点阵字库,将字符显示到dc下,然后扫描dc的颜色就可以了。
      

  5.   

    我刚才输出错误代码,输出的错误代码为10031003 Cannot complete this function.  ERROR_CAN_NOT_COMPLETE 
      

  6.   

    用GetLastError输出错误代码10031003 Cannot complete this function.  ERROR_CAN_NOT_COMPLETE 
      

  7.   


    GetGlyphOutline
    The GetGlyphOutline function retrieves the outline or bitmap for a character in the TrueType font that is selected into the specified device context. 程序中的这两行:hFont=(HFONT)GetStockObject(ANSI_VAR_FONT);
    oldFont=(HFONT)SelectObject(hdc,hFont);其中ANSI_VAR_FONT不是TrueType font所以改用:DEFAULT_GUI_FONT DEFAULT_GUI_FONT Default font for user interface objects such as menus and dialog boxes. This is MS Sans Serif. Compare this with SYSTEM_FONT. 
      

  8.   

    dwBufSize是无符号数,换成有符号数这个值不就是-1吗?没有用过Windows的,只是用过FreeType
      

  9.   

    WM_PAINT分支这样修改
    case WM_PAINT:
    hdc = BeginPaint (hwnd, &ps) ;
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    oldFont=(HFONT)SelectObject(hdc, hFont);
    MAT2 mat2;
    mat2.eM11 = FixedFromDouble(2);
    mat2.eM12 = FixedFromDouble(0);
    mat2.eM21 = FixedFromDouble(0);
    mat2.eM22 = FixedFromDouble(2); GLYPHMETRICS gm; chText =L'A';
    dwBufSize=GetGlyphOutline(hdc, chText, GGO_BITMAP, &gm, 0L, NULL, &mat2);
    if(dwBufSize>0 && dwBufSize<0xFFFF)
    { LPBYTE lpBuf=(LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize); if(lpBuf)
    {
    GetGlyphOutline(hdc, chText, GGO_BITMAP, &gm, dwBufSize, lpBuf, &mat2); int nByteCount = ((gm.gmBlackBoxX +31) >> 5) << 2; for (i = 0; i<gm.gmBlackBoxY; i++)
    {
    for (j = 0; j<nByteCount; j++)
    {
    BYTE btCode = lpBuf[i* nByteCount + j]; for (k = 0; k<8; k++)
    { if (btCode & (0x80>>k))
    {   
    SetPixel(hdc,j*8+k,i*1,RGB(244,0,0));
    }
    else
    {
    SetPixel(hdc,j*8+k,i*1,RGB(0,0,0));
    }   }
    }
    }
    HeapFree(GetProcessHeap(),0,lpBuf);
    }
    }
    SelectObject(hdc,oldFont);
    DeleteObject(hFont);   
    EndPaint (hwnd, &ps) ;
    return 0 ;
    这里注意两个问题
    一、如kaizi65535在13楼所说,字体需要是TrueType的
    二、你要确定你预获取的字符被你选择的字体所支持