gpt4 book ai didi

c++ - 在编辑控件中显示无效输入的工具提示

转载 作者:可可西里 更新时间:2023-11-01 15:14:33 28 4
gpt4 key购买 nike

我将编辑控件子类化为只接受 float 。当用户输入无效时,我想弹出一个工具提示。我的目标行为就像一个带有 ES_NUMBER 的编辑控件有:

enter image description here

到目前为止,我已经能够实现跟踪工具提示并在用户进行无效输入时显示它。

但是,工具提示放错了地方。我试过使用 ScreenToClientClientToScreen解决这个问题但失败了。

以下是创建 SCCE 的说明:

1) 在 Visual Studio 中创建默认的 Win32 项目。

2) 在您的 stdafx.h 中添加以下内容, 就在 #include <windows.h> 之下:

#include <windowsx.h>
#include <commctrl.h>

#pragma comment( lib, "comctl32.lib")

#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"publicKeyToken='6595b64144ccf1df' "\
"language='*'\"")

3) 添加这些全局变量:

HWND g_hwndTT;
TOOLINFO g_ti;

4) 这是一个用于编辑控件的简单子(monad)类过程(仅用于测试目的):

LRESULT CALLBACK EditSubProc ( HWND hwnd, UINT message, 
WPARAM wParam, LPARAM lParam,
UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
{
switch (message)
{
case WM_CHAR:
{
POINT pt;
if( ! isdigit( wParam ) ) // if not a number pop a tooltip!
{
if (GetCaretPos(&pt)) // here comes the problem
{
// coordinates are not good, so tooltip is misplaced
ClientToScreen( hwnd, &pt );


/************************** EDIT #1 ****************************/
/******* If I delete this line x-coordinate is OK *************/
/*** y-coordinate should be little lower, but it is still OK **/
/**************************************************************/

ScreenToClient( GetParent(hwnd), &pt );

/************************* Edit #2 ****************************/

// this adjusts the y-coordinate, see the second edit
RECT rcClientRect;
Edit_GetRect( hwnd, &rcClientRect );
pt.y = rcClientRect.bottom;

/**************************************************************/

SendMessage(g_hwndTT, TTM_TRACKACTIVATE,
TRUE, (LPARAM)&g_ti);
SendMessage(g_hwndTT, TTM_TRACKPOSITION,
0, MAKELPARAM(pt.x, pt.y));
}
return FALSE;
}
else
{
SendMessage(g_hwndTT, TTM_TRACKACTIVATE,
FALSE, (LPARAM)&g_ti);
return ::DefSubclassProc( hwnd, message, wParam, lParam );
}
}
break;
case WM_NCDESTROY:
::RemoveWindowSubclass( hwnd, EditSubProc, 0 );
return DefSubclassProc( hwnd, message, wParam, lParam);
break;
}
return DefSubclassProc( hwnd, message, wParam, lParam);
}

5) 添加以下 WM_CREATE处理程序:

case WM_CREATE:
{
HWND hEdit = CreateWindowEx( 0, L"EDIT", L"edit", WS_CHILD | WS_VISIBLE |
WS_BORDER | ES_CENTER, 150, 150, 100, 30, hWnd, (HMENU)1000, hInst, 0 );

// try with tooltip
g_hwndTT = CreateWindow(TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
0, 0, 0, 0, hWnd, NULL, hInst, NULL);

if( !g_hwndTT )
MessageBeep(0); // just to signal error somehow

g_ti.cbSize = sizeof(TOOLINFO);
g_ti.uFlags = TTF_TRACK | TTF_ABSOLUTE;
g_ti.hwnd = hWnd;
g_ti.hinst = hInst;
g_ti.lpszText = TEXT("Hi there");

if( ! SendMessage(g_hwndTT, TTM_ADDTOOL, 0, (LPARAM)&g_ti) )
MessageBeep(0); // just to have some error signal

// subclass edit control
SetWindowSubclass( hEdit, EditSubProc, 0, 0 );
}
return 0L;

6) 在MyRegisterClass中初始化常用控件(在 return 声明之前):

// initialize common controls
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_BAR_CLASSES | ICC_WIN95_CLASSES |
ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_STANDARD_CLASSES ;

if( !InitCommonControlsEx(&iccex) )
MessageBeep(0); // signal error

就是这样,SSCCE

我的问题如下:

  1. 如何在我的主窗口中正确定位工具提示?我应该如何使用插入符坐标进行操作?

  2. 有没有办法让 tooltip handle 和 toolinfo 结构不是全局的?

感谢您的宝贵时间。

最好的问候。

编辑#1:

我通过删除 ScreenToClient 取得了相当大的进步调用子类过程。 x坐标很好,y坐标可以稍微低一点。我仍然想以某种方式删除全局变量...

编辑#2:

我可以使用 EM_GETRECT 调整 y 坐标消息并将 y 坐标设置为格式矩形的底部:

RECT rcClientRect;
Edit_GetRect( hwnd, &rcClientRect );
pt.y = rcClient.bottom;

现在最终结果好多了。剩下的就是删除全局变量...

编辑#3:

看来我破解了!解决方案在EM_SHOWBALLOONTIPEM_HIDEBALLOONTIP消息! Tooltip 放在了 caret 位置,气球形状和图片上的一样,并且自动关闭了。最棒的是,我不需要全局变量!

这是我的子类过程片段:

case WM_CHAR:
{
// whatever... This condition is for testing purpose only
if( ! IsCharAlpha( wParam ) && IsCharAlphaNumeric( wParam ) )
{
SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0);
return ::DefSubclassProc( hwnd, message, wParam, lParam );
}
else
{
EDITBALLOONTIP ebt;

ebt.cbStruct = sizeof( EDITBALLOONTIP );
ebt.pszText = L" Tooltip text! ";
ebt.pszTitle = L" Tooltip title!!! ";
ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip icon

SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);

return FALSE;
}
}
break;

最佳答案

经过进一步测试,我决定将此作为答案,以便其他人可以清楚地发现它。

解决方案是使用 EM_SHOWBALLOONTIPEM_HIDEBALLOONTIP 消息。 您不需要创建工具提示并将其关联到编辑控件!因此,我现在需要做的只是子类化编辑控件,一切正常:

LRESULT CALLBACK EditSubProc ( HWND hwnd, UINT message, 
WPARAM wParam, LPARAM lParam,
UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
{
switch (message)
{
case WM_CHAR:
{
if( ! isdigit( wParam ) ) // if not a number pop a tooltip!
{
EDITBALLOONTIP ebt;

ebt.cbStruct = sizeof( EDITBALLOONTIP );
ebt.pszText = L" Tooltip text! ";
ebt.pszTitle = L" Tooltip title!!! ";
ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip icon

SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
return FALSE;
}
else
{
SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0);
return ::DefSubclassProc( hwnd, message, wParam, lParam );
}
}
break;
case WM_NCDESTROY:
::RemoveWindowSubclass( hwnd, EditSubProc, 0 );
return DefSubclassProc( hwnd, message, wParam, lParam);
break;
}
return DefSubclassProc( hwnd, message, wParam, lParam);
}

就是这样!

希望这个答案也能帮到别人!

关于c++ - 在编辑控件中显示无效输入的工具提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23892594/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com