Delphi TPageControl没有响应选项卡上的点击

时间:2010-07-13 23:33:31

标签: delphi focus tabs click tpagecontrol

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

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

我已经确认当我点击另一个标签时焦点从第一个标签移开,当我点击该标签时向后移动。

我还没有确定行为是否局限于某个特定标签,因为它需要一段时间才会发生。

有什么想法吗?

更新

有趣的说明。我已经确定在这种情况下会出现问题。应用程序启动,然后最小化到托盘。检测到警报条件,弹出窗口并恢复主窗口(这是应用程序的预期行为)。正是在这一点上观察到了错误 - 即当我点击它们时我无法看到其他标签。

  • 启动应用。显示标签1
  • 最小化应用。托盘
  • 等待弹出窗口显示,主窗体恢复
  • 点击Tab 2 FAULT OBSERVED(标签2正文不显示)
  • 将断点放在TWinControl.CreateHandle
  • 点击Tab 3 - 中断
  • 运行 - 不显示标签3正文
  • 点击标签1 - 不会中断
  • 点击标签3 - 不会中断
  • 点击Tab 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处理程序不会被触发。 Grrrrr。

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

1 个答案:

答案 0 :(得分:3)

完全从5年前的记忆开始工作,但这里有:

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

通常情况下,VCL控件在实际需要之前不会创建窗口句柄 - 例如,实际显示它时。这减少了窗口句柄消耗。在Windows 3.1和Win95中非常重要,但在今天的基于NT的32位操作系统中并不那么重要。

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

单击选项卡时,为什么没有绘制页面有几种可能性:

  1. 耗尽GDI窗口句柄池。除非您使用的是16位Windows操作系统,否则极不可能。 (赢得3.1或Win95)
  2. 内存泄漏导致您的应用程序溢出到交换文件中并使硬盘崩溃。该应用程序将濒临停止,看起来像是冻结了,偶尔也会出现UI活动。
  3. 在没有消息循环的后台线程上创建窗口句柄。你在后台线程做什么吗?触摸后台线程中的VCL控件可能导致窗口句柄过早创建,窗口句柄将绑定到创建它的线程。如果该线程没有消息循环,那么该窗口句柄将永远不会收到任何消息,因此它永远不会在屏幕上绘制。
  4. 没有。 3是你最可能的罪魁祸首。那么,你在后台线程做什么? ;>