Friday, 6 September 2013

C# - Sending Windows API messages to ListView in Windows 7

C# - Sending Windows API messages to ListView in Windows 7

Below is some code which works beautifully on Windows XP, but does not
work on Windows 7. I'd like to know how to fix this for Windows 7, or
perhaps a different approach...
I'm developing a C# application where I would like to launch a generic
OpenFileDialog browser and have a particular file in the list
pre-selected. As far as I can tell, the OpenFileDialog itself does not
support selecting a particular file in the list, so I took to the Windows
API to send messages directly to the handle of the ListView.
In UISpy, the ListView in the OpenFileDialog window is identified as
ClassName=SysListView32 in Windows XP. In Windows 7 however this list is
identified by ClassName=DUIListView. I cannot seem to find any
documentation for the DUI library.
[DllImport("User32.dll")]
public static extern IntPtr FindWindow(String lpClassName, String
lpWindowName);
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr
wParam, IntPtr lParam);
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct LV_ITEM
{
public uint mask;
public int iItem;
public int iSubItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public IntPtr lParam;
}
//get a handle to the ListView object
// findList is my own function which drills down through the UI tree
for me
AutomationElement list = findList("Title of containing window", "Name of
List in UISpy");
int handle_list = list.Current.NativeWindowHandle;
//some constants right out of CommCtrl.h
const int LVM_FIRST = 0x1000;
const int LVM_SETITEMSTATE = LVM_FIRST + 43;
const int LVIS_FOCUSED = 0x0001;
const int LVIS_SELECTED = 0x0002;
//build a LV_ITEM object to send in the API message
LV_ITEM lvi = new LV_ITEM();
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
//pick the index number of the file to select in the ListView
int wParam = 8;
IntPtr ptrLvi = Marshal.AllocHGlobal(Marshal.SizeOf(lvi));
Marshal.StructureToPtr(lvi, ptrLvi, false);
//send the message to the ListView!!
SendMessage(new IntPtr(handle_list), LVM_SETITEMSTATE, new IntPtr(wParam),
ptrLvi);
Does anyone know the correct way to interface with the new DUIListView
object? Does anyone know a different approach I can take to accomplish
this task? Thank you so much.

No comments:

Post a Comment