自由浮动控件的实现
浮动工具条应该都不会陌生。MS Office Word 、Excel中都有,只要你选中内容就会出现透明淡淡的工具条。鼠标移动到上面就会显示。
要实现浮动效果只要把 ParentHandle = 0 系统就会把控件浮出显示,但效果不好,系统任务条上会出现多余的东西,程序焦点会被显示的控件夺走。
解决这个问题,需要系统的API提供了几个样式扩展参数。
- WS_EX_TOOLWINDOW 这个木,像浮动工具条一样一样样的。
- WS_EX_APPWINDOW 控件浮出来后会在系统工具条上显示出来,作为工具条这个肯定是不应该出现的。
- WS_EX_NOACTIVATE 防止主界面的Active被干掉,保证你界面的Focus有效
- WS_EX_TOPMOST 窗口置顶设置
这种方案适用单一控件浮动控制,主要是因为多控件需要对多种事件进行特殊处理才能达到比较理想的效果。
有效:不需要焦点处理的控件(toolbar),单一控件(如Edit,Listbox 等)
不推荐复合处理,建议特殊处理 如:Frame或Panel中放置了很多需要消息控制的控件。
处理步骤
- 去除ParentHandle控制,让其浮出
- 设置控件样式,让它看起来像一个真的浮动对象
- 处理你需要的响应消息
通过上述3步就能实现一个简单的浮出。
测试环境
- Delphi XE2
- WIN7
代码实现
type TWinAcc = class(TWinControl); procedure TForm9.Button3Click(Sender: TObject); var cDrop: TWinControl; v:NativeInt; begin cDrop := TListBox.Create(Edit4); cDrop.Visible := False; cDrop.Parent := Edit4; // 设置样式,变成浮动窗体 /// WS_EX_APPWINDOW --- 去掉系统工具条显示 /// WS_EX_NOACTIVATE --- 不使用Active,这样主界面就不会闪烁问题 /// WS_EX_TOOLWINDOW --- (这个木,像浮动工具条一样一样样的) v := GetWindowLong(cDrop.Handle, GWL_EXSTYLE); v := v and not WS_EX_APPWINDOW or WS_EX_NOACTIVATE or WS_EX_TOOLWINDOW; SetWindowLong(cDrop.Handle, GWL_EXSTYLE, v); // 这个木自然是为了把控件浮出界面 Winapi.Windows.SetParent(cDrop.Handle, 0); // 这个很重要,由于没有了Active,无法正常处理焦点问题 // 因此需要接收处理 SetFocus 的消息 CallWindowProc(TWinAcc(cDrop).DefWndProc, cDrop.Handle, WM_SETFOCUS, 0, 0); TListBox(cDrop).Items.Assign(ListBox1.Items); cDrop.Width := 300; cDrop.Height := 230; cDrop.Visible := True; end;
使用这种方式可以实现一些比较复杂ComboBox的下拉样式。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步