ShowCaret
会导致SetCaretPos
和ERROR_ACCESS_DENIED
失败的原因是什么?
我正在WM_CREATE
创建插入符并在WM_COMMAND
中显示插入符号。
我检查了CreateCaret
正在成功执行。
它们应该在同一个线程中运行。
我在调用SetScrollInfo
之前使用InvalidateRect
和ShowCaret
来更新我的窗口内容。但我认为这些不会导致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;
答案 0 :(得分:5)
是的,你没有正确地这样做。每个消息队列只有一个插入符号(换句话说,每个线程)。当另一个窗口已经有一个插入符号时,您无法创建插入符号,编辑框是最可能的情况。在您的窗口收到焦点WM_SETFOCUS消息之前,您必须才能创建插入符号或显示它。当窗口失去焦点时,你必须销毁它,WM_KILLFOCUS消息。
你使用GetLastError()的方式也很危险,虽然你现在可能已经侥幸逃脱了。在C或C ++中求值参数的顺序不是确定性的。您冒着其中一个参数表达式改变错误代码的风险。在调用其他任何内容之前始终获取错误代码,将其存储在本地变量中。
并且从不跳过错误检查,至少你必须断言()返回值。 CreateCaret()调用可能现在失败,因为刚创建的窗口永远不会有焦点。