?? tristatetree.cs
字號:
this.UpdateChildNodeState();
this.UpdateParentNodeState(true);
tv.EndUpdate();
}
}
/// <summary>
/// Recursiveley update child node's state based on the state of this node.
/// </summary>
private void UpdateChildNodeState()
{
ThreeStateTreeNode child;
foreach (TreeNode node in this.Nodes)
{
// It is possible node is not a ThreeStateTreeNode, so check first.
if (node is ThreeStateTreeNode)
{
child = node as ThreeStateTreeNode;
child.Checked = (this.State != CheckBoxState.Unchecked);
child.State = this.State;
child.UpdateChildNodeState();
}
}
}
/// <summary>
/// Recursiveley update parent node state based on the current state of this node.
/// </summary>
private void UpdateParentNodeState(bool isStartingPoint)
{
// If isStartingPoint is false, then know this is not the initial call
// to the recursive method as we want to force on the first time
// this is called to set the instance's parent node state based on
// the state of all the siblings of this node, including the state
// of this node. So, if not the startpoint (!isStartingPoint) and
// the state of this instance is indeterminate (CheckBoxState.Indeterminate)
// then know to set all subsequent parents to the indeterminate
// state. However, if not in an indeterminate state, then still need
// to evaluate the state of all the siblings of this node, including the state
// of this node before setting the state of the parent of this instance.
ThreeStateTreeNode parent = this.Parent as ThreeStateTreeNode;
if (parent != null)
{
CheckBoxState state = CheckBoxState.Unchecked;
// Determine the new state
if (!isStartingPoint && (this.State == CheckBoxState.Indeterminate))
state = CheckBoxState.Indeterminate;
else
state = this.SiblingsState;
// Update parent state if not the same.
if (parent.State != state)
{
parent.Checked = (state != CheckBoxState.Unchecked);
parent.State = state;
parent.UpdateParentNodeState(false);
}
}
}
#endregion
private void SetState(CheckBoxState state)
{
// _threeStateChecked = state;
if (this.TreeView != null && this.TreeView.IsHandleCreated && this.Handle != IntPtr.Zero)
{
SetInternalState(state);
}
}
private void SetInternalState(CheckBoxState state)
{
ThreeStateTreeView view = this.TreeView as ThreeStateTreeView;
if (view == null)
return;
NativeMethods.TVITEM item = new NativeMethods.TVITEM();
item.mask = (int)(NativeMethods.TreeViewMask.TVIF_HANDLE | NativeMethods.TreeViewMask.TVIF_STATE);
item.hItem = this.Handle;
item.stateMask = (int)NativeMethods.TreeViewStateMask.TVIS_STATEIMAGEMASK;
switch (state)
{
case CheckBoxState.Unchecked:
item.state |= 0x1000;
break;
case CheckBoxState.Checked:
item.state |= 0x2000;
break;
case CheckBoxState.Indeterminate:
item.state |= 0x3000;
break;
default:
throw new ArgumentOutOfRangeException("state");
}
NativeMethods.SendMessage(
new HandleRef(this.TreeView, this.TreeView.Handle),
(int)NativeMethods.Messages.TVM_SETITEM,
0,
ref item);
//view.TreeViewAfterThreeStateCheckUpdate(this);
}
}
internal sealed class NativeMethods
{
#region Enums and structs
[Flags]
public enum TreeViewMask
{
TVIF_TEXT = 0x0001,
TVIF_IMAGE = 0x0002,
TVIF_PARAM = 0x0004,
TVIF_STATE = 0x0008,
TVIF_HANDLE = 0x0010,
TVIF_SELECTEDIMAGE = 0x0020,
TVIF_CHILDREN = 0x0040,
TVIF_INTEGRAL = 0x0080
}
[Flags]
public enum TreeViewStateMask
{
TVIS_SELECTED = 0x0002,
TVIS_CUT = 0x0004,
TVIS_DROPHILITED = 0x0008,
TVIS_BOLD = 0x0010,
TVIS_EXPANDED = 0x0020,
TVIS_EXPANDEDONCE = 0x0040,
TVIS_EXPANDPARTIAL = 0x0080,
TVIS_OVERLAYMASK = 0x0F00,
TVIS_STATEIMAGEMASK = 0xF000,
TVIS_USERMASK = 0xF000
}
public enum TreeViewImageListType
{
TVSIL_NORMAL = 0,
TVSIL_STATE = 2
}
public enum Messages
{
TVM_SETIMAGELIST = 0x1109,
TVM_SETITEM = 0x110d
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct TVITEM
{
public int mask;
public IntPtr hItem;
public int state;
public int stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
}
[StructLayout(LayoutKind.Sequential)]
public struct DLLVersionInfo
{
public int cbSize;
public int dwMajorVersion;
public int dwMinorVersion;
public int dwBuildNumber;
public int dwPlatformID;
}
#endregion
#region Native methods
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref NativeMethods.TVITEM lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
[DllImport("comctl32.dll")]
public static extern IntPtr ImageList_Create(int cx, int cy, int flags, int cInitial, int cGrow);
[DllImport("Comctl32.dll", EntryPoint = "DllGetVersion", ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern int DllGetVersion(ref DLLVersionInfo version);
#endregion
public static bool VisualStylesEnabled()
{
OperatingSystem os = Environment.OSVersion;
bool isAppropriateOS = os.Platform == PlatformID.Win32NT && ((os.Version.Major == 5 && os.Version.Minor >= 1) || os.Version.Major > 5);
bool osFeatureThemesPresent = false;
bool osThemeDLLAvailable = false;
if (isAppropriateOS)
{
Version osThemeVersion = OSFeature.Feature.GetVersionPresent(OSFeature.Themes);
osFeatureThemesPresent = osThemeVersion != null;
DLLVersionInfo dllVersion = new DLLVersionInfo();
dllVersion.cbSize = Marshal.SizeOf(typeof(DLLVersionInfo));
int temp = DllGetVersion(ref dllVersion);
osThemeDLLAvailable = dllVersion.dwMajorVersion >= 5;
}
return isAppropriateOS && osFeatureThemesPresent && osThemeDLLAvailable && UXTheme.IsAppThemed() && UXTheme.IsThemeActive();
}
}
internal static class UXTheme
{
/// <summary>States available for Button.CheckBox part.summary>
public enum CheckBoxState : int
{
UncheckedNormal = 1,
UncheckedHot = 2,
UncheckedPressed = 3,
UncheckedDisabled = 4,
CheckedNormal = 5,
CheckedHot = 6,
CheckedPressed = 7,
CheckedDisabled = 8,
MixedNormal = 9,
MixedHot = 10,
MixedPressed = 11,
MixedDisabled = 12
};
/// <summary>Parts available for button control.</summary>
public enum ButtonPart : uint
{
Pushbutton = 1,
RadioButton = 2,
Checkbox = 3,
Groupbox = 4,
UserButton = 5
/*
CommandLink = 6,
CommandLinkGlyph = 7
*/
};
/// <summary>RECT structure.</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(System.Drawing.Rectangle rc)
{
Left = rc.X;
Top = rc.Y;
Right = rc.Right;
Bottom = rc.Bottom;
}
public RECT(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
/// <summary>
/// Converts the current <b>RECT</b> to a <see cref="System.Drawing.Rectangle"/>.
/// </summary>
public System.Drawing.Rectangle ToRectangle()
{
System.Drawing.Rectangle rect = System.Drawing.Rectangle.Empty;
rect.X = Left;
rect.Y = Top;
rect.Width = Right - Left;
rect.Height = Bottom - Top;
return rect;
}
}
////Declare a private constructor so nothing can be instantiated as this class.
//private UXTheme(){}
/// <summary>
/// Closes the theme data handle.
/// </summary>
/// <param name="hTheme">Handle to a window's specified theme data.</param>
[DllImport("UxTheme.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int CloseThemeData(IntPtr hTheme);
/// <summary>
/// Draws the background image defined by the visual style for the specified control part.
/// </summary>
/// <param name="hTheme">Handle to a window's specified theme data.</param>
/// <param name="hdc">Handle to a device context (HDC) used for drawing the theme-defined background image.</param>
/// <param name="iPartId">Value that specifies the part to draw.</param>
/// <param name="iStateId">Value that specifies the state of the part to draw.</param>
/// <param name="pRect">Pointer to a RECT structure that contains the rectangle, in logical coordinates, in which the background image is drawn.</param>
/// <param name="pClipRect">Pointer to a RECT structure that contains a clipping rectangle.</param>
[DllImport("UxTheme.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern System.Int32 DrawThemeBackground(
IntPtr hTheme,
IntPtr hdc,
UInt32 iPartId,
UInt32 iStateId,
ref RECT pRect,
ref RECT pClipRect
);
[DllImport("UxTheme.dll", ExactSpelling = true)]
public extern static Int32 DrawThemeBackground(
IntPtr hTheme,
IntPtr hdc,
UInt32 iPartId,
UInt32 iStateId,
ref RECT pRect,
IntPtr pClipRect
);
/// <summary>
/// Reports whether the current application's user interface displays using visual styles.
/// </summary>
[DllImport("UxTheme", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool IsAppThemed();
/// <summary>
/// Tests if a visual style for the current application is active.
/// </summary>
[DllImport("UxTheme.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool IsThemeActive();
public static void LoadCheckBoxImage(System.Windows.Forms.ImageList iList, CheckBoxState state)
{
RECT r = new RECT(0, 0, 16, 16);
Bitmap bmp;
Graphics g;
bmp = new Bitmap(16, 16);
g = Graphics.FromImage(bmp);
IntPtr gHandle = g.GetHdc();
IntPtr hTheme = OpenThemeData(IntPtr.Zero, "BUTTON");
DrawThemeBackground(hTheme, gHandle, (uint)ButtonPart.Checkbox, (uint)state, ref r, IntPtr.Zero);
CloseThemeData(hTheme);
g.ReleaseHdc();
iList.Images.Add(bmp);
}
/// <summary>
/// Opens the theme data for a window and its associated class.
/// </summary>
/// <param name="hwnd">Handle of the window for which theme data is required.</param>
/// <param name="pszClassList">Pointer to a string that contains a semicolon-separated list of classes.</param>
[DllImport("UxTheme.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenThemeData(
IntPtr hwnd,
String pszClassList
);
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -