熟悉汉字点阵的请进(在线等)

hnzlk 2009-07-08 04:44:06
功能要求:取得汉字的点阵,返回点阵的16进制,然后发送到rs232
我在网上找了一个函数,内容如下:


unsigned long TMainForm::GetCHNFontEx(
char *lpszOutString,
char *lpszBuffer,
char *lpszStringName,
char *lpszFontName,
int nHeight,
int nWidth,
bool ftbBold,
bool ftbItalic,
bool ftbUnderline,
bool ftbStrikeOut,
int nAngle,
DWORD ftwCharSet,
DWORD fdwOutputPrecision,
DWORD fdwClipPrecision,
DWORD fdwQuality,
DWORD fdwPitchAndFamily)
{
if (lpszOutString==NULL || Trim((AnsiString)lpszOutString)=="") return 0; //空字串,返回

HDC hDC;
HBITMAP hBitmap,hOldBMP;
HFONT hFont,hOldFont;
SIZE size1;
COLORREF BackColor=RGB(0,0,0);
COLORREF TextColor=RGB(255,255,255);

if ((hDC=GetDC(0))==NULL) return 2; //不能取得DC句柄
if ((hDC=CreateCompatibleDC(hDC))==NULL) return 3; //不能建立内存图形设备CreateCompatibleDC
if ((hFont=CreateFont(
nHeight, nWidth, nAngle, nAngle,
(ftbBold?700:0), ftbItalic, ftbUnderline, ftbStrikeOut,
ftwCharSet, fdwOutputPrecision, fdwClipPrecision,
fdwQuality, fdwPitchAndFamily, lpszFontName
))==NULL)
return 1; //不能创建逻辑字体

if ((hOldFont=SelectObject(hDC,hFont))==NULL) return 1;

GetTextExtentPoint32(hDC,lpszOutString,StrLen(lpszOutString),&size1);
unsigned int nOneLineSize = (size1.cx/8+(size1.cx%8?1:0));

if(lpszBuffer==NULL)//若缓冲区为空,返回所需缓冲区的大小
{
return (nOneLineSize * 2 * size1.cy + StrLen(lpszStringName) +
Trim(IntToStr(nOneLineSize*size1.cy)).Length() +
Trim(IntToStr(nOneLineSize)).Length() + 10 //"~DGR:,,,"
);
}

if ((hBitmap=CreateCompatibleBitmap(hDC,size1.cx,size1.cy))==NULL)
{ //不能创建位图设备CreateCompatibleBitmap
SelectObject(hDC,hOldFont);
DeleteObject(hFont);
DeleteDC(hDC);
return 4;
}
if ((hOldBMP=SelectObject(hDC,hBitmap))==NULL)
{
SelectObject(hDC,hOldFont);
DeleteObject(hBitmap);
DeleteObject(hFont);
DeleteDC(hDC);
return 4;
}

SetBkColor(hDC,BackColor);
SetTextColor(hDC,TextColor);
FillRect(hDC,&Rect(0,0,size1.cx,size1.cy),0); //????
//BitBlt(GetDC(0),0,0,size1.cx,size1.cy,hDC,0,0,SRCCOPY);

TextOut(hDC,0,0,lpszOutString,StrLen(lpszOutString));
//BitBlt(GetDC(0),0,0,size1.cx,size1.cy,hDC,0,0,SRCCOPY);

//取点串点阵
unsigned char bits,k;
char cHex[] = "0123456789ABCDEF";
char *lpBuffer = lpszBuffer;
StrCopy(lpszBuffer, "~DGR:");
StrCat(lpszBuffer, lpszStringName);
StrCat(lpszBuffer, (","+Trim(IntToStr(nOneLineSize*size1.cy))+","+Trim(IntToStr(nOneLineSize))+",").c_str());
lpBuffer += StrLen(lpszBuffer);

for (int i=0;i<size1.cy;i++)
{
bits = 0;
k = 0x80;
for(int j=0;j<size1.cx;j++)
{
if(GetPixel(hDC,j,i)==TextColor) bits|=k;
k>>=1;
if(!k)
{
*lpBuffer++ = cHex[bits>>4];
*lpBuffer++ = cHex[bits&0xF];
bits = 0;
k = 0x80;
}
}
if(k && k<0x80)
{
*lpBuffer++= cHex[bits>>4];
*lpBuffer++ = cHex[bits&0xF];
}
}
*lpBuffer = 0;

SelectObject(hDC,hOldBMP);
SelectObject(hDC,hOldFont);
DeleteObject(hBitmap);
DeleteObject(hFont);
DeleteDC(hDC);

return (lpBuffer-lpszBuffer);
}


然后调用:

char str1[]="字";
int count=GetCHNFontEx(str1,NULL,str3,"宋体",32,32,false,false,false,false,0,GB2312_CHARSET,0,0,0,0);
char *str2=new char[count];
memset(str2,0x00,count*sizeof(char));
GetCHNFontEx(str1,str2,str3,"宋体",32,32,false,false,false,false,0,GB2312_CHARSET,0,0,0,0);


为什么返回的字节数是542?还有hBitmap,好像也是变动的,我看到有的人的写法是直接固定了,如果是32*32的点阵,那么就只有那么一个位图,不知道你们是怎么弄的?大家有没有好的意见?
...全文
144 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
lambochan 2009-07-10
  • 打赏
  • 举报
回复
不会的,偶还有时候把它写到dc.TextOut( 0, -1, str )这样的坐标.
固定大小是最好处理的,发送接收都方便.
hnzlk 2009-07-10
  • 打赏
  • 举报
回复
这样强制的话,不知道会不会出现显示不全。
tkminigame 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 hnzlk 的回复:]
这样强制的话,不知道会不会出现显示不全。
[/Quote]

truetype转点阵肯定会显示不全。truetype字体本身就可以超出显示范围。
只需要保证字可以辨认就行了。
hnzlk 2009-07-09
  • 打赏
  • 举报
回复
我顶
用户 昵称 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 hnzlk 的回复:]
不是有横向取模,纵向取模之分吗?横向取模就是一行一行的取吗?好像还有左高位,右高位及上或下高位等分别,这些不是很懂,谁解释一下。
[/Quote]

没错,那要看显示模块是怎么显示的,好多模块是纵向显示的,所以扫描也要纵向。

一个16 * 16的汉字一般用32个字节点阵,以前做过一种是这样的,纵向显示,送一个字节ff给lcd,显示一条8个像素的竖线,位序是下面为lsb, 上面为msb。

lambochan 2009-07-09
  • 打赏
  • 举报
回复
Create一个1Bit的Dib,然后在上面写..
写完取其位数据,然后Flip vert(假如需要自顶向下),当然,其实取得位数据,想怎么变换储存都行.
这会比它的GetPixel()快pixel倍~~
MengWang 2009-07-09
  • 打赏
  • 举报
回复
帮顶,我也想了解一下!!
hnzlk 2009-07-09
  • 打赏
  • 举报
回复
llyyttzj 2009-07-09
  • 打赏
  • 举报
回复
CFile transfile;
CFileDialog mFileDlg(TRUE, NULL,NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT , "bmp文件(*.bmp)|*.bmp|All Files (*.*)|*.*| |", AfxGetMainWnd());
m_strContents.Empty();

if(mFileDlg.DoModal()==IDOK)
{
m_strSendDisp.Empty();//初始化显示文件窗口
m_strlSendDisp.SetWindowText(m_strSendDisp);
CFileException e;
BOOL file;
file=transfile.Open(mFileDlg.GetPathName(),CFile::modeRead,&e);

BITMAPFILEHEADER bmfHeader;

// 读取文件头
transfile.Read(&bmfHeader, sizeof(bmfHeader));

if(bmfHeader.bfType != 0x4D42)
{
AfxMessageBox("本程序仅读取BMP文件!");
}

// 读取信息头
BITMAPINFOHEADER *pBMIH;
pBMIH = (BITMAPINFOHEADER*)new BYTE[bmfHeader.bfOffBits - sizeof(bmfHeader)];
if(!transfile.Read(pBMIH, bmfHeader.bfOffBits - sizeof(bmfHeader)))
{
delete pBMIH;
}
int m_bitCount; // BMP图像的颜色深度
m_bitCount = pBMIH->biBitCount;
m_nWidth = pBMIH->biWidth;
m_nHeight = pBMIH->biHeight;
CString m_nth,m_nght;
m_nth.Format("图像宽度(像素)%2d",pBMIH->biWidth);
m_nght.Format("图像高度(像素)%2d",pBMIH->biHeight);
m_ctrlnth.SetWindowText(m_nth);
m_ctrlnght.SetWindowText(m_nght);
SetTimer(5,5,NULL);

LPBYTE *lpData;
int nWidthBytes = WIDTHBYTES((pBMIH->biWidth)*pBMIH->biBitCount);

lpData = (LPBYTE*)new LPBYTE[pBMIH->biHeight];
for(int i=0; i<pBMIH->biHeight; i++)
{
lpData[i] = new BYTE[nWidthBytes];
transfile.ReadHuge(lpData[i], nWidthBytes);
}

CString StrTemp,StrTemp1;
BYTE bt1,bt2;
if ((pBMIH->biWidth == 16))// && (pBMIH->biHeight == 16))
{
for(i=pBMIH->biHeight - 1; i>= 0 ; i--)
{

for (int ii=0;ii<nWidthBytes-2;ii++)
{
bt1=*(lpData[i]+ii);
bt2 = ~bt1;
StrTemp1=bt1;
m_strContents+=StrTemp1;
}
}
}

else

{
for(i=pBMIH->biHeight - 1; i>= 0 ; i--)
{

for (int ii=0;ii<nWidthBytes - 2;ii++)
{
bt1=*(lpData[i]+ii);
//bt2 = ~bt1;
//StrTemp1=bt1;
m_strContents+=~(*(lpData[i]+ii));

}
}
}

transfile.Close();

m_filepath=mFileDlg.GetPathName();
m_sFilePath.SetWindowText(m_filepath);

}

}
laowang2 2009-07-09
  • 打赏
  • 举报
回复
副组长 2009-07-09
  • 打赏
  • 举报
回复
呵呵,刚才没仔细看你的代码,原来你的代码里面就是象我说的这么干的。
副组长 2009-07-09
  • 打赏
  • 举报
回复
这个貌似TrueType字体,不是简单的点阵,而是根据文字大小临时生成点阵,关于TrueType字体的描述方法有专门的论著。
如果不是非常专业的应用,分析这个有点得不偿失。你往RS232上发应该不是一个非常严格的应用,可以采用一种变通的方法,找一块内存,把文字打上去,然后传这块内存里面的点阵。
tkminigame 2009-07-09
  • 打赏
  • 举报
回复
当然是变动的了,每个字的体积都不一样大。二占的面积肯定比一大。
关键是这句
GetTextExtentPoint32(hDC,lpszOutString,StrLen(lpszOutString),&size1);
这个取字的外轮廓,导致你每次取的size都是变动的。
把它设置成固定的值。如果你要的是32x32,那就是(32,32),dc画好后blt到缓存位图上到固定的地方去取就行了,别使用变动的size。
hnzlk 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 ttgoo 的回复:]
不知道为什么要用DC 位图等操作.你要给RS232传送什么数据呢?如果仅仅是汉字的点阵信息,直接找个字库文件分析出来就行了啊...分析出来就是2*2的数组
[/Quote]

用字库不灵活!
hnzlk 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 lambochan 的回复:]
nHeight = 32;
nWidth = 0;
if ((hFont=CreateFont(
nHeight, nWidth, nAngle, nAngle,
(ftbBold?700:0), ftbItalic, ftbUnderline, ftbStrikeOut,
ftwCharSet, fdwOutputPrecision, fdwClipPrecision,
fdwQuality, fdwPitchAndFamily, lpszFontName
))==NULL)

[/Quote]

发现传nHeight = 32过去,GetTextExtentPoint32(hDC,lpszOutString,StrLen(lpszOutString),&size1);
size1的值为32*33,不知道为什么?
lambochan 2009-07-09
  • 打赏
  • 举报
回复
nHeight = 32;
nWidth = 0;
if ((hFont=CreateFont(
nHeight, nWidth, nAngle, nAngle,
(ftbBold?700:0), ftbItalic, ftbUnderline, ftbStrikeOut,
ftwCharSet, fdwOutputPrecision, fdwClipPrecision,
fdwQuality, fdwPitchAndFamily, lpszFontName
))==NULL)

// 32 x 32 pixel 点阵
atopp 2009-07-09
  • 打赏
  • 举报
回复
不知道为什么要用DC 位图等操作.你要给RS232传送什么数据呢?如果仅仅是汉字的点阵信息,直接找个字库文件分析出来就行了啊...分析出来就是2*2的数组
hnzlk 2009-07-09
  • 打赏
  • 举报
回复
上面的代码经过仔细测试,

if ((hFont=CreateFont(
nHeight, nWidth, nAngle, nAngle,
(ftbBold?700:0), ftbItalic, ftbUnderline, ftbStrikeOut,
ftwCharSet, fdwOutputPrecision, fdwClipPrecision,
fdwQuality, fdwPitchAndFamily, lpszFontName
))==NULL)


把nHeight, nWidth,都设为0的话,表示缺省值。然后会得出正确的结果,但是,不知道为什么会占64字节,按道理是32字节,还不知道怎么改,另外,如果我想设成32*32点阵方式,这个地方不知道怎么转换。
xjq2003 2009-07-09
  • 打赏
  • 举报
回复
有专门的字模软件啊,
单片机控制显示屏不就是这样搞的吗
wendysen 2009-07-09
  • 打赏
  • 举报
回复
没仔细看,觉得好复杂!
以前做过一个从汉字库里去字模点阵的程序,转换成坐标,很简单,不知道你为啥做这么复杂。呵呵
加载更多回复(16)

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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