Delphi中的SelectDirectory对话框如何动态验证突出显示的文件夹?

mjn*_*mjn 4 delphi directory dialog

有没有办法根据验证规则启用/禁用SelectDirectory对话框中的"确定"按钮,例如:

  • 如果突出显示的文件夹的名称是"config",则启用"确定"按钮
  • 如果突出显示的文件夹包含名为".project"的文件和名为".settings"的文件夹,则启用"确定"按钮

Rob*_*edy 7

如果使用ShBrowseForFolderAPI函数,则可以执行此操作.我认为Delphi附带了一个SelectDirectory包装该函数的版本,尽管包装器可能无法为您需要的内容提供足够的访问权限.您需要包括一个回调函数用于lpfn与此签名的参数:

function BrowseCallbackProc(Wnd: HWnd; uMsg: UInt; lParam, lpData: LParam): Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)

当选择更改时,对话框将调用您提供的函数bffm_SelChanged作为uMsg参数.第三个参数是表示当前选择的PIDL,因此您可能需要调用ShGetPathFromIDList以确定字符串名称.您可以通过将消息发送回Wnd参数中对话框的窗口句柄来控制"确定"按钮.例如:

SendMessage(Wnd, bffm_EnableOK, 0, 0); // disable the button
SendMessage(Wnd, bffm_EnableOK, 0, 1); // enable the button
Run Code Online (Sandbox Code Playgroud)

在禁用该选项以进行无效选择后,请不要忘记重新启用该按钮以进行良好选择.

如果有效选择的标准是目录应包含具有特定名称的文件,请确保包含该bif_BrowseIncludeFiles标志,以便人们可以看到哪些文件存在.


RRU*_*RUZ 5

只是为了补充@Rob的优秀答案.

看到这段代码.

uses  ShlObj;

function BrowseCallbackProc(hwnd: HWND; MessageID: UINT; lParam: LPARAM; lpData: LPARAM): Integer; stdcall;
var
    DirName:  array[0..MAX_PATH] of Char;
    pIDL   :  pItemIDList;
begin
  case  MessageID    of
    BFFM_INITIALIZED:SendMessage(hwnd, BFFM_SETSELECTION, 1, lpData);
    BFFM_SELCHANGED :begin
                        pIDL := Pointer(lParam);
                        if  Assigned(PIDL) then
                        begin
                          SHGetPathFromIDList(pIDL, DirName);
                          if DirectoryExists(DirName) then
                           if (ExtractFileName(DirName)='config') then    //you can add more validations here
                            SendMessage(hwnd, BFFM_ENABLEOK, 0, 1) //enable the ok button
                           else
                            SendMessage(hwnd, BFFM_ENABLEOK, 0, 0) //disable the ok button
                          else
                          SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
                        end
                        else
                          SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
                     end;
  end;

  Result := 0;
end;

function SelectFolderDialogExt(Handle: Integer; var SelectedFolder: string): Boolean;
var
  ItemIDList: PItemIDList;
  JtemIDList: PItemIDList;
  DialogInfo: TBrowseInfo;
  Path: PAnsiChar;
begin
  Result := False;
  Path   := StrAlloc(MAX_PATH);
  SHGetSpecialFolderLocation(Handle, CSIDL_DRIVES, JtemIDList);
  with DialogInfo do
  begin
    pidlRoot      := JtemIDList;
    //ulFlags       := BIF_RETURNONLYFSDIRS;     //only select directories
    hwndOwner     := GetActiveWindow;
    SHGetSpecialFolderLocation(hwndOwner, CSIDL_DRIVES, JtemIDList);
    pszDisplayName := StrAlloc(MAX_PATH);
    lpszTitle       := PChar('Select a folder');
    lpfn            := @BrowseCallbackProc;
    lParam            := LongInt(PChar(SelectedFolder));
  end;

  ItemIDList := SHBrowseForFolder(DialogInfo);

  if (ItemIDList <> nil) then
    if SHGetPathFromIDList(ItemIDList, Path) then
    begin
      SelectedFolder := Path;
      Result         := True;
    end;
end;
Run Code Online (Sandbox Code Playgroud)

执行

if SelectFolderDialogExt(Handle, SelectedDir) then
  ShowMessage(SelectedDir);
Run Code Online (Sandbox Code Playgroud)