Richedit中的文本高亮显示和撤消

Richedit中的文本高亮显示和撤消,c,winapi,undo,richedit,tom.h,C,Winapi,Undo,Richedit,Tom.h,我正在尝试在RichEdit中实现文本高亮显示和撤消。下面的代码标记了5个和6个字符,但撤消不起作用(文本不变),尽管Edit\u CanUndo返回1。如果我关闭了一个updateHighlighting,则撤消可以工作,但一次回滚的次数太多(例如,输入一个长文本,按Ctrl+V粘贴一个文本,输入另一个文本-只需3次撤消即可回滚所有文本) 我的代码有什么问题?也许我应该从updateHighlighting返回一个特定值 #define UNICODE #define _UNICODE #i

我正在尝试在RichEdit中实现文本高亮显示和撤消。下面的代码标记了5个和6个字符,但撤消不起作用(文本不变),尽管
Edit\u CanUndo
返回
1
。如果我关闭了一个
updateHighlighting
,则撤消可以工作,但一次回滚的次数太多(例如,输入一个长文本,按Ctrl+V粘贴一个文本,输入另一个文本-只需3次撤消即可回滚所有文本)

我的代码有什么问题?也许我应该从
updateHighlighting
返回一个特定值

#define UNICODE
#define _UNICODE

#include <tchar.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <richedit.h>

#define IDC_EDITOR 1000
#define IDC_BUTTON 1001

HWND hEditorWnd;

bool updateHighlighting(HWND hWnd) {
    int carriagePos = 0;
    SendMessage(hWnd, EM_GETSEL, (WPARAM)&carriagePos, (WPARAM)&carriagePos);

    CHARFORMAT cf = {0};
    cf.cbSize = sizeof(CHARFORMAT) ;
    cf.dwMask = CFM_COLOR | CFM_BOLD;
    cf.crTextColor = RGB(0, 0, 200);
    cf.dwEffects = CFM_BOLD;
    SendMessage(hWnd, EM_SETSEL, 0, -1);
    SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);

    cf.dwMask = CFM_COLOR | CFM_BOLD;
    cf.dwEffects = cf.dwEffects & ~CFM_BOLD;
    cf.crTextColor = RGB(200, 0, 0);
    SendMessage(hWnd, EM_SETSEL, 4, 6);
    SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
    SendMessage(hWnd, EM_SETSEL, carriagePos, carriagePos);

    _tprintf(TEXT("End highlight\n"));
    return true;
}

LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_DESTROY:
            PostQuitMessage (0);
            break;

        case WM_COMMAND: {
            if (LOWORD(wParam) == IDC_EDITOR && HIWORD(wParam) == EN_CHANGE)
                return updateHighlighting(hEditorWnd);

            if (LOWORD(wParam) == IDC_BUTTON && HIWORD(wParam) == BN_CLICKED)
                _tprintf(TEXT("UNDO: can %i => result: %i\n"), Edit_CanUndo(hEditorWnd), Edit_Undo(hEditorWnd));
        }
        break;

        default:
            return DefWindowProc (hWnd, msg, wParam, lParam);
    }

    return 0;
}

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
    InitCommonControls();
    LoadLibrary(TEXT("msftedit.dll"));

    HWND hWnd;
    MSG msg;
    WNDCLASSEX wincl;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = TEXT("AppClass");
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hWnd = CreateWindowEx (0, TEXT("AppClass"), TEXT("Test"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 300, 400, 310, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);

    CreateWindowEx(0, WC_BUTTON , L"UNDO", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 10, 310, 280, 30, hWnd, (HMENU)IDC_BUTTON, hThisInstance,  NULL);
    hEditorWnd = CreateWindowEx(0, TEXT("RICHEDIT50W"), NULL, WS_VISIBLE | WS_CHILD | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | ES_NOHIDESEL, 0, 0, 300, 300, hWnd, (HMENU)IDC_EDITOR, hThisInstance,  NULL);
    SendMessage(hEditorWnd, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_UPDATE | ENM_KEYEVENTS);

    while (GetMessage (&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
#定义UNICODE
#定义UNICODE
#包括
#包括
#包括
#包括
#包括
#定义IDC_编辑器1000
#定义IDC_按钮1001
HWND hEditorWnd;
布尔更新高光照明(HWND HWND){
int=0;
发送消息(hWnd、EM_GETSEL、(WPARAM)和careepos、(WPARAM)和careepos);
CHARFORMAT cf={0};
cf.cbSize=sizeof(字符格式);
cf.dwMask=CFM_COLOR | CFM_BOLD;
cf.crTextColor=RGB(0,0200);
cf.dwEffects=CFM_粗体;
发送消息(hWnd,EM_setel,0,-1);
SendMessage(hWnd、EM_设置字符格式、SCF_选择(LPRAM)和cf);
cf.dwMask=CFM_COLOR | CFM_BOLD;
cf.dwEffects=cf.dwEffects&~CFM_BOLD;
cf.crTextColor=RGB(200,0,0);
发送消息(hWnd、EM_设置、4、6);
SendMessage(hWnd、EM_设置字符格式、SCF_选择(LPRAM)和cf);
发送消息(hWnd、EM_设置、车厢位置、车厢位置);
_tprintf(文本(“结束突出显示”);
返回true;
}
LRESULT回调窗口过程(HWND HWND、UINT msg、WPARAM WPARAM、LPARAM LPARAM){
开关(msg){
案例WM_销毁:
PostQuitMessage(0);
打破
case WM_命令:{
if(LOWORD(wParam)==IDC\u编辑器和HIWORD(wParam)==EN\u更改)
返回updateHighlighting(hEditorWnd);
如果(LOWORD(wParam)==IDC\u按钮和HIWORD(wParam)==BN\u点击)
_tprintf(TEXT(“UNDO:can%i=>结果:%i\n”)、Edit_CanUndo(hEditorWnd)、Edit_UNDO(hEditorWnd));
}
打破
违约:
返回DefWindowProc(hWnd、msg、wParam、lParam);
}
返回0;
}
int WINAPI WinMain(HINSTANCE hThisInstance、HINSTANCE HPPreInstance、LPSTR lpszArgument、int nCmdShow){
InitCommonControls();
加载库(文本(“msftedit.dll”);
HWND-HWND;
味精;
WNDCLASSEX wincl;
wincl.hInstance=hthis实例;
wincl.lpszClassName=文本(“AppClass”);
wincl.lpfnWndProc=窗口程序;
wincl.style=CS_DBLCLKS;
wincl.cbSize=sizeof(WNDCLASSEX);
wincl.hIcon=加载图标(空,IDI_应用程序);
wincl.hIconSm=加载图标(空,IDI_应用程序);
wincl.hCursor=LoadCursor(空,IDC_箭头);
wincl.lpszMenuName=NULL;
wincl.cbClsExtra=0;
wincl.cbWndExtra=0;
wincl.hbrBackground=(HBRUSH)颜色背景;
if(!RegisterClass(&wincl))
返回0;
hWnd=CreateWindowEx(0,文本(“AppClass”)、文本(“测试”)、WS_重叠窗口| WS_可见、300、400、310、375、hWnd_桌面、NULL、hThisInstance、NULL);
CreateWindowEx(0,WC_按钮,L“撤消”,WS_可见| WS_子项| WS_选项卡,10,310,280,30,hWnd,(HMENU)IDC_按钮,hThisInstance,NULL);
hEditorWnd=CreateWindowEx(0,文本(“RICHEDIT50W”),NULL,WS|u可视| WS|u CHILD | ES|u多行| ES|u AUTOVSCROLL | ES|u WANTRETURN | WS|u HSCROLL | WS| u TABSTOP | ES| u NOHIDESEL,0,0,0,300,300,hWnd,(汉努)IDC u编辑器,hthis实例,NULL);
SendMessage(hEditorWnd,EM_SETEVENTMASK,0,ENM_CHANGE | ENM_UPDATE | ENM_KEYEVENTS);
while(GetMessage(&msg,NULL,0,0)){
翻译信息(&msg);
发送消息(&msg);
}
返回msg.wParam;
}

另外,我在Win7x64上使用Code::Block 17.12+gcc5.1(但要构建一个32位的应用程序)。

你对“不起作用”或“什么时候起作用”的确切含义尚不清楚,但是,更改颜色也是可以撤消的,因此如果你不想这样做,那么你必须在着色之前关闭撤消,并在着色之后恢复

我不知道是否有更简单的方法,但在C中,我使用以下函数:

//#include <windows, richedit, ...>
#include <TOM.h>

extern HWND ghEditWnd;

static IUnknown *pUnk;
static ITextDocument *pDoc;

static const IID IID_ITextDocument = {
    0x8CC497C0, 0xA1DF, 0x11CE,
    {0x80,0x98,0x00,0xAA,0x00,0x47,0xBE,0x5D}
};

static int tomInit(void)
{
    if (!pUnk) SendMessage(ghEditWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pUnk);
    if (!pUnk || pUnk->lpVtbl->QueryInterface(pUnk,&IID_ITextDocument, &pDoc) != NOERROR)
        {pUnk= 0; return FALSE;}
    return TRUE;
}
void undoSuspend(void)
{
    if (!pUnk) if (!tomInit()) return;
    pDoc->lpVtbl->Undo(pDoc,tomSuspend,0); //Suspends Undo.
}
void undoResume(void)
{
    if (!pUnk) if (!tomInit()) return;
    pDoc->lpVtbl->Undo(pDoc,tomResume,0);   // resume Undo.
}
void releaseTOM(void)
{
    if (pUnk) {
        pUnk->lpVtbl->Release(pUnk); pUnk= 0; pDoc= 0;
    }
}
/#包括
#包括
外部HWND ghEditWnd;
静态IUnknown*朋克;
静态ITextDocument*pDoc;
静态常量IID IID_ITextDocument={
0x8CC497C0、0xA1DF、0x11CE、,
{0x80,0x98,0x00,0xAA,0x00,0x47,0xBE,0x5D}
};
静态int-tomInit(void)
{
如果(!pUnk)发送消息(ghEditWnd,EM_GETOLEINTERFACE,0,(LPARAM)和pUnk);
如果(!pUnk | | pUnk->lpVtbl->QueryInterface(pUnk,&IID|u ITextDocument,&pDoc)!=NOERROR)
{pUnk=0;返回FALSE;}
返回TRUE;
}
作废撤消暂停(作废)
{
if(!pUnk)if(!tomInit())返回;
pDoc->lpVtbl->Undo(pDoc,tomSuspend,0);//挂起Undo。
}
作废恢复(作废)
{
if(!pUnk)if(!tomInit())返回;
pDoc->lpVtbl->Undo(pDoc,tomResume,0);//resume Undo。
}
无效释放汤姆(无效)
{
如果(朋克){
朋克->lpVtbl->释放(朋克);朋克=0;pDoc=0;
}
}
另见

编辑:有问题的建议是将UndoLimit设置为零。目前尚不清楚这是否也会清除现有的撤消堆栈


微软表示,在RichEdit 3.0中,撤销可以暂停并恢复。

您对“不起作用”或“何时起作用”的确切含义尚不清楚,但是,更改颜色也是可以撤销的,因此如果您不想这样做,那么您必须在着色之前关闭撤销,并在着色之后恢复

我不知道是否有更简单的方法,但在C中,我使用以下函数:

//#include <windows, richedit, ...>
#include <TOM.h>

extern HWND ghEditWnd;

static IUnknown *pUnk;
static ITextDocument *pDoc;

static const IID IID_ITextDocument = {
    0x8CC497C0, 0xA1DF, 0x11CE,
    {0x80,0x98,0x00,0xAA,0x00,0x47,0xBE,0x5D}
};

static int tomInit(void)
{
    if (!pUnk) SendMessage(ghEditWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pUnk);
    if (!pUnk || pUnk->lpVtbl->QueryInterface(pUnk,&IID_ITextDocument, &pDoc) != NOERROR)
        {pUnk= 0; return FALSE;}
    return TRUE;
}
void undoSuspend(void)
{
    if (!pUnk) if (!tomInit()) return;
    pDoc->lpVtbl->Undo(pDoc,tomSuspend,0); //Suspends Undo.
}
void undoResume(void)
{
    if (!pUnk) if (!tomInit()) return;
    pDoc->lpVtbl->Undo(pDoc,tomResume,0);   // resume Undo.
}
void releaseTOM(void)
{
    if (pUnk) {
        pUnk->lpVtbl->Release(pUnk); pUnk= 0; pDoc= 0;
    }
}
/#包括
#包括
外部HWND ghEditWnd;
静态IUnknown*朋克;
静态ITextDocument*pDoc;
静态常量IID IID_ITextDocument={
0x8CC497C0、0xA1DF、0x11CE、,
{0x80,0x98,0x00,0xAA,0x00,0x47,0xBE,0x5D}
};
静态int-tomInit(void)
{
如果(!pUnk)发送消息(ghEditWnd,EM_GETOLEINTERFACE,0,(LPARAM)和pUnk);
如果(!pUnk | | pUnk->lpVtbl->QueryInterface(pUnk,&IID|u ITextDocument,&pDoc)!=NOERROR)
{pUnk=0;返回FALSE