我在WINAPI上写了一个程序。我必须实现语法突出显示。此时I使用以下算法:
void PaintWords(const char *SearchWord,COLORREF rgb)
{
counter = TabCtrl_GetCurSel(TabControl_hWnd);
ft.chrg.cpMin = 0;
ft.chrg.cpMax = GetWindowTextLength(hWnd);
ft.lpstrText = (LPCSTR)SearchWord; //keyword
do
{
int poe_p = SendMessage(hWnd, EM_FINDTEXTEX, FR_DOWN | FR_WHOLEWORD | FR_MATCHCASE, (LPARAM)&ft);
if(poe_p != -1)
{
int selword = SendMessage(hWnd, EM_EXSETSEL,0,(LPARAM)&ft.chrgText);
ZeroMemory(&chd, sizeof(chd));
chd.cbSize = sizeof(CHARFORMAT);
chd.dwMask = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_CHARSET;
chd.crTextColor = rgb;
chd.bPitchAndFamily = FW_THIN;
lstrcpy(chd.szFaceName , "Courier New");
SendMessage(hWnd,EM_SETCHARFORMAT,SCF_WORD|SCF_SELECTION,(LPARAM)&chd);
ft.chrg.cpMin = ft.chrgText.cpMax;
}
else
{
break;
}
}while(ft.chrg.cpMin != ft.chrg.cpMax);
}
这段代码太慢了,因为这不是最好的选择,闪烁是可见的。
我对其他变体感兴趣。
我认为您需要使用双缓冲来减少闪烁。除此之外,您不应该对任何窗口(在同一线程内)使用 SendMessage
(甚至PostMessage
)。为什么必须在语法高亮绘制代码中进行选择?
关于双缓冲的文章之一是这样的。
我遇到了这个项目的RichTextbox,它被用作xml编辑器:http://xpathvisualizer.codeplex.com/SourceControl/changeset/view/42057#XPathVisualizer/CustomControls/RichTextBoxEx.cs
它在 C# 中,但发送的消息是可见的。
使用此文本框时,在突出显示文本之前,应调用 BeginUpdateAndSuspendEvents 函数。
public IntPtr BeginUpdateAndSuspendEvents()
{
// Stop redrawing:
User32.SendMessage(this.Handle, (int) User32.Msgs.WM_SETREDRAW, 0, IntPtr.Zero);
// Stop sending of events:
IntPtr eventMask = User32.SendMessage(this.Handle, User32.Msgs.EM_GETEVENTMASK, 0, IntPtr.Zero);
return eventMask;
}
此函数可防止在处理文本时重绘,完成编辑后,应调用
public void EndUpdateAndResumeEvents(IntPtr eventMask)
{
// turn on events
User32.SendMessage(this.Handle, User32.Msgs.EM_SETEVENTMASK, 0, eventMask);
// turn on redrawing
User32.SendMessage(this.Handle, User32.Msgs.WM_SETREDRAW, 1, IntPtr.Zero);
NeedRecomputeOfLineNumbers();
this.Invalidate();
}
双缓冲不能解决此问题,因为它不会阻止绘制的发生,在不禁用绘制事件的情况下突出显示编辑器可能会导致程序停止超过 5 分钟,具体取决于文件大小和要突出显示的字数。