通过处理NativeWindow中的WM_GETOBJECT返回IOleCommandTarget [英] Return an IOleCommandTarget from processing WM_GETOBJECT in a NativeWindow
问题描述
我试图从面板控件句柄中检索IOleCommandTarget引用,以便可以在其上调用IOleCommandTarget.Exec().
I am trying to retrieve an IOleCommandTarget reference from a panel control handle, so that I can call IOleCommandTarget.Exec() on it.
NativeMethods.IOleCommandTarget target = null;
if (GetObjectFromHandle<NativeMethods.IOleCommandTarget>(panel.Handle, out target))
{
Guid guidCmdGroup = commandID.Guid;
handled = (target.Exec(ref guidCmdGroup, commandID.ID, 0, null, 0) == NativeMethods.S_OK);
}
private static bool GetObjectFromHandle<T>(IntPtr hwnd, out T value)
{
Guid guid = typeof(T).GUID;
object obj = null;
var hr = NativeMethods.AccessibleObjectFromWindow(hwnd, 0, ref guid, ref obj);
if (hr == NativeMethods.S_OK)
{
value = (T)obj;
return true;
}
value = default(T);
return false;
}
在我的NativeMethods.cs中:
In my NativeMethods.cs:
[ComImport]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("B722BCCB-4E68-101B-A2BC-00AA00404770")]
public interface IOleCommandTarget
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int QueryStatus(ref Guid pguidCmdGroup, int cCmds, [In, Out] NativeMethods.OLECMD prgCmds, [In, Out] IntPtr pCmdText);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, [In, MarshalAs(UnmanagedType.LPArray)] object[] pvaIn, int pvaOut);
}
[DllImport("oleacc.dll")]
public static extern int AccessibleObjectFromWindow(
IntPtr hwnd,
uint id,
ref Guid iid,
[In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);
为了能够返回IOleCommandTarget引用,我创建了一个实现NativeWindow和IOleCommandTarget的CommandTargetWindow类,并且我重写WndProc来拦截AccessibleObjectFromWindow()发送的WM_GETOBJECT消息:
To be able to return an IOleCommandTarget reference, I created a CommandTargetWindow class that implements NativeWindow and IOleCommandTarget, and I am overriding WndProc to intercept the WM_GETOBJECT message that AccessibleObjectFromWindow() sends:
public sealed class CommandTargetWindow : NativeWindow,
NativeMethods.IOleCommandTarget,
IDisposable
{
private IWin32Window _parent;
public CommandTargetWindow(IWin32Window parent)
{
_parent = parent;
base.AssignHandle(parent.Handle);
}
[PermissionSetAttribute(SecurityAction.Demand, Unrestricted = true)]
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == NativeMethods.WM_GETOBJECT)
{
//How do I pass back an IOleCommandTarget through the message?
}
base.WndProc(ref m);
}
}
问题是,如上面的评论中所述,如何通过消息传递回IOleCommandTarget?
The question is, as in the comment above, how do I pass back an IOleCommandTarget through the message?
出于自动化目的,我们通过实现接口IRawElementProviderSimple(而不是IOleCommandTarget)并使用已定义的静态方法AutomationInteropProvider.ReturnRawElementProvider()来执行类似的操作:
We do something similar elsewhere for automation purposes, by implementing interface IRawElementProviderSimple (instead of IOleCommandTarget) and using the defined static method AutomationInteropProvider.ReturnRawElementProvider():
[PermissionSetAttribute(SecurityAction.Demand, Unrestricted = true)]
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if ((m.Msg == NativeMethods.WM_GETOBJECT) && (m.LParam.ToInt32() == AutomationInteropProvider.RootObjectId))
{
m.Result = AutomationInteropProvider.ReturnRawElementProvider(
Handle, m.WParam, m.LParam, (IRawElementProviderSimple)this);
return;
}
base.WndProc(ref m);
}
有什么想法吗?
推荐答案
事实证明,我需要使用在NativeMethods.cs中定义为COM的COM方法LresultFromObject
It turns out I needed to use COM method LresultFromObject which I defined in NativeMethods.cs as
[DllImport("oleacc.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr LresultFromObject(ref Guid refiid, IntPtr wParam, IntPtr pAcc);
现在在我的WndProc中,我调用LresultFromObject以在m.Result中返回IOleCommandTarget句柄:
Now in my WndProc, I call LresultFromObject to return the IOleCommandTarget handle in m.Result:
[PermissionSetAttribute(SecurityAction.Demand, Unrestricted = true)]
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == (int)NativeMethods.WindowMessage.GETOBJECT)
{
if (m.LParam.ToInt32() == AutomationInteropProvider.RootObjectId)
{
m.Result = AutomationInteropProvider.ReturnRawElementProvider(
Handle, m.WParam, m.LParam, (IRawElementProviderSimple)this);
return;
}
else if (m.LParam == (IntPtr)NativeMethods.OBJID_NATIVEOM)
{
IntPtr handle = Marshal.GetComInterfaceForObject(this, typeof(NativeMethods.IOleCommandTarget));
Guid unknownGuid = typeof(NativeMethods.IUnknown).GUID;
m.Result = NativeMethods.LresultFromObject(ref unknownGuid, m.WParam, handle);
return;
}
}
base.WndProc(ref m);
}
这篇关于通过处理NativeWindow中的WM_GETOBJECT返回IOleCommandTarget的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!