2011-06-08 53 views
4

我有一个C#应用程序,需要从使用MFC编写的另一个使用C++编写的窗口中检索一堆信息。 C#应用程序是包含此其他窗口的产品的插件,因此它们都在相同的进程中运行。从.NET中获取MFC列表控件中的项目

这等窗口包含一个数字,我已经成功地从得到的字符串字段致电:

[DllImport("user32.dll", SetLastError = true)] 
     public static extern uint GetDlgItemText(IntPtr hDlg, int nIDDlgItem, [Out] StringBuilder lpString, int nMaxCount); 

但它也包含2个可能包含若干个数据行的列表控件,每一个列数。

如何获取此数据?

我应该使用user32.dll中是否有另一个函数?

你可以得到一个句柄使用列表控件:

[DllImport("User32", SetLastError = true)] 
     public static extern IntPtr GetDlgItem(IntPtr hwndParent, int ItemId); 

然后以某种方式将它转换成.NET控件,你可以从行和列?

回答

3

这实际上非常困难。您将用于从列表视图控件中获取数据的LVM_ *消息被视为用户定义的消息,并且它们的参数不能使用标准Win32调用跨进程边界封送。

方法来完成此 - 一个是将代码注入远程进程(使用,比方说,CreateRemoteThread的),然后有一个远程线程执行的操作,并将结果写入到共享存储器中 - 但它们是不平凡的,我没有很好的例子代码给你。

编辑:好的,如果你是同一个过程你应该能够做到这一点。以下是一些代码(从this article开始),它使用LVM_ *消息从列表控件中提取选定的文本。这应该让你朝着正确的方向前进。还有一篇文章here有类似的代码。由于跨越流程边界,他无法工作,但它可能适用于您。

private string GetSelectedItem() 
{ 
    string item = null; 

    IntPtr pStringBuffer = Marshal.AllocHGlobal(2048); 
    IntPtr pItemBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LVITEM))); 

    int selectedItemIndex = SendMessage(base.Handle, LVM_GETNEXTITEM, (IntPtr)(-1), (IntPtr)LVNI_SELECTED).ToInt32(); 
    if (selectedItemIndex > -1) 
    { 
     LVITEM lvi = new LVITEM(); 
     lvi.cchTextMax = 1024; 
     lvi.pszText = pStringBuffer; 
     Marshal.StructureToPtr(lvi, pItemBuffer, false); 
     int numChars = SendMessage(base.Handle, LVM_GETITEMTEXT, (IntPtr)selectedItemIndex, pItemBuffer).ToInt32(); 
     if (numChars > 0) 
     { 
      item = Marshal.PtrToStringUni(lvi.pszText, numChars); 
     } 
    } 

    Marshal.FreeHGlobal(pStringBuffer); 
    Marshal.FreeHGlobal(pItemBuffer); 

    return item; 
} 

struct LVITEM 
{ 
    public int mask; 
    public int iItem; 
    public int iSubItem; 
    public int state; 
    public int stateMask; 
    public IntPtr pszText; 
    public int cchTextMax; 
    public int iImage; 
    public IntPtr lParam; 
    public int iIndent; 
    public int iGroupId; 
    int cColumns; // tile view columns 
    public IntPtr puColumns; 
    public IntPtr piColFmt; 
    public int iGroup; 

} 
+0

我在同一个过程中运行。我开发了一个现有产品的插件。除了使用我相信的Win32调用之外,我只是没有对该窗口的任何编程访问权限。如果他们将在这种情况下工作,如何使用LVM_ *消息的例子将非常感谢! – TerryB 2011-06-08 23:48:37

+0

哦,很酷!根据此信息编辑回答。 – mwigdahl 2011-06-09 16:25:19