SHMultiFileProperties的第一个参数是一个自定义的IDataObject。我个人不是很懂怎么去构造这个IDataObject,虽然参数说明里的那些数据我都有,但就是不知道怎么用。求一个SHMultiFileProperties的调用例子,特别是有IDataObject的使用。

解决方案 »

  1.   

    .net已经有IDataObject的实现,只要正确使用就可以了。其实答案很容易找,Google一下前几条就有,参考以下代码:
            [DllImport("shell32.dll", CharSet = CharSet.Auto)]
            private static extern IntPtr SHMultiFileProperties(IDataObject pdtobj, int dwFlags);
            [DllImport("shell32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr ILCreateFromPath(string path);
            [DllImport("shell32.dll", CharSet = CharSet.None)]
            public static extern void ILFree(IntPtr pidl);
            [DllImport("shell32.dll", CharSet = CharSet.None)]
            public static extern int ILGetSize(IntPtr pidl);        private void button2_Click(object sender, EventArgs e)
            {            var data = new DataObject();
                var files = new StringCollection() { @"c:\temp\2010_12_21 9_11_21.jpg", @"c:\temp\2010_12_21 9_09_31.jpg" };
                data.SetFileDropList(files);
                data.SetData("Preferred DropEffect", true, new MemoryStream(new byte[] { 5, 0, 0, 0 }));
                data.SetData("Shell IDList Array", true, CreateShellIDList(files));
                Clipboard.SetDataObject(data, true);            SHMultiFileProperties(data, 0);
            }        private static MemoryStream CreateShellIDList(StringCollection filenames)
            {
                // first convert all files into pidls list
                int pos = 0;
                byte[][] pidls = new byte[filenames.Count][];
                foreach (var filename in filenames)
                {
                    // Get pidl based on name
                    IntPtr pidl = ILCreateFromPath(filename);
                    int pidlSize = ILGetSize(pidl);
                    // Copy over to our managed array
                    pidls[pos] = new byte[pidlSize];
                    Marshal.Copy(pidl, pidls[pos++], 0, pidlSize);
                    ILFree(pidl);
                }            // Determine where in CIDL we will start pumping PIDLs
                int pidlOffset = 4 * (filenames.Count + 2);
                // Start the CIDL stream
                var memStream = new MemoryStream();
                var sw = new BinaryWriter(memStream);
                // Initialize CIDL witha count of files
                sw.Write(filenames.Count);
                // Calcualte and write relative offsets of every pidl starting with root
                sw.Write(pidlOffset);
                pidlOffset += 4; // root is 4 bytes
                foreach (var pidl in pidls)
                {
                    sw.Write(pidlOffset);
                    pidlOffset += pidl.Length;
                }            // Write the root pidl (0) followed by all pidls
                sw.Write(0);
                foreach (var pidl in pidls) sw.Write(pidl);
                // stream now contains the CIDL
                return memStream;
            }此代码在Win7下通过测试,但据原作者说在XP下无法正常工作,我没有环境没办法测试,这里有一篇文章可能会有帮助,楼主自己去发现吧。
    http://www.zaoxue.com/article/tech-31614.htm