Delphi TPageControl 不响应选项卡上的点击

标签 delphi focus tabs click tpagecontrol

我有一个主窗体上带有 TPageControl 的应用程序。页面控件有几个选项卡。该应用程序可以最小化为托盘图标。有时在最小化运行一段时间后,当我恢复主窗口(通过鼠标右键单击托盘图标)时,会显示上次显示的选项卡,但无法选择任何其他选项卡!

如果我单击另一个选项卡,外观会发生变化,以便该选项卡看起来是事件选项卡(即选项卡本身移动到选项卡行的前面),但选项卡的主体保持原样。我还有菜单项和快捷键来选择其他选项卡,它们的行为相同。如果我输入 Alt-O(选项),顶部的选项选项卡将变为事件状态,但我看不到该选项卡主体上的内容 - 我仍然可以看到其他选项卡的内容。

我已经验证,当我单击另一个选项卡时,焦点会从第一个选项卡移开,而当我单击该选项卡时,焦点会移回。

我尚未确定该行为是否仅限于特定选项卡,因为它需要一段时间才能发生。

有什么想法吗?

更新

有趣的注释。我已经确定问题是在这些情况下发生的。应用程序启动,然后最小化到托盘。检测到警报条件,弹出一个窗口并恢复主窗口(这是应用程序的预期行为)。正是在这一点上观察到了错误 - 即,当我单击其他选项卡时,我看不到它们。

  • 启动应用程序。显示选项卡 1
  • 最小化应用程序。到托盘
  • 等待弹出窗口显示,主窗体已恢复
  • 单击选项卡 2 FAULT OBSERVED(选项卡 2 正文不显示)
  • 在 TWinControl.CreateHandle 中放置断点
  • 点击选项卡 3 - 休息
  • 运行 - 不显示选项卡 3 主体
  • 点击选项卡 1 - 不会中断
  • 单击选项卡 3 - 不会中断
  • 点击选项卡 4 - 休息
  • 运行 - 不显示选项卡 4 主体
  • 点击选项卡 1、2、3、4 - 不会中断

因此,选项卡似乎在第一次单击时创建了句柄,从那时起,它们认为它们存在,但它们没有显示。如果弹出窗口被禁用,则不会观察到故障。弹出窗口是由 Application.OnIdle 任务触发的。

另一个更新:一些进展。在网上查了一下之后,我做了一些修改。

我删除了以下代码:

procedure RestoreMainWindow ;

begin
MainForm.WindowState := wsNormal ;
MainForm.visible := true ;
Application.Restore ;
Application.BringToFront ;
ShowWindow (Application.Handle, SW_SHOW) ;  { show the taskbar button }
end ;

并将其替换为:

procedure RestoreMainWindow ;

begin
MainForm.Show () ;
MainForm.WindowState := wsNormal ;
Application.BringToFront () ;
ShowWindow (Application.Handle, SW_SHOW) ;  { show the taskbar button }
end ;

我删除了:

procedure TTADMainForm.SendToTray (Sender: TObject) ;

begin
MainForm.visible := false ;
ShowWindow (Application.Handle, SW_HIDE) ;  { hide the taskbar button }
end ;
...
Application.OnMinimize := SendToTray ;    

并将其替换为:

procedure TTADMainForm.ApplicationEvents1Minimize(Sender: TObject) ;

begin
Hide();
WindowState := wsMinimized ;
TrayIcon1.Visible := True;
end ;

问题似乎已经消失了。然而。现在我可以在启动后最小化应用程序,弹出窗口出现并以模式方式显示,主窗体显示,所有选项卡显示并工作。但。我无法再次最小化表单。 OnMinimize 处理程序在第一次后不会被触发。咕噜咕噜。

我仍然无法理解为什么它现在有效,这有点令人担忧。我怎样才能让它再次最小化?

最佳答案

完全根据 5 年前的内存进行工作,但这里是:

TPageControl 对其中的每个页面使用不同的窗口句柄。标签栏是它自己的窗口句柄,TPageControl负责监听标签变化并做出相应的页面隐藏/显示。因此,当您单击某个选项卡并且该选项卡跳转到包的前面时,TPageControl 应该隐藏当前页面窗口并显示与所选选项卡对应的页面窗口。

通常,VCL 控件不会创建其窗口句柄,直到实际需要时(例如,当它实际显示时)。这减少了窗口句柄消耗。在 Windows 3.1 和 Win95 中至关重要,但在当今基于 NT 的 32 位操作系统中则不那么重要。

为了最大限度地减少资源负载和启动时间,TPageControl 在创建控件时不会为其所有隐藏页面创建窗口句柄。页面窗口句柄将在首次显示时创建。

单击选项卡时未绘制页面的原因有几种可能:

  1. 耗尽 GDI 窗口句柄池。除非您使用的是 16 位 Windows 操作系统,否则极不可能。 (Win 3.1或Win95)
  2. 内存泄漏导致您的应用程序溢出到交换文件中并破坏硬盘。该应用程序会逐渐停止,看起来像是被卡住了,UI 事件时不时会出现断断续续的情况。
  3. 在没有消息循环的后台线程上创建的窗口句柄。您在后台线程中执行任何操作吗?在后台线程中触摸 VCL 控件可能会导致过早创建窗口句柄,并且窗口句柄将绑定(bind)到创建它的线程。如果该线程没有消息循环,则该窗口句柄将永远不会接收任何消息,因此它永远不会在屏幕上绘制自己。

没有。 3 是最有可能的罪魁祸首。那么,您在后台线程中做什么? ;>

关于Delphi TPageControl 不响应选项卡上的点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3242359/

相关文章:

delphi - 推送到特定用户

wpf - 撤消日记 : focusing the control being undone

android - 如何在另一个 Activity 中调用方法

windows - Delphi:如何设置(写入)扩展文件属性?

delphi - 在 Delphi 11.3 IDE 编辑器中,如何禁用双击时不需要的滚动?

Delphi - 如何将通用参数传递给接受 const 参数数组的函数

java - 使焦点不转到第一个组件

java - 当我在 JTextField 中写入时,JPopupMenu 会自动调整大小

java - 如何在使用新的android滑动选项卡技术时处理listview事件?

javascript - Chromium 上的 Indexeddb OpenCursor 是否在非事件选项卡上受到限制?