全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2604
推到 Plurk!
推到 Facebook!

使用SelectDirectory有辦法控制出現位置嗎?

答題得分者是:wameng
darnell
版主


發表:25
回覆:103
積分:145
註冊:2003-03-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-10-24 15:56:49 IP:218.161.xxx.xxx 未訂閱
var strDir : String;//預設的選擇目錄 請問使用SelectDirectory('挑選目錄', '', strDir)這種選擇目錄的方法,每次選擇視窗都會出現在右下角,有辦法移到其他位置嗎? ------------------------ 創造其實就是...... 轉個彎看世界......
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-10-24 16:13:02 IP:61.229.xxx.xxx 未訂閱
hi,darnell: 1.我呼叫SelectDirectory,視窗會出現在中央,並沒有像你說的在右下角的位置. 2.如果你要讓跳出來的視窗,可以在其他地方出現,那麼,你可能要自己寫自己的SelectDirectory function. source code在Delphi目錄下的\source\vcl\filectrl.pas檔裡.你可以發現原來的程式只是動態產生一個TSelectDirDlg的畫面而已.你可以自加再上那個form的Top及Left等屬性,也能改變視窗出現的位置.試試看
darnell
版主


發表:25
回覆:103
積分:145
註冊:2003-03-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-10-24 23:31:34 IP:218.161.xxx.xxx 未訂閱
謝謝你的回答... SelectDirectory一共有兩種產生的樣式... 其中SelectDirectory(Directory,Options,HelpCtx):Boolean;所產生的對話框的確在正中央,可是我是需要用另外一種可以選取網路芳鄰的目錄 SelectDirectory('挑選目錄', '', strDir)此種所產生的對話框我也有想過你說的加入屬性來改變位置,可是第二種的原始碼並不像第一種方式可以輕易改變,也或許我不太了解可以加在哪裡,請再指點謝謝~  
function SelectDirectory(const Caption: string; const Root: WideString;
  var Directory: string): Boolean;
var
  WindowList: Pointer;
  BrowseInfo: TBrowseInfo;
  Buffer: PChar;
  OldErrorMode: Cardinal;
  RootItemIDList, ItemIDList: PItemIDList;
  ShellMalloc: IMalloc;
  IDesktopFolder: IShellFolder;
  Eaten, Flags: LongWord;
begin
  Result := False;
  if not DirectoryExists(Directory) then
    Directory := '';
  FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
  if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
  begin
    Buffer := ShellMalloc.Alloc(MAX_PATH);
    try
      RootItemIDList := nil;
      if Root <> '' then
      begin
        SHGetDesktopFolder(IDesktopFolder);
        IDesktopFolder.ParseDisplayName(Application.Handle, nil,
          POleStr(Root), Eaten, RootItemIDList, Flags);
      end;
      with BrowseInfo do
      begin
        hwndOwner := Application.Handle;
        pidlRoot := RootItemIDList;
        pszDisplayName := Buffer;
        lpszTitle := PChar(Caption);
        ulFlags := BIF_RETURNONLYFSDIRS;
        if Directory <> '' then
        begin
          lpfn := SelectDirCB;
          lParam := Integer(PChar(Directory));
        end;
      end;
      WindowList := DisableTaskWindows(0);
      OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
      try
        ItemIDList := ShBrowseForFolder(BrowseInfo);
      finally
        SetErrorMode(OldErrorMode);
        EnableTaskWindows(WindowList);
      end;
      Result :=  ItemIDList <> nil;
      if Result then
      begin
        ShGetPathFromIDList(ItemIDList, Buffer);
        ShellMalloc.Free(ItemIDList);
        Directory := Buffer;
      end;
    finally
      ShellMalloc.Free(Buffer);
    end;
  end;
end; 
------------------------ 創造其實就是...... 轉個彎看世界......
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-10-25 10:03:21 IP:61.31.xxx.xxx 未訂閱
好吧!這是您要的程式碼。    其中我已修改視窗會直接顯示正中央。    
Function SelectDirectory(const Caption: string; const Root: String;
                         out Directory: String): Boolean;
  function CBBrowseForFolder(Wnd: HWND; uMsg: UINT;
                             lParam, lpData: LPARAM): Integer stdcall;
  Var
    WRect : TRect;
  begin
    Result:= 0;
    case uMsg of
      BFFM_INITIALIZED:
        begin
          WRect.Left := 0;WRect.Top := 0;
          if Windows.GetClientRect(Wnd,WRect) then
          begin
            WRect.Left :=(GetSystemMetrics(SM_CXSCREEN) - WRect.Right) div 2;
            WRect.Top  :=(GetSystemMetrics(SM_CYSCREEN) - WRect.Bottom) div 2;
          end;
          SetWindowPos(Wnd, 0,WRect.Left,WRect.Top, 0, 0,
                       SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
        end;
    end;
  end;
var
  WindowList: Pointer;
  BrowseInfo: TBrowseInfo;
  Buffer: PChar;
  RootItemIDList, ItemIDList: PItemIDList;
  ShellMalloc: IMalloc;
  IDesktopFolder: IShellFolder;
  Eaten, Flags: LongWord;
begin
  Result := False;
  Directory := '';
  FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
  if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
  begin
    Buffer := ShellMalloc.Alloc(MAX_PATH);
    try
      RootItemIDList := nil;
      if Root <> '' then
      begin
        SHGetDesktopFolder(IDesktopFolder);
        IDesktopFolder.ParseDisplayName(Application.Handle, nil,
          POleStr(Root), Eaten, RootItemIDList, Flags);
      end;
      with BrowseInfo do
      begin
        hwndOwner := Application.Handle;
        pidlRoot := RootItemIDList;
        pszDisplayName := Buffer;
        lpszTitle := PChar(Caption);
        ulFlags := BIF_RETURNONLYFSDIRS;
        lpfn := @CBBrowseForFolder;
      end;
      WindowList := DisableTaskWindows(0);
      try
        ItemIDList := ShBrowseForFolder(BrowseInfo);
      finally
        EnableTaskWindows(WindowList);
      end;
      Result :=  ItemIDList <> nil;
      if Result then
      begin
        ShGetPathFromIDList(ItemIDList, Buffer);
        ShellMalloc.Free(ItemIDList);
        Directory := Buffer;
      end;
    finally
      ShellMalloc.Free(Buffer);
    end;
  end;
end;
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-10-25 10:20:18 IP:61.229.xxx.xxx 未訂閱
耶,被wameng搶先了 好吧,這裡有解說可以參考 http://delphi.about.com/library/weekly/aa122803a.htm 重點在設定TBrowseInfo.lpfn指到一個callback的function
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-10-25 10:27:54 IP:61.31.xxx.xxx 未訂閱
to change.jian 版主大大!    Sorry.... 被我多此一舉了,給搶先了。 想必對大大而言,這個問題是輕而易舉的。    恭喜大大,差一分就破百了! 恭喜!恭喜!< >< >
darnell
版主


發表:25
回覆:103
積分:145
註冊:2003-03-04

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-10-25 11:15:56 IP:61.223.xxx.xxx 未訂閱
引言:
Sorry....
被我多此一舉了,給搶先了。
想必對大大而言,這個問題是輕而易舉的。 恭喜大大,差一分就破百了!
恭喜!恭喜!

真的非常感謝兩位
編輯記錄
darnell 重新編輯於 2008-10-19 00:51:04, 註解 無‧
系統時間:2024-05-02 8:06:38
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!