mirror of https://github.com/dahall/Vanara.git
BREAKING CHANGE: Fixed problems with STRRET and its use in IShellFolder::GetDisplayNameOf. #73
parent
42771630ad
commit
37b9f50288
|
@ -351,16 +351,57 @@ namespace Vanara.PInvoke
|
|||
object GetUIObjectOf(HWND hwndOwner, uint cidl, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] IntPtr[] apidl, in Guid riid, IntPtr rgfReserved = default);
|
||||
|
||||
/// <summary>Retrieves the display name for the specified file object or subfolder.</summary>
|
||||
/// <param name="pidl">PIDL that uniquely identifies the file object or subfolder relative to the parent folder.</param>
|
||||
/// <param name="pidl">
|
||||
/// <para>Type: <c>PCUITEMID_CHILD</c></para>
|
||||
/// <para>PIDL that uniquely identifies the file object or subfolder relative to the parent folder.</para>
|
||||
/// </param>
|
||||
/// <param name="uFlags">
|
||||
/// <para>Type: <c>SHGDNF</c></para>
|
||||
/// <para>
|
||||
/// Flags used to request the type of display name to return. For a list of possible values, see the SHGDNF enumerated type.
|
||||
/// </para>
|
||||
/// </param>
|
||||
/// <param name="pName">
|
||||
/// <para>
|
||||
/// When this method returns, contains the display name. The type of name returned in this structure can be the requested type,
|
||||
/// but the Shell folder might return a different type.
|
||||
/// </para>
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// When this method returns, contains a pointer to a STRRET structure in which to return the display name. The type of name
|
||||
/// returned in this structure can be the requested type, but the Shell folder might return a different type.
|
||||
/// <para>Type: <c>HRESULT</c></para>
|
||||
/// <para>If this method succeeds, it returns <c>S_OK</c>. Otherwise, it returns an <c>HRESULT</c> error code.</para>
|
||||
/// </returns>
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(STRRETMarshaler))]
|
||||
string GetDisplayNameOf([In] PIDL pidl, SHGDNF uFlags);
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Normally, pidl can refer only to items contained by the parent folder. The PIDL must be single-level and contain exactly one
|
||||
/// SHITEMID structure followed by a terminating zero. If you want to retrieve the display name of an item that is deeper than
|
||||
/// one level away from the parent folder, use SHBindToParent to bind with the item's immediate parent folder and then pass the
|
||||
/// item's single-level PIDL to <c>IShellFolder::GetDisplayNameOf</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Also, if the SHGDN_FORPARSING flag is set in uFlags and the SHGDN_INFOLDER flag is not set, pidl can refer to an object at
|
||||
/// any level below the parent folder in the namespace hierarchy. At one time, pidl could be a multilevel PIDL, relative to the
|
||||
/// parent folder, and could contain multiple SHITEMID structures. However, this is no longer supported and pidl should now
|
||||
/// refer only to a single child item.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The flags specified in uFlags are hints about the intended use of the name. They do not guarantee that IShellFolder will
|
||||
/// return the requested form of the name. If that form is not available, a different one might be returned. In particular,
|
||||
/// there is no guarantee that the name returned by the SHGDN_FORPARSING flag will be successfully parsed by
|
||||
/// IShellFolder::ParseDisplayName. There are also some combinations of flags that might cause the <c>GetDisplayNameOf</c>/
|
||||
/// <c>ParseDisplayName</c> round trip to not return the original identifier list. This occurrence is exceptional, but you
|
||||
/// should check to be sure.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <c>Note</c> The parsing name that is returned when uFlags has the SHGDN_FORPARSING flag set is not necessarily a normal text
|
||||
/// string. Virtual folders such as My Computer might return a string containing the folder object's GUID in the form
|
||||
/// "::{GUID}". Developers who implement <c>IShellFolder::GetDisplayNameOf</c> are encouraged to return parse names that are as
|
||||
/// close to the display names as possible, because the end user often needs to type or edit these names.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellfolder-getdisplaynameof
|
||||
// HRESULT GetDisplayNameOf( PCUITEMID_CHILD pidl, SHGDNF uFlags, STRRET *pName );
|
||||
void GetDisplayNameOf([In] PIDL pidl, SHGDNF uFlags, out STRRET pName); //[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(STRRETMarshaler))] out string pName);
|
||||
|
||||
/// <summary>Sets the display name of a file object or subfolder, changing the item identifier in the process.</summary>
|
||||
/// <param name="hwnd">A handle to the owner window of any dialog or message box that the client displays.</param>
|
||||
|
|
|
@ -152,9 +152,15 @@ namespace Vanara.PInvoke
|
|||
[FieldOffset(4)]
|
||||
public StrPtrAnsi cStr;
|
||||
|
||||
/// <summary>Returns a <see cref="System.String"/> that represents this instance.</summary>
|
||||
/// <returns>A <see cref="System.String"/> that represents this instance.</returns>
|
||||
public override string ToString() => (uType == STRRET_TYPE.STRRET_CSTR ? cStr : (uType == STRRET_TYPE.STRRET_WSTR ? pOleStr : (string)null)) ?? string.Empty;
|
||||
/// <summary>Performs an implicit conversion from <see cref="STRRET"/> to <see cref="System.String"/>.</summary>
|
||||
/// <param name="s">The <see cref="STRRET"/> instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator string(in STRRET s) =>
|
||||
ShlwApi.StrRetToBSTR(new PinnedObject(s), default, out var ret).Succeeded ? ret : null;
|
||||
|
||||
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
|
||||
/// <returns>A <see cref="string"/> that represents this instance.</returns>
|
||||
public override string ToString() => (string)this ?? "";
|
||||
}
|
||||
|
||||
internal class STRRETMarshaler : ICustomMarshaler
|
||||
|
@ -182,15 +188,8 @@ namespace Vanara.PInvoke
|
|||
return sr.MarshalToPtr(Marshal.AllocCoTaskMem, out var _);
|
||||
}
|
||||
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero) return null;
|
||||
var sr = pNativeData.ToStructure<STRRET>();
|
||||
var s = sr.ToString().Clone() as string;
|
||||
if (sr.uType == STRRET_TYPE.STRRET_WSTR)
|
||||
sr.pOleStr.Free();
|
||||
return s;
|
||||
}
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData) =>
|
||||
pNativeData != IntPtr.Zero && ShlwApi.StrRetToBSTR(pNativeData, default, out var ret).Succeeded ? ret : null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Vanara.PInvoke.Shell32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
|
@ -35,6 +37,22 @@ namespace Vanara.PInvoke.Tests
|
|||
//Assert.That(AssocGetDetailsOfPropKey(), Is.Zero);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SHGetDesktopFolderTest()
|
||||
{
|
||||
Assert.That(SHGetDesktopFolder(out var sf), ResultIs.Successful);
|
||||
var eo = sf.EnumObjects(HWND.NULL, SHCONTF.SHCONTF_NONFOLDERS);
|
||||
Assert.That(eo, Is.Not.Null);
|
||||
foreach (var sub in new Collections.IEnumFromNext<IntPtr>((out IntPtr p) => eo.Next(1, out p, out var f).Succeeded && f == 1, () => { try { eo.Reset(); } catch { } }))
|
||||
{
|
||||
STRRET name = default;
|
||||
Assert.That(() => sf.GetDisplayNameOf(sub, SHGDNF.SHGDN_NORMAL | SHGDNF.SHGDN_INFOLDER, out name), Throws.Nothing);
|
||||
TestContext.WriteLine(name);
|
||||
}
|
||||
Marshal.ReleaseComObject(eo);
|
||||
Marshal.ReleaseComObject(sf);
|
||||
}
|
||||
|
||||
/*
|
||||
AssocCreateForClasses
|
||||
AssocGetDetailsOfPropKey
|
||||
|
@ -136,7 +154,6 @@ namespace Vanara.PInvoke.Tests
|
|||
SHFreeNameMappings
|
||||
SHGetAttributesFromDataObject
|
||||
SHGetDataFromIDList
|
||||
SHGetDesktopFolder
|
||||
SHGetDiskFreeSpaceA
|
||||
SHGetDiskFreeSpaceEx
|
||||
SHGetDiskFreeSpaceW
|
||||
|
|
Loading…
Reference in New Issue