我正在使用以下代码调用TaskDialog。
[DllImport("ComCtl32", CharSet = CharSet.Unicode, PreserveSig = false)]
internal static extern void TaskDialogIndirect(
[In] ref TASKDIALOGCONFIG pTaskConfig,
[Out] out int pnButton,
[Out] out int pnRadioButton,
[Out] out bool pfVerificationFlagChecked);
但是,我得到异常“无法在DLL'ComCtl32'中找到名为'TaskDialogIndirect'的入口点。”
我带了this code。我使用的是Windows 7 x64(RC)。
我做错了什么?
答案 0 :(得分:8)
除此之外的任何内容都不是vista功能
更新: 这个探针与并排程序集有关:这些函数仅存在于comctl32.dll版本6中,但出于兼容性原因,除非另有说明,否则Vista将加载早期版本。大多数人(包括我)采取的方法是使用清单。这已被证明是棘手的,并且可能不是正确的解决方案,特别是如果您正在编写的是库:您不一定要强制整个应用程序使用通用控件6.
正确的解决方案是在调用其中一个仅限Vista的API时推送new activation上下文。激活上下文将使用正确版本的comctl32.dll,而单独保留应用程序的其余部分,并且不需要清单。
幸运的是,这很容易。已经存在的一些完整代码MS Knowledgebase。文章中的代码(KB 830033)就是这样做的。
替代托管API: Vista的TaskDialog& amp;的完整包装器。 TaskDialogIndirect可以在这里找到:
http://code.msdn.microsoft.com/WindowsAPICodePack
对于WPF,请使用以下内容:
下载后从http://code.msdn.microsoft.com/VistaBridge下载'VistaBridge示例库',打开项目然后构建它(如果要查看所有代码,请检查\ Library或\ Interop文件夹中的文件)。您现在可以从VistaBridge \ bin \ debug \中获取DLL,并在项目中添加对它的引用,并且必须为每个不同的VistaBridge模块添加using语句。例如:
使用Microsoft.SDK.Samples.VistaBridge.Interop或.Library或.Properties或.Services - 根据您的需要。
VistaBridge项目包括用于许多其他Vista功能的API(例如TaskDialog,Vista OpenFile和SaveFile对话框,当然还有Aero Glass Effects)来试用这些功能,运行VistaBridge项目。
答案 1 :(得分:3)
使用Task Dialog需要Windows Common Controls DLL(ComCtl32.dll)的第6版!出于兼容性原因,默认情况下应用程序不绑定到此版本。绑定到版本6的一种方法是将清单文件放在可执行文件旁边(名为YourAppName.exe.manifest),其中包含以下内容:
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
如果您不想拥有额外的独立文件,则此清单也可以作为Win32资源嵌入您的可执行文件中(名称为RT_MANIFEST,ID设置为1)。如果您将清单文件关联到项目的属性中,Visual Studio可以为您完成此工作。
答案 2 :(得分:0)
基于almog.ori的答案(有一些孤立的链接),我对链接的代码进行了少量更改,大约几天后我感到困惑:
MS Knowledgebase为(Archiv)提供了帮助,并为我提供了完整的代码:
using System.Runtime.InteropServices;
using System;
using System.Security;
using System.Security.Permissions;
using System.Collections;
using System.IO;
using System.Text;
namespace MyOfficeNetAddin
{
/// <devdoc>
/// This class is intended to use with the C# 'using' statement in
/// to activate an activation context for turning on visual theming at
/// the beginning of a scope, and have it automatically deactivated
/// when the scope is exited.
/// </devdoc>
[SuppressUnmanagedCodeSecurity]
internal class EnableThemingInScope : IDisposable
{
// Private data
private IntPtr cookie; // changed cookie from uint to IntPtr
private static ACTCTX enableThemingActivationContext;
private static IntPtr hActCtx;
private static bool contextCreationSucceeded = false;
public EnableThemingInScope(bool enable)
{
if (enable)
{
if (EnsureActivateContextCreated())
{
if (!ActivateActCtx(hActCtx, out cookie))
{
// Be sure cookie always zero if activation failed
cookie = IntPtr.Zero;
}
}
}
}
// Finalizer removed, that could cause Exceptions
// ~EnableThemingInScope()
// {
// Dispose(false);
// }
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (cookie != IntPtr.Zero)
{
if (DeactivateActCtx(0, cookie))
{
// deactivation succeeded...
cookie = IntPtr.Zero;
}
}
}
private bool EnsureActivateContextCreated()
{
lock (typeof(EnableThemingInScope))
{
if (!contextCreationSucceeded)
{
// Pull manifest from the .NET Framework install
// directory
string assemblyLoc = null;
FileIOPermission fiop = new FileIOPermission(PermissionState.None);
fiop.AllFiles = FileIOPermissionAccess.PathDiscovery;
fiop.Assert();
try
{
assemblyLoc = typeof(Object).Assembly.Location;
}
finally
{
CodeAccessPermission.RevertAssert();
}
string manifestLoc = null;
string installDir = null;
if (assemblyLoc != null)
{
installDir = Path.GetDirectoryName(assemblyLoc);
const string manifestName = "XPThemes.manifest";
manifestLoc = Path.Combine(installDir, manifestName);
}
if (manifestLoc != null && installDir != null)
{
enableThemingActivationContext = new ACTCTX();
enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX));
enableThemingActivationContext.lpSource = manifestLoc;
// Set the lpAssemblyDirectory to the install
// directory to prevent Win32 Side by Side from
// looking for comctl32 in the application
// directory, which could cause a bogus dll to be
// placed there and open a security hole.
enableThemingActivationContext.lpAssemblyDirectory = installDir;
enableThemingActivationContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
// Note this will fail gracefully if file specified
// by manifestLoc doesn't exist.
hActCtx = CreateActCtx(ref enableThemingActivationContext);
contextCreationSucceeded = (hActCtx != new IntPtr(-1));
}
}
// If we return false, we'll try again on the next call into
// EnsureActivateContextCreated(), which is fine.
return contextCreationSucceeded;
}
}
// All the pinvoke goo...
[DllImport("Kernel32.dll")]
private extern static IntPtr CreateActCtx(ref ACTCTX actctx);
// changed from uint to IntPtr according to
// https://www.pinvoke.net/default.aspx/kernel32.ActiveActCtx
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie);
// changed from uint to IntPtr according to
// https://www.pinvoke.net/default.aspx/kernel32.DeactivateActCtx
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie);
private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;
private struct ACTCTX
{
public int cbSize;
public uint dwFlags;
public string lpSource;
public ushort wProcessorArchitecture;
public ushort wLangId;
public string lpAssemblyDirectory;
public string lpResourceName;
public string lpApplicationName;
}
}
}
然后我以这种方式使用它:
using (new EnableThemingInScope(true))
{
// The call all this mucking about is here for.
VistaUnsafeNativeMethods.TaskDialogIndirect(ref config, out result, out radioButtonResult, out verificationFlagChecked);
}
在WPF Task Dialog Wrapper on GitHub中提供的TaskDialogInterop.cs
中
有关SEHException
的终结器中可能的EnableThemingInScope
的更多信息,请参见此Question on SO