2011-05-12 85 views
1

的。当我使用“TBrowseForFolder”德尔福XE与选项TBrowseForFolder选择行聚焦

object actBrowseCommonData: TBrowseForFolder 
    Category = 'Base' 
    Caption = 'Browse...' 
    DialogCaption = 'Browse for Common data path' 
    BrowseOptions = [bifUseNewUI] 
    BeforeExecute = actBrowseCommonDataBeforeExecute 
    OnAccept = actBrowseCommonDataAccept 
end 
代码

,事件BeforeExecute具有下面的代码:

begin 
    actBrowseProjectPath.Folder := eProjectPath.Text; // "C:\test\" 
end; 

大多数对话框不会聚焦所选路径,而只显示顶部的列表。有时候(随机?),尽管所选行是可见的。为什么不浏览文件夹显示选定的路径?

+0

哪个操作系统? - 我很确定XP不支持显示选定的路径。 – daven11 2011-05-12 10:54:31

+0

我在Microsoft Connect上找到了以下内容: “在下面的代码中使用BFFM_SETSELECTION和BIF_NEWDIALOGSTYLE时,在XP和Vista中选择该文件夹并滚动列表以使用户可以看到选定的文件夹,但在Windows 7中,列表不滚动以显示选定的文件夹“ https://connect.microsoft.com/VisualStudio/feedback/details/518103/bffm-setselection-does-not-work-with-shbrowseforfolder-on-windows-7 它可以相互关联或使我更接近解决方案吗? – Tool 2011-05-12 11:03:10

+0

------------ --- – Tool 2011-05-12 11:18:33

回答

3

这似乎与Microsoft Connect上的示例工作:

uses ShlObj; //BFFM_INITIALIZED... 

OnCallBack := actBrowseProjectPathCallback; 

procedure TSettingsDialogBase.actBrowseProjectPathCallback(
    Sender: TBrowseForFolder; Wnd: HWND; uMsg: Cardinal; lParam, lpData: Integer; 
    var Result: Integer); 
begin 
    inherited; 

    if uMsg = BFFM_INITIALIZED then 
    begin 
    SendMessage(Wnd, BFFM_SETSELECTION, 1, Integer(@Sender.Folder[1])); 
    Sleep(1000); 
    PostMessage(Wnd, BFFM_SETSELECTION, 1, Integer(@Sender.Folder[1])); 
    end; 
end; 

这给专注于所选择的文件夹 - 即使它不是在可视光区域之前,在树中。我的问题似乎解决了!如果有人看到这个问题 - 请回复!

下面是解决办法的OP有什么就讲:
http://connect.microsoft.com/VisualStudio/feedback/details/518103/bffm-setselection-does-not-work-with-shbrowseforfolder-on-windows-7#

我能找到一个解决办法。问题似乎是,当发生BFFM_INITIALIZED回调并发送BFFM_SETSELECTION消息时,必须在发送BFFM_SETSELECTION消息之前打开并初始化该树。换句话说,它看起来像缺陷是在树完全打开之前滚动代码正在执行,并且失败。

如果在回调中发送BFFM_SETSELECTION消息,树会打开,但选择不会滚动到。要让它滚动,你必须延迟发送第二个相同的BFFM_SETSELECTION消息。那么树会滚动到选定的文件夹。 BFFM_INITIALIZED回调中的第一条消息仍然必须发生以打开树,然后必须发送第二个延迟的消息并且它将起作用。有几种方法可以做到这一点。一种是在BFFM_INITIALIZED发生时设置一个标志,然后在之后继续发送BFFM_SETSELECTION给。或者你可以在你的代码中设置一个定时器来第二次触发信息,比如500到1000毫秒。

0

我意识到这是一个古老的线程,但良好的解决方案是无处可寻......

这为我工作,在C ...

INT CALLBACK BFFHookProc(HWND Dlg, UINT Msg, LPARAM Lparam, LPARAM Data) 
    { 
    switch(Msg) 
     { 
     case BFFM_INITIALIZED : 
      PostMessage(Dlg, BFFM_SETSELECTION, 1, Data); 
      return 0; 
     case BFFM_SELCHANGED : 
     Sleep(20); 
     default : 
     return 0; 
     } 
    } 

这是一个计时问题但它的确切性质是一个谜。使用PostMessage而不是SendMessage几乎可以工作......在BFFM_SELCHANGED中添加Sleep可以非常可靠地工作。