windows api 获取字库点阵的问题

fulltimeangel 2012-04-26 02:20:21
大家好,我想开发一个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
#endif

int 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) ;
}
...全文
634 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
fulltimeangel 2012-04-27
  • 打赏
  • 举报
回复
13楼和15楼正解,非常感谢
向立天 2012-04-26
  • 打赏
  • 举报
回复
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的
二、你要确定你预获取的字符被你选择的字体所支持
「已注销」 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

单步调试dwBufSize=4294967295;
[/Quote]
dwBufSize是无符号数,换成有符号数这个值不就是-1吗?

没有用过Windows的,只是用过FreeType
kaizi65535 2012-04-26
  • 打赏
  • 举报
回复

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.
zhouzhipen 2012-04-26
  • 打赏
  • 举报
回复
自己做字库吧
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
谁帮忙看看问题出在哪里?
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
用GetLastError输出错误代码1003

1003 Cannot complete this function. ERROR_CAN_NOT_COMPLETE
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
我刚才输出错误代码,输出的错误代码为1003

1003 Cannot complete this function. ERROR_CAN_NOT_COMPLETE
用户 昵称 2012-04-26
  • 打赏
  • 举报
回复
弄点阵字库,将字符显示到dc下,然后扫描dc的颜色就可以了。
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
我参考了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,我再修改代码试试。
向立天 2012-04-26
  • 打赏
  • 举报
回复
是不是GetGlyphOutline调用失败了
看看GetGlyphOutline的说明
http://baike.baidu.com/view/1080765.htm
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
单步调试dwBufSize=4294967295;
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
dwBufSize=GetGlyphOutline(hdc,chText,GGO_BITMAP,&gm,0L,NULL,&mat2);这个缓冲区大小远远超过了65535;
xiaohuh421 2012-04-26
  • 打赏
  • 举报
回复
你的问题在哪里的,或者说你的难点在哪里呢.
都有例子程序了,
这个程序是哪里不能满足你的要求呢
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
又沉下来了?顶起啊顶起
fulltimeangel 2012-04-26
  • 打赏
  • 举报
回复
自己先顶一下,希望不要石沉大海

19,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧