Solved

copy files from virtual folders

Posted on 2004-09-01
37
515 Views
Last Modified: 2013-11-15
Hello,

I need a hint how to copy files from virtual folders.
My digital camera is connected as virtual folder in 'my computer' -> 'control panel' -> 'scanners and cameras'.
It is not difficult to gain access to that camera by using iterative IShellFolder commands. GetDisplayName generates a full path like:
'::{GUID of my computer}\::{GUID of control panel}\::{GUID of scanners and camera\devid:{GUID of camera}\0003:\0003\Root\Ext0\DCIM\100Ricoh\picture1234.jpg'
SHOperation fails when passing this path.
Any help is appreciated.
Thanks in advance!

Sebastian
0
Comment
Question by:sieppl
  • 16
  • 11
  • 4
  • +1
37 Comments
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11958526
http://www.torry.net/pages.php?id=507

look at MultiTWAIN v.0.5
0
 

Author Comment

by:sieppl
ID: 11958683
My program is trayed, catches WM_DEVICECHANGE and if a camera is found, the images should be copied from the cam to a file system folder. This folder can be selected by SHBrowseForFolder. The copy-process should be cancelable. Thus I like to you use SHFIleOperation. When I drag the images from the camera folder and drop them to a file system folder the ordinary windows file copy process starts. How can I realize that?
My program is compatible to any camera. Gaining access is no problem, I just need a helping hand for the copy method.
This is urgent (project for a costumer). If anybody can help me with the realization I'd like to honor that with 500 points additonally.
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11960383
SHFileOperation returns zero if successful or nonzero if an error occurs. After it fails, try to see the error code after that with GetLastError API...
0
 

Author Comment

by:sieppl
ID: 11960953
Hello Ivanov,

the DWORD value of the error code is 1026. Couldn't find anything about that on MSDN. But Windows displays an error-message: 'failure reading from source or volume'. (Sorry, for the bad translation) That is the standard message if SHFileOperation fails when you remove the source before.
To makes things clear: We are talking about digital photo cameras. When the user connects them to the computer I'd like my program to copy all pictures in a bunch to disk. Are you sure TWAIN is here the best way to solve that?
Has nobody before implemented an interface to digital cameras to acquire images?
 
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11962071
0
 

Author Comment

by:sieppl
ID: 11962321
Thank you, I know how to use MSDN. :O)
As I meantioned before the returned error code is 1026. SHFileOperation cannot handle such paths. How about using IContextMenu to transfer the files to clipboard?
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11965866
The result will be the same I guess...
0
 

Author Comment

by:sieppl
ID: 11966498
no, that works.
PLEASE CLOSE THAT TOPIC AND REFUND POINTS.
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11967326
How does the path show in the Explorer addressbar?
Have you tried using the SHGDN_FORADDRESSBAR flag?

Check the last entry in this search of posts by Jim Kueneman:
(Subject: Re: getting name/path of a PIDL)
http://216.101.185.148/scripts/isapi.dll/execute?SearchFor=TPIDLManager+Kueneman


0
 

Author Comment

by:sieppl
ID: 11967694
no chance, I've tried all of them. Even Windows Explorer won't show the full paths to any files on virtual folders. Why? Because they are virtual. :) It makes no sense to use them.
I'll give 1000 points for that excellent person posts code which copies pictures from a camera virtual folder to the file system by using SHFileOperation. :)
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11967999
Without having the same brand of camera, I doubt you are going to get anyone to give you a full solution.
Why don't you show some of your code, as well, because, you never know, you may be doing something incorrectly.
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11968007
I'd also like to know what camera you have, too.
0
 

Author Comment

by:sieppl
ID: 11969200
Hi Eddie,

I'm currently testing with a Ricoh Caplio G3, tomorrow I'll get a Canon.
When you right click pictures on the camera and select 'copy' you won't find any CF_HDROP values in the clipboard. Very Interesting. But Windows can handle that file transfer as usual. So I decided to use IContextMenu.
Sorry my code has changed a lot, since I've tried to reach my goals by the 'full path method'.
I have no problem posting my current routine. The PasteCameraFiles function is under construction. Maybe it helps somebody else..
I'm glad that this stuff works fine. Here's the link that inspired me using the IContextMenu:
http://netez.com/2xExplorer/shellFAQ/bas_manage.html#idman_vitro
(ADVANCED: Managing virtual reality)

function TImportUtils.RecursiveSearchCamera(PFolder: IShellFolder):boolean;
var
  Allocator: IMalloc;
  PEnumList: IEnumIDList;
  NumIDs: ulong;
  PSubFolder: IShellFolder;
  PIDL: PItemIDList;
  StrRet: TStrRet;
  Path: string;
  PConMenu: IContextMenu;
  Command: TCMInvokeCommandInfo;
  APIDL: array of PItemIDList;
  count: Integer;

  function PasteCameraFiles: boolean;
  var
    Allocator: IMalloc;
    PDesktop, PSubFolder: IShellFolder;
    PIDL: PItemIDList;
    OleString: PWideChar;
    iEaten, iAttributes: cardinal;
    PConMenu: IContextMenu;
  begin
    Result := False;
    Path := FEdit.Text;
    if SHGetMalloc(Allocator) = NOERROR then
    begin
      if SHGetDesktopFolder(PDesktop) = S_OK then
      begin
        if Length(Path) = 2 then
          Path := Path + '\'
        else
          Path := GetParentDirectory(Path);
        OleString := StringToOLEStr(Path);
        iAttributes := 0;
        if PDesktop.ParseDisplayName(0, nil, OleString,
                                     iEaten, PIDL, iAttributes) = S_OK then
        begin
          if PDesktop.BindToObject(PIDL,nil,IID_IShellFolder,PSubfolder) = S_OK then
          begin
             OleString := StringToOLEStr(GetLastDirectory(FEdit.Text));
             iAttributes := 0;
             if PSubFolder.ParseDisplayName(0, nil, OleString,
                                     iEaten, PIDL, iAttributes) = S_OK then
             begin
               if OleInitialize(nil) = S_OK or S_FALSE then
               begin
                if PSubFolder.GetUIObjectOf(0,1,PIDL,IID_IContextMenu,nil,PConMenu) = S_OK then
                begin
                  FillChar(Command,sizeof(Command),#0);
                  Command.cbSize:= sizeof(Command);
                  Command.lpVerb := MakeIntResource('paste');
                  if PConMenu.InvokeCommand(Command) = S_OK then
                    Result := True;
                end;
              end;
              OleUnInitialize;
             end;
          Allocator.Free(PIDL);
          end;
        end;
      end;
    end;
  end;


begin
  Result := False;
  if SHGetMalloc(Allocator) = NOERROR then
  begin
    if PFolder.EnumObjects(0,SHCONTF_FOLDERS or
                          SHCONTF_NONFOLDERS,PEnumList) = S_OK then
    begin
      while (PEnumList.Next(1,PIDL,NumIDs) <> S_FALSE) do
      begin
        PFolder.GetDisplayNameOf(PIDL,SHGDN_INFOLDER or SHGDN_FORPARSING, StrRet);
        if (PFolder.BindToObject(PIDL,nil,IID_IShellFolder,PSubFolder) = S_OK) then
          RecursiveSearchCamera(PSubFolder);
        FillChar(StrRet, SizeOf(StrRet), 0);
        PSubFolder.GetDisplayNameOf(PIDL,SHGDN_FORPARSING, StrRet);
        if  Uppercase(MyExtractFileExt(StrRet.pOleStr)) = '.JPG' then
        begin
          SetLength(APIDL,length(APIDL)+1);
          APIDL[high(APIDL)] := PIDL;
        end else
          Allocator.Free(PIDL);
      end;
     if length(APIDL) > 0 then
     begin
       if OleInitialize(nil) = S_OK or S_FALSE then
       begin
         if PSubFolder.GetUIObjectOf(0,length(APIDL),APIDL[0],IID_IContextMenu,nil,PConMenu) = S_OK then
            begin
              FillChar(Command,sizeof(Command),#0);
              Command.cbSize:= sizeof(Command);
              Command.lpVerb := MakeIntResource('copy');
              if PConMenu.InvokeCommand(Command) = S_OK then
                if PasteCameraFiles then
                  Result := True;
            end;
       OleUnInitialize;
       end;
       for count := 0 to length(APIDL) -1 do
         Allocator.Free(APIDL[count]);
     end;
    end;
  end;
end;
0
 

Author Comment

by:sieppl
ID: 11969222
The brand of the camera you copying from doesn't matter. Important is that you have a virtual folder. I think you have a virtual folder when the camera model comes with WIA-drivers..
There is a great WIA-interface to get access to such cameras. check it out on MSDN..
It's a pity that I didn't find any translation of WIA libraries to Delphi. When you try to google for WIA you'll find nothing helpful.
0
 

Author Comment

by:sieppl
ID: 11970884
I'll have to move that RecursiveSearchCamera call downwards to avoid execution of recursion with *.jpg files.
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11972501
From what I read in the MSDN docs, you can AUTOMATE the WIA Aquisition so have you tried that instead of working
with the Shell? You can import the TypeLib in Delphi.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 26

Expert Comment

by:EddieShipman
ID: 11972585
0
 

Author Comment

by:sieppl
ID: 11972618
no, I have not. sure, using the WIA would be the best solution. But I have a deadline for completion of the code. Importing and translating the typeLib would take a lot of time. Furthermore you find nearly nothing about WIA usage in the internet.

btw: Do you have an idea how to get an IContextMenu of the plain area inside a directory? You need a PIDL to get an IContextMenu, but the plain area has none ?!
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11972663
[quote]Importing and translating the typeLib would take a lot of time[/quote]
It took me about 5 minutes to download the WIAAUT.DLL register it and import
the type lib, what are you talking about?

There is lots of examples on MSDN on using WIA, you just have to translate
from VB or VBS...;-)

No, sorry, I don't do context menus.
0
 

Author Comment

by:sieppl
ID: 11972809
I have no experience in importing type libs. So it would take a lot of time for ME :)
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11974816
Very easy:
First, download the SDK and extract the WIAAUT.DLL to the Wndows/System32 dir. Then open DOS Prompt
and register like this:

regsvr32 c:\windows\system32\wiaaut.dll

Project->Import Type Library, Select "Microsoft Windows Image Aquisition  Library v2.0 (Version 1.0)"
and click Install. It will prompt for a package to install into, you can use the default User package(dcluser.dpk).
Compile the package, click install and away you go...

E.

BTW, there are a couple VB examples in the SDK zip file.
0
 

Author Comment

by:sieppl
ID: 11975104
Hi Eddie!

Thanks a lot! Due to my rare time I'll have a look on WIA when my project is finished.
I will implement a WIA interface for the future use of cameras. The current solution is not very satisfying at all. :)
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11976621
I just purchased a Minolta Dimage Z1 for my wife, maybe it is WIA compliant. If it is, then I
will be able to work on a solution for you.
0
 

Author Comment

by:sieppl
ID: 11976830
That would be pretty cool. The WIA architecture is quite interesting. I'am wondering why you cannot find any piece of delphi-code on the web.
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 11976847
I would think that mainly because WIA is XP/2K only. Borland and Dejphi-Jedi have been very slow to
convert API's, especially if they are as limited as WIA. I've been looking for a conversion of IImgCtx
interface forever.
0
 
LVL 26

Expert Comment

by:EddieShipman
ID: 12001107
My Minolta is not WIA compliant. However, I will try to find the header and convert it.
0
 
LVL 33

Expert Comment

by:Slick812
ID: 12002164
hello sieppl , , I have not worked with virtual folders to any great extent, so I am reluctant to comment,, , but you seem to want to try and copy and paste the picture files of this virtual folder, here is some code that I have used to delete files from the Recycle bin (virtual , I beleive)

        ZeroMemory(@CmInfo, SizeOf(CmInfo));
        with CmInfo do
          begin
          cbSize:= SizeOf(CMINVOKECOMMANDINFO);
          fMask:= CMIC_MASK_FLAG_NO_UI; //Zero
          hwnd:= Application.Handle;
          lpVerb:= 'delete';
          //lpParameters:= nil;
         // lpDirectory:= nil;
          nShow:= SW_SHOWDEFAULT;
         // dwHotKey:= 0;
         // hIcon:= 0;
          end;

        OleCheck(ContextMenu.InvokeCommand(CmInfo));

I do not have time now to try a copy and paste. . .

and you ask
"how to get an IContextMenu of the plain area inside a directory?"

I can not really get what you mean?  plain area, this has no meaning to me, as the plain area has no code representation, it's just drawn on the screen as plain (I guess blank) area. . . anyway, I can only guess that you mean the virtual folder, you do not need to get a "Blank" or "Plain" area item from a vitual folder, I would beleive you would use the PIDL  of that virtual folder (or any folder), not any "Item" in that folder, for a paste operation, however for a copy operation you might want to use a folder "Item"

Although I have not done it, I would think to try the IDragDrop interface for the IShellFolder  virtual folder. . . .
0
 

Author Comment

by:sieppl
ID: 12004629
@Eddie: a converted header would be great! a good base to start from for me.. :)

@slick: thanks for your code. As I mentioned before I use IContextMenu to manage file operations on virtual folders. I call IContextMenu::InvokeCommand which is similar to your 'direct way' to call this command. I have to work on PIDLs, IContextMenu is fine for that.

yes, you are right, I've meant the 'blank area'. First I thought it would be tricky to paste files from the clipboard to volumes. When you right click on Volume C you wont't see any 'paste' command until there are files in the clipboard.(under windows xp) Following silly me thought I have to paste the files inside volume C to the blank area. When you right click the blank area you'll always see 'paste' either grey or black. (depends on clipboard). Self-made problems are great aren't they?? :o)
0
 
LVL 26

Accepted Solution

by:
EddieShipman earned 50 total points
ID: 12006347
I just found something that may be interesting to you:
"Accessing Kernel-Mode Drivers for Still Image Devices"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/still/hh/still/WIA_drv_basic_3ce1f660-0d58-43c1-97fa-22334fe4ac3d.xml.asp
0
 
LVL 33

Assisted Solution

by:Slick812
Slick812 earned 50 total points
ID: 12022870
I could not get the  ContextMenu.InvokeCommand(CmInfo) to work in a normal disk folder with the 'copy' verb, it would work with the 'delete' verb, so I'm not sure if, or how you would get that to work.

I was looking and did find some info about IshellFolder, and it said that file transfers were not done with the context menu interface (which makes sense), but they were done with the IDataObject inteface, although it did not give any code on how to do that. .
here is some code that you might consider, I do not have time now to work on it and beat it and bang it, so that it will work, this is not working code, just an idea

var
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;


IShFolder.GetUIObjectOf(Application.Handle, 1, pFileIDList,
               IID_IDataObject, nil, DataObj));

with FormatEtc do
       begin
       cfFormat := CFSTR_FILEDESCRIPTOR; // I think this is the right format ?
       ptd      := nil;
       dwAspect := DVASPECT_CONTENT;
       lindex   := -1;
       tymed    := TYMED_HGLOBAL; // TYMED_ISTREAM
       end;

sResult := DataObj.GetData(FormatEtc, StgMedium);

if the GetData supports the HGLOBAL then the StgMedium.hGlobal should have the vitual file in it, if the software
for the virtual folder expects large file DATA chunks, it may need to do a ISTREAM  transfer and have the StgMedium.pstm
as an IStream with the Data in it

I could not get the

IShFolder.GetUIObjectOf(Application.Handle, 1, pFileIDList,
               IID_IDataObject, nil, DataObj));

to compile, There is no value for the IID_IDataObject constant in shlobj.pas, I looked in some old C code header files
but they did not have it either, like I said got to much to do now, but you may can search and find some code example somewhere to help you.
I did a search at EE but it got 1 hit for  IID_IDataObject  and it was C code and it was worthless

good luck
0
 

Author Comment

by:sieppl
ID: 12024206
Hi Slick!

Misuse of IContextMenu to Copy files is dirty, but works fine.
I'll have a closer look to IDataObject when my project is finished. Good idea to try that anyway!
A Delphi-WIA interface would probably the best solution to manage such devices.
0
 

Author Comment

by:sieppl
ID: 13341683
Since my solution posted above was the last one worked for me I like to refund the points.
If possible I'd like to give 50 points each to Slick812 and EddieShipman for their efforts.
0
 

Author Comment

by:sieppl
ID: 15477248
point splitting is done. thanks for cleaning up.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
The article will include the best Data Recovery Tools along with their Features, Capabilities, and their Download Links. Hope you’ll enjoy it and will choose the one as required by you.
This tutorial will walk an individual through the steps necessary to install and configure the Windows Server Backup Utility. Directly connect an external storage device such as a USB drive, or CD\DVD burner: If the device is a USB drive, ensure i…
This tutorial will walk an individual through the process of installing the necessary services and then configuring a Windows Server 2012 system as an iSCSI target. To install the necessary roles, go to Server Manager, and select Add Roles and Featu…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now