【作图】在图片上直接敲入字符
作者: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); }
我的免费空间正在升级,所以暂时没有空间摆上工程代码。空间好了,我会贴出来的。

|