我正在实现一个 AutoComplete,但它会匹配枚举字符串列表中任何位置的文本,而不仅仅是像内置 SHAutoComplete 控件的行为那样只是建议的开头。 例如:
“弹出”窗口是一个TForm,它必须:
期间设置
CS_DROPSHADOW
样式(当然要检查SPI_GETDROPSHADOW
;我不是一个不缴税的异教徒)
Params.WindowClass.Style := Params.WindowClass.Style or CS_DROPSHADOW;
WndParent
设置为保存
TEdit的表单(以便下拉列表出现在弹出的表单顶部)
Params.WndParent := FWndParent;
、Down、Return、Escape 键盘导航工作正常。打字员可以快速选择他们想要的项目,然后建议列表就会关闭。 表单包含实际项目的
TListView(很像 Windows 中的 CAutoComplete
SHAutoComplete 类)。
下拉列表中的某个项目,则使用 Inspect(SDK 中的辅助功能工具)我们可以看到焦点已分配给 (现已隐藏)中的列表项之一下拉菜单:
如何防止我的窗口获得输入焦点?
尝试
MA_NOACTIVATE
窗口消息并返回
MA_NOACTIVATE
:
描述 | |
---|---|
激活窗口,并且不丢弃鼠标消息。 | |
激活窗口,并丢弃鼠标消息。 | |
不激活窗口,也不丢弃鼠标消息。 | |
不激活窗口,但丢弃鼠标消息。 |
procedure TfrmAutoComplete.WMMouseActivate(var Msg: TMessage);
begin
inherited;
Msg.Result := MA_NOACTIVATE;
end;
但它仍然受到关注。
WM_ACTIVATE期间设置焦点
WM_ACTIVATE
期间调用SetFocus:
procedure TfrmAutoComplete.WMActivate(var Msg: TMessage);
begin
inherited;
Msg.Result := MA_NOACTIVATE;
Windows.SetFocus(FEdit.Handle);
end;
Raymond Chens谈论为什么这是一个坏主意处理 WM_ACTIVATE 消息时扰乱激活的危险
焦点锁定竞赛。陈雷蒙德,2005 年 8 月 9 日
这与处理 WM_KILLFOCUS 消息时玩焦点游戏的危险基本相同,只是用激活代替焦点。
一位开发人员艰难地发现,如果您在 WM_ACTIVATE 处理程序中搞乱了激活,事情就会变得很奇怪。作者指出,如果他发布一条消息并根据发布的消息执行工作,那么一切都会正常。 原始消息的后续内容指出,将 SWP_NOACTIVATE 标志传递给 SetWindowPos 函数可以解决该问题。你明白为什么吗?
当然,当 TEdit
失去焦点时,它会隐藏建议下拉菜单。所以可能正在进行一场
procedure TfrmAutoComplete.WMActivate(var Msg: TWMActivate);
begin
inherited;
if Msg.Active = 0 then
begin
if Visible then
begin
Hide;
end;
end
else
begin
SendMessage(FWndParent, WM_NCACTIVATE, 1, 0);
end;
end;