【作图】在图片上直接敲入字符
作者:enoloo
在论坛经常看到提出怎么在图片上直接敲入字符。今天又碰到一个,于是趁着月黑风高写了几个小程序。
第一个程序,效果图如下:
第二个程序,效果如下:
[说明]
第一个程序:
开始想到的。用半透明文本框(真是很不爽,搞了半天截图软件也不能截取透明窗口的像样图片 @_@)。没有用SDK,用USER32.dll的函数SetLayeredWindowAttributes。网上有很多这方面的介绍。主要是:
1, m_hDll = ::LoadLibrary(_T("USER32.dll"));
2, ::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
3, if (m_hDll)
{
lpfnSetLayeredWindowAttributes pFn = NULL;
pFn = (lpfnSetLayeredWindowAttributes)GetProcAddress(m_hDll, "SetLayeredWindowAttributes");
if (pFn)
{
bRetValue = pFn(hWnd, crKey, bAlpha, dwFlags);
}
}
4, if (m_hDll) ::FreeLibrary(m_hDll);
m_hDll = NULL;
5, 有几个标志WS_EX_LAYERED等需要define一下。
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
在某个窗体上随便写文字,还是老办法,鼠标点击的时候Create一个文本框(半透明),离开的时候把文本框中的文字写入窗口上文本框的那个位置,然后Destroy文本框。
窗口半透明之后,虽然能够看到窗口下面的东西,但是窗口里面所有的东西都半透明了,包括插入符,文字等等。所以,如果透明度很高的话,书写的文字是很难看清楚,所以,如果要实现完全透明的输入窗口并写东西,是很难控制的,因为找不到插入符在哪里。不过半透明的输入框也是挺有意思的。这个程序我没有深入写下去。
第二个程序:
功能:
1,鼠标点击窗体客户区的某个地方,产生一个插入符。
2,敲击键盘能过直接在窗体上写上字符,包括汉字,字母。因为是个测试程序,我只处理了等宽字体。
3,支持BackSpace消除字符,回车书写完毕。
因为写得比较匆忙,肯定有不少bug,我处理了一些。这算是抛砖引玉,大家有兴趣的话可以参考并完善。
程序代码(部分):
/*!
*
* 处理字符消息,并将字符写在窗体上
* \note 能处理中文,支持backspace编辑
* \bug 不支持HOME,END,LEFT,RIGHT等键,需要改进
* \bug 字符宽度需要改进,某些字体不受支持
* \author enoloo
* \date 2004-6-14 /first edition
*/
void CChildView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if(!m_bShow)
{
CWnd::OnChar(nChar,nRepCnt,nFlags);
return;
}
static char sTmp[3] = "";
static BOOL bTmp = FALSE;
CClientDC dc(this);
dc.SetBkMode(TRANSPARENT);
CRect rtTmp;
if(nChar == VK_RETURN)
{
m_bShow = false;
::HideCaret(this->GetSafeHwnd());
}
else if(nChar == VK_BACK)
{
if(m_nPos > 0)
{
--m_nPos;
if(!bChinese)
{
rtTmp.left = m_xPos + m_nPos*m_xChar;
rtTmp.top = m_yPos;
rtTmp.right = m_xPos + m_strText.GetLength()*m_xChar;
rtTmp.bottom = m_yPos + m_yChar;
InvalidateRect( &rtTmp );
::SetCaretPos((m_xPos + m_nPos*m_xChar), m_yPos);
}
else
{
rtTmp.left = m_xPos + m_nPos*m_xChar*2;
rtTmp.top = m_yPos;
rtTmp.right = m_xPos + m_strText.GetLength()*m_xChar*2;
rtTmp.bottom = m_yPos + m_yChar;
InvalidateRect( &rtTmp );
::SetCaretPos((m_xPos + m_nPos*m_xChar*2), m_yPos);
}
m_strText.Delete(m_nPos);
}
}
else // 正常的字符码
{
CString strTmp;
if(nChar > 127 && bTmp)
{
sTmp[1] = nChar;
sTmp[2] = 0;
bChinese = true;
bTmp = false;
}
else if(nChar > 127 && !bTmp)
{
sTmp[0] = nChar;
bTmp = true;
CWnd::OnChar(nChar,nRepCnt,nFlags);
return;
}
else
{
bChinese = false;
sTmp[0] = nChar;
sTmp[1] = 0;
}
strTmp = sTmp;
if(!bChinese)
{
dc.TextOut((m_xPos + m_nPos*m_xChar + 2), m_yPos, strTmp);
++m_nPos;
::SetCaretPos((m_xPos + m_nPos*m_xChar), m_yPos);
}
else
{
dc.TextOut((m_xPos + m_nPos*m_xChar*2 + 2), m_yPos, strTmp);
++m_nPos;
::SetCaretPos((m_xPos + m_nPos*m_xChar*2), m_yPos);
}
m_strText += strTmp;
CWnd::OnChar(nChar, nRepCnt, nFlags);
return;
}
CWnd ::OnChar(nChar, nRepCnt, nFlags);
}
我的免费空间正在升级,所以暂时没有空间摆上工程代码。空间好了,我会贴出来的。