富文本编辑器中的列选择。





5.00/5 (12投票s)
富文本编辑器中的列选择。
介绍
该项目将帮助您了解基于列的选择,以及如何在您的项目中实现基于列的选择。 我一直在寻找这类文章或帮助,但没有找到,这促使我创建了这种类型的应用程序。 我希望它们对那些想要在其编辑器中实现基于列的选择功能的人有所帮助。
下面我展示了一些图片,这些图片描绘了其他应用程序中的基于列的选择功能。
Visual Studio 中的基于列的选择。
我的应用程序的富文本编辑器中的基于列的选择。
在大多数应用程序中,可以通过“按住 Alt + 拖动鼠标”来实现基于列的选择。 我的应用程序中的方式也一样。
背景
策略很简单
1. 首先从编辑控件的可视部分创建一个新的位图。 但以文本颜色为白色,背景(除了文本区域)颜色为蓝色的方式处理此位图。
2. 处理后,将此位图保存在一个 DC(设备上下文)中。 在我的例子中,这是 m_processedDC.
3. 现在计算用户选择的区域,并在 2 个成员变量中存储 2 个点。 2 个点表示起始点和结束点。 结束点必须通过鼠标移动消息不断更新。
4. 在用户选择矩形计算后,从m_processedDC
复制仅选定的矩形到目标 DC,在我的例子中是富文本编辑器的 DC(设备上下文),通过 BitBlt() 方法。
5. 现在用户将看到他的某些区域被选中。
代码说明
我将在下面解释代码的一些重要区域,
1. 我已在 CColBasedRichEdit 类中实现了这一点,该类继承自 MFC 的 CRichEditCtrl。
2. 创建一个与应用程序当前屏幕兼容的内存 DC,并创建一个与 RichEdit 控件的设备兼容的位图。
m_processedDC = ::CreateCompatibleDC(NULL);
HBITMAP bmpREdit = ::CreateCompatibleBitmap(*pDC, rcClient.Width(), rcClient.Height() );
::SelectObject(m_processedDC, bmpREdit);
3. 使用系统当前高亮颜色创建一个纯色画笔,并使用当前创建的画笔填充目标 DC 的背景。
COLORREF clrHilite = ::GetSysColor(COLOR_HIGHLIGHT);
HBRUSH brHilite = CreateSolidBrush( clrHilite);
::FillRect(m_processedDC, CRect(0, 0, rcClient.Width(), rcClient.Height()), brHilite);
4. 创建一个具有指定宽度和高度但其内容未定义(为 NULL)的位图
CHBITMAP hMemBmp = CreateBitmap(rcClient.Width(), rcClient.Height(), 1, 1/*BitsPerPixel*/, NULL);
这里,第四个参数要求分配每像素的位数,我们分配了“1”,因此结果位图将是一个黑白位图。 现在将新的位图保存在 m_hSelectionDC
DC 中。
5. 将 RichEdit 的 DC 复制到 'm_hSelectionDC
'
BitBlt(m_hSelectionDC, 0, 0, rcClient.Width(), rcClient.Height(), *pDC, 0, 0, SRCCOPY);
重要的事情是 'm_hSelectionDC
' 具有黑白像素,因此,如果您在某个地方绘制 'm_hSelectionDC
' 进行测试,那么您将看到一个富文本编辑控件的黑白图像。 制作黑白图像的目的是如果 RichEdit 控件具有不同的颜色字符(文本)。
6. 现在是重要部分。 在这里我们可以看到 'MERGEPAINT
' 的魔力。
BitBlt(m_processedDC, 0,0, rcClient.Width(), rcClient.Height(), m_hSelectionDC , 0, 0, MERGEPAINT );
首先反转源 DC 的像素。
其次,将 'm_processedDC
' 的颜色与 'm_hSelectionDC
' 合并(逐像素合并)
你还记得 'm_processedDC
' 的像素是当前系统的高亮颜色像素吗?
7. 现在在这一点上,我们已经得到了/准备好了我们的 m_processedDC
并且它已准备好使用。
8. 在鼠标移动消息中,我计算了用户选择的起始点和结束点。
// Adjust end line position
CPoint ptTemp = PosFromChar( CharFromPos( point ) );
ptTemp.x = ptTemp.x + m_FontWidth - 2;
ptTemp.y = ptTemp.y + m_FontHeight - 2;
//m_colSelEndPt = ptTemp;
if(( ptTemp.x > (m_colSelEndPt.x + 4)) || ( ptTemp.x < (m_colSelEndPt.x - 4) )
|| ( ptTemp.y > (m_colSelEndPt.y + 4)) || ( ptTemp.y < (m_colSelEndPt.y - 4)) )
{
m_colSelEndPt = ptTemp;
Invalidate();
UpdateWindow(); }
9. 为了复制选定的区域/文本,我使用了 MSDN 的剪贴板概念,它实际上分配了全局内存/共享内存,
hClipboardData = (HGLOBAL)GlobalAlloc(GMEM_DDESHARE, sizeText);
pszClipText = (LPTSTR)GlobalLock((HGLOBAL)hClipboardData);
SetClipboardData(CF_UNICODETEXT/*CF_TEXT*/, hClipboardData);
如何使用
下载 zip 文件,这是一个 VC 项目(我使用了 Visual Studio 2005),然后编译并运行。
按住 ALT 键 + 鼠标拖动并释放两者(鼠标按下和 ALT 键)来选择文本。
现在单击“复制选择”按钮,然后转到您的编辑器并粘贴它。
关注点
有趣的是我的应用程序/实现的外观/外观,然而,它比一些应用程序更好,例如 - Edit Plus。我使用了 MFC 的富文本编辑控件,但如果有人掌握了基本概念,那么它可以用任何编程语言实现。