mirror of https://github.com/dahall/Vanara.git
157 lines
5.5 KiB
C#
157 lines
5.5 KiB
C#
#if SYSLINKGETSWORKING
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using Vanara.Extensions;
|
|
using Vanara.InteropServices;
|
|
using static Vanara.PInvoke.ComCtl32;
|
|
using static Vanara.PInvoke.User32;
|
|
|
|
namespace Vanara.PInvoke.Controls;
|
|
|
|
/// <summary>Represents a Windows SysLink control that displays one or more hyperlinks.</summary>
|
|
/// <seealso cref="Control"/>
|
|
public class SysLink : Control
|
|
{
|
|
private static readonly bool IsPlatformSupported = Environment.OSVersion.Version.Major > 5;
|
|
private static Lazy<bool> init = new(() => InitCommonControlsEx(CommonControlClass.ICC_LINK_CLASS));
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="SysLink"/> class.</summary>
|
|
public SysLink()
|
|
{
|
|
if (!IsPlatformSupported) throw new InvalidOperationException("A SysLink control is only supported after Vista.");
|
|
if (!init.Value) throw new InvalidOperationException("Failed to initialize common controls.");
|
|
Items = new(this);
|
|
}
|
|
|
|
/// <summary>Gets the list of hyperlinks.</summary>
|
|
/// <value>The hyperlinks.</value>
|
|
public SysLinkItemList Items { get; }
|
|
|
|
/// <inheritdoc/>
|
|
protected override CreateParams CreateParams
|
|
{
|
|
get
|
|
{
|
|
CreateParams cp = base.CreateParams;
|
|
cp.ClassName = WC_LINK;
|
|
cp.Caption = "Click <a id=\"ID01\">here</a>";
|
|
return cp;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
protected override Size DefaultSize => new(200, AutoSize ? PreferredSize.Height : 58);
|
|
|
|
/// <inheritdoc/>
|
|
public override Size GetPreferredSize(Size proposedSize)
|
|
{
|
|
SIZE sz = proposedSize;
|
|
if (IsHandleCreated)
|
|
{
|
|
using PinnedObject psz = new(sz);
|
|
var h = SendMessage(Handle, SysLinkMessage.LM_GETIDEALSIZE, proposedSize.Width, psz).ToInt32();
|
|
}
|
|
return sz;
|
|
}
|
|
}
|
|
|
|
/// <summary>Exposes the list of hyperlinks in a <see cref="SysLink"/> control. This class cannot be inherited.</summary>
|
|
public sealed class SysLinkItemList : IReadOnlyList<SysLinkItem>
|
|
{
|
|
private readonly SysLink parent;
|
|
|
|
internal SysLinkItemList(SysLink parent) => this.parent = parent;
|
|
|
|
/// <inheritdoc/>
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
int count = 0;
|
|
for (IEnumerator<SysLinkItem> e = GetEnumerator(); e.MoveNext(); count++) ;
|
|
return Count;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public SysLinkItem this[int index] => new((HWND)parent.Handle, ValidateIndex(index));
|
|
|
|
/// <inheritdoc/>
|
|
public IEnumerator<SysLinkItem> GetEnumerator()
|
|
{
|
|
LITEM li = new(0, LIF.LIF_STATE);
|
|
using var pli = new PinnedObject(li);
|
|
if (parent.IsHandleCreated)
|
|
for (; li.iLink < ushort.MaxValue && IntPtr.Zero != SendMessage(parent.Handle, SysLinkMessage.LM_GETITEM, default, pli); li.iLink++)
|
|
yield return new((HWND)parent.Handle, li.iLink);
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
|
|
private int ValidateIndex(int index)
|
|
{
|
|
LITEM li = new(index, LIF.LIF_STATE);
|
|
using var pli = new PinnedObject(li);
|
|
return IntPtr.Zero == SendMessage(parent.Handle, SysLinkMessage.LM_GETITEM, default, pli)
|
|
? throw new ArgumentOutOfRangeException(nameof(index))
|
|
: index;
|
|
}
|
|
}
|
|
|
|
/// <summary>Information about a hyperlink exposed by a <see cref="SysLink"/> control. This class cannot be inherited.</summary>
|
|
public sealed class SysLinkItem
|
|
{
|
|
private readonly int index;
|
|
private readonly HWND parent;
|
|
|
|
internal SysLinkItem(HWND handle, int index) { parent = handle; this.index = index; }
|
|
|
|
/// <summary>Gets or sets a value indicating whether this <see cref="SysLinkItem"/> is enabled.</summary>
|
|
/// <value><see langword="true"/> if enabled; otherwise, <see langword="false"/>.</value>
|
|
public bool Enabled { get => GetState(LIS.LIS_ENABLED); set => SetState(LIS.LIS_ENABLED, value); }
|
|
|
|
/// <summary>Gets or sets a value indicating whether this <see cref="SysLinkItem"/> is focused.</summary>
|
|
/// <value><see langword="true"/> if focused; otherwise, <see langword="false"/>.</value>
|
|
public bool Focused { get => GetState(LIS.LIS_FOCUSED); set => SetState(LIS.LIS_FOCUSED, value); }
|
|
|
|
/// <summary>Gets or sets a value indicating whether this <see cref="SysLinkItem"/> is hover.</summary>
|
|
/// <value><see langword="true"/> if hover; otherwise, <see langword="false"/>.</value>
|
|
public bool Hover { get => GetState(LIS.LIS_HOTTRACK); set => SetState(LIS.LIS_HOTTRACK, value); }
|
|
|
|
/// <summary>Gets or sets the key.</summary>
|
|
/// <value>The key.</value>
|
|
public string Key { get => GetInfo(LIF.LIF_ITEMID).szID ?? index.ToString(); set => SetInfo(new(index, LIF.LIF_ITEMID) { szID = value }); }
|
|
|
|
/// <summary>Gets or sets the URL.</summary>
|
|
/// <value>The URL.</value>
|
|
public Uri Url { get => new(GetInfo(LIF.LIF_URL).szUrl); set => SetInfo(new(index, LIF.LIF_URL) { szUrl = value.AbsoluteUri }); }
|
|
|
|
/// <summary>Gets or sets a value indicating whether this <see cref="SysLinkItem"/> is visited.</summary>
|
|
/// <value><see langword="true"/> if visited; otherwise, <see langword="false"/>.</value>
|
|
public bool Visited { get => GetState(LIS.LIS_VISITED); set => SetState(LIS.LIS_VISITED, value); }
|
|
|
|
private LITEM GetInfo(LIF mask)
|
|
{
|
|
LITEM li = new(index, mask);
|
|
using PinnedObject pli = new(li);
|
|
if (mask.IsFlagSet(LIF.LIF_STATE))
|
|
li.stateMask = (LIS)0x1f;
|
|
SendMessage(parent, SysLinkMessage.LM_GETITEM, default, pli);
|
|
return li;
|
|
}
|
|
|
|
private bool GetState(LIS mask) => GetInfo(LIF.LIF_STATE).state.IsFlagSet(mask);
|
|
|
|
private void SetInfo(in LITEM item)
|
|
{
|
|
using PinnedObject pli = new(item);
|
|
if (0 != SendMessage(parent, SysLinkMessage.LM_SETITEM, default, pli).ToInt32())
|
|
Win32Error.ThrowLastError();
|
|
}
|
|
|
|
private void SetState(LIS lIS, bool value) => SetInfo(new(index, LIF.LIF_STATE) { stateMask = lIS, state = value ? lIS : 0 });
|
|
}
|
|
#endif |