Getting items from an MFC list control from .NET
I have a C# application that needs to retrieve a bunch of information from another window that was written in C++ using MFC. The C# app is a plugin to a product containing this other window so they are both running within the same process开发者_运维百科.
This other window contains a number of fields that I have successfully gotten the strings from by calling:
[DllImport( "user32.dll", SetLastError = true )]
public static extern uint GetDlgItemText( IntPtr hDlg, int nIDDlgItem, [Out] StringBuilder lpString, int nMaxCount );
But it also contains 2 list controls that may contain a number of rows of data, each with a number of columns.
How do I fetch this data?
Is there another function in user32.dll I should be using?
Can you get a handle to the list control using:
[DllImport( "User32", SetLastError = true )]
public static extern IntPtr GetDlgItem( IntPtr hwndParent, int ItemId );
and then somehow cast it into a .NET control that you can get the rows and columns from?
This is actually surprisingly difficult. The LVM_* messages that you would use to get the data out of the listview controls are considered user-defined messages, and their parameters cannot be marshaled across process boundaries using standard Win32 calls.
There are ways to accomplish this -- one is to inject code into the remote process (using, say, CreateRemoteThread) and then have that remote thread perform the operation and write the results into shared memory -- but they are non-trivial and I don't have good example code for you.
Edit: OK, if you're int the same process you ought to be able to make this work. Here's some code (pulled from this article) that uses the LVM_* messages to extract the selected text from a list control. This ought to get you going in the right direction. There's also an article here that has similar code. He couldn't get it to work due to crossing process boundaries, but it might work for you.
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;
}
精彩评论