Code clean up on Mainform and VirtuallistView.

This commit is contained in:
adelikat 2013-12-20 22:05:56 +00:00
parent cc23c120c0
commit 1c44d21562
2 changed files with 827 additions and 512 deletions

View File

@ -1,105 +1,105 @@
using System; using System;
using System.Windows.Forms;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Drawing; using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk namespace BizHawk.Client.EmuHawk
{ {
#region win32interop #region win32interop
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct LVDISPINFO { internal struct LvDispInfo
public NMHDR hdr; {
public LVITEM item; public NmHdr Hdr;
public LvItem Item;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct NMHDR { internal struct NmHdr
public int hwndFrom; {
public int idFrom; public int HwndFrom;
public int code; public int IdFrom;
} public int Code;
[StructLayout(LayoutKind.Sequential)]
internal struct NMITEMACTIVATE {
NMHDR hdr;
int iItem;
int iSubItem;
uint uNewState;
uint uOldState;
uint uChanged;
POINT ptAction;
uint lParam;
uint uKeyFlags;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT {
public int left, top, right, bottom;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct NMCUSTOMDRAWINFO { internal struct NmItemActivate
public NMHDR hdr; {
public NmHdr Hdr;
public int Item;
public int SubItem;
public uint NewState;
public uint OldState;
public uint uChanged;
public POINT Action;
public uint lParam;
public uint KeyFlags;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int Top;
public int Left;
public int Bottom;
public int Right;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NmCustomDrawInfo
{
public NmHdr Hdr;
public uint dwDrawStage; public uint dwDrawStage;
public IntPtr hdc; public IntPtr Hdc;
public RECT rc; public RECT Rect;
public int dwItemSpec; public int dwItemSpec;
public uint uItemState; public uint ItemState;
public int lItemlParam; public int lItemlParam;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct NMLVCUSTOMDRAW { internal struct NmLvCustomDraw
public NMCUSTOMDRAWINFO nmcd; {
public int clrText; public NmCustomDrawInfo Nmcd;
public int clrTextBk; public int ClearText;
public int iSubItem; public int ClearTextBackground;
public int SubItem;
} }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct LVITEM { internal struct LvItem
public uint mask; {
public int iItem; public uint Mask;
public int iSubItem; public int Item;
public uint state; public int SubItem;
public uint stateMask; public uint State;
public IntPtr pszText; public uint StateMask;
public IntPtr PszText;
public int cchTextMax; public int cchTextMax;
public int iImage; public int Image;
public IntPtr lParam; public IntPtr lParam;
//#if (_WIN32_IE >= 0x0300) public int Indent;
public int iIndent;
//#endif
//#if (_WIN32_WINNT >= 0x501)
//public int iGroupId;
//public uint cColumns;
//public IntPtr puColumns;
//#endif
} }
[FlagsAttribute] [FlagsAttribute]
enum CUSTOMDRAWRETURNFLAGS { internal enum CustomDrawReturnFlags
{
CDRF_DODEFAULT = 0x00000000, CDRF_DODEFAULT = 0x00000000,
CDRF_NEWFONT = 0x00000002, CDRF_NEWFONT = 0x00000002,
CDRF_SKIPDEFAULT = 0x00000004, CDRF_SKIPDEFAULT = 0x00000004,
CDRF_NOTIFYPOSTPAINT = 0x00000010, CDRF_NOTIFYPOSTPAINT = 0x00000010,
CDRF_NOTIFYITEMDRAW = 0x00000020, CDRF_NOTIFYITEMDRAW = 0x00000020,
//#if (_WIN32_IE >= 0x0400) CDRF_NOTIFYSUBITEMDRAW = 0x00000020,
CDRF_NOTIFYSUBITEMDRAW = 0x00000020,//[sic]
//#endif
CDRF_NOTIFYPOSTERASE = 0x00000040, CDRF_NOTIFYPOSTERASE = 0x00000040,
} }
[FlagsAttribute] [FlagsAttribute]
enum CUSTOMDRAWDRAWSTAGEFLAGS { internal enum CustomDrawDrawStageFlags
{
CDDS_PREPAINT = 0x00000001, CDDS_PREPAINT = 0x00000001,
CDDS_POSTPAINT = 0x00000002, CDDS_POSTPAINT = 0x00000002,
CDDS_PREERASE = 0x00000003, CDDS_PREERASE = 0x00000003,
@ -111,17 +111,16 @@ namespace BizHawk.Client.EmuHawk
CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT), CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT),
CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE), CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE),
CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE), CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE),
//#if (_WIN32_IE >= 0x0400)
CDDS_SUBITEM = 0x00020000, CDDS_SUBITEM = 0x00020000,
CDDS_SUBITEMPREPAINT = (CDDS_SUBITEM | CDDS_ITEMPREPAINT), CDDS_SUBITEMPREPAINT = (CDDS_SUBITEM | CDDS_ITEMPREPAINT),
CDDS_SUBITEMPOSTPAINT = (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT), CDDS_SUBITEMPOSTPAINT = (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT),
CDDS_SUBITEMPREERASE = (CDDS_SUBITEM | CDDS_ITEMPREERASE), CDDS_SUBITEMPREERASE = (CDDS_SUBITEM | CDDS_ITEMPREERASE),
CDDS_SUBITEMPOSTERASE = (CDDS_SUBITEM | CDDS_ITEMPOSTERASE), CDDS_SUBITEMPOSTERASE = (CDDS_SUBITEM | CDDS_ITEMPOSTERASE),
//#endif
} }
[FlagsAttribute] [FlagsAttribute]
enum LVHITTESTFLAGS { internal enum LvHitTestFlags
{
LVHT_NOWHERE = 0x0001, LVHT_NOWHERE = 0x0001,
LVHT_ONITEMICON = 0x0002, LVHT_ONITEMICON = 0x0002,
LVHT_ONITEMLABEL = 0x0004, LVHT_ONITEMLABEL = 0x0004,
@ -135,22 +134,25 @@ namespace BizHawk.Client.EmuHawk
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct POINT { internal struct POINT
public int x; {
public int y; public int X;
public int Y;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal class LVHITTESTINFO { internal class LvHitTestInfo
public POINT pt; {
public uint flags; public POINT Point;
public int iItem; public uint Flags;
public int iSubItem; public int Item;
public int SubItem;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct NMLISTVIEW { internal struct NMLISTVIEW
public NMHDR hdr; {
public NmHdr hdr;
public int iItem; public int iItem;
public int iSubItem; public int iSubItem;
public uint uNewState; public uint uNewState;
@ -161,7 +163,8 @@ namespace BizHawk.Client.EmuHawk
} }
internal enum ListViewItemMask : short { internal enum ListViewItemMask : short
{
LVIF_TEXT = 0x0001, LVIF_TEXT = 0x0001,
LVIF_IMAGE = 0x0002, LVIF_IMAGE = 0x0002,
LVIF_PARAM = 0x0004, LVIF_PARAM = 0x0004,
@ -173,7 +176,8 @@ namespace BizHawk.Client.EmuHawk
LVIF_COLUMNS = 0x0200 LVIF_COLUMNS = 0x0200
} }
internal enum LVNI { internal enum LvNi
{
ALL = 0x0000, ALL = 0x0000,
FOCUSED = 0x0001, FOCUSED = 0x0001,
SELECTED = 0x0002, SELECTED = 0x0002,
@ -186,7 +190,8 @@ namespace BizHawk.Client.EmuHawk
TORIGHT = 0x0800 TORIGHT = 0x0800
} }
internal enum ListViewMessages { internal enum ListViewMessages
{
LVM_FIRST = 0x1000, LVM_FIRST = 0x1000,
LVM_GETITEMCOUNT = (LVM_FIRST + 4), LVM_GETITEMCOUNT = (LVM_FIRST + 4),
LVM_SETCALLBACKMASK = (LVM_FIRST + 11), LVM_SETCALLBACKMASK = (LVM_FIRST + 11),
@ -199,7 +204,8 @@ namespace BizHawk.Client.EmuHawk
LVM_GETSUBITEMRECT = (LVM_FIRST + 56) LVM_GETSUBITEMRECT = (LVM_FIRST + 56)
} }
internal enum ListViewStyles : short { internal enum ListViewStyles : short
{
LVS_OWNERDATA = 0x1000, LVS_OWNERDATA = 0x1000,
LVS_SORTASCENDING = 0x0010, LVS_SORTASCENDING = 0x0010,
LVS_SORTDESCENDING = 0x0020, LVS_SORTDESCENDING = 0x0020,
@ -207,12 +213,15 @@ namespace BizHawk.Client.EmuHawk
LVS_NOLABELWRAP = 0x0080, LVS_NOLABELWRAP = 0x0080,
LVS_AUTOARRANGE = 0x0100 LVS_AUTOARRANGE = 0x0100
} }
internal enum ListViewStylesICF : uint {
internal enum ListViewStylesICF : uint
{
LVSICF_NOINVALIDATEALL = 0x00000001, LVSICF_NOINVALIDATEALL = 0x00000001,
LVSICF_NOSCROLL = 0x00000002 LVSICF_NOSCROLL = 0x00000002
} }
internal enum WindowsMessage : uint { internal enum WindowsMessage : uint
{
WM_ERASEBKGND = 0x0014, WM_ERASEBKGND = 0x0014,
WM_SCROLL = 0x115, WM_SCROLL = 0x115,
WM_LBUTTONDOWN = 0x0201, WM_LBUTTONDOWN = 0x0201,
@ -227,28 +236,31 @@ namespace BizHawk.Client.EmuHawk
WM_REFLECT = WM_USER + 0x1c00 WM_REFLECT = WM_USER + 0x1c00
} }
internal enum Notices : int { internal enum Notices
{
NM_FIRST = 0, NM_FIRST = 0,
NM_CUSTOMDRAW = NM_FIRST - 12, NM_CUSTOMDRAW = NM_FIRST - 12,
NM_CLICK = NM_FIRST - 2, NM_CLICK = NM_FIRST - 2,
NM_DBLCLICK = NM_FIRST - 3, NM_DBLCLICK = NM_FIRST - 3,
} }
internal enum ListViewNotices : int { internal enum ListViewNotices
{
LVN_FIRST = (0 - 100), LVN_FIRST = (0 - 100),
LVN_LAST = (0 - 199), LVN_LAST = (0 - 199),
LVN_BEGINDRAG = (int)LVN_FIRST - 9, LVN_BEGINDRAG = LVN_FIRST - 9,
LVN_BEGINRDRAG = (int)LVN_FIRST - 11, LVN_BEGINRDRAG = LVN_FIRST - 11,
LVN_GETDISPINFOA = (int)LVN_FIRST - 50, LVN_GETDISPINFOA = LVN_FIRST - 50,
LVN_GETDISPINFOW = (int)LVN_FIRST - 77, LVN_GETDISPINFOW = LVN_FIRST - 77,
LVN_SETDISPINFOA = (int)LVN_FIRST - 51, LVN_SETDISPINFOA = LVN_FIRST - 51,
LVN_SETDISPINFOW = (int)LVN_FIRST - 78, LVN_SETDISPINFOW = LVN_FIRST - 78,
LVN_ODCACHEHINT = (int)LVN_FIRST - 13, LVN_ODCACHEHINT = LVN_FIRST - 13,
LVN_ODFINDITEMW = (int)LVN_FIRST - 79 LVN_ODFINDITEMW = LVN_FIRST - 79
} }
[Flags] [Flags]
internal enum ListViewCallBackMask : uint { internal enum ListViewCallBackMask : uint
{
LVIS_FOCUSED = 0x0001, LVIS_FOCUSED = 0x0001,
LVIS_SELECTED = 0x0002, LVIS_SELECTED = 0x0002,
LVIS_CUT = 0x0004, LVIS_CUT = 0x0004,
@ -260,10 +272,10 @@ namespace BizHawk.Client.EmuHawk
LVIS_STATEIMAGEMASK = 0xF000, LVIS_STATEIMAGEMASK = 0xF000,
} }
#endregion #endregion
#region VirtualListView Delegates #region VirtualListView Delegates
/// <summary> /// <summary>
/// Retrieve the background color for a Listview cell (item and subitem). /// Retrieve the background color for a Listview cell (item and subitem).
/// </summary> /// </summary>
@ -272,7 +284,6 @@ namespace BizHawk.Client.EmuHawk
/// <param name="color">Background color to use</param> /// <param name="color">Background color to use</param>
public delegate void QueryItemBkColorHandler(int item, int subItem, ref Color color); public delegate void QueryItemBkColorHandler(int item, int subItem, ref Color color);
/// <summary> /// <summary>
/// Retrieve the text for a Listview cell (item and subitem). /// Retrieve the text for a Listview cell (item and subitem).
/// </summary> /// </summary>
@ -298,6 +309,7 @@ namespace BizHawk.Client.EmuHawk
public delegate void QueryItemIndentHandler(int item, out int itemIndent); public delegate void QueryItemIndentHandler(int item, out int itemIndent);
public delegate void QueryItemHandler(int idx, out ListViewItem item); public delegate void QueryItemHandler(int idx, out ListViewItem item);
#endregion #endregion
/// <summary> /// <summary>
@ -305,11 +317,13 @@ namespace BizHawk.Client.EmuHawk
/// to be displayed. The virtual Listview contains very little actual information - /// to be displayed. The virtual Listview contains very little actual information -
/// mainly item selection and focus information. /// mainly item selection and focus information.
/// </summary> /// </summary>
public class VirtualListView : ListView { public class VirtualListView : ListView
{
// store the item count to prevent the call to SendMessage(LVM_GETITEMCOUNT) // store the item count to prevent the call to SendMessage(LVM_GETITEMCOUNT)
private int itemCount = 0; private int _itemCount;
#region Display query callbacks #region Display query callbacks
/// <summary> /// <summary>
/// Fire the QueryItemBkColor event which requests the background color for the passed Listview cell /// Fire the QueryItemBkColor event which requests the background color for the passed Listview cell
/// </summary> /// </summary>
@ -320,66 +334,86 @@ namespace BizHawk.Client.EmuHawk
/// </summary> /// </summary>
[Category("Data")] [Category("Data")]
public event QueryItemTextHandler QueryItemText; public event QueryItemTextHandler QueryItemText;
/// <summary> /// <summary>
/// Fire the QueryItemImage event which requests the ImageIndex for the passed Listview item. /// Fire the QueryItemImage event which requests the ImageIndex for the passed Listview item.
/// </summary> /// </summary>
[Category("Data")] [Category("Data")]
public event QueryItemImageHandler QueryItemImage; public event QueryItemImageHandler QueryItemImage;
/// <summary> /// <summary>
/// Fire the QueryItemIndent event which requests the indent for the passed Listview item. /// Fire the QueryItemIndent event which requests the indent for the passed Listview item.
/// </summary> /// </summary>
[Category("Data")] [Category("Data")]
public event QueryItemIndentHandler QueryItemIndent; public event QueryItemIndentHandler QueryItemIndent;
[Category("Data")] [Category("Data")]
public event QueryItemHandler QueryItem; public event QueryItemHandler QueryItem;
#endregion #endregion
#region Properties #region Properties
/// <summary> /// <summary>
/// Gets/sets the sets the virtual number of items to be displayed. /// Gets or sets the sets the virtual number of items to be displayed.
/// </summary> /// </summary>
[Category("Behavior")] [Category("Behavior")]
public int ItemCount { public int ItemCount
get { {
return itemCount; get
{
return _itemCount;
} }
set {
itemCount = value; set
// if the virtual item count is set before the handle is created {
_itemCount = value;
// If the virtual item count is set before the handle is created
// then the image lists don't get loaded properly // then the image lists don't get loaded properly
if(!this.IsHandleCreated) if (!IsHandleCreated)
{
return; return;
}
SetVirtualItemCount(); SetVirtualItemCount();
} }
} }
/// <summary> /// <summary>
/// Gets/sets how list items are to be displayed. /// Gets or sets how list items are to be displayed.
///
/// Hide the ListView.View property. /// Hide the ListView.View property.
/// Virtual Listviews only allow Details or List. /// Virtual Listviews only allow Details or List.
/// </summary> /// </summary>
public new System.Windows.Forms.View View { public new View View
get { {
get
{
return base.View; return base.View;
} }
set {
if(value == View.LargeIcon || set
value == View.SmallIcon) { {
if (value == View.LargeIcon ||
value == View.SmallIcon)
{
throw new ArgumentException("Icon views are invalid for virtual ListViews", "View"); throw new ArgumentException("Icon views are invalid for virtual ListViews", "View");
} }
base.View = value; base.View = value;
} }
} }
/// <summary> /// <summary>
/// Gets the required creation parameters when the control handle is created. /// Gets the required creation parameters when the control handle is created.
///
/// Use LVS_OWNERDATA to set this as a virtual Listview. /// Use LVS_OWNERDATA to set this as a virtual Listview.
/// </summary> /// </summary>
protected override System.Windows.Forms.CreateParams CreateParams { protected override CreateParams CreateParams
get { {
CreateParams cp = base.CreateParams; get
{
var cp = base.CreateParams;
// LVS_OWNERDATA style must be set when the control is created // LVS_OWNERDATA style must be set when the control is created
cp.Style |= (int)ListViewStyles.LVS_OWNERDATA; cp.Style |= (int)ListViewStyles.LVS_OWNERDATA;
return cp; return cp;
@ -389,22 +423,26 @@ namespace BizHawk.Client.EmuHawk
#endregion #endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="VirtualListView"/> class.
/// Create a new instance of this control. /// Create a new instance of this control.
/// </summary> /// </summary>
public VirtualListView() { public VirtualListView()
{
// virtual listviews must be Details or List view with no sorting // virtual listviews must be Details or List view with no sorting
View = View.Details; View = View.Details;
Sorting = SortOrder.None; Sorting = SortOrder.None;
ptrlvhti = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LVHITTESTINFO))); ptrlvhti = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LvHitTestInfo)));
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true);
} }
~VirtualListView() { ~VirtualListView()
{
Marshal.FreeHGlobal(ptrlvhti); Marshal.FreeHGlobal(ptrlvhti);
} }
@ -416,110 +454,136 @@ namespace BizHawk.Client.EmuHawk
/// </summary> /// </summary>
/// <param name="index">Listview item's index.</param> /// <param name="index">Listview item's index.</param>
/// <param name="selected">Select the passed item?</param> /// <param name="selected">Select the passed item?</param>
public void SelectItem(int index, bool selected) { public void SelectItem(int index, bool selected)
IntPtr ptrItem = IntPtr.Zero; {
var ptrItem = IntPtr.Zero;
try { try
{
// Determine whether selecting or unselecting. // Determine whether selecting or unselecting.
uint select = selected ? (uint)ListViewCallBackMask.LVIS_SELECTED : 0; uint select = selected ? (uint)ListViewCallBackMask.LVIS_SELECTED : 0;
// Fill in the LVITEM structure with state fields. // Fill in the LVITEM structure with state fields.
LVITEM stateItem = new LVITEM(); var stateItem = new LvItem
stateItem.mask = (uint)ListViewItemMask.LVIF_STATE; {
stateItem.iItem = index; Mask = (uint)ListViewItemMask.LVIF_STATE,
stateItem.iSubItem = 0; Item = index,
stateItem.state = select; SubItem = 0,
stateItem.stateMask = (uint)ListViewCallBackMask.LVIS_SELECTED; State = @select,
StateMask = (uint)ListViewCallBackMask.LVIS_SELECTED
};
// Copy the structure to unmanaged memory. // Copy the structure to unmanaged memory.
ptrItem = Marshal.AllocHGlobal(Marshal.SizeOf(stateItem.GetType())); ptrItem = Marshal.AllocHGlobal(Marshal.SizeOf(stateItem.GetType()));
Marshal.StructureToPtr(stateItem, ptrItem, true); Marshal.StructureToPtr(stateItem, ptrItem, true);
// Send the message to the control window. // Send the message to the control window.
int result = Win32.SendMessage( Win32.SendMessage(
this.Handle, this.Handle,
(int)ListViewMessages.LVM_SETITEMSTATE, (int)ListViewMessages.LVM_SETITEMSTATE,
index, index,
ptrItem.ToInt32()); ptrItem.ToInt32());
} catch(Exception ex) { }
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine("VirtualListView.SetItemState error=" + ex.Message); System.Diagnostics.Trace.WriteLine("VirtualListView.SetItemState error=" + ex.Message);
// TODO: should this eat any exceptions? // TODO: should this eat any exceptions?
throw ex; throw;
} finally { }
finally
{
// Always release the unmanaged memory. // Always release the unmanaged memory.
if(ptrItem != IntPtr.Zero) { if (ptrItem != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptrItem); Marshal.FreeHGlobal(ptrItem);
} }
} }
} }
private void SetVirtualItemCount() { private void SetVirtualItemCount()
int result; {
result = Win32.SendMessage( Win32.SendMessage(
this.Handle, this.Handle,
(int)ListViewMessages.LVM_SETITEMCOUNT, (int)ListViewMessages.LVM_SETITEMCOUNT,
itemCount, this._itemCount,
0); 0);
} }
protected void OnDispInfoNotice(ref Message m, bool useAnsi) { protected void OnDispInfoNotice(ref Message m, bool useAnsi)
{
var info = (LvDispInfo)m.GetLParam(typeof(LvDispInfo));
LVDISPINFO info = (LVDISPINFO)m.GetLParam(typeof(LVDISPINFO)); if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_TEXT) > 0)
string lvtext = null; {
if (QueryItemText != null)
if((info.item.mask & (uint)ListViewItemMask.LVIF_TEXT) > 0) { {
if(QueryItemText != null) { string lvtext;
QueryItemText(info.item.iItem, info.item.iSubItem, out lvtext); QueryItemText(info.Item.Item, info.Item.SubItem, out lvtext);
if(lvtext != null) { if (lvtext != null)
try { {
int maxIndex = Math.Min(info.item.cchTextMax - 1, lvtext.Length); try
char[] data = new char[maxIndex + 1]; {
int maxIndex = Math.Min(info.Item.cchTextMax - 1, lvtext.Length);
var data = new char[maxIndex + 1];
lvtext.CopyTo(0, data, 0, lvtext.Length); lvtext.CopyTo(0, data, 0, lvtext.Length);
data[maxIndex] = '\0'; data[maxIndex] = '\0';
System.Runtime.InteropServices.Marshal.Copy(data, 0, info.item.pszText, data.Length); Marshal.Copy(data, 0, info.Item.PszText, data.Length);
} catch(Exception e) { }
Debug.WriteLine("Failed to copy text name from client: " + e.ToString(), "VirtualListView.OnDispInfoNotice"); catch (Exception e)
{
Debug.WriteLine("Failed to copy text name from client: " + e, "VirtualListView.OnDispInfoNotice");
} }
} }
} }
} }
if((info.item.mask & (uint)ListViewItemMask.LVIF_IMAGE) > 0) { if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_IMAGE) > 0)
{
int imageIndex = 0; int imageIndex = 0;
if(QueryItemImage != null) { if (QueryItemImage != null)
QueryItemImage(info.item.iItem, info.item.iSubItem, out imageIndex); {
QueryItemImage(info.Item.Item, info.Item.SubItem, out imageIndex);
} }
info.item.iImage = imageIndex;
System.Runtime.InteropServices.Marshal.StructureToPtr(info, m.LParam, false); info.Item.Image = imageIndex;
Marshal.StructureToPtr(info, m.LParam, false);
} }
if((info.item.mask & (uint)ListViewItemMask.LVIF_INDENT) > 0) { if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_INDENT) > 0)
{
int itemIndent = 0; int itemIndent = 0;
if(QueryItemIndent != null) { if (QueryItemIndent != null)
QueryItemIndent(info.item.iItem, out itemIndent); {
QueryItemIndent(info.Item.Item, out itemIndent);
} }
info.item.iIndent = itemIndent;
System.Runtime.InteropServices.Marshal.StructureToPtr(info, m.LParam, false); info.Item.Indent = itemIndent;
Marshal.StructureToPtr(info, m.LParam, false);
} }
m.Result = new IntPtr(0); m.Result = new IntPtr(0);
} }
protected void OnCustomDrawNotice(ref System.Windows.Forms.Message m) { protected void OnCustomDrawNotice(ref Message m)
NMLVCUSTOMDRAW cd = (NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW)); {
switch(cd.nmcd.dwDrawStage) { var cd = (NmLvCustomDraw)m.GetLParam(typeof(NmLvCustomDraw));
case (int)CUSTOMDRAWDRAWSTAGEFLAGS.CDDS_ITEMPREPAINT: switch (cd.Nmcd.dwDrawStage)
case (int)CUSTOMDRAWDRAWSTAGEFLAGS.CDDS_PREPAINT: {
m.Result = new IntPtr((int)CUSTOMDRAWRETURNFLAGS.CDRF_NOTIFYSUBITEMDRAW); case (int)CustomDrawDrawStageFlags.CDDS_ITEMPREPAINT:
case (int)CustomDrawDrawStageFlags.CDDS_PREPAINT:
m.Result = new IntPtr((int)CustomDrawReturnFlags.CDRF_NOTIFYSUBITEMDRAW);
break; break;
case (int)CUSTOMDRAWDRAWSTAGEFLAGS.CDDS_SUBITEMPREPAINT: case (int)CustomDrawDrawStageFlags.CDDS_SUBITEMPREPAINT:
Color color; if (QueryItemBkColor != null)
if(QueryItemBkColor != null) { {
color = Color.FromArgb(cd.clrTextBk & 0xFF, (cd.clrTextBk >> 8) & 0xFF, (cd.clrTextBk >> 16) & 0xFF); var color = Color.FromArgb(cd.ClearTextBackground & 0xFF, (cd.ClearTextBackground >> 8) & 0xFF, (cd.ClearTextBackground >> 16) & 0xFF);
QueryItemBkColor(cd.nmcd.dwItemSpec, cd.iSubItem, ref color); QueryItemBkColor(cd.Nmcd.dwItemSpec, cd.SubItem, ref color);
cd.clrTextBk = (color.B << 16) | (color.G << 8) | (color.R); cd.ClearTextBackground = (color.B << 16) | (color.G << 8) | color.R;
System.Runtime.InteropServices.Marshal.StructureToPtr(cd, m.LParam, false); Marshal.StructureToPtr(cd, m.LParam, false);
} }
m.Result = new IntPtr((int)CUSTOMDRAWRETURNFLAGS.CDRF_DODEFAULT);
m.Result = new IntPtr((int)CustomDrawReturnFlags.CDRF_DODEFAULT);
break; break;
} }
} }
@ -530,28 +594,33 @@ namespace BizHawk.Client.EmuHawk
public event ScrollEventHandler Scroll; public event ScrollEventHandler Scroll;
protected virtual void OnScroll(ScrollEventArgs e) protected virtual void OnScroll(ScrollEventArgs e)
{ {
ScrollEventHandler handler = this.Scroll; var handler = this.Scroll;
if (handler != null) handler(this, e); if (handler != null)
{
handler(this, e);
}
} }
[DllImport("user32.dll", CharSet = CharSet.Auto)] [DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar); public static extern int GetScrollPos(IntPtr hWnd, Orientation nBar);
/// <summary> /// <summary>
/// Gets and Sets the Vertical Scroll position of the control. /// Gets and Sets the Vertical Scroll position of the control.
/// </summary> /// </summary>
public int VScrollPos public int VScrollPos
{ {
get { return GetScrollPos((IntPtr)this.Handle, System.Windows.Forms.Orientation.Vertical); } get { return GetScrollPos(this.Handle, Orientation.Vertical); }
} }
protected override void WndProc(ref System.Windows.Forms.Message m) { protected override void WndProc(ref Message m)
NMHDR nm1; {
bool messageProcessed = false; var messageProcessed = false;
switch(m.Msg) { switch (m.Msg)
{
case (int)WindowsMessage.WM_REFLECT + (int)WindowsMessage.WM_NOTIFY: case (int)WindowsMessage.WM_REFLECT + (int)WindowsMessage.WM_NOTIFY:
nm1 = (NMHDR)m.GetLParam(typeof(NMHDR)); var nm1 = (NmHdr)m.GetLParam(typeof(NmHdr));
switch(nm1.code) { switch (nm1.Code)
{
case (int)Notices.NM_CUSTOMDRAW: case (int)Notices.NM_CUSTOMDRAW:
OnCustomDrawNotice(ref m); OnCustomDrawNotice(ref m);
messageProcessed = true; messageProcessed = true;
@ -568,138 +637,142 @@ namespace BizHawk.Client.EmuHawk
OnBeginItemDrag(MouseButtons.Right, ref m); OnBeginItemDrag(MouseButtons.Right, ref m);
messageProcessed = true; messageProcessed = true;
break; break;
//case (int)Notices.NM_CLICK:
//case (int)Notices.NM_DBLCLICK:
// {
// NMITEMACTIVATE test = (NMITEMACTIVATE)m.GetLParam(typeof(NMITEMACTIVATE));
// messageProcessed = true;
// break;
// }
default:
break;
} }
break;
break;
case (int)WindowsMessage.WM_SCROLL: case (int)WindowsMessage.WM_SCROLL:
//http://stackoverflow.com/questions/1851620/handling-scroll-event-on-listview-in-c-sharp // http://stackoverflow.com/questions/1851620/handling-scroll-event-on-listview-in-c-sharp
OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), m.WParam.ToInt32())); OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), m.WParam.ToInt32()));
break; break;
//obscure message loop flakiness when exceptions are thrown from the message loop...
//THIS BREAKS PROPER LISTVIEW FOCUS SELECTION (blue)
//next time we run into this, debug it better.
//case (int)WindowsMessage.WM_SETFOCUS:
// if (SelectedIndices.Count > 0 && SelectedIndices[0] >= VirtualListSize)
// messageProcessed = true;
// break;
//TRY THIS HACK INSTEAD TO FIX THE EXCEPTION
// (( NOPE, THEY ALL BREAK ONE THING OR ANOTHER. WINFORMS LISTVIEW JUST THROWS EXCEPTIONS, WHAT CAN WE DO? ))
//case 0x100C:
// {
// base.WndProc(ref m);
// int num = m.Result.ToInt32();
// messageProcessed = true;
// m.Result = new IntPtr(-1);
// break;
// }
//case 0x1012:
// {
// base.WndProc(ref m);
// int num = m.Result.ToInt32();
// messageProcessed = true;
// m.Result = new IntPtr(-1);
// break;
// }
case (int)WindowsMessage.WM_ERASEBKGND: case (int)WindowsMessage.WM_ERASEBKGND:
if (BlazingFast) if (BlazingFast)
{ {
messageProcessed = true; messageProcessed = true;
m.Result = new IntPtr(1); m.Result = new IntPtr(1);
} }
break;
default:
break; break;
} }
if(!messageProcessed) {
try { if (!messageProcessed)
{
try
{
base.WndProc(ref m); base.WndProc(ref m);
} catch(Exception ex) { }
catch (Exception ex)
{
Trace.WriteLine(string.Format("Message {0} caused an exception: {1}", m, ex.Message)); Trace.WriteLine(string.Format("Message {0} caused an exception: {1}", m, ex.Message));
} }
} }
} }
public bool BlazingFast = false; public bool BlazingFast { get; set; }
protected ListViewItem GetItem(int idx) { protected ListViewItem GetItem(int idx)
{
ListViewItem item = null; ListViewItem item = null;
if(QueryItem != null) { if (QueryItem != null)
{
QueryItem(idx, out item); QueryItem(idx, out item);
} }
if(item == null) {
throw new ArgumentException("cannot find item " + idx.ToString() + " via QueryItem event"); if (item == null)
{
throw new ArgumentException("cannot find item " + idx + " via QueryItem event");
} }
return item; return item;
} }
protected void OnBeginItemDrag(MouseButtons mouseButton, ref System.Windows.Forms.Message m) { protected void OnBeginItemDrag(MouseButtons mouseButton, ref Message m)
NMLISTVIEW info = (NMLISTVIEW)m.GetLParam(typeof(NMLISTVIEW)); {
var info = (NMLISTVIEW)m.GetLParam(typeof(NMLISTVIEW));
ListViewItem item = null; ListViewItem item = null;
if(QueryItem != null) { if (QueryItem != null)
{
QueryItem(info.iItem, out item); QueryItem(info.iItem, out item);
} }
OnItemDrag(new ItemDragEventArgs(mouseButton, item)); OnItemDrag(new ItemDragEventArgs(mouseButton, item));
} }
protected override void OnHandleCreated(System.EventArgs e) { protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e); base.OnHandleCreated(e);
// ensure the value for ItemCount is sent to the control properly if the user set it // ensure the value for ItemCount is sent to the control properly if the user set it
// before the handle was created // before the handle was created
SetVirtualItemCount(); SetVirtualItemCount();
} }
protected override void OnHandleDestroyed(System.EventArgs e) { protected override void OnHandleDestroyed(EventArgs e)
{
// the ListView OnHandleDestroyed accesses the Items list for all selected items // the ListView OnHandleDestroyed accesses the Items list for all selected items
ItemCount = 0; ItemCount = 0;
base.OnHandleDestroyed(e); base.OnHandleDestroyed(e);
} }
#endregion #endregion
LVHITTESTINFO lvhti = new LVHITTESTINFO(); LvHitTestInfo lvhti = new LvHitTestInfo();
IntPtr ptrlvhti; IntPtr ptrlvhti;
int selection = -1; int selection = -1;
public int hitTest(int x, int y) { public int hitTest(int x, int y)
lvhti.pt.x = x; {
lvhti.pt.y = y; lvhti.Point.X = x;
lvhti.Point.Y = y;
Marshal.StructureToPtr(lvhti, ptrlvhti, true); Marshal.StructureToPtr(lvhti, ptrlvhti, true);
int z = Win32.SendMessage(this.Handle, (int)ListViewMessages.LVM_HITTEST, 0, ptrlvhti.ToInt32()); int z = Win32.SendMessage(this.Handle, (int)ListViewMessages.LVM_HITTEST, 0, ptrlvhti.ToInt32());
Marshal.PtrToStructure(ptrlvhti, lvhti); Marshal.PtrToStructure(ptrlvhti, lvhti);
return z; return z;
} }
public void ensureVisible(int index) { public void ensureVisible(int index)
{
Win32.SendMessage(Handle, (int)ListViewMessages.LVM_ENSUREVISIBLE, index, 1); Win32.SendMessage(Handle, (int)ListViewMessages.LVM_ENSUREVISIBLE, index, 1);
} }
public void ensureVisible() { public void ensureVisible()
{
ensureVisible(selectedItem); ensureVisible(selectedItem);
} }
public void setSelection(int index) { public void setSelection(int index)
{
clearSelection(); clearSelection();
selection = index; selection = index;
SelectItem(selection, true); SelectItem(selection, true);
} }
public int selectedItem { get { if(SelectedIndices.Count == 0) return -1; else return SelectedIndices[0]; } set { setSelection(value); } } public int selectedItem
{
get
{
if (SelectedIndices.Count == 0)
{
return -1;
}
else
{
return SelectedIndices[0];
}
}
set
{
setSelection(value);
}
}
public void clearSelection() { public void clearSelection()
if(selection != -1) {
if (selection != -1)
{
SelectItem(selection, false); SelectItem(selection, false);
}
selection = -1; selection = -1;
} }
} }

File diff suppressed because it is too large Load Diff