我在下面给出了我的问题的英文解释,但这是一个视觉问题所以如果你不想阅读它只是看看底部的图片。)
我正在为我的班级构建一个反向抛光符号计算器,我刚刚完成了我的GUI上的按钮控件能够将它们的值附加到编辑控件,该编辑控件工作正常,但插入符号正在做一些奇怪的事情。我找不到任何关于它的信息。
我向编辑控件发送一条自定义消息,在该控件中它找到控件中当前文本的长度,然后将插入符号放在文本的末尾,这样我就可以添加需要添加的文本(它是与ES_RIGHT
)右对齐,再次正常工作,但当插入符号位于最右边的位置时,它几乎正好位于任何数字的中间位置。
这似乎只发生在插入符号最右边的位置(即插入符号位于前一个字符右侧的任何其他位置,应该如此)我尝试将插入符号一直替换为右侧使用代码,使用我的键盘/鼠标放置它,并尝试调整窗口的尺寸,希望它只是我为它定义的宽度的偏移导致最后一个地方稍微关闭,但问题仍然存在,它这使得很难阅读文本字段中的最后一个字符。
相关守则:
LRESULT CALLBACK EditBoxClass::WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_COMMAND:
break;
case WM_APPEND_EDIT:
/* Get current length of text in the box */
index = new int( GetWindowTextLength (hWnd) );
SetFocus( hWnd );
/* Set the caret to the end of the text in the box */
SendMessage( hWnd, EM_SETSEL, (WPARAM)index, (LPARAM)index );
/* "Replace" the selection (the selection is actually targeting
nothing and just sits at the end of the text in the box)
with the passed in TCHAR* from the button control that
sent the WM_APPEND_EDIT message */
SendMessage( hWnd, EM_REPLACESEL, 0, lParam );
break;
}
return CallWindowProc( EditClassStruct.GetOldProc(), hWnd, msg, wParam, lParam );
}
问题图片:
答案 0 :(得分:1)
这可能是原因,也可能不是原因,但您滥用EM_SETSEL
。您正在堆上动态分配(和泄漏)int
并将指针作为消息参数传递给它,但EM_SETSEL
不期望或使用指针开始。所以摆脱动态分配。
此外,默认窗口proc不会知道如何处理您的WM_APPEND_EDIT
消息,因此将消息传递给CallWindowProc()
是没有意义的。
请改为尝试:
case WM_APPEND_EDIT:
{
/* Get current length of text in the box */
int index = GetWindowTextLength( hWnd );
SetFocus( hWnd );
/* Set the caret to the end of the text in the box */
SendMessage( hWnd, EM_SETSEL, (WPARAM)index, (LPARAM)index );
/* "Replace" the selection (the selection is actually targeting
nothing and just sits at the end of the text in the box)
with the passed in TCHAR* from the button control that
sent the WM_APPEND_EDIT message */
SendMessage( hWnd, EM_REPLACESEL, 0, lParam );
return 0;
}
话虽如此,请尝试使用EM_GETRECT
/ EM_SETRECT
将编辑控件formatting rectangle的右边缘展开几个像素。这应该给予插入符号一些额外的工作空间。
答案 1 :(得分:1)
在面对同样的问题并在这个答案中展示我的第一个方法之后,我现在将提供两个很好的解决方案。我认为没有其他方法可以正确解决这个故障(除非你是负责WinAPI这一部分的微软程序员)。
我想知道如何在使用ES_MULTILINE
创建的编辑控件上修复此问题,但这个故障似乎只是单行编辑控件上的问题(在Windows 7 64位上测试)。启用视觉样式也很有帮助,但问题仍然存在(偏移至少不那么明显)。
通常,当插入符号位于最右侧位置时,它的x值(由GetCaretPos ()
提供)应等于rect.right
提供的EM_GETRECT
值(当编辑控件为使用ES_RIGHT
创建。由于原因不明,情况并非如此。因此,您必须检查插入位置是否至少在rect.right
值附近(但不比最后一个字母宽)。所以你有两种可能性来完成这项任务:
GetTextExtentPoint32 ()
计算外部右侧字符的宽度,并使用rect.right
调用SendMessage ()
提供的EM_GETRECT
值减去它,并检查x位置插入符号大于结果或不是OR rect.right
值与右外角度位置(我的情况下为3
)之间的差距,并将此值用作硬编码偏移量以进行简单检查。在这些步骤之后(无论您选择哪一个),必须在必要时重新定位插入符号。
case WM_LBUTTONDOWN: {
TRACKMOUSEEVENT tme = {sizeof (tme), TME_LEAVE, hwnd, HOVER_DEFAULT};
TrackMouseEvent (&tme);
}
break;
case WM_KEYDOWN:
case WM_MOUSELEAVE:
case WM_SETCURSOR: {
DefSubclassProc (hwnd, message, wParam, lParam);
DWORD end;
SendMessage (hwnd, EM_GETSEL, (WPARAM) NULL, (LPARAM) &end);
int len = GetWindowTextLength (hwnd);
if (end < len || len <= 0)
return TRUE;
wchar_t *buffer = new wchar_t[len + 1];
GetWindowText (hwnd, buffer, len + 1);
wchar_t lastChar[] = {buffer[len - 1], '\0'};
delete[] buffer;
SIZE size;
HDC hdc = GetDC (hwnd);
if (hdc == NULL)
return TRUE;
GetTextExtentPoint32 (hdc, lastChar, 1, &size);
ReleaseDC (hwnd, hdc);
POINT pt;
RECT rect;
GetCaretPos (&pt);
SendMessage (hwnd, EM_GETRECT, (WPARAM) 0, (LPARAM) &rect);
if ((rect.right - size.cx) <= pt.x)
SetCaretPos (rect.right, pt.y);
return TRUE;
}
break;
case WM_LBUTTONDOWN: {
TRACKMOUSEEVENT tme = {sizeof (tme), TME_LEAVE, hwnd, HOVER_DEFAULT};
TrackMouseEvent (&tme);
}
break;
case WM_KEYDOWN:
case WM_MOUSELEAVE:
case WM_SETCURSOR: {
DefSubclassProc (hwnd, message, wParam, lParam);
POINT pt;
RECT rect;
GetCaretPos (&pt);
SendMessage (hwnd, EM_GETRECT, (WPARAM) 0, (LPARAM) &rect);
if ((rect.right - pt.x) <= 3)
SetCaretPos (rect.right, pt.y);
return TRUE;
}
break;
您必须创建编辑控件的子类。然后在他们的窗口程序中使用此代码并享受。
在这两种情况下,跟踪鼠标事件并非绝对必要,但建议完全避免此故障。调用DefSubclassProc ()
将确保在鼠标悬停时更改光标。