ShowCaret和SetCaretPos失败并出现ERROR_ACCESS_DENIED

时间:2013-03-02 15:42:07

标签: c++ winapi

ShowCaret会导致SetCaretPosERROR_ACCESS_DENIED失败的原因是什么?

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

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

我在调用SetScrollInfo之前使用InvalidateRectShowCaret来更新我的窗口内容。但我认为这些不会导致ShowCaret失败..

相关代码:

#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;

1 个答案:

答案 0 :(得分:5)

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

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

并且从不跳过错误检查,至少你必须断言()返回值。 CreateCaret()调用可能现在失败,因为刚创建的窗口永远不会有焦点。