如何防止我的窗口获得输入焦点?

问题描述 投票:0回答:1

我正在实现一个 AutoComplete,但它会匹配枚举字符串列表中任何位置的文本,而不仅仅是像内置 SHAutoComplete 控件的行为那样只是建议的开头。 例如:

enter image description here

“弹出”

窗口是一个TForm,它必须:

  • CreateParams

    期间设置

    CS_DROPSHADOW
    样式(当然要检查SPI_GETDROPSHADOW;我不是一个不缴税的
    异教徒
    Params.WindowClass.Style := Params.WindowClass.Style or CS_DROPSHADOW;

  • 当然,将其
  • WndParent

    设置为保存

    TEdit
    的表单(以便下拉列表出现在弹出的表单顶部) Params.WndParent := FWndParent;

    
    
  • 我的
Up

DownReturnEscape 键盘导航工作正常。打字员可以快速选择他们想要的项目,然后建议列表就会关闭。 表单包含实际项目的

TListView

(很像 Windows 中的 CAutoComplete SHAutoComplete 类)。

点击获得焦点

如果用户

单击

下拉列表中的某个项目,则使用 Inspect(SDK 中的辅助功能工具)我们可以看到焦点已分配给 (现已隐藏)中的列表项之一下拉菜单:

enter image description here 您甚至可以看到标题栏表明整个窗口都具有焦点。

如何防止我的窗口获得输入焦点?

尝试

返回

MA_NOACTIVATE

我尝试回复 

WM_MOUSEACTIVATE

 窗口消息并返回 
MA_NOACTIVATE:

返回代码/值MA_激活(1)MA_ACTIVATEANDEAT (2)MA_NOACTIVATE (3)MA_NOACTIVATEANDEAT (4)
描述
激活窗口,并且不丢弃鼠标消息。
激活窗口,并丢弃鼠标消息。
不激活窗口,也不丢弃鼠标消息。
不激活窗口,但丢弃鼠标消息。
如:

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

失去焦点时,它会隐藏建议下拉菜单。所以可能正在进行一场
焦点锁定竞赛。

简短版 有更好的方法吗?

奖励阅读(又名研究工作)

防止窗口自动获得焦点(使用 Windows API)

  • 通知窗口 - 防止窗口获得焦点
  • 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;
delphi winapi window focus
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.