Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to programmatically display the "share folder" dialog 1

Status
Not open for further replies.

alexd007

Programmer
Jul 2, 2003
4
CA
Hi !

I need to programmatically launch the "share folder" dialog for a given folder (for example C:\MyApp\Data\ )

Anybody knows how I could achieve this ? I run Delphi 5, and the client's machine can be any flavour of Windows 9x, or NT.

Thanks !
 
Hi ! Thanks for the link !

Unfortunately, I already found such info elsewhere on the web, and it is not what I'm looking for.

What I want is to display the "share folder" dialog (the one that windows shows when you right-click a folder and choose "share"). This lets more control to the user, they can choose the name and permissions, and sysadmins are not lost (they know well this dialog).

The link you provided shows how to programmatically share a folder, but that's not what I need, I only need to display the windows dialog that allows to share a folder.

Anyone else want to try ?

Thanks :)

 
I had a feeling you were going to say that!

I've got pretty close to an answer so I'm gonna post up with what I've found so far:
Code:
uses ShellAPI;
...
procedure PropertiesDialog(filename:String);
var
  Info: ShellExecuteInfo;
begin
  FillChar(Info, SizeOf(Info), 0);
  with Info do
  begin
    cbSize := SizeOf(Info);
    lpFile := PChar(filename);
    lpVerb := 'properties';
    fMask  := SEE_MASK_INVOKEIDLIST;
  end;
  ShellExecuteEx(@Info);
end;
usage:
Code:
PropertiesDialog('C:\temp\');

This code opens the Properties Dialog for any file or folder you care to specify.

However, this still doesn't show the "Sharing" tab your after. I've done some digging and what you need to do is this:
- a call to the WaitForInputIdle() API function waits until the process has fully loaded.
- you must then locate the dialog box and gets the window handle of the tab control within it (you can use FindWindow for this).
- you then send both TCM_SETCURFOCUS and TCM_SETCURSEL messages using the SendMessage API call to select the desired tab.

I've tried doing this process but haven't been able to get it to work so anyone else's input would be much appreciated.

Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
That's great, I love it !

If someone find how to do the last step, cool, but if nobody does, no problem, you've already done a great job !!

I'll code it as-is in my application. After all, if I can pop the dialog, the users will only have to switch to the "sharing" tab, which is not that much.

Thanks a lot !!!
 
I've done it!!! Woo-hoo!!!

The only annoying thing is that I've had to wait 5 seconds after calling the dialog before changing the tab so that the dialog is there before the tab change is attempted. I tried using WaitForInputIdle as you can see (it's commented out) but the process identifier returned from the PropertiesDialog function only seems to return 0 and not a meaningful value with which WaitForInputIdle could make use of.
Code:
procedure TForm1.Button16Click(Sender: TObject);

  function PropertiesDialog(AFilename: String): Cardinal;
  var
    Info: ShellExecuteInfo;
    hDialog: hWnd;
  begin
    FillChar(Info, SizeOf(Info), 0);
    with Info do
    begin
      cbSize := SizeOf(Info);
      lpFile := PChar(AFilename);
      lpVerb := 'properties';
      fMask  := SEE_MASK_INVOKEIDLIST;
    end;
    ShellExecuteEx(@Info);
    Result := Info.hProcess;
  end;

  function GetFolderName(AFilename: String): String;
  var
    lastBackSlashPos: Integer;
    secondFromLastBSPos: Integer;
    counter: Integer;
    filename: String;
  begin
    lastBackSlashPos := 0;
    filename := ExcludeTrailingBackslash(AFilename);
    for counter := Length(filename) downto 1 do
      if filename[counter] = '\' then
      begin
        lastBackSlashPos := counter;
        Break;
      end;
    Result := Copy(filename, lastBackSlashPos + 1, Length(filename) - lastBackSlashPos);
  end;

  procedure SetCurSel(AParentHandle, AChildHandle: hWND; AValue: integer);
  var
    Msg: TMessage;
    NM: TNMHdr;
  begin
    NM.hwndFrom := AChildHandle;
    NM.idFrom := AParentHandle;
    NM.code := TCN_SELCHANGING;
    Msg.Msg := WM_NOTIFY;
    Msg.WParam := AParentHandle;
    Msg.LParam := integer(@NM);
    Dispatch(Msg);
    SendMessage(AChildHandle,TCM_SETCURSEL,AValue,0);
    NM.code := TCN_SELCHANGE;
    Dispatch(Msg);
  end;

var
  OpenDialog: TOpenDialog;
  DialogName: String;
  hDialog: hWnd;
  hTabControl: hWnd;
  hProcess: Cardinal;
begin
  OpenDialog := TOpenDialog.Create(nil);
  try
    if OpenDialog.Execute then
    begin
      hProcess := PropertiesDialog(ExtractFileDir(OpenDialog.FileName));
      Sleep(5000);
      //WaitForInputIdle(hProcess, INFINITE);
      DialogName := GetFolderName(ExtractFileDir(OpenDialog.Filename)) + ' Properties';
      hDialog := FindWindow('#32770', PChar(DialogName));
      if hDialog > 0 then
      begin
        hTabControl := FindWindowEx(hDialog, 0, 'SysTabControl32', nil);
        if hTabControl > 0 then
          SetCurSel(hDialog, hTabControl, 1);
      end;
    end;
  finally
    OpenDialog.Free;
  end;
end;


Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
Interesting stuff Clive.
This seems to be a partial answer to my earier questions on PIF's which were never resolved.
The next question is. Is it possible to change items on the accessed tab programatically? perhaps via lpParameters?

Just one other point I need to declare the 'ShellExecuteInfo' variable as 'TShellExecuteInfo' a cut and paste of your example gives a declaration error.

Steve.

 
Steve,

Thanks for pointing out that problem - must have lost the "T" in transit! I'll look into changing items on the tab in the next few days - I'll see what I can come up with.

Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
There seems to be quite a major glitch in my code cos although it successfully changes the tab to "Sharing" it does not show the associated page. It still shows the "General" page contents. I presume it's because we've underhandedly altered the control without the event handling noticing so the page is not changed.

Aside from that, in order to change items on the accessed tab you have to locate the window of the control and send a message to it. I came up with the following code to check the Read-only checkbox in the properties dialog:
Code:
      hDialog := FindWindow('#32770', PChar(DialogName));
      if hDialog > 0 then
      begin
        hGeneral := FindWindowEx(hDialog, 0, '#32770', nil);
        if hGeneral > 0 then
        begin
          hCheckBox := FindWindowEx(hGeneral, 0, 'Button', '&Read-only');
          if hCheckBox > 0 then
            SendMessage(hCheckBox, BM_SETCHECK, BST_CHECKED, 0);
        end;
      end;
You do need to know the class name of the control you are looking for (in this case: Button) and I've specified the text of the control (it's possible to do it without this parameter but only because "Read-only" is the first button control in the General window). Then you send a BM_SETCHECK message to tell the control you are trying to set it and the BST_CHECKED to tell the control you want it to be checked rather than unchecked/grayed.

You really have to get a program called WinDowse if you want to do this kind of stuff cos it tells you all the information that you need to be able to access windows and controls in this way. It is available here: (click "download free" at the bottom of the page)

A good tutorial of this whole process that I found very useful is here:

P.S.
The ShellExecuteInfo type seems to work for me (in Delphi 6) whether I add the T prefix or not.


Clive [infinity]
Ex nihilo, nihil fit (Out of nothing, nothing comes)
 
Yes you would expect it to work without the T Prefix as doing an F1 on 'Shellexecuteinfo' brings up the API help on that Item. I am using D3 here. It must be fixed by D6. I will try it with D4 later.
Steve.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top