- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在使用 delphi 的最后几天,我很头疼,我想做的很简单,在某个时间点阻止界面并在其他时间点后启用。
但就像听起来一样,我无法弄清楚为什么设计允许某些东西,所以要澄清一下:
1)创建项目
2)在表单中放置一个编辑和一个按钮,编辑的标签顺序必须在前
3)配置编辑写入的OnExit事件:
Enabled := False;
ShowMessage('this is right?');
最佳答案
两者 TButton
和 TEdit
是 TWinControl
后代 - 这意味着它们是窗口控件。当它们被创建时,它们被分配了自己的 HWND
当他们获得焦点时,操作系统会直接向他们发送消息。禁用它们的包含表单会阻止主表单接收输入消息或接收焦点,但如果它已经具有输入焦点,则不会禁用任何其他窗口控件。
如果这些控件没有输入焦点,则包含表单有责任在用户输入(单击、Tab 键等)指示时将输入焦点转移给它们。如果表单被禁用并且这些控件未获得焦点,则表单将不会接收允许其转移焦点的输入消息。但是,如果焦点转移到窗口控件,则所有用户输入都会直接转到该控件,即使其父控件的窗口被禁用 - 它们实际上是它们自己的单独窗口。
我不确定您观察到的行为是错误 - 这可能不是预期的,但它是标准行为。通常不会期望禁用一个窗口也会禁用同一应用程序中的其他窗口。
问题是有两个独立的层次结构在起作用。在 VCL 级别,Button 是一个子控件并且有一个父控件(窗体)。然而,在操作系统级别,两者都是单独的窗口,操作系统不知道(组件级别)父/子关系。这将是类似的情况:
procedure TForm1.Button1Click(Sender: TObject);
var
form2 : TForm1;
begin
self.Enabled := false;
form2 := TForm1.Create(self);
try
form2.ShowModal;
finally
form2.Free;
end;
end;
你真的会期待
form2
在显示时被禁用,仅仅是因为它的
TComponent
店主是
Form1
?当然不是。窗口控件大致相同。
The system passes a child window's input messages directly to thechild window; the messages are not passed through the parent window.The only exception is if the child window has been disabled by theEnableWindow function. In this case, the system passes any inputmessages that would have gone to the child window to the parent windowinstead. This permits the parent window to examine the input messagesand enable the child window, if necessary.
TWinControl
s 的行为是这样的:
TSafeButton = class(TButton)
protected
procedure WndProc(var Msg : TMessage); override;
end;
{...}
procedure TSafeButton.WndProc(var Msg : TMessage);
function ParentForm(AControl : TWinControl) : TWinControl;
begin
if Assigned(AControl) and (AControl is TForm) then
result := AControl
else
if Assigned(AControl.Parent) then
result := ParentForm(AControl.Parent)
else result := nil;
end;
begin
if Assigned(ParentForm(self)) and (not ParentForm(self).Enabled) then
Msg.Result := 0
else
inherited;
end;
这会沿着 VCL 父树向上走,直到找到一个表单——如果它找到了并且表单被禁用,那么它也会拒绝对窗口控件的输入。凌乱,可能更有选择性(也许有些消息不应该被忽略......)但这将是一些可行的开始。
Only one window at a time can receive keyboard input; that window issaid to have the keyboard focus. If an application uses theEnableWindow function to disable a keyboard-focus window, the windowloses the keyboard focus in addition to being disabled. EnableWindowthen sets the keyboard focus to NULL, meaning no window has the focus.If a child window, or other descendant window, has the keyboard focus,the descendant window loses the focus when the parent window isdisabled. For more information, see Keyboard Input.
oldParent := WinAPI.Windows.SetParent(Button1.Handle, Form1.Handle);
// here, in fact, oldParent = Form1.Handle, so parent/child HWND
// relationship is correct by default.
多一点(用于重现) - 相同的场景
Edit
选项卡焦点到按钮,退出处理程序启用 TTimer。这里表单被禁用,但按钮保持焦点,即使这似乎确认 Form1 的 HWND 确实是按钮的父窗口,它应该失去焦点。
procedure TForm1.Timer1Timer(Sender: TObject);
var
h1, h2, h3 : cardinal;
begin
h1 := GetFocus; // h1 = Button1.Handle
h2 := GetParent(h1); // h2 = Form1.Handle
self.Enabled := false;
h3 := GetFocus; // h3 = Button1.Handle
end;
在
的情况下我们将按钮移动到面板 ,一切似乎都按预期工作(大部分)。面板被禁用,按钮失去焦点,但焦点然后移动到父窗体(WinAPI 建议它应该是 NULL)。
procedure TForm1.Timer1Timer(Sender: TObject);
var
h1, h2, h3 : cardinal;
begin
h1 := GetFocus; // h1 = Button1.Handle
h2 := GetParent(h1); // h2 = Panel1.Handle
Panel1.Enabled := false;
h3 := GetFocus; // h3 = Form1.Handle
end;
问题的一部分似乎在这里 - 看起来顶级表单本身正在为散焦控件负责。这有效,除非表单本身被禁用:
procedure TWinControl.CMEnabledChanged(var Message: TMessage);
begin
if not Enabled and (Parent <> nil) then RemoveFocus(False);
// ^^ False if form itself is being disabled!
if HandleAllocated and not (csDesigning in ComponentState) then
EnableWindow(WindowHandle, Enabled);
end;
procedure TWinControl.RemoveFocus(Removing: Boolean);
var
Form: TCustomForm;
begin
Form := GetParentForm(Self);
if Form <> nil then Form.DefocusControl(Self, Removing);
end
哪里
procedure TCustomForm.DefocusControl(Control: TWinControl; Removing: Boolean);
begin
if Removing and Control.ContainsControl(FFocusedControl) then
FFocusedControl := Control.Parent;
if Control.ContainsControl(FActiveControl) then SetActiveControl(nil);
end;
这部分解释了上述观察到的行为 - 焦点移动到父控件,事件控件失去焦点。它仍然没有解释为什么“EnableWindow”无法将焦点移到按钮的子窗口。这确实开始看起来像一个 WinAPI 问题......
关于delphi - 禁用表单仍然允许子控件接收输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28408953/
请在标记为重复之前阅读。 我正在创建一组依赖智能卡进行身份验证的应用程序。到目前为止,每个应用程序都单独控制智能卡读卡器。几周后,我的一些客户将同时使用多个应用程序。因此,我认为创建一个控制身份验证过
我想设置一个小程序,从数据库中检索信息,然后根据请求将该信息分发给另一个程序。例如,一个名为“Master”的程序将从数据库中检索数据并创建一个对象集合(列表、数组等,无论哪种效果最好),然后一个名为
我有两台电脑,都装有 XE2。我以为我在两者上安装了相同的安装,但在其中一个上安装第 3 方软件包时遇到问题,而另一个则正常。 无论如何,我希望两者都一样。最简单的人可能只是通过移入我的 Dropbo
有冲突吗? 最佳答案 所有新版本的 Delphi 始终可以安全地安装到旧版本的下一个版本。 每个新版本都应安装在其自己的目录中。 如果您要安装多个版本,请始终先安装最旧的版本,然后再安装最新版本。 我
快速提问:如果我从代码中删除 // 或 (* *) 中的注释,Delphi 2007 的执行时间会受到影响吗?最终结果是一个可能包含数千行注释的 EXE 文件。 最佳答案 编译器会简单地忽略注释,并且
我必须对照另一个文件检查文件的每一行。 如果第二个文件中存在第一个文件中的一行,则必须删除它。 现在,我正在使用2个列表框,并且“对于listbox1.items.count-1可以开始...” 我的
我正在尝试在访问数据库中添加一些数据。但是我有麻烦,因为这会返回错误: ADOQuery1 missing sql property 实现了对代码的几次修改,到目前为止没有任何效果。 我究竟做错了什么
我用Delphi 5编写了一个程序,在Windows 8 32位PC上可以正常运行。我发现在Windows 7 64位笔记本电脑上运行它最终会导致reallocmem错误,而该错误在32位PC上不会发
看来这是我需要的工具,用于提取XML并与TClientDataset连接。我已经在几篇文章和文档中看到了它,但是我无法在XE2组件列表中找到它-在任何地方!应该在哪里?是否在可能未安装的可选软件包中?
我正在寻找一个非常通用的TDBTree组件,我想听听一些建议。我正在特别寻找一种显示主记录和“ n”个链接表记录的记录。 (我的意思是来自各个表的记录)。例如,TDBTree将钩接到主表,明细表1,附
我需要将按钮制作成旋转三角形的形状(或者说是任何多边形)。谁能提供任何建议? 最佳答案 查看Win32 API CreatePolygonRgn()和SetWindowRgn()函数,以创建一个HRG
你好专家 我的JvPasswordForm1有一个旧的JVC组件。 似乎该组件不再存在:它替换为哪个组件? 重新获得 最佳答案 尝试查找TJvLoginDialog,TjvPassword已合并到其中
几天前,我已经设置了我的开发环境(在装有Win 7的VM和域上的用户的VM上安装了delphi 2009),并安装了我的组件(jedi's,devExpress,ADS等)。 今天,我启动机器,打开d
开始对控件进行子分类的正确位置/时间是什么? 恢复原始窗口proc的正确时间是几点? 现在我在表单创建过程中子类化: procedure TForm1.FormCreate(Sender: TObje
有人可以给我一些有关如何登录访问的网页(使用任何网络浏览器)的指示吗?我应该建立一个全球代理....钩住网络....吗?我需要记录的只是页面地址,而不是其中包含的信息。 我正在使用Delphi。 谢谢
我创建了一个像 TMyClass = class(TObject) private FList1: TObjectList; FList2: TObjectList; public end;
我有一个BPG文件,我已对其进行修改以用作我们公司的自动构建服务器的make文件。为了使其正常工作,我必须进行更改 用途*用途 'unit1.pas'中的unit1 * unit1 'unit2.pa
我将Delphi 7代码迁移到了Delphi XE4。我在Delphi XE4的LoadFromStram方法中遇到错误,但对于Delphi 7来说也可以正常工作。 错误: First chance
我正在尝试学习一些新技巧,以便更好地组织我在 Delphi 中的单元中的一些源代码。 我注意到我访问的一些函数或方法似乎是类中的类,但是我还没有成功地在类中创建一个工作类,虽然它编译得很好,但在执行代
我有一个包含许多类的大单元,现在我想通过将某些类分成新的单元来重构该单元。 我不得不承认我缺乏使用Delphi内置IDE功能的经验。利用内置功能“查找|查找对类型的本地引用”并没有多大帮助,因为类方法
我是一名优秀的程序员,十分优秀!