ShowCaret和SetCaretPos失败并出现ERROR_ACCESS_DENIED

Jos*_*osh 0 c++ winapi

什么可能导致ShowCaretSetCaretPos失败ERROR_ACCESS_DENIED

我正在创建插入符号WM_CREATE并显示插入符号WM_COMMAND.我检查并CreateCaret正在成功执行.

它们应该在同一个线程中运行.

我在调用之前使用SetScrollInfo并更新了我的窗口内容.但我不认为这会导致失败..InvalidateRectShowCaretShowCaret

相关代码:

#define CHAR_WIDTH  7
#define CHAR_HEIGHT 12

case WM_CREATE:
    CreateCaret(hWnd, NULL, CHAR_WIDTH, 2);
    UpdateScrollbar(hWnd); // calls SetScrollInfo. initially nMin and nMax are both 0
    return 0;

case WM_COMMAND:
    switch(LOWORD(wParam))
    {
    case IDM_OPENFILE:
        if (DoOpenFile(hWnd))
        {
            InvalidateRect(hWnd, NULL, TRUE);
            UpdateScrollbar(hWnd);

            if (SetCaretPos(CHAR_WIDTH * 12, CHAR_HEIGHT - 1) == 0)
            {
                char ss[33];
                sprintf_s(ss, "DEBUG 2: %d\n", GetLastError());
                OutputDebugString(ss);
            }

            if (ShowCaret(hWnd) == 0)
            {
                char ss[33];
                sprintf_s(ss, "DEBUG 3: %d\n", GetLastError());
                OutputDebugString(ss);
            }
        }
        break;
    }
    return 0;
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

是的,你没有正确地这样做.每个消息队列只有一个插入符号(换句话说,每个线程).当另一个窗口已经有一个插入符号时,您无法创建插入符号,编辑框是最可能的情况.你必须不能创建插入符号或显示它,直到你的窗口接收焦点,WM_SETFOCUS消息.当窗口失去焦点时,你必须销毁它,WM_KILLFOCUS消息.

你使用GetLastError()的方式也很危险,尽管你现在可能已经侥幸逃脱了.在C或C++中求值参数的顺序不是确定性的.您冒着其中一个参数表达式改变错误代码的风险.在调用其他任何内容之前始终获取错误代码,将其存储在本地变量中.

从来没有跳过错误检查,在最起码你必须断言()的返回值.CreateCaret()调用可能现在失败,因为刚创建的窗口永远不会有焦点.