我正在使用 Shell Lightweight Utility Functions中的 SHAutoComplete() 功能 库在模式对话框中为编辑字段启用路径自动完成. 按下Esc键时,对话框应该关闭,但仅当自动完成未激活时才会关闭. 如何检查
SHAutoComplete()
功能
库在模式对话框中为编辑字段启用路径自动完成.
按下Esc键时,对话框应该关闭,但仅当自动完成未激活时才会关闭.
如何检查焦点编辑控件当前是否显示完成列表?
编辑:
我在Windows XP 64上使用Delphi 2009. David发布的代码
procedure TMyForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_ESCAPE then ModalResult := mrCancel; end;
对我不起作用 – 对话框关闭了.
我试过几个系统,结果很奇怪:>在使用Windows XP 64的PC上,当列表被删除时,对话框将关闭
>在VMware虚拟机中的Windows XP Pro上,对话框也会关闭
但
>在我的Windows 7笔记本电脑上,对话框没有关闭
>在VMware虚拟机中的Windows 2000 Pro上,对话框不会关闭
由于这是如此不稳定,我选择编写一个小组件,即使操作系统不提供它也会强制执行正确的行为.
该组件可以像这样使用:
procedure TForm2.FormCreate(Sender: TObject); const SHACF_FILESYS_DIRS = $00000020; begin SHAutoComplete(Edit1.Handle, SHACF_FILESYS_DIRS or SHACF_USETAB); fAutoSuggestDropdownChecker := TAutoSuggestDropdownChecker.Create(Self); end; procedure TForm2.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_ESCAPE then begin if not fAutoSuggestDropdownChecker.DroppedDown then ModalResult := mrCancel; end; end;
但重要的是取消按钮没有设置取消属性.
组件本身通过挂钩到应用程序消息处理并使用当前线程的窗口枚举来检查具有“Auto-Suggest Dropdown”类名称的可见窗口.如果存在且可见,则自动完成列表将被删除.
unit uAutoSuggestDropdownCheck; interface uses Windows, Classes, Messages, Forms; type TAutoSuggestDropdownChecker = class(TComponent) private fDroppedDown: boolean; fSaveMessageEvent: TMessageEvent; procedure AppOnMessage(var AMsg: TMsg; var AHandled: Boolean); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property DroppedDown: boolean read fDroppedDown; end; implementation //////////////////////////////////////////////////////////////////////////////// function EnumThreadWindowsProc(AWnd: HWND; AParam: LPARAM): BOOL; stdcall; var WndClassName: string; FoundAndVisiblePtr: PInteger; begin SetLength(WndClassName, 1024); GetClassName(AWnd, PChar(WndClassName), Length(WndClassName)); WndClassName := PChar(WndClassName); if WndClassName = 'Auto-Suggest Dropdown' then begin FoundAndVisiblePtr := PInteger(AParam); FoundAndVisiblePtr^ := Ord(IsWindowVisible(AWnd)); Result := False; end else Result := True; end; function IsAutoSuggestDropdownVisible: boolean; var FoundAndVisible: integer; begin FoundAndVisible := 0; EnumThreadWindows(GetCurrentThreadId, @EnumThreadWindowsProc, LParam(@FoundAndVisible)); Result := FoundAndVisible > 0; end; //////////////////////////////////////////////////////////////////////////////// // TAutoSuggestDropdownChecker //////////////////////////////////////////////////////////////////////////////// constructor TAutoSuggestDropdownChecker.Create(AOwner: TComponent); begin inherited Create(AOwner); fSaveMessageEvent := Application.OnMessage; Application.OnMessage := AppOnMessage; end; destructor TAutoSuggestDropdownChecker.Destroy; begin if (TMethod(fSaveMessageEvent).Code = TMethod(Application.OnMessage).Code) and (TMethod(fSaveMessageEvent).Data = TMethod(Application.OnMessage).Data) then begin Application.OnMessage := fSaveMessageEvent; end; fSaveMessageEvent := nil; inherited; end; procedure TAutoSuggestDropdownChecker.AppOnMessage(var AMsg: TMsg; var AHandled: Boolean); begin if ((AMsg.message >= WM_KEYFIRST) and (AMsg.message <= WM_KEYLAST)) or ((AMsg.message >= WM_MOUSEFIRST) and (AMsg.message <= WM_MOUSELAST)) or (AMsg.message = WM_CANCELMODE) then fDroppedDown := IsAutoSuggestDropdownVisible end; end.
这里发布的代码只是概念验证,但可以作为那些在同一问题上挣扎的人的起点.